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