src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java

Print this page




 347         final int height = sy2 - sy1;
 348         final BufferedImage bimg = new BufferedImage(width, height, type);
 349         final SunGraphics2D g2d = (SunGraphics2D) bimg.createGraphics();
 350         g2d.setComposite(AlphaComposite.Src);
 351         bimg.setAccelerationPriority(0);
 352         if (bgColor != null) {
 353             g2d.setColor(bgColor);
 354             g2d.fillRect(0, 0, width, height);
 355             g2d.setComposite(AlphaComposite.SrcOver);
 356         }
 357         g2d.copyImage(img, 0, 0, sx1, sy1, width, height, null, null);
 358         g2d.dispose();
 359         return bimg;
 360     }
 361 
 362     protected void renderImageXform(SunGraphics2D sg, Image img,
 363                                     AffineTransform tx, int interpType,
 364                                     int sx1, int sy1, int sx2, int sy2,
 365                                     Color bgColor)
 366     {




































 367         Region clip = sg.getCompClip();
 368         SurfaceData dstData = sg.surfaceData;









 369         SurfaceData srcData = dstData.getSourceSurfaceData(img,
 370                                                            SunGraphics2D.TRANSFORM_GENERIC,
 371                                                            sg.imageComp,
 372                                                            bgColor);
 373 
 374         if (srcData == null) {
 375             img = getBufferedImage(img);
 376             srcData = dstData.getSourceSurfaceData(img,
 377                                                    SunGraphics2D.TRANSFORM_GENERIC,
 378                                                    sg.imageComp,
 379                                                    bgColor);
 380             if (srcData == null) {
 381                 // REMIND: Is this correct?  Can this happen?
 382                 return;
 383             }
 384         }
 385 
 386         if (isBgOperation(srcData, bgColor)) {
 387             // We cannot perform bg operations during transform so make
 388             // an opaque temp image with the appropriate background


 412              * tend to have converters that convert to ARGB.
 413              */
 414             int type = ((srcData.getTransparency() == Transparency.OPAQUE)
 415                         ? BufferedImage.TYPE_INT_RGB
 416                         : BufferedImage.TYPE_INT_ARGB);
 417             img = makeBufferedImage(img, null, type, sx1, sy1, sx2, sy2);
 418             // Temp image has appropriate subimage at 0,0 now.
 419             sx2 -= sx1;
 420             sy2 -= sy1;
 421             sx1 = sy1 = 0;
 422 
 423             srcData = dstData.getSourceSurfaceData(img,
 424                                                    SunGraphics2D.TRANSFORM_GENERIC,
 425                                                    sg.imageComp,
 426                                                    null);
 427             srcType = srcData.getSurfaceType();
 428             helper = TransformHelper.getFromCache(srcType);
 429             // assert(helper != null);
 430         }
 431 
 432         AffineTransform itx;
 433         try {
 434             itx = tx.createInverse();
 435         } catch (NoninvertibleTransformException e) {
 436             // Non-invertible transform means no output
 437             return;
 438         }
 439 
 440         /*
 441          * Find the maximum bounds on the destination that will be
 442          * affected by the transformed source.  First, transform all
 443          * four corners of the source and then min and max the resulting
 444          * destination coordinates of the transformed corners.
 445          * Note that tx already has the offset to sx1,sy1 accounted
 446          * for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the
 447          * source coordinates.
 448          */
 449         double coords[] = new double[8];
 450         /* corner:  UL      UR      LL      LR   */
 451         /* index:  0  1    2  3    4  5    6  7  */
 452         /* coord: (0, 0), (w, 0), (0, h), (w, h) */
 453         coords[2] = coords[6] = sx2 - sx1;
 454         coords[5] = coords[7] = sy2 - sy1;
 455         tx.transform(coords, 0, coords, 0, 4);
 456         double ddx1, ddy1, ddx2, ddy2;
 457         ddx1 = ddx2 = coords[0];
 458         ddy1 = ddy2 = coords[1];
 459         for (int i = 2; i < coords.length; i += 2) {
 460             double d = coords[i];
 461             if (ddx1 > d) ddx1 = d;
 462             else if (ddx2 < d) ddx2 = d;
 463             d = coords[i+1];
 464             if (ddy1 > d) ddy1 = d;
 465             else if (ddy2 < d) ddy2 = d;
 466         }
 467         int dx1 = (int) Math.floor(ddx1);
 468         int dy1 = (int) Math.floor(ddy1);
 469         int dx2 = (int) Math.ceil(ddx2);
 470         int dy2 = (int) Math.ceil(ddy2);
 471 
 472         SurfaceType dstType = dstData.getSurfaceType();
 473         MaskBlit maskblit;
 474         Blit blit;
 475         if (sg.compositeState <= SunGraphics2D.COMP_ALPHA) {
 476             /* NOTE: We either have, or we can make,
 477              * a MaskBlit for any alpha composite type
 478              */
 479             maskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre,
 480                                              sg.imageComp,
 481                                              dstType);
 482 
 483             /* NOTE: We can only use the native TransformHelper
 484              * func to go directly to the dest if both the helper
 485              * and the MaskBlit are native.
 486              * All helpers are native at this point, but some MaskBlit
 487              * objects are implemented in Java, so we need to check.
 488              */
 489             if (maskblit.getNativePrim() != 0) {
 490                 // We can render directly.
 491                 helper.Transform(maskblit, srcData, dstData,
 492                                  sg.composite, clip,
 493                                  itx, interpType,
 494                                  sx1, sy1, sx2, sy2,
 495                                  dx1, dy1, dx2, dy2,
 496                                  null, 0, 0);
 497                 return;
 498             }
 499             blit = null;
 500         } else {
 501             /* NOTE: We either have, or we can make,
 502              * a Blit for any composite type, even Custom
 503              */
 504             maskblit = null;
 505             blit = Blit.getFromCache(SurfaceType.IntArgbPre,
 506                                      sg.imageComp,
 507                                      dstType);
 508         }
 509 
 510         // We need to transform to a temp image and then copy
 511         // just the pieces that are valid data to the dest.
 512         BufferedImage tmpimg = new BufferedImage(dx2-dx1, dy2-dy1,


 513                                                  BufferedImage.TYPE_INT_ARGB_PRE);
 514         SurfaceData tmpData = SurfaceData.getPrimarySurfaceData(tmpimg);
 515         SurfaceType tmpType = tmpData.getSurfaceType();
 516         MaskBlit tmpmaskblit =
 517             MaskBlit.getFromCache(SurfaceType.IntArgbPre,
 518                                   CompositeType.SrcNoEa,
 519                                   tmpType);
 520         /*
 521          * The helper function fills a temporary edges buffer
 522          * for us with the bounding coordinates of each scanline
 523          * in the following format:
 524          *
 525          * edges[0, 1] = [top y, bottom y)
 526          * edges[2, 3] = [left x, right x) of top row
 527          * ...
 528          * edges[h*2, h*2+1] = [left x, right x) of bottom row
 529          *
 530          * all coordinates in the edges array will be relative to dx1, dy1
 531          *
 532          * edges thus has to be h*2+2 in length
 533          */
 534         int edges[] = new int[(dy2-dy1)*2+2];
 535         // It is important that edges[0]=edges[1]=0 when we call
 536         // Transform in case it must return early and we would
 537         // not want to render anything on an error condition.
 538         helper.Transform(tmpmaskblit, srcData, tmpData,
 539                          AlphaComposite.Src, null,
 540                          itx, interpType,
 541                          sx1, sy1, sx2, sy2,
 542                          0, 0, dx2-dx1, dy2-dy1,
 543                          edges, dx1, dy1);
 544 
 545         /*
 546          * Now copy the results, scanline by scanline, into the dest.
 547          * The edges array helps us minimize the work.


 548          */
 549         int index = 2;
 550         for (int y = edges[0]; y < edges[1]; y++) {
 551             int relx1 = edges[index++];
 552             int relx2 = edges[index++];
 553             if (relx1 >= relx2) {
 554                 continue;
 555             }
 556             if (maskblit != null) {
 557                 maskblit.MaskBlit(tmpData, dstData,
 558                                   sg.composite, clip,
 559                                   relx1, y,
 560                                   dx1+relx1, dy1+y,
 561                                   relx2 - relx1, 1,
 562                                   null, 0, 0);
 563             } else {
 564                 blit.Blit(tmpData, dstData,
 565                           sg.composite, clip,
 566                           relx1, y,
 567                           dx1+relx1, dy1+y,
 568                           relx2 - relx1, 1);
 569             }
 570         }
 571     }
 572 
 573     // Render an image using only integer translation
 574     // (no scale or transform or sub-pixel interpolated translations).
 575     protected boolean renderImageCopy(SunGraphics2D sg, Image img,
 576                                       Color bgColor,
 577                                       int dx, int dy,
 578                                       int sx, int sy,
 579                                       int w, int h)
 580     {
 581         Region clip = sg.getCompClip();
 582         SurfaceData dstData = sg.surfaceData;
 583 
 584         int attempts = 0;
 585         // Loop up to twice through; this gives us a chance to
 586         // revalidate the surfaceData objects in case of an exception
 587         // and try it once more
 588         while (true) {
 589             SurfaceData srcData =
 590                 dstData.getSourceSurfaceData(img,




 347         final int height = sy2 - sy1;
 348         final BufferedImage bimg = new BufferedImage(width, height, type);
 349         final SunGraphics2D g2d = (SunGraphics2D) bimg.createGraphics();
 350         g2d.setComposite(AlphaComposite.Src);
 351         bimg.setAccelerationPriority(0);
 352         if (bgColor != null) {
 353             g2d.setColor(bgColor);
 354             g2d.fillRect(0, 0, width, height);
 355             g2d.setComposite(AlphaComposite.SrcOver);
 356         }
 357         g2d.copyImage(img, 0, 0, sx1, sy1, width, height, null, null);
 358         g2d.dispose();
 359         return bimg;
 360     }
 361 
 362     protected void renderImageXform(SunGraphics2D sg, Image img,
 363                                     AffineTransform tx, int interpType,
 364                                     int sx1, int sy1, int sx2, int sy2,
 365                                     Color bgColor)
 366     {
 367         final AffineTransform itx;
 368         try {
 369             itx = tx.createInverse();
 370         } catch (final NoninvertibleTransformException ignored) {
 371             // Non-invertible transform means no output
 372             return;
 373         }
 374 
 375         /*
 376          * Find the maximum bounds on the destination that will be
 377          * affected by the transformed source.  First, transform all
 378          * four corners of the source and then min and max the resulting
 379          * destination coordinates of the transformed corners.
 380          * Note that tx already has the offset to sx1,sy1 accounted
 381          * for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the
 382          * source coordinates.
 383          */
 384         final double[] coords = new double[8];
 385         /* corner:  UL      UR      LL      LR   */
 386         /* index:  0  1    2  3    4  5    6  7  */
 387         /* coord: (0, 0), (w, 0), (0, h), (w, h) */
 388         coords[2] = coords[6] = sx2 - sx1;
 389         coords[5] = coords[7] = sy2 - sy1;
 390         tx.transform(coords, 0, coords, 0, 4);
 391         double ddx1, ddy1, ddx2, ddy2;
 392         ddx1 = ddx2 = coords[0];
 393         ddy1 = ddy2 = coords[1];
 394         for (int i = 2; i < coords.length; i += 2) {
 395             double d = coords[i];
 396             if (ddx1 > d) ddx1 = d;
 397             else if (ddx2 < d) ddx2 = d;
 398             d = coords[i+1];
 399             if (ddy1 > d) ddy1 = d;
 400             else if (ddy2 < d) ddy2 = d;
 401         }
 402 
 403         Region clip = sg.getCompClip();
 404         final int dx1 = Math.max((int) Math.floor(ddx1), clip.lox);
 405         final int dy1 = Math.max((int) Math.floor(ddy1), clip.loy);
 406         final int dx2 = Math.min((int) Math.ceil(ddx2), clip.hix);
 407         final int dy2 = Math.min((int) Math.ceil(ddy2), clip.hiy);
 408         if (dx2 <= dx1 || dy2 <= dy1) {
 409             // empty destination means no output
 410             return;
 411         }
 412 
 413         final SurfaceData dstData = sg.surfaceData;
 414         SurfaceData srcData = dstData.getSourceSurfaceData(img,
 415                                                            SunGraphics2D.TRANSFORM_GENERIC,
 416                                                            sg.imageComp,
 417                                                            bgColor);
 418 
 419         if (srcData == null) {
 420             img = getBufferedImage(img);
 421             srcData = dstData.getSourceSurfaceData(img,
 422                                                    SunGraphics2D.TRANSFORM_GENERIC,
 423                                                    sg.imageComp,
 424                                                    bgColor);
 425             if (srcData == null) {
 426                 // REMIND: Is this correct?  Can this happen?
 427                 return;
 428             }
 429         }
 430 
 431         if (isBgOperation(srcData, bgColor)) {
 432             // We cannot perform bg operations during transform so make
 433             // an opaque temp image with the appropriate background


 457              * tend to have converters that convert to ARGB.
 458              */
 459             int type = ((srcData.getTransparency() == Transparency.OPAQUE)
 460                         ? BufferedImage.TYPE_INT_RGB
 461                         : BufferedImage.TYPE_INT_ARGB);
 462             img = makeBufferedImage(img, null, type, sx1, sy1, sx2, sy2);
 463             // Temp image has appropriate subimage at 0,0 now.
 464             sx2 -= sx1;
 465             sy2 -= sy1;
 466             sx1 = sy1 = 0;
 467 
 468             srcData = dstData.getSourceSurfaceData(img,
 469                                                    SunGraphics2D.TRANSFORM_GENERIC,
 470                                                    sg.imageComp,
 471                                                    null);
 472             srcType = srcData.getSurfaceType();
 473             helper = TransformHelper.getFromCache(srcType);
 474             // assert(helper != null);
 475         }
 476 








































 477         SurfaceType dstType = dstData.getSurfaceType();


 478         if (sg.compositeState <= SunGraphics2D.COMP_ALPHA) {
 479             /* NOTE: We either have, or we can make,
 480              * a MaskBlit for any alpha composite type
 481              */
 482             MaskBlit maskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre,
 483                                                       sg.imageComp, dstType);

 484 
 485             /* NOTE: We can only use the native TransformHelper
 486              * func to go directly to the dest if both the helper
 487              * and the MaskBlit are native.
 488              * All helpers are native at this point, but some MaskBlit
 489              * objects are implemented in Java, so we need to check.
 490              */
 491             if (maskblit.getNativePrim() != 0) {
 492                 // We can render directly.
 493                 helper.Transform(maskblit, srcData, dstData,
 494                                  sg.composite, clip,
 495                                  itx, interpType,
 496                                  sx1, sy1, sx2, sy2,
 497                                  dx1, dy1, dx2, dy2,
 498                                  null, 0, 0);
 499                 return;
 500             }









 501         }
 502 
 503         // We need to transform to a temp image and then copy
 504         // just the pieces that are valid data to the dest.
 505         final int w = dx2 - dx1;
 506         final int h = dy2 - dy1;
 507         BufferedImage tmpimg = new BufferedImage(w, h,
 508                                                  BufferedImage.TYPE_INT_ARGB_PRE);
 509         SurfaceData tmpData = SurfaceData.getPrimarySurfaceData(tmpimg);
 510         SurfaceType tmpType = tmpData.getSurfaceType();
 511         MaskBlit tmpmaskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre,

 512                                                      CompositeType.SrcNoEa,
 513                                                      tmpType);
 514         /*
 515          * The helper function fills a temporary edges buffer
 516          * for us with the bounding coordinates of each scanline
 517          * in the following format:
 518          *
 519          * edges[0, 1] = [top y, bottom y)
 520          * edges[2, 3] = [left x, right x) of top row
 521          * ...
 522          * edges[h*2, h*2+1] = [left x, right x) of bottom row
 523          *
 524          * all coordinates in the edges array will be relative to dx1, dy1
 525          *
 526          * edges thus has to be h*2+2 in length
 527          */
 528         final int[] edges = new int[h * 2 + 2];
 529         // It is important that edges[0]=edges[1]=0 when we call
 530         // Transform in case it must return early and we would
 531         // not want to render anything on an error condition.
 532         helper.Transform(tmpmaskblit, srcData, tmpData,
 533                          AlphaComposite.Src, null,
 534                          itx, interpType,
 535                          sx1, sy1, sx2, sy2,
 536                          0, 0, w, h,
 537                          edges, dx1, dy1);
 538 
 539         final Region region = Region.getInstance(dx1, dy1, dx2, dy2, edges);
 540         clip = clip.getIntersection(region);
 541 
 542         /* NOTE: We either have, or we can make,
 543          * a Blit for any composite type, even Custom
 544          */
 545         final Blit blit = Blit.getFromCache(tmpType, sg.imageComp, dstType);
 546         blit.Blit(tmpData, dstData, sg.composite, clip, 0, 0, dx1, dy1, w, h);




















 547     }
 548 
 549     // Render an image using only integer translation
 550     // (no scale or transform or sub-pixel interpolated translations).
 551     protected boolean renderImageCopy(SunGraphics2D sg, Image img,
 552                                       Color bgColor,
 553                                       int dx, int dy,
 554                                       int sx, int sy,
 555                                       int w, int h)
 556     {
 557         Region clip = sg.getCompClip();
 558         SurfaceData dstData = sg.surfaceData;
 559 
 560         int attempts = 0;
 561         // Loop up to twice through; this gives us a chance to
 562         // revalidate the surfaceData objects in case of an exception
 563         // and try it once more
 564         while (true) {
 565             SurfaceData srcData =
 566                 dstData.getSourceSurfaceData(img,