Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/SurfaceData.java
38829 views
/*1* Copyright (c) 1999, 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.Color;28import java.awt.Rectangle;29import java.awt.Transparency;30import java.awt.GraphicsConfiguration;31import java.awt.Image;32import java.awt.image.ColorModel;33import java.awt.image.IndexColorModel;34import java.awt.image.Raster;3536import sun.java2d.loops.RenderCache;37import sun.java2d.loops.RenderLoops;38import sun.java2d.loops.CompositeType;39import sun.java2d.loops.SurfaceType;40import sun.java2d.loops.MaskFill;41import sun.java2d.loops.DrawLine;42import sun.java2d.loops.FillRect;43import sun.java2d.loops.DrawRect;44import sun.java2d.loops.DrawPolygons;45import sun.java2d.loops.DrawPath;46import sun.java2d.loops.FillPath;47import sun.java2d.loops.FillSpans;48import sun.java2d.loops.FillParallelogram;49import sun.java2d.loops.DrawParallelogram;50import sun.java2d.loops.FontInfo;51import sun.java2d.loops.DrawGlyphList;52import sun.java2d.loops.DrawGlyphListAA;53import sun.java2d.loops.DrawGlyphListLCD;54import sun.java2d.pipe.LoopPipe;55import sun.java2d.pipe.ShapeDrawPipe;56import sun.java2d.pipe.ParallelogramPipe;57import sun.java2d.pipe.CompositePipe;58import sun.java2d.pipe.GeneralCompositePipe;59import sun.java2d.pipe.SpanClipRenderer;60import sun.java2d.pipe.SpanShapeRenderer;61import sun.java2d.pipe.AAShapePipe;62import sun.java2d.pipe.AlphaPaintPipe;63import sun.java2d.pipe.AlphaColorPipe;64import sun.java2d.pipe.PixelToShapeConverter;65import sun.java2d.pipe.PixelToParallelogramConverter;66import sun.java2d.pipe.TextPipe;67import sun.java2d.pipe.TextRenderer;68import sun.java2d.pipe.AATextRenderer;69import sun.java2d.pipe.LCDTextRenderer;70import sun.java2d.pipe.SolidTextRenderer;71import sun.java2d.pipe.OutlineTextRenderer;72import sun.java2d.pipe.DrawImagePipe;73import sun.java2d.pipe.DrawImage;74import sun.awt.SunHints;75import sun.awt.image.SurfaceManager;76import sun.java2d.pipe.LoopBasedPipe;7778/**79* This class provides various pieces of information relevant to a80* particular drawing surface. The information obtained from this81* object describes the pixels of a particular instance of a drawing82* surface and can only be shared among the various graphics objects83* that target the same BufferedImage or the same screen Component.84* <p>85* Each SurfaceData object holds a StateTrackableDelegate object86* which tracks both changes to the content of the pixels of this87* surface and changes to the overall state of the pixels - such88* as becoming invalid or losing the surface. The delegate is89* marked "dirty" whenever the setSurfaceLost() or invalidate()90* methods are called and should also be marked "dirty" by the91* rendering pipelines whenever they modify the pixels of this92* SurfaceData.93* <p>94* If you get a StateTracker from a SurfaceData and it reports95* that it is still "current", then you can trust that the pixels96* have not changed and that the SurfaceData is still valid and97* has not lost its underlying storage (surfaceLost) since you98* retrieved the tracker.99*/100public abstract class SurfaceData101implements Transparency, DisposerTarget, StateTrackable, Surface102{103private long pData;104private boolean valid;105private boolean surfaceLost; // = false;106private SurfaceType surfaceType;107private ColorModel colorModel;108109private Object disposerReferent = new Object();110111private static native void initIDs();112113private Object blitProxyKey;114private StateTrackableDelegate stateDelegate;115116static {117initIDs();118}119120protected SurfaceData(SurfaceType surfaceType, ColorModel cm) {121this(State.STABLE, surfaceType, cm);122}123124protected SurfaceData(State state, SurfaceType surfaceType, ColorModel cm) {125this(StateTrackableDelegate.createInstance(state), surfaceType, cm);126}127128protected SurfaceData(StateTrackableDelegate trackable,129SurfaceType surfaceType, ColorModel cm)130{131this.stateDelegate = trackable;132this.colorModel = cm;133this.surfaceType = surfaceType;134valid = true;135}136137protected SurfaceData(State state) {138this.stateDelegate = StateTrackableDelegate.createInstance(state);139valid = true;140}141142/**143* Subclasses can set a "blit proxy key" which will be used144* along with the SurfaceManager.getCacheData() mechanism to145* store acceleration-compatible cached copies of source images.146* This key is a "tag" used to identify which cached copies147* are compatible with this destination SurfaceData.148* The getSourceSurfaceData() method uses this key to manage149* cached copies of a source image as described below.150* <p>151* The Object used as this key should be as unique as it needs152* to be to ensure that multiple acceleratible destinations can153* each store their cached copies separately under different keys154* without interfering with each other or getting back the wrong155* cached copy.156* <p>157* Many acceleratable SurfaceData objects can use their own158* GraphicsConfiguration as their proxy key as the GC object will159* typically be unique to a given screen and pixel format, but160* other rendering destinations may have more or less stringent161* sharing requirements. For instance, X11 pixmaps can be162* shared on a given screen by any GraphicsConfiguration that163* has the same depth and SurfaceType. Multiple such GCs with164* the same depth and SurfaceType can exist per screen so storing165* a different cached proxy for each would be a waste. One can166* imagine platforms where a single cached copy can be created167* and shared across all screens and pixel formats - such168* implementations could use a single heavily shared key Object.169*/170protected void setBlitProxyKey(Object key) {171// Caching is effectively disabled if we never have a proxy key172// since the getSourceSurfaceData() method only does caching173// if the key is not null.174if (SurfaceDataProxy.isCachingAllowed()) {175this.blitProxyKey = key;176}177}178179/**180* This method is called on a destination SurfaceData to choose181* the best SurfaceData from a source Image for an imaging182* operation, with help from its SurfaceManager.183* The method may determine that the default SurfaceData was184* really the best choice in the first place, or it may decide185* to use a cached surface. Some general decisions about whether186* acceleration is enabled are made by this method, but any187* decision based on the type of the source image is made in188* the makeProxyFor method below when it comes up with the189* appropriate SurfaceDataProxy instance.190* The parameters describe the type of imaging operation being performed.191* <p>192* If a blitProxyKey was supplied by the subclass then it is193* used to potentially override the choice of source SurfaceData.194* The outline of this process is:195* <ol>196* <li> Image pipeline asks destSD to find an appropriate197* srcSD for a given source Image object.198* <li> destSD gets the SurfaceManager of the source Image199* and first retrieves the default SD from it using200* getPrimarySurfaceData()201* <li> destSD uses its "blit proxy key" (if set) to look for202* some cached data stored in the source SurfaceManager203* <li> If the cached data is null then makeProxyFor() is used204* to create some cached data which is stored back in the205* source SurfaceManager under the same key for future uses.206* <li> The cached data will be a SurfaceDataProxy object.207* <li> The SurfaceDataProxy object is then consulted to208* return a replacement SurfaceData object (typically209* a cached copy if appropriate, or the original if not).210* </ol>211*/212public SurfaceData getSourceSurfaceData(Image img,213int txtype,214CompositeType comp,215Color bgColor)216{217SurfaceManager srcMgr = SurfaceManager.getManager(img);218SurfaceData srcData = srcMgr.getPrimarySurfaceData();219if (img.getAccelerationPriority() > 0.0f &&220blitProxyKey != null)221{222SurfaceDataProxy sdp =223(SurfaceDataProxy) srcMgr.getCacheData(blitProxyKey);224if (sdp == null || !sdp.isValid()) {225if (srcData.getState() == State.UNTRACKABLE) {226sdp = SurfaceDataProxy.UNCACHED;227} else {228sdp = makeProxyFor(srcData);229}230srcMgr.setCacheData(blitProxyKey, sdp);231}232srcData = sdp.replaceData(srcData, txtype, comp, bgColor);233}234return srcData;235}236237/**238* This method is called on a destination SurfaceData to choose239* a proper SurfaceDataProxy subclass for a source SurfaceData240* to use to control when and with what surface to override a241* given image operation. The argument is the default SurfaceData242* for the source Image.243* <p>244* The type of the return object is chosen based on the245* acceleration capabilities of this SurfaceData and the246* type of the given source SurfaceData object.247* <p>248* In some cases the original SurfaceData will always be the249* best choice to use to blit to this SurfaceData. This can250* happen if the source image is a hardware surface of the251* same type as this one and so acceleration will happen without252* any caching. It may also be the case that the source image253* can never be accelerated on this SurfaceData - for example254* because it is translucent and there are no accelerated255* translucent image ops for this surface.256* <p>257* In those cases there is a special SurfaceDataProxy.UNCACHED258* instance that represents a NOP for caching purposes - it259* always returns the original sourceSD object as the replacement260* copy so no caching is ever performed.261*/262public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {263return SurfaceDataProxy.UNCACHED;264}265266/**267* Extracts the SurfaceManager from the given Image, and then268* returns the SurfaceData object that would best be suited as the269* destination surface in some rendering operation.270*/271public static SurfaceData getPrimarySurfaceData(Image img) {272SurfaceManager sMgr = SurfaceManager.getManager(img);273return sMgr.getPrimarySurfaceData();274}275276/**277* Restores the contents of the given Image and then returns the new278* SurfaceData object in use by the Image's SurfaceManager.279*/280public static SurfaceData restoreContents(Image img) {281SurfaceManager sMgr = SurfaceManager.getManager(img);282return sMgr.restoreContents();283}284285public State getState() {286return stateDelegate.getState();287}288289public StateTracker getStateTracker() {290return stateDelegate.getStateTracker();291}292293/**294* Marks this surface as dirty.295*/296public final void markDirty() {297stateDelegate.markDirty();298}299300/**301* Sets the value of the surfaceLost variable, which indicates whether302* something has happened to the rendering surface such that it needs303* to be restored and re-rendered.304*/305public void setSurfaceLost(boolean lost) {306surfaceLost = lost;307stateDelegate.markDirty();308}309310public boolean isSurfaceLost() {311return surfaceLost;312}313314/**315* Returns a boolean indicating whether or not this SurfaceData is valid.316*/317public final boolean isValid() {318return valid;319}320321public Object getDisposerReferent() {322return disposerReferent;323}324325public long getNativeOps() {326return pData;327}328329/**330* Sets this SurfaceData object to the invalid state. All Graphics331* objects must get a new SurfaceData object via the refresh method332* and revalidate their pipelines before continuing.333*/334public void invalidate() {335valid = false;336stateDelegate.markDirty();337}338339/**340* Certain changes in the configuration of a surface require the341* invalidation of existing associated SurfaceData objects and342* the creation of brand new ones. These changes include size,343* ColorModel, or SurfaceType. Existing Graphics objects344* which are directed at such surfaces, however, must continue345* to render to them even after the change occurs underneath346* the covers. The getReplacement() method is called from347* SunGraphics2D.revalidateAll() when the associated SurfaceData348* is found to be invalid so that a Graphics object can continue349* to render to the surface in its new configuration.350*351* Such changes only tend to happen to window based surfaces since352* most image based surfaces never change size or pixel format.353* Even VolatileImage objects never change size and they only354* change their pixel format when manually validated against a355* new GraphicsConfiguration, at which point old Graphics objects356* are no longer expected to render to them after the validation357* step. Thus, only window based surfaces really need to deal358* with this form of replacement.359*/360public abstract SurfaceData getReplacement();361362protected static final LoopPipe colorPrimitives;363364public static final TextPipe outlineTextRenderer;365public static final TextPipe solidTextRenderer;366public static final TextPipe aaTextRenderer;367public static final TextPipe lcdTextRenderer;368369protected static final AlphaColorPipe colorPipe;370protected static final PixelToShapeConverter colorViaShape;371protected static final PixelToParallelogramConverter colorViaPgram;372protected static final TextPipe colorText;373protected static final CompositePipe clipColorPipe;374protected static final TextPipe clipColorText;375protected static final AAShapePipe AAColorShape;376protected static final PixelToParallelogramConverter AAColorViaShape;377protected static final PixelToParallelogramConverter AAColorViaPgram;378protected static final AAShapePipe AAClipColorShape;379protected static final PixelToParallelogramConverter AAClipColorViaShape;380381protected static final CompositePipe paintPipe;382protected static final SpanShapeRenderer paintShape;383protected static final PixelToShapeConverter paintViaShape;384protected static final TextPipe paintText;385protected static final CompositePipe clipPaintPipe;386protected static final TextPipe clipPaintText;387protected static final AAShapePipe AAPaintShape;388protected static final PixelToParallelogramConverter AAPaintViaShape;389protected static final AAShapePipe AAClipPaintShape;390protected static final PixelToParallelogramConverter AAClipPaintViaShape;391392protected static final CompositePipe compPipe;393protected static final SpanShapeRenderer compShape;394protected static final PixelToShapeConverter compViaShape;395protected static final TextPipe compText;396protected static final CompositePipe clipCompPipe;397protected static final TextPipe clipCompText;398protected static final AAShapePipe AACompShape;399protected static final PixelToParallelogramConverter AACompViaShape;400protected static final AAShapePipe AAClipCompShape;401protected static final PixelToParallelogramConverter AAClipCompViaShape;402403protected static final DrawImagePipe imagepipe;404405// Utility subclass to add the LoopBasedPipe tagging interface406static class PixelToShapeLoopConverter407extends PixelToShapeConverter408implements LoopBasedPipe409{410public PixelToShapeLoopConverter(ShapeDrawPipe pipe) {411super(pipe);412}413}414415// Utility subclass to add the LoopBasedPipe tagging interface416static class PixelToPgramLoopConverter417extends PixelToParallelogramConverter418implements LoopBasedPipe419{420public PixelToPgramLoopConverter(ShapeDrawPipe shapepipe,421ParallelogramPipe pgrampipe,422double minPenSize,423double normPosition,424boolean adjustfill)425{426super(shapepipe, pgrampipe, minPenSize, normPosition, adjustfill);427}428}429430private static PixelToParallelogramConverter431makeConverter(AAShapePipe renderer,432ParallelogramPipe pgrampipe)433{434return new PixelToParallelogramConverter(renderer,435pgrampipe,4361.0/8.0, 0.499,437false);438}439440private static PixelToParallelogramConverter441makeConverter(AAShapePipe renderer)442{443return makeConverter(renderer, renderer);444}445446static {447colorPrimitives = new LoopPipe();448449outlineTextRenderer = new OutlineTextRenderer();450solidTextRenderer = new SolidTextRenderer();451aaTextRenderer = new AATextRenderer();452lcdTextRenderer = new LCDTextRenderer();453454colorPipe = new AlphaColorPipe();455// colorShape = colorPrimitives;456colorViaShape = new PixelToShapeLoopConverter(colorPrimitives);457colorViaPgram = new PixelToPgramLoopConverter(colorPrimitives,458colorPrimitives,4591.0, 0.25, true);460colorText = new TextRenderer(colorPipe);461clipColorPipe = new SpanClipRenderer(colorPipe);462clipColorText = new TextRenderer(clipColorPipe);463AAColorShape = new AAShapePipe(colorPipe);464AAColorViaShape = makeConverter(AAColorShape);465AAColorViaPgram = makeConverter(AAColorShape, colorPipe);466AAClipColorShape = new AAShapePipe(clipColorPipe);467AAClipColorViaShape = makeConverter(AAClipColorShape);468469paintPipe = new AlphaPaintPipe();470paintShape = new SpanShapeRenderer.Composite(paintPipe);471paintViaShape = new PixelToShapeConverter(paintShape);472paintText = new TextRenderer(paintPipe);473clipPaintPipe = new SpanClipRenderer(paintPipe);474clipPaintText = new TextRenderer(clipPaintPipe);475AAPaintShape = new AAShapePipe(paintPipe);476AAPaintViaShape = makeConverter(AAPaintShape);477AAClipPaintShape = new AAShapePipe(clipPaintPipe);478AAClipPaintViaShape = makeConverter(AAClipPaintShape);479480compPipe = new GeneralCompositePipe();481compShape = new SpanShapeRenderer.Composite(compPipe);482compViaShape = new PixelToShapeConverter(compShape);483compText = new TextRenderer(compPipe);484clipCompPipe = new SpanClipRenderer(compPipe);485clipCompText = new TextRenderer(clipCompPipe);486AACompShape = new AAShapePipe(compPipe);487AACompViaShape = makeConverter(AACompShape);488AAClipCompShape = new AAShapePipe(clipCompPipe);489AAClipCompViaShape = makeConverter(AAClipCompShape);490491imagepipe = new DrawImage();492}493494/* Not all surfaces and rendering mode combinations support LCD text. */495static final int LOOP_UNKNOWN = 0;496static final int LOOP_FOUND = 1;497static final int LOOP_NOTFOUND = 2;498int haveLCDLoop;499int havePgramXORLoop;500int havePgramSolidLoop;501502public boolean canRenderLCDText(SunGraphics2D sg2d) {503// For now the answer can only be true in the following cases:504if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&505sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&506sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&507sg2d.surfaceData.getTransparency() == Transparency.OPAQUE)508{509if (haveLCDLoop == LOOP_UNKNOWN) {510DrawGlyphListLCD loop =511DrawGlyphListLCD.locate(SurfaceType.AnyColor,512CompositeType.SrcNoEa,513getSurfaceType());514haveLCDLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;515}516return haveLCDLoop == LOOP_FOUND;517}518return false; /* for now - in the future we may want to search */519}520521public boolean canRenderParallelograms(SunGraphics2D sg2d) {522if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {523if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {524if (havePgramXORLoop == LOOP_UNKNOWN) {525FillParallelogram loop =526FillParallelogram.locate(SurfaceType.AnyColor,527CompositeType.Xor,528getSurfaceType());529havePgramXORLoop =530(loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;531}532return havePgramXORLoop == LOOP_FOUND;533} else if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&534sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&535sg2d.clipState != SunGraphics2D.CLIP_SHAPE)536{537if (havePgramSolidLoop == LOOP_UNKNOWN) {538FillParallelogram loop =539FillParallelogram.locate(SurfaceType.AnyColor,540CompositeType.SrcNoEa,541getSurfaceType());542havePgramSolidLoop =543(loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;544}545return havePgramSolidLoop == LOOP_FOUND;546}547}548return false;549}550551public void validatePipe(SunGraphics2D sg2d) {552sg2d.imagepipe = imagepipe;553if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {554if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) {555sg2d.drawpipe = paintViaShape;556sg2d.fillpipe = paintViaShape;557sg2d.shapepipe = paintShape;558// REMIND: Ideally custom paint mode would use glyph559// rendering as opposed to outline rendering but the560// glyph paint rendering pipeline uses MaskBlit which561// is not defined for XOR. This means that text drawn562// in XOR mode with a Color object is different than563// text drawn in XOR mode with a Paint object.564sg2d.textpipe = outlineTextRenderer;565} else {566PixelToShapeConverter converter;567if (canRenderParallelograms(sg2d)) {568converter = colorViaPgram;569// Note that we use the transforming pipe here because it570// will examine the shape and possibly perform an optimized571// operation if it can be simplified. The simplifications572// will be valid for all STROKE and TRANSFORM types.573sg2d.shapepipe = colorViaPgram;574} else {575converter = colorViaShape;576sg2d.shapepipe = colorPrimitives;577}578if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {579sg2d.drawpipe = converter;580sg2d.fillpipe = converter;581// REMIND: We should not be changing text strategies582// between outline and glyph rendering based upon the583// presence of a complex clip as that could cause a584// mismatch when drawing the same text both clipped585// and unclipped on two separate rendering passes.586// Unfortunately, all of the clipped glyph rendering587// pipelines rely on the use of the MaskBlit operation588// which is not defined for XOR.589sg2d.textpipe = outlineTextRenderer;590} else {591if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {592sg2d.drawpipe = converter;593sg2d.fillpipe = converter;594} else {595if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {596sg2d.drawpipe = converter;597} else {598sg2d.drawpipe = colorPrimitives;599}600sg2d.fillpipe = colorPrimitives;601}602sg2d.textpipe = solidTextRenderer;603}604// assert(sg2d.surfaceData == this);605}606} else if (sg2d.compositeState == SunGraphics2D.COMP_CUSTOM) {607if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) {608if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {609sg2d.drawpipe = AAClipCompViaShape;610sg2d.fillpipe = AAClipCompViaShape;611sg2d.shapepipe = AAClipCompViaShape;612sg2d.textpipe = clipCompText;613} else {614sg2d.drawpipe = AACompViaShape;615sg2d.fillpipe = AACompViaShape;616sg2d.shapepipe = AACompViaShape;617sg2d.textpipe = compText;618}619} else {620sg2d.drawpipe = compViaShape;621sg2d.fillpipe = compViaShape;622sg2d.shapepipe = compShape;623if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {624sg2d.textpipe = clipCompText;625} else {626sg2d.textpipe = compText;627}628}629} else if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) {630sg2d.alphafill = getMaskFill(sg2d);631// assert(sg2d.surfaceData == this);632if (sg2d.alphafill != null) {633if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {634sg2d.drawpipe = AAClipColorViaShape;635sg2d.fillpipe = AAClipColorViaShape;636sg2d.shapepipe = AAClipColorViaShape;637sg2d.textpipe = clipColorText;638} else {639PixelToParallelogramConverter converter =640(sg2d.alphafill.canDoParallelograms()641? AAColorViaPgram642: AAColorViaShape);643sg2d.drawpipe = converter;644sg2d.fillpipe = converter;645sg2d.shapepipe = converter;646if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR ||647sg2d.compositeState > SunGraphics2D.COMP_ISCOPY)648{649sg2d.textpipe = colorText;650} else {651sg2d.textpipe = getTextPipe(sg2d, true /* AA==ON */);652}653}654} else {655if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {656sg2d.drawpipe = AAClipPaintViaShape;657sg2d.fillpipe = AAClipPaintViaShape;658sg2d.shapepipe = AAClipPaintViaShape;659sg2d.textpipe = clipPaintText;660} else {661sg2d.drawpipe = AAPaintViaShape;662sg2d.fillpipe = AAPaintViaShape;663sg2d.shapepipe = AAPaintViaShape;664sg2d.textpipe = paintText;665}666}667} else if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR ||668sg2d.compositeState > SunGraphics2D.COMP_ISCOPY ||669sg2d.clipState == SunGraphics2D.CLIP_SHAPE)670{671sg2d.drawpipe = paintViaShape;672sg2d.fillpipe = paintViaShape;673sg2d.shapepipe = paintShape;674sg2d.alphafill = getMaskFill(sg2d);675// assert(sg2d.surfaceData == this);676if (sg2d.alphafill != null) {677if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {678sg2d.textpipe = clipColorText;679} else {680sg2d.textpipe = colorText;681}682} else {683if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {684sg2d.textpipe = clipPaintText;685} else {686sg2d.textpipe = paintText;687}688}689} else {690PixelToShapeConverter converter;691if (canRenderParallelograms(sg2d)) {692converter = colorViaPgram;693// Note that we use the transforming pipe here because it694// will examine the shape and possibly perform an optimized695// operation if it can be simplified. The simplifications696// will be valid for all STROKE and TRANSFORM types.697sg2d.shapepipe = colorViaPgram;698} else {699converter = colorViaShape;700sg2d.shapepipe = colorPrimitives;701}702if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {703sg2d.drawpipe = converter;704sg2d.fillpipe = converter;705} else {706if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {707sg2d.drawpipe = converter;708} else {709sg2d.drawpipe = colorPrimitives;710}711sg2d.fillpipe = colorPrimitives;712}713714sg2d.textpipe = getTextPipe(sg2d, false /* AA==OFF */);715// assert(sg2d.surfaceData == this);716}717718// check for loops719if (sg2d.textpipe instanceof LoopBasedPipe ||720sg2d.shapepipe instanceof LoopBasedPipe ||721sg2d.fillpipe instanceof LoopBasedPipe ||722sg2d.drawpipe instanceof LoopBasedPipe ||723sg2d.imagepipe instanceof LoopBasedPipe)724{725sg2d.loops = getRenderLoops(sg2d);726}727}728729/* Return the text pipe to be used based on the graphics AA hint setting,730* and the rest of the graphics state is compatible with these loops.731* If the text AA hint is "DEFAULT", then the AA graphics hint requests732* the AA text renderer, else it requests the B&W text renderer.733*/734private TextPipe getTextPipe(SunGraphics2D sg2d, boolean aaHintIsOn) {735736/* Try to avoid calling getFontInfo() unless its needed to737* resolve one of the new AA types.738*/739switch (sg2d.textAntialiasHint) {740case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT:741if (aaHintIsOn) {742return aaTextRenderer;743} else {744return solidTextRenderer;745}746case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:747return solidTextRenderer;748749case SunHints.INTVAL_TEXT_ANTIALIAS_ON:750return aaTextRenderer;751752default:753switch (sg2d.getFontInfo().aaHint) {754755case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:756case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:757return lcdTextRenderer;758759case SunHints.INTVAL_TEXT_ANTIALIAS_ON:760return aaTextRenderer;761762case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:763return solidTextRenderer;764765/* This should not be reached as the FontInfo will766* always explicitly set its hint value. So whilst767* this could be collapsed to returning say just768* solidTextRenderer, or even removed, its left769* here in case DEFAULT is ever passed in.770*/771default:772if (aaHintIsOn) {773return aaTextRenderer;774} else {775return solidTextRenderer;776}777}778}779}780781private static SurfaceType getPaintSurfaceType(SunGraphics2D sg2d) {782switch (sg2d.paintState) {783case SunGraphics2D.PAINT_OPAQUECOLOR:784return SurfaceType.OpaqueColor;785case SunGraphics2D.PAINT_ALPHACOLOR:786return SurfaceType.AnyColor;787case SunGraphics2D.PAINT_GRADIENT:788if (sg2d.paint.getTransparency() == OPAQUE) {789return SurfaceType.OpaqueGradientPaint;790} else {791return SurfaceType.GradientPaint;792}793case SunGraphics2D.PAINT_LIN_GRADIENT:794if (sg2d.paint.getTransparency() == OPAQUE) {795return SurfaceType.OpaqueLinearGradientPaint;796} else {797return SurfaceType.LinearGradientPaint;798}799case SunGraphics2D.PAINT_RAD_GRADIENT:800if (sg2d.paint.getTransparency() == OPAQUE) {801return SurfaceType.OpaqueRadialGradientPaint;802} else {803return SurfaceType.RadialGradientPaint;804}805case SunGraphics2D.PAINT_TEXTURE:806if (sg2d.paint.getTransparency() == OPAQUE) {807return SurfaceType.OpaqueTexturePaint;808} else {809return SurfaceType.TexturePaint;810}811default:812case SunGraphics2D.PAINT_CUSTOM:813return SurfaceType.AnyPaint;814}815}816817private static CompositeType getFillCompositeType(SunGraphics2D sg2d) {818CompositeType compType = sg2d.imageComp;819if (sg2d.compositeState == SunGraphics2D.COMP_ISCOPY) {820if (compType == CompositeType.SrcOverNoEa) {821compType = CompositeType.OpaqueSrcOverNoEa;822} else {823compType = CompositeType.SrcNoEa;824}825}826return compType;827}828829/**830* Returns a MaskFill object that can be used on this destination831* with the source (paint) and composite types determined by the given832* SunGraphics2D, or null if no such MaskFill object can be located.833* Subclasses can override this method if they wish to filter other834* attributes (such as the hardware capabilities of the destination835* surface) before returning a specific MaskFill object.836*/837protected MaskFill getMaskFill(SunGraphics2D sg2d) {838SurfaceType src = getPaintSurfaceType(sg2d);839CompositeType comp = getFillCompositeType(sg2d);840SurfaceType dst = getSurfaceType();841return MaskFill.getFromCache(src, comp, dst);842}843844private static RenderCache loopcache = new RenderCache(30);845846/**847* Return a RenderLoops object containing all of the basic848* GraphicsPrimitive objects for rendering to the destination849* surface with the current attributes of the given SunGraphics2D.850*/851public RenderLoops getRenderLoops(SunGraphics2D sg2d) {852SurfaceType src = getPaintSurfaceType(sg2d);853CompositeType comp = getFillCompositeType(sg2d);854SurfaceType dst = sg2d.getSurfaceData().getSurfaceType();855856Object o = loopcache.get(src, comp, dst);857if (o != null) {858return (RenderLoops) o;859}860861RenderLoops loops = makeRenderLoops(src, comp, dst);862loopcache.put(src, comp, dst, loops);863return loops;864}865866/**867* Construct and return a RenderLoops object containing all of868* the basic GraphicsPrimitive objects for rendering to the869* destination surface with the given source, destination, and870* composite types.871*/872public static RenderLoops makeRenderLoops(SurfaceType src,873CompositeType comp,874SurfaceType dst)875{876RenderLoops loops = new RenderLoops();877loops.drawLineLoop = DrawLine.locate(src, comp, dst);878loops.fillRectLoop = FillRect.locate(src, comp, dst);879loops.drawRectLoop = DrawRect.locate(src, comp, dst);880loops.drawPolygonsLoop = DrawPolygons.locate(src, comp, dst);881loops.drawPathLoop = DrawPath.locate(src, comp, dst);882loops.fillPathLoop = FillPath.locate(src, comp, dst);883loops.fillSpansLoop = FillSpans.locate(src, comp, dst);884loops.fillParallelogramLoop = FillParallelogram.locate(src, comp, dst);885loops.drawParallelogramLoop = DrawParallelogram.locate(src, comp, dst);886loops.drawGlyphListLoop = DrawGlyphList.locate(src, comp, dst);887loops.drawGlyphListAALoop = DrawGlyphListAA.locate(src, comp, dst);888loops.drawGlyphListLCDLoop = DrawGlyphListLCD.locate(src, comp, dst);889/*890System.out.println("drawLine: "+loops.drawLineLoop);891System.out.println("fillRect: "+loops.fillRectLoop);892System.out.println("drawRect: "+loops.drawRectLoop);893System.out.println("drawPolygons: "+loops.drawPolygonsLoop);894System.out.println("fillSpans: "+loops.fillSpansLoop);895System.out.println("drawGlyphList: "+loops.drawGlyphListLoop);896System.out.println("drawGlyphListAA: "+loops.drawGlyphListAALoop);897System.out.println("drawGlyphListLCD: "+loops.drawGlyphListLCDLoop);898*/899return loops;900}901902/**903* Return the GraphicsConfiguration object that describes this904* destination surface.905*/906public abstract GraphicsConfiguration getDeviceConfiguration();907908/**909* Return the SurfaceType object that describes the destination910* surface.911*/912public final SurfaceType getSurfaceType() {913return surfaceType;914}915916/**917* Return the ColorModel for the destination surface.918*/919public final ColorModel getColorModel() {920return colorModel;921}922923/**924* Returns the type of this <code>Transparency</code>.925* @return the field type of this <code>Transparency</code>, which is926* either OPAQUE, BITMASK or TRANSLUCENT.927*/928public int getTransparency() {929return getColorModel().getTransparency();930}931932/**933* Return a readable Raster which contains the pixels for the934* specified rectangular region of the destination surface.935* The coordinate origin of the returned Raster is the same as936* the device space origin of the destination surface.937* In some cases the returned Raster might also be writeable.938* In most cases, the returned Raster might contain more pixels939* than requested.940*941* @see useTightBBoxes942*/943public abstract Raster getRaster(int x, int y, int w, int h);944945/**946* Does the pixel accessibility of the destination surface947* suggest that rendering algorithms might want to take948* extra time to calculate a more accurate bounding box for949* the operation being performed?950* The typical case when this will be true is when a copy of951* the pixels has to be made when doing a getRaster. The952* fewer pixels copied, the faster the operation will go.953*954* @see getRaster955*/956public boolean useTightBBoxes() {957// Note: The native equivalent would trigger on VISIBLE_TO_NATIVE958// REMIND: This is not used - should be obsoleted maybe959return true;960}961962/**963* Returns the pixel data for the specified Argb value packed964* into an integer for easy storage and conveyance.965*/966public int pixelFor(int rgb) {967return surfaceType.pixelFor(rgb, colorModel);968}969970/**971* Returns the pixel data for the specified color packed into an972* integer for easy storage and conveyance.973*974* This method will use the getRGB() method of the Color object975* and defer to the pixelFor(int rgb) method if not overridden.976*977* For now this is a convenience function, but for cases where978* the highest quality color conversion is requested, this method979* should be overridden in those cases so that a more direct980* conversion of the color to the destination color space981* can be done using the additional information in the Color982* object.983*/984public int pixelFor(Color c) {985return pixelFor(c.getRGB());986}987988/**989* Returns the Argb representation for the specified integer value990* which is packed in the format of the associated ColorModel.991*/992public int rgbFor(int pixel) {993return surfaceType.rgbFor(pixel, colorModel);994}995996/**997* Returns the bounds of the destination surface.998*/999public abstract Rectangle getBounds();10001001static java.security.Permission compPermission;10021003/**1004* Performs Security Permissions checks to see if a Custom1005* Composite object should be allowed access to the pixels1006* of this surface.1007*/1008protected void checkCustomComposite() {1009SecurityManager sm = System.getSecurityManager();1010if (sm != null) {1011if (compPermission == null) {1012compPermission =1013new java.awt.AWTPermission("readDisplayPixels");1014}1015sm.checkPermission(compPermission);1016}1017}10181019/**1020* Fetches private field IndexColorModel.allgrayopaque1021* which is true when all palette entries in the color1022* model are gray and opaque.1023*/1024protected static native boolean isOpaqueGray(IndexColorModel icm);10251026/**1027* For our purposes null and NullSurfaceData are the same as1028* they represent a disposed surface.1029*/1030public static boolean isNull(SurfaceData sd) {1031if (sd == null || sd == NullSurfaceData.theInstance) {1032return true;1033}1034return false;1035}10361037/**1038* Performs a copyarea within this surface. Returns1039* false if there is no algorithm to perform the copyarea1040* given the current settings of the SunGraphics2D.1041*/1042public boolean copyArea(SunGraphics2D sg2d,1043int x, int y, int w, int h, int dx, int dy)1044{1045return false;1046}10471048/**1049* Synchronously releases resources associated with this surface.1050*/1051public void flush() {}10521053/**1054* Returns destination associated with this SurfaceData. This could be1055* either an Image or a Component; subclasses of SurfaceData are1056* responsible for returning the appropriate object.1057*/1058public abstract Object getDestination();10591060/**1061* Returns default scale factor of the destination surface. Scale factor1062* describes the mapping between virtual and physical coordinates of the1063* SurfaceData. If the scale is 2 then virtual pixel coordinates need to be1064* doubled for physical pixels.1065*/1066public int getDefaultScale() {1067return 1;1068}1069}107010711072