Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/java2d/OSXSurfaceData.java
38829 views
1
/*
2
* Copyright (c) 2011, 2013, 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
final static float UPPER_BND = Float.MAX_VALUE / 2.0f;
47
final static 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.reshape(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
Point2D p = color.getStartPoint();
621
this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
622
this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
623
p = color.getEndPoint();
624
this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
625
this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
626
627
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
628
} else {
629
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
630
}
631
} else {
632
setGradientViaRasterPath(sg2d);
633
}
634
} else if (sg2d.paint instanceof RadialGradientPaint) {
635
RadialGradientPaint color = (RadialGradientPaint) sg2d.paint;
636
if (color.getCycleMethod() == RadialGradientPaint.CycleMethod.NO_CYCLE) {
637
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorRadialGradient) || (lastPaint != sg2d.paint)) {
638
639
this.fGraphicsStatesInt.put(kColorStateIndex, kColorRadialGradient);
640
int numColor = color.getColors().length;
641
int colorArray[] = new int[numColor];
642
for (int i = 0; i < numColor; i++) {
643
colorArray[i] = color.getColors()[i].getRGB();
644
}
645
this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;
646
647
int numStops = color.getFractions().length;
648
float stopsArray[] = new float[numStops];
649
for (int i = 0; i < numStops; i++) {
650
stopsArray[i] = color.getFractions()[i];
651
}
652
this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();
653
Point2D p = color.getFocusPoint();
654
this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
655
this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
656
p = color.getCenterPoint();
657
this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
658
this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
659
this.fGraphicsStatesFloat.put(kRadiusIndex, color.getRadius());
660
661
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
662
} else {
663
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
664
}
665
} else {
666
setGradientViaRasterPath(sg2d);
667
}
668
} else if (sg2d.paint instanceof TexturePaint) {
669
if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint)) {
670
TexturePaint color = (TexturePaint) sg2d.paint;
671
this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
672
texturePaintImage = color.getImage();
673
SurfaceData textureSurfaceData = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage);
674
this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
675
this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
676
Rectangle2D anchor = color.getAnchorRect();
677
this.fGraphicsStatesFloat.put(kColortxIndex, (float) anchor.getX());
678
this.fGraphicsStatesFloat.put(kColortyIndex, (float) anchor.getY());
679
this.fGraphicsStatesFloat.put(kColorsxIndex, (float) (anchor.getWidth() / texturePaintImage.getWidth()));
680
this.fGraphicsStatesFloat.put(kColorsyIndex, (float) (anchor.getHeight() / texturePaintImage.getHeight()));
681
this.fGraphicsStatesObject[kTextureImageIndex] = textureSurfaceData;
682
683
this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
684
} else {
685
this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
686
}
687
} else {
688
setGradientViaRasterPath(sg2d);
689
}
690
lastPaint = sg2d.paint;
691
}
692
693
Composite lastComposite;
694
int lastCompositeAlphaRule = 0;
695
float lastCompositeAlphaValue = 0;
696
697
void setupComposite(SunGraphics2D sg2d) {
698
Composite composite = sg2d.composite;
699
700
if (lastComposite != composite) {
701
lastComposite = composite;
702
703
// For composite state COMP_ISCOPY, COMP_XOR or COMP_CUSTOM set alpha compositor to COPY:
704
int alphaRule = AlphaComposite.SRC_OVER;
705
float alphaValue = 1.0f;
706
707
// For composite state COMP_ISCOPY composite could be null. If it's not (or composite state == COMP_ALPHA)
708
// get alpha compositor's values:
709
if ((sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) && (composite != null)) {
710
AlphaComposite alphaComposite = (AlphaComposite) composite;
711
alphaRule = alphaComposite.getRule();
712
alphaValue = alphaComposite.getAlpha();
713
}
714
715
// 2-17-03 VL: [Radar 3174922]
716
// For COMP_XOR and COMP_CUSTOM compositing modes we should be setting alphaRule = AlphaComposite.SRC
717
// which should map to kCGCompositeCopy.
718
719
if ((lastCompositeAlphaRule != alphaRule) || (lastCompositeAlphaValue != alphaValue)) {
720
this.fGraphicsStatesInt.put(kCompositeRuleIndex, alphaRule);
721
this.fGraphicsStatesFloat.put(kCompositeValueIndex, alphaValue);
722
723
lastCompositeAlphaRule = alphaRule;
724
lastCompositeAlphaValue = alphaValue;
725
726
this.fChangeFlag = (this.fChangeFlag | kCompositeChangedBit);
727
} else {
728
this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);
729
}
730
} else {
731
this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);
732
}
733
}
734
735
BasicStroke lastStroke = null;
736
static BasicStroke defaultBasicStroke = new BasicStroke();
737
738
void setupStroke(SunGraphics2D sg2d) {
739
BasicStroke stroke = defaultBasicStroke;
740
741
if (sg2d.stroke instanceof BasicStroke) {
742
stroke = (BasicStroke) sg2d.stroke;
743
}
744
745
if (lastStroke != stroke) {
746
this.fGraphicsStatesObject[kStrokeDashArrayIndex] = stroke.getDashArray();
747
this.fGraphicsStatesFloat.put(kStrokeDashPhaseIndex, stroke.getDashPhase());
748
this.fGraphicsStatesInt.put(kStrokeCapIndex, stroke.getEndCap());
749
this.fGraphicsStatesInt.put(kStrokeJoinIndex, stroke.getLineJoin());
750
this.fGraphicsStatesFloat.put(kStrokeWidthIndex, stroke.getLineWidth());
751
this.fGraphicsStatesFloat.put(kStrokeLimitIndex, stroke.getMiterLimit());
752
753
this.fChangeFlag = (this.fChangeFlag | kStrokeChangedBit);
754
755
lastStroke = stroke;
756
} else {
757
this.fChangeFlag = (this.fChangeFlag & kStrokeNotChangedBit);
758
}
759
}
760
761
Font lastFont;
762
763
void setupFont(Font font, Paint paint) {
764
if (font == null) { return; }
765
766
// We have to setup the kFontPaintIndex if we have changed the color so we added the last
767
// test to see if the color has changed - needed for complex strings
768
// see Radar 3368674
769
if ((font != lastFont) || ((this.fChangeFlag & kColorChangedBit) != 0)) {
770
this.fGraphicsStatesObject[kFontIndex] = font;
771
this.fGraphicsStatesObject[kFontPaintIndex] = paint;
772
773
this.fChangeFlag = (this.fChangeFlag | kFontChangedBit);
774
775
lastFont = font;
776
} else {
777
this.fChangeFlag = (this.fChangeFlag & kFontNotChangedBit);
778
}
779
}
780
781
void setupRenderingHints(SunGraphics2D sg2d) {
782
boolean hintsChanged = false;
783
784
// Significant for draw, fill, text, and image ops:
785
int antialiasHint = sg2d.antialiasHint;
786
if (this.fGraphicsStatesInt.get(kHintsAntialiasIndex) != antialiasHint) {
787
this.fGraphicsStatesInt.put(kHintsAntialiasIndex, antialiasHint);
788
hintsChanged = true;
789
}
790
791
// Significant only for text ops:
792
int textAntialiasHint = sg2d.textAntialiasHint;
793
if (this.fGraphicsStatesInt.get(kHintsTextAntialiasIndex) != textAntialiasHint) {
794
this.fGraphicsStatesInt.put(kHintsTextAntialiasIndex, textAntialiasHint);
795
hintsChanged = true;
796
}
797
798
// Significant only for text ops:
799
int fractionalMetricsHint = sg2d.fractionalMetricsHint;
800
if (this.fGraphicsStatesInt.get(kHintsFractionalMetricsIndex) != fractionalMetricsHint) {
801
this.fGraphicsStatesInt.put(kHintsFractionalMetricsIndex, fractionalMetricsHint);
802
hintsChanged = true;
803
}
804
805
// Significant only for image ops:
806
int renderHint = sg2d.renderHint;
807
if (this.fGraphicsStatesInt.get(kHintsRenderingIndex) != renderHint) {
808
this.fGraphicsStatesInt.put(kHintsRenderingIndex, renderHint);
809
hintsChanged = true;
810
}
811
812
// Significant only for image ops:
813
Object hintValue = sg2d.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
814
int interpolationHint = (hintValue != null ? ((SunHints.Value) hintValue).getIndex() : -1);
815
if (this.fGraphicsStatesInt.get(kHintsInterpolationIndex) != interpolationHint) {
816
this.fGraphicsStatesInt.put(kHintsInterpolationIndex, interpolationHint);
817
hintsChanged = true;
818
}
819
820
if (hintsChanged) {
821
this.fChangeFlag = (this.fChangeFlag | kHintsChangedBit);
822
} else {
823
this.fChangeFlag = (this.fChangeFlag & kHintsNotChangedBit);
824
}
825
}
826
827
SunGraphics2D sg2dCurrent = null;
828
Thread threadCurrent = null;
829
830
void setupGraphicsState(SunGraphics2D sg2d, int primitiveType) {
831
setupGraphicsState(sg2d, primitiveType, sg2d.font, 0, 0, fBounds.width, fBounds.height); // deviceBounds into userBounds
832
}
833
834
void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, int x, int y, int w, int h) {
835
setupGraphicsState(sg2d, primitiveType, sg2d.font, x, y, w, h);
836
}
837
838
// the method below is overriden by CPeerSurface to check the last peer used to draw
839
// if the peer changed we finish lazy drawing
840
void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, Font font, int x, int y, int w, int h) {
841
this.fChangeFlag = 0;
842
843
setUserBounds(sg2d, x, y, w, h);
844
845
Thread thread = Thread.currentThread();
846
if ((this.sg2dCurrent != sg2d) || (this.threadCurrent != thread)) {
847
this.sg2dCurrent = sg2d;
848
this.threadCurrent = thread;
849
850
setupClip(sg2d);
851
setupTransform(sg2d);
852
setupPaint(sg2d, x, y, w, h);
853
setupComposite(sg2d);
854
setupStroke(sg2d);
855
setupFont(font, sg2d.paint);
856
setupRenderingHints(sg2d);
857
858
this.fChangeFlag = kEverythingChangedFlag;
859
} else {
860
int rendererType = getRendererTypeForPrimitive(primitiveType);
861
862
setupClip(sg2d);
863
setupTransform(sg2d);
864
865
if (rendererType != kCopyArea) {
866
setupComposite(sg2d);
867
setupRenderingHints(sg2d);
868
869
if ((rendererType != kImage)) {
870
setupPaint(sg2d, x, y, w, h);
871
setupStroke(sg2d);
872
}
873
if (rendererType != kPrimitive) {
874
setupFont(font, sg2d.paint);
875
}
876
877
}
878
}
879
880
this.fGraphicsStatesInt.put(kChangeFlagIndex, this.fChangeFlag);
881
}
882
883
boolean isCustomPaint(SunGraphics2D sg2d) {
884
if ((sg2d.paint instanceof Color) || (sg2d.paint instanceof SystemColor) || (sg2d.paint instanceof GradientPaint) || (sg2d.paint instanceof TexturePaint)) { return false; }
885
886
return true;
887
}
888
889
final float[] segmentCoordinatesArray = new float[6];
890
891
int getPathLength(GeneralPath gp) {
892
int length = 0;
893
894
PathIterator pi = gp.getPathIterator(null);
895
while (pi.isDone() == false) {
896
pi.next();
897
length++;
898
}
899
900
return length;
901
}
902
903
int getPathCoordinates(GeneralPath gp, FloatBuffer coordinates, IntBuffer types) {
904
// System.err.println("getPathCoordinates");
905
boolean skip = false;
906
907
coordinates.clear();
908
types.clear();
909
910
int type;
911
912
PathIterator pi = gp.getPathIterator(null);
913
while (pi.isDone() == false) {
914
skip = false;
915
type = pi.currentSegment(segmentCoordinatesArray);
916
917
switch (type) {
918
case PathIterator.SEG_MOVETO:
919
// System.err.println(" SEG_MOVETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");
920
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
921
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {
922
coordinates.put(segmentCoordinatesArray[0]);
923
coordinates.put(segmentCoordinatesArray[1]);
924
} else {
925
skip = true;
926
}
927
break;
928
case PathIterator.SEG_LINETO:
929
// System.err.println(" SEG_LINETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");
930
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
931
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {
932
coordinates.put(segmentCoordinatesArray[0]);
933
coordinates.put(segmentCoordinatesArray[1]);
934
} else {
935
skip = true;
936
}
937
break;
938
case PathIterator.SEG_QUADTO:
939
// System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+")");
940
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
941
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&
942
segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&
943
segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND) {
944
coordinates.put(segmentCoordinatesArray[0]);
945
coordinates.put(segmentCoordinatesArray[1]);
946
coordinates.put(segmentCoordinatesArray[2]);
947
coordinates.put(segmentCoordinatesArray[3]);
948
} else {
949
skip = true;
950
}
951
break;
952
case PathIterator.SEG_CUBICTO:
953
// System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+"), ("+segmentCoordinatesArray[4]+", "+segmentCoordinatesArray[5]+")");
954
if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
955
segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&
956
segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&
957
segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND &&
958
segmentCoordinatesArray[4] < UPPER_BND && segmentCoordinatesArray[4] > LOWER_BND &&
959
segmentCoordinatesArray[5] < UPPER_BND && segmentCoordinatesArray[5] > LOWER_BND) {
960
coordinates.put(segmentCoordinatesArray[0]);
961
coordinates.put(segmentCoordinatesArray[1]);
962
coordinates.put(segmentCoordinatesArray[2]);
963
coordinates.put(segmentCoordinatesArray[3]);
964
coordinates.put(segmentCoordinatesArray[4]);
965
coordinates.put(segmentCoordinatesArray[5]);
966
} else {
967
skip = true;
968
}
969
break;
970
case PathIterator.SEG_CLOSE:
971
// System.err.println(" SEG_CLOSE");
972
break;
973
}
974
975
if (!skip) {
976
types.put(type);
977
}
978
979
pi.next();
980
}
981
982
return pi.getWindingRule();
983
}
984
985
public void doLine(CRenderer renderer, SunGraphics2D sg2d, float x1, float y1, float x2, float y2) {
986
// System.err.println("-- doLine x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2+" paint="+sg2d.paint);
987
setupGraphicsState(sg2d, kLine, sg2d.font, 0, 0, fBounds.width, fBounds.height);
988
renderer.doLine(this, x1, y1, x2, y2);
989
}
990
991
public void doRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {
992
// System.err.println("-- doRect x="+x+" y="+y+" w="+width+" h="+height+" isfill="+isfill+" paint="+sg2d.paint);
993
if ((isfill) && (isCustomPaint(sg2d))) {
994
setupGraphicsState(sg2d, kRect, (int) x, (int) y, (int) width, (int) height);
995
} else {
996
setupGraphicsState(sg2d, kRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);
997
}
998
renderer.doRect(this, x, y, width, height, isfill);
999
}
1000
1001
public void doRoundRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float arcW, float arcH, boolean isfill) {
1002
// System.err.println("--- doRoundRect");
1003
if ((isfill) && (isCustomPaint(sg2d))) {
1004
setupGraphicsState(sg2d, kRoundRect, (int) x, (int) y, (int) width, (int) height);
1005
} else {
1006
setupGraphicsState(sg2d, kRoundRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1007
}
1008
renderer.doRoundRect(this, x, y, width, height, arcW, arcH, isfill);
1009
}
1010
1011
public void doOval(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {
1012
// System.err.println("--- doOval");
1013
if ((isfill) && (isCustomPaint(sg2d))) {
1014
setupGraphicsState(sg2d, kOval, (int) x, (int) y, (int) width, (int) height);
1015
} else {
1016
setupGraphicsState(sg2d, kOval, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1017
}
1018
renderer.doOval(this, x, y, width, height, isfill);
1019
}
1020
1021
public void doArc(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float startAngle, float arcAngle, int type, boolean isfill) {
1022
// System.err.println("--- doArc");
1023
if ((isfill) && (isCustomPaint(sg2d))) {
1024
setupGraphicsState(sg2d, kArc, (int) x, (int) y, (int) width, (int) height);
1025
} else {
1026
setupGraphicsState(sg2d, kArc, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1027
}
1028
1029
renderer.doArc(this, x, y, width, height, startAngle, arcAngle, type, isfill);
1030
}
1031
1032
public void doPolygon(CRenderer renderer, SunGraphics2D sg2d, int xpoints[], int ypoints[], int npoints, boolean ispolygon, boolean isfill) {
1033
// System.err.println("--- doPolygon");
1034
1035
if ((isfill) && (isCustomPaint(sg2d))) {
1036
int minx = xpoints[0];
1037
int miny = ypoints[0];
1038
int maxx = minx;
1039
int maxy = miny;
1040
for (int i = 1; i < npoints; i++) {
1041
int x = xpoints[i];
1042
if (x < minx) {
1043
minx = x;
1044
} else if (x > maxx) {
1045
maxx = x;
1046
}
1047
1048
int y = ypoints[i];
1049
if (y < miny) {
1050
miny = y;
1051
} else if (y > maxy) {
1052
maxy = y;
1053
}
1054
}
1055
setupGraphicsState(sg2d, kPolygon, minx, miny, maxx - minx, maxy - miny);
1056
} else {
1057
setupGraphicsState(sg2d, kPolygon, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1058
}
1059
renderer.doPoly(this, xpoints, ypoints, npoints, ispolygon, isfill);
1060
}
1061
1062
FloatBuffer shapeCoordinatesArray = null;
1063
IntBuffer shapeTypesArray = null;
1064
1065
public void drawfillShape(CRenderer renderer, SunGraphics2D sg2d, GeneralPath gp, boolean isfill, boolean shouldApplyOffset) {
1066
// System.err.println("--- drawfillShape");
1067
1068
if ((isfill) && (isCustomPaint(sg2d))) {
1069
Rectangle bounds = gp.getBounds();
1070
setupGraphicsState(sg2d, kShape, bounds.x, bounds.y, bounds.width, bounds.height);
1071
} else {
1072
setupGraphicsState(sg2d, kShape, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1073
}
1074
1075
int shapeLength = getPathLength(gp);
1076
1077
if ((shapeCoordinatesArray == null) || (shapeCoordinatesArray.capacity() < (shapeLength * 6))) {
1078
shapeCoordinatesArray = getBufferOfSize(shapeLength * 6).asFloatBuffer(); // segment can have a max of 6
1079
// coordinates
1080
}
1081
if ((shapeTypesArray == null) || (shapeTypesArray.capacity() < shapeLength)) {
1082
shapeTypesArray = getBufferOfSize(shapeLength).asIntBuffer();
1083
}
1084
1085
int windingRule = getPathCoordinates(gp, shapeCoordinatesArray, shapeTypesArray);
1086
1087
renderer.doShape(this, shapeLength, shapeCoordinatesArray, shapeTypesArray, windingRule, isfill, shouldApplyOffset);
1088
}
1089
1090
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) {
1091
// System.err.println("--- blitImage sx="+sx+", sy="+sy+", sw="+sw+", sh="+sh+", img="+img);
1092
OSXOffScreenSurfaceData osxsd = (OSXOffScreenSurfaceData) img;
1093
synchronized (osxsd.getLockObject()) {
1094
int w = osxsd.bim.getWidth();
1095
int h = osxsd.bim.getHeight();
1096
1097
// the image itself can have outstanding graphics primitives that might need to be flushed
1098
setupGraphicsState(sg2d, kImage, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1099
1100
// 04/06/04 cmc: radr://3612381 Graphics.drawImage ignores bgcolor parameter
1101
if (bgColor != null) {
1102
img = osxsd.getCopyWithBgColor(bgColor);
1103
}
1104
1105
renderer.doImage(this, img, fliph, flipv, w, h, sx, sy, sw, sh, dx, dy, dw, dh);
1106
}
1107
}
1108
1109
public interface CGContextDrawable {
1110
public void drawIntoCGContext(final long cgContext);
1111
}
1112
1113
public void drawString(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, String str, double x, double y) {
1114
// System.err.println("--- drawString str=\""+str+"\"");
1115
// see <rdar://problem/3825795>. We don't want to call anything if the string is empty!
1116
if (str.length() == 0) { return; }
1117
1118
setupGraphicsState(sg2d, kString, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1119
renderer.doDrawString(this, nativeStrikePtr, str, x, y);
1120
}
1121
1122
public void drawGlyphs(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, GlyphVector gv, float x, float y) {
1123
// System.err.println("--- drawGlyphs");
1124
setupGraphicsState(sg2d, kGlyphs, gv.getFont(), 0, 0, fBounds.width, fBounds.height);
1125
renderer.doDrawGlyphs(this, nativeStrikePtr, gv, x, y);
1126
}
1127
1128
public void drawUnicodes(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, char unicodes[], int offset, int length, float x, float y) {
1129
// System.err.println("--- drawUnicodes "+(new String(unicodes, offset, length)));
1130
setupGraphicsState(sg2d, kUnicodes, sg2d.font, 0, 0, fBounds.width, fBounds.height);
1131
if (length == 1) {
1132
renderer.doOneUnicode(this, nativeStrikePtr, unicodes[offset], x, y);
1133
} else {
1134
renderer.doUnicodes(this, nativeStrikePtr, unicodes, offset, length, x, y);
1135
}
1136
}
1137
1138
// used by copyArea:
1139
1140
Rectangle srcCopyAreaRect = new Rectangle();
1141
Rectangle dstCopyAreaRect = new Rectangle();
1142
Rectangle finalCopyAreaRect = new Rectangle();
1143
Rectangle copyAreaBounds = new Rectangle();
1144
1145
void intersection(Rectangle r1, Rectangle r2, Rectangle r3) {
1146
// this code is taken from Rectangle.java (modified to put results in r3)
1147
int tx1 = r1.x;
1148
int ty1 = r1.y;
1149
long tx2 = tx1 + r1.width;
1150
long ty2 = ty1 + r1.height;
1151
1152
int rx1 = r2.x;
1153
int ry1 = r2.y;
1154
long rx2 = rx1 + r2.width;
1155
long ry2 = ry1 + r2.height;
1156
1157
if (tx1 < rx1) tx1 = rx1;
1158
if (ty1 < ry1) ty1 = ry1;
1159
if (tx2 > rx2) tx2 = rx2;
1160
if (ty2 > ry2) ty2 = ry2;
1161
1162
tx2 -= tx1;
1163
ty2 -= ty1;
1164
1165
// tx2,ty2 will never overflow (they will never be
1166
// larger than the smallest of the two source w,h)
1167
// they might underflow, though...
1168
if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
1169
if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
1170
1171
r3.setBounds(tx1, ty1, (int) tx2, (int) ty2);
1172
}
1173
1174
/**
1175
* Clips the copy area to the heavywieght bounds and returns the cliped rectangle. The tricky part here is the the
1176
* passed arguments x, y are in the coordinate space of the sg2d/lightweight comp. In order to do the clipping we
1177
* translate them to the coordinate space of the surface, and the returned clipped rectangle is in the coordinate
1178
* 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
// put src rect into surface coordinate space
1185
x += sg2d.transX;
1186
y += sg2d.transY;
1187
1188
// clip src rect
1189
srcCopyAreaRect.setBounds(x, y, w, h);
1190
intersection(srcCopyAreaRect, copyAreaBounds, srcCopyAreaRect);
1191
if ((srcCopyAreaRect.width <= 0) || (srcCopyAreaRect.height <= 0)) {
1192
// src rect outside bounds
1193
return null;
1194
}
1195
1196
// clip dst rect
1197
dstCopyAreaRect.setBounds(srcCopyAreaRect.x + dx, srcCopyAreaRect.y + dy, srcCopyAreaRect.width, srcCopyAreaRect.height);
1198
intersection(dstCopyAreaRect, copyAreaBounds, dstCopyAreaRect);
1199
if ((dstCopyAreaRect.width <= 0) || (dstCopyAreaRect.height <= 0)) {
1200
// dst rect outside clip
1201
return null;
1202
}
1203
1204
x = dstCopyAreaRect.x - dx;
1205
y = dstCopyAreaRect.y - dy;
1206
w = dstCopyAreaRect.width;
1207
h = dstCopyAreaRect.height;
1208
1209
finalCopyAreaRect.setBounds(x, y, w, h);
1210
1211
return finalCopyAreaRect;
1212
}
1213
1214
// <rdar://3785539> We only need to mark dirty on screen surfaces. This method is
1215
// marked as protected and it is intended for subclasses to override if they need to
1216
// be notified when the surface is dirtied. See CPeerSurfaceData.markDirty() for implementation.
1217
// We don't do anything for buffered images.
1218
protected void markDirty(boolean markAsDirty) {
1219
// do nothing by default
1220
}
1221
1222
// LazyDrawing optimization implementation:
1223
1224
@Override
1225
public boolean canRenderLCDText(SunGraphics2D sg2d) {
1226
if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
1227
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
1228
sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&
1229
// sg2d.surfaceData.getTransparency() == Transparency.OPAQUE &&
1230
// This last test is a workaround until we fix loop selection
1231
// in the pipe validation
1232
sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { return true; }
1233
return false; /* for now - in the future we may want to search */
1234
}
1235
1236
public static boolean IsSimpleColor(Object c) {
1237
return ((c instanceof Color) || (c instanceof SystemColor) || (c instanceof javax.swing.plaf.ColorUIResource));
1238
}
1239
1240
static {
1241
if ((kColorPointerIndex % 2) != 0) {
1242
System.err.println("kColorPointerIndex=" + kColorPointerIndex + " is NOT aligned for 64 bit");
1243
System.exit(0);
1244
}
1245
}
1246
}
1247
1248