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
|