4632N/A/*
4632N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/Apackage sun.java2d;
4632N/A
4632N/Aimport java.awt.*;
4632N/Aimport java.awt.font.*;
4632N/Aimport java.awt.geom.*;
4632N/Aimport java.awt.image.*;
4632N/Aimport java.nio.*;
4632N/A
4632N/Aimport sun.awt.*;
4632N/Aimport sun.awt.image.*;
4632N/Aimport sun.java2d.loops.*;
4632N/Aimport sun.java2d.pipe.*;
4632N/Aimport sun.lwawt.macosx.*;
4632N/A
4632N/A/*
4632N/A * This is the SurfaceData for a CGContextRef.
4632N/A */
4632N/Apublic abstract class OSXSurfaceData extends BufImgSurfaceData {
4632N/A final static float UPPER_BND = Float.MAX_VALUE / 2.0f;
4632N/A final static float LOWER_BND = -UPPER_BND;
4632N/A
4632N/A protected static CRenderer sQuartzPipe = null;
4632N/A protected static CTextPipe sCocoaTextPipe = null;
4632N/A protected static CompositeCRenderer sQuartzCompositePipe = null;
4632N/A
4632N/A private GraphicsConfiguration fConfig;
4632N/A private Rectangle fBounds; // bounds in user coordinates
4632N/A
4632N/A static {
4632N/A sQuartzPipe = new CRenderer(); // Creates the singleton quartz pipe.
4632N/A }
4632N/A
4632N/A // NOTE: Any subclasses must eventually call QuartzSurfaceData_InitOps in OSXSurfaceData.h
4632N/A // This sets up the native side for the SurfaceData, and is required.
4632N/A public OSXSurfaceData(SurfaceType sType, ColorModel cm) {
4632N/A this(sType, cm, null, new Rectangle());
4632N/A }
4632N/A
4632N/A public OSXSurfaceData(SurfaceType sType, ColorModel cm, GraphicsConfiguration config, Rectangle bounds) {
4632N/A super(sType, cm);
4632N/A
4632N/A this.fConfig = config;
4632N/A
4632N/A this.fBounds = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.y + bounds.height);
4632N/A
4632N/A this.fGraphicsStates = getBufferOfSize(kSizeOfParameters);
4632N/A this.fGraphicsStatesInt = this.fGraphicsStates.asIntBuffer();
4632N/A this.fGraphicsStatesFloat = this.fGraphicsStates.asFloatBuffer();
4632N/A this.fGraphicsStatesLong = this.fGraphicsStates.asLongBuffer();
4632N/A this.fGraphicsStatesObject = new Object[6]; // clip coordinates + clip types + texture paint image + stroke dash
4632N/A // array + font + font paint
4632N/A
4632N/A // NOTE: All access to the DrawingQueue comes through this OSXSurfaceData instance. Therefore
4632N/A // every instance method of OSXSurfaceData that accesses the fDrawingQueue is synchronized.
4632N/A
4632N/A // Thread.dumpStack();
4632N/A }
4632N/A
4632N/A public void validatePipe(SunGraphics2D sg2d) {
4632N/A
4632N/A if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
4632N/A if (sCocoaTextPipe == null) {
4632N/A sCocoaTextPipe = new CTextPipe();
4632N/A }
4632N/A
4632N/A sg2d.imagepipe = sQuartzPipe;
4632N/A sg2d.drawpipe = sQuartzPipe;
4632N/A sg2d.fillpipe = sQuartzPipe;
4632N/A sg2d.shapepipe = sQuartzPipe;
4632N/A sg2d.textpipe = sCocoaTextPipe;
4632N/A } else {
4632N/A setPipesToQuartzComposite(sg2d);
4632N/A }
4632N/A }
4632N/A
4632N/A protected void setPipesToQuartzComposite(SunGraphics2D sg2d) {
4632N/A if (sQuartzCompositePipe == null) {
4632N/A sQuartzCompositePipe = new CompositeCRenderer();
4632N/A }
4632N/A
4632N/A if (sCocoaTextPipe == null) {
4632N/A sCocoaTextPipe = new CTextPipe();
4632N/A }
4632N/A
4632N/A sg2d.imagepipe = sQuartzCompositePipe;
4632N/A sg2d.drawpipe = sQuartzCompositePipe;
4632N/A sg2d.fillpipe = sQuartzCompositePipe;
4632N/A sg2d.shapepipe = sQuartzCompositePipe;
4632N/A sg2d.textpipe = sCocoaTextPipe;
4632N/A }
4632N/A
4632N/A public Rectangle getBounds() {
4632N/A // gznote: always return a copy, not the rect itself and translate into device space
4632N/A return new Rectangle(fBounds.x, fBounds.y, fBounds.width, fBounds.height - fBounds.y);
4632N/A }
4632N/A
4632N/A public GraphicsConfiguration getDeviceConfiguration() {
4632N/A return fConfig;
4632N/A }
4632N/A
4632N/A protected void setBounds(int x, int y, int w, int h) {
4632N/A fBounds.reshape(x, y, w, y + h);
4632N/A }
4632N/A
4632N/A // START compositing support API
4632N/A public abstract BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage image);
4632N/A
4632N/A public abstract boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR);
4632N/A
4632N/A GraphicsConfiguration sDefaultGraphicsConfiguration = null;
4632N/A
4632N/A protected BufferedImage getCompositingImage(int w, int h) {
4632N/A if (sDefaultGraphicsConfiguration == null) {
4632N/A sDefaultGraphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
4632N/A }
4632N/A
4632N/A BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
4632N/A // clear the image.
4632N/A clearRect(img, w, h);
4632N/A return img;
4632N/A }
4632N/A
4632N/A protected BufferedImage getCompositingImageSame(BufferedImage img, int w, int h) {
4632N/A if ((img == null) || (img.getWidth() != w) || (img.getHeight() != h)) {
4632N/A img = getCompositingImage(w, h);
4632N/A }
4632N/A return img;
4632N/A }
4632N/A
4632N/A BufferedImage sSrcComposite = null;
4632N/A
4632N/A public BufferedImage getCompositingSrcImage(int w, int h) {
4632N/A // <rdar://problem/3720263>. Changed from getCompositingImageBiggerOrSame() to
4632N/A // getCompositingImageSame(). (vm)
4632N/A BufferedImage bim = getCompositingImageSame(sSrcComposite, w, h);
4632N/A sSrcComposite = bim;
4632N/A return bim;
4632N/A }
4632N/A
4632N/A BufferedImage sDstInComposite = null;
4632N/A
4632N/A public BufferedImage getCompositingDstInImage(int w, int h) {
4632N/A BufferedImage bim = getCompositingImageSame(sDstInComposite, w, h);
4632N/A sDstInComposite = bim;
4632N/A return bim;
4632N/A }
4632N/A
4632N/A BufferedImage sDstOutComposite = null;
4632N/A
4632N/A public BufferedImage getCompositingDstOutImage(int w, int h) {
4632N/A BufferedImage bim = getCompositingImageSame(sDstOutComposite, w, h);
4632N/A sDstOutComposite = bim;
4632N/A return bim;
4632N/A }
4632N/A
4632N/A public void clearRect(BufferedImage bim, int w, int h) {
4632N/A Graphics2D g = bim.createGraphics();
4632N/A g.setComposite(AlphaComposite.Clear);
4632N/A g.fillRect(0, 0, w, h);
4632N/A g.dispose();
4632N/A }
4632N/A
4632N/A // END compositing support API
4632N/A
4632N/A public void invalidate() {
4632N/A // always valid
4632N/A }
4632N/A
4632N/A // graphics primitives drawing implementation:
4632N/A
4632N/A // certain primitives don't care about all the states (ex. drawing an image needs not involve setting current paint)
4632N/A static final int kPrimitive = 0;
4632N/A static final int kImage = 1;
4632N/A static final int kText = 2;
4632N/A static final int kCopyArea = 3;
4632N/A static final int kExternal = 4;
4632N/A
4632N/A static final int kLine = 5; // belongs to kPrimitive
4632N/A static final int kRect = 6; // belongs to kPrimitive
4632N/A static final int kRoundRect = 7; // belongs to kPrimitive
4632N/A static final int kOval = 8; // belongs to kPrimitive
4632N/A static final int kArc = 9; // belongs to kPrimitive
4632N/A static final int kPolygon = 10; // belongs to kPrimitive
4632N/A static final int kShape = 11; // belongs to kPrimitive
4632N/A // static final int kImage = 12; // belongs to kImage
4632N/A static final int kString = 13; // belongs to kText
4632N/A static final int kGlyphs = 14; // belongs to kText
4632N/A static final int kUnicodes = 15; // belongs to kText
4632N/A // static final int kCopyArea = 16; // belongs to kCopyArea
4632N/A // static final int kExternal = 17; // belongs to kExternal
4632N/A
4632N/A static final int kCommonParameterCount = 1 + 1 + 4 + 4; // type + change flags + color info (type(1) align(1) and
4632N/A // value(2)) + parameters ((x1, y1, x2, y2) OR (x, y, w, h))
4632N/A static final int kLineParametersCount = kCommonParameterCount; // kCommonParameterCount
4632N/A static final int kRectParametersCount = kCommonParameterCount + 1; // kCommonParameterCount + isfill
4632N/A static final int kRoundRectParametersCount = kCommonParameterCount + 2 + 1; // kCommonParameterCount + arcW + arcH +
4632N/A // isfill
4632N/A static final int kOvalParametersCount = kCommonParameterCount + 1; // kCommonParameterCount + isfill
4632N/A static final int kArcParametersCount = kCommonParameterCount + 2 + 1 + 1;// kCommonParameterCount + startAngle +
4632N/A // arcAngle + isfill + type
4632N/A static final int kPolygonParametersCount = 0; // not supported
4632N/A static final int kShapeParametersCount = 0; // not supported
4632N/A static final int kImageParametersCount = kCommonParameterCount + 2 + 2 + 4 + 4; // flip horz vert + w&h + src + dst
4632N/A static final int kStringParametersCount = 0; // not supported
4632N/A static final int kGlyphsParametersCount = 0; // not supported
4632N/A static final int kUnicodesParametersCount = 0; // not supported
4632N/A static final int kPixelParametersCount = 0; // not supported
4632N/A static final int kExternalParametersCount = 0; // not supported
4632N/A
4632N/A // for intParameters
4632N/A // states info
4632N/A static final int kChangeFlagIndex = 0; // kBoundsChangedBit | .. | kFontChangedBit
4632N/A // bounds info
4632N/A static final int kBoundsXIndex = 1;
4632N/A static final int kBoundsYIndex = 2;
4632N/A static final int kBoundsWidthIndex = 3;
4632N/A static final int kBoundsHeightIndex = 4;
4632N/A // clip info
4632N/A static final int kClipStateIndex = 5;
4632N/A static final int kClipNumTypesIndex = 6;
4632N/A static final int kClipNumCoordsIndex = 7;
4632N/A static final int kClipWindingRuleIndex = 8;
4632N/A static final int kClipXIndex = 9;
4632N/A static final int kClipYIndex = 10;
4632N/A static final int kClipWidthIndex = 11;
4632N/A static final int kClipHeightIndex = 12;
4632N/A // ctm info
4632N/A static final int kCTMaIndex = 13;
4632N/A static final int kCTMbIndex = 14;
4632N/A static final int kCTMcIndex = 15;
4632N/A static final int kCTMdIndex = 16;
4632N/A static final int kCTMtxIndex = 17;
4632N/A static final int kCTMtyIndex = 18;
4632N/A // color info
4632N/A static final int kColorStateIndex = 19; // kColorSimple or kColorGradient or kColorTexture
4632N/A static final int kColorRGBValueIndex = 20; // if kColorSimple
4632N/A static final int kColorIndexValueIndex = 21; // if kColorSystem
4632N/A static final int kColorPointerIndex = 22; //
4632N/A static final int kColorPointerIndex2 = 23; //
4632N/A static final int kColorRGBValue1Index = 24; // if kColorGradient
4632N/A static final int kColorWidthIndex = 25; // if kColorTexture
4632N/A static final int kColorRGBValue2Index = 26; // if kColorGradient
4632N/A static final int kColorHeightIndex = 27; // if kColorTexture
4632N/A static final int kColorIsCyclicIndex = 28; // if kColorGradient (kColorNonCyclic or kColorCyclic)
4632N/A static final int kColorx1Index = 29;
4632N/A static final int kColortxIndex = 30;
4632N/A static final int kColory1Index = 31;
4632N/A static final int kColortyIndex = 32;
4632N/A static final int kColorx2Index = 33;
4632N/A static final int kColorsxIndex = 34;
4632N/A static final int kColory2Index = 35;
4632N/A static final int kColorsyIndex = 36;
4632N/A // composite info
4632N/A static final int kCompositeRuleIndex = 37; // kCGCompositeClear or ... or kCGCompositeXor
4632N/A static final int kCompositeValueIndex = 38;
4632N/A // stroke info
4632N/A static final int kStrokeJoinIndex = 39; // see BasicStroke.java
4632N/A static final int kStrokeCapIndex = 40; // see BasicStroke.java
4632N/A static final int kStrokeWidthIndex = 41;
4632N/A static final int kStrokeDashPhaseIndex = 42;
4632N/A static final int kStrokeLimitIndex = 43;
4632N/A // hints info
4632N/A static final int kHintsAntialiasIndex = 44;
4632N/A static final int kHintsTextAntialiasIndex = 45;
4632N/A static final int kHintsFractionalMetricsIndex = 46;
4632N/A static final int kHintsRenderingIndex = 47;
4632N/A static final int kHintsInterpolationIndex = 48;
4632N/A // live resizing info
4632N/A static final int kCanDrawDuringLiveResizeIndex = 49;
4632N/A
4632N/A static final int kSizeOfParameters = kCanDrawDuringLiveResizeIndex + 1;
4632N/A
4632N/A // for objectParameters
4632N/A static final int kClipCoordinatesIndex = 0;
4632N/A static final int kClipTypesIndex = 1;
4632N/A static final int kTextureImageIndex = 2;
4632N/A static final int kStrokeDashArrayIndex = 3;
4632N/A static final int kFontIndex = 4;
4632N/A static final int kFontPaintIndex = 5;
4632N/A
4632N/A // possible state changes
4632N/A static final int kBoundsChangedBit = 1 << 0;
4632N/A static final int kBoundsNotChangedBit = ~kBoundsChangedBit;
4632N/A static final int kClipChangedBit = 1 << 1;
4632N/A static final int kClipNotChangedBit = ~kClipChangedBit;
4632N/A static final int kCTMChangedBit = 1 << 2;
4632N/A static final int kCTMNotChangedBit = ~kCTMChangedBit;
4632N/A static final int kColorChangedBit = 1 << 3;
4632N/A static final int kColorNotChangedBit = ~kColorChangedBit;
4632N/A static final int kCompositeChangedBit = 1 << 4;
4632N/A static final int kCompositeNotChangedBit = ~kCompositeChangedBit;
4632N/A static final int kStrokeChangedBit = 1 << 5;
4632N/A static final int kStrokeNotChangedBit = ~kStrokeChangedBit;
4632N/A static final int kHintsChangedBit = 1 << 6;
4632N/A static final int kHintsNotChangedBit = ~kHintsChangedBit;
4632N/A static final int kFontChangedBit = 1 << 7;
4632N/A static final int kFontNotChangedBit = ~kFontChangedBit;
4632N/A static final int kEverythingChangedFlag = 0xffffffff;
4632N/A
4632N/A // possible color states
4632N/A static final int kColorSimple = 0;
4632N/A static final int kColorSystem = 1;
4632N/A static final int kColorGradient = 2;
4632N/A static final int kColorTexture = 3;
4632N/A
4632N/A // possible gradient color states
4632N/A static final int kColorNonCyclic = 0;
4632N/A static final int kColorCyclic = 1;
4632N/A
4632N/A // possible clip states
4632N/A static final int kClipRect = 0;
4632N/A static final int kClipShape = 1;
4632N/A
4632N/A static int getRendererTypeForPrimitive(int primitiveType) {
4632N/A switch (primitiveType) {
4632N/A case kImage:
4632N/A return kImage;
4632N/A case kCopyArea:
4632N/A return kCopyArea;
4632N/A case kExternal:
4632N/A return kExternal;
4632N/A case kString:
4632N/A case kGlyphs:
4632N/A case kUnicodes:
4632N/A return kText;
4632N/A default:
4632N/A return kPrimitive;
4632N/A }
4632N/A }
4632N/A
4632N/A int fChangeFlag;
4632N/A protected ByteBuffer fGraphicsStates = null;
4632N/A IntBuffer fGraphicsStatesInt = null;
4632N/A FloatBuffer fGraphicsStatesFloat = null;
4632N/A LongBuffer fGraphicsStatesLong = null;
4632N/A protected Object[] fGraphicsStatesObject = null;
4632N/A
4632N/A Rectangle userBounds = new Rectangle();
4632N/A float lastUserX = 0;
4632N/A float lastUserY = 0;
4632N/A float lastUserW = 0;
4632N/A float lastUserH = 0;
4632N/A
4632N/A void setUserBounds(SunGraphics2D sg2d, int x, int y, int width, int height) {
4632N/A if ((lastUserX != x) || (lastUserY != y) || (lastUserW != width) || (lastUserH != height)) {
4632N/A lastUserX = x;
4632N/A lastUserY = y;
4632N/A lastUserW = width;
4632N/A lastUserH = height;
4632N/A
4632N/A this.fGraphicsStatesInt.put(kBoundsXIndex, x);
4632N/A this.fGraphicsStatesInt.put(kBoundsYIndex, y);
4632N/A this.fGraphicsStatesInt.put(kBoundsWidthIndex, width);
4632N/A this.fGraphicsStatesInt.put(kBoundsHeightIndex, height);
4632N/A
4632N/A userBounds.setBounds(x, y, width, height);
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kBoundsChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kBoundsNotChangedBit);
4632N/A }
4632N/A }
4632N/A
4632N/A static ByteBuffer getBufferOfSize(int size) {
4632N/A ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4);
4632N/A buffer.order(ByteOrder.nativeOrder());
4632N/A return buffer;
4632N/A }
4632N/A
4632N/A FloatBuffer clipCoordinatesArray = null;
4632N/A IntBuffer clipTypesArray = null;
4632N/A Shape lastClipShape = null;
4632N/A float lastClipX = 0;
4632N/A float lastClipY = 0;
4632N/A float lastClipW = 0;
4632N/A float lastClipH = 0;
4632N/A
4632N/A void setupClip(SunGraphics2D sg2d) {
4632N/A switch (sg2d.clipState) {
4632N/A case SunGraphics2D.CLIP_DEVICE:
4632N/A case SunGraphics2D.CLIP_RECTANGULAR: {
4632N/A Region clip = sg2d.getCompClip();
4632N/A float x = clip.getLoX();
4632N/A float y = clip.getLoY();
4632N/A float w = clip.getWidth();
4632N/A float h = clip.getHeight();
4632N/A if ((this.fGraphicsStatesInt.get(kClipStateIndex) != kClipRect) ||
4632N/A (x != lastClipX) ||
4632N/A (y != lastClipY) ||
4632N/A (w != lastClipW) ||
4632N/A (h != lastClipH)) {
4632N/A this.fGraphicsStatesFloat.put(kClipXIndex, x);
4632N/A this.fGraphicsStatesFloat.put(kClipYIndex, y);
4632N/A this.fGraphicsStatesFloat.put(kClipWidthIndex, w);
4632N/A this.fGraphicsStatesFloat.put(kClipHeightIndex, h);
4632N/A
4632N/A lastClipX = x;
4632N/A lastClipY = y;
4632N/A lastClipW = w;
4632N/A lastClipH = h;
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kClipChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kClipNotChangedBit);
4632N/A }
4632N/A this.fGraphicsStatesInt.put(kClipStateIndex, kClipRect);
4632N/A break;
4632N/A }
4632N/A case SunGraphics2D.CLIP_SHAPE: {
4632N/A // if (lastClipShape != sg2d.usrClip) shapes are mutable!, and doing "equals" traverses all
4632N/A // the coordinates, so we might as well do all of it anyhow
4632N/A lastClipShape = sg2d.usrClip;
4632N/A
4632N/A GeneralPath gp = null;
4632N/A
4632N/A if (sg2d.usrClip instanceof GeneralPath) {
4632N/A gp = (GeneralPath) sg2d.usrClip;
4632N/A } else {
4632N/A gp = new GeneralPath(sg2d.usrClip);
4632N/A }
4632N/A
4632N/A int shapeLength = getPathLength(gp);
4632N/A
4632N/A if ((clipCoordinatesArray == null) || (clipCoordinatesArray.capacity() < (shapeLength * 6))) {
4632N/A clipCoordinatesArray = getBufferOfSize(shapeLength * 6).asFloatBuffer(); // segment can have a
4632N/A // max of 6 coordinates
4632N/A }
4632N/A if ((clipTypesArray == null) || (clipTypesArray.capacity() < shapeLength)) {
4632N/A clipTypesArray = getBufferOfSize(shapeLength).asIntBuffer();
4632N/A }
4632N/A
4632N/A int windingRule = getPathCoordinates(gp, clipCoordinatesArray, clipTypesArray);
4632N/A
4632N/A this.fGraphicsStatesInt.put(kClipNumTypesIndex, clipTypesArray.position());
4632N/A this.fGraphicsStatesInt.put(kClipNumCoordsIndex, clipCoordinatesArray.position());
4632N/A this.fGraphicsStatesInt.put(kClipWindingRuleIndex, windingRule);
4632N/A this.fGraphicsStatesObject[kClipTypesIndex] = clipTypesArray;
4632N/A this.fGraphicsStatesObject[kClipCoordinatesIndex] = clipCoordinatesArray;
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kClipChangedBit);
4632N/A this.fGraphicsStatesInt.put(kClipStateIndex, kClipShape);
4632N/A break;
4632N/A }
4632N/A }
4632N/A
4632N/A }
4632N/A
4632N/A final double[] lastCTM = new double[6];
4632N/A float lastCTMa = 0;
4632N/A float lastCTMb = 0;
4632N/A float lastCTMc = 0;
4632N/A float lastCTMd = 0;
4632N/A float lastCTMtx = 0;
4632N/A float lastCTMty = 0;
4632N/A
4632N/A void setupTransform(SunGraphics2D sg2d) {
4632N/A sg2d.transform.getMatrix(lastCTM);
4632N/A
4632N/A float a = (float) lastCTM[0];
4632N/A float b = (float) lastCTM[1];
4632N/A float c = (float) lastCTM[2];
4632N/A float d = (float) lastCTM[3];
4632N/A float tx = (float) lastCTM[4];
4632N/A float ty = (float) lastCTM[5];
4632N/A if (tx != lastCTMtx ||
4632N/A ty != lastCTMty ||
4632N/A a != lastCTMa ||
4632N/A b != lastCTMb ||
4632N/A c != lastCTMc ||
4632N/A d != lastCTMd) {
4632N/A this.fGraphicsStatesFloat.put(kCTMaIndex, a);
4632N/A this.fGraphicsStatesFloat.put(kCTMbIndex, b);
4632N/A this.fGraphicsStatesFloat.put(kCTMcIndex, c);
4632N/A this.fGraphicsStatesFloat.put(kCTMdIndex, d);
4632N/A this.fGraphicsStatesFloat.put(kCTMtxIndex, tx);
4632N/A this.fGraphicsStatesFloat.put(kCTMtyIndex, ty);
4632N/A
4632N/A lastCTMa = a;
4632N/A lastCTMb = b;
4632N/A lastCTMc = c;
4632N/A lastCTMd = d;
4632N/A lastCTMtx = tx;
4632N/A lastCTMty = ty;
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kCTMChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kCTMNotChangedBit);
4632N/A }
4632N/A }
4632N/A
4632N/A static AffineTransform sIdentityMatrix = new AffineTransform();
4632N/A Paint lastPaint = null;
4632N/A long lastPaintPtr = 0;
4632N/A int lastPaintRGB = 0;
4632N/A int lastPaintIndex = 0;
4632N/A BufferedImage texturePaintImage = null;
4632N/A
4632N/A void setupPaint(SunGraphics2D sg2d, int x, int y, int w, int h) {
4632N/A if (sg2d.paint instanceof SystemColor) {
4632N/A SystemColor color = (SystemColor) sg2d.paint;
4632N/A int index = color.hashCode(); // depends on Color.java hashCode implementation! (returns "value" of color)
4632N/A if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorSystem) || (index != this.lastPaintIndex)) {
4632N/A this.lastPaintIndex = index;
4632N/A
4632N/A this.fGraphicsStatesInt.put(kColorStateIndex, kColorSystem);
4632N/A this.fGraphicsStatesInt.put(kColorIndexValueIndex, index);
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
4632N/A }
4632N/A } else if (sg2d.paint instanceof Color) {
4632N/A Color color = (Color) sg2d.paint;
4632N/A int rgb = color.getRGB();
4632N/A if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorSimple) || (rgb != this.lastPaintRGB)) {
4632N/A this.lastPaintRGB = rgb;
4632N/A
4632N/A this.fGraphicsStatesInt.put(kColorStateIndex, kColorSimple);
4632N/A this.fGraphicsStatesInt.put(kColorRGBValueIndex, rgb);
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
4632N/A }
4632N/A } else if (sg2d.paint instanceof GradientPaint) {
4632N/A if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorGradient) || (lastPaint != sg2d.paint)) {
4632N/A GradientPaint color = (GradientPaint) sg2d.paint;
4632N/A this.fGraphicsStatesInt.put(kColorStateIndex, kColorGradient);
4632N/A this.fGraphicsStatesInt.put(kColorRGBValue1Index, color.getColor1().getRGB());
4632N/A this.fGraphicsStatesInt.put(kColorRGBValue2Index, color.getColor2().getRGB());
4632N/A this.fGraphicsStatesInt.put(kColorIsCyclicIndex, (color.isCyclic()) ? kColorCyclic : kColorNonCyclic);
4632N/A Point2D p = color.getPoint1();
4632N/A this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
4632N/A this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
4632N/A p = color.getPoint2();
4632N/A this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
4632N/A this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
4632N/A }
4632N/A } else if (sg2d.paint instanceof TexturePaint) {
4632N/A if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint)) {
4632N/A TexturePaint color = (TexturePaint) sg2d.paint;
4632N/A this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
4632N/A texturePaintImage = color.getImage();
4632N/A SurfaceData textureSurfaceData = BufImgSurfaceData.createData(texturePaintImage);
4632N/A this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
4632N/A this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
4632N/A Rectangle2D anchor = color.getAnchorRect();
4632N/A this.fGraphicsStatesFloat.put(kColortxIndex, (float) anchor.getX());
4632N/A this.fGraphicsStatesFloat.put(kColortyIndex, (float) anchor.getY());
4632N/A this.fGraphicsStatesFloat.put(kColorsxIndex, (float) (anchor.getWidth() / texturePaintImage.getWidth()));
4632N/A this.fGraphicsStatesFloat.put(kColorsyIndex, (float) (anchor.getHeight() / texturePaintImage.getHeight()));
4632N/A this.fGraphicsStatesObject[kTextureImageIndex] = textureSurfaceData;
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
4632N/A }
4632N/A } else {
4632N/A if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) {
4632N/A PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints());
4632N/A WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height));
4632N/A ColorModel cm = context.getColorModel();
4632N/A texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
4632N/A
4632N/A this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
4632N/A this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
4632N/A this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
4632N/A this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX());
4632N/A this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY());
4632N/A this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f);
4632N/A this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f);
4632N/A this.fGraphicsStatesObject[kTextureImageIndex] = sun.awt.image.BufImgSurfaceData.createData(texturePaintImage);
4632N/A
4632N/A context.dispose();
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
4632N/A }
4632N/A }
4632N/A lastPaint = sg2d.paint;
4632N/A }
4632N/A
4632N/A Composite lastComposite;
4632N/A int lastCompositeAlphaRule = 0;
4632N/A float lastCompositeAlphaValue = 0;
4632N/A
4632N/A void setupComposite(SunGraphics2D sg2d) {
4632N/A Composite composite = sg2d.composite;
4632N/A
4632N/A if (lastComposite != composite) {
4632N/A lastComposite = composite;
4632N/A
4632N/A // For composite state COMP_ISCOPY, COMP_XOR or COMP_CUSTOM set alpha compositor to COPY:
4632N/A int alphaRule = AlphaComposite.SRC_OVER;
4632N/A float alphaValue = 1.0f;
4632N/A
4632N/A // For composite state COMP_ISCOPY composite could be null. If it's not (or composite state == COMP_ALPHA)
4632N/A // get alpha compositor's values:
4632N/A if ((sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) && (composite != null)) {
4632N/A AlphaComposite alphaComposite = (AlphaComposite) composite;
4632N/A alphaRule = alphaComposite.getRule();
4632N/A alphaValue = alphaComposite.getAlpha();
4632N/A }
4632N/A
4632N/A // 2-17-03 VL: [Radar 3174922]
4632N/A // For COMP_XOR and COMP_CUSTOM compositing modes we should be setting alphaRule = AlphaComposite.SRC
4632N/A // which should map to kCGCompositeCopy.
4632N/A
4632N/A if ((lastCompositeAlphaRule != alphaRule) || (lastCompositeAlphaValue != alphaValue)) {
4632N/A this.fGraphicsStatesInt.put(kCompositeRuleIndex, alphaRule);
4632N/A this.fGraphicsStatesFloat.put(kCompositeValueIndex, alphaValue);
4632N/A
4632N/A lastCompositeAlphaRule = alphaRule;
4632N/A lastCompositeAlphaValue = alphaValue;
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kCompositeChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);
4632N/A }
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kCompositeNotChangedBit);
4632N/A }
4632N/A }
4632N/A
4632N/A BasicStroke lastStroke = null;
4632N/A static BasicStroke defaultBasicStroke = new BasicStroke();
4632N/A
4632N/A void setupStroke(SunGraphics2D sg2d) {
4632N/A BasicStroke stroke = defaultBasicStroke;
4632N/A
4632N/A if (sg2d.stroke instanceof BasicStroke) {
4632N/A stroke = (BasicStroke) sg2d.stroke;
4632N/A }
4632N/A
4632N/A if (lastStroke != stroke) {
4632N/A this.fGraphicsStatesObject[kStrokeDashArrayIndex] = stroke.getDashArray();
4632N/A this.fGraphicsStatesFloat.put(kStrokeDashPhaseIndex, stroke.getDashPhase());
4632N/A this.fGraphicsStatesInt.put(kStrokeCapIndex, stroke.getEndCap());
4632N/A this.fGraphicsStatesInt.put(kStrokeJoinIndex, stroke.getLineJoin());
4632N/A this.fGraphicsStatesFloat.put(kStrokeWidthIndex, stroke.getLineWidth());
4632N/A this.fGraphicsStatesFloat.put(kStrokeLimitIndex, stroke.getMiterLimit());
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kStrokeChangedBit);
4632N/A
4632N/A lastStroke = stroke;
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kStrokeNotChangedBit);
4632N/A }
4632N/A }
4632N/A
4632N/A Font lastFont;
4632N/A
4632N/A void setupFont(Font font, Paint paint) {
4632N/A if (font == null) { return; }
4632N/A
4632N/A // We have to setup the kFontPaintIndex if we have changed the color so we added the last
4632N/A // test to see if the color has changed - needed for complex strings
4632N/A // see Radar 3368674
4632N/A if ((font != lastFont) || ((this.fChangeFlag & kColorChangedBit) != 0)) {
4632N/A this.fGraphicsStatesObject[kFontIndex] = font;
4632N/A this.fGraphicsStatesObject[kFontPaintIndex] = paint;
4632N/A
4632N/A this.fChangeFlag = (this.fChangeFlag | kFontChangedBit);
4632N/A
4632N/A lastFont = font;
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kFontNotChangedBit);
4632N/A }
4632N/A }
4632N/A
4632N/A void setupRenderingHints(SunGraphics2D sg2d) {
4632N/A boolean hintsChanged = false;
4632N/A
4632N/A // Significant for draw, fill, text, and image ops:
4632N/A int antialiasHint = sg2d.antialiasHint;
4632N/A if (this.fGraphicsStatesInt.get(kHintsAntialiasIndex) != antialiasHint) {
4632N/A this.fGraphicsStatesInt.put(kHintsAntialiasIndex, antialiasHint);
4632N/A hintsChanged = true;
4632N/A }
4632N/A
4632N/A // Significant only for text ops:
4632N/A int textAntialiasHint = sg2d.textAntialiasHint;
4632N/A if (this.fGraphicsStatesInt.get(kHintsTextAntialiasIndex) != textAntialiasHint) {
4632N/A this.fGraphicsStatesInt.put(kHintsTextAntialiasIndex, textAntialiasHint);
4632N/A hintsChanged = true;
4632N/A }
4632N/A
4632N/A // Significant only for text ops:
4632N/A int fractionalMetricsHint = sg2d.fractionalMetricsHint;
4632N/A if (this.fGraphicsStatesInt.get(kHintsFractionalMetricsIndex) != fractionalMetricsHint) {
4632N/A this.fGraphicsStatesInt.put(kHintsFractionalMetricsIndex, fractionalMetricsHint);
4632N/A hintsChanged = true;
4632N/A }
4632N/A
4632N/A // Significant only for image ops:
4632N/A int renderHint = sg2d.renderHint;
4632N/A if (this.fGraphicsStatesInt.get(kHintsRenderingIndex) != renderHint) {
4632N/A this.fGraphicsStatesInt.put(kHintsRenderingIndex, renderHint);
4632N/A hintsChanged = true;
4632N/A }
4632N/A
4632N/A // Significant only for image ops:
4632N/A Object hintValue = sg2d.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
4632N/A int interpolationHint = (hintValue != null ? ((SunHints.Value) hintValue).getIndex() : -1);
4632N/A if (this.fGraphicsStatesInt.get(kHintsInterpolationIndex) != interpolationHint) {
4632N/A this.fGraphicsStatesInt.put(kHintsInterpolationIndex, interpolationHint);
4632N/A hintsChanged = true;
4632N/A }
4632N/A
4632N/A if (hintsChanged) {
4632N/A this.fChangeFlag = (this.fChangeFlag | kHintsChangedBit);
4632N/A } else {
4632N/A this.fChangeFlag = (this.fChangeFlag & kHintsNotChangedBit);
4632N/A }
4632N/A }
4632N/A
4632N/A SunGraphics2D sg2dCurrent = null;
4632N/A Thread threadCurrent = null;
4632N/A
4632N/A void setupGraphicsState(SunGraphics2D sg2d, int primitiveType) {
4632N/A setupGraphicsState(sg2d, primitiveType, sg2d.font, 0, 0, fBounds.width, fBounds.height); // deviceBounds into userBounds
4632N/A }
4632N/A
4632N/A void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, int x, int y, int w, int h) {
4632N/A setupGraphicsState(sg2d, primitiveType, sg2d.font, x, y, w, h);
4632N/A }
4632N/A
4632N/A // the method below is overriden by CPeerSurface to check the last peer used to draw
4632N/A // if the peer changed we finish lazy drawing
4632N/A void setupGraphicsState(SunGraphics2D sg2d, int primitiveType, Font font, int x, int y, int w, int h) {
4632N/A this.fChangeFlag = 0;
4632N/A
4632N/A setUserBounds(sg2d, x, y, w, h);
4632N/A
4632N/A Thread thread = Thread.currentThread();
4632N/A if ((this.sg2dCurrent != sg2d) || (this.threadCurrent != thread)) {
4632N/A this.sg2dCurrent = sg2d;
4632N/A this.threadCurrent = thread;
4632N/A
4632N/A setupClip(sg2d);
4632N/A setupTransform(sg2d);
4632N/A setupPaint(sg2d, x, y, w, h);
4632N/A setupComposite(sg2d);
4632N/A setupStroke(sg2d);
4632N/A setupFont(font, sg2d.paint);
4632N/A setupRenderingHints(sg2d);
4632N/A
4632N/A this.fChangeFlag = kEverythingChangedFlag;
4632N/A } else {
4632N/A int rendererType = getRendererTypeForPrimitive(primitiveType);
4632N/A
4632N/A setupClip(sg2d);
4632N/A setupTransform(sg2d);
4632N/A
4632N/A if (rendererType != kCopyArea) {
4632N/A setupComposite(sg2d);
4632N/A setupRenderingHints(sg2d);
4632N/A
4632N/A if ((rendererType != kImage)) {
4632N/A setupPaint(sg2d, x, y, w, h);
4632N/A setupStroke(sg2d);
4632N/A }
4632N/A if (rendererType != kPrimitive) {
4632N/A setupFont(font, sg2d.paint);
4632N/A }
4632N/A
4632N/A }
4632N/A }
4632N/A
4632N/A this.fGraphicsStatesInt.put(kChangeFlagIndex, this.fChangeFlag);
4632N/A }
4632N/A
4632N/A boolean isCustomPaint(SunGraphics2D sg2d) {
4632N/A if ((sg2d.paint instanceof Color) || (sg2d.paint instanceof SystemColor) || (sg2d.paint instanceof GradientPaint) || (sg2d.paint instanceof TexturePaint)) { return false; }
4632N/A
4632N/A return true;
4632N/A }
4632N/A
4632N/A final float[] segmentCoordinatesArray = new float[6];
4632N/A
4632N/A int getPathLength(GeneralPath gp) {
4632N/A int length = 0;
4632N/A
4632N/A PathIterator pi = gp.getPathIterator(null);
4632N/A while (pi.isDone() == false) {
4632N/A pi.next();
4632N/A length++;
4632N/A }
4632N/A
4632N/A return length;
4632N/A }
4632N/A
4632N/A int getPathCoordinates(GeneralPath gp, FloatBuffer coordinates, IntBuffer types) {
4632N/A // System.err.println("getPathCoordinates");
4632N/A boolean skip = false;
4632N/A
4632N/A coordinates.clear();
4632N/A types.clear();
4632N/A
4632N/A int type;
4632N/A
4632N/A PathIterator pi = gp.getPathIterator(null);
4632N/A while (pi.isDone() == false) {
4632N/A skip = false;
4632N/A type = pi.currentSegment(segmentCoordinatesArray);
4632N/A
4632N/A switch (type) {
4632N/A case PathIterator.SEG_MOVETO:
4632N/A // System.err.println(" SEG_MOVETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");
4632N/A if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
4632N/A segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {
4632N/A coordinates.put(segmentCoordinatesArray[0]);
4632N/A coordinates.put(segmentCoordinatesArray[1]);
4632N/A } else {
4632N/A skip = true;
4632N/A }
4632N/A break;
4632N/A case PathIterator.SEG_LINETO:
4632N/A // System.err.println(" SEG_LINETO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+")");
4632N/A if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
4632N/A segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND) {
4632N/A coordinates.put(segmentCoordinatesArray[0]);
4632N/A coordinates.put(segmentCoordinatesArray[1]);
4632N/A } else {
4632N/A skip = true;
4632N/A }
4632N/A break;
4632N/A case PathIterator.SEG_QUADTO:
4632N/A // System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+")");
4632N/A if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
4632N/A segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&
4632N/A segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&
4632N/A segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND) {
4632N/A coordinates.put(segmentCoordinatesArray[0]);
4632N/A coordinates.put(segmentCoordinatesArray[1]);
4632N/A coordinates.put(segmentCoordinatesArray[2]);
4632N/A coordinates.put(segmentCoordinatesArray[3]);
4632N/A } else {
4632N/A skip = true;
4632N/A }
4632N/A break;
4632N/A case PathIterator.SEG_CUBICTO:
4632N/A // System.err.println(" SEG_QUADTO ("+segmentCoordinatesArray[0]+", "+segmentCoordinatesArray[1]+"), ("+segmentCoordinatesArray[2]+", "+segmentCoordinatesArray[3]+"), ("+segmentCoordinatesArray[4]+", "+segmentCoordinatesArray[5]+")");
4632N/A if (segmentCoordinatesArray[0] < UPPER_BND && segmentCoordinatesArray[0] > LOWER_BND &&
4632N/A segmentCoordinatesArray[1] < UPPER_BND && segmentCoordinatesArray[1] > LOWER_BND &&
4632N/A segmentCoordinatesArray[2] < UPPER_BND && segmentCoordinatesArray[2] > LOWER_BND &&
4632N/A segmentCoordinatesArray[3] < UPPER_BND && segmentCoordinatesArray[3] > LOWER_BND &&
4632N/A segmentCoordinatesArray[4] < UPPER_BND && segmentCoordinatesArray[4] > LOWER_BND &&
4632N/A segmentCoordinatesArray[5] < UPPER_BND && segmentCoordinatesArray[5] > LOWER_BND) {
4632N/A coordinates.put(segmentCoordinatesArray[0]);
4632N/A coordinates.put(segmentCoordinatesArray[1]);
4632N/A coordinates.put(segmentCoordinatesArray[2]);
4632N/A coordinates.put(segmentCoordinatesArray[3]);
4632N/A coordinates.put(segmentCoordinatesArray[4]);
4632N/A coordinates.put(segmentCoordinatesArray[5]);
4632N/A } else {
4632N/A skip = true;
4632N/A }
4632N/A break;
4632N/A case PathIterator.SEG_CLOSE:
4632N/A // System.err.println(" SEG_CLOSE");
4632N/A break;
4632N/A }
4632N/A
4632N/A if (!skip) {
4632N/A types.put(type);
4632N/A }
4632N/A
4632N/A pi.next();
4632N/A }
4632N/A
4632N/A return pi.getWindingRule();
4632N/A }
4632N/A
4632N/A public void doLine(CRenderer renderer, SunGraphics2D sg2d, float x1, float y1, float x2, float y2) {
4632N/A // System.err.println("-- doLine x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2+" paint="+sg2d.paint);
4632N/A setupGraphicsState(sg2d, kLine, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A renderer.doLine(this, x1, y1, x2, y2);
4632N/A }
4632N/A
4632N/A public void doRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {
4632N/A // System.err.println("-- doRect x="+x+" y="+y+" w="+width+" h="+height+" isfill="+isfill+" paint="+sg2d.paint);
4632N/A if ((isfill) && (isCustomPaint(sg2d))) {
4632N/A setupGraphicsState(sg2d, kRect, (int) x, (int) y, (int) width, (int) height);
4632N/A } else {
4632N/A setupGraphicsState(sg2d, kRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A }
4632N/A renderer.doRect(this, x, y, width, height, isfill);
4632N/A }
4632N/A
4632N/A public void doRoundRect(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float arcW, float arcH, boolean isfill) {
4632N/A // System.err.println("--- doRoundRect");
4632N/A if ((isfill) && (isCustomPaint(sg2d))) {
4632N/A setupGraphicsState(sg2d, kRoundRect, (int) x, (int) y, (int) width, (int) height);
4632N/A } else {
4632N/A setupGraphicsState(sg2d, kRoundRect, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A }
4632N/A renderer.doRoundRect(this, x, y, width, height, arcW, arcH, isfill);
4632N/A }
4632N/A
4632N/A public void doOval(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, boolean isfill) {
4632N/A // System.err.println("--- doOval");
4632N/A if ((isfill) && (isCustomPaint(sg2d))) {
4632N/A setupGraphicsState(sg2d, kOval, (int) x, (int) y, (int) width, (int) height);
4632N/A } else {
4632N/A setupGraphicsState(sg2d, kOval, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A }
4632N/A renderer.doOval(this, x, y, width, height, isfill);
4632N/A }
4632N/A
4632N/A public void doArc(CRenderer renderer, SunGraphics2D sg2d, float x, float y, float width, float height, float startAngle, float arcAngle, int type, boolean isfill) {
4632N/A // System.err.println("--- doArc");
4632N/A if ((isfill) && (isCustomPaint(sg2d))) {
4632N/A setupGraphicsState(sg2d, kArc, (int) x, (int) y, (int) width, (int) height);
4632N/A } else {
4632N/A setupGraphicsState(sg2d, kArc, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A }
4632N/A
4632N/A renderer.doArc(this, x, y, width, height, startAngle, arcAngle, type, isfill);
4632N/A }
4632N/A
4632N/A public void doPolygon(CRenderer renderer, SunGraphics2D sg2d, int xpoints[], int ypoints[], int npoints, boolean ispolygon, boolean isfill) {
4632N/A // System.err.println("--- doPolygon");
4632N/A
4632N/A if ((isfill) && (isCustomPaint(sg2d))) {
4632N/A int minx = xpoints[0];
4632N/A int miny = ypoints[0];
4632N/A int maxx = minx;
4632N/A int maxy = miny;
4632N/A for (int i = 1; i < npoints; i++) {
4632N/A int x = xpoints[i];
4632N/A if (x < minx) {
4632N/A minx = x;
4632N/A } else if (x > maxx) {
4632N/A maxx = x;
4632N/A }
4632N/A
4632N/A int y = ypoints[i];
4632N/A if (y < miny) {
4632N/A miny = y;
4632N/A } else if (y > maxy) {
4632N/A maxy = y;
4632N/A }
4632N/A }
4632N/A setupGraphicsState(sg2d, kPolygon, minx, miny, maxx - minx, maxy - miny);
4632N/A } else {
4632N/A setupGraphicsState(sg2d, kPolygon, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A }
4632N/A renderer.doPoly(this, xpoints, ypoints, npoints, ispolygon, isfill);
4632N/A }
4632N/A
4632N/A FloatBuffer shapeCoordinatesArray = null;
4632N/A IntBuffer shapeTypesArray = null;
4632N/A
4632N/A public void drawfillShape(CRenderer renderer, SunGraphics2D sg2d, GeneralPath gp, boolean isfill, boolean shouldApplyOffset) {
4632N/A // System.err.println("--- drawfillShape");
4632N/A
4632N/A if ((isfill) && (isCustomPaint(sg2d))) {
4632N/A Rectangle bounds = gp.getBounds();
4632N/A setupGraphicsState(sg2d, kShape, bounds.x, bounds.y, bounds.width, bounds.height);
4632N/A } else {
4632N/A setupGraphicsState(sg2d, kShape, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A }
4632N/A
4632N/A int shapeLength = getPathLength(gp);
4632N/A
4632N/A if ((shapeCoordinatesArray == null) || (shapeCoordinatesArray.capacity() < (shapeLength * 6))) {
4632N/A shapeCoordinatesArray = getBufferOfSize(shapeLength * 6).asFloatBuffer(); // segment can have a max of 6
4632N/A // coordinates
4632N/A }
4632N/A if ((shapeTypesArray == null) || (shapeTypesArray.capacity() < shapeLength)) {
4632N/A shapeTypesArray = getBufferOfSize(shapeLength).asIntBuffer();
4632N/A }
4632N/A
4632N/A int windingRule = getPathCoordinates(gp, shapeCoordinatesArray, shapeTypesArray);
4632N/A
4632N/A renderer.doShape(this, shapeLength, shapeCoordinatesArray, shapeTypesArray, windingRule, isfill, shouldApplyOffset);
4632N/A }
4632N/A
4632N/A 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) {
4632N/A // System.err.println("--- blitImage sx="+sx+", sy="+sy+", sw="+sw+", sh="+sh+", img="+img);
4632N/A OSXOffScreenSurfaceData osxsd = (OSXOffScreenSurfaceData) img;
4632N/A synchronized (osxsd.getLockObject()) {
4632N/A int w = osxsd.bim.getWidth();
4632N/A int h = osxsd.bim.getHeight();
4632N/A
4632N/A // the image itself can have outstanding graphics primitives that might need to be flushed
4632N/A setupGraphicsState(sg2d, kImage, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A
4632N/A // 04/06/04 cmc: radr://3612381 Graphics.drawImage ignores bgcolor parameter
4632N/A if (bgColor != null) {
4632N/A img = osxsd.getCopyWithBgColor(bgColor);
4632N/A }
4632N/A
4632N/A renderer.doImage(this, img, fliph, flipv, w, h, sx, sy, sw, sh, dx, dy, dw, dh);
4632N/A }
4632N/A }
4632N/A
4632N/A public interface CGContextDrawable {
4632N/A public void drawIntoCGContext(final long cgContext);
4632N/A }
4632N/A
4632N/A public void drawString(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, String str, double x, double y) {
4632N/A // System.err.println("--- drawString str=\""+str+"\"");
4632N/A // see <rdar://problem/3825795>. We don't want to call anything if the string is empty!
4632N/A if (str.length() == 0) { return; }
4632N/A
4632N/A setupGraphicsState(sg2d, kString, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A renderer.doDrawString(this, nativeStrikePtr, str, x, y);
4632N/A }
4632N/A
4632N/A public void drawGlyphs(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, GlyphVector gv, float x, float y) {
4632N/A // System.err.println("--- drawGlyphs");
4632N/A setupGraphicsState(sg2d, kGlyphs, gv.getFont(), 0, 0, fBounds.width, fBounds.height);
4632N/A renderer.doDrawGlyphs(this, nativeStrikePtr, gv, x, y);
4632N/A }
4632N/A
4632N/A public void drawUnicodes(CTextPipe renderer, SunGraphics2D sg2d, long nativeStrikePtr, char unicodes[], int offset, int length, float x, float y) {
4632N/A // System.err.println("--- drawUnicodes "+(new String(unicodes, offset, length)));
4632N/A setupGraphicsState(sg2d, kUnicodes, sg2d.font, 0, 0, fBounds.width, fBounds.height);
4632N/A if (length == 1) {
4632N/A renderer.doOneUnicode(this, nativeStrikePtr, unicodes[offset], x, y);
4632N/A } else {
4632N/A renderer.doUnicodes(this, nativeStrikePtr, unicodes, offset, length, x, y);
4632N/A }
4632N/A }
4632N/A
4632N/A // used by copyArea:
4632N/A
4632N/A Rectangle srcCopyAreaRect = new Rectangle();
4632N/A Rectangle dstCopyAreaRect = new Rectangle();
4632N/A Rectangle finalCopyAreaRect = new Rectangle();
4632N/A Rectangle copyAreaBounds = new Rectangle();
4632N/A
4632N/A void intersection(Rectangle r1, Rectangle r2, Rectangle r3) {
4632N/A // this code is taken from Rectangle.java (modified to put results in r3)
4632N/A int tx1 = r1.x;
4632N/A int ty1 = r1.y;
4632N/A long tx2 = tx1 + r1.width;
4632N/A long ty2 = ty1 + r1.height;
4632N/A
4632N/A int rx1 = r2.x;
4632N/A int ry1 = r2.y;
4632N/A long rx2 = rx1 + r2.width;
4632N/A long ry2 = ry1 + r2.height;
4632N/A
4632N/A if (tx1 < rx1) tx1 = rx1;
4632N/A if (ty1 < ry1) ty1 = ry1;
4632N/A if (tx2 > rx2) tx2 = rx2;
4632N/A if (ty2 > ry2) ty2 = ry2;
4632N/A
4632N/A tx2 -= tx1;
4632N/A ty2 -= ty1;
4632N/A
4632N/A // tx2,ty2 will never overflow (they will never be
4632N/A // larger than the smallest of the two source w,h)
4632N/A // they might underflow, though...
4632N/A if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
4632N/A if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
4632N/A
4632N/A r3.setBounds(tx1, ty1, (int) tx2, (int) ty2);
4632N/A }
4632N/A
4632N/A /**
4632N/A * Clips the copy area to the heavywieght bounds and returns the cliped rectangle. The tricky part here is the the
4632N/A * passed arguments x, y are in the coordinate space of the sg2d/lightweight comp. In order to do the clipping we
4632N/A * translate them to the coordinate space of the surface, and the returned clipped rectangle is in the coordinate
4632N/A * space of the surface.
4632N/A */
4632N/A protected Rectangle clipCopyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) {
4632N/A // we need to clip against the heavyweight bounds
4632N/A copyAreaBounds.setBounds(sg2d.devClip.getLoX(), sg2d.devClip.getLoY(), sg2d.devClip.getWidth(), sg2d.devClip.getHeight());
4632N/A
4632N/A // put src rect into surface coordinate space
4632N/A x += sg2d.transX;
4632N/A y += sg2d.transY;
4632N/A
4632N/A // clip src rect
4632N/A srcCopyAreaRect.setBounds(x, y, w, h);
4632N/A intersection(srcCopyAreaRect, copyAreaBounds, srcCopyAreaRect);
4632N/A if ((srcCopyAreaRect.width <= 0) || (srcCopyAreaRect.height <= 0)) {
4632N/A // src rect outside bounds
4632N/A return null;
4632N/A }
4632N/A
4632N/A // clip dst rect
4632N/A dstCopyAreaRect.setBounds(srcCopyAreaRect.x + dx, srcCopyAreaRect.y + dy, srcCopyAreaRect.width, srcCopyAreaRect.height);
4632N/A intersection(dstCopyAreaRect, copyAreaBounds, dstCopyAreaRect);
4632N/A if ((dstCopyAreaRect.width <= 0) || (dstCopyAreaRect.height <= 0)) {
4632N/A // dst rect outside clip
4632N/A return null;
4632N/A }
4632N/A
4632N/A x = dstCopyAreaRect.x - dx;
4632N/A y = dstCopyAreaRect.y - dy;
4632N/A w = dstCopyAreaRect.width;
4632N/A h = dstCopyAreaRect.height;
4632N/A
4632N/A finalCopyAreaRect.setBounds(x, y, w, h);
4632N/A
4632N/A return finalCopyAreaRect;
4632N/A }
4632N/A
4632N/A // <rdar://3785539> We only need to mark dirty on screen surfaces. This method is
4632N/A // marked as protected and it is intended for subclasses to override if they need to
4632N/A // be notified when the surface is dirtied. See CPeerSurfaceData.markDirty() for implementation.
4632N/A // We don't do anything for buffered images.
4632N/A protected void markDirty(boolean markAsDirty) {
4632N/A // do nothing by default
4632N/A }
4632N/A
4632N/A // LazyDrawing optimization implementation:
4632N/A
4632N/A @Override
4632N/A public boolean canRenderLCDText(SunGraphics2D sg2d) {
4632N/A if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
4632N/A sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
4632N/A sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&
4632N/A // sg2d.surfaceData.getTransparency() == Transparency.OPAQUE &&
4632N/A // This last test is a workaround until we fix loop selection
4632N/A // in the pipe validation
4632N/A sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { return true; }
4632N/A return false; /* for now - in the future we may want to search */
4632N/A }
4632N/A
4632N/A public static boolean IsSimpleColor(Object c) {
4632N/A return ((c instanceof Color) || (c instanceof SystemColor) || (c instanceof javax.swing.plaf.ColorUIResource));
4632N/A }
4632N/A
4632N/A static {
4632N/A if ((kColorPointerIndex % 2) != 0) {
4632N/A System.err.println("kColorPointerIndex=" + kColorPointerIndex + " is NOT aligned for 64 bit");
4632N/A System.exit(0);
4632N/A }
4632N/A }
4632N/A}