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 33 import sun.java2d.*; 34 import sun.java2d.loops.*; 35 import sun.java2d.pipe.*; 36 37 abstract class XRPaints { 38 static XRCompositeManager xrCompMan; 39 40 static final XRGradient xrGradient = new XRGradient(); 41 static final XRLinearGradient xrLinearGradient = new XRLinearGradient(); 42 static final XRRadialGradient xrRadialGradient = new XRRadialGradient(); 43 static final XRTexture xrTexture = new XRTexture(); 44 45 public static void register(XRCompositeManager xrComp) { 46 xrCompMan = xrComp; 47 } 48 49 private static XRPaints getXRPaint(SunGraphics2D sg2d) { 50 switch (sg2d.paintState) { 51 case SunGraphics2D.PAINT_GRADIENT: 52 return xrGradient; 53 54 case SunGraphics2D.PAINT_LIN_GRADIENT: 55 return xrLinearGradient; 56 57 case SunGraphics2D.PAINT_RAD_GRADIENT: 58 return xrRadialGradient; 59 60 case SunGraphics2D.PAINT_TEXTURE: 61 return xrTexture; 62 63 default: 64 return null; 65 } 66 } 67 68 /** 69 * Attempts to locate an implementation corresponding to the paint state of 70 * the provided SunGraphics2D object. If no implementation can be found, or 71 * if the paint cannot be accelerated under the conditions of the 72 * SunGraphics2D, this method returns false; otherwise, returns true. 73 */ 74 static boolean isValid(SunGraphics2D sg2d) { 75 XRPaints impl = getXRPaint(sg2d); 76 return (impl != null && impl.isPaintValid(sg2d)); 77 } 78 79 static void setPaint(SunGraphics2D sg2d, Paint paint) { 80 XRPaints impl = getXRPaint(sg2d); 81 if (impl != null) { 82 impl.setXRPaint(sg2d, paint); 83 } 84 } 85 86 /** 87 * Returns true if this implementation is able to accelerate the Paint 88 * object associated with, and under the conditions of, the provided 89 * SunGraphics2D instance; otherwise returns false. 90 */ 91 abstract boolean isPaintValid(SunGraphics2D sg2d); 92 93 abstract void setXRPaint(SunGraphics2D sg2d, Paint paint); 94 95 private static class XRGradient extends XRPaints { 96 private XRGradient() { 97 } 98 99 /** 100 * There are no restrictions for accelerating GradientPaint, so this 101 * method always returns true. 102 */ 103 @Override 104 boolean isPaintValid(SunGraphics2D sg2d) { 105 return true; 106 } 107 108 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 109 GradientPaint paint = (GradientPaint) pt; 110 111 int[] pixels = convertToIntArgbPixels(new Color[] { paint.getColor1(), paint.getColor2() }, false); 112 113 float fractions[] = new float[2]; 114 fractions[0] = 0; 115 fractions[1] = 1; 116 117 Point2D pt1 = paint.getPoint1(); 118 Point2D pt2 = paint.getPoint2(); 119 120 AffineTransform at = (AffineTransform) sg2d.transform.clone(); 121 try { 122 at.invert(); 123 } catch (NoninvertibleTransformException ex) { 124 at.setToIdentity(); 125 } 126 127 int repeat = paint.isCyclic() ? XRUtils.RepeatReflect : XRUtils.RepeatPad; 128 129 XRBackend con = xrCompMan.getBackend(); 130 int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat, at); 131 xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient, at)); 132 } 133 } 134 135 public int getGradientLength(Point2D pt1, Point2D pt2) { 136 double xDiff = Math.max(pt1.getX(), pt2.getX()) - Math.min(pt1.getX(), pt2.getX()); 137 double yDiff = Math.max(pt1.getY(), pt2.getY()) - Math.min(pt1.getY(), pt2.getY()); 138 return (int) Math.ceil(Math.sqrt(xDiff*xDiff + yDiff*yDiff)); 139 } 140 141 private static class XRLinearGradient extends XRPaints { 142 143 @Override 144 boolean isPaintValid(SunGraphics2D sg2d) { 145 return true; 146 } 147 148 @Override 149 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 150 LinearGradientPaint paint = (LinearGradientPaint) pt; 151 boolean linear = (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB); 152 153 Color[] colors = paint.getColors(); 154 Point2D pt1 = paint.getStartPoint(); 155 Point2D pt2 = paint.getEndPoint(); 156 157 158 AffineTransform at = paint.getTransform(); 159 at.preConcatenate(sg2d.transform); 160 161 int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod()); 162 float[] fractions = paint.getFractions(); 163 int[] pixels = convertToIntArgbPixels(colors, linear); 164 165 try { 166 at.invert(); 167 } catch (NoninvertibleTransformException ex) { 168 ex.printStackTrace(); 169 } 170 171 XRBackend con = xrCompMan.getBackend(); 172 int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat, at); 173 xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient, at)); 174 } 175 } 176 177 private static class XRRadialGradient extends XRPaints { 178 179 @Override 180 boolean isPaintValid(SunGraphics2D sg2d) { 181 RadialGradientPaint grad = (RadialGradientPaint) sg2d.paint; 182 return grad.getFocusPoint().equals(grad.getCenterPoint()); 183 } 184 185 @Override 186 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 187 RadialGradientPaint paint = (RadialGradientPaint) pt; 188 boolean linear = (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB); 189 Color[] colors = paint.getColors(); 190 Point2D center = paint.getCenterPoint(); 191 Point2D focus = paint.getFocusPoint(); 192 193 int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod()); 194 float[] fractions = paint.getFractions(); 195 int[] pixels = convertToIntArgbPixels(colors, linear); 196 float radius = paint.getRadius(); 197 198 // save original (untransformed) center and focus points 199 double cx = center.getX(); 200 double cy = center.getY(); 201 double fx = focus.getX(); 202 double fy = focus.getY(); 203 204 AffineTransform at = paint.getTransform(); 205 at.preConcatenate(sg2d.transform); 206 focus = at.transform(focus, focus); 207 208 // transform unit circle to gradient coords; we start with the 209 // unit circle (center=(0,0), focus on positive x-axis, radius=1) 210 // and then transform into gradient space 211 at.translate(cx, cy); 212 at.rotate(fx - cx, fy - cy); 213 // at.scale(radius, radius); 214 215 // invert to get mapping from device coords to unit circle 216 try { 217 at.invert(); 218 } catch (Exception e) { 219 at.setToScale(0.0, 0.0); 220 } 221 focus = at.transform(focus, focus); 222 223 // clamp the focus point so that it does not rest on, or outside 224 // of, the circumference of the gradient circle 225 fx = Math.min(focus.getX(), 0.99); 226 227 XRBackend con = xrCompMan.getBackend(); 228 int gradient = con.createRadialGradient(new Point2D.Float(0, 0), new Point2D.Float(0, 0), 0, radius, fractions, pixels, repeat, at); 229 xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient, at)); 230 } 231 } 232 233 private static class XRTexture extends XRPaints { 234 235 @Override 236 boolean isPaintValid(SunGraphics2D sg2d) { 237 TexturePaint paint = (TexturePaint) sg2d.paint; 238 BufferedImage bi = paint.getImage(); 239 XRSurfaceData dstData = (XRSurfaceData) sg2d.getDestSurface(); 240 241 SurfaceData srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 242 if (!(srcData instanceof XRSurfaceData)) { 243 // REMIND: this is a hack that attempts to cache the system 244 // memory image from the TexturePaint instance into an 245 // OpenGL texture... 246 srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 247 if (!(srcData instanceof XRSurfaceData)) { 248 return false; 249 } 250 } 251 252 return true; 253 } 254 255 @Override 256 void setXRPaint(SunGraphics2D sg2d, Paint pt) { 257 TexturePaint paint = (TexturePaint) pt; 258 259 BufferedImage bi = paint.getImage(); 260 SurfaceData dstData = sg2d.surfaceData; 261 SurfaceData srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 262 263 // REMIND: this hack tries to ensure that we have a cached texture 264 if (!(srcData instanceof XRSurfaceData)) { 265 srcData = dstData.getSourceSurfaceData(paint.getImage(), SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null); 266 if (!(srcData instanceof XRSurfaceData)) { 267 throw new InternalError("Surface not cachable"); 268 } 269 } 270 271 XRSurfaceData x11SrcData = (XRSurfaceData) srcData; 272 273 AffineTransform at = (AffineTransform) sg2d.transform.clone(); 274 Rectangle2D anchor = paint.getAnchorRect(); 275 at.translate(anchor.getX(), anchor.getY()); 276 at.scale(anchor.getWidth() / ((double) bi.getWidth()), anchor.getHeight() / ((double) bi.getHeight())); 277 278 try { 279 at.invert(); 280 } catch (NoninvertibleTransformException ex) { 281 at.setToIdentity(); /* TODO: Right thing to do in this case? */ 282 } 283 284 x11SrcData.validateAsSource(at, XRUtils.RepeatNormal, XRUtils.ATransOpToXRQuality(sg2d.interpolationType)); 285 xrCompMan.setTexturePaint(((XRSurfaceData) srcData)); 286 } 287 } 288 289 public int[] convertToIntArgbPixels(Color[] colors, boolean linear) { 290 int[] pixels = new int[colors.length]; 291 for (int i = 0; i < colors.length; i++) { 292 pixels[i] = colorToIntArgbPixel(colors[i], linear); 293 } 294 return pixels; 295 } 296 297 public int colorToIntArgbPixel(Color c, boolean linear) { 298 int rgb = c.getRGB(); 299 300 int a = rgb >>> 24; 301 int r = (rgb >> 16) & 0xff; 302 int g = (rgb >> 8) & 0xff; 303 int b = (rgb) & 0xff; 304 if (linear) { 305 r = BufferedPaints.convertSRGBtoLinearRGB(r); 306 g = BufferedPaints.convertSRGBtoLinearRGB(g); 307 b = BufferedPaints.convertSRGBtoLinearRGB(b); 308 } 309 310 a *= xrCompMan.getExtraAlpha(); 311 312 return ((a << 24) | (r << 16) | (g << 8) | (b)); 313 } 314 }