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.geom.*; 30 31 import java.security.AccessController; 32 import java.security.PrivilegedAction; 33 34 import sun.font.*; 35 import sun.java2d.*; 36 import sun.java2d.jules.*; 37 import sun.java2d.loops.*; 38 39 /** 40 * Manages per-application resources, e.g. the 1x1 pixmap used for solid color 41 * fill as well as per-application state e.g. the currently set source picture 42 * used for composition . 43 * 44 * @author Clemens Eisserer 45 */ 46 47 public class XRCompositeManager { 48 private static boolean enableGradCache = true; 49 private static XRCompositeManager instance; 50 51 XRSurfaceData src; 52 XRSurfaceData texture; 53 XRSurfaceData gradient; 54 int alphaMask = XRUtils.None; 55 56 XRColor solidColor = new XRColor(); 57 float extraAlpha = 1.0f; 58 byte compRule = XRUtils.PictOpOver; 59 XRColor alphaColor = new XRColor(); 60 61 XRSurfaceData solidSrcPict; 62 int alphaMaskPict; 63 int gradCachePixmap; 64 int gradCachePicture; 65 66 boolean xorEnabled = false; 67 int validatedPixel = 0; 68 Composite validatedComp; 69 Paint validatedPaint; 70 float validatedExtraAlpha = 1.0f; 71 72 XRBackend con; 73 MaskTileManager maskBuffer; 74 XRTextRenderer textRenderer; 75 XRMaskImage maskImage; 76 77 public static synchronized XRCompositeManager getInstance( 78 XRSurfaceData surface) { 79 if (instance == null) { 80 instance = new XRCompositeManager(surface); 81 } 82 return instance; 83 } 84 85 private XRCompositeManager(XRSurfaceData surface) { 86 con = new XRBackendNative(); 87 // con = XRBackendJava.getInstance(); 88 89 String gradProp = 90 AccessController.doPrivileged(new PrivilegedAction<String>() { 91 public String run() { 92 return System.getProperty("sun.java2d.xrgradcache"); 93 } 94 }); 95 96 enableGradCache = gradProp == null || 97 !(gradProp.equalsIgnoreCase("false") || 98 gradProp.equalsIgnoreCase("f")); 99 100 XRPaints.register(this); 101 102 initResources(surface); 103 104 maskBuffer = new MaskTileManager(this, surface.getXid()); 105 textRenderer = new XRTextRenderer(this); 106 maskImage = new XRMaskImage(this, surface.getXid()); 107 } 108 109 public void initResources(XRSurfaceData surface) { 110 int parentXid = surface.getXid(); 111 112 int solidPixmap = con.createPixmap(parentXid, 32, 1, 1); 113 int solidSrcPictXID = con.createPicture(solidPixmap, 114 XRUtils.PictStandardARGB32); 115 con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal); 116 con.renderRectangle(solidSrcPictXID, XRUtils.PictOpSrc, 117 XRColor.FULL_ALPHA, 0, 0, 1, 1); 118 solidSrcPict = new XRSurfaceData.XRInternalSurfaceData(con, 119 solidSrcPictXID, null); 120 setForeground(0); 121 122 int extraAlphaMask = con.createPixmap(parentXid, 8, 1, 1); 123 alphaMaskPict = con.createPicture(extraAlphaMask, 124 XRUtils.PictStandardA8); 125 con.setPictureRepeat(alphaMaskPict, XRUtils.RepeatNormal); 126 con.renderRectangle(alphaMaskPict, XRUtils.PictOpClear, 127 XRColor.NO_ALPHA, 0, 0, 1, 1); 128 129 if (enableGradCache) { 130 gradCachePixmap = con.createPixmap(parentXid, 32, 131 MaskTileManager.MASK_SIZE, MaskTileManager.MASK_SIZE); 132 gradCachePicture = con.createPicture(gradCachePixmap, 133 XRUtils.PictStandardARGB32); 134 } 135 } 136 137 public void setForeground(int pixel) { 138 solidColor.setColorValues(pixel, false); 139 con.renderRectangle(solidSrcPict.picture, XRUtils.PictOpSrc, 140 solidColor, 0, 0, 1, 1); 141 } 142 143 public void setGradientPaint(XRSurfaceData gradient) { 144 if (this.gradient != null) { 145 con.freePicture(this.gradient.picture); 146 } 147 this.gradient = gradient; 148 src = gradient; 149 } 150 151 public void setTexturePaint(XRSurfaceData texture) { 152 this.texture = texture; 153 src = texture; 154 } 155 156 public void XRResetPaint() { 157 src = solidSrcPict; 158 } 159 160 public void validateCompositeState(Composite comp, AffineTransform xform, 161 Paint paint, SunGraphics2D sg2d) { 162 boolean updatePaint = (paint != validatedPaint) || paint == null; 163 164 // validate composite 165 if ((comp != validatedComp)) { 166 if (comp != null) { 167 setComposite(comp); 168 } else { 169 comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER); 170 setComposite(comp); 171 } 172 // the paint state is dependent on the composite state, so make 173 // sure we update the color below 174 updatePaint = true; 175 validatedComp = comp; 176 } 177 178 if (sg2d != null && validatedPixel != sg2d.pixel) { 179 validatedPixel = sg2d.pixel; 180 setForeground(validatedPixel); 181 } 182 183 // validate paint 184 if (updatePaint) { 185 if (paint != null && sg2d != null 186 && sg2d.paintState >= SunGraphics2D.PAINT_GRADIENT) { 187 XRPaints.setPaint(sg2d, paint); 188 } else { 189 XRResetPaint(); 190 } 191 validatedPaint = paint; 192 } 193 194 if (src != solidSrcPict) { 195 AffineTransform at = (AffineTransform) xform.clone(); 196 try { 197 at.invert(); 198 } catch (NoninvertibleTransformException e) { 199 at.setToIdentity(); 200 } 201 src.validateAsSource(at, -1, -1); 202 } 203 } 204 205 private void setComposite(Composite comp) { 206 if (comp instanceof AlphaComposite) { 207 AlphaComposite aComp = (AlphaComposite) comp; 208 validatedExtraAlpha = aComp.getAlpha(); 209 210 this.compRule = XRUtils.j2dAlphaCompToXR(aComp.getRule()); 211 this.extraAlpha = validatedExtraAlpha; 212 213 if (extraAlpha == 1.0f) { 214 alphaMask = XRUtils.None; 215 alphaColor.alpha = XRColor.FULL_ALPHA.alpha; 216 } else { 217 alphaColor.alpha = XRColor 218 .byteToXRColorValue((int) (extraAlpha * 255)); 219 alphaMask = alphaMaskPict; 220 con.renderRectangle(alphaMaskPict, XRUtils.PictOpSrc, 221 alphaColor, 0, 0, 1, 1); 222 } 223 224 xorEnabled = false; 225 } else if (comp instanceof XORComposite) { 226 /* XOR composite validation is handled in XRSurfaceData */ 227 xorEnabled = true; 228 } else { 229 throw new InternalError( 230 "Composite accaleration not implemented for: " 231 + comp.getClass().getName()); 232 } 233 } 234 235 public boolean maskRequired() { 236 return (!xorEnabled) 237 && ((src != solidSrcPict) 238 || (src == solidSrcPict && solidColor.alpha != 0xffff) || (extraAlpha != 1.0f)); 239 } 240 241 public void XRComposite(int src, int mask, int dst, int srcX, int srcY, 242 int maskX, int maskY, int dstX, int dstY, int width, int height) { 243 int cachedSrc = (src == XRUtils.None) ? this.src.picture : src; 244 int cachedX = srcX; 245 int cachedY = srcY; 246 247 if (enableGradCache && gradient != null 248 && cachedSrc == gradient.picture) { 249 con.renderComposite(XRUtils.PictOpSrc, gradient.picture, 250 XRUtils.None, gradCachePicture, srcX, srcY, 0, 0, 0, 0, 251 width, height); 252 cachedX = 0; 253 cachedY = 0; 254 cachedSrc = gradCachePicture; 255 } 256 257 con.renderComposite(compRule, cachedSrc, mask, dst, cachedX, cachedY, 258 maskX, maskY, dstX, dstY, width, height); 259 } 260 261 public void XRCompositeTraps(int dst, int srcX, int srcY, 262 TrapezoidList trapList) { 263 int renderReferenceX = 0; 264 int renderReferenceY = 0; 265 266 if (trapList.getP1YLeft(0) < trapList.getP2YLeft(0)) { 267 renderReferenceX = trapList.getP1XLeft(0); 268 renderReferenceY = trapList.getP1YLeft(0); 269 } else { 270 renderReferenceX = trapList.getP2XLeft(0); 271 renderReferenceY = trapList.getP2YLeft(0); 272 } 273 274 renderReferenceX = (int) Math.floor(XRUtils 275 .XFixedToDouble(renderReferenceX)); 276 renderReferenceY = (int) Math.floor(XRUtils 277 .XFixedToDouble(renderReferenceY)); 278 279 con.renderCompositeTrapezoids(compRule, src.picture, 280 XRUtils.PictStandardA8, dst, renderReferenceX, 281 renderReferenceY, trapList); 282 } 283 284 public void XRRenderRectangles(XRSurfaceData dst, GrowableRectArray rects) { 285 if (xorEnabled) { 286 con.GCRectangles(dst.getXid(), dst.getGC(), rects); 287 } else { 288 if (rects.getSize() == 1) { 289 con.renderRectangle(dst.getPicture(), compRule, solidColor, 290 rects.getX(0), rects.getY(0), rects.getWidth(0), rects.getHeight(0)); 291 } else { 292 con.renderRectangles(dst.getPicture(), compRule, solidColor, rects); 293 } 294 } 295 } 296 297 public void compositeBlit(XRSurfaceData src, XRSurfaceData dst, int sx, 298 int sy, int dx, int dy, int w, int h) { 299 con.renderComposite(compRule, src.picture, alphaMask, dst.picture, sx, 300 sy, 0, 0, dx, dy, w, h); 301 } 302 303 public void compositeText(XRSurfaceData dst, int sx, int sy, 304 int glyphSet, int maskFormat, GrowableEltArray elts) { 305 con.XRenderCompositeText(compRule, src.picture, dst.picture, 306 maskFormat, sx, sy, 0, 0, glyphSet, elts); 307 } 308 309 public XRColor getMaskColor() { 310 return !isTexturePaintActive() ? XRColor.FULL_ALPHA : getAlphaColor(); 311 } 312 313 public int getExtraAlphaMask() { 314 return alphaMask; 315 } 316 317 public boolean isTexturePaintActive() { 318 return src == texture; 319 } 320 321 public XRColor getAlphaColor() { 322 return alphaColor; 323 } 324 325 public XRBackend getBackend() { 326 return con; 327 } 328 329 public float getExtraAlpha() { 330 return validatedExtraAlpha; 331 } 332 333 public byte getCompRule() { 334 return compRule; 335 } 336 337 public XRTextRenderer getTextRenderer() { 338 return textRenderer; 339 } 340 341 public MaskTileManager getMaskBuffer() { 342 return maskBuffer; 343 } 344 345 public XRMaskImage getMaskImage() { 346 return maskImage; 347 } 348 }