Rendering a UIView into a PDF as vectors on an iPad - Sometimes renders as bitmap, sometimes as vectors

前端 未结 5 1974
眼角桃花
眼角桃花 2020-12-13 14:41

I have an iPad app and I\'m trying to generate a PDF from a UIView and it\'s almost working perfectly.

The code is really simple as follows:



        
相关标签:
5条回答
  • 2020-12-13 14:55

    The only way I found to make it so labels are rendered vectorized is to use a subclass of UILabel with the following method:

    /** Overriding this CALayer delegate method is the magic that allows us to draw a vector version of the label into the layer instead of the default unscalable ugly bitmap */
    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
        BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
        if (!layer.shouldRasterize && isPDF)
            [self drawRect:self.bounds]; // draw unrasterized
        else
            [super drawLayer:layer inContext:ctx];
    }
    

    Swift 5.x:

    override func draw(_ layer: CALayer, in ctx: CGContext) {
        let isPDF = !UIGraphicsGetPDFContextBounds().isEmpty
    
        if !self.layer.shouldRasterize && isPDF {
            self.draw(self.bounds)
        } else {
            super.draw(layer, in: ctx)
        }
    }
    

    That does the trick for me: labels are unrasterized and selectable in the resulting PDF view, and behave normally when rendered to the screen.

    0 讨论(0)
  • 2020-12-13 14:56

    Use drawInContext rather than renderInContext.

    0 讨论(0)
  • 2020-12-13 15:09

    Trying using the view's viewPrintFormatter.

    Instead of [view.layer renderInContext:pdfContext];

    try this

    CALayer* formattedLayer = [view viewPrintFormatter].view.layer;
    [formattedLayer renderInContext:pdfContext];
    
    0 讨论(0)
  • 2020-12-13 15:17

    I want to suggest an alternative to mprudhom's great solution: Using the UIString extensions you can also make the text in the UILabel be rendered as font (with select'n'copy support etc.) This way the glyphs of the font are embedded in the PDF correctly.

    To support right and center text alignments as well as the default vertical centered alignment, I had to calculate a bounding box for the drawInRect method.

    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
    {
        BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
    
        if (!layer.shouldRasterize && isPDF) {
            // [self drawRect:self.bounds];
    
            CGSize fitSize = [self sizeThatFits:self.bounds.size];
            float x = self.bounds.origin.x;
            float y = self.bounds.origin.y;
    
            if (self.textAlignment == NSTextAlignmentCenter) {
                x += (self.bounds.size.width  - fitSize.width)  / 2.0f;
                y += (self.bounds.size.height - fitSize.height) / 2.0f;
            } else if (self.textAlignment == NSTextAlignmentRight) {
                x += self.bounds.size.width  - fitSize.width;
                y += self.bounds.size.height - fitSize.height;
            }
            [self.textColor set];
            [self.text drawInRect:CGRectMake(x, y, fitSize.width, fitSize.height) withFont:self.font lineBreakMode:NSLineBreakByWordWrapping alignment:self.textAlignment];
        } else {
            [super drawLayer:layer inContext:ctx];
        }
    }
    
    0 讨论(0)
  • 2020-12-13 15:18

    What about if you add the view on screen but at offscreen coordinates. This seems more like a hack but it might work.

    0 讨论(0)
提交回复
热议问题