Search in sources :

Example 1 with TransformHelper

use of sun.java2d.loops.TransformHelper in project jdk8u_jdk by JetBrains.

the class DrawImage method renderImageXform.

protected void renderImageXform(SunGraphics2D sg, Image img, AffineTransform tx, int interpType, int sx1, int sy1, int sx2, int sy2, Color bgColor) {
    final AffineTransform itx;
    try {
        itx = tx.createInverse();
    } catch (final NoninvertibleTransformException ignored) {
        // Non-invertible transform means no output
        return;
    }
    /*
         * Find the maximum bounds on the destination that will be
         * affected by the transformed source.  First, transform all
         * four corners of the source and then min and max the resulting
         * destination coordinates of the transformed corners.
         * Note that tx already has the offset to sx1,sy1 accounted
         * for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the
         * source coordinates.
         */
    final double[] coords = new double[8];
    /* corner:  UL      UR      LL      LR   */
    /* index:  0  1    2  3    4  5    6  7  */
    /* coord: (0, 0), (w, 0), (0, h), (w, h) */
    coords[2] = coords[6] = sx2 - sx1;
    coords[5] = coords[7] = sy2 - sy1;
    tx.transform(coords, 0, coords, 0, 4);
    double ddx1, ddy1, ddx2, ddy2;
    ddx1 = ddx2 = coords[0];
    ddy1 = ddy2 = coords[1];
    for (int i = 2; i < coords.length; i += 2) {
        double d = coords[i];
        if (ddx1 > d)
            ddx1 = d;
        else if (ddx2 < d)
            ddx2 = d;
        d = coords[i + 1];
        if (ddy1 > d)
            ddy1 = d;
        else if (ddy2 < d)
            ddy2 = d;
    }
    Region clip = sg.getCompClip();
    final int dx1 = Math.max((int) Math.floor(ddx1), clip.lox);
    final int dy1 = Math.max((int) Math.floor(ddy1), clip.loy);
    final int dx2 = Math.min((int) Math.ceil(ddx2), clip.hix);
    final int dy2 = Math.min((int) Math.ceil(ddy2), clip.hiy);
    if (dx2 <= dx1 || dy2 <= dy1) {
        // empty destination means no output
        return;
    }
    final SurfaceData dstData = sg.surfaceData;
    SurfaceData srcData = dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_GENERIC, sg.imageComp, bgColor);
    if (srcData == null) {
        img = getBufferedImage(img);
        srcData = dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_GENERIC, sg.imageComp, bgColor);
        if (srcData == null) {
            // REMIND: Is this correct?  Can this happen?
            return;
        }
    }
    if (isBgOperation(srcData, bgColor)) {
        // We cannot perform bg operations during transform so make
        // an opaque temp image with the appropriate background
        // and work from there.
        img = makeBufferedImage(img, bgColor, BufferedImage.TYPE_INT_RGB, sx1, sy1, sx2, sy2);
        // Temp image has appropriate subimage at 0,0 now.
        sx2 -= sx1;
        sy2 -= sy1;
        sx1 = sy1 = 0;
        srcData = dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_GENERIC, sg.imageComp, bgColor);
    }
    SurfaceType srcType = srcData.getSurfaceType();
    TransformHelper helper = TransformHelper.getFromCache(srcType);
    if (helper == null) {
        /* We have no helper for this source image type.
             * But we know that we do have helpers for both RGB and ARGB,
             * so convert to one of those types depending on transparency.
             * ARGB_PRE might be a better choice if the source image has
             * alpha, but it may cause some recursion here since we only
             * tend to have converters that convert to ARGB.
             */
        int type = ((srcData.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
        img = makeBufferedImage(img, null, type, sx1, sy1, sx2, sy2);
        // Temp image has appropriate subimage at 0,0 now.
        sx2 -= sx1;
        sy2 -= sy1;
        sx1 = sy1 = 0;
        srcData = dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_GENERIC, sg.imageComp, null);
        srcType = srcData.getSurfaceType();
        helper = TransformHelper.getFromCache(srcType);
    // assert(helper != null);
    }
    SurfaceType dstType = dstData.getSurfaceType();
    if (sg.compositeState <= SunGraphics2D.COMP_ALPHA) {
        /* NOTE: We either have, or we can make,
             * a MaskBlit for any alpha composite type
             */
        MaskBlit maskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre, sg.imageComp, dstType);
        /* NOTE: We can only use the native TransformHelper
             * func to go directly to the dest if both the helper
             * and the MaskBlit are native.
             * All helpers are native at this point, but some MaskBlit
             * objects are implemented in Java, so we need to check.
             */
        if (maskblit.getNativePrim() != 0) {
            // We can render directly.
            helper.Transform(maskblit, srcData, dstData, sg.composite, clip, itx, interpType, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2, null, 0, 0);
            return;
        }
    }
    // We need to transform to a temp image and then copy
    // just the pieces that are valid data to the dest.
    final int w = dx2 - dx1;
    final int h = dy2 - dy1;
    BufferedImage tmpimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
    SurfaceData tmpData = SurfaceData.getPrimarySurfaceData(tmpimg);
    SurfaceType tmpType = tmpData.getSurfaceType();
    MaskBlit tmpmaskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre, CompositeType.SrcNoEa, tmpType);
    /*
         * The helper function fills a temporary edges buffer
         * for us with the bounding coordinates of each scanline
         * in the following format:
         *
         * edges[0, 1] = [top y, bottom y)
         * edges[2, 3] = [left x, right x) of top row
         * ...
         * edges[h*2, h*2+1] = [left x, right x) of bottom row
         *
         * all coordinates in the edges array will be relative to dx1, dy1
         *
         * edges thus has to be h*2+2 in length
         */
    final int[] edges = new int[h * 2 + 2];
    // It is important that edges[0]=edges[1]=0 when we call
    // Transform in case it must return early and we would
    // not want to render anything on an error condition.
    helper.Transform(tmpmaskblit, srcData, tmpData, AlphaComposite.Src, null, itx, interpType, sx1, sy1, sx2, sy2, 0, 0, w, h, edges, dx1, dy1);
    final Region region = Region.getInstance(dx1, dy1, dx2, dy2, edges);
    clip = clip.getIntersection(region);
    /* NOTE: We either have, or we can make,
         * a Blit for any composite type, even Custom
         */
    final Blit blit = Blit.getFromCache(tmpType, sg.imageComp, dstType);
    blit.Blit(tmpData, dstData, sg.composite, clip, 0, 0, dx1, dy1, w, h);
}
Also used : Blit(sun.java2d.loops.Blit) MaskBlit(sun.java2d.loops.MaskBlit) ScaledBlit(sun.java2d.loops.ScaledBlit) SurfaceType(sun.java2d.loops.SurfaceType) TransformHelper(sun.java2d.loops.TransformHelper) BufferedImage(java.awt.image.BufferedImage) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) SurfaceData(sun.java2d.SurfaceData) MaskBlit(sun.java2d.loops.MaskBlit) AffineTransform(java.awt.geom.AffineTransform)

Aggregations

AffineTransform (java.awt.geom.AffineTransform)1 NoninvertibleTransformException (java.awt.geom.NoninvertibleTransformException)1 BufferedImage (java.awt.image.BufferedImage)1 SurfaceData (sun.java2d.SurfaceData)1 Blit (sun.java2d.loops.Blit)1 MaskBlit (sun.java2d.loops.MaskBlit)1 ScaledBlit (sun.java2d.loops.ScaledBlit)1 SurfaceType (sun.java2d.loops.SurfaceType)1 TransformHelper (sun.java2d.loops.TransformHelper)1