Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.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
import java.nio.*;
33
34
import sun.awt.*;
35
import sun.awt.image.*;
36
import sun.java2d.loops.*;
37
import sun.java2d.pipe.*;
38
import sun.lwawt.macosx.*;
39
40
import java.lang.annotation.Native;
41
42
/*
43
* This is the SurfaceData for a CGContextRef.
44
*/
45
public abstract class OSXSurfaceData extends BufImgSurfaceData {
46
static final float UPPER_BND = Float.MAX_VALUE / 2.0f;
47
static final float LOWER_BND = -UPPER_BND;
48
49
protected static CRenderer sQuartzPipe = null;
50
protected static CTextPipe sCocoaTextPipe = null;
51
protected static CompositeCRenderer sQuartzCompositePipe = null;
52
53
private GraphicsConfiguration fConfig;
54
private Rectangle fBounds; // bounds in user coordinates
55
56
static {
57
sQuartzPipe = new CRenderer(); // Creates the singleton quartz pipe.
58
}
59
60
// NOTE: Any subclasses must eventually call QuartzSurfaceData_InitOps in OSXSurfaceData.h
61
// This sets up the native side for the SurfaceData, and is required.
62
public OSXSurfaceData(SurfaceType sType, ColorModel cm) {
63
this(sType, cm, null, new Rectangle());
64
}
65
66
public OSXSurfaceData(SurfaceType sType, ColorModel cm, GraphicsConfiguration config, Rectangle bounds) {
67
super(sType, cm);
68
69
this.fConfig = config;
70
71
this.fBounds = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.y + bounds.height);
72
73
this.fGraphicsStates = getBufferOfSize(kSizeOfParameters);
74
this.fGraphicsStatesInt = this.fGraphicsStates.asIntBuffer();
75
this.fGraphicsStatesFloat = this.fGraphicsStates.asFloatBuffer();
76
this.fGraphicsStatesLong = this.fGraphicsStates.asLongBuffer();
77
this.fGraphicsStatesObject = new Object[8]; // clip coordinates +
78
// clip types +
79
// texture paint image +
80
// stroke dash array +
81
// font + font paint +
82
// linear/radial gradient color +
83
// linear/radial gradient fractions
84
85
// NOTE: All access to the DrawingQueue comes through this OSXSurfaceData instance. Therefore
86
// every instance method of OSXSurfaceData that accesses the fDrawingQueue is synchronized.
87
88
// Thread.dumpStack();
89
}
90
91
public void validatePipe(SunGraphics2D sg2d) {
92
93
if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
94
if (sCocoaTextPipe == null) {
95
sCocoaTextPipe = new CTextPipe();
96
}
97
98
sg2d.imagepipe = sQuartzPipe;
99
sg2d.drawpipe = sQuartzPipe;
100
sg2d.fillpipe = sQuartzPipe;
101
sg2d.shapepipe = sQuartzPipe;
102
sg2d.textpipe = sCocoaTextPipe;
103
} else {
104
setPipesToQuartzComposite(sg2d);
105
}
106
}
107
108
protected void setPipesToQuartzComposite(SunGraphics2D sg2d) {
109
if (sQuartzCompositePipe == null) {
110
sQuartzCompositePipe = new CompositeCRenderer();
111
}
112
113
if (sCocoaTextPipe == null) {
114
sCocoaTextPipe = new CTextPipe();
115
}
116
117
sg2d.imagepipe = sQuartzCompositePipe;
118
sg2d.drawpipe = sQuartzCompositePipe;
119
sg2d.fillpipe = sQuartzCompositePipe;
120
sg2d.shapepipe = sQuartzCompositePipe;
121
sg2d.textpipe = sCocoaTextPipe;
122
}
123
124
public Rectangle getBounds() {
125
// gznote: always return a copy, not the rect itself and translate into device space
126
return new Rectangle(fBounds.x, fBounds.y, fBounds.width, fBounds.height - fBounds.y);
127
}
128
129
public GraphicsConfiguration getDeviceConfiguration() {
130
return fConfig;
131
}
132
133
protected void setBounds(int x, int y, int w, int h) {
134
fBounds.setBounds(x, y, w, y + h);
135
}
136
137
// START compositing support API
138
public abstract BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage image);
139
140
public abstract boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR);
141
142
GraphicsConfiguration sDefaultGraphicsConfiguration = null;
143
144
protected BufferedImage getCompositingImage(int w, int h) {
145
if (sDefaultGraphicsConfiguration == null) {
146
sDefaultGraphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
147
}
148
149
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
150
// clear the image.
151
clearRect(img, w, h);
152
return img;
153
}
154
155
protected BufferedImage getCompositingImageSame(BufferedImage img, int w, int h) {
156
if ((img == null) || (img.getWidth() != w) || (img.getHeight() != h)) {
157
img = getCompositingImage(w, h);
158
}
159
return img;
160
}
161
162
BufferedImage sSrcComposite = null;
163
164
public BufferedImage getCompositingSrcImage(int w, int h) {
165
// <rdar://problem/3720263>. Changed from getCompositingImageBiggerOrSame() to
166
// getCompositingImageSame(). (vm)
167
BufferedImage bim = getCompositingImageSame(sSrcComposite, w, h);
168
sSrcComposite = bim;
169
return bim;
170
}
171
172
BufferedImage sDstInComposite = null;
173
174
public BufferedImage getCompositingDstInImage(int w, int h) {
175
BufferedImage bim = getCompositingImageSame(sDstInComposite, w, h);
176
sDstInComposite = bim;
177
return bim;
178
}
179
180
BufferedImage sDstOutComposite = null;
181
182
public BufferedImage getCompositingDstOutImage(int w, int h) {
183
BufferedImage bim = getCompositingImageSame(sDstOutComposite, w, h);
184
sDstOutComposite = bim;
185
return bim;
186
}
187
188
public void clearRect(BufferedImage bim, int w, int h) {
189
Graphics2D g = bim.createGraphics();
190
g.setComposite(AlphaComposite.Clear);
191
g.fillRect(0, 0, w, h);
192
g.dispose();
193
}
194
195
// END compositing support API
196
197
public void invalidate() {
198
// always valid
199
}
200
201
// graphics primitives drawing implementation:
202
203
// certain primitives don't care about all the states (ex. drawing an image needs not involve setting current paint)
204
@Native static final int kPrimitive = 0;
205
@Native static final int kImage = 1;
206
@Native static final int kText = 2;
207
@Native static final int kCopyArea = 3;
208
@Native static final int kExternal = 4;
209
210
@Native static final int kLine = 5; // belongs to kPrimitive
211
@Native static final int kRect = 6; // belongs to kPrimitive
212
@Native static final int kRoundRect = 7; // belongs to kPrimitive
213
@Native static final int kOval = 8; // belongs to kPrimitive
214
@Native static final int kArc = 9; // belongs to kPrimitive
215
@Native static final int kPolygon = 10; // belongs to kPrimitive
216
@Native static final int kShape = 11; // belongs to kPrimitive
217
// static final int kImage = 12; // belongs to kImage
218
@Native static final int kString = 13; // belongs to kText
219
@Native static final int kGlyphs = 14; // belongs to kText
220
@Native static final int kUnicodes = 15; // belongs to kText
221
// static final int kCopyArea = 16; // belongs to kCopyArea
222
// static final int kExternal = 17; // belongs to kExternal
223
224
@Native static final int kCommonParameterCount = 1 + 1 + 4 + 4; // type + change flags + color info (type(1) align(1) and
225
// value(2)) + parameters ((x1, y1, x2, y2) OR (x, y, w, h))
226
@Native static final int kLineParametersCount = kCommonParameterCount; // kCommonParameterCount
227
@Native static final int kRectParametersCount = kCommonParameterCount + 1; // kCommonParameterCount + isfill
228
@Native static final int kRoundRectParametersCount = kCommonParameterCount + 2 + 1; // kCommonParameterCount + arcW + arcH +
229
// isfill
230
@Native static final int kOvalParametersCount = kCommonParameterCount + 1; // kCommonParameterCount + isfill
231
@Native static final int kArcParametersCount = kCommonParameterCount + 2 + 1 + 1;// kCommonParameterCount + startAngle +
232
// arcAngle + isfill + type
233
@Native static final int kPolygonParametersCount = 0; // not supported
234
@Native static final int kShapeParametersCount = 0; // not supported
235
@Native static final int kImageParametersCount = kCommonParameterCount + 2 + 2 + 4 + 4; // flip horz vert + w&h + src + dst
236
@Native static final int kStringParametersCount = 0; // not supported
237
@Native static final int kGlyphsParametersCount = 0; // not supported
238
@Native static final int kUnicodesParametersCount = 0; // not supported
239
@Native static final int kPixelParametersCount = 0; // not supported
240
@Native static final int kExternalParametersCount = 0; // not supported
241
242
// for intParameters
243
// states info
244
@Native static final int kChangeFlagIndex = 0; // kBoundsChangedBit | .. | kFontChangedBit
245
// bounds info
246
@Native static final int kBoundsXIndex = 1;
247
@Native static final int kBoundsYIndex = 2;
248
@Native static final int kBoundsWidthIndex = 3;
249
@Native static final int kBoundsHeightIndex = 4;
250
// clip info
251
@Native static final int kClipStateIndex = 5;
252
@Native static final int kClipNumTypesIndex = 6;
253
@Native static final int kClipNumCoordsIndex = 7;
254
@Native static final int kClipWindingRuleIndex = 8;
255
@Native static final int kClipXIndex = 9;
256
@Native static final int kClipYIndex = 10;
257
@Native static final int kClipWidthIndex = 11;
258
@Native static final int kClipHeightIndex = 12;
259
// ctm info
260
@Native static final int kCTMaIndex = 13;
261
@Native static final int kCTMbIndex = 14;
262
@Native static final int kCTMcIndex = 15;
263
@Native static final int kCTMdIndex = 16;
264
@Native static final int kCTMtxIndex = 17;
265
@Native static final int kCTMtyIndex = 18;
266
// color info
267
@Native static final int kColorStateIndex = 19; // kColorSimple or kColorGradient or kColorTexture
268
@Native static final int kColorRGBValueIndex = 20; // if kColorSimple
269
@Native static final int kColorIndexValueIndex = 21; // if kColorSystem
270
@Native static final int kColorPointerIndex = 22; //
271
@Native static final int kColorPointerIndex2 = 23; //
272
@Native static final int kColorRGBValue1Index = 24; // if kColorGradient
273
@Native static final int kColorWidthIndex = 25; // if kColorTexture
274
@Native static final int kColorRGBValue2Index = 26; // if kColorGradient
275
@Native static final int kColorHeightIndex = 27; // if kColorTexture
276
@Native static final int kColorIsCyclicIndex = 28; // if kColorGradient (kColorNonCyclic or kColorCyclic)
277
@Native static final int kColorx1Index = 29;
278
@Native static final int kColortxIndex = 30;
279
@Native static final int kColory1Index = 31;
280
@Native static final int kColortyIndex = 32;
281
@Native static final int kColorx2Index = 33;
282
@Native static final int kColorsxIndex = 34;
283
@Native static final int kColory2Index = 35;
284
@Native static final int kColorsyIndex = 36;
285
// composite info
286
@Native static final int kCompositeRuleIndex = 37; // kCGCompositeClear or ... or kCGCompositeXor
287
@Native static final int kCompositeValueIndex = 38;
288
// stroke info
289
@Native static final int kStrokeJoinIndex = 39; // see BasicStroke.java
290
@Native static final int kStrokeCapIndex = 40; // see BasicStroke.java
291
@Native static final int kStrokeWidthIndex = 41;
292
@Native static final int kStrokeDashPhaseIndex = 42;
293
@Native static final int kStrokeLimitIndex = 43;
294
// hints info
295
@Native static final int kHintsAntialiasIndex = 44;
296
@Native static final int kHintsTextAntialiasIndex = 45;
297
@Native static final int kHintsFractionalMetricsIndex = 46;
298
@Native static final int kHintsRenderingIndex = 47;
299
@Native static final int kHintsInterpolationIndex = 48;
300
//gradient info
301
@Native static final int kRadiusIndex = 49;
302
303
@Native static final int kSizeOfParameters = kRadiusIndex + 1;
304
305
// for objectParameters
306
@Native static final int kClipCoordinatesIndex = 0;
307
@Native static final int kClipTypesIndex = 1;
308
@Native static final int kTextureImageIndex = 2;
309
@Native static final int kStrokeDashArrayIndex = 3;
310
@Native static final int kFontIndex = 4;
311
@Native static final int kFontPaintIndex = 5;
312
@Native static final int kColorArrayIndex = 6;
313
@Native static final int kFractionsArrayIndex = 7;
314
315
// possible state changes
316
@Native static final int kBoundsChangedBit = 1 << 0;
317
@Native static final int kBoundsNotChangedBit = ~kBoundsChangedBit;
318
@Native static final int kClipChangedBit = 1 << 1;
319
@Native static final int kClipNotChangedBit = ~kClipChangedBit;
320
@Native static final int kCTMChangedBit = 1 << 2;
321
@Native static final int kCTMNotChangedBit = ~kCTMChangedBit;
322
@Native static final int kColorChangedBit = 1 << 3;
323
@Native static final int kColorNotChangedBit = ~kColorChangedBit;
324
@Native static final int kCompositeChangedBit = 1 << 4;
325
@Native static final int kCompositeNotChangedBit = ~kCompositeChangedBit;
326
@Native static final int kStrokeChangedBit = 1 << 5;
327
@Native static final int kStrokeNotChangedBit = ~kStrokeChangedBit;
328
@Native static final int kHintsChangedBit = 1 << 6;
329
@Native static final int kHintsNotChangedBit = ~kHintsChangedBit;
330
@Native static final int kFontChangedBit = 1 << 7;
331
@Native static final int kFontNotChangedBit = ~kFontChangedBit;
332
@Native static final int kEverythingChangedFlag = 0xffffffff;
333
334
// possible color states
335
@Native static final int kColorSimple = 0;
336
@Native static final int kColorSystem = 1;
337
@Native static final int kColorGradient = 2;
338
@Native static final int kColorTexture = 3;
339
@Native static final int kColorLinearGradient = 4;
340
@Native static final int kColorRadialGradient = 5;
341
342
// possible gradient color states
343
@Native static final int kColorNonCyclic = 0;
344
@Native static final int kColorCyclic = 1;
345
346
// possible clip states
347
@Native static final int kClipRect = 0;
348
@Native static final int kClipShape = 1;
349
350
static int getRendererTypeForPrimitive(int primitiveType) {
351
switch (primitiveType) {
352
case kImage:
353
return kImage;
354
case kCopyArea:
355
return kCopyArea;
356
case kExternal:
357
return kExternal;
358
case kString:
359
case kGlyphs:
360
case kUnicodes:
361
return kText;
362
default:
363
return kPrimitive;
364
}
365
}
366
367
int fChangeFlag;
368
protected ByteBuffer fGraphicsStates = null;
369
IntBuffer fGraphicsStatesInt = null;
370
FloatBuffer fGraphicsStatesFloat = null;
371
LongBuffer fGraphicsStatesLong = null;
372
protected Object[] fGraphicsStatesObject = null;
373
374
Rectangle userBounds = new Rectangle();
375
float lastUserX = 0;
376
float lastUserY = 0;
377
float lastUserW = 0;
378
float lastUserH = 0;
379
380
void setUserBounds(SunGraphics2D sg2d, int x, int y, int width, int height) {
381
if ((lastUserX != x) || (lastUserY != y) || (lastUserW != width) || (lastUserH != height)) {
382
lastUserX = x;
383
lastUserY = y;
384
lastUserW = width;
385
lastUserH = height;
386
387
this.fGraphicsStatesInt.put(kBoundsXIndex, x);
388
this.fGraphicsStatesInt.put(kBoundsYIndex, y);
389
this.fGraphicsStatesInt.put(kBoundsWidthIndex, width);
390
this.fGraphicsStatesInt.put(kBoundsHeightIndex, height);
391
392
userBounds.setBounds(x, y, width, height);
393
394
this.fChangeFlag = (this.fChangeFlag | kBoundsChangedBit);
395
} else {
396
this.fChangeFlag = (this.fChangeFlag & kBoundsNotChangedBit);
397
}
398
}
399
400
static ByteBuffer getBufferOfSize(int size) {
401
ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4);
402
buffer.order(ByteOrder.nativeOrder());
403
return buffer;
404
}
405
406
FloatBuffer clipCoordinatesArray = null;
407
IntBuffer clipTypesArray = null;
408
Shape lastClipShape = null;
409
float lastClipX = 0;
410
float lastClipY = 0;
411
float lastClipW = 0;
412
float lastClipH = 0;
413
414
void setupClip(SunGraphics2D sg2d) {
415
switch (sg2d.clipState) {
416
case SunGraphics2D.CLIP_DEVICE:
417
case SunGraphics2D.CLIP_RECTANGULAR: {
418
Region clip = sg2d.getCompClip();
419
float x = clip.getLoX();
420
float y = clip.getLoY();
421
float w = clip.getWidth();
422
float h = clip.getHeight();
423
if ((this.fGraphicsStatesInt.get(kClipStateIndex) != kClipRect) ||
424
(x != lastClipX) ||
425
(y != lastClipY) ||
426
(w != lastClipW) ||
427
(h != lastClipH)) {
428
this.fGraphicsStatesFloat.put(kClipXIndex, x);
429
this.fGraphicsStatesFloat.put(kClipYIndex, y);
430
this.fGraphicsStatesFloat.put(kClipWidthIndex, w);
431
this.fGraphicsStatesFloat.put(kClipHeightIndex, h);
432
433
lastClipX = x;
434
lastClipY = y;
435
lastClipW = w;
436
lastClipH = h;
437
438
this.fChangeFlag = (this.fChangeFlag | kClipChangedBit);
439
} else {
440
this.fChangeFlag = (this.fChangeFlag & kClipNotChangedBit);
441
}
442
this.fGraphicsStatesInt.put(kClipStateIndex, kClipRect);
443
break;
444
}
445
case SunGraphics2D.CLIP_SHAPE: {
446
// if (lastClipShape != sg2d.usrClip) shapes are mutable!, and doing "equals" traverses all
447
// the coordinates, so we might as well do all of it anyhow
448
lastClipShape = sg2d.usrClip;
449
450
GeneralPath gp = null;
451
452
if (sg2d.usrClip instanceof GeneralPath) {
453
gp = (GeneralPath) sg2d.usrClip;
454
} else {
455
gp = new GeneralPath(sg2d.usrClip);
456
}
457
458
int shapeLength = getPathLength(gp);
459
460
if ((clipCoordinatesArray == null) || (clipCoordinatesArray.capacity() < (shapeLength * 6))) {
461
clipCoordinatesArray = getBufferOfSize(shapeLength * 6).asFloatBuffer(); // segment can have a
462
// max of 6 coordinates
463
}
464
if ((clipTypesArray == null) || (clipTypesArray.capacity() < shapeLength)) {
465
clipTypesArray = getBufferOfSize(shapeLength).asIntBuffer();
466
}
467
468
int windingRule = getPathCoordinates(gp, clipCoordinatesArray, clipTypesArray);
469
470
this.fGraphicsStatesInt.put(kClipNumTypesIndex, clipTypesArray.position());
471
this.fGraphicsStatesInt.put(kClipNumCoordsIndex, clipCoordinatesArray.position());
472
this.fGraphicsStatesInt.put(kClipWindingRuleIndex, windingRule);
473
this.fGraphicsStatesObject[kClipTypesIndex] = clipTypesArray;
474
this.fGraphicsStatesObject[kClipCoordinatesIndex] = clipCoordinatesArray;
475
476
this.fChangeFlag = (this.fChangeFlag | kClipChangedBit);
477
this.fGraphicsStatesInt.put(kClipStateIndex, kClipShape);
478
break;
479
}
480
}
481
482
}
483
484
final double[] lastCTM = new double[6];
485
float lastCTMa = 0;
486
float lastCTMb = 0;
487
float lastCTMc = 0;
488
float lastCTMd = 0;
489
float lastCTMtx = 0;
490
float lastCTMty = 0;
491
492
void setupTransform(SunGraphics2D sg2d) {
493
sg2d.transform.getMatrix(lastCTM);
494
495
float a = (float) lastCTM[0];
496
float b = (float) lastCTM[1];
497
float c = (float) lastCTM[2];
498
float d = (float) lastCTM[3];
499
float tx = (float) lastCTM[4];
500
float ty = (float) lastCTM[5];
501
if (tx != lastCTMtx ||
502
ty != lastCTMty ||
503
a != lastCTMa ||
504
b != lastCTMb ||
505
c != lastCTMc ||
506
d != lastCTMd) {
507
this.fGraphicsStatesFloat.put(kCTMaIndex, a);
508
this.fGraphicsStatesFloat.put(kCTMbIndex, b);
509
this.fGraphicsStatesFloat.put(kCTMcIndex, c);
510
this.fGraphicsStatesFloat.put(kCTMdIndex, d);
511
this.fGraphicsStatesFloat.put(kCTMtxIndex, tx);
512
this.fGraphicsStatesFloat.put(kCTMtyIndex, ty);
513
514
lastCTMa = a;
515
lastCTMb = b;
516
lastCTMc = c;
517
lastCTMd = d;
518
lastCTMtx = tx;
519
lastCTMty = ty;
520
521
this.fChangeFlag = (this.fChangeFlag | kCTMChangedBit);
522
} else {
523
this.fChangeFlag = (this.fChangeFlag & kCTMNotChangedBit);
524
}
525
}
526
527
static AffineTransform sIdentityMatrix = new AffineTransform();
528
Paint lastPaint = null;
529
long lastPaintPtr = 0;
530
int lastPaintRGB = 0;
531
int lastPaintIndex = 0;
532
BufferedImage texturePaintImage = null;
533
534
void setGradientViaRasterPath(SunGraphics2D sg2d) {
535
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) {
536
PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints());
537
WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height));
538
ColorModel cm = context.getColorModel();
539
texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
540
541
this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
542
this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
543
this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
544
this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX());
545
this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY());
546
this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f);
547
this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f);
548
this.fGraphicsStatesObject[kTextureImageIndex] = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage);
549
550
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
551
} else {
552
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
553
}
554
}
555
556
void setupPaint(SunGraphics2D sg2d, int x, int y, int w, int h) {
557
if (sg2d.paint instanceof SystemColor) {
558
SystemColor color = (SystemColor) sg2d.paint;
559
int index = color.hashCode(); // depends on Color.java hashCode implementation! (returns "value" of color)
560
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorSystem) || (index != this.lastPaintIndex)) {
561
this.lastPaintIndex = index;
562
563
this.fGraphicsStatesInt.put(kColorStateIndex, kColorSystem);
564
this.fGraphicsStatesInt.put(kColorIndexValueIndex, index);
565
566
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
567
} else {
568
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
569
}
570
} else if (sg2d.paint instanceof Color) {
571
Color color = (Color) sg2d.paint;
572
int rgb = color.getRGB();
573
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorSimple) || (rgb != this.lastPaintRGB)) {
574
this.lastPaintRGB = rgb;
575
576
this.fGraphicsStatesInt.put(kColorStateIndex, kColorSimple);
577
this.fGraphicsStatesInt.put(kColorRGBValueIndex, rgb);
578
579
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
580
} else {
581
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
582
}
583
} else if (sg2d.paint instanceof GradientPaint) {
584
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorGradient) || (lastPaint != sg2d.paint)) {
585
GradientPaint color = (GradientPaint) sg2d.paint;
586
this.fGraphicsStatesInt.put(kColorStateIndex, kColorGradient);
587
this.fGraphicsStatesInt.put(kColorRGBValue1Index, color.getColor1().getRGB());
588
this.fGraphicsStatesInt.put(kColorRGBValue2Index, color.getColor2().getRGB());
589
this.fGraphicsStatesInt.put(kColorIsCyclicIndex, (color.isCyclic()) ? kColorCyclic : kColorNonCyclic);
590
Point2D p = color.getPoint1();
591
this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
592
this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
593
p = color.getPoint2();
594
this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
595
this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
596
597
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
598
} else {
599
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
600
}
601
} else if (sg2d.paint instanceof LinearGradientPaint) {
602
LinearGradientPaint color = (LinearGradientPaint) sg2d.paint;
603
if (color.getCycleMethod() == LinearGradientPaint.CycleMethod.NO_CYCLE) {
604
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorLinearGradient) || (lastPaint != sg2d.paint)) {
605
606
this.fGraphicsStatesInt.put(kColorStateIndex, kColorLinearGradient);
607
int numColor = color.getColors().length;
608
int[] colorArray = new int[numColor];
609
for (int i = 0; i < numColor; i++) {
610
colorArray[i] = color.getColors()[i].getRGB();
611
}
612
this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;
613
614
int numFractions = color.getFractions().length;
615
float[] fractionArray = new float[numFractions];
616
for (int i = 0; i < numFractions; i++) {
617
fractionArray[i] = color.getFractions()[i];
618
}
619
this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();
620
621
Point2D p = color.getStartPoint();
622
this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
623
this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
624
p = color.getEndPoint();
625
this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
626
this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
627
628
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
629
} else {
630
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
631
}
632
} else {
633
setGradientViaRasterPath(sg2d);
634
}
635
} else if (sg2d.paint instanceof RadialGradientPaint) {
636
RadialGradientPaint color = (RadialGradientPaint) sg2d.paint;
637
if (color.getCycleMethod() == RadialGradientPaint.CycleMethod.NO_CYCLE) {
638
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorRadialGradient) || (lastPaint != sg2d.paint)) {
639
640
this.fGraphicsStatesInt.put(kColorStateIndex, kColorRadialGradient);
641
int numColor = color.getColors().length;
642
int[] colorArray = new int[numColor];
643
for (int i = 0; i < numColor; i++) {
644
colorArray[i] = color.getColors()[i].getRGB();
645
}
646
this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;
647
648
int numStops = color.getFractions().length;
649
float[] stopsArray = new float[numStops];
650
for (int i = 0; i < numStops; i++) {
651
stopsArray[i] = color.getFractions()[i];
652
}
653
this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();
654
655
Point2D p = color.getFocusPoint();
656
this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
657
this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
658
p = color.getCenterPoint();
659
this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
660
this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
661
this.fGraphicsStatesFloat.put(kRadiusIndex, color.getRadius());
662
663
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
664
} else {
665
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
666
}
667
} else {
668
setGradientViaRasterPath(sg2d);
669
}
670
} else if (sg2d.paint instanceof TexturePaint) {
671
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint)) {
672
TexturePaint color = (TexturePaint) sg2d.paint;
673
this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
674
texturePaintImage = color.getImage();
675
SurfaceData textureSurfaceData = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage);
676
this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
677
this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
678
Rectangle2D anchor = color.getAnchorRect();
679
this.fGraphicsStatesFloat.put(kColortxIndex, (float) anchor.getX());
680
this.fGraphicsStatesFloat.put(kColortyIndex, (float) anchor.getY());
681
this.fGraphicsStatesFloat.put(kColorsxIndex, (float) (anchor.getWidth() / texturePaintImage.getWidth()));
682
this.fGraphicsStatesFloat.put(kColorsyIndex, (float) (anchor.getHeight() / texturePaintImage.getHeight()));
683
this.fGraphicsStatesObject[kTextureImageIndex] = textureSurfaceData;
684
685
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
686
} else {
687
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
688
}
689
} else {
690
setGradientViaRasterPath(sg2d);
691
}
692
lastPaint = sg2d.paint;
693
}
694
695
Composite lastComposite;
696
int lastCompositeAlphaRule = 0;
697
float lastCompositeAlphaValue = 0;
698
699
void setupComposite(SunGraphics2D sg2d) {
700
Composite composite = sg2d.composite;
701
702
if (lastComposite != composite) {
703
lastComposite = composite;
704
705
// For composite state COMP_ISCOPY, COMP_XOR or COMP_CUSTOM set alpha compositor to COPY:
706
int alphaRule = AlphaComposite.SRC_OVER;
707
float alphaValue = 1.0f;
708
709
// For composite state COMP_ISCOPY composite could be null. If it's not (or composite state == COMP_ALPHA)
710
// get alpha compositor's values:
711
if ((sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) && (composite != null)) {
712
AlphaComposite alphaComposite = (AlphaComposite) composite;
713
alphaRule = alphaComposite.getRule();
714
alphaValue = alphaComposite.getAlpha();
715
}
716
717
// 2-17-03 VL: [Radar 3174922]
718
// For COMP_XOR and COMP_CUSTOM compositing modes we should be setting alphaRule = AlphaComposite.SRC
719
// which should map to kCGCompositeCopy.
720
721
if ((lastCompositeAlphaRule != alphaRule) || (lastCompositeAlphaValue != alphaValue)) {
722
this.fGraphicsStatesInt.put(kCompositeRuleIndex, alphaRule);
723
this.fGraphicsStatesFloat.put(kCompositeValueIndex, alphaValue);
724
725
lastCompositeAlphaRule = alphaRule;
726
lastCompositeAlphaValue = alphaValue;
727
728
this.fChangeFlag = (this.fChangeFlag | kCompositeChangedBit);
729
} else {
730
this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);
731
}
732
} else {
733
this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);
734
}
735
}
736
737
BasicStroke lastStroke = null;
738
static BasicStroke defaultBasicStroke = new BasicStroke();
739
740
void setupStroke(SunGraphics2D sg2d) {
741
BasicStroke stroke = defaultBasicStroke;
742
743
if (sg2d.stroke instanceof BasicStroke) {
744
stroke = (BasicStroke) sg2d.stroke;
745
}
746
747
if (lastStroke != stroke) {
748
this.fGraphicsStatesObject[kStrokeDashArrayIndex] = stroke.getDashArray();
749
this.fGraphicsStatesFloat.put(kStrokeDashPhaseIndex, stroke.getDashPhase());
750
this.fGraphicsStatesInt.put(kStrokeCapIndex, stroke.getEndCap());
751
this.fGraphicsStatesInt.put(kStrokeJoinIndex, stroke.getLineJoin());
752
this.fGraphicsStatesFloat.put(kStrokeWidthIndex, stroke.getLineWidth());
753
this.fGraphicsStatesFloat.put(kStrokeLimitIndex, stroke.getMiterLimit());
754
755
this.fChangeFlag = (this.fChangeFlag | kStrokeChangedBit);
756
757
lastStroke = stroke;
758
} else {
759
this.fChangeFlag = (this.fChangeFlag & kStrokeNotChangedBit);
760
}
761
}
762
763
Font lastFont;
764
765
void setupFont(Font font, Paint paint) {
766
if (font == null) { return; }
767
768
// We have to setup the kFontPaintIndex if we have changed the color so we added the last
769
// test to see if the color has changed - needed for complex strings
770
// see Radar 3368674
771
if ((font != lastFont) || ((this.fChangeFlag & kColorChangedBit) != 0)) {
772
this.fGraphicsStatesObject[kFontIndex] = font;
773
this.fGraphicsStatesObject[kFontPaintIndex] = paint;
774
775
this.fChangeFlag = (this.fChangeFlag | kFontChangedBit);
776
777
lastFont = font;
778
} else {
779
this.fChangeFlag = (this.fChangeFlag & kFontNotChangedBit);
780
}
781
}
782
783
void setupRenderingHints(SunGraphics2D sg2d) {
784
boolean hintsChanged = false;
785
786
// Significant for draw, fill, text, and image ops:
787
int antialiasHint = sg2d.antialiasHint;
788
if (this.fGraphicsStatesInt.get(kHintsAntialiasIndex) != antialiasHint) {
789
this.fGraphicsStatesInt.put(kHintsAntialiasIndex, antialiasHint);
790
hintsChanged = true;
791
}
792
793
// Significant only for text ops:
794
int textAntialiasHint = sg2d.textAntialiasHint;
795
if (this.fGraphicsStatesInt.get(kHintsTextAntialiasIndex) != textAntialiasHint) {
796
this.fGraphicsStatesInt.put(kHintsTextAntialiasIndex, textAntialiasHint);
797
hintsChanged = true;
798
}
799
800
// Significant only for text ops:
801
int fractionalMetricsHint = sg2d.fractionalMetricsHint;
802
if (this.fGraphicsStatesInt.get(kHintsFractionalMetricsIndex) != fractionalMetricsHint) {
803
this.fGraphicsStatesInt.put(kHintsFractionalMetricsIndex, fractionalMetricsHint);
804
hintsChanged = true;
805
}
806
807
// Significant only for image ops:
808
int renderHint = sg2d.renderHint;
809
if (this.fGraphicsStatesInt.get(kHintsRenderingIndex) != renderHint) {
810
this.fGraphicsStatesInt.put(kHintsRenderingIndex, renderHint);
811
hintsChanged = true;
812
}
813
814
// Significant only for image ops:
815
Object hintValue = sg2d.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
816
int interpolationHint = (hintValue != null ? ((SunHints.Value) hintValue).getIndex() : -1);
817
if (this.fGraphicsStatesInt.get(kHintsInterpolationIndex) != interpolationHint) {
818
this.fGraphicsStatesInt.put(kHintsInterpolationIndex, interpolationHint);
819
hintsChanged = true;
820
}
821
822
if (hintsChanged) {
823
this.fChangeFlag = (this.fChangeFlag | kHintsChangedBit);
824
} else {
825
this.fChangeFlag = (this.fChangeFlag & kHintsNotChangedBit);
826
}
827
}
828
829
SunGraphics2D sg2dCurrent = null;
830
Thread threadCurrent = null;
831
832
void setupGraphicsState(SunGraphics2D sg2d, int primitiveType) {
833
setupGraphicsState(sg2d, primitiveType, sg2d.font, 0, 0, fBounds.width, fBounds.height); // deviceBounds into userBounds
834
}
835
836
void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, int x, int y, int w, int h) {
837
setupGraphicsState(sg2d, primitiveType, sg2d.font, x, y, w, h);
838
}
839
840
// the method below is overriden by CPeerSurface to check the last peer used to draw
841
// if the peer changed we finish lazy drawing
842
void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, Font font, int x, int y, int w, int h) {
843
this.fChangeFlag = 0;
844
845
setUserBounds(sg2d, x, y, w, h);
846
847
Thread thread = Thread.currentThread();
848
if ((this.sg2dCurrent != sg2d) || (this.threadCurrent != thread)) {
849
this.sg2dCurrent = sg2d;
850
this.threadCurrent = thread;
851
852
setupClip(sg2d);
853
setupTransform(sg2d);
854
setupPaint(sg2d, x, y, w, h);
855
setupComposite(sg2d);
856
setupStroke(sg2d);
857
setupFont(font, sg2d.paint);
858
setupRenderingHints(sg2d);
859
860
this.fChangeFlag = kEverythingChangedFlag;
861
} else {
862
int rendererType = getRendererTypeForPrimitive(primitiveType);
863
864
setupClip(sg2d);
865
setupTransform(sg2d);
866
867
if (rendererType != kCopyArea) {
868
setupComposite(sg2d);
869
setupRenderingHints(sg2d);
870
871
if ((rendererType != kImage)) {
872
setupPaint(sg2d, x, y, w, h);
873
setupStroke(sg2d);
874
}
875
if (rendererType != kPrimitive) {
876
setupFont(font, sg2d.paint);
877
}
878
879
}
880
}
881
882
this.fGraphicsStatesInt.put(kChangeFlagIndex, this.fChangeFlag);
883
}
884
885
boolean isCustomPaint(SunGraphics2D sg2d) {
886
if ((sg2d.paint instanceof Color) || (sg2d.paint instanceof SystemColor) || (sg2d.paint instanceof GradientPaint) || (sg2d.paint instanceof TexturePaint)) { return false; }
887
888
return true;
889
}
890
891
final float[] segmentCoordinatesArray = new float[6];
892
893
int getPathLength(GeneralPath gp) {
894
int length = 0;
895
896
PathIterator pi = gp.getPathIterator(null);
897
while (pi.isDone() == false) {
898
pi.next();
899
length++;
900
}
901
902
return length;
903
}
904
905
int getPathCoordinates(GeneralPath gp, FloatBuffer coordinates, IntBuffer types) {
906
// System.err.println("getPathCoordinates");
907
boolean skip = false;
908
909
coordinates.clear();
910
types.clear();
911
912
int type;
913
914
PathIterator pi = gp.getPathIterator(null);
915
while (pi.isDone() == false) {
916
skip = false;
917
type = pi.currentSegment(segmentCoordinatesArray);
918
919
switch (type) {
920
case PathIterator.SEG_MOVETO:
921
// System.err.println(" SEG_MOVETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");
922
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
923
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {
924
coordinates.put(segmentCoordinatesArray[0]);
925
coordinates.put(segmentCoordinatesArray[1]);
926
} else {
927
skip = true;
928
}
929
break;
930
case PathIterator.SEG_LINETO:
931
// System.err.println(" SEG_LINETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");
932
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
933
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {
934
coordinates.put(segmentCoordinatesArray[0]);
935
coordinates.put(segmentCoordinatesArray[1]);
936
} else {
937
skip = true;
938
}
939
break;
940
case PathIterator.SEG_QUADTO:
941
// System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+")");
942
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
943
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&
944
segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&
945
segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND) {
946
coordinates.put(segmentCoordinatesArray[0]);
947
coordinates.put(segmentCoordinatesArray[1]);
948
coordinates.put(segmentCoordinatesArray[2]);
949
coordinates.put(segmentCoordinatesArray[3]);
950
} else {
951
skip = true;
952
}
953
break;
954
case PathIterator.SEG_CUBICTO:
955
// System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+"), ("+segmentCoordinatesArray[4]+", "+segmentCoordinatesArray[5]+")");
956
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
957
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&
958
segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&
959
segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND &&
960
segmentCoordinatesArray[4] < UPPER_BND && segmentCoordinatesArray[4] > LOWER_BND &&
961
segmentCoordinatesArray[5] < UPPER_BND && segmentCoordinatesArray[5] > LOWER_BND) {
962
coordinates.put(segmentCoordinatesArray[0]);
963
coordinates.put(segmentCoordinatesArray[1]);
964
coordinates.put(segmentCoordinatesArray[2]);
965
coordinates.put(segmentCoordinatesArray[3]);
966
coordinates.put(segmentCoordinatesArray[4]);
967
coordinates.put(segmentCoordinatesArray[5]);
968
} else {
969
skip = true;
970
}
971
break;
972
case PathIterator.SEG_CLOSE:
973
// System.err.println(" SEG_CLOSE");
974
break;
975
}
976
977
if (!skip) {
978
types.put(type);
979
}
980
981
pi.next();
982
}
983
984
return pi.getWindingRule();
985
}
986
987
public void doLine(CRenderer renderer, SunGraphics2D sg2d, float x1, float y1, float x2, float y2) {
988
// System.err.println("-- doLine x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2+" paint="+sg2d.paint);
989
setupGraphicsState(sg2d, kLine, sg2d.font, 0, 0, fBounds.width, fBounds.height);
990
renderer.doLine(this, x1, y1, x2, y2);
991
}
992
993
public void doRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {
994
// System.err.println("-- doRect x="+x+" y="+y+" w="+width+" h="+height+" isfill="+isfill+" paint="+sg2d.paint);
995
if ((isfill) && (isCustomPaint(sg2d))) {
996
setupGraphicsState(sg2d, kRect, (int) x, (int) y, (int) width, (int) height);
997
} else {
998
setupGraphicsState(sg2d, kRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);
999
}
1000
renderer.doRect(this, x, y, width, height, isfill);
1001
}
1002
1003
public void doRoundRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float arcW, float arcH, boolean isfill) {
1004
// System.err.println("--- doRoundRect");
1005
if ((isfill) && (isCustomPaint(sg2d))) {
1006
setupGraphicsState(sg2d, kRoundRect, (int) x, (int) y, (int) width, (int) height);
1007
} else {
1008
setupGraphicsState(sg2d, kRoundRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1009
}
1010
renderer.doRoundRect(this, x, y, width, height, arcW, arcH, isfill);
1011
}
1012
1013
public void doOval(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {
1014
// System.err.println("--- doOval");
1015
if ((isfill) && (isCustomPaint(sg2d))) {
1016
setupGraphicsState(sg2d, kOval, (int) x, (int) y, (int) width, (int) height);
1017
} else {
1018
setupGraphicsState(sg2d, kOval, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1019
}
1020
renderer.doOval(this, x, y, width, height, isfill);
1021
}
1022
1023
public void doArc(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float startAngle, float arcAngle, int type, boolean isfill) {
1024
// System.err.println("--- doArc");
1025
if ((isfill) && (isCustomPaint(sg2d))) {
1026
setupGraphicsState(sg2d, kArc, (int) x, (int) y, (int) width, (int) height);
1027
} else {
1028
setupGraphicsState(sg2d, kArc, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1029
}
1030
1031
renderer.doArc(this, x, y, width, height, startAngle, arcAngle, type, isfill);
1032
}
1033
1034
public void doPolygon(CRenderer renderer, SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints, boolean ispolygon, boolean isfill) {
1035
// System.err.println("--- doPolygon");
1036
1037
if ((isfill) && (isCustomPaint(sg2d))) {
1038
int minx = xpoints[0];
1039
int miny = ypoints[0];
1040
int maxx = minx;
1041
int maxy = miny;
1042
for (int i = 1; i < npoints; i++) {
1043
int x = xpoints[i];
1044
if (x < minx) {
1045
minx = x;
1046
} else if (x > maxx) {
1047
maxx = x;
1048
}
1049
1050
int y = ypoints[i];
1051
if (y < miny) {
1052
miny = y;
1053
} else if (y > maxy) {
1054
maxy = y;
1055
}
1056
}
1057
setupGraphicsState(sg2d, kPolygon, minx, miny, maxx - minx, maxy - miny);
1058
} else {
1059
setupGraphicsState(sg2d, kPolygon, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1060
}
1061
renderer.doPoly(this, xpoints, ypoints, npoints, ispolygon, isfill);
1062
}
1063
1064
FloatBuffer shapeCoordinatesArray = null;
1065
IntBuffer shapeTypesArray = null;
1066
1067
public void drawfillShape(CRenderer renderer, SunGraphics2D sg2d, GeneralPath gp, boolean isfill, boolean shouldApplyOffset) {
1068
// System.err.println("--- drawfillShape");
1069
1070
if ((isfill) && (isCustomPaint(sg2d))) {
1071
Rectangle bounds = gp.getBounds();
1072
setupGraphicsState(sg2d, kShape, bounds.x, bounds.y, bounds.width, bounds.height);
1073
} else {
1074
setupGraphicsState(sg2d, kShape, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1075
}
1076
1077
int shapeLength = getPathLength(gp);
1078
1079
if ((shapeCoordinatesArray == null) || (shapeCoordinatesArray.capacity() < (shapeLength * 6))) {
1080
shapeCoordinatesArray = getBufferOfSize(shapeLength * 6).asFloatBuffer(); // segment can have a max of 6
1081
// coordinates
1082
}
1083
if ((shapeTypesArray == null) || (shapeTypesArray.capacity() < shapeLength)) {
1084
shapeTypesArray = getBufferOfSize(shapeLength).asIntBuffer();
1085
}
1086
1087
int windingRule = getPathCoordinates(gp, shapeCoordinatesArray, shapeTypesArray);
1088
1089
renderer.doShape(this, shapeLength, shapeCoordinatesArray, shapeTypesArray, windingRule, isfill, shouldApplyOffset);
1090
}
1091
1092
public void blitImage(CRenderer renderer, SunGraphics2D sg2d, SurfaceData img, boolean fliph, boolean flipv, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, Color bgColor) {
1093
// System.err.println("--- blitImage sx="+sx+", sy="+sy+", sw="+sw+", sh="+sh+", img="+img);
1094
OSXOffScreenSurfaceData osxsd = (OSXOffScreenSurfaceData) img;
1095
synchronized (osxsd.getLockObject()) {
1096
int w = osxsd.bim.getWidth();
1097
int h = osxsd.bim.getHeight();
1098
1099
// the image itself can have outstanding graphics primitives that might need to be flushed
1100
setupGraphicsState(sg2d, kImage, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1101
1102
// 04/06/04 cmc: radr://3612381 Graphics.drawImage ignores bgcolor parameter
1103
if (bgColor != null) {
1104
img = osxsd.getCopyWithBgColor(bgColor);
1105
}
1106
1107
renderer.doImage(this, img, fliph, flipv, w, h, sx, sy, sw, sh, dx, dy, dw, dh);
1108
}
1109
}
1110
1111
public interface CGContextDrawable {
1112
public void drawIntoCGContext(final long cgContext);
1113
}
1114
1115
public void drawString(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, String str, double x, double y) {
1116
// System.err.println("--- drawString str=\""+str+"\"");
1117
// see <rdar://problem/3825795>. We don't want to call anything if the string is empty!
1118
if (str.length() == 0) { return; }
1119
1120
setupGraphicsState(sg2d, kString, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1121
renderer.doDrawString(this, nativeStrikePtr, str, x, y);
1122
}
1123
1124
public void drawGlyphs(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, GlyphVector gv, float x, float y) {
1125
// System.err.println("--- drawGlyphs");
1126
setupGraphicsState(sg2d, kGlyphs, gv.getFont(), 0, 0, fBounds.width, fBounds.height);
1127
renderer.doDrawGlyphs(this, nativeStrikePtr, gv, x, y);
1128
}
1129
1130
public void drawUnicodes(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, char[] unicodes, int offset, int length, float x, float y) {
1131
// System.err.println("--- drawUnicodes "+(new String(unicodes, offset, length)));
1132
setupGraphicsState(sg2d, kUnicodes, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1133
if (length == 1) {
1134
renderer.doOneUnicode(this, nativeStrikePtr, unicodes[offset], x, y);
1135
} else {
1136
renderer.doUnicodes(this, nativeStrikePtr, unicodes, offset, length, x, y);
1137
}
1138
}
1139
1140
// used by copyArea:
1141
1142
Rectangle srcCopyAreaRect = new Rectangle();
1143
Rectangle dstCopyAreaRect = new Rectangle();
1144
Rectangle finalCopyAreaRect = new Rectangle();
1145
Rectangle copyAreaBounds = new Rectangle();
1146
1147
void intersection(Rectangle r1, Rectangle r2, Rectangle r3) {
1148
// this code is taken from Rectangle.java (modified to put results in r3)
1149
int tx1 = r1.x;
1150
int ty1 = r1.y;
1151
long tx2 = tx1 + r1.width;
1152
long ty2 = ty1 + r1.height;
1153
1154
int rx1 = r2.x;
1155
int ry1 = r2.y;
1156
long rx2 = rx1 + r2.width;
1157
long ry2 = ry1 + r2.height;
1158
1159
if (tx1 < rx1) tx1 = rx1;
1160
if (ty1 < ry1) ty1 = ry1;
1161
if (tx2 > rx2) tx2 = rx2;
1162
if (ty2 > ry2) ty2 = ry2;
1163
1164
tx2 -= tx1;
1165
ty2 -= ty1;
1166
1167
// tx2,ty2 will never overflow (they will never be
1168
// larger than the smallest of the two source w,h)
1169
// they might underflow, though...
1170
if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
1171
if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
1172
1173
r3.setBounds(tx1, ty1, (int) tx2, (int) ty2);
1174
}
1175
1176
/**
1177
* Clips the copy area to the heavyweight bounds and returns the clipped rectangle.
1178
* The returned clipped rectangle is in the coordinate space of the surface.
1179
*/
1180
protected Rectangle clipCopyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) {
1181
// we need to clip against the heavyweight bounds
1182
copyAreaBounds.setBounds(sg2d.devClip.getLoX(), sg2d.devClip.getLoY(), sg2d.devClip.getWidth(), sg2d.devClip.getHeight());
1183
1184
// clip src rect
1185
srcCopyAreaRect.setBounds(x, y, w, h);
1186
intersection(srcCopyAreaRect, copyAreaBounds, srcCopyAreaRect);
1187
if ((srcCopyAreaRect.width <= 0) || (srcCopyAreaRect.height <= 0)) {
1188
// src rect outside bounds
1189
return null;
1190
}
1191
1192
// clip dst rect
1193
dstCopyAreaRect.setBounds(srcCopyAreaRect.x + dx, srcCopyAreaRect.y + dy, srcCopyAreaRect.width, srcCopyAreaRect.height);
1194
intersection(dstCopyAreaRect, copyAreaBounds, dstCopyAreaRect);
1195
if ((dstCopyAreaRect.width <= 0) || (dstCopyAreaRect.height <= 0)) {
1196
// dst rect outside clip
1197
return null;
1198
}
1199
1200
x = dstCopyAreaRect.x - dx;
1201
y = dstCopyAreaRect.y - dy;
1202
w = dstCopyAreaRect.width;
1203
h = dstCopyAreaRect.height;
1204
1205
finalCopyAreaRect.setBounds(x, y, w, h);
1206
1207
return finalCopyAreaRect;
1208
}
1209
1210
// <rdar://3785539> We only need to mark dirty on screen surfaces. This method is
1211
// marked as protected and it is intended for subclasses to override if they need to
1212
// be notified when the surface is dirtied. See CPeerSurfaceData.markDirty() for implementation.
1213
// We don't do anything for buffered images.
1214
protected void markDirty(boolean markAsDirty) {
1215
// do nothing by default
1216
}
1217
1218
// LazyDrawing optimization implementation:
1219
1220
@Override
1221
public boolean canRenderLCDText(SunGraphics2D sg2d) {
1222
if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
1223
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
1224
sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&
1225
// sg2d.surfaceData.getTransparency() == Transparency.OPAQUE &&
1226
// This last test is a workaround until we fix loop selection
1227
// in the pipe validation
1228
sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { return true; }
1229
return false; /* for now - in the future we may want to search */
1230
}
1231
1232
public static boolean IsSimpleColor(Object c) {
1233
return ((c instanceof Color) || (c instanceof SystemColor) || (c instanceof javax.swing.plaf.ColorUIResource));
1234
}
1235
1236
static {
1237
if ((kColorPointerIndex % 2) != 0) {
1238
System.err.println("kColorPointerIndex=" + kColorPointerIndex + " is NOT aligned for 64 bit");
1239
System.exit(0);
1240
}
1241
}
1242
}
1243
1244