Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/java2d/OSXSurfaceData.java
38829 views
/*1* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d;2627import java.awt.*;28import java.awt.font.*;29import java.awt.geom.*;30import java.awt.image.*;31import java.nio.*;3233import sun.awt.*;34import sun.awt.image.*;35import sun.java2d.loops.*;36import sun.java2d.pipe.*;37import sun.lwawt.macosx.*;3839import java.lang.annotation.Native;4041/*42* This is the SurfaceData for a CGContextRef.43*/44public abstract class OSXSurfaceData extends BufImgSurfaceData {45final static float UPPER_BND = Float.MAX_VALUE / 2.0f;46final static float LOWER_BND = -UPPER_BND;4748protected static CRenderer sQuartzPipe = null;49protected static CTextPipe sCocoaTextPipe = null;50protected static CompositeCRenderer sQuartzCompositePipe = null;5152private GraphicsConfiguration fConfig;53private Rectangle fBounds; // bounds in user coordinates5455static {56sQuartzPipe = new CRenderer(); // Creates the singleton quartz pipe.57}5859// NOTE: Any subclasses must eventually call QuartzSurfaceData_InitOps in OSXSurfaceData.h60// This sets up the native side for the SurfaceData, and is required.61public OSXSurfaceData(SurfaceType sType, ColorModel cm) {62this(sType, cm, null, new Rectangle());63}6465public OSXSurfaceData(SurfaceType sType, ColorModel cm, GraphicsConfiguration config, Rectangle bounds) {66super(sType, cm);6768this.fConfig = config;6970this.fBounds = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.y + bounds.height);7172this.fGraphicsStates = getBufferOfSize(kSizeOfParameters);73this.fGraphicsStatesInt = this.fGraphicsStates.asIntBuffer();74this.fGraphicsStatesFloat = this.fGraphicsStates.asFloatBuffer();75this.fGraphicsStatesLong = this.fGraphicsStates.asLongBuffer();76this.fGraphicsStatesObject = new Object[8]; // clip coordinates +77// clip types +78// texture paint image +79// stroke dash array +80// font + font paint +81// linear/radial gradient color +82// linear/radial gradient fractions8384// NOTE: All access to the DrawingQueue comes through this OSXSurfaceData instance. Therefore85// every instance method of OSXSurfaceData that accesses the fDrawingQueue is synchronized.8687// Thread.dumpStack();88}8990public void validatePipe(SunGraphics2D sg2d) {9192if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {93if (sCocoaTextPipe == null) {94sCocoaTextPipe = new CTextPipe();95}9697sg2d.imagepipe = sQuartzPipe;98sg2d.drawpipe = sQuartzPipe;99sg2d.fillpipe = sQuartzPipe;100sg2d.shapepipe = sQuartzPipe;101sg2d.textpipe = sCocoaTextPipe;102} else {103setPipesToQuartzComposite(sg2d);104}105}106107protected void setPipesToQuartzComposite(SunGraphics2D sg2d) {108if (sQuartzCompositePipe == null) {109sQuartzCompositePipe = new CompositeCRenderer();110}111112if (sCocoaTextPipe == null) {113sCocoaTextPipe = new CTextPipe();114}115116sg2d.imagepipe = sQuartzCompositePipe;117sg2d.drawpipe = sQuartzCompositePipe;118sg2d.fillpipe = sQuartzCompositePipe;119sg2d.shapepipe = sQuartzCompositePipe;120sg2d.textpipe = sCocoaTextPipe;121}122123public Rectangle getBounds() {124// gznote: always return a copy, not the rect itself and translate into device space125return new Rectangle(fBounds.x, fBounds.y, fBounds.width, fBounds.height - fBounds.y);126}127128public GraphicsConfiguration getDeviceConfiguration() {129return fConfig;130}131132protected void setBounds(int x, int y, int w, int h) {133fBounds.reshape(x, y, w, y + h);134}135136// START compositing support API137public abstract BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage image);138139public abstract boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR);140141GraphicsConfiguration sDefaultGraphicsConfiguration = null;142143protected BufferedImage getCompositingImage(int w, int h) {144if (sDefaultGraphicsConfiguration == null) {145sDefaultGraphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();146}147148BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);149// clear the image.150clearRect(img, w, h);151return img;152}153154protected BufferedImage getCompositingImageSame(BufferedImage img, int w, int h) {155if ((img == null) || (img.getWidth() != w) || (img.getHeight() != h)) {156img = getCompositingImage(w, h);157}158return img;159}160161BufferedImage sSrcComposite = null;162163public BufferedImage getCompositingSrcImage(int w, int h) {164// <rdar://problem/3720263>. Changed from getCompositingImageBiggerOrSame() to165// getCompositingImageSame(). (vm)166BufferedImage bim = getCompositingImageSame(sSrcComposite, w, h);167sSrcComposite = bim;168return bim;169}170171BufferedImage sDstInComposite = null;172173public BufferedImage getCompositingDstInImage(int w, int h) {174BufferedImage bim = getCompositingImageSame(sDstInComposite, w, h);175sDstInComposite = bim;176return bim;177}178179BufferedImage sDstOutComposite = null;180181public BufferedImage getCompositingDstOutImage(int w, int h) {182BufferedImage bim = getCompositingImageSame(sDstOutComposite, w, h);183sDstOutComposite = bim;184return bim;185}186187public void clearRect(BufferedImage bim, int w, int h) {188Graphics2D g = bim.createGraphics();189g.setComposite(AlphaComposite.Clear);190g.fillRect(0, 0, w, h);191g.dispose();192}193194// END compositing support API195196public void invalidate() {197// always valid198}199200// graphics primitives drawing implementation:201202// certain primitives don't care about all the states (ex. drawing an image needs not involve setting current paint)203@Native static final int kPrimitive = 0;204@Native static final int kImage = 1;205@Native static final int kText = 2;206@Native static final int kCopyArea = 3;207@Native static final int kExternal = 4;208209@Native static final int kLine = 5; // belongs to kPrimitive210@Native static final int kRect = 6; // belongs to kPrimitive211@Native static final int kRoundRect = 7; // belongs to kPrimitive212@Native static final int kOval = 8; // belongs to kPrimitive213@Native static final int kArc = 9; // belongs to kPrimitive214@Native static final int kPolygon = 10; // belongs to kPrimitive215@Native static final int kShape = 11; // belongs to kPrimitive216// static final int kImage = 12; // belongs to kImage217@Native static final int kString = 13; // belongs to kText218@Native static final int kGlyphs = 14; // belongs to kText219@Native static final int kUnicodes = 15; // belongs to kText220// static final int kCopyArea = 16; // belongs to kCopyArea221// static final int kExternal = 17; // belongs to kExternal222223@Native static final int kCommonParameterCount = 1 + 1 + 4 + 4; // type + change flags + color info (type(1) align(1) and224// value(2)) + parameters ((x1, y1, x2, y2) OR (x, y, w, h))225@Native static final int kLineParametersCount = kCommonParameterCount; // kCommonParameterCount226@Native static final int kRectParametersCount = kCommonParameterCount + 1; // kCommonParameterCount + isfill227@Native static final int kRoundRectParametersCount = kCommonParameterCount + 2 + 1; // kCommonParameterCount + arcW + arcH +228// isfill229@Native static final int kOvalParametersCount = kCommonParameterCount + 1; // kCommonParameterCount + isfill230@Native static final int kArcParametersCount = kCommonParameterCount + 2 + 1 + 1;// kCommonParameterCount + startAngle +231// arcAngle + isfill + type232@Native static final int kPolygonParametersCount = 0; // not supported233@Native static final int kShapeParametersCount = 0; // not supported234@Native static final int kImageParametersCount = kCommonParameterCount + 2 + 2 + 4 + 4; // flip horz vert + w&h + src + dst235@Native static final int kStringParametersCount = 0; // not supported236@Native static final int kGlyphsParametersCount = 0; // not supported237@Native static final int kUnicodesParametersCount = 0; // not supported238@Native static final int kPixelParametersCount = 0; // not supported239@Native static final int kExternalParametersCount = 0; // not supported240241// for intParameters242// states info243@Native static final int kChangeFlagIndex = 0; // kBoundsChangedBit | .. | kFontChangedBit244// bounds info245@Native static final int kBoundsXIndex = 1;246@Native static final int kBoundsYIndex = 2;247@Native static final int kBoundsWidthIndex = 3;248@Native static final int kBoundsHeightIndex = 4;249// clip info250@Native static final int kClipStateIndex = 5;251@Native static final int kClipNumTypesIndex = 6;252@Native static final int kClipNumCoordsIndex = 7;253@Native static final int kClipWindingRuleIndex = 8;254@Native static final int kClipXIndex = 9;255@Native static final int kClipYIndex = 10;256@Native static final int kClipWidthIndex = 11;257@Native static final int kClipHeightIndex = 12;258// ctm info259@Native static final int kCTMaIndex = 13;260@Native static final int kCTMbIndex = 14;261@Native static final int kCTMcIndex = 15;262@Native static final int kCTMdIndex = 16;263@Native static final int kCTMtxIndex = 17;264@Native static final int kCTMtyIndex = 18;265// color info266@Native static final int kColorStateIndex = 19; // kColorSimple or kColorGradient or kColorTexture267@Native static final int kColorRGBValueIndex = 20; // if kColorSimple268@Native static final int kColorIndexValueIndex = 21; // if kColorSystem269@Native static final int kColorPointerIndex = 22; //270@Native static final int kColorPointerIndex2 = 23; //271@Native static final int kColorRGBValue1Index = 24; // if kColorGradient272@Native static final int kColorWidthIndex = 25; // if kColorTexture273@Native static final int kColorRGBValue2Index = 26; // if kColorGradient274@Native static final int kColorHeightIndex = 27; // if kColorTexture275@Native static final int kColorIsCyclicIndex = 28; // if kColorGradient (kColorNonCyclic or kColorCyclic)276@Native static final int kColorx1Index = 29;277@Native static final int kColortxIndex = 30;278@Native static final int kColory1Index = 31;279@Native static final int kColortyIndex = 32;280@Native static final int kColorx2Index = 33;281@Native static final int kColorsxIndex = 34;282@Native static final int kColory2Index = 35;283@Native static final int kColorsyIndex = 36;284// composite info285@Native static final int kCompositeRuleIndex = 37; // kCGCompositeClear or ... or kCGCompositeXor286@Native static final int kCompositeValueIndex = 38;287// stroke info288@Native static final int kStrokeJoinIndex = 39; // see BasicStroke.java289@Native static final int kStrokeCapIndex = 40; // see BasicStroke.java290@Native static final int kStrokeWidthIndex = 41;291@Native static final int kStrokeDashPhaseIndex = 42;292@Native static final int kStrokeLimitIndex = 43;293// hints info294@Native static final int kHintsAntialiasIndex = 44;295@Native static final int kHintsTextAntialiasIndex = 45;296@Native static final int kHintsFractionalMetricsIndex = 46;297@Native static final int kHintsRenderingIndex = 47;298@Native static final int kHintsInterpolationIndex = 48;299//gradient info300@Native static final int kRadiusIndex = 49;301302@Native static final int kSizeOfParameters = kRadiusIndex + 1;303304// for objectParameters305@Native static final int kClipCoordinatesIndex = 0;306@Native static final int kClipTypesIndex = 1;307@Native static final int kTextureImageIndex = 2;308@Native static final int kStrokeDashArrayIndex = 3;309@Native static final int kFontIndex = 4;310@Native static final int kFontPaintIndex = 5;311@Native static final int kColorArrayIndex = 6;312@Native static final int kFractionsArrayIndex = 7;313314// possible state changes315@Native static final int kBoundsChangedBit = 1 << 0;316@Native static final int kBoundsNotChangedBit = ~kBoundsChangedBit;317@Native static final int kClipChangedBit = 1 << 1;318@Native static final int kClipNotChangedBit = ~kClipChangedBit;319@Native static final int kCTMChangedBit = 1 << 2;320@Native static final int kCTMNotChangedBit = ~kCTMChangedBit;321@Native static final int kColorChangedBit = 1 << 3;322@Native static final int kColorNotChangedBit = ~kColorChangedBit;323@Native static final int kCompositeChangedBit = 1 << 4;324@Native static final int kCompositeNotChangedBit = ~kCompositeChangedBit;325@Native static final int kStrokeChangedBit = 1 << 5;326@Native static final int kStrokeNotChangedBit = ~kStrokeChangedBit;327@Native static final int kHintsChangedBit = 1 << 6;328@Native static final int kHintsNotChangedBit = ~kHintsChangedBit;329@Native static final int kFontChangedBit = 1 << 7;330@Native static final int kFontNotChangedBit = ~kFontChangedBit;331@Native static final int kEverythingChangedFlag = 0xffffffff;332333// possible color states334@Native static final int kColorSimple = 0;335@Native static final int kColorSystem = 1;336@Native static final int kColorGradient = 2;337@Native static final int kColorTexture = 3;338@Native static final int kColorLinearGradient = 4;339@Native static final int kColorRadialGradient = 5;340341// possible gradient color states342@Native static final int kColorNonCyclic = 0;343@Native static final int kColorCyclic = 1;344345// possible clip states346@Native static final int kClipRect = 0;347@Native static final int kClipShape = 1;348349static int getRendererTypeForPrimitive(int primitiveType) {350switch (primitiveType) {351case kImage:352return kImage;353case kCopyArea:354return kCopyArea;355case kExternal:356return kExternal;357case kString:358case kGlyphs:359case kUnicodes:360return kText;361default:362return kPrimitive;363}364}365366int fChangeFlag;367protected ByteBuffer fGraphicsStates = null;368IntBuffer fGraphicsStatesInt = null;369FloatBuffer fGraphicsStatesFloat = null;370LongBuffer fGraphicsStatesLong = null;371protected Object[] fGraphicsStatesObject = null;372373Rectangle userBounds = new Rectangle();374float lastUserX = 0;375float lastUserY = 0;376float lastUserW = 0;377float lastUserH = 0;378379void setUserBounds(SunGraphics2D sg2d, int x, int y, int width, int height) {380if ((lastUserX != x) || (lastUserY != y) || (lastUserW != width) || (lastUserH != height)) {381lastUserX = x;382lastUserY = y;383lastUserW = width;384lastUserH = height;385386this.fGraphicsStatesInt.put(kBoundsXIndex, x);387this.fGraphicsStatesInt.put(kBoundsYIndex, y);388this.fGraphicsStatesInt.put(kBoundsWidthIndex, width);389this.fGraphicsStatesInt.put(kBoundsHeightIndex, height);390391userBounds.setBounds(x, y, width, height);392393this.fChangeFlag = (this.fChangeFlag | kBoundsChangedBit);394} else {395this.fChangeFlag = (this.fChangeFlag & kBoundsNotChangedBit);396}397}398399static ByteBuffer getBufferOfSize(int size) {400ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4);401buffer.order(ByteOrder.nativeOrder());402return buffer;403}404405FloatBuffer clipCoordinatesArray = null;406IntBuffer clipTypesArray = null;407Shape lastClipShape = null;408float lastClipX = 0;409float lastClipY = 0;410float lastClipW = 0;411float lastClipH = 0;412413void setupClip(SunGraphics2D sg2d) {414switch (sg2d.clipState) {415case SunGraphics2D.CLIP_DEVICE:416case SunGraphics2D.CLIP_RECTANGULAR: {417Region clip = sg2d.getCompClip();418float x = clip.getLoX();419float y = clip.getLoY();420float w = clip.getWidth();421float h = clip.getHeight();422if ((this.fGraphicsStatesInt.get(kClipStateIndex) != kClipRect) ||423(x != lastClipX) ||424(y != lastClipY) ||425(w != lastClipW) ||426(h != lastClipH)) {427this.fGraphicsStatesFloat.put(kClipXIndex, x);428this.fGraphicsStatesFloat.put(kClipYIndex, y);429this.fGraphicsStatesFloat.put(kClipWidthIndex, w);430this.fGraphicsStatesFloat.put(kClipHeightIndex, h);431432lastClipX = x;433lastClipY = y;434lastClipW = w;435lastClipH = h;436437this.fChangeFlag = (this.fChangeFlag | kClipChangedBit);438} else {439this.fChangeFlag = (this.fChangeFlag & kClipNotChangedBit);440}441this.fGraphicsStatesInt.put(kClipStateIndex, kClipRect);442break;443}444case SunGraphics2D.CLIP_SHAPE: {445// if (lastClipShape != sg2d.usrClip) shapes are mutable!, and doing "equals" traverses all446// the coordinates, so we might as well do all of it anyhow447lastClipShape = sg2d.usrClip;448449GeneralPath gp = null;450451if (sg2d.usrClip instanceof GeneralPath) {452gp = (GeneralPath) sg2d.usrClip;453} else {454gp = new GeneralPath(sg2d.usrClip);455}456457int shapeLength = getPathLength(gp);458459if ((clipCoordinatesArray == null) || (clipCoordinatesArray.capacity() < (shapeLength * 6))) {460clipCoordinatesArray = getBufferOfSize(shapeLength * 6).asFloatBuffer(); // segment can have a461// max of 6 coordinates462}463if ((clipTypesArray == null) || (clipTypesArray.capacity() < shapeLength)) {464clipTypesArray = getBufferOfSize(shapeLength).asIntBuffer();465}466467int windingRule = getPathCoordinates(gp, clipCoordinatesArray, clipTypesArray);468469this.fGraphicsStatesInt.put(kClipNumTypesIndex, clipTypesArray.position());470this.fGraphicsStatesInt.put(kClipNumCoordsIndex, clipCoordinatesArray.position());471this.fGraphicsStatesInt.put(kClipWindingRuleIndex, windingRule);472this.fGraphicsStatesObject[kClipTypesIndex] = clipTypesArray;473this.fGraphicsStatesObject[kClipCoordinatesIndex] = clipCoordinatesArray;474475this.fChangeFlag = (this.fChangeFlag | kClipChangedBit);476this.fGraphicsStatesInt.put(kClipStateIndex, kClipShape);477break;478}479}480481}482483final double[] lastCTM = new double[6];484float lastCTMa = 0;485float lastCTMb = 0;486float lastCTMc = 0;487float lastCTMd = 0;488float lastCTMtx = 0;489float lastCTMty = 0;490491void setupTransform(SunGraphics2D sg2d) {492sg2d.transform.getMatrix(lastCTM);493494float a = (float) lastCTM[0];495float b = (float) lastCTM[1];496float c = (float) lastCTM[2];497float d = (float) lastCTM[3];498float tx = (float) lastCTM[4];499float ty = (float) lastCTM[5];500if (tx != lastCTMtx ||501ty != lastCTMty ||502a != lastCTMa ||503b != lastCTMb ||504c != lastCTMc ||505d != lastCTMd) {506this.fGraphicsStatesFloat.put(kCTMaIndex, a);507this.fGraphicsStatesFloat.put(kCTMbIndex, b);508this.fGraphicsStatesFloat.put(kCTMcIndex, c);509this.fGraphicsStatesFloat.put(kCTMdIndex, d);510this.fGraphicsStatesFloat.put(kCTMtxIndex, tx);511this.fGraphicsStatesFloat.put(kCTMtyIndex, ty);512513lastCTMa = a;514lastCTMb = b;515lastCTMc = c;516lastCTMd = d;517lastCTMtx = tx;518lastCTMty = ty;519520this.fChangeFlag = (this.fChangeFlag | kCTMChangedBit);521} else {522this.fChangeFlag = (this.fChangeFlag & kCTMNotChangedBit);523}524}525526static AffineTransform sIdentityMatrix = new AffineTransform();527Paint lastPaint = null;528long lastPaintPtr = 0;529int lastPaintRGB = 0;530int lastPaintIndex = 0;531BufferedImage texturePaintImage = null;532533void setGradientViaRasterPath(SunGraphics2D sg2d) {534if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) {535PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints());536WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height));537ColorModel cm = context.getColorModel();538texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);539540this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);541this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());542this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());543this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX());544this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY());545this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f);546this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f);547this.fGraphicsStatesObject[kTextureImageIndex] = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage);548549this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);550} else {551this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);552}553}554555void setupPaint(SunGraphics2D sg2d, int x, int y, int w, int h) {556if (sg2d.paint instanceof SystemColor) {557SystemColor color = (SystemColor) sg2d.paint;558int index = color.hashCode(); // depends on Color.java hashCode implementation! (returns "value" of color)559if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorSystem) || (index != this.lastPaintIndex)) {560this.lastPaintIndex = index;561562this.fGraphicsStatesInt.put(kColorStateIndex, kColorSystem);563this.fGraphicsStatesInt.put(kColorIndexValueIndex, index);564565this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);566} else {567this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);568}569} else if (sg2d.paint instanceof Color) {570Color color = (Color) sg2d.paint;571int rgb = color.getRGB();572if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorSimple) || (rgb != this.lastPaintRGB)) {573this.lastPaintRGB = rgb;574575this.fGraphicsStatesInt.put(kColorStateIndex, kColorSimple);576this.fGraphicsStatesInt.put(kColorRGBValueIndex, rgb);577578this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);579} else {580this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);581}582} else if (sg2d.paint instanceof GradientPaint) {583if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorGradient) || (lastPaint != sg2d.paint)) {584GradientPaint color = (GradientPaint) sg2d.paint;585this.fGraphicsStatesInt.put(kColorStateIndex, kColorGradient);586this.fGraphicsStatesInt.put(kColorRGBValue1Index, color.getColor1().getRGB());587this.fGraphicsStatesInt.put(kColorRGBValue2Index, color.getColor2().getRGB());588this.fGraphicsStatesInt.put(kColorIsCyclicIndex, (color.isCyclic()) ? kColorCyclic : kColorNonCyclic);589Point2D p = color.getPoint1();590this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());591this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());592p = color.getPoint2();593this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());594this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());595596this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);597} else {598this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);599}600} else if (sg2d.paint instanceof LinearGradientPaint) {601LinearGradientPaint color = (LinearGradientPaint) sg2d.paint;602if (color.getCycleMethod() == LinearGradientPaint.CycleMethod.NO_CYCLE) {603if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorLinearGradient) || (lastPaint != sg2d.paint)) {604605this.fGraphicsStatesInt.put(kColorStateIndex, kColorLinearGradient);606int numColor = color.getColors().length;607int colorArray[] = new int[numColor];608for (int i = 0; i < numColor; i++) {609colorArray[i] = color.getColors()[i].getRGB();610}611this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;612613int numFractions = color.getFractions().length;614float fractionArray[] = new float[numFractions];615for (int i = 0; i < numFractions; i++) {616fractionArray[i] = color.getFractions()[i];617}618this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();619Point2D p = color.getStartPoint();620this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());621this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());622p = color.getEndPoint();623this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());624this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());625626this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);627} else {628this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);629}630} else {631setGradientViaRasterPath(sg2d);632}633} else if (sg2d.paint instanceof RadialGradientPaint) {634RadialGradientPaint color = (RadialGradientPaint) sg2d.paint;635if (color.getCycleMethod() == RadialGradientPaint.CycleMethod.NO_CYCLE) {636if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorRadialGradient) || (lastPaint != sg2d.paint)) {637638this.fGraphicsStatesInt.put(kColorStateIndex, kColorRadialGradient);639int numColor = color.getColors().length;640int colorArray[] = new int[numColor];641for (int i = 0; i < numColor; i++) {642colorArray[i] = color.getColors()[i].getRGB();643}644this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;645646int numStops = color.getFractions().length;647float stopsArray[] = new float[numStops];648for (int i = 0; i < numStops; i++) {649stopsArray[i] = color.getFractions()[i];650}651this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();652Point2D p = color.getFocusPoint();653this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());654this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());655p = color.getCenterPoint();656this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());657this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());658this.fGraphicsStatesFloat.put(kRadiusIndex, color.getRadius());659660this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);661} else {662this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);663}664} else {665setGradientViaRasterPath(sg2d);666}667} else if (sg2d.paint instanceof TexturePaint) {668if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint)) {669TexturePaint color = (TexturePaint) sg2d.paint;670this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);671texturePaintImage = color.getImage();672SurfaceData textureSurfaceData = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage);673this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());674this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());675Rectangle2D anchor = color.getAnchorRect();676this.fGraphicsStatesFloat.put(kColortxIndex, (float) anchor.getX());677this.fGraphicsStatesFloat.put(kColortyIndex, (float) anchor.getY());678this.fGraphicsStatesFloat.put(kColorsxIndex, (float) (anchor.getWidth() / texturePaintImage.getWidth()));679this.fGraphicsStatesFloat.put(kColorsyIndex, (float) (anchor.getHeight() / texturePaintImage.getHeight()));680this.fGraphicsStatesObject[kTextureImageIndex] = textureSurfaceData;681682this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);683} else {684this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);685}686} else {687setGradientViaRasterPath(sg2d);688}689lastPaint = sg2d.paint;690}691692Composite lastComposite;693int lastCompositeAlphaRule = 0;694float lastCompositeAlphaValue = 0;695696void setupComposite(SunGraphics2D sg2d) {697Composite composite = sg2d.composite;698699if (lastComposite != composite) {700lastComposite = composite;701702// For composite state COMP_ISCOPY, COMP_XOR or COMP_CUSTOM set alpha compositor to COPY:703int alphaRule = AlphaComposite.SRC_OVER;704float alphaValue = 1.0f;705706// For composite state COMP_ISCOPY composite could be null. If it's not (or composite state == COMP_ALPHA)707// get alpha compositor's values:708if ((sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) && (composite != null)) {709AlphaComposite alphaComposite = (AlphaComposite) composite;710alphaRule = alphaComposite.getRule();711alphaValue = alphaComposite.getAlpha();712}713714// 2-17-03 VL: [Radar 3174922]715// For COMP_XOR and COMP_CUSTOM compositing modes we should be setting alphaRule = AlphaComposite.SRC716// which should map to kCGCompositeCopy.717718if ((lastCompositeAlphaRule != alphaRule) || (lastCompositeAlphaValue != alphaValue)) {719this.fGraphicsStatesInt.put(kCompositeRuleIndex, alphaRule);720this.fGraphicsStatesFloat.put(kCompositeValueIndex, alphaValue);721722lastCompositeAlphaRule = alphaRule;723lastCompositeAlphaValue = alphaValue;724725this.fChangeFlag = (this.fChangeFlag | kCompositeChangedBit);726} else {727this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);728}729} else {730this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);731}732}733734BasicStroke lastStroke = null;735static BasicStroke defaultBasicStroke = new BasicStroke();736737void setupStroke(SunGraphics2D sg2d) {738BasicStroke stroke = defaultBasicStroke;739740if (sg2d.stroke instanceof BasicStroke) {741stroke = (BasicStroke) sg2d.stroke;742}743744if (lastStroke != stroke) {745this.fGraphicsStatesObject[kStrokeDashArrayIndex] = stroke.getDashArray();746this.fGraphicsStatesFloat.put(kStrokeDashPhaseIndex, stroke.getDashPhase());747this.fGraphicsStatesInt.put(kStrokeCapIndex, stroke.getEndCap());748this.fGraphicsStatesInt.put(kStrokeJoinIndex, stroke.getLineJoin());749this.fGraphicsStatesFloat.put(kStrokeWidthIndex, stroke.getLineWidth());750this.fGraphicsStatesFloat.put(kStrokeLimitIndex, stroke.getMiterLimit());751752this.fChangeFlag = (this.fChangeFlag | kStrokeChangedBit);753754lastStroke = stroke;755} else {756this.fChangeFlag = (this.fChangeFlag & kStrokeNotChangedBit);757}758}759760Font lastFont;761762void setupFont(Font font, Paint paint) {763if (font == null) { return; }764765// We have to setup the kFontPaintIndex if we have changed the color so we added the last766// test to see if the color has changed - needed for complex strings767// see Radar 3368674768if ((font != lastFont) || ((this.fChangeFlag & kColorChangedBit) != 0)) {769this.fGraphicsStatesObject[kFontIndex] = font;770this.fGraphicsStatesObject[kFontPaintIndex] = paint;771772this.fChangeFlag = (this.fChangeFlag | kFontChangedBit);773774lastFont = font;775} else {776this.fChangeFlag = (this.fChangeFlag & kFontNotChangedBit);777}778}779780void setupRenderingHints(SunGraphics2D sg2d) {781boolean hintsChanged = false;782783// Significant for draw, fill, text, and image ops:784int antialiasHint = sg2d.antialiasHint;785if (this.fGraphicsStatesInt.get(kHintsAntialiasIndex) != antialiasHint) {786this.fGraphicsStatesInt.put(kHintsAntialiasIndex, antialiasHint);787hintsChanged = true;788}789790// Significant only for text ops:791int textAntialiasHint = sg2d.textAntialiasHint;792if (this.fGraphicsStatesInt.get(kHintsTextAntialiasIndex) != textAntialiasHint) {793this.fGraphicsStatesInt.put(kHintsTextAntialiasIndex, textAntialiasHint);794hintsChanged = true;795}796797// Significant only for text ops:798int fractionalMetricsHint = sg2d.fractionalMetricsHint;799if (this.fGraphicsStatesInt.get(kHintsFractionalMetricsIndex) != fractionalMetricsHint) {800this.fGraphicsStatesInt.put(kHintsFractionalMetricsIndex, fractionalMetricsHint);801hintsChanged = true;802}803804// Significant only for image ops:805int renderHint = sg2d.renderHint;806if (this.fGraphicsStatesInt.get(kHintsRenderingIndex) != renderHint) {807this.fGraphicsStatesInt.put(kHintsRenderingIndex, renderHint);808hintsChanged = true;809}810811// Significant only for image ops:812Object hintValue = sg2d.getRenderingHint(RenderingHints.KEY_INTERPOLATION);813int interpolationHint = (hintValue != null ? ((SunHints.Value) hintValue).getIndex() : -1);814if (this.fGraphicsStatesInt.get(kHintsInterpolationIndex) != interpolationHint) {815this.fGraphicsStatesInt.put(kHintsInterpolationIndex, interpolationHint);816hintsChanged = true;817}818819if (hintsChanged) {820this.fChangeFlag = (this.fChangeFlag | kHintsChangedBit);821} else {822this.fChangeFlag = (this.fChangeFlag & kHintsNotChangedBit);823}824}825826SunGraphics2D sg2dCurrent = null;827Thread threadCurrent = null;828829void setupGraphicsState(SunGraphics2D sg2d, int primitiveType) {830setupGraphicsState(sg2d, primitiveType, sg2d.font, 0, 0, fBounds.width, fBounds.height); // deviceBounds into userBounds831}832833void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, int x, int y, int w, int h) {834setupGraphicsState(sg2d, primitiveType, sg2d.font, x, y, w, h);835}836837// the method below is overriden by CPeerSurface to check the last peer used to draw838// if the peer changed we finish lazy drawing839void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, Font font, int x, int y, int w, int h) {840this.fChangeFlag = 0;841842setUserBounds(sg2d, x, y, w, h);843844Thread thread = Thread.currentThread();845if ((this.sg2dCurrent != sg2d) || (this.threadCurrent != thread)) {846this.sg2dCurrent = sg2d;847this.threadCurrent = thread;848849setupClip(sg2d);850setupTransform(sg2d);851setupPaint(sg2d, x, y, w, h);852setupComposite(sg2d);853setupStroke(sg2d);854setupFont(font, sg2d.paint);855setupRenderingHints(sg2d);856857this.fChangeFlag = kEverythingChangedFlag;858} else {859int rendererType = getRendererTypeForPrimitive(primitiveType);860861setupClip(sg2d);862setupTransform(sg2d);863864if (rendererType != kCopyArea) {865setupComposite(sg2d);866setupRenderingHints(sg2d);867868if ((rendererType != kImage)) {869setupPaint(sg2d, x, y, w, h);870setupStroke(sg2d);871}872if (rendererType != kPrimitive) {873setupFont(font, sg2d.paint);874}875876}877}878879this.fGraphicsStatesInt.put(kChangeFlagIndex, this.fChangeFlag);880}881882boolean isCustomPaint(SunGraphics2D sg2d) {883if ((sg2d.paint instanceof Color) || (sg2d.paint instanceof SystemColor) || (sg2d.paint instanceof GradientPaint) || (sg2d.paint instanceof TexturePaint)) { return false; }884885return true;886}887888final float[] segmentCoordinatesArray = new float[6];889890int getPathLength(GeneralPath gp) {891int length = 0;892893PathIterator pi = gp.getPathIterator(null);894while (pi.isDone() == false) {895pi.next();896length++;897}898899return length;900}901902int getPathCoordinates(GeneralPath gp, FloatBuffer coordinates, IntBuffer types) {903// System.err.println("getPathCoordinates");904boolean skip = false;905906coordinates.clear();907types.clear();908909int type;910911PathIterator pi = gp.getPathIterator(null);912while (pi.isDone() == false) {913skip = false;914type = pi.currentSegment(segmentCoordinatesArray);915916switch (type) {917case PathIterator.SEG_MOVETO:918// System.err.println(" SEG_MOVETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");919if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&920segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {921coordinates.put(segmentCoordinatesArray[0]);922coordinates.put(segmentCoordinatesArray[1]);923} else {924skip = true;925}926break;927case PathIterator.SEG_LINETO:928// System.err.println(" SEG_LINETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");929if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&930segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {931coordinates.put(segmentCoordinatesArray[0]);932coordinates.put(segmentCoordinatesArray[1]);933} else {934skip = true;935}936break;937case PathIterator.SEG_QUADTO:938// System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+")");939if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&940segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&941segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&942segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND) {943coordinates.put(segmentCoordinatesArray[0]);944coordinates.put(segmentCoordinatesArray[1]);945coordinates.put(segmentCoordinatesArray[2]);946coordinates.put(segmentCoordinatesArray[3]);947} else {948skip = true;949}950break;951case PathIterator.SEG_CUBICTO:952// System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+"), ("+segmentCoordinatesArray[4]+", "+segmentCoordinatesArray[5]+")");953if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&954segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&955segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&956segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND &&957segmentCoordinatesArray[4] < UPPER_BND && segmentCoordinatesArray[4] > LOWER_BND &&958segmentCoordinatesArray[5] < UPPER_BND && segmentCoordinatesArray[5] > LOWER_BND) {959coordinates.put(segmentCoordinatesArray[0]);960coordinates.put(segmentCoordinatesArray[1]);961coordinates.put(segmentCoordinatesArray[2]);962coordinates.put(segmentCoordinatesArray[3]);963coordinates.put(segmentCoordinatesArray[4]);964coordinates.put(segmentCoordinatesArray[5]);965} else {966skip = true;967}968break;969case PathIterator.SEG_CLOSE:970// System.err.println(" SEG_CLOSE");971break;972}973974if (!skip) {975types.put(type);976}977978pi.next();979}980981return pi.getWindingRule();982}983984public void doLine(CRenderer renderer, SunGraphics2D sg2d, float x1, float y1, float x2, float y2) {985// System.err.println("-- doLine x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2+" paint="+sg2d.paint);986setupGraphicsState(sg2d, kLine, sg2d.font, 0, 0, fBounds.width, fBounds.height);987renderer.doLine(this, x1, y1, x2, y2);988}989990public void doRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {991// System.err.println("-- doRect x="+x+" y="+y+" w="+width+" h="+height+" isfill="+isfill+" paint="+sg2d.paint);992if ((isfill) && (isCustomPaint(sg2d))) {993setupGraphicsState(sg2d, kRect, (int) x, (int) y, (int) width, (int) height);994} else {995setupGraphicsState(sg2d, kRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);996}997renderer.doRect(this, x, y, width, height, isfill);998}9991000public void doRoundRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float arcW, float arcH, boolean isfill) {1001// System.err.println("--- doRoundRect");1002if ((isfill) && (isCustomPaint(sg2d))) {1003setupGraphicsState(sg2d, kRoundRect, (int) x, (int) y, (int) width, (int) height);1004} else {1005setupGraphicsState(sg2d, kRoundRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);1006}1007renderer.doRoundRect(this, x, y, width, height, arcW, arcH, isfill);1008}10091010public void doOval(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {1011// System.err.println("--- doOval");1012if ((isfill) && (isCustomPaint(sg2d))) {1013setupGraphicsState(sg2d, kOval, (int) x, (int) y, (int) width, (int) height);1014} else {1015setupGraphicsState(sg2d, kOval, sg2d.font, 0, 0, fBounds.width, fBounds.height);1016}1017renderer.doOval(this, x, y, width, height, isfill);1018}10191020public void doArc(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float startAngle, float arcAngle, int type, boolean isfill) {1021// System.err.println("--- doArc");1022if ((isfill) && (isCustomPaint(sg2d))) {1023setupGraphicsState(sg2d, kArc, (int) x, (int) y, (int) width, (int) height);1024} else {1025setupGraphicsState(sg2d, kArc, sg2d.font, 0, 0, fBounds.width, fBounds.height);1026}10271028renderer.doArc(this, x, y, width, height, startAngle, arcAngle, type, isfill);1029}10301031public void doPolygon(CRenderer renderer, SunGraphics2D sg2d, int xpoints[], int ypoints[], int npoints, boolean ispolygon, boolean isfill) {1032// System.err.println("--- doPolygon");10331034if ((isfill) && (isCustomPaint(sg2d))) {1035int minx = xpoints[0];1036int miny = ypoints[0];1037int maxx = minx;1038int maxy = miny;1039for (int i = 1; i < npoints; i++) {1040int x = xpoints[i];1041if (x < minx) {1042minx = x;1043} else if (x > maxx) {1044maxx = x;1045}10461047int y = ypoints[i];1048if (y < miny) {1049miny = y;1050} else if (y > maxy) {1051maxy = y;1052}1053}1054setupGraphicsState(sg2d, kPolygon, minx, miny, maxx - minx, maxy - miny);1055} else {1056setupGraphicsState(sg2d, kPolygon, sg2d.font, 0, 0, fBounds.width, fBounds.height);1057}1058renderer.doPoly(this, xpoints, ypoints, npoints, ispolygon, isfill);1059}10601061FloatBuffer shapeCoordinatesArray = null;1062IntBuffer shapeTypesArray = null;10631064public void drawfillShape(CRenderer renderer, SunGraphics2D sg2d, GeneralPath gp, boolean isfill, boolean shouldApplyOffset) {1065// System.err.println("--- drawfillShape");10661067if ((isfill) && (isCustomPaint(sg2d))) {1068Rectangle bounds = gp.getBounds();1069setupGraphicsState(sg2d, kShape, bounds.x, bounds.y, bounds.width, bounds.height);1070} else {1071setupGraphicsState(sg2d, kShape, sg2d.font, 0, 0, fBounds.width, fBounds.height);1072}10731074int shapeLength = getPathLength(gp);10751076if ((shapeCoordinatesArray == null) || (shapeCoordinatesArray.capacity() < (shapeLength * 6))) {1077shapeCoordinatesArray = getBufferOfSize(shapeLength * 6).asFloatBuffer(); // segment can have a max of 61078// coordinates1079}1080if ((shapeTypesArray == null) || (shapeTypesArray.capacity() < shapeLength)) {1081shapeTypesArray = getBufferOfSize(shapeLength).asIntBuffer();1082}10831084int windingRule = getPathCoordinates(gp, shapeCoordinatesArray, shapeTypesArray);10851086renderer.doShape(this, shapeLength, shapeCoordinatesArray, shapeTypesArray, windingRule, isfill, shouldApplyOffset);1087}10881089public 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) {1090// System.err.println("--- blitImage sx="+sx+", sy="+sy+", sw="+sw+", sh="+sh+", img="+img);1091OSXOffScreenSurfaceData osxsd = (OSXOffScreenSurfaceData) img;1092synchronized (osxsd.getLockObject()) {1093int w = osxsd.bim.getWidth();1094int h = osxsd.bim.getHeight();10951096// the image itself can have outstanding graphics primitives that might need to be flushed1097setupGraphicsState(sg2d, kImage, sg2d.font, 0, 0, fBounds.width, fBounds.height);10981099// 04/06/04 cmc: radr://3612381 Graphics.drawImage ignores bgcolor parameter1100if (bgColor != null) {1101img = osxsd.getCopyWithBgColor(bgColor);1102}11031104renderer.doImage(this, img, fliph, flipv, w, h, sx, sy, sw, sh, dx, dy, dw, dh);1105}1106}11071108public interface CGContextDrawable {1109public void drawIntoCGContext(final long cgContext);1110}11111112public void drawString(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, String str, double x, double y) {1113// System.err.println("--- drawString str=\""+str+"\"");1114// see <rdar://problem/3825795>. We don't want to call anything if the string is empty!1115if (str.length() == 0) { return; }11161117setupGraphicsState(sg2d, kString, sg2d.font, 0, 0, fBounds.width, fBounds.height);1118renderer.doDrawString(this, nativeStrikePtr, str, x, y);1119}11201121public void drawGlyphs(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, GlyphVector gv, float x, float y) {1122// System.err.println("--- drawGlyphs");1123setupGraphicsState(sg2d, kGlyphs, gv.getFont(), 0, 0, fBounds.width, fBounds.height);1124renderer.doDrawGlyphs(this, nativeStrikePtr, gv, x, y);1125}11261127public void drawUnicodes(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, char unicodes[], int offset, int length, float x, float y) {1128// System.err.println("--- drawUnicodes "+(new String(unicodes, offset, length)));1129setupGraphicsState(sg2d, kUnicodes, sg2d.font, 0, 0, fBounds.width, fBounds.height);1130if (length == 1) {1131renderer.doOneUnicode(this, nativeStrikePtr, unicodes[offset], x, y);1132} else {1133renderer.doUnicodes(this, nativeStrikePtr, unicodes, offset, length, x, y);1134}1135}11361137// used by copyArea:11381139Rectangle srcCopyAreaRect = new Rectangle();1140Rectangle dstCopyAreaRect = new Rectangle();1141Rectangle finalCopyAreaRect = new Rectangle();1142Rectangle copyAreaBounds = new Rectangle();11431144void intersection(Rectangle r1, Rectangle r2, Rectangle r3) {1145// this code is taken from Rectangle.java (modified to put results in r3)1146int tx1 = r1.x;1147int ty1 = r1.y;1148long tx2 = tx1 + r1.width;1149long ty2 = ty1 + r1.height;11501151int rx1 = r2.x;1152int ry1 = r2.y;1153long rx2 = rx1 + r2.width;1154long ry2 = ry1 + r2.height;11551156if (tx1 < rx1) tx1 = rx1;1157if (ty1 < ry1) ty1 = ry1;1158if (tx2 > rx2) tx2 = rx2;1159if (ty2 > ry2) ty2 = ry2;11601161tx2 -= tx1;1162ty2 -= ty1;11631164// tx2,ty2 will never overflow (they will never be1165// larger than the smallest of the two source w,h)1166// they might underflow, though...1167if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;1168if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;11691170r3.setBounds(tx1, ty1, (int) tx2, (int) ty2);1171}11721173/**1174* Clips the copy area to the heavywieght bounds and returns the cliped rectangle. The tricky part here is the the1175* passed arguments x, y are in the coordinate space of the sg2d/lightweight comp. In order to do the clipping we1176* translate them to the coordinate space of the surface, and the returned clipped rectangle is in the coordinate1177* space of the surface.1178*/1179protected Rectangle clipCopyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) {1180// we need to clip against the heavyweight bounds1181copyAreaBounds.setBounds(sg2d.devClip.getLoX(), sg2d.devClip.getLoY(), sg2d.devClip.getWidth(), sg2d.devClip.getHeight());11821183// put src rect into surface coordinate space1184x += sg2d.transX;1185y += sg2d.transY;11861187// clip src rect1188srcCopyAreaRect.setBounds(x, y, w, h);1189intersection(srcCopyAreaRect, copyAreaBounds, srcCopyAreaRect);1190if ((srcCopyAreaRect.width <= 0) || (srcCopyAreaRect.height <= 0)) {1191// src rect outside bounds1192return null;1193}11941195// clip dst rect1196dstCopyAreaRect.setBounds(srcCopyAreaRect.x + dx, srcCopyAreaRect.y + dy, srcCopyAreaRect.width, srcCopyAreaRect.height);1197intersection(dstCopyAreaRect, copyAreaBounds, dstCopyAreaRect);1198if ((dstCopyAreaRect.width <= 0) || (dstCopyAreaRect.height <= 0)) {1199// dst rect outside clip1200return null;1201}12021203x = dstCopyAreaRect.x - dx;1204y = dstCopyAreaRect.y - dy;1205w = dstCopyAreaRect.width;1206h = dstCopyAreaRect.height;12071208finalCopyAreaRect.setBounds(x, y, w, h);12091210return finalCopyAreaRect;1211}12121213// <rdar://3785539> We only need to mark dirty on screen surfaces. This method is1214// marked as protected and it is intended for subclasses to override if they need to1215// be notified when the surface is dirtied. See CPeerSurfaceData.markDirty() for implementation.1216// We don't do anything for buffered images.1217protected void markDirty(boolean markAsDirty) {1218// do nothing by default1219}12201221// LazyDrawing optimization implementation:12221223@Override1224public boolean canRenderLCDText(SunGraphics2D sg2d) {1225if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&1226sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&1227sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&1228// sg2d.surfaceData.getTransparency() == Transparency.OPAQUE &&1229// This last test is a workaround until we fix loop selection1230// in the pipe validation1231sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { return true; }1232return false; /* for now - in the future we may want to search */1233}12341235public static boolean IsSimpleColor(Object c) {1236return ((c instanceof Color) || (c instanceof SystemColor) || (c instanceof javax.swing.plaf.ColorUIResource));1237}12381239static {1240if ((kColorPointerIndex % 2) != 0) {1241System.err.println("kColorPointerIndex=" + kColorPointerIndex + " is NOT aligned for 64 bit");1242System.exit(0);1243}1244}1245}124612471248