* @param pagePainter          class which will receive paint events.
     * @param paintAnnotations     true enables the painting of page annotations.  False
     *                             paints no annotaitons for a given page.
     * @param paintSearchHighlight true enables the painting of search highlight
     *                             state of text object.  The search controller can
     *                             be used to easily search and add highlighted state
     *                             for search terms.
     */
    public void paint(Graphics g, int renderHintType, final int boundary,
                      float userRotation, float userZoom,
                      PageViewComponentImpl.PagePainter pagePainter,
                      boolean paintAnnotations, boolean paintSearchHighlight) {
        if (!isInited && pagePainter == null) {
            init();
        } else if (!isInited) {
            // make sure we don't do a page init on the awt thread in the viewer
            // ri, let the
            return;
        }

        Graphics2D g2 = (Graphics2D) g;
        GraphicsRenderingHints grh = GraphicsRenderingHints.getDefault();
        g2.setRenderingHints(grh.getRenderingHints(renderHintType));

        AffineTransform at = getPageTransform(boundary, userRotation, userZoom);
        g2.transform(at);

        PRectangle pageBoundary = getPageBoundary(boundary);
        float x = 0 - pageBoundary.x;
        float y = 0 - (pageBoundary.y - pageBoundary.height);

        // Draw the (typically white) background
        Color backgroundColor = grh.getPageBackgroundColor(renderHintType);
        if (backgroundColor != null) {
            g2.setColor(backgroundColor);
            g2.fillRect((int) (0 - x),
                    (int) (0 - y),
                    (int) pageBoundary.width,
                    (int) pageBoundary.height);
        }

        // We have to impose a page clip because some documents don't separate
        //  pages into separate Page objects, but instead reuse the Page object,
        //  but with a different clip
        // And we can't stomp over the clip, because the PageView might be
        //  trying to only draw a portion of the page for performance, or
        //  other reasons
        Rectangle2D rect = new Rectangle2D.Double(-x, -y, pageBoundary.width, pageBoundary.height);
        Shape oldClip = g2.getClip();
        if (oldClip == null) {
            g2.setClip(rect);
        } else {
            Area area = new Area(oldClip);
            area.intersect(new Area(rect));
            g2.setClip(area);
        }

        // draw page content
        if (shapes != null) {

            AffineTransform pageTransform = g2.getTransform();
            Shape pageClip = g2.getClip();

            shapes.setPageParent(this);
            shapes.paint(g2, pagePainter);
            shapes.setPageParent(null);

            g2.setTransform(pageTransform);
            g2.setClip(pageClip);
        }
        // paint annotations if available and desired.
        if (annotations != null && paintAnnotations) {
            float totalRotation = getTotalRotation(userRotation);
            int num = annotations.size();
            for (int i = 0; i < num; i++) {
                Annotation annot = annotations.get(i);
                annot.render(g2, renderHintType, totalRotation, userZoom, false);
            }
        }
        // paint search highlight values
        if (paintSearchHighlight) {
            PageText pageText = getViewText();
            if (pageText != null) {
                g2.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER,
                        TextSelectionPageHandler.selectionAlpha));
                // paint the sprites
                GeneralPath textPath;
                // iterate over the data structure.
                for (LineText lineText : pageText.getPageLines()) {
                    for (WordText wordText : lineText.getWords()) {
                        // paint whole word
                        if (wordText.isHighlighted()) {
                            textPath = new GeneralPath(wordText.getBounds());
                            g2.setColor(TextSelectionPageHandler.highlightColor);
                            g2.fill(textPath);
                        } else {
                            for (GlyphText glyph : wordText.getGlyphs()) {
                                if (glyph.isHighlighted()) {
                                    textPath = new GeneralPath(glyph.getBounds());
                                    g2.setColor(TextSelectionPageHandler.highlightColor);
                                    g2.fill(textPath);
                                }
                            }
                        }
                    }
                }
            }
        }
        // one last repaint, just to be sure
        notifyPaintPageListeners();
    }