Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/classes/sun/java2d/CompositeCRenderer.java
41152 views
1
/*
2
* Copyright (c) 2011, 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;
27
28
import java.awt.*;
29
import java.awt.font.*;
30
import java.awt.geom.*;
31
import java.awt.image.*;
32
33
import sun.awt.image.*;
34
import sun.java2d.loops.*;
35
import sun.java2d.pipe.*;
36
37
public class CompositeCRenderer extends CRenderer implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, DrawImagePipe, TextPipe {
38
static final int fPadding = 4;
39
static final int fPaddingHalf = fPadding / 2;
40
41
private static AffineTransform sIdentityMatrix = new AffineTransform();
42
43
AffineTransform ShapeTM = new AffineTransform();
44
Rectangle2D ShapeBounds = new Rectangle2D.Float();
45
46
Line2D line = new Line2D.Float();
47
Rectangle2D rectangle = new Rectangle2D.Float();
48
RoundRectangle2D roundrectangle = new RoundRectangle2D.Float();
49
Ellipse2D ellipse = new Ellipse2D.Float();
50
Arc2D arc = new Arc2D.Float();
51
52
public synchronized void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) {
53
// create shape corresponding to this primitive
54
line.setLine(x1, y1, x2, y2);
55
56
draw(sg2d, line);
57
}
58
59
public synchronized void drawRect(SunGraphics2D sg2d, int x, int y, int width, int height) {
60
// create shape corresponding to this primitive
61
rectangle.setRect(x, y, width, height);
62
63
draw(sg2d, rectangle);
64
}
65
66
public synchronized void drawRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) {
67
// create shape corresponding to this primitive
68
roundrectangle.setRoundRect(x, y, width, height, arcWidth, arcHeight);
69
70
draw(sg2d, roundrectangle);
71
}
72
73
public synchronized void drawOval(SunGraphics2D sg2d, int x, int y, int width, int height) {
74
// create shape corresponding to this primitive
75
ellipse.setFrame(x, y, width, height);
76
77
draw(sg2d, ellipse);
78
}
79
80
public synchronized void drawArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) {
81
// create shape corresponding to this primitive
82
arc.setArc(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN);
83
84
draw(sg2d, arc);
85
}
86
87
public synchronized void drawPolyline(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) {
88
doPolygon(sg2d, xpoints, ypoints, npoints, false, false);
89
}
90
91
public synchronized void drawPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) {
92
doPolygon(sg2d, xpoints, ypoints, npoints, true, false);
93
}
94
95
public synchronized void fillRect(SunGraphics2D sg2d, int x, int y, int width, int height) {
96
// create shape corresponding to this primitive
97
rectangle.setRect(x, y, width, height);
98
99
fill(sg2d, rectangle);
100
}
101
102
public synchronized void fillRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) {
103
// create shape corresponding to this primitive
104
roundrectangle.setRoundRect(x, y, width, height, arcWidth, arcHeight);
105
106
fill(sg2d, roundrectangle);
107
}
108
109
public synchronized void fillOval(SunGraphics2D sg2d, int x, int y, int width, int height) {
110
// create shape corresponding to this primitive
111
ellipse.setFrame(x, y, width, height);
112
113
fill(sg2d, ellipse);
114
}
115
116
public synchronized void fillArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) {
117
// create shape corresponding to this primitive
118
arc.setArc(x, y, width, height, startAngle, arcAngle, Arc2D.PIE);
119
120
fill(sg2d, arc);
121
}
122
123
public synchronized void fillPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) {
124
doPolygon(sg2d, xpoints, ypoints, npoints, true, true);
125
}
126
127
public synchronized void doPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints, boolean ispolygon, boolean isfill) {
128
GeneralPath gp = new GeneralPath(Path2D.WIND_NON_ZERO, npoints);
129
gp.moveTo(xpoints[0], ypoints[0]);
130
for (int i = 1; i < npoints; i++) {
131
gp.lineTo(xpoints[i], ypoints[i]);
132
}
133
if (ispolygon) {
134
// according to the specs (only applies to polygons, not polylines)
135
if ((xpoints[0] != xpoints[npoints - 1]) || (ypoints[0] != ypoints[npoints - 1])) {
136
gp.lineTo(xpoints[0], ypoints[0]);
137
}
138
}
139
140
doShape(sg2d, (OSXSurfaceData) sg2d.getSurfaceData(), (Shape) gp, isfill);
141
}
142
143
public synchronized void draw(SunGraphics2D sg2d, Shape shape) {
144
doShape(sg2d, (OSXSurfaceData) sg2d.getSurfaceData(), shape, false);
145
}
146
147
public synchronized void fill(SunGraphics2D sg2d, Shape shape) {
148
doShape(sg2d, (OSXSurfaceData) sg2d.getSurfaceData(), shape, true);
149
}
150
151
void doShape(SunGraphics2D sg2d, OSXSurfaceData surfaceData, Shape shape, boolean isfill) {
152
Rectangle2D shapeBounds = shape.getBounds2D();
153
154
// We don't want to draw with negative width and height (CRender doesn't do it and Windows doesn't do it either)
155
// Drawing with negative w and h, can cause CG problems down the line <rdar://3960579> (vm)
156
if ((shapeBounds.getWidth() < 0) || (shapeBounds.getHeight() < 0)) { return; }
157
158
// get final destination compositing bounds (after all transformations if needed)
159
Rectangle2D compositingBounds = padBounds(sg2d, shape);
160
161
// constrain the bounds to be within surface bounds
162
clipBounds(sg2d, compositingBounds);
163
164
// if the compositing region is empty we skip all remaining compositing work:
165
if (compositingBounds.isEmpty() == false) {
166
BufferedImage srcPixels;
167
// create a matching surface into which we'll render the primitive to be composited
168
// with the desired dimension
169
srcPixels = surfaceData.getCompositingSrcImage((int) (compositingBounds.getWidth()),
170
(int) (compositingBounds.getHeight()));
171
172
Graphics2D g = srcPixels.createGraphics();
173
174
// sync up graphics state
175
ShapeTM.setToTranslation(-compositingBounds.getX(), -compositingBounds.getY());
176
ShapeTM.concatenate(sg2d.transform);
177
g.setTransform(ShapeTM);
178
g.setRenderingHints(sg2d.getRenderingHints());
179
g.setPaint(sg2d.getPaint());
180
g.setStroke(sg2d.getStroke());
181
182
// render the primitive to be composited
183
if (isfill) {
184
g.fill(shape);
185
} else {
186
g.draw(shape);
187
}
188
189
g.dispose();
190
191
composite(sg2d, surfaceData, srcPixels, compositingBounds);
192
}
193
}
194
195
public synchronized void drawString(SunGraphics2D sg2d, String str, double x, double y) {
196
drawGlyphVector(sg2d, sg2d.getFont().createGlyphVector(sg2d.getFontRenderContext(), str), x, y);
197
}
198
199
public synchronized void drawChars(SunGraphics2D sg2d, char[] data, int offset, int length, int x, int y) {
200
drawString(sg2d, new String(data, offset, length), x, y);
201
}
202
203
public synchronized void drawGlyphVector(SunGraphics2D sg2d, GlyphVector glyphVector, double x, double y) {
204
drawGlyphVector(sg2d, glyphVector, (float) x, (float) y);
205
}
206
207
public synchronized void drawGlyphVector(SunGraphics2D sg2d, GlyphVector glyphVector, float x, float y) {
208
OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData();
209
210
Shape shape = glyphVector.getOutline(x, y);
211
212
// get final destination compositing bounds (after all transformations if needed)
213
Rectangle2D compositingBounds = padBounds(sg2d, shape);
214
215
// constrain the bounds to be within surface bounds
216
clipBounds(sg2d, compositingBounds);
217
218
// if the compositing region is empty we skip all remaining compositing work:
219
if (compositingBounds.isEmpty() == false) {
220
BufferedImage srcPixels;
221
{
222
// create matching image into which we'll render the primitive to be composited
223
srcPixels = surfaceData.getCompositingSrcImage((int) compositingBounds.getWidth(), (int) compositingBounds.getHeight());
224
225
Graphics2D g = srcPixels.createGraphics();
226
227
// sync up graphics state
228
ShapeTM.setToTranslation(-compositingBounds.getX(), -compositingBounds.getY());
229
ShapeTM.concatenate(sg2d.transform);
230
g.setTransform(ShapeTM);
231
g.setPaint(sg2d.getPaint());
232
g.setStroke(sg2d.getStroke());
233
g.setFont(sg2d.getFont());
234
g.setRenderingHints(sg2d.getRenderingHints());
235
236
// render the primitive to be composited
237
g.drawGlyphVector(glyphVector, x, y);
238
g.dispose();
239
}
240
241
composite(sg2d, surfaceData, srcPixels, compositingBounds);
242
}
243
}
244
245
protected boolean blitImage(SunGraphics2D sg2d, Image img, boolean fliph, boolean flipv, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, Color bgColor) {
246
OSXSurfaceData surfaceData = (OSXSurfaceData) sg2d.getSurfaceData();
247
248
// get final destination compositing bounds (after all transformations if needed)
249
dx = (flipv == false) ? dx : dx - dw;
250
dy = (fliph == false) ? dy : dy - dh;
251
ShapeBounds.setFrame(dx, dy, dw, dh);
252
Rectangle2D compositingBounds = ShapeBounds;
253
boolean complexTransform = (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE);
254
if (complexTransform == false) {
255
double newX = Math.floor(compositingBounds.getX() + sg2d.transX);
256
double newY = Math.floor(compositingBounds.getY() + sg2d.transY);
257
double newW = Math.ceil(compositingBounds.getWidth()) + (newX < compositingBounds.getX() ? 1 : 0);
258
double newH = Math.ceil(compositingBounds.getHeight()) + (newY < compositingBounds.getY() ? 1 : 0);
259
compositingBounds.setRect(newX, newY, newW, newH);
260
} else {
261
Shape transformedShape = sg2d.transform.createTransformedShape(compositingBounds);
262
compositingBounds = transformedShape.getBounds2D();
263
double newX = Math.floor(compositingBounds.getX());
264
double newY = Math.floor(compositingBounds.getY());
265
double newW = Math.ceil(compositingBounds.getWidth()) + (newX < compositingBounds.getX() ? 1 : 0);
266
double newH = Math.ceil(compositingBounds.getHeight()) + (newY < compositingBounds.getY() ? 1 : 0);
267
compositingBounds.setRect(newX, newY, newW, newH);
268
}
269
270
// constrain the bounds to be within surface bounds
271
clipBounds(sg2d, compositingBounds);
272
273
// if the compositing region is empty we skip all remaining compositing work:
274
if (compositingBounds.isEmpty() == false) {
275
BufferedImage srcPixels;
276
{
277
// create matching image into which we'll render the primitive to be composited
278
srcPixels = surfaceData.getCompositingSrcImage((int) compositingBounds.getWidth(), (int) compositingBounds.getHeight());
279
280
Graphics2D g = srcPixels.createGraphics();
281
282
// sync up graphics state
283
ShapeTM.setToTranslation(-compositingBounds.getX(), -compositingBounds.getY());
284
ShapeTM.concatenate(sg2d.transform);
285
g.setTransform(ShapeTM);
286
g.setRenderingHints(sg2d.getRenderingHints());
287
g.setComposite(AlphaComposite.Src);
288
289
int sx2 = (flipv == false) ? sx + sw : sx - sw;
290
int sy2 = (fliph == false) ? sy + sh : sy - sh;
291
g.drawImage(img, dx, dy, dx + dw, dy + dh, sx, sy, sx2, sy2, null);
292
293
g.dispose();
294
}
295
296
composite(sg2d, surfaceData, srcPixels, compositingBounds);
297
}
298
299
return true;
300
}
301
302
Rectangle2D padBounds(SunGraphics2D sg2d, Shape shape) {
303
shape = sg2d.transformShape(shape);
304
305
int paddingHalf = fPaddingHalf;
306
int padding = fPadding;
307
if (sg2d.stroke != null) {
308
if (sg2d.stroke instanceof BasicStroke) {
309
int width = (int) (((BasicStroke) sg2d.stroke).getLineWidth() + 0.5f);
310
int widthHalf = width / 2 + 1;
311
paddingHalf += widthHalf;
312
padding += 2 * widthHalf;
313
} else {
314
shape = sg2d.stroke.createStrokedShape(shape);
315
}
316
}
317
Rectangle2D bounds = shape.getBounds2D();
318
bounds.setRect(bounds.getX() - paddingHalf, bounds.getY() - paddingHalf, bounds.getWidth() + padding, bounds.getHeight() + padding);
319
320
double newX = Math.floor(bounds.getX());
321
double newY = Math.floor(bounds.getY());
322
double newW = Math.ceil(bounds.getWidth()) + (newX < bounds.getX() ? 1 : 0);
323
double newH = Math.ceil(bounds.getHeight()) + (newY < bounds.getY() ? 1 : 0);
324
bounds.setRect(newX, newY, newW, newH);
325
326
return bounds;
327
}
328
329
void clipBounds(SunGraphics2D sg2d, Rectangle2D bounds) {
330
/*
331
* System.err.println("clipBounds"); System.err.println(" transform="+sg2d.transform);
332
* System.err.println(" getTransform()="+sg2d.getTransform());
333
* System.err.println(" complexTransform="+(sg2d.transformState > SunGraphics2D.TRANSFORM_TRANSLATESCALE));
334
* System.err.println(" transX="+sg2d.transX+" transY="+sg2d.transX);
335
* System.err.println(" sg2d.constrainClip="+sg2d.constrainClip); if (sg2d.constrainClip != null) {
336
* System.err
337
* .println(" constrainClip: x="+sg2d.constrainClip.getLoX()+" y="+sg2d.constrainClip.getLoY()+" w="
338
* +sg2d.constrainClip.getWidth()+" h="+sg2d.constrainClip.getHeight());}
339
* System.err.println(" constrainX="+sg2d.constrainX+" constrainY="+sg2d.constrainY);
340
* System.err.println(" usrClip="+sg2d.usrClip);
341
* System.err.println(" devClip: x="+sg2d.devClip.getLoX()+" y="
342
* +sg2d.devClip.getLoY()+" w="+sg2d.devClip.getWidth()+" h="+sg2d.devClip.getHeight());
343
*/
344
Region intersection = sg2d.clipRegion.getIntersectionXYWH((int) bounds.getX(), (int) bounds.getY(), (int) bounds.getWidth(), (int) bounds.getHeight());
345
bounds.setRect(intersection.getLoX(), intersection.getLoY(), intersection.getWidth(), intersection.getHeight());
346
}
347
348
BufferedImage getSurfacePixels(SunGraphics2D sg2d, OSXSurfaceData surfaceData, int x, int y, int w, int h) {
349
// create an image to copy the surface pixels into
350
BufferedImage dstInPixels = surfaceData.getCompositingDstInImage(w, h);
351
352
// get the pixels from the dst surface
353
return surfaceData.copyArea(sg2d, x, y, w, h, dstInPixels);
354
}
355
356
void composite(SunGraphics2D sg2d, OSXSurfaceData surfaceData, BufferedImage srcPixels, Rectangle2D compositingBounds) {
357
// Thread.dumpStack();
358
// System.err.println("composite");
359
// System.err.println(" compositingBounds="+compositingBounds);
360
int x = (int) compositingBounds.getX();
361
int y = (int) compositingBounds.getY();
362
int w = (int) compositingBounds.getWidth();
363
int h = (int) compositingBounds.getHeight();
364
365
boolean succeded = false;
366
367
Composite composite = sg2d.getComposite();
368
if (composite instanceof XORComposite) {
369
// 1st native XOR try
370
// we try to perform XOR using surface pixels directly
371
try {
372
succeded = surfaceData.xorSurfacePixels(sg2d, srcPixels, x, y, w, h, ((XORComposite) composite).getXorColor().getRGB());
373
} catch (Exception e) {
374
succeded = false;
375
}
376
}
377
378
if (succeded == false) {
379
// create image with the original pixels of surface
380
BufferedImage dstInPixels = getSurfacePixels(sg2d, surfaceData, x, y, w, h);
381
BufferedImage dstOutPixels = null;
382
383
if (composite instanceof XORComposite) {
384
// 2nd native XOR try
385
// we try to perform XOR on image's pixels (which were copied from surface first)
386
try {
387
OSXSurfaceData osxsd = (OSXSurfaceData) (BufImgSurfaceData.createData(dstInPixels));
388
succeded = osxsd.xorSurfacePixels(sg2d, srcPixels, 0, 0, w, h, ((XORComposite) composite).getXorColor().getRGB());
389
dstOutPixels = dstInPixels;
390
} catch (Exception e) {
391
succeded = false;
392
}
393
}
394
395
// either 2nd native XOR failed OR we have a case of custom compositing
396
if (succeded == false) {
397
// create an image into which we'll composite result: we MUST use a different destination (compositing
398
// is NOT "in place" operation)
399
dstOutPixels = surfaceData.getCompositingDstOutImage(w, h);
400
401
// prepare rasters for compositing
402
WritableRaster srcRaster = srcPixels.getRaster();
403
WritableRaster dstInRaster = dstInPixels.getRaster();
404
WritableRaster dstOutRaster = dstOutPixels.getRaster();
405
406
CompositeContext compositeContext = composite.createContext(srcPixels.getColorModel(), dstOutPixels.getColorModel(), sg2d.getRenderingHints());
407
compositeContext.compose(srcRaster, dstInRaster, dstOutRaster);
408
compositeContext.dispose();
409
410
// gznote: radar bug number
411
// "cut out" the shape we're interested in
412
// applyMask(BufImgSurfaceData.createData(dstOutPixels), BufImgSurfaceData.createData(srcPixels), w, h);
413
}
414
415
// blit the results back to the dst surface
416
Composite savedComposite = sg2d.getComposite();
417
AffineTransform savedTM = sg2d.getTransform();
418
int savedCX = sg2d.constrainX;
419
int savedCY = sg2d.constrainY;
420
{
421
sg2d.setComposite(AlphaComposite.SrcOver);
422
// all the compositing is done in the coordinate space of the component. the x and the y are the
423
// position of that component in the surface
424
// so we need to set the sg2d.transform to identity and we must set the contrainX/Y to 0 for the
425
// setTransform() to not be constrained
426
sg2d.constrainX = 0;
427
sg2d.constrainY = 0;
428
sg2d.setTransform(sIdentityMatrix);
429
sg2d.drawImage(dstOutPixels, x, y, x + w, y + h, 0, 0, w, h, null);
430
}
431
sg2d.constrainX = savedCX;
432
sg2d.constrainY = savedCY;
433
sg2d.setTransform(savedTM);
434
sg2d.setComposite(savedComposite);
435
}
436
}
437
}
438
439