public RenderedImage createTile()

in batik-awt-util/src/main/java/org/apache/batik/ext/awt/image/renderable/TileRable8Bit.java [356:704]


    public RenderedImage createTile(RenderContext rc){
        AffineTransform usr2dev = rc.getTransform();

        // Hints
        RenderingHints rcHints = rc.getRenderingHints();
        RenderingHints hints = new RenderingHints(null);
        if(rcHints != null){
            hints.add(rcHints);
        }

        // The region actually tiles is the intersection
        // of the tiledRegion and the area of interest
        Rectangle2D tiledRect = getBounds2D();
        Shape       aoiShape  = rc.getAreaOfInterest();
        Rectangle2D aoiRect   = aoiShape.getBounds2D();
        if ( ! tiledRect.intersects(aoiRect) )
            return null;
        Rectangle2D.intersect(tiledRect, aoiRect, tiledRect);

        // Get the tile rectangle in user space
        Rectangle2D tileRect = (Rectangle2D)tileRegion.clone();

        // System.out.println("tileRect : " + tileRect);
        // System.out.println("tiledRect: " + tiledRect);

        if ((tileRect.getWidth()   <= 0)
            || (tileRect.getHeight()  <= 0)
            || (tiledRect.getWidth()  <= 0)
            || (tiledRect.getHeight() <= 0))
            return null;

        //
        // (tiledX, tiledY)
        //                    <------- min(tileWidth, tiledWidth) ----------->
        //                    ^ +------+-------------------------------------+
        //                    | +  A'  +                   B'                +
        //                    | +------+-------------------------------------+
        // min(tileHeight,    | +      +                                     +
        //     tiledHeight)   | +      +                                     +
        //                    | +  C'  +                   D'                +
        //                    | +      +                                     +
        //                    ^ +------+-------------------------------------+
        //
        // Maps to, in the tile:
        //
        // (tileX, tileY)
        //
        //                    <-----------      tileWidth     --------------->
        //                    ^ +-----------------------------+------+-------+
        //                    | +                             +      +       |
        //     tiledHeight    | +                             +      +       |
        //                    | +               D             +      +   C   |
        //                    | +                             +      +       |
        //                    | +-----------------------------+------+-------|
        //                    | +                             |      |       |
        //                    | +                             |      |       |
        //                    | +-----------------------------+------+-------+
        //                    | |               B             +      +   A   |
        //                    ^ +-----------------------------+------+-------+

        // w  = min(tileWidth, tiledWidth)
        // h  = min(tileHeight, tiledHeight)
        // dx = tileWidth  - (tiledX - tileX)%tileWidth;
        // dy = tileHeight - (tiledY - tileY)%tileHeight;
        //
        // A = (tileX + tileWidth - dx, tileY + tileHeight - dy, dx, dy)
        // B = (tileX, tileY + tileHeight - dy, w - dx, dy)
        // C = (tileX + tileWidth - dx, tileY, dx, h - dy)
        // D = (tileX, tileY, w - dx, h - dy)

        double tileX = tileRect.getX();
        double tileY = tileRect.getY();
        double tileWidth = tileRect.getWidth();
        double tileHeight = tileRect.getHeight();

        double tiledX = tiledRect.getX();
        double tiledY = tiledRect.getY();
        double tiledWidth = tiledRect.getWidth();
        double tiledHeight = tiledRect.getHeight();

        double w = Math.min(tileWidth, tiledWidth);
        double h = Math.min(tileHeight, tiledHeight);
        double dx = (tiledX - tileX)%tileWidth;
        double dy = (tiledY - tileY)%tileHeight;

        if(dx > 0){
            dx = tileWidth - dx;
        }
        else{
            dx *= -1;
        }

        if(dy > 0){
            dy = tileHeight - dy;
        }
        else{
            dy *= -1;
        }

        //
        // Adjust dx and dy so that they fall on a pixel boundary
        //
        double scaleX = usr2dev.getScaleX();
        double scaleY = usr2dev.getScaleY();
        double tdx = Math.floor(scaleX*dx);
        double tdy = Math.floor(scaleY*dy);

        dx = tdx/scaleX;
        dy = tdy/scaleY;

        // System.out.println("dx / dy / w / h : " + dx + " / " + dy + " / " + w + " / " + h);

        Rectangle2D.Double A = new Rectangle2D.Double
            (tileX + tileWidth - dx, tileY + tileHeight - dy, dx, dy);
        Rectangle2D.Double B = new Rectangle2D.Double
            (tileX, tileY + tileHeight - dy, w - dx, dy);
        Rectangle2D.Double C = new Rectangle2D.Double
            (tileX + tileWidth - dx, tileY, dx, h - dy);
        Rectangle2D.Double D = new Rectangle2D.Double
            (tileX, tileY, w - dx, h - dy);

        Rectangle2D realTileRect
            = new Rectangle2D.Double(tiledRect.getX(),
                                     tiledRect.getY(),
                                     w, h);

        // System.out.println("A rect    : " + A);
        // System.out.println("B rect    : " + B);
        // System.out.println("C rect    : " + C);
        // System.out.println("D rect    : " + D);
        // System.out.println("realTileR : " + realTileRect);

        // A, B, C and D are the four user space are that make the
        // tile that will be used. We create a rendering for each of
        // these areas that i s not empty (i.e., with either width or
        // height equal to zero)
        RenderedImage ARed = null, BRed = null, CRed = null, DRed = null;
        Filter source = getSource();

        if (A.getWidth() > 0 && A.getHeight() > 0){
            // System.out.println("Rendering A");
            Rectangle devA = usr2dev.createTransformedShape(A).getBounds();
            if(devA.width > 0 && devA.height > 0){
                AffineTransform ATxf = new AffineTransform(usr2dev);
                ATxf.translate(-A.x + tiledX,
                               -A.y + tiledY);

                Shape aoi = A;
                if(overflow){
                    aoi = new Rectangle2D.Double(A.x,
                                                 A.y,
                                                 tiledWidth,
                                                 tiledHeight);
                }

                hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST,
                          aoi);

                RenderContext arc
                    = new RenderContext(ATxf, aoi, hints);

                ARed = source.createRendering(arc);

                //System.out.println("ARed : " + ARed.getMinX() + " / " +
                //                   ARed.getMinY() + " / " +
                //                   ARed.getWidth() + " / " +
                //                   ARed.getHeight());
            }
        }

        if(B.getWidth() > 0 && B.getHeight() > 0){
            // System.out.println("Rendering B");
            Rectangle devB = usr2dev.createTransformedShape(B).getBounds();
            if(devB.width > 0 && devB.height > 0){
                AffineTransform BTxf = new AffineTransform(usr2dev);
                BTxf.translate(-B.x + (tiledX + dx),
                               -B.y + tiledY);

                Shape aoi = B;
                if(overflow){
                    aoi = new Rectangle2D.Double(B.x - tiledWidth + w - dx,
                                                 B.y,
                                                 tiledWidth,
                                                 tiledHeight);
                }

                hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST,
                          aoi);

                RenderContext brc
                    = new RenderContext(BTxf, aoi, hints);

                BRed = source.createRendering(brc);
                // System.out.println("BRed : " + BRed.getMinX() + " / " + BRed.getMinY() + " / " + BRed.getWidth() + " / " + BRed.getHeight());
            }
        }

        if(C.getWidth() > 0 && C.getHeight() > 0){
            // System.out.println("Rendering C");
            Rectangle devC = usr2dev.createTransformedShape(C).getBounds();
            if(devC.width > 0 && devC.height > 0){
                AffineTransform CTxf = new AffineTransform(usr2dev);
                CTxf.translate(-C.x + tiledX,
                               -C.y + (tiledY + dy));

                Shape aoi = C;
                if(overflow){
                    aoi = new Rectangle2D.Double(C.x,
                                                 C.y - tileHeight + h - dy,
                                                 tiledWidth,
                                                 tiledHeight);
                }

                hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST,
                          aoi);

                RenderContext crc
                    = new RenderContext(CTxf, aoi, hints);

                CRed = source.createRendering(crc);
                // System.out.println("CRed : " + CRed.getMinX() + " / " + CRed.getMinY() + " / " + CRed.getWidth() + " / " + CRed.getHeight());
            }
        }

        if(D.getWidth() > 0 && D.getHeight() > 0){
            // System.out.println("Rendering D");
            Rectangle devD = usr2dev.createTransformedShape(D).getBounds();
            if(devD.width > 0 && devD.height > 0){
                AffineTransform DTxf = new AffineTransform(usr2dev);
                DTxf.translate(-D.x + (tiledX + dx),
                               -D.y + (tiledY + dy));

                Shape aoi = D;
                if(overflow){
                    aoi = new Rectangle2D.Double(D.x - tileWidth + w - dx,
                                                 D.y - tileHeight + h - dy,
                                                 tiledWidth,
                                                 tiledHeight);
                }

                hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST,
                          aoi);

                RenderContext drc
                    = new RenderContext(DTxf, aoi, hints);

                DRed = source.createRendering(drc);
                // System.out.println("DRed : " + DRed.getMinX() + " / " + DRed.getMinY() + " / " + DRed.getWidth() + " / " + DRed.getHeight());
            }
        }

        //
        // Now, combine ARed, BRed, CRed and DRed into a single
        // RenderedImage that will be tiled
        //
        final Rectangle realTileRectDev
            = usr2dev.createTransformedShape(realTileRect).getBounds();

        if(realTileRectDev.width == 0 || realTileRectDev.height == 0){
            return null;
        }

        BufferedImage realTileBI
            = new BufferedImage(realTileRectDev.width,
                                realTileRectDev.height,
                                BufferedImage.TYPE_INT_ARGB);

        Graphics2D g = GraphicsUtil.createGraphics(realTileBI,
                                                   rc.getRenderingHints());
        // g.setPaint(new java.awt.Color(0, 255, 0, 64));
        // g.fillRect(0, 0, realTileBI.getWidth(), realTileBI.getHeight());
        g.translate(-realTileRectDev.x,
                    -realTileRectDev.y);

        // System.out.println("realTileRectDev " + realTileRectDev);

        AffineTransform redTxf = new AffineTransform();
        Point2D.Double redVec = new Point2D.Double();
        RenderedImage refRed = null;
        if(ARed != null){
            // System.out.println("Drawing A");
            g.drawRenderedImage(ARed, redTxf);
            refRed = ARed;
        }
        if(BRed != null){
            // System.out.println("Drawing B");

            if(refRed == null){
                refRed = BRed;
            }

            // Adjust B's coordinates
            redVec.x = dx;
            redVec.y = 0;
            usr2dev.deltaTransform(redVec, redVec);
            redVec.x = Math.floor(redVec.x) - (BRed.getMinX() - refRed.getMinX());
            redVec.y = Math.floor(redVec.y) - (BRed.getMinY() - refRed.getMinY());

            // System.out.println("BRed adjust : " + redVec);

                // redTxf.setToTranslation(redVec.x, redVec.y);
            g.drawRenderedImage(BRed, redTxf);
        }
        if(CRed != null){
            // System.out.println("Drawing C");

            if(refRed == null){
                refRed = CRed;
            }

            // Adjust C's coordinates
            redVec.x = 0;
            redVec.y = dy;
            usr2dev.deltaTransform(redVec, redVec);
            redVec.x = Math.floor(redVec.x) - (CRed.getMinX() - refRed.getMinX());
            redVec.y = Math.floor(redVec.y) - (CRed.getMinY() - refRed.getMinY());

            // System.out.println("CRed adjust : " + redVec);

                // redTxf.setToTranslation(redVec.x, redVec.y);
            g.drawRenderedImage(CRed, redTxf);
        }
        if(DRed != null){
            // System.out.println("Drawing D");

            if(refRed == null){
                refRed = DRed;
            }

            // Adjust D's coordinates
            redVec.x = dx;
            redVec.y = dy;
            usr2dev.deltaTransform(redVec, redVec);
            redVec.x = Math.floor(redVec.x) - (DRed.getMinX() - refRed.getMinX());
            redVec.y = Math.floor(redVec.y) - (DRed.getMinY() - refRed.getMinY());

            // System.out.println("DRed adjust : " + redVec);

                // redTxf.setToTranslation(redVec.x, redVec.y);
            g.drawRenderedImage(DRed, redTxf);
        }

        CachableRed realTile;
        realTile = new BufferedImageCachableRed(realTileBI,
                                                realTileRectDev.x,
                                                realTileRectDev.y);

        return realTile;
    }