Class PDFRenderer

  • All Implemented Interfaces:
    Watchable, java.lang.Runnable

    public class PDFRenderer
    extends BaseWatchable
    implements java.lang.Runnable
    This class turns a set of PDF Commands from a PDF page into an image. It encapsulates the state of drawing in terms of stroke, fill, transform, etc., as well as pushing and popping these states. When the run method is called, this class goes through all remaining commands in the PDF Page and draws them to its buffered image. It then updates any ImageConsumers with the drawn data.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private int currentCommand
      where we are in the page's command list
      private java.awt.Graphics2D g
      the graphics object for use within an iteration.
      private java.awt.geom.Rectangle2D globalDirtyRegion
      the total region of this image that has been written to
      private ImageInfo imageinfo
      the info about the image, if we need to recreate it
      private java.lang.ref.WeakReference imageRef
      a weak reference to the image we render into.
      private java.awt.geom.GeneralPath lastShape
      the last shape we drew (to check for overlaps)
      static int NOCAP  
      static float[] NODASH  
      static int NOJOIN  
      static float NOLIMIT  
      static float NOPHASE  
      static float NOWIDTH  
      private java.util.List<java.awt.image.ImageObserver> observers
      the image observers that will be updated when this image changes
      private PDFPage page
      the page we were generate from
      private java.util.Stack<PDFRenderer.GraphicsState> stack
      the stack of push()ed graphics states
      private PDFRenderer.GraphicsState state
      the current graphics state
      private long then
      the next time the image should be notified about updates
      private java.awt.geom.Rectangle2D unupdatedRegion
      the sum of all the individual dirty regions since the last update
      static long UPDATE_DURATION
      how long (in milliseconds) to wait between image updates
    • Constructor Summary

      Constructors 
      Constructor Description
      PDFRenderer​(PDFPage page, ImageInfo imageinfo, java.awt.image.BufferedImage bi)
      create a new PDFGraphics state
      PDFRenderer​(PDFPage page, java.awt.Graphics2D g, java.awt.Rectangle imgbounds, java.awt.geom.Rectangle2D clip, java.awt.Color bgColor)
      create a new PDFGraphics state, given a Graphics2D.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private java.awt.geom.Rectangle2D addDirtyRegion​(java.awt.geom.Rectangle2D region, java.awt.geom.Rectangle2D glob)
      Append a rectangle to the total dirty region of this shape
      void addObserver​(java.awt.image.ImageObserver observer)
      Add an image observer
      private java.awt.BasicStroke autoAdjustStrokeWidth​(java.awt.Graphics2D g, java.awt.BasicStroke bs)
      auto adjust the stroke width, according to 6.5.4, which presumes that the device characteristics (an image) require a single pixel wide line, even if the width is set to less.
      void cleanup()
      Called when iteration has stopped
      void clip​(java.awt.geom.GeneralPath s)
      add the path to the current clip.
      void draw​(java.awt.geom.GeneralPath p, java.awt.BasicStroke bs)
      draw an outline.
      java.awt.geom.Rectangle2D drawImage​(PDFImage image)
      draw an image.
      java.awt.geom.Rectangle2D fill​(java.awt.geom.GeneralPath s)
      fill an outline using the current fill paint
      java.awt.geom.AffineTransform getInitialTransform()
      get the initial transform from page space to Java space
      java.awt.geom.GeneralPath getLastShape()
      Get the last shape drawn
      private java.awt.image.BufferedImage getMaskedImage​(java.awt.image.BufferedImage bi)
      Convert an image mask into an image by painting over any pixels that have a value in the image with the current paint
      java.awt.BasicStroke getStroke()
      get the current stroke as a BasicStroke
      java.awt.geom.AffineTransform getTransform()
      get the current affinetransform
      int iterate()
      Draws the next command in the PDFPage to the buffered image.
      private void notifyObservers​(java.awt.image.BufferedImage bi, java.awt.geom.Rectangle2D region)
      Notify the observer that a region of the image has changed
      void pop()
      restore the state of this object to what it was when the previous push() was called.
      void push()
      push the current graphics state onto the stack.
      void removeObserver​(java.awt.image.ImageObserver observer)
      Remove an image observer
      private boolean rendererFinished()
      Determine if we are finished
      private void setClip​(java.awt.Shape s)
      set the clip to be the given shape.
      void setFillAlpha​(float alpha)
      set the stroke alpha
      void setFillPaint​(PDFPaint paint)
      set the fill color
      void setLastShape​(java.awt.geom.GeneralPath shape)
      Set the last shape drawn
      void setStroke​(java.awt.BasicStroke bs)
      set the current stroke as a BasicStroke
      void setStrokeAlpha​(float alpha)
      set the stroke alpha
      void setStrokePaint​(PDFPaint paint)
      set the stroke color
      void setStrokeParts​(float w, int cap, int join, float limit, float[] ary, float phase)
      Set some or all aspects of the current stroke.
      void setTransform​(java.awt.geom.AffineTransform at)
      replace the current transform with the given one.
      void setup()
      Setup rendering.
      private void setupRendering​(java.awt.Graphics2D g)
      Set up the graphics transform to match the clip region to the image size.
      java.awt.geom.Rectangle2D stroke​(java.awt.geom.GeneralPath s)
      draw an outline using the current stroke and draw paint
      void transform​(java.awt.geom.AffineTransform at)
      concatenate the given transform with the current transform
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • Methods inherited from interface java.lang.Runnable

        run
    • Field Detail

      • page

        private PDFPage page
        the page we were generate from
      • currentCommand

        private int currentCommand
        where we are in the page's command list
      • imageRef

        private java.lang.ref.WeakReference imageRef
        a weak reference to the image we render into. For the image to remain available, some other code must retain a strong reference to it.
      • g

        private java.awt.Graphics2D g
        the graphics object for use within an iteration. Note this must be set to null at the end of each iteration, or the image will not be collected
      • globalDirtyRegion

        private java.awt.geom.Rectangle2D globalDirtyRegion
        the total region of this image that has been written to
      • observers

        private java.util.List<java.awt.image.ImageObserver> observers
        the image observers that will be updated when this image changes
      • lastShape

        private java.awt.geom.GeneralPath lastShape
        the last shape we drew (to check for overlaps)
      • imageinfo

        private ImageInfo imageinfo
        the info about the image, if we need to recreate it
      • then

        private long then
        the next time the image should be notified about updates
      • unupdatedRegion

        private java.awt.geom.Rectangle2D unupdatedRegion
        the sum of all the individual dirty regions since the last update
      • UPDATE_DURATION

        public static final long UPDATE_DURATION
        how long (in milliseconds) to wait between image updates
        See Also:
        Constant Field Values
      • NODASH

        public static final float[] NODASH
    • Constructor Detail

      • PDFRenderer

        public PDFRenderer​(PDFPage page,
                           ImageInfo imageinfo,
                           java.awt.image.BufferedImage bi)
        create a new PDFGraphics state
        Parameters:
        page - the current page
        imageinfo - the paramters of the image to render
      • PDFRenderer

        public PDFRenderer​(PDFPage page,
                           java.awt.Graphics2D g,
                           java.awt.Rectangle imgbounds,
                           java.awt.geom.Rectangle2D clip,
                           java.awt.Color bgColor)
        create a new PDFGraphics state, given a Graphics2D. This version will not create an image, and you will get a NullPointerException if you attempt to call getImage().
        Parameters:
        page - the current page
        g - the Graphics2D object to use for drawing
        imgbounds - the bounds of the image into which to fit the page
        clip - the portion of the page to draw, in page space, or null if the whole page should be drawn
        bgColor - the color to draw the background of the image, or null for no color (0 alpha value)
    • Method Detail

      • setupRendering

        private void setupRendering​(java.awt.Graphics2D g)
        Set up the graphics transform to match the clip region to the image size.
      • push

        public void push()
        push the current graphics state onto the stack. Continue working with the current object; calling pop() restores the state of this object to its state when push() was called.
      • pop

        public void pop()
        restore the state of this object to what it was when the previous push() was called.
      • stroke

        public java.awt.geom.Rectangle2D stroke​(java.awt.geom.GeneralPath s)
        draw an outline using the current stroke and draw paint
        Parameters:
        s - the path to stroke
        Returns:
        a Rectangle2D to which the current region being drawn will be added. May also be null, in which case no dirty region will be recorded.
      • autoAdjustStrokeWidth

        private java.awt.BasicStroke autoAdjustStrokeWidth​(java.awt.Graphics2D g,
                                                           java.awt.BasicStroke bs)
        auto adjust the stroke width, according to 6.5.4, which presumes that the device characteristics (an image) require a single pixel wide line, even if the width is set to less. We determine the scaling to see if we would produce a line that was too small, and if so, scale it up to produce a graphics line of 1 pixel, or so. This matches our output with Adobe Reader.
        Parameters:
        g -
        bs -
        Returns:
      • draw

        public void draw​(java.awt.geom.GeneralPath p,
                         java.awt.BasicStroke bs)
        draw an outline.
        Parameters:
        p - the path to draw
        bs - the stroke with which to draw the path
      • fill

        public java.awt.geom.Rectangle2D fill​(java.awt.geom.GeneralPath s)
        fill an outline using the current fill paint
        Parameters:
        s - the path to fill
      • drawImage

        public java.awt.geom.Rectangle2D drawImage​(PDFImage image)
        draw an image.
        Parameters:
        image - the image to draw
      • clip

        public void clip​(java.awt.geom.GeneralPath s)
        add the path to the current clip. The new clip will be the intersection of the old clip and given path.
      • setClip

        private void setClip​(java.awt.Shape s)
        set the clip to be the given shape. The current clip is not taken into account.
      • getTransform

        public java.awt.geom.AffineTransform getTransform()
        get the current affinetransform
      • transform

        public void transform​(java.awt.geom.AffineTransform at)
        concatenate the given transform with the current transform
      • setTransform

        public void setTransform​(java.awt.geom.AffineTransform at)
        replace the current transform with the given one.
      • getInitialTransform

        public java.awt.geom.AffineTransform getInitialTransform()
        get the initial transform from page space to Java space
      • setStrokeParts

        public void setStrokeParts​(float w,
                                   int cap,
                                   int join,
                                   float limit,
                                   float[] ary,
                                   float phase)
        Set some or all aspects of the current stroke.
        Parameters:
        w - the width of the stroke, or NOWIDTH to leave it unchanged
        cap - the end cap style, or NOCAP to leave it unchanged
        join - the join style, or NOJOIN to leave it unchanged
        limit - the miter limit, or NOLIMIT to leave it unchanged
        phase - the phase of the dash array, or NOPHASE to leave it unchanged
        ary - the dash array, or null to leave it unchanged. phase and ary must both be valid, or phase must be NOPHASE while ary is null.
      • getStroke

        public java.awt.BasicStroke getStroke()
        get the current stroke as a BasicStroke
      • setStroke

        public void setStroke​(java.awt.BasicStroke bs)
        set the current stroke as a BasicStroke
      • setStrokePaint

        public void setStrokePaint​(PDFPaint paint)
        set the stroke color
      • setFillPaint

        public void setFillPaint​(PDFPaint paint)
        set the fill color
      • setStrokeAlpha

        public void setStrokeAlpha​(float alpha)
        set the stroke alpha
      • setFillAlpha

        public void setFillAlpha​(float alpha)
        set the stroke alpha
      • addObserver

        public void addObserver​(java.awt.image.ImageObserver observer)
        Add an image observer
      • removeObserver

        public void removeObserver​(java.awt.image.ImageObserver observer)
        Remove an image observer
      • setLastShape

        public void setLastShape​(java.awt.geom.GeneralPath shape)
        Set the last shape drawn
      • getLastShape

        public java.awt.geom.GeneralPath getLastShape()
        Get the last shape drawn
      • setup

        public void setup()
        Setup rendering. Called before iteration begins
        Overrides:
        setup in class BaseWatchable
      • iterate

        public int iterate()
                    throws java.lang.Exception
        Draws the next command in the PDFPage to the buffered image. The image will be notified about changes no less than every UPDATE_DURATION milliseconds.
        Specified by:
        iterate in class BaseWatchable
        Returns:
        • Watchable.RUNNING when there are commands to be processed
        • Watchable.NEEDS_DATA when there are no commands to be processed, but the page is not yet complete
        • Watchable.COMPLETED when the page is done and all the commands have been processed
        • Watchable.STOPPED if the image we are rendering into has gone away
        Throws:
        java.lang.Exception
      • cleanup

        public void cleanup()
        Called when iteration has stopped
        Overrides:
        cleanup in class BaseWatchable
      • addDirtyRegion

        private java.awt.geom.Rectangle2D addDirtyRegion​(java.awt.geom.Rectangle2D region,
                                                         java.awt.geom.Rectangle2D glob)
        Append a rectangle to the total dirty region of this shape
      • rendererFinished

        private boolean rendererFinished()
        Determine if we are finished
      • notifyObservers

        private void notifyObservers​(java.awt.image.BufferedImage bi,
                                     java.awt.geom.Rectangle2D region)
        Notify the observer that a region of the image has changed
      • getMaskedImage

        private java.awt.image.BufferedImage getMaskedImage​(java.awt.image.BufferedImage bi)
        Convert an image mask into an image by painting over any pixels that have a value in the image with the current paint