int havePgramSolidLoop; public boolean canRenderLCDText(SunGraphics2D sg2d) { // For now the answer can only be true in the following cases: if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY && sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR && sg2d.surfaceData.getTransparency() == Transparency.OPAQUE) { if (haveLCDLoop == LOOP_UNKNOWN) { DrawGlyphListLCD loop = DrawGlyphListLCD.locate(SurfaceType.AnyColor, CompositeType.SrcNoEa, getSurfaceType()); haveLCDLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND; } return haveLCDLoop == LOOP_FOUND; } return false; /* for now - in the future we may want to search */ } public boolean canRenderParallelograms(SunGraphics2D sg2d) { if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) { if (sg2d.compositeState == sg2d.COMP_XOR) { if (havePgramXORLoop == LOOP_UNKNOWN) { FillParallelogram loop = FillParallelogram.locate(SurfaceType.AnyColor, CompositeType.Xor, getSurfaceType()); havePgramXORLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND; } return havePgramXORLoop == LOOP_FOUND; } else if (sg2d.compositeState <= sg2d.COMP_ISCOPY && sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && sg2d.clipState != sg2d.CLIP_SHAPE) { if (havePgramSolidLoop == LOOP_UNKNOWN) { FillParallelogram loop = FillParallelogram.locate(SurfaceType.AnyColor, CompositeType.SrcNoEa, getSurfaceType()); havePgramSolidLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND; } return havePgramSolidLoop == LOOP_FOUND; } } return false; } public void validatePipe(SunGraphics2D sg2d) { sg2d.imagepipe = imagepipe; if (sg2d.compositeState == sg2d.COMP_XOR) { if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR) { sg2d.drawpipe = paintViaShape; sg2d.fillpipe = paintViaShape; sg2d.shapepipe = paintShape; // REMIND: Ideally custom paint mode would use glyph // rendering as opposed to outline rendering but the // glyph paint rendering pipeline uses MaskBlit which // is not defined for XOR. This means that text drawn // in XOR mode with a Color object is different than // text drawn in XOR mode with a Paint object. sg2d.textpipe = outlineTextRenderer; } else { PixelToShapeConverter converter; if (canRenderParallelograms(sg2d)) { converter = colorViaPgram; // Note that we use the transforming pipe here because it // will examine the shape and possibly perform an optimized // operation if it can be simplified. The simplifications // will be valid for all STROKE and TRANSFORM types. sg2d.shapepipe = colorViaPgram; } else { converter = colorViaShape; sg2d.shapepipe = colorPrimitives; } if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = converter; sg2d.fillpipe = converter; // REMIND: We should not be changing text strategies // between outline and glyph rendering based upon the // presence of a complex clip as that could cause a // mismatch when drawing the same text both clipped // and unclipped on two separate rendering passes. // Unfortunately, all of the clipped glyph rendering // pipelines rely on the use of the MaskBlit operation // which is not defined for XOR. sg2d.textpipe = outlineTextRenderer; } else { if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { sg2d.drawpipe = converter; sg2d.fillpipe = converter; } else { if (sg2d.strokeState != sg2d.STROKE_THIN) { sg2d.drawpipe = converter; } else { sg2d.drawpipe = colorPrimitives; } sg2d.fillpipe = colorPrimitives; } sg2d.textpipe = solidTextRenderer; } // assert(sg2d.surfaceData == this); } } else if (sg2d.compositeState == sg2d.COMP_CUSTOM) { if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipCompViaShape; sg2d.fillpipe = AAClipCompViaShape; sg2d.shapepipe = AAClipCompViaShape; sg2d.textpipe = clipCompText; } else { sg2d.drawpipe = AACompViaShape; sg2d.fillpipe = AACompViaShape; sg2d.shapepipe = AACompViaShape; sg2d.textpipe = compText; } } else { sg2d.drawpipe = compViaShape; sg2d.fillpipe = compViaShape; sg2d.shapepipe = compShape; if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.textpipe = clipCompText; } else { sg2d.textpipe = compText; } } } else if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) { sg2d.alphafill = getMaskFill(sg2d); // assert(sg2d.surfaceData == this); if (sg2d.alphafill != null) { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipColorViaShape; sg2d.fillpipe = AAClipColorViaShape; sg2d.shapepipe = AAClipColorViaShape; sg2d.textpipe = clipColorText; } else { PixelToParallelogramConverter converter = (sg2d.alphafill.canDoParallelograms() ? AAColorViaPgram : AAColorViaShape); sg2d.drawpipe = converter; sg2d.fillpipe = converter; sg2d.shapepipe = converter; if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR || sg2d.compositeState > sg2d.COMP_ISCOPY) { sg2d.textpipe = colorText; } else { sg2d.textpipe = getTextPipe(sg2d, true /* AA==ON */); } } } else { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipPaintViaShape; sg2d.fillpipe = AAClipPaintViaShape; sg2d.shapepipe = AAClipPaintViaShape; sg2d.textpipe = clipPaintText; } else { sg2d.drawpipe = AAPaintViaShape; sg2d.fillpipe = AAPaintViaShape; sg2d.shapepipe = AAPaintViaShape; sg2d.textpipe = paintText; } } } else if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR || sg2d.compositeState > sg2d.COMP_ISCOPY || sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = paintViaShape; sg2d.fillpipe = paintViaShape; sg2d.shapepipe = paintShape; sg2d.alphafill = getMaskFill(sg2d); // assert(sg2d.surfaceData == this); if (sg2d.alphafill != null) { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.textpipe = clipColorText; } else { sg2d.textpipe = colorText; } } else { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.textpipe = clipPaintText; } else { sg2d.textpipe = paintText; } } } else { PixelToShapeConverter converter; if (canRenderParallelograms(sg2d)) { converter = colorViaPgram; // Note that we use the transforming pipe here because it // will examine the shape and possibly perform an optimized // operation if it can be simplified. The simplifications // will be valid for all STROKE and TRANSFORM types. sg2d.shapepipe = colorViaPgram; } else { converter = colorViaShape; sg2d.shapepipe = colorPrimitives; } if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { sg2d.drawpipe = converter; sg2d.fillpipe = converter; } else { if (sg2d.strokeState != sg2d.STROKE_THIN) { sg2d.drawpipe = converter; } else { sg2d.drawpipe = colorPrimitives; } sg2d.fillpipe = colorPrimitives; } sg2d.textpipe = getTextPipe(sg2d, false /* AA==OFF */); // assert(sg2d.surfaceData == this); } // check for loops if (sg2d.textpipe instanceof LoopBasedPipe || sg2d.shapepipe instanceof LoopBasedPipe || sg2d.fillpipe instanceof LoopBasedPipe || sg2d.drawpipe instanceof LoopBasedPipe || sg2d.imagepipe instanceof LoopBasedPipe) { sg2d.loops = getRenderLoops(sg2d); } } /* Return the text pipe to be used based on the graphics AA hint setting, * and the rest of the graphics state is compatible with these loops. * If the text AA hint is "DEFAULT", then the AA graphics hint requests * the AA text renderer, else it requests the B&W text renderer. */ private TextPipe getTextPipe(SunGraphics2D sg2d, boolean aaHintIsOn) { /* Try to avoid calling getFontInfo() unless its needed to * resolve one of the new AA types. */ switch (sg2d.textAntialiasHint) { case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT: if (aaHintIsOn) { return aaTextRenderer; } else { return solidTextRenderer; } case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: return solidTextRenderer; case SunHints.INTVAL_TEXT_ANTIALIAS_ON: return aaTextRenderer; default: switch (sg2d.getFontInfo().aaHint) { case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB: case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB: return lcdTextRenderer; case SunHints.INTVAL_TEXT_ANTIALIAS_ON: return aaTextRenderer; case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: return solidTextRenderer; /* This should not be reached as the FontInfo will * always explicitly set its hint value. So whilst * this could be collapsed to returning say just * solidTextRenderer, or even removed, its left * here in case DEFAULT is ever passed in. */ default: if (aaHintIsOn) { return aaTextRenderer; } else { return solidTextRenderer; } } } } private static SurfaceType getPaintSurfaceType(SunGraphics2D sg2d) { switch (sg2d.paintState) { case SunGraphics2D.PAINT_OPAQUECOLOR: return SurfaceType.OpaqueColor; case SunGraphics2D.PAINT_ALPHACOLOR: return SurfaceType.AnyColor; case SunGraphics2D.PAINT_GRADIENT: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueGradientPaint; } else { return SurfaceType.GradientPaint; } case SunGraphics2D.PAINT_LIN_GRADIENT: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueLinearGradientPaint; } else { return SurfaceType.LinearGradientPaint; } case SunGraphics2D.PAINT_RAD_GRADIENT: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueRadialGradientPaint; } else { return SurfaceType.RadialGradientPaint; } case SunGraphics2D.PAINT_TEXTURE: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueTexturePaint; } else { return SurfaceType.TexturePaint; } default: case SunGraphics2D.PAINT_CUSTOM: return SurfaceType.AnyPaint; } } private static CompositeType getFillCompositeType(SunGraphics2D sg2d) { CompositeType compType = sg2d.imageComp; if (sg2d.compositeState == sg2d.COMP_ISCOPY) { if (compType == CompositeType.SrcOverNoEa) { compType = CompositeType.OpaqueSrcOverNoEa; } else { compType = CompositeType.SrcNoEa; } } return compType; } /** * Returns a MaskFill object that can be used on this destination * with the source (paint) and composite types determined by the given * SunGraphics2D, or null if no such MaskFill object can be located. * Subclasses can override this method if they wish to filter other * attributes (such as the hardware capabilities of the destination * surface) before returning a specific MaskFill object. */ protected MaskFill getMaskFill(SunGraphics2D sg2d) { SurfaceType src = getPaintSurfaceType(sg2d); CompositeType comp = getFillCompositeType(sg2d); SurfaceType dst = getSurfaceType(); return MaskFill.getFromCache(src, comp, dst); } private static RenderCache loopcache = new RenderCache(30); /** * Return a RenderLoops object containing all of the basic * GraphicsPrimitive objects for rendering to the destination * surface with the current attributes of the given SunGraphics2D. */ public RenderLoops getRenderLoops(SunGraphics2D sg2d) { SurfaceType src = getPaintSurfaceType(sg2d); CompositeType comp = getFillCompositeType(sg2d); SurfaceType dst = sg2d.getSurfaceData().getSurfaceType(); Object o = loopcache.get(src, comp, dst); if (o != null) { return (RenderLoops) o; } RenderLoops loops = makeRenderLoops(src, comp, dst); loopcache.put(src, comp, dst, loops); return loops; } /** * Construct and return a RenderLoops object containing all of * the basic GraphicsPrimitive objects for rendering to the * destination surface with the given source, destination, and * composite types. */ public static RenderLoops makeRenderLoops(SurfaceType src, CompositeType comp, SurfaceType dst) { RenderLoops loops = new RenderLoops(); loops.drawLineLoop = DrawLine.locate(src, comp, dst); loops.fillRectLoop = FillRect.locate(src, comp, dst); loops.drawRectLoop = DrawRect.locate(src, comp, dst); loops.drawPolygonsLoop = DrawPolygons.locate(src, comp, dst); loops.drawPathLoop = DrawPath.locate(src, comp, dst); loops.fillPathLoop = FillPath.locate(src, comp, dst); loops.fillSpansLoop = FillSpans.locate(src, comp, dst); loops.fillParallelogramLoop = FillParallelogram.locate(src, comp, dst); loops.drawParallelogramLoop = DrawParallelogram.locate(src, comp, dst); loops.drawGlyphListLoop = DrawGlyphList.locate(src, comp, dst); loops.drawGlyphListAALoop = DrawGlyphListAA.locate(src, comp, dst); loops.drawGlyphListLCDLoop = DrawGlyphListLCD.locate(src, comp, dst); /* System.out.println("drawLine: "+loops.drawLineLoop); System.out.println("fillRect: "+loops.fillRectLoop); System.out.println("drawRect: "+loops.drawRectLoop); System.out.println("drawPolygons: "+loops.drawPolygonsLoop); System.out.println("fillSpans: "+loops.fillSpansLoop); System.out.println("drawGlyphList: "+loops.drawGlyphListLoop); System.out.println("drawGlyphListAA: "+loops.drawGlyphListAALoop); System.out.println("drawGlyphListLCD: "+loops.drawGlyphListLCDLoop); */ return loops; } /** * Return the GraphicsConfiguration object that describes this * destination surface. */ public abstract GraphicsConfiguration getDeviceConfiguration(); /** * Return the SurfaceType object that describes the destination * surface. */ public final SurfaceType getSurfaceType() { return surfaceType; } /** * Return the ColorModel for the destination surface. */ public final ColorModel getColorModel() { return colorModel; } /** * Returns the type of this <code>Transparency</code>. * @return the field type of this <code>Transparency</code>, which is * either OPAQUE, BITMASK or TRANSLUCENT. */ public int getTransparency() { return getColorModel().getTransparency(); } /** * Return a readable Raster which contains the pixels for the * specified rectangular region of the destination surface. * The coordinate origin of the returned Raster is the same as * the device space origin of the destination surface. * In some cases the returned Raster might also be writeable. * In most cases, the returned Raster might contain more pixels * than requested. * * @see useTightBBoxes */ public abstract Raster getRaster(int x, int y, int w, int h); /** * Does the pixel accessibility of the destination surface * suggest that rendering algorithms might want to take * extra time to calculate a more accurate bounding box for * the operation being performed? * The typical case when this will be true is when a copy of * the pixels has to be made when doing a getRaster. The * fewer pixels copied, the faster the operation will go. * * @see getRaster */ public boolean useTightBBoxes() { // Note: The native equivalent would trigger on VISIBLE_TO_NATIVE // REMIND: This is not used - should be obsoleted maybe return true; } /** * Returns the pixel data for the specified Argb value packed * into an integer for easy storage and conveyance. */ public int pixelFor(int rgb) { return surfaceType.pixelFor(rgb, colorModel); } /** * Returns the pixel data for the specified color packed into an * integer for easy storage and conveyance. * * This method will use the getRGB() method of the Color object * and defer to the pixelFor(int rgb) method if not overridden. * * For now this is a convenience function, but for cases where * the highest quality color conversion is requested, this method * should be overridden in those cases so that a more direct * conversion of the color to the destination color space * can be done using the additional information in the Color * object. */ public int pixelFor(Color c) { return pixelFor(c.getRGB()); } /** * Returns the Argb representation for the specified integer value * which is packed in the format of the associated ColorModel. */ public int rgbFor(int pixel) { return surfaceType.rgbFor(pixel, colorModel); } /** * Returns the bounds of the destination surface. */ public abstract Rectangle getBounds();Lines 501–1000 of 1060. Previous lines Load more
int havePgramSolidLoop; public boolean canRenderLCDText(SunGraphics2D sg2d) { // For now the answer can only be true in the following cases: if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY && sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR && sg2d.surfaceData.getTransparency() == Transparency.OPAQUE) { if (haveLCDLoop == LOOP_UNKNOWN) { DrawGlyphListLCD loop = DrawGlyphListLCD.locate(SurfaceType.AnyColor, CompositeType.SrcNoEa, getSurfaceType()); haveLCDLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND; } return haveLCDLoop == LOOP_FOUND; } return false; /* for now - in the future we may want to search */ } public boolean canRenderParallelograms(SunGraphics2D sg2d) { if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) { if (sg2d.compositeState == sg2d.COMP_XOR) { if (havePgramXORLoop == LOOP_UNKNOWN) { FillParallelogram loop = FillParallelogram.locate(SurfaceType.AnyColor, CompositeType.Xor, getSurfaceType()); havePgramXORLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND; } return havePgramXORLoop == LOOP_FOUND; } else if (sg2d.compositeState <= sg2d.COMP_ISCOPY && sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && sg2d.clipState != sg2d.CLIP_SHAPE) { if (havePgramSolidLoop == LOOP_UNKNOWN) { FillParallelogram loop = FillParallelogram.locate(SurfaceType.AnyColor, CompositeType.SrcNoEa, getSurfaceType()); havePgramSolidLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND; } return havePgramSolidLoop == LOOP_FOUND; } } return false; } public void validatePipe(SunGraphics2D sg2d) { sg2d.imagepipe = imagepipe; if (sg2d.compositeState == sg2d.COMP_XOR) { if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR) { sg2d.drawpipe = paintViaShape; sg2d.fillpipe = paintViaShape; sg2d.shapepipe = paintShape; // REMIND: Ideally custom paint mode would use glyph // rendering as opposed to outline rendering but the // glyph paint rendering pipeline uses MaskBlit which // is not defined for XOR. This means that text drawn // in XOR mode with a Color object is different than // text drawn in XOR mode with a Paint object. sg2d.textpipe = outlineTextRenderer; } else { PixelToShapeConverter converter; if (canRenderParallelograms(sg2d)) { converter = colorViaPgram; // Note that we use the transforming pipe here because it // will examine the shape and possibly perform an optimized // operation if it can be simplified. The simplifications // will be valid for all STROKE and TRANSFORM types. sg2d.shapepipe = colorViaPgram; } else { converter = colorViaShape; sg2d.shapepipe = colorPrimitives; } if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = converter; sg2d.fillpipe = converter; // REMIND: We should not be changing text strategies // between outline and glyph rendering based upon the // presence of a complex clip as that could cause a // mismatch when drawing the same text both clipped // and unclipped on two separate rendering passes. // Unfortunately, all of the clipped glyph rendering // pipelines rely on the use of the MaskBlit operation // which is not defined for XOR. sg2d.textpipe = outlineTextRenderer; } else { if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { sg2d.drawpipe = converter; sg2d.fillpipe = converter; } else { if (sg2d.strokeState != sg2d.STROKE_THIN) { sg2d.drawpipe = converter; } else { sg2d.drawpipe = colorPrimitives; } sg2d.fillpipe = colorPrimitives; } sg2d.textpipe = solidTextRenderer; } // assert(sg2d.surfaceData == this); } } else if (sg2d.compositeState == sg2d.COMP_CUSTOM) { if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipCompViaShape; sg2d.fillpipe = AAClipCompViaShape; sg2d.shapepipe = AAClipCompViaShape; sg2d.textpipe = clipCompText; } else { sg2d.drawpipe = AACompViaShape; sg2d.fillpipe = AACompViaShape; sg2d.shapepipe = AACompViaShape; sg2d.textpipe = compText; } } else { sg2d.drawpipe = compViaShape; sg2d.fillpipe = compViaShape; sg2d.shapepipe = compShape; if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.textpipe = clipCompText; } else { sg2d.textpipe = compText; } } } else if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) { sg2d.alphafill = getMaskFill(sg2d); // assert(sg2d.surfaceData == this); if (sg2d.alphafill != null) { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipColorViaShape; sg2d.fillpipe = AAClipColorViaShape; sg2d.shapepipe = AAClipColorViaShape; sg2d.textpipe = clipColorText; } else { PixelToParallelogramConverter converter = (sg2d.alphafill.canDoParallelograms() ? AAColorViaPgram : AAColorViaShape); sg2d.drawpipe = converter; sg2d.fillpipe = converter; sg2d.shapepipe = converter; if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR || sg2d.compositeState > sg2d.COMP_ISCOPY) { sg2d.textpipe = colorText; } else { sg2d.textpipe = getTextPipe(sg2d, true /* AA==ON */); } } } else { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipPaintViaShape; sg2d.fillpipe = AAClipPaintViaShape; sg2d.shapepipe = AAClipPaintViaShape; sg2d.textpipe = clipPaintText; } else { sg2d.drawpipe = AAPaintViaShape; sg2d.fillpipe = AAPaintViaShape; sg2d.shapepipe = AAPaintViaShape; sg2d.textpipe = paintText; } } } else if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR || sg2d.compositeState > sg2d.COMP_ISCOPY || sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = paintViaShape; sg2d.fillpipe = paintViaShape; sg2d.shapepipe = paintShape; sg2d.alphafill = getMaskFill(sg2d); // assert(sg2d.surfaceData == this); if (sg2d.alphafill != null) { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.textpipe = clipColorText; } else { sg2d.textpipe = colorText; } } else { if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.textpipe = clipPaintText; } else { sg2d.textpipe = paintText; } } } else { PixelToShapeConverter converter; if (canRenderParallelograms(sg2d)) { converter = colorViaPgram; // Note that we use the transforming pipe here because it // will examine the shape and possibly perform an optimized // operation if it can be simplified. The simplifications // will be valid for all STROKE and TRANSFORM types. sg2d.shapepipe = colorViaPgram; } else { converter = colorViaShape; sg2d.shapepipe = colorPrimitives; } if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { sg2d.drawpipe = converter; sg2d.fillpipe = converter; } else { if (sg2d.strokeState != sg2d.STROKE_THIN) { sg2d.drawpipe = converter; } else { sg2d.drawpipe = colorPrimitives; } sg2d.fillpipe = colorPrimitives; } sg2d.textpipe = getTextPipe(sg2d, false /* AA==OFF */); // assert(sg2d.surfaceData == this); } // check for loops if (sg2d.textpipe instanceof LoopBasedPipe || sg2d.shapepipe instanceof LoopBasedPipe || sg2d.fillpipe instanceof LoopBasedPipe || sg2d.drawpipe instanceof LoopBasedPipe || sg2d.imagepipe instanceof LoopBasedPipe) { sg2d.loops = getRenderLoops(sg2d); } } /* Return the text pipe to be used based on the graphics AA hint setting, * and the rest of the graphics state is compatible with these loops. * If the text AA hint is "DEFAULT", then the AA graphics hint requests * the AA text renderer, else it requests the B&W text renderer. */ private TextPipe getTextPipe(SunGraphics2D sg2d, boolean aaHintIsOn) { /* Try to avoid calling getFontInfo() unless its needed to * resolve one of the new AA types. */ switch (sg2d.textAntialiasHint) { case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT: if (aaHintIsOn) { return aaTextRenderer; } else { return solidTextRenderer; } case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: return solidTextRenderer; case SunHints.INTVAL_TEXT_ANTIALIAS_ON: return aaTextRenderer; default: switch (sg2d.getFontInfo().aaHint) { case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB: case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB: return lcdTextRenderer; case SunHints.INTVAL_TEXT_ANTIALIAS_ON: return aaTextRenderer; case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: return solidTextRenderer; /* This should not be reached as the FontInfo will * always explicitly set its hint value. So whilst * this could be collapsed to returning say just * solidTextRenderer, or even removed, its left * here in case DEFAULT is ever passed in. */ default: if (aaHintIsOn) { return aaTextRenderer; } else { return solidTextRenderer; } } } } private static SurfaceType getPaintSurfaceType(SunGraphics2D sg2d) { switch (sg2d.paintState) { case SunGraphics2D.PAINT_OPAQUECOLOR: return SurfaceType.OpaqueColor; case SunGraphics2D.PAINT_ALPHACOLOR: return SurfaceType.AnyColor; case SunGraphics2D.PAINT_GRADIENT: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueGradientPaint; } else { return SurfaceType.GradientPaint; } case SunGraphics2D.PAINT_LIN_GRADIENT: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueLinearGradientPaint; } else { return SurfaceType.LinearGradientPaint; } case SunGraphics2D.PAINT_RAD_GRADIENT: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueRadialGradientPaint; } else { return SurfaceType.RadialGradientPaint; } case SunGraphics2D.PAINT_TEXTURE: if (sg2d.paint.getTransparency() == OPAQUE) { return SurfaceType.OpaqueTexturePaint; } else { return SurfaceType.TexturePaint; } default: case SunGraphics2D.PAINT_CUSTOM: return SurfaceType.AnyPaint; } } private static CompositeType getFillCompositeType(SunGraphics2D sg2d) { CompositeType compType = sg2d.imageComp; if (sg2d.compositeState == sg2d.COMP_ISCOPY) { if (compType == CompositeType.SrcOverNoEa) { compType = CompositeType.OpaqueSrcOverNoEa; } else { compType = CompositeType.SrcNoEa; } } return compType; } /** * Returns a MaskFill object that can be used on this destination * with the source (paint) and composite types determined by the given * SunGraphics2D, or null if no such MaskFill object can be located. * Subclasses can override this method if they wish to filter other * attributes (such as the hardware capabilities of the destination * surface) before returning a specific MaskFill object. */ protected MaskFill getMaskFill(SunGraphics2D sg2d) { SurfaceType src = getPaintSurfaceType(sg2d); CompositeType comp = getFillCompositeType(sg2d); SurfaceType dst = getSurfaceType(); return MaskFill.getFromCache(src, comp, dst); } private static RenderCache loopcache = new RenderCache(30); /** * Return a RenderLoops object containing all of the basic * GraphicsPrimitive objects for rendering to the destination * surface with the current attributes of the given SunGraphics2D. */ public RenderLoops getRenderLoops(SunGraphics2D sg2d) { SurfaceType src = getPaintSurfaceType(sg2d); CompositeType comp = getFillCompositeType(sg2d); SurfaceType dst = sg2d.getSurfaceData().getSurfaceType(); Object o = loopcache.get(src, comp, dst); if (o != null) { return (RenderLoops) o; } RenderLoops loops = makeRenderLoops(src, comp, dst); loopcache.put(src, comp, dst, loops); return loops; } /** * Construct and return a RenderLoops object containing all of * the basic GraphicsPrimitive objects for rendering to the * destination surface with the given source, destination, and * composite types. */ public static RenderLoops makeRenderLoops(SurfaceType src, CompositeType comp, SurfaceType dst) { RenderLoops loops = new RenderLoops(); loops.drawLineLoop = DrawLine.locate(src, comp, dst); loops.fillRectLoop = FillRect.locate(src, comp, dst); loops.drawRectLoop = DrawRect.locate(src, comp, dst); loops.drawPolygonsLoop = DrawPolygons.locate(src, comp, dst); loops.drawPathLoop = DrawPath.locate(src, comp, dst); loops.fillPathLoop = FillPath.locate(src, comp, dst); loops.fillSpansLoop = FillSpans.locate(src, comp, dst); loops.fillParallelogramLoop = FillParallelogram.locate(src, comp, dst); loops.drawParallelogramLoop = DrawParallelogram.locate(src, comp, dst); loops.drawGlyphListLoop = DrawGlyphList.locate(src, comp, dst); loops.drawGlyphListAALoop = DrawGlyphListAA.locate(src, comp, dst); loops.drawGlyphListLCDLoop = DrawGlyphListLCD.locate(src, comp, dst); /* System.out.println("drawLine: "+loops.drawLineLoop); System.out.println("fillRect: "+loops.fillRectLoop); System.out.println("drawRect: "+loops.drawRectLoop); System.out.println("drawPolygons: "+loops.drawPolygonsLoop); System.out.println("fillSpans: "+loops.fillSpansLoop); System.out.println("drawGlyphList: "+loops.drawGlyphListLoop); System.out.println("drawGlyphListAA: "+loops.drawGlyphListAALoop); System.out.println("drawGlyphListLCD: "+loops.drawGlyphListLCDLoop); */ return loops; } /** * Return the GraphicsConfiguration object that describes this * destination surface. */ public abstract GraphicsConfiguration getDeviceConfiguration(); /** * Return the SurfaceType object that describes the destination * surface. */ public final SurfaceType getSurfaceType() { return surfaceType; } /** * Return the ColorModel for the destination surface. */ public final ColorModel getColorModel() { return colorModel; } /** * Returns the type of this <code>Transparency</code>. * @return the field type of this <code>Transparency</code>, which is * either OPAQUE, BITMASK or TRANSLUCENT. */ public int getTransparency() { return getColorModel().getTransparency(); } /** * Return a readable Raster which contains the pixels for the * specified rectangular region of the destination surface. * The coordinate origin of the returned Raster is the same as * the device space origin of the destination surface. * In some cases the returned Raster might also be writeable. * In most cases, the returned Raster might contain more pixels * than requested. * * @see useTightBBoxes */ public abstract Raster getRaster(int x, int y, int w, int h); /** * Does the pixel accessibility of the destination surface * suggest that rendering algorithms might want to take * extra time to calculate a more accurate bounding box for * the operation being performed? * The typical case when this will be true is when a copy of * the pixels has to be made when doing a getRaster. The * fewer pixels copied, the faster the operation will go. * * @see getRaster */ public boolean useTightBBoxes() { // Note: The native equivalent would trigger on VISIBLE_TO_NATIVE // REMIND: This is not used - should be obsoleted maybe return true; } /** * Returns the pixel data for the specified Argb value packed * into an integer for easy storage and conveyance. */ public int pixelFor(int rgb) { return surfaceType.pixelFor(rgb, colorModel); } /** * Returns the pixel data for the specified color packed into an * integer for easy storage and conveyance. * * This method will use the getRGB() method of the Color object * and defer to the pixelFor(int rgb) method if not overridden. * * For now this is a convenience function, but for cases where * the highest quality color conversion is requested, this method * should be overridden in those cases so that a more direct * conversion of the color to the destination color space * can be done using the additional information in the Color * object. */ public int pixelFor(Color c) { return pixelFor(c.getRGB()); } /** * Returns the Argb representation for the specified integer value * which is packed in the format of the associated ColorModel. */ public int rgbFor(int pixel) { return surfaceType.rgbFor(pixel, colorModel); } /** * Returns the bounds of the destination surface. */ public abstract Rectangle getBounds();