1 /* 2 * Copyright (c) 2011, 2015, 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. OSXSurfaceData(SurfaceType sType, ColorModel cm)62 public OSXSurfaceData(SurfaceType sType, ColorModel cm) { 63 this(sType, cm, null, new Rectangle()); 64 } 65 OSXSurfaceData(SurfaceType sType, ColorModel cm, GraphicsConfiguration config, Rectangle bounds)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 validatePipe(SunGraphics2D sg2d)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 setPipesToQuartzComposite(SunGraphics2D sg2d)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 getBounds()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 getDeviceConfiguration()129 public GraphicsConfiguration getDeviceConfiguration() { 130 return fConfig; 131 } 132 setBounds(int x, int y, int w, int h)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 copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage image)138 public abstract BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage image); 139 xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR)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 getCompositingImage(int w, int h)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 getCompositingImageSame(BufferedImage img, int w, int h)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 getCompositingSrcImage(int w, int h)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 getCompositingDstInImage(int w, int h)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 getCompositingDstOutImage(int w, int h)182 public BufferedImage getCompositingDstOutImage(int w, int h) { 183 BufferedImage bim = getCompositingImageSame(sDstOutComposite, w, h); 184 sDstOutComposite = bim; 185 return bim; 186 } 187 clearRect(BufferedImage bim, int w, int h)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 invalidate()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 getRendererTypeForPrimitive(int primitiveType)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 setUserBounds(SunGraphics2D sg2d, int x, int y, int width, int height)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 getBufferOfSize(int size)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 setupClip(SunGraphics2D sg2d)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 setupTransform(SunGraphics2D sg2d)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 setGradientViaRasterPath(SunGraphics2D sg2d)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 setupPaint(SunGraphics2D sg2d, int x, int y, int w, int h)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 setupComposite(SunGraphics2D sg2d)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 setupStroke(SunGraphics2D sg2d)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 setupFont(Font font, Paint paint)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 setupRenderingHints(SunGraphics2D sg2d)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 setupGraphicsState(SunGraphics2D sg2d, int primitiveType)832 void setupGraphicsState(SunGraphics2D sg2d, int primitiveType) { 833 setupGraphicsState(sg2d, primitiveType, sg2d.font, 0, 0, fBounds.width, fBounds.height); // deviceBounds into userBounds 834 } 835 setupGraphicsState(SunGraphics2D sg2d, int primitiveType, int x, int y, int w, int h)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 setupGraphicsState(SunGraphics2D sg2d, int primitiveType, Font font, int x, int y, int w, int h)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 isCustomPaint(SunGraphics2D sg2d)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 getPathLength(GeneralPath gp)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 getPathCoordinates(GeneralPath gp, FloatBuffer coordinates, IntBuffer types)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 doLine(CRenderer renderer, SunGraphics2D sg2d, float x1, float y1, float x2, float y2)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 doRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill)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 doRoundRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float arcW, float arcH, boolean isfill)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 doOval(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill)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 doArc(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float startAngle, float arcAngle, int type, boolean isfill)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 doPolygon(CRenderer renderer, SunGraphics2D sg2d, int xpoints[], int ypoints[], int npoints, boolean ispolygon, boolean isfill)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 drawfillShape(CRenderer renderer, SunGraphics2D sg2d, GeneralPath gp, boolean isfill, boolean shouldApplyOffset)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 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)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 { drawIntoCGContext(final long cgContext)1112 public void drawIntoCGContext(final long cgContext); 1113 } 1114 drawString(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, String str, double x, double y)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 drawGlyphs(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, GlyphVector gv, float x, float y)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 drawUnicodes(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, char unicodes[], int offset, int length, float x, float y)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 intersection(Rectangle r1, Rectangle r2, Rectangle r3)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 */ clipCopyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy)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. markDirty(boolean markAsDirty)1214 protected void markDirty(boolean markAsDirty) { 1215 // do nothing by default 1216 } 1217 1218 // LazyDrawing optimization implementation: 1219 1220 @Override canRenderLCDText(SunGraphics2D sg2d)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 IsSimpleColor(Object c)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