< prev index next >

modules/javafx.web/src/main/java/com/sun/javafx/webkit/prism/WCGraphicsPrismContext.java

Print this page




  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.webkit.prism;
  27 
  28 import com.sun.glass.ui.Screen;
  29 import com.sun.javafx.font.FontStrike;
  30 import com.sun.javafx.font.Metrics;
  31 import com.sun.javafx.font.PGFont;
  32 import com.sun.javafx.geom.*;
  33 import com.sun.javafx.geom.transform.Affine2D;
  34 import com.sun.javafx.geom.transform.Affine3D;
  35 import com.sun.javafx.geom.transform.BaseTransform;


  36 import com.sun.javafx.scene.text.GlyphList;
  37 import com.sun.javafx.scene.text.TextLayout;
  38 import com.sun.javafx.sg.prism.*;
  39 import com.sun.javafx.text.TextRun;
  40 import com.sun.prism.*;
  41 import com.sun.prism.paint.Color;
  42 import com.sun.prism.paint.Gradient;
  43 import com.sun.prism.paint.ImagePattern;
  44 import com.sun.prism.paint.Paint;
  45 import com.sun.scenario.effect.*;
  46 import com.sun.scenario.effect.impl.prism.PrDrawable;
  47 import com.sun.scenario.effect.impl.prism.PrEffectHelper;
  48 import com.sun.scenario.effect.impl.prism.PrFilterContext;
  49 import com.sun.webkit.graphics.*;
  50 
  51 import java.nio.ByteBuffer;
  52 import java.nio.ByteOrder;
  53 import java.security.AccessController;
  54 import java.security.PrivilegedAction;
  55 import java.util.ArrayList;
  56 import java.util.List;
  57 import java.util.logging.Level;
  58 import java.util.logging.Logger;
  59 
  60 import static com.sun.scenario.effect.Blend.Mode.*;
  61 import com.sun.scenario.effect.impl.Renderer;
  62 import com.sun.scenario.effect.impl.prism.PrRenderer;
  63 
  64 class WCGraphicsPrismContext extends WCGraphicsContext {
  65 
  66     public enum Type {
  67         /**
  68          * Base context associated with the topmost page buffer.
  69          * Created and disposed during a single render pass.
  70          */
  71         PRIMARY,
  72 
  73         /**
  74          * A context associated with a dedicated buffer representing
  75          * a separate render target like canvas, buffered image etc.
  76          * Its life cycle is not limited to a single render pass.
  77          */
  78         DEDICATED
  79     }
  80 
  81     private final static Logger log =
  82         Logger.getLogger(WCGraphicsPrismContext.class.getName());
  83     private final static boolean DEBUG_DRAW_CLIP_SHAPE = Boolean.valueOf(
  84             AccessController.doPrivileged((PrivilegedAction<String>) () ->
  85             System.getProperty("com.sun.webkit.debugDrawClipShape", "false")));
  86 
  87     Graphics baseGraphics;
  88     private BaseTransform baseTransform;
  89 
  90     private final List<ContextState> states = new ArrayList<ContextState>();
  91 
  92     private ContextState state = new ContextState();
  93 
  94     // Cache for getPlatformGraphics
  95     private Graphics cachedGraphics = null;
  96 
  97     private int fontSmoothingType;
  98     private boolean isRootLayerValid = false;
  99 
 100     WCGraphicsPrismContext(Graphics g) {
 101         state.setClip(g.getClipRect());
 102         state.setAlpha(g.getExtraAlpha());


 368 */
 369 /* #2 problem with negative coordinates
 370         RectBounds rb = TransformedShape.transformedShape(
 371             new RoundRectangle2D(localClip.x, localClip.y, localClip.width, localClip.height, 0, 0),
 372             state.getTransformNoClone()).getBounds();
 373         return rb.isEmpty()
 374             ? null
 375             : new Rectangle(rb);
 376  */
 377     }
 378 
 379     private void setClip(Rectangle shape) {
 380         Affine3D tr = state.getTransformNoClone();
 381         if (tr.getMxy() == 0 && tr.getMxz() == 0
 382          && tr.getMyx() == 0 && tr.getMyz() == 0
 383          && tr.getMzx() == 0 && tr.getMzy() == 0) {
 384             //There is no rotation here: scale + translation.
 385             //Fast & easy!
 386             state.clip(transformClip(shape));
 387             if (log.isLoggable(Level.FINE)) {
 388                 log.log(Level.FINE, "setClip({0})", shape);
 389             }
 390             if (DEBUG_DRAW_CLIP_SHAPE) {
 391                 //Draw clip shape
 392                 Rectangle rc = state.getClipNoClone();
 393                 if (rc != null && rc.width >= 2 && rc.height >= 2) {
 394                     WCTransform cur = getTransform();
 395                     //translate to (layer.getX(), layer.getY())
 396                     setTransform(new WCTransform(
 397                         1.0, 0.0,
 398                         0.0, 1.0,
 399                         0.0, 0.0));
 400 
 401                     Graphics g2d = getGraphics(true);
 402                     if (g2d != null) {
 403                         float fbase = (float)Math.random();
 404                         g2d.setPaint(new Color(
 405                                 fbase,
 406                                 1f - fbase,
 407                                 0.5f,
 408                                 0.1f));


 439     public void setClip(WCRectangle c) {
 440         setClip(new Rectangle((int)c.getX(), (int)c.getY(),
 441                               (int)c.getWidth(), (int)c.getHeight()));
 442     }
 443 
 444     public WCRectangle getClip() {
 445         Rectangle r = state.getClipNoClone();
 446         return r == null ? null : new WCRectangle(r.x, r.y, r.width, r.height);
 447     }
 448 
 449     protected Rectangle getClipRectNoClone() {
 450         return state.getClipNoClone();
 451     }
 452 
 453     protected Affine3D getTransformNoClone() {
 454         return state.getTransformNoClone();
 455     }
 456 
 457     public void translate(float x, float y) {
 458         if (log.isLoggable(Level.FINE)) {
 459             log.log(Level.FINE, "translate({0},{1})", new Object[] {x, y});
 460         }
 461         state.translate(x, y);
 462         if (cachedGraphics != null) {
 463             cachedGraphics.translate(x, y);
 464         }
 465     }
 466 
 467     public void scale(float sx, float sy) {
 468         if (log.isLoggable(Level.FINE)) {
 469             log.fine("scale(" + sx + " " + sy + ")");
 470         }
 471         state.scale(sx, sy);
 472         if (cachedGraphics != null) {
 473             cachedGraphics.scale(sx, sy);
 474         }
 475     }
 476 
 477     public void rotate(float radians) {
 478         if (log.isLoggable(Level.FINE)) {
 479             log.fine("rotate(" + radians + ")");


 567 
 568     @Override
 569     public void clearRect(final float x, final float y, final float w, final float h) {
 570         if (log.isLoggable(Level.FINE)) {
 571             log.fine(String.format("clearRect(%f, %f, %f, %f)", x, y, w, h));
 572         }
 573         if (shouldCalculateIntersection()) {
 574             // No intersection is applicable for clearRect.
 575             return;
 576         }
 577         new Composite() {
 578             @Override void doPaint(Graphics g) {
 579                 g.clearQuad(x, y, x + w, y + h);
 580             }
 581         }.paint();
 582     }
 583 
 584     @Override
 585     public void setFillColor(int rgba) {
 586         if (log.isLoggable(Level.FINE)) {
 587             log.log(Level.FINE, String.format("setFillColor(0x%x)", rgba));
 588         }
 589         state.setPaint(createColor(rgba));
 590     }
 591 
 592     @Override
 593     public void setFillGradient(WCGradient gradient) {
 594         if (log.isLoggable(Level.FINE)) {
 595             log.fine("setFillGradient(" + gradient + ")");
 596         }
 597         state.setPaint((Gradient) gradient.getPlatformGradient());
 598     }
 599 
 600     @Override
 601     public void setTextMode(boolean fill, boolean stroke, boolean clip) {
 602         if (log.isLoggable(Level.FINE)) {
 603             log.fine("setTextMode(fill:" + fill + ",stroke:" + stroke + ",clip:" + clip + ")");
 604         }
 605         state.setTextMode(fill, stroke, clip);
 606     }
 607 
 608     @Override
 609     public void setFontSmoothingType(int fontSmoothingType) {
 610         this.fontSmoothingType = fontSmoothingType;
 611     }
 612 
 613     @Override
 614     public int getFontSmoothingType() {
 615         return fontSmoothingType;
 616     }
 617 
 618     @Override
 619     public void setStrokeStyle(int style) {
 620         if (log.isLoggable(Level.FINE)) {
 621             log.log(Level.FINE, "setStrokeStyle({0})", style);
 622         }
 623         state.getStrokeNoClone().setStyle(style);
 624     }
 625 
 626     @Override
 627     public void setStrokeColor(int rgba) {
 628         if (log.isLoggable(Level.FINE)) {
 629             log.log(Level.FINE, String.format("setStrokeColor(0x%x)", rgba));
 630         }
 631         state.getStrokeNoClone().setPaint(createColor(rgba));
 632     }
 633 
 634     @Override
 635     public void setStrokeWidth(float width) {
 636         if (log.isLoggable(Level.FINE)) {
 637             log.log(Level.FINE, "setStrokeWidth({0})", new Object[] { width });
 638         }
 639         state.getStrokeNoClone().setThickness(width);
 640     }
 641 
 642     @Override
 643     public void setStrokeGradient(WCGradient gradient) {
 644         if (log.isLoggable(Level.FINE)) {
 645             log.fine("setStrokeGradient(" + gradient + ")");
 646         }
 647         state.getStrokeNoClone().setPaint((Gradient) gradient.getPlatformGradient());
 648     }
 649 
 650     @Override
 651     public void setLineDash(float offset, float... sizes) {
 652         if (log.isLoggable(Level.FINE)) {
 653             StringBuilder s = new StringBuilder("[");
 654             for (int i=0; i < sizes.length; i++) {
 655                 s.append(sizes[i]).append(',');
 656             }
 657             s.append(']');
 658             log.log(Level.FINE, "setLineDash({0},{1}", new Object[] {offset, s});
 659         }
 660         state.getStrokeNoClone().setDashOffset(offset);
 661         if (sizes != null) {
 662             boolean allZero = true;
 663             for (int i = 0; i < sizes.length; i++) {
 664                 if (sizes[i] != 0) {
 665                     allZero = false;
 666                     break;
 667                 }
 668             }
 669             if (allZero) {
 670                 sizes = null;
 671             }
 672         }
 673         state.getStrokeNoClone().setDashSizes(sizes);
 674     }
 675 
 676     @Override
 677     public void setLineCap(int lineCap) {
 678         if (log.isLoggable(Level.FINE)) {


 692     @Override
 693     public void setMiterLimit(float miterLimit) {
 694         if (log.isLoggable(Level.FINE)) {
 695             log.fine("setMiterLimit(" + miterLimit + ")");
 696         }
 697         state.getStrokeNoClone().setMiterLimit(miterLimit);
 698     }
 699 
 700     @Override
 701     public void setShadow(float dx, float dy, float blur, int rgba) {
 702         if (log.isLoggable(Level.FINE)) {
 703             String format = "setShadow(%f, %f, %f, 0x%x)";
 704             log.fine(String.format(format, dx, dy, blur, rgba));
 705         }
 706         state.setShadow(createShadow(dx, dy, blur, rgba));
 707     }
 708 
 709     @Override
 710     public void drawPolygon(final WCPath path, final boolean shouldAntialias) {
 711         if (log.isLoggable(Level.FINE)) {
 712             log.log(Level.FINE, "drawPolygon({0})",
 713                     new Object[] {shouldAntialias});
 714         }
 715         if (!shouldRenderShape(((WCPathImpl)path).getPlatformPath(), null,
 716                                 state.getStrokeNoClone().getPlatformStroke()))
 717         {
 718             return;
 719         }
 720         new Composite() {
 721             @Override void doPaint(Graphics g) {
 722                 Path2D p2d = (Path2D) path.getPlatformPath();
 723                 g.setPaint(state.getPaintNoClone());
 724                 g.fill(p2d);
 725                 if (state.getStrokeNoClone().apply(g)) {
 726                     g.draw(p2d);
 727                 }
 728             }
 729         }.paint();
 730     }
 731 
 732     @Override
 733     public void drawLine(final int x0, final int y0, final int x1, final int y1) {
 734         if (log.isLoggable(Level.FINE)) {
 735             log.log(Level.FINE, "drawLine({0}, {1}, {2}, {3})",
 736                     new Object[] {x0, y0, x1, y1});
 737         }
 738         Line2D line = new Line2D(x0, y0, x1, y1);
 739         if (!shouldRenderShape(line, null, state.getStrokeNoClone().getPlatformStroke())) {
 740             return;
 741         }
 742         new Composite() {
 743             @Override void doPaint(Graphics g) {
 744                 if (state.getStrokeNoClone().apply(g)) {
 745                     g.drawLine(x0, y0, x1, y1);
 746                 }
 747             }
 748         }.paint();
 749     }
 750 
 751     @Override
 752     public void drawPattern(
 753         final WCImage texture,
 754         final WCRectangle srcRect,
 755         final WCTransform patternTransform,
 756         final WCPoint phase,
 757         final WCRectangle destRect)
 758     {
 759         if (log.isLoggable(Level.FINE)) {
 760             log.log(Level.FINE, "drawPattern({0}, {1}, {2}, {3})",
 761                     new Object[] {destRect.getIntX(), destRect.getIntY(),
 762                                   destRect.getIntWidth(),
 763                                   destRect.getIntHeight()});
 764         }
 765         if (!shouldRenderRect(destRect.getX(), destRect.getY(),
 766                               destRect.getWidth(), destRect.getHeight(), null, null))
 767         {
 768             return;
 769         }
 770         if (texture != null) {
 771             new Composite() {
 772                 @Override void doPaint(Graphics g) {
 773                     // The handling of pattern transform is modeled after the WebKit
 774                     // ImageCG.cpp's Image::drawPattern()
 775                     float adjustedX = phase.getX()
 776                             + srcRect.getX() * (float) patternTransform.getMatrix()[0];
 777                     float adjustedY = phase.getY()
 778                             + srcRect.getY() * (float) patternTransform.getMatrix()[3];
 779                     float scaledTileWidth =
 780                             srcRect.getWidth() * (float) patternTransform.getMatrix()[0];


 793                     }
 794                     g.setPaint(new ImagePattern(
 795                                img,
 796                                adjustedX, adjustedY,
 797                                scaledTileWidth, scaledTileHeight,
 798                                false, false));
 799 
 800                     g.fillRect(destRect.getX(), destRect.getY(),
 801                                destRect.getWidth(), destRect.getHeight());
 802                 }
 803             }.paint();
 804         }
 805     }
 806 
 807     @Override
 808     public void drawImage(final WCImage img,
 809                           final float dstx, final float dsty, final float dstw, final float dsth,
 810                           final float srcx, final float srcy, final float srcw, final float srch)
 811     {
 812         if (log.isLoggable(Level.FINE)){
 813             log.log(Level.FINE, "drawImage(img, dst({0},{1},{2},{3}), " +
 814                     "src({4},{5},{6},{7}))",
 815                     new Object[] {dstx, dsty, dstw, dsth,
 816                                   srcx, srcy, srcw, srch});
 817         }
 818         if (!shouldRenderRect(dstx, dsty, dstw, dsth, state.getShadowNoClone(), null)) {
 819             return;
 820         }
 821         if (img instanceof PrismImage) {
 822             new Composite() {
 823                 @Override void doPaint(Graphics g) {
 824                     PrismImage pi = (PrismImage) img;
 825                     DropShadow shadow = state.getShadowNoClone();
 826                     if (shadow != null) {
 827                         NGImageView node = new NGImageView();
 828                         node.setImage(pi.getImage());
 829                         node.setX(dstx);
 830                         node.setY(dsty);
 831                         node.setViewport(srcx, srcy, srcw, srch, dstw, dsth);
 832                         node.setContentBounds(new RectBounds(dstx, dsty, dstx + dstw, dsty + dsth));
 833                         render(g, shadow, null, null, node);


 846     @Override
 847     public void drawBitmapImage(final ByteBuffer image, final int x, final int y, final int w, final int h) {
 848         if (!shouldRenderRect(x, y, w, h, null, null)) {
 849             return;
 850         }
 851         new Composite() {
 852             @Override void doPaint(Graphics g) {
 853                 image.order(ByteOrder.nativeOrder());
 854                 Image img = Image.fromByteBgraPreData(image, w, h);
 855                 ResourceFactory rf = g.getResourceFactory();
 856                 Texture txt = rf.createTexture(img, Texture.Usage.STATIC, Texture.WrapMode.REPEAT);
 857                 g.drawTexture(txt, x, y, x + w, y + h, 0, 0, w, h);
 858                 txt.dispose();
 859             }
 860         }.paint();
 861     }
 862 
 863     @Override
 864     public void drawIcon(WCIcon icon, int x, int y) {
 865         if (log.isLoggable(Level.FINE)) {
 866             log.log(Level.FINE, "UNIMPLEMENTED drawIcon ({0}, {1})",
 867                     new Object[] {x, y});
 868         }
 869     }
 870 
 871     @Override
 872     public void drawRect(final int x, final int y, final int w, final int h) {
 873         if (log.isLoggable(Level.FINE)) {
 874             log.log(Level.FINE, "drawRect({0}, {1}, {2}, {3})",
 875                     new Object[]{x, y, w, h});
 876         }
 877         if (!shouldRenderRect(x, y, w, h,
 878                               null, state.getStrokeNoClone().getPlatformStroke()))
 879         {
 880             return;
 881         }
 882         new Composite() {
 883             @Override void doPaint(Graphics g) {
 884                 Paint c = state.getPaintNoClone();
 885                 if (c != null && c.isOpaque()) {
 886                     g.setPaint(c);
 887                     g.fillRect(x, y, w, h);
 888                 }
 889 
 890                 if (state.getStrokeNoClone().apply(g)) {
 891                     g.drawRect(x, y, w, h);
 892                 }
 893             }
 894         }.paint();


 971             int gc = run.getGlyphCount();
 972             for (int i = 0; i < gc; i++) {
 973                 glyphs[count] = run.getGlyphCode(i);
 974                 adv[count] = run.getPosX(i + 1) - run.getPosX(i);
 975                 count++;
 976             }
 977         }
 978 
 979         // adjust x coordinate (see RT-29908)
 980         if (rtl) {
 981             x += (TextUtilities.getLayoutWidth(str.substring(from), f.getPlatformFont()) -
 982                   layout.getBounds().getWidth());
 983         } else {
 984             x += TextUtilities.getLayoutWidth(str.substring(0, from), f.getPlatformFont());
 985         }
 986         drawString(f, glyphs, adv, x, y);
 987     }
 988 
 989     @Override
 990     public void setComposite(int composite) {
 991         log.log(Level.FINE, "setComposite({0})", composite);
 992         state.setCompositeOperation(composite);
 993     }
 994 
 995     @Override
 996     public void drawEllipse(final int x, final int y, final int w, final int h) {
 997         if (log.isLoggable(Level.FINE)) {
 998             log.log(Level.FINE, "drawEllipse({0}, {1}, {2}, {3})",
 999                     new Object[] { x, y, w, h});
1000         }
1001         if (!shouldRenderRect(x, y, w, h,
1002                               null, state.getStrokeNoClone().getPlatformStroke()))
1003         {
1004             return;
1005         }
1006         new Composite() {
1007             @Override void doPaint(Graphics g) {
1008                 g.setPaint(state.getPaintNoClone());
1009                 g.fillEllipse(x, y, w, h);
1010                 if (state.getStrokeNoClone().apply(g)) {
1011                     g.drawEllipse(x, y, w, h);
1012                 }
1013             }
1014         }.paint();
1015     }
1016 
1017     private final static BasicStroke focusRingStroke =
1018         new BasicStroke(1.1f, BasicStroke.CAP_BUTT,
1019                          BasicStroke.JOIN_ROUND, 0.0f,
1020                          new float[] {1.0f}, 0.0f);
1021 
1022     @Override
1023     public void drawFocusRing(final int x, final int y, final int w, final int h, final int rgba) {
1024         if (log.isLoggable(Level.FINE)) {
1025             log.log(Level.FINE,
1026                     String.format("drawFocusRing: %d, %d, %d, %d, 0x%x",
1027                                   x, y, w, h, rgba));
1028         }
1029         if (!shouldRenderRect(x, y, w, h, null, focusRingStroke)) {
1030             return;
1031         }
1032         new Composite() {
1033             @Override void doPaint(Graphics g) {
1034                 g.setPaint(createColor(rgba));
1035                 BasicStroke stroke = g.getStroke();
1036                 g.setStroke(focusRingStroke);
1037                 g.drawRoundRect(x, y, w, h, 4, 4);
1038                 g.setStroke(stroke);
1039             }
1040         }.paint();
1041     }
1042 
1043     public void setAlpha(float alpha) {
1044         log.log(Level.FINE, "setAlpha({0})", alpha);
1045 
1046         state.setAlpha(alpha);
1047 
1048         if (null != cachedGraphics) {
1049             cachedGraphics.setExtraAlpha(state.getAlpha());
1050         }
1051     }
1052 
1053     public float getAlpha() {
1054         return state.getAlpha();
1055     }
1056 
1057     @Override public void beginTransparencyLayer(float opacity) {
1058         TransparencyLayer layer = new TransparencyLayer(
1059                 getGraphics(false), state.getClipNoClone(), opacity);
1060 
1061         if (log.isLoggable(Level.FINE)) {
1062             log.fine(String.format("beginTransparencyLayer(%s)", layer));
1063         }
1064 




  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.webkit.prism;
  27 
  28 import com.sun.glass.ui.Screen;
  29 import com.sun.javafx.font.FontStrike;
  30 import com.sun.javafx.font.Metrics;
  31 import com.sun.javafx.font.PGFont;
  32 import com.sun.javafx.geom.*;
  33 import com.sun.javafx.geom.transform.Affine2D;
  34 import com.sun.javafx.geom.transform.Affine3D;
  35 import com.sun.javafx.geom.transform.BaseTransform;
  36 import com.sun.javafx.logging.PlatformLogger;
  37 import com.sun.javafx.logging.PlatformLogger.Level;
  38 import com.sun.javafx.scene.text.GlyphList;
  39 import com.sun.javafx.scene.text.TextLayout;
  40 import com.sun.javafx.sg.prism.*;
  41 import com.sun.javafx.text.TextRun;
  42 import com.sun.prism.*;
  43 import com.sun.prism.paint.Color;
  44 import com.sun.prism.paint.Gradient;
  45 import com.sun.prism.paint.ImagePattern;
  46 import com.sun.prism.paint.Paint;
  47 import com.sun.scenario.effect.*;
  48 import com.sun.scenario.effect.impl.prism.PrDrawable;
  49 import com.sun.scenario.effect.impl.prism.PrEffectHelper;
  50 import com.sun.scenario.effect.impl.prism.PrFilterContext;
  51 import com.sun.webkit.graphics.*;
  52 
  53 import java.nio.ByteBuffer;
  54 import java.nio.ByteOrder;
  55 import java.security.AccessController;
  56 import java.security.PrivilegedAction;
  57 import java.util.ArrayList;
  58 import java.util.List;


  59 
  60 import static com.sun.scenario.effect.Blend.Mode.*;
  61 import com.sun.scenario.effect.impl.Renderer;
  62 import com.sun.scenario.effect.impl.prism.PrRenderer;
  63 
  64 class WCGraphicsPrismContext extends WCGraphicsContext {
  65 
  66     public enum Type {
  67         /**
  68          * Base context associated with the topmost page buffer.
  69          * Created and disposed during a single render pass.
  70          */
  71         PRIMARY,
  72 
  73         /**
  74          * A context associated with a dedicated buffer representing
  75          * a separate render target like canvas, buffered image etc.
  76          * Its life cycle is not limited to a single render pass.
  77          */
  78         DEDICATED
  79     }
  80 
  81     private final static PlatformLogger log =
  82             PlatformLogger.getLogger(WCGraphicsPrismContext.class.getName());
  83     private final static boolean DEBUG_DRAW_CLIP_SHAPE = Boolean.valueOf(
  84             AccessController.doPrivileged((PrivilegedAction<String>) () ->
  85             System.getProperty("com.sun.webkit.debugDrawClipShape", "false")));
  86 
  87     Graphics baseGraphics;
  88     private BaseTransform baseTransform;
  89 
  90     private final List<ContextState> states = new ArrayList<ContextState>();
  91 
  92     private ContextState state = new ContextState();
  93 
  94     // Cache for getPlatformGraphics
  95     private Graphics cachedGraphics = null;
  96 
  97     private int fontSmoothingType;
  98     private boolean isRootLayerValid = false;
  99 
 100     WCGraphicsPrismContext(Graphics g) {
 101         state.setClip(g.getClipRect());
 102         state.setAlpha(g.getExtraAlpha());


 368 */
 369 /* #2 problem with negative coordinates
 370         RectBounds rb = TransformedShape.transformedShape(
 371             new RoundRectangle2D(localClip.x, localClip.y, localClip.width, localClip.height, 0, 0),
 372             state.getTransformNoClone()).getBounds();
 373         return rb.isEmpty()
 374             ? null
 375             : new Rectangle(rb);
 376  */
 377     }
 378 
 379     private void setClip(Rectangle shape) {
 380         Affine3D tr = state.getTransformNoClone();
 381         if (tr.getMxy() == 0 && tr.getMxz() == 0
 382          && tr.getMyx() == 0 && tr.getMyz() == 0
 383          && tr.getMzx() == 0 && tr.getMzy() == 0) {
 384             //There is no rotation here: scale + translation.
 385             //Fast & easy!
 386             state.clip(transformClip(shape));
 387             if (log.isLoggable(Level.FINE)) {
 388                 log.fine("setClip({0})", shape);
 389             }
 390             if (DEBUG_DRAW_CLIP_SHAPE) {
 391                 //Draw clip shape
 392                 Rectangle rc = state.getClipNoClone();
 393                 if (rc != null && rc.width >= 2 && rc.height >= 2) {
 394                     WCTransform cur = getTransform();
 395                     //translate to (layer.getX(), layer.getY())
 396                     setTransform(new WCTransform(
 397                         1.0, 0.0,
 398                         0.0, 1.0,
 399                         0.0, 0.0));
 400 
 401                     Graphics g2d = getGraphics(true);
 402                     if (g2d != null) {
 403                         float fbase = (float)Math.random();
 404                         g2d.setPaint(new Color(
 405                                 fbase,
 406                                 1f - fbase,
 407                                 0.5f,
 408                                 0.1f));


 439     public void setClip(WCRectangle c) {
 440         setClip(new Rectangle((int)c.getX(), (int)c.getY(),
 441                               (int)c.getWidth(), (int)c.getHeight()));
 442     }
 443 
 444     public WCRectangle getClip() {
 445         Rectangle r = state.getClipNoClone();
 446         return r == null ? null : new WCRectangle(r.x, r.y, r.width, r.height);
 447     }
 448 
 449     protected Rectangle getClipRectNoClone() {
 450         return state.getClipNoClone();
 451     }
 452 
 453     protected Affine3D getTransformNoClone() {
 454         return state.getTransformNoClone();
 455     }
 456 
 457     public void translate(float x, float y) {
 458         if (log.isLoggable(Level.FINE)) {
 459             log.fine("translate({0},{1})", new Object[] {x, y});
 460         }
 461         state.translate(x, y);
 462         if (cachedGraphics != null) {
 463             cachedGraphics.translate(x, y);
 464         }
 465     }
 466 
 467     public void scale(float sx, float sy) {
 468         if (log.isLoggable(Level.FINE)) {
 469             log.fine("scale(" + sx + " " + sy + ")");
 470         }
 471         state.scale(sx, sy);
 472         if (cachedGraphics != null) {
 473             cachedGraphics.scale(sx, sy);
 474         }
 475     }
 476 
 477     public void rotate(float radians) {
 478         if (log.isLoggable(Level.FINE)) {
 479             log.fine("rotate(" + radians + ")");


 567 
 568     @Override
 569     public void clearRect(final float x, final float y, final float w, final float h) {
 570         if (log.isLoggable(Level.FINE)) {
 571             log.fine(String.format("clearRect(%f, %f, %f, %f)", x, y, w, h));
 572         }
 573         if (shouldCalculateIntersection()) {
 574             // No intersection is applicable for clearRect.
 575             return;
 576         }
 577         new Composite() {
 578             @Override void doPaint(Graphics g) {
 579                 g.clearQuad(x, y, x + w, y + h);
 580             }
 581         }.paint();
 582     }
 583 
 584     @Override
 585     public void setFillColor(int rgba) {
 586         if (log.isLoggable(Level.FINE)) {
 587             log.fine(String.format("setFillColor(0x%x)", rgba));
 588         }
 589         state.setPaint(createColor(rgba));
 590     }
 591 
 592     @Override
 593     public void setFillGradient(WCGradient gradient) {
 594         if (log.isLoggable(Level.FINE)) {
 595             log.fine("setFillGradient(" + gradient + ")");
 596         }
 597         state.setPaint((Gradient) gradient.getPlatformGradient());
 598     }
 599 
 600     @Override
 601     public void setTextMode(boolean fill, boolean stroke, boolean clip) {
 602         if (log.isLoggable(Level.FINE)) {
 603             log.fine("setTextMode(fill:" + fill + ",stroke:" + stroke + ",clip:" + clip + ")");
 604         }
 605         state.setTextMode(fill, stroke, clip);
 606     }
 607 
 608     @Override
 609     public void setFontSmoothingType(int fontSmoothingType) {
 610         this.fontSmoothingType = fontSmoothingType;
 611     }
 612 
 613     @Override
 614     public int getFontSmoothingType() {
 615         return fontSmoothingType;
 616     }
 617 
 618     @Override
 619     public void setStrokeStyle(int style) {
 620         if (log.isLoggable(Level.FINE)) {
 621             log.fine("setStrokeStyle({0})", style);
 622         }
 623         state.getStrokeNoClone().setStyle(style);
 624     }
 625 
 626     @Override
 627     public void setStrokeColor(int rgba) {
 628         if (log.isLoggable(Level.FINE)) {
 629             log.fine(String.format("setStrokeColor(0x%x)", rgba));
 630         }
 631         state.getStrokeNoClone().setPaint(createColor(rgba));
 632     }
 633 
 634     @Override
 635     public void setStrokeWidth(float width) {
 636         if (log.isLoggable(Level.FINE)) {
 637             log.fine("setStrokeWidth({0})", new Object[] { width });
 638         }
 639         state.getStrokeNoClone().setThickness(width);
 640     }
 641 
 642     @Override
 643     public void setStrokeGradient(WCGradient gradient) {
 644         if (log.isLoggable(Level.FINE)) {
 645             log.fine("setStrokeGradient(" + gradient + ")");
 646         }
 647         state.getStrokeNoClone().setPaint((Gradient) gradient.getPlatformGradient());
 648     }
 649 
 650     @Override
 651     public void setLineDash(float offset, float... sizes) {
 652         if (log.isLoggable(Level.FINE)) {
 653             StringBuilder s = new StringBuilder("[");
 654             for (int i=0; i < sizes.length; i++) {
 655                 s.append(sizes[i]).append(',');
 656             }
 657             s.append(']');
 658             log.fine("setLineDash({0},{1}", new Object[] {offset, s});
 659         }
 660         state.getStrokeNoClone().setDashOffset(offset);
 661         if (sizes != null) {
 662             boolean allZero = true;
 663             for (int i = 0; i < sizes.length; i++) {
 664                 if (sizes[i] != 0) {
 665                     allZero = false;
 666                     break;
 667                 }
 668             }
 669             if (allZero) {
 670                 sizes = null;
 671             }
 672         }
 673         state.getStrokeNoClone().setDashSizes(sizes);
 674     }
 675 
 676     @Override
 677     public void setLineCap(int lineCap) {
 678         if (log.isLoggable(Level.FINE)) {


 692     @Override
 693     public void setMiterLimit(float miterLimit) {
 694         if (log.isLoggable(Level.FINE)) {
 695             log.fine("setMiterLimit(" + miterLimit + ")");
 696         }
 697         state.getStrokeNoClone().setMiterLimit(miterLimit);
 698     }
 699 
 700     @Override
 701     public void setShadow(float dx, float dy, float blur, int rgba) {
 702         if (log.isLoggable(Level.FINE)) {
 703             String format = "setShadow(%f, %f, %f, 0x%x)";
 704             log.fine(String.format(format, dx, dy, blur, rgba));
 705         }
 706         state.setShadow(createShadow(dx, dy, blur, rgba));
 707     }
 708 
 709     @Override
 710     public void drawPolygon(final WCPath path, final boolean shouldAntialias) {
 711         if (log.isLoggable(Level.FINE)) {
 712             log.fine("drawPolygon({0})",
 713                     new Object[] {shouldAntialias});
 714         }
 715         if (!shouldRenderShape(((WCPathImpl)path).getPlatformPath(), null,
 716                                 state.getStrokeNoClone().getPlatformStroke()))
 717         {
 718             return;
 719         }
 720         new Composite() {
 721             @Override void doPaint(Graphics g) {
 722                 Path2D p2d = (Path2D) path.getPlatformPath();
 723                 g.setPaint(state.getPaintNoClone());
 724                 g.fill(p2d);
 725                 if (state.getStrokeNoClone().apply(g)) {
 726                     g.draw(p2d);
 727                 }
 728             }
 729         }.paint();
 730     }
 731 
 732     @Override
 733     public void drawLine(final int x0, final int y0, final int x1, final int y1) {
 734         if (log.isLoggable(Level.FINE)) {
 735             log.fine("drawLine({0}, {1}, {2}, {3})",
 736                     new Object[] {x0, y0, x1, y1});
 737         }
 738         Line2D line = new Line2D(x0, y0, x1, y1);
 739         if (!shouldRenderShape(line, null, state.getStrokeNoClone().getPlatformStroke())) {
 740             return;
 741         }
 742         new Composite() {
 743             @Override void doPaint(Graphics g) {
 744                 if (state.getStrokeNoClone().apply(g)) {
 745                     g.drawLine(x0, y0, x1, y1);
 746                 }
 747             }
 748         }.paint();
 749     }
 750 
 751     @Override
 752     public void drawPattern(
 753         final WCImage texture,
 754         final WCRectangle srcRect,
 755         final WCTransform patternTransform,
 756         final WCPoint phase,
 757         final WCRectangle destRect)
 758     {
 759         if (log.isLoggable(Level.FINE)) {
 760             log.fine("drawPattern({0}, {1}, {2}, {3})",
 761                     new Object[] {destRect.getIntX(), destRect.getIntY(),
 762                                   destRect.getIntWidth(),
 763                                   destRect.getIntHeight()});
 764         }
 765         if (!shouldRenderRect(destRect.getX(), destRect.getY(),
 766                               destRect.getWidth(), destRect.getHeight(), null, null))
 767         {
 768             return;
 769         }
 770         if (texture != null) {
 771             new Composite() {
 772                 @Override void doPaint(Graphics g) {
 773                     // The handling of pattern transform is modeled after the WebKit
 774                     // ImageCG.cpp's Image::drawPattern()
 775                     float adjustedX = phase.getX()
 776                             + srcRect.getX() * (float) patternTransform.getMatrix()[0];
 777                     float adjustedY = phase.getY()
 778                             + srcRect.getY() * (float) patternTransform.getMatrix()[3];
 779                     float scaledTileWidth =
 780                             srcRect.getWidth() * (float) patternTransform.getMatrix()[0];


 793                     }
 794                     g.setPaint(new ImagePattern(
 795                                img,
 796                                adjustedX, adjustedY,
 797                                scaledTileWidth, scaledTileHeight,
 798                                false, false));
 799 
 800                     g.fillRect(destRect.getX(), destRect.getY(),
 801                                destRect.getWidth(), destRect.getHeight());
 802                 }
 803             }.paint();
 804         }
 805     }
 806 
 807     @Override
 808     public void drawImage(final WCImage img,
 809                           final float dstx, final float dsty, final float dstw, final float dsth,
 810                           final float srcx, final float srcy, final float srcw, final float srch)
 811     {
 812         if (log.isLoggable(Level.FINE)){
 813             log.fine("drawImage(img, dst({0},{1},{2},{3}), " +
 814                     "src({4},{5},{6},{7}))",
 815                     new Object[] {dstx, dsty, dstw, dsth,
 816                                   srcx, srcy, srcw, srch});
 817         }
 818         if (!shouldRenderRect(dstx, dsty, dstw, dsth, state.getShadowNoClone(), null)) {
 819             return;
 820         }
 821         if (img instanceof PrismImage) {
 822             new Composite() {
 823                 @Override void doPaint(Graphics g) {
 824                     PrismImage pi = (PrismImage) img;
 825                     DropShadow shadow = state.getShadowNoClone();
 826                     if (shadow != null) {
 827                         NGImageView node = new NGImageView();
 828                         node.setImage(pi.getImage());
 829                         node.setX(dstx);
 830                         node.setY(dsty);
 831                         node.setViewport(srcx, srcy, srcw, srch, dstw, dsth);
 832                         node.setContentBounds(new RectBounds(dstx, dsty, dstx + dstw, dsty + dsth));
 833                         render(g, shadow, null, null, node);


 846     @Override
 847     public void drawBitmapImage(final ByteBuffer image, final int x, final int y, final int w, final int h) {
 848         if (!shouldRenderRect(x, y, w, h, null, null)) {
 849             return;
 850         }
 851         new Composite() {
 852             @Override void doPaint(Graphics g) {
 853                 image.order(ByteOrder.nativeOrder());
 854                 Image img = Image.fromByteBgraPreData(image, w, h);
 855                 ResourceFactory rf = g.getResourceFactory();
 856                 Texture txt = rf.createTexture(img, Texture.Usage.STATIC, Texture.WrapMode.REPEAT);
 857                 g.drawTexture(txt, x, y, x + w, y + h, 0, 0, w, h);
 858                 txt.dispose();
 859             }
 860         }.paint();
 861     }
 862 
 863     @Override
 864     public void drawIcon(WCIcon icon, int x, int y) {
 865         if (log.isLoggable(Level.FINE)) {
 866             log.fine("UNIMPLEMENTED drawIcon ({0}, {1})",
 867                     new Object[] {x, y});
 868         }
 869     }
 870 
 871     @Override
 872     public void drawRect(final int x, final int y, final int w, final int h) {
 873         if (log.isLoggable(Level.FINE)) {
 874             log.fine("drawRect({0}, {1}, {2}, {3})",
 875                     new Object[]{x, y, w, h});
 876         }
 877         if (!shouldRenderRect(x, y, w, h,
 878                               null, state.getStrokeNoClone().getPlatformStroke()))
 879         {
 880             return;
 881         }
 882         new Composite() {
 883             @Override void doPaint(Graphics g) {
 884                 Paint c = state.getPaintNoClone();
 885                 if (c != null && c.isOpaque()) {
 886                     g.setPaint(c);
 887                     g.fillRect(x, y, w, h);
 888                 }
 889 
 890                 if (state.getStrokeNoClone().apply(g)) {
 891                     g.drawRect(x, y, w, h);
 892                 }
 893             }
 894         }.paint();


 971             int gc = run.getGlyphCount();
 972             for (int i = 0; i < gc; i++) {
 973                 glyphs[count] = run.getGlyphCode(i);
 974                 adv[count] = run.getPosX(i + 1) - run.getPosX(i);
 975                 count++;
 976             }
 977         }
 978 
 979         // adjust x coordinate (see RT-29908)
 980         if (rtl) {
 981             x += (TextUtilities.getLayoutWidth(str.substring(from), f.getPlatformFont()) -
 982                   layout.getBounds().getWidth());
 983         } else {
 984             x += TextUtilities.getLayoutWidth(str.substring(0, from), f.getPlatformFont());
 985         }
 986         drawString(f, glyphs, adv, x, y);
 987     }
 988 
 989     @Override
 990     public void setComposite(int composite) {
 991         log.fine("setComposite({0})", composite);
 992         state.setCompositeOperation(composite);
 993     }
 994 
 995     @Override
 996     public void drawEllipse(final int x, final int y, final int w, final int h) {
 997         if (log.isLoggable(Level.FINE)) {
 998             log.fine("drawEllipse({0}, {1}, {2}, {3})",
 999                     new Object[] { x, y, w, h});
1000         }
1001         if (!shouldRenderRect(x, y, w, h,
1002                               null, state.getStrokeNoClone().getPlatformStroke()))
1003         {
1004             return;
1005         }
1006         new Composite() {
1007             @Override void doPaint(Graphics g) {
1008                 g.setPaint(state.getPaintNoClone());
1009                 g.fillEllipse(x, y, w, h);
1010                 if (state.getStrokeNoClone().apply(g)) {
1011                     g.drawEllipse(x, y, w, h);
1012                 }
1013             }
1014         }.paint();
1015     }
1016 
1017     private final static BasicStroke focusRingStroke =
1018         new BasicStroke(1.1f, BasicStroke.CAP_BUTT,
1019                          BasicStroke.JOIN_ROUND, 0.0f,
1020                          new float[] {1.0f}, 0.0f);
1021 
1022     @Override
1023     public void drawFocusRing(final int x, final int y, final int w, final int h, final int rgba) {
1024         if (log.isLoggable(Level.FINE)) {
1025             log.fine(String.format("drawFocusRing: %d, %d, %d, %d, 0x%x", x, y, w, h, rgba));


1026         }
1027         if (!shouldRenderRect(x, y, w, h, null, focusRingStroke)) {
1028             return;
1029         }
1030         new Composite() {
1031             @Override void doPaint(Graphics g) {
1032                 g.setPaint(createColor(rgba));
1033                 BasicStroke stroke = g.getStroke();
1034                 g.setStroke(focusRingStroke);
1035                 g.drawRoundRect(x, y, w, h, 4, 4);
1036                 g.setStroke(stroke);
1037             }
1038         }.paint();
1039     }
1040 
1041     public void setAlpha(float alpha) {
1042         log.fine("setAlpha({0})", alpha);
1043 
1044         state.setAlpha(alpha);
1045 
1046         if (null != cachedGraphics) {
1047             cachedGraphics.setExtraAlpha(state.getAlpha());
1048         }
1049     }
1050 
1051     public float getAlpha() {
1052         return state.getAlpha();
1053     }
1054 
1055     @Override public void beginTransparencyLayer(float opacity) {
1056         TransparencyLayer layer = new TransparencyLayer(
1057                 getGraphics(false), state.getClipNoClone(), opacity);
1058 
1059         if (log.isLoggable(Level.FINE)) {
1060             log.fine(String.format("beginTransparencyLayer(%s)", layer));
1061         }
1062 


< prev index next >