1 /* 2 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 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 sun.java2d.xr; 27 28 import java.awt.*; 29 import java.awt.MultipleGradientPaint.*; 30 import java.awt.geom.*; 31 import java.awt.image.*; 32 import sun.java2d.*; 33 import sun.java2d.loops.*; 34 import sun.java2d.xr.XRSurfaceData.XRInternalSurfaceData; 35 36 abstract class XRPaints { 37 static XRCompositeManager xrCompMan; 38 39 static final XRGradient xrGradient = new XRGradient(); 40 static final XRLinearGradient xrLinearGradient = new XRLinearGradient(); 41 static final XRRadialGradient xrRadialGradient = new XRRadialGradient(); 42 static final XRTexture xrTexture = new XRTexture(); 43 44 public static void register(XRCompositeManager xrComp) { 45 xrCompMan = xrComp; 46 } 47 48 private static XRPaints getXRPaint(SunGraphics2D sg2d) { 49 switch (sg2d.paintState) { 50 case SunGraphics2D.PAINT_GRADIENT: 51 return xrGradient; 52 53 case SunGraphics2D.PAINT_LIN_GRADIENT: 54 return xrLinearGradient; 55 56 case SunGraphics2D.PAINT_RAD_GRADIENT: 57 return xrRadialGradient; 58 59 case SunGraphics2D.PAINT_TEXTURE: 60 return xrTexture; 61 62 default: 63 return null; 64 } 65 } 66 67 /** 68 * Attempts to locate an implementation corresponding to the paint state of 69 * the provided SunGraphics2D object. If no implementation can be found, or 70 * if the paint cannot be accelerated under the conditions of the 71 * SunGraphics2D, this method returns false; otherwise, returns true. 72 */ 73 static boolean isValid(SunGraphics2D sg2d) { 74 XRPaints impl = getXRPaint(sg2d); 75 return (impl != null && impl.isPaintValid(sg2d)); 76 } 77 78 static void setPaint(SunGraphics2D sg2d, Paint paint) { 79 XRPaints impl = getXRPaint(sg2d); 80 if (impl != null) { 81 impl.setXRPaint(sg2d, paint); 82 } 83 } 84 85 /** 86 * Returns true if this implementation is able to accelerate the Paint 87 * object associated with, and under the conditions of, the provided 88 * SunGraphics2D instance; otherwise returns false. 89 */ 90 abstract boolean isPaintValid(SunGraphics2D sg2d); 91 92 abstract void setXRPaint(SunGraphics2D sg2d, Paint paint); 93 94 private static class XRGradient extends XRPaints { 95 private XRGradient() { 96 } 97 98 @Override 99 boolean isPaintValid(SunGraphics2D sg2d) { 100 GradientPaint paint = (GradientPaint) sg2d.paint; 101 102 return XRUtils.isPointCoordInShortRange(paint.getPoint1()) 103 && XRUtils.isPointCoordInShortRange(paint.getPoint2()); 104 } 105 106 @Override 107 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 108 GradientPaint paint = (GradientPaint) pt; 109 110 int repeat = paint.isCyclic() ? XRUtils.RepeatReflect : XRUtils.RepeatPad; 111 float fractions[] = {0, 1}; 112 int[] pixels = convertToIntArgbPixels(new Color[] { paint.getColor1(), paint.getColor2() }); 113 114 Point2D pt1 = paint.getPoint1(); 115 Point2D pt2 = paint.getPoint2(); 116 117 XRBackend con = xrCompMan.getBackend(); 118 int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat); 119 xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient)); 120 } 121 } 122 123 public int getGradientLength(Point2D pt1, Point2D pt2) { 124 double xDiff = Math.max(pt1.getX(), pt2.getX()) - Math.min(pt1.getX(), pt2.getX()); 125 double yDiff = Math.max(pt1.getY(), pt2.getY()) - Math.min(pt1.getY(), pt2.getY()); 126 return (int) Math.ceil(Math.sqrt(xDiff*xDiff + yDiff*yDiff)); 127 } 128 129 private static class XRLinearGradient extends XRPaints { 130 131 @Override 132 boolean isPaintValid(SunGraphics2D sg2d) { 133 LinearGradientPaint paint = (LinearGradientPaint) sg2d.getPaint(); 134 135 return paint.getColorSpace() == ColorSpaceType.SRGB 136 && XRUtils.isPointCoordInShortRange(paint.getStartPoint()) 137 && XRUtils.isPointCoordInShortRange(paint.getEndPoint()) 138 && paint.getTransform().getDeterminant() != 0.0; 139 } 140 141 @Override 142 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 143 LinearGradientPaint paint = (LinearGradientPaint) pt; 144 Color[] colors = paint.getColors(); 145 Point2D pt1 = paint.getStartPoint(); 146 Point2D pt2 = paint.getEndPoint(); 147 int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod()); 148 float[] fractions = paint.getFractions(); 149 int[] pixels = convertToIntArgbPixels(colors); 150 AffineTransform at = paint.getTransform(); 151 152 try { 153 at.invert(); 154 } catch (NoninvertibleTransformException ex) { 155 ex.printStackTrace(); 156 } 157 158 XRBackend con = xrCompMan.getBackend(); 159 int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat); 160 XRInternalSurfaceData x11sd = new XRSurfaceData.XRInternalSurfaceData(con, gradient); 161 x11sd.setStaticSrcTx(at); 162 xrCompMan.setGradientPaint(x11sd); 163 } 164 } 165 166 private static class XRRadialGradient extends XRPaints { 167 168 @Override 169 boolean isPaintValid(SunGraphics2D sg2d) { 170 RadialGradientPaint grad = (RadialGradientPaint) sg2d.paint; 171 172 return grad.getColorSpace() == ColorSpaceType.SRGB 173 && grad.getFocusPoint().equals(grad.getCenterPoint()) 174 && XRUtils.isPointCoordInShortRange(grad.getCenterPoint()) 175 && grad.getRadius() <= Short.MAX_VALUE 176 && grad.getTransform().getDeterminant() != 0.0; 177 } 178 179 @Override 180 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 181 RadialGradientPaint paint = (RadialGradientPaint) pt; 182 Color[] colors = paint.getColors(); 183 Point2D center = paint.getCenterPoint(); 184 float cx = (float) center.getX(); 185 float cy = (float) center.getY(); 186 187 AffineTransform at = paint.getTransform(); 188 int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod()); 189 float[] fractions = paint.getFractions(); 190 int[] pixels = convertToIntArgbPixels(colors); 191 float radius = paint.getRadius(); 192 193 try { 194 at.invert(); 195 } catch (NoninvertibleTransformException ex) { 196 ex.printStackTrace(); 197 } 198 199 XRBackend con = xrCompMan.getBackend(); 200 int gradient = con.createRadialGradient(cx, cy, 0, radius, fractions, pixels, repeat); 201 XRInternalSurfaceData x11sd = new XRSurfaceData.XRInternalSurfaceData(con, gradient); 202 x11sd.setStaticSrcTx(at); 203 xrCompMan.setGradientPaint(x11sd); 204 } 205 } 206 207 private static class XRTexture extends XRPaints { 208 209 private XRSurfaceData getAccSrcSurface(XRSurfaceData dstData, BufferedImage bi) { 210 // REMIND: this is a hack that attempts to cache the system 211 // memory image from the TexturePaint instance into an 212 // XRender pixmap... 213 SurfaceData srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 214 if (!(srcData instanceof XRSurfaceData)) { 215 srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 216 if (!(srcData instanceof XRSurfaceData)) { 217 throw new InternalError("Surface not cachable"); 218 } 219 } 220 221 return (XRSurfaceData) srcData; 222 } 223 224 @Override 225 boolean isPaintValid(SunGraphics2D sg2d) { 226 TexturePaint paint = (TexturePaint) sg2d.paint; 227 BufferedImage bi = paint.getImage(); 228 XRSurfaceData dstData = (XRSurfaceData) sg2d.getDestSurface(); 229 230 return getAccSrcSurface(dstData, bi) != null; 231 } 232 233 @Override 234 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 235 TexturePaint paint = (TexturePaint) pt; 236 BufferedImage bi = paint.getImage(); 237 Rectangle2D anchor = paint.getAnchorRect(); 238 239 XRSurfaceData dstData = (XRSurfaceData) sg2d.surfaceData; 240 XRSurfaceData srcData = getAccSrcSurface(dstData, bi); 241 242 AffineTransform at = new AffineTransform(); 243 at.translate(anchor.getX(), anchor.getY()); 244 at.scale(anchor.getWidth() / ((double) bi.getWidth()), anchor.getHeight() / ((double) bi.getHeight())); 245 246 try { 247 at.invert(); 248 } catch (NoninvertibleTransformException ex) { 249 at.setToIdentity(); 250 } 251 srcData.setStaticSrcTx(at); 252 253 srcData.validateAsSource(at, XRUtils.RepeatNormal, XRUtils.ATransOpToXRQuality(sg2d.interpolationType)); 254 xrCompMan.setTexturePaint(srcData); 255 } 256 } 257 258 public int[] convertToIntArgbPixels(Color[] colors) { 259 int[] pixels = new int[colors.length]; 260 for (int i = 0; i < colors.length; i++) { 261 pixels[i] = colorToIntArgbPixel(colors[i]); 262 } 263 return pixels; 264 } 265 266 public int colorToIntArgbPixel(Color c) { 267 int rgb = c.getRGB(); 268 int a = Math.round(xrCompMan.getExtraAlpha() * (rgb >>> 24)); 269 return ((a << 24) | (rgb & 0x00FFFFFF)); 270 } 271 }