1 /* 2 * Copyright (c) 2010, 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 /** 99 * There are no restrictions for accelerating GradientPaint, so this 100 * method always returns true. 101 */ 102 @Override 103 boolean isPaintValid(SunGraphics2D sg2d) { 104 return true; 105 } 106 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 return ((LinearGradientPaint) sg2d.getPaint()).getColorSpace() == ColorSpaceType.SRGB; 134 } 135 136 @Override 137 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 138 LinearGradientPaint paint = (LinearGradientPaint) pt; 139 140 Color[] colors = paint.getColors(); 141 Point2D pt1 = paint.getStartPoint(); 142 Point2D pt2 = paint.getEndPoint(); 143 144 int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod()); 145 float[] fractions = paint.getFractions(); 146 int[] pixels = convertToIntArgbPixels(colors); 147 148 AffineTransform at = paint.getTransform(); 149 try { 150 at.invert(); 151 } catch (NoninvertibleTransformException ex) { 152 ex.printStackTrace(); 153 } 154 155 XRBackend con = xrCompMan.getBackend(); 156 int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat); 157 XRInternalSurfaceData x11sd = new XRSurfaceData.XRInternalSurfaceData(con, gradient); 158 x11sd.setStaticSrcTx(at); 159 xrCompMan.setGradientPaint(x11sd); 160 } 161 } 162 163 private static class XRRadialGradient extends XRPaints { 164 165 @Override 166 boolean isPaintValid(SunGraphics2D sg2d) { 167 RadialGradientPaint grad = (RadialGradientPaint) sg2d.paint; 168 return grad.getFocusPoint().equals(grad.getCenterPoint()) 169 && grad.getColorSpace() == ColorSpaceType.SRGB; 170 } 171 172 @Override 173 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 174 RadialGradientPaint paint = (RadialGradientPaint) pt; 175 Color[] colors = paint.getColors(); 176 Point2D center = paint.getCenterPoint(); 177 178 int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod()); 179 float[] fractions = paint.getFractions(); 180 int[] pixels = convertToIntArgbPixels(colors); 181 float radius = paint.getRadius(); 182 183 float cx = (float) center.getX(); 184 float cy = (float) center.getY(); 185 186 AffineTransform at = paint.getTransform(); 187 try { 188 at.invert(); 189 } catch (NoninvertibleTransformException ex) { 190 ex.printStackTrace(); 191 } 192 193 XRBackend con = xrCompMan.getBackend(); 194 int gradient = con.createRadialGradient(cx, cy, 0, radius, fractions, pixels, repeat); 195 XRInternalSurfaceData x11sd = new XRSurfaceData.XRInternalSurfaceData(con, gradient); 196 x11sd.setStaticSrcTx(at); 197 xrCompMan.setGradientPaint(x11sd); 198 } 199 } 200 201 private static class XRTexture extends XRPaints { 202 203 private XRSurfaceData getAccSrcSurface(XRSurfaceData dstData, BufferedImage bi) { 204 // REMIND: this is a hack that attempts to cache the system 205 // memory image from the TexturePaint instance into an 206 // XRender pixmap... 207 SurfaceData srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 208 if (!(srcData instanceof XRSurfaceData)) { 209 srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 210 if (!(srcData instanceof XRSurfaceData)) { 211 throw new InternalError("Surface not cachable"); 212 } 213 } 214 215 return (XRSurfaceData) srcData; 216 } 217 218 @Override 219 boolean isPaintValid(SunGraphics2D sg2d) { 220 TexturePaint paint = (TexturePaint) sg2d.paint; 221 BufferedImage bi = paint.getImage(); 222 XRSurfaceData dstData = (XRSurfaceData) sg2d.getDestSurface(); 223 224 return getAccSrcSurface(dstData, bi) != null; 225 } 226 227 @Override 228 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 229 TexturePaint paint = (TexturePaint) pt; 230 BufferedImage bi = paint.getImage(); 231 Rectangle2D anchor = paint.getAnchorRect(); 232 233 XRSurfaceData dstData = (XRSurfaceData) sg2d.surfaceData; 234 XRSurfaceData srcData = (XRSurfaceData) getAccSrcSurface(dstData, bi); 235 236 AffineTransform at = new AffineTransform(); 237 at.translate(anchor.getX(), anchor.getY()); 238 at.scale(anchor.getWidth() / ((double) bi.getWidth()), anchor.getHeight() / ((double) bi.getHeight())); 239 240 try { 241 at.invert(); 242 } catch (NoninvertibleTransformException ex) { 243 at.setToIdentity(); 244 } 245 srcData.setStaticSrcTx(at); 246 247 srcData.validateAsSource(at, XRUtils.RepeatNormal, XRUtils.ATransOpToXRQuality(sg2d.interpolationType)); 248 xrCompMan.setTexturePaint(srcData); 249 } 250 } 251 252 public int[] convertToIntArgbPixels(Color[] colors) { 253 int[] pixels = new int[colors.length]; 254 for (int i = 0; i < colors.length; i++) { 255 pixels[i] = colorToIntArgbPixel(colors[i]); 256 } 257 return pixels; 258 } 259 260 public int colorToIntArgbPixel(Color c) { 261 int rgb = c.getRGB(); 262 int a = (int) Math.round(xrCompMan.getExtraAlpha() * (rgb >>> 24)); 263 return ((a << 24) | (rgb & 0x00FFFFFF)); 264 } 265 }