Path: blob/master/src/java.desktop/share/classes/sun/java2d/loops/GeneralRenderer.java
41159 views
/*1* Copyright (c) 1998, 2018, 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*/2425/*26* @author Charlton Innovations, Inc.27*/2829package sun.java2d.loops;3031import java.awt.image.WritableRaster;32import java.awt.image.DataBuffer;33import java.awt.image.ColorModel;34import java.awt.geom.Path2D;35import sun.java2d.pipe.Region;36import sun.java2d.pipe.SpanIterator;37import sun.java2d.SunGraphics2D;38import sun.java2d.SurfaceData;39import sun.java2d.loops.ProcessPath;40import sun.font.GlyphList;4142/**43* GeneralRenderer collection44* Basically, a collection of components which permit basic45* rendering to occur on rasters of any format46*/4748public final class GeneralRenderer {49public static void register() {50Class<?> owner = GeneralRenderer.class;51GraphicsPrimitive[] primitives = {52new GraphicsPrimitiveProxy(owner, "SetFillRectANY",53FillRect.methodSignature,54FillRect.primTypeID,55SurfaceType.AnyColor,56CompositeType.SrcNoEa,57SurfaceType.Any),58new GraphicsPrimitiveProxy(owner, "SetFillPathANY",59FillPath.methodSignature,60FillPath.primTypeID,61SurfaceType.AnyColor,62CompositeType.SrcNoEa,63SurfaceType.Any),64new GraphicsPrimitiveProxy(owner, "SetFillSpansANY",65FillSpans.methodSignature,66FillSpans.primTypeID,67SurfaceType.AnyColor,68CompositeType.SrcNoEa,69SurfaceType.Any),70new GraphicsPrimitiveProxy(owner, "SetDrawLineANY",71DrawLine.methodSignature,72DrawLine.primTypeID,73SurfaceType.AnyColor,74CompositeType.SrcNoEa,75SurfaceType.Any),76new GraphicsPrimitiveProxy(owner, "SetDrawPolygonsANY",77DrawPolygons.methodSignature,78DrawPolygons.primTypeID,79SurfaceType.AnyColor,80CompositeType.SrcNoEa,81SurfaceType.Any),82new GraphicsPrimitiveProxy(owner, "SetDrawPathANY",83DrawPath.methodSignature,84DrawPath.primTypeID,85SurfaceType.AnyColor,86CompositeType.SrcNoEa,87SurfaceType.Any),88new GraphicsPrimitiveProxy(owner, "SetDrawRectANY",89DrawRect.methodSignature,90DrawRect.primTypeID,91SurfaceType.AnyColor,92CompositeType.SrcNoEa,93SurfaceType.Any),9495new GraphicsPrimitiveProxy(owner, "XorFillRectANY",96FillRect.methodSignature,97FillRect.primTypeID,98SurfaceType.AnyColor,99CompositeType.Xor,100SurfaceType.Any),101new GraphicsPrimitiveProxy(owner, "XorFillPathANY",102FillPath.methodSignature,103FillPath.primTypeID,104SurfaceType.AnyColor,105CompositeType.Xor,106SurfaceType.Any),107new GraphicsPrimitiveProxy(owner, "XorFillSpansANY",108FillSpans.methodSignature,109FillSpans.primTypeID,110SurfaceType.AnyColor,111CompositeType.Xor,112SurfaceType.Any),113new GraphicsPrimitiveProxy(owner, "XorDrawLineANY",114DrawLine.methodSignature,115DrawLine.primTypeID,116SurfaceType.AnyColor,117CompositeType.Xor,118SurfaceType.Any),119new GraphicsPrimitiveProxy(owner, "XorDrawPolygonsANY",120DrawPolygons.methodSignature,121DrawPolygons.primTypeID,122SurfaceType.AnyColor,123CompositeType.Xor,124SurfaceType.Any),125new GraphicsPrimitiveProxy(owner, "XorDrawPathANY",126DrawPath.methodSignature,127DrawPath.primTypeID,128SurfaceType.AnyColor,129CompositeType.Xor,130SurfaceType.Any),131new GraphicsPrimitiveProxy(owner, "XorDrawRectANY",132DrawRect.methodSignature,133DrawRect.primTypeID,134SurfaceType.AnyColor,135CompositeType.Xor,136SurfaceType.Any),137new GraphicsPrimitiveProxy(owner, "XorDrawGlyphListANY",138DrawGlyphList.methodSignature,139DrawGlyphList.primTypeID,140SurfaceType.AnyColor,141CompositeType.Xor,142SurfaceType.Any),143new GraphicsPrimitiveProxy(owner, "XorDrawGlyphListAAANY",144DrawGlyphListAA.methodSignature,145DrawGlyphListAA.primTypeID,146SurfaceType.AnyColor,147CompositeType.Xor,148SurfaceType.Any),149};150GraphicsPrimitiveMgr.register(primitives);151}152153static void doDrawPoly(SurfaceData sData, PixelWriter pw,154int[] xPoints, int[] yPoints, int off, int nPoints,155Region clip, int transx, int transy, boolean close)156{157int mx, my, x1, y1;158int[] tmp = null;159160if (nPoints <= 0) {161return;162}163mx = x1 = xPoints[off] + transx;164my = y1 = yPoints[off] + transy;165while (--nPoints > 0) {166++off;167int x2 = xPoints[off] + transx;168int y2 = yPoints[off] + transy;169tmp = GeneralRenderer.doDrawLine(sData, pw, tmp, clip,170x1, y1, x2, y2);171x1 = x2;172y1 = y2;173}174if (close && (x1 != mx || y1 != my)) {175tmp = GeneralRenderer.doDrawLine(sData, pw, tmp, clip,176x1, y1, mx, my);177}178}179180static void doSetRect(SurfaceData sData, PixelWriter pw,181int x1, int y1, int x2, int y2) {182WritableRaster dstRast =183(WritableRaster) sData.getRaster(x1, y1, x2-x1, y2-y1);184pw.setRaster(dstRast);185186while (y1 < y2) {187for (int x = x1; x < x2; x++) {188pw.writePixel(x, y1);189}190y1++;191}192}193194static int[] doDrawLine(SurfaceData sData, PixelWriter pw, int[] boundPts,195Region clip,196int origx1, int origy1, int origx2, int origy2)197{198if (boundPts == null) {199boundPts = new int[8];200}201boundPts[0] = origx1;202boundPts[1] = origy1;203boundPts[2] = origx2;204boundPts[3] = origy2;205if (!adjustLine(boundPts,206clip.getLoX(), clip.getLoY(),207clip.getHiX(), clip.getHiY()))208{209return boundPts;210}211int x1 = boundPts[0];212int y1 = boundPts[1];213int x2 = boundPts[2];214int y2 = boundPts[3];215216WritableRaster dstRast = (WritableRaster)217sData.getRaster(Math.min(x1, x2), Math.min(y1, y2),218Math.abs(x1 - x2) + 1, Math.abs(y1 - y2) + 1);219pw.setRaster(dstRast);220221/* this could be made smaller, more elegant, more traditional. */222if (x1 == x2) {223if (y1 > y2) {224do {225pw.writePixel(x1, y1);226y1--;227} while (y1 >= y2);228} else {229do {230pw.writePixel(x1, y1);231y1++;232} while (y1 <= y2);233}234} else if (y1 == y2) {235if (x1 > x2) {236do {237pw.writePixel(x1, y1);238x1--;239} while (x1 >= x2);240} else {241do {242pw.writePixel(x1, y1);243x1++;244} while (x1 <= x2);245}246} else {247int dx = boundPts[4];248int dy = boundPts[5];249int ax = boundPts[6];250int ay = boundPts[7];251int steps;252int bumpmajor;253int bumpminor;254int errminor;255int errmajor;256int error;257boolean xmajor;258259if (ax >= ay) {260/* x is dominant */261xmajor = true;262errmajor = ay * 2;263errminor = ax * 2;264bumpmajor = (dx < 0) ? -1 : 1;265bumpminor = (dy < 0) ? -1 : 1;266ax = -ax; /* For clipping adjustment below */267steps = x2 - x1;268} else {269/* y is dominant */270xmajor = false;271errmajor = ax * 2;272errminor = ay * 2;273bumpmajor = (dy < 0) ? -1 : 1;274bumpminor = (dx < 0) ? -1 : 1;275ay = -ay; /* For clipping adjustment below */276steps = y2 - y1;277}278error = - (errminor / 2);279if (y1 != origy1) {280int ysteps = y1 - origy1;281if (ysteps < 0) {282ysteps = -ysteps;283}284error += ysteps * ax * 2;285}286if (x1 != origx1) {287int xsteps = x1 - origx1;288if (xsteps < 0) {289xsteps = -xsteps;290}291error += xsteps * ay * 2;292}293if (steps < 0) {294steps = -steps;295}296if (xmajor) {297do {298pw.writePixel(x1, y1);299x1 += bumpmajor;300error += errmajor;301if (error >= 0) {302y1 += bumpminor;303error -= errminor;304}305} while (--steps >= 0);306} else {307do {308pw.writePixel(x1, y1);309y1 += bumpmajor;310error += errmajor;311if (error >= 0) {312x1 += bumpminor;313error -= errminor;314}315} while (--steps >= 0);316}317}318return boundPts;319}320321public static void doDrawRect(PixelWriter pw,322SunGraphics2D sg2d, SurfaceData sData,323int x, int y, int w, int h)324{325if (w < 0 || h < 0) {326return;327}328int x2 = Region.dimAdd(Region.dimAdd(x, w), 1);329int y2 = Region.dimAdd(Region.dimAdd(y, h), 1);330Region r = sg2d.getCompClip().getBoundsIntersectionXYXY(x, y, x2, y2);331if (r.isEmpty()) {332return;333}334int cx1 = r.getLoX();335int cy1 = r.getLoY();336int cx2 = r.getHiX();337int cy2 = r.getHiY();338339if (w < 2 || h < 2) {340doSetRect(sData, pw, cx1, cy1, cx2, cy2);341return;342}343344345if (cy1 == y) {346doSetRect(sData, pw, cx1, cy1, cx2, cy1+1);347}348if (cx1 == x) {349doSetRect(sData, pw, cx1, cy1+1, cx1+1, cy2-1);350}351if (cx2 == x2) {352doSetRect(sData, pw, cx2-1, cy1+1, cx2, cy2-1);353}354if (cy2 == y2) {355doSetRect(sData, pw, cx1, cy2-1, cx2, cy2);356}357}358359/*360* REMIND: For now this will field both AA and non-AA requests and361* use a simple threshold to choose pixels if the supplied grey362* bits are antialiased. We should really find a way to disable363* AA text at a higher level or to have the GlyphList be able to364* reset the glyphs to non-AA after construction.365*/366static void doDrawGlyphList(SurfaceData sData, PixelWriter pw,367GlyphList gl, int fromGlyph, int toGlyph,368Region clip)369{370int[] bounds = gl.getBounds(toGlyph);371clip.clipBoxToBounds(bounds);372int cx1 = bounds[0];373int cy1 = bounds[1];374int cx2 = bounds[2];375int cy2 = bounds[3];376377WritableRaster dstRast =378(WritableRaster) sData.getRaster(cx1, cy1, cx2 - cx1, cy2 - cy1);379pw.setRaster(dstRast);380381for (int i = fromGlyph; i < toGlyph; i++) {382gl.setGlyphIndex(i);383int[] metrics = gl.getMetrics();384int gx1 = metrics[0];385int gy1 = metrics[1];386int w = metrics[2];387int gx2 = gx1 + w;388int gy2 = gy1 + metrics[3];389int off = 0;390if (gx1 < cx1) {391off = cx1 - gx1;392gx1 = cx1;393}394if (gy1 < cy1) {395off += (cy1 - gy1) * w;396gy1 = cy1;397}398if (gx2 > cx2) gx2 = cx2;399if (gy2 > cy2) gy2 = cy2;400if (gx2 > gx1 && gy2 > gy1) {401byte[] alpha = gl.getGrayBits();402w -= (gx2 - gx1);403for (int y = gy1; y < gy2; y++) {404for (int x = gx1; x < gx2; x++) {405if (alpha[off++] < 0) {406pw.writePixel(x, y);407}408}409off += w;410}411}412}413}414415static final int OUTCODE_TOP = 1;416static final int OUTCODE_BOTTOM = 2;417static final int OUTCODE_LEFT = 4;418static final int OUTCODE_RIGHT = 8;419420static int outcode(int x, int y, int xmin, int ymin, int xmax, int ymax) {421int code;422if (y < ymin) {423code = OUTCODE_TOP;424} else if (y > ymax) {425code = OUTCODE_BOTTOM;426} else {427code = 0;428}429if (x < xmin) {430code |= OUTCODE_LEFT;431} else if (x > xmax) {432code |= OUTCODE_RIGHT;433}434return code;435}436437public static boolean adjustLine(int [] boundPts,438int cxmin, int cymin, int cx2, int cy2)439{440int cxmax = cx2 - 1;441int cymax = cy2 - 1;442int x1 = boundPts[0];443int y1 = boundPts[1];444int x2 = boundPts[2];445int y2 = boundPts[3];446447if ((cxmax < cxmin) || (cymax < cymin)) {448return false;449}450451if (x1 == x2) {452if (x1 < cxmin || x1 > cxmax) {453return false;454}455if (y1 > y2) {456int t = y1;457y1 = y2;458y2 = t;459}460if (y1 < cymin) {461y1 = cymin;462}463if (y2 > cymax) {464y2 = cymax;465}466if (y1 > y2) {467return false;468}469boundPts[1] = y1;470boundPts[3] = y2;471} else if (y1 == y2) {472if (y1 < cymin || y1 > cymax) {473return false;474}475if (x1 > x2) {476int t = x1;477x1 = x2;478x2 = t;479}480if (x1 < cxmin) {481x1 = cxmin;482}483if (x2 > cxmax) {484x2 = cxmax;485}486if (x1 > x2) {487return false;488}489boundPts[0] = x1;490boundPts[2] = x2;491} else {492/* REMIND: This could overflow... */493int outcode1, outcode2;494int dx = x2 - x1;495int dy = y2 - y1;496int ax = (dx < 0) ? -dx : dx;497int ay = (dy < 0) ? -dy : dy;498boolean xmajor = (ax >= ay);499500outcode1 = outcode(x1, y1, cxmin, cymin, cxmax, cymax);501outcode2 = outcode(x2, y2, cxmin, cymin, cxmax, cymax);502while ((outcode1 | outcode2) != 0) {503int xsteps, ysteps;504if ((outcode1 & outcode2) != 0) {505return false;506}507if (outcode1 != 0) {508if (0 != (outcode1 & (OUTCODE_TOP | OUTCODE_BOTTOM))) {509if (0 != (outcode1 & OUTCODE_TOP)) {510y1 = cymin;511} else {512y1 = cymax;513}514ysteps = y1 - boundPts[1];515if (ysteps < 0) {516ysteps = -ysteps;517}518xsteps = 2 * ysteps * ax + ay;519if (xmajor) {520xsteps += ay - ax - 1;521}522xsteps = xsteps / (2 * ay);523if (dx < 0) {524xsteps = -xsteps;525}526x1 = boundPts[0] + xsteps;527} else if (0 !=528(outcode1 & (OUTCODE_LEFT | OUTCODE_RIGHT))) {529if (0 != (outcode1 & OUTCODE_LEFT)) {530x1 = cxmin;531} else {532x1 = cxmax;533}534xsteps = x1 - boundPts[0];535if (xsteps < 0) {536xsteps = -xsteps;537}538ysteps = 2 * xsteps * ay + ax;539if (!xmajor) {540ysteps += ax - ay - 1;541}542ysteps = ysteps / (2 * ax);543if (dy < 0) {544ysteps = -ysteps;545}546y1 = boundPts[1] + ysteps;547}548outcode1 = outcode(x1, y1, cxmin, cymin, cxmax, cymax);549} else {550if (0 != (outcode2 & (OUTCODE_TOP | OUTCODE_BOTTOM))) {551if (0 != (outcode2 & OUTCODE_TOP)) {552y2 = cymin;553} else {554y2 = cymax;555}556ysteps = y2 - boundPts[3];557if (ysteps < 0) {558ysteps = -ysteps;559}560xsteps = 2 * ysteps * ax + ay;561if (xmajor) {562xsteps += ay - ax;563} else {564xsteps -= 1;565}566xsteps = xsteps / (2 * ay);567if (dx > 0) {568xsteps = -xsteps;569}570x2 = boundPts[2] + xsteps;571} else if (0 !=572(outcode2 & (OUTCODE_LEFT | OUTCODE_RIGHT))) {573if (0 != (outcode2 & OUTCODE_LEFT)) {574x2 = cxmin;575} else {576x2 = cxmax;577}578xsteps = x2 - boundPts[2];579if (xsteps < 0) {580xsteps = -xsteps;581}582ysteps = 2 * xsteps * ay + ax;583if (xmajor) {584ysteps -= 1;585} else {586ysteps += ax - ay;587}588ysteps = ysteps / (2 * ax);589if (dy > 0) {590ysteps = -ysteps;591}592y2 = boundPts[3] + ysteps;593}594outcode2 = outcode(x2, y2, cxmin, cymin, cxmax, cymax);595}596}597boundPts[0] = x1;598boundPts[1] = y1;599boundPts[2] = x2;600boundPts[3] = y2;601boundPts[4] = dx;602boundPts[5] = dy;603boundPts[6] = ax;604boundPts[7] = ay;605}606return true;607}608609static PixelWriter createSolidPixelWriter(SunGraphics2D sg2d,610SurfaceData sData)611{612ColorModel dstCM = sData.getColorModel();613Object srcPixel = dstCM.getDataElements(sg2d.eargb, null);614615return new SolidPixelWriter(srcPixel);616}617618static PixelWriter createXorPixelWriter(SunGraphics2D sg2d,619SurfaceData sData)620{621ColorModel dstCM = sData.getColorModel();622623Object srcPixel = dstCM.getDataElements(sg2d.eargb, null);624625XORComposite comp = (XORComposite)sg2d.getComposite();626int xorrgb = comp.getXorColor().getRGB();627Object xorPixel = dstCM.getDataElements(xorrgb, null);628629switch (dstCM.getTransferType()) {630case DataBuffer.TYPE_BYTE:631return new XorPixelWriter.ByteData(srcPixel, xorPixel);632case DataBuffer.TYPE_SHORT:633case DataBuffer.TYPE_USHORT:634return new XorPixelWriter.ShortData(srcPixel, xorPixel);635case DataBuffer.TYPE_INT:636return new XorPixelWriter.IntData(srcPixel, xorPixel);637case DataBuffer.TYPE_FLOAT:638return new XorPixelWriter.FloatData(srcPixel, xorPixel);639case DataBuffer.TYPE_DOUBLE:640return new XorPixelWriter.DoubleData(srcPixel, xorPixel);641default:642throw new InternalError("Unsupported XOR pixel type");643}644}645}646647class SetFillRectANY extends FillRect {648SetFillRectANY() {649super(SurfaceType.AnyColor,650CompositeType.SrcNoEa,651SurfaceType.Any);652}653654public void FillRect(SunGraphics2D sg2d, SurfaceData sData,655int x, int y, int w, int h)656{657PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);658659Region r = sg2d.getCompClip().getBoundsIntersectionXYWH(x, y, w, h);660661GeneralRenderer.doSetRect(sData, pw,662r.getLoX(), r.getLoY(),663r.getHiX(), r.getHiY());664}665}666667class PixelWriterDrawHandler extends ProcessPath.DrawHandler {668PixelWriter pw;669SurfaceData sData;670Region clip;671672public PixelWriterDrawHandler(SurfaceData sData, PixelWriter pw,673Region clip, int strokeHint) {674super(clip.getLoX(), clip.getLoY(),675clip.getHiX(), clip.getHiY(),676strokeHint);677this.sData = sData;678this.pw = pw;679this.clip = clip;680}681682public void drawLine(int x0, int y0, int x1, int y1) {683GeneralRenderer.doDrawLine(sData, pw, null, clip,684x0, y0, x1, y1);685}686687public void drawPixel(int x0, int y0) {688GeneralRenderer.doSetRect(sData, pw, x0, y0, x0 + 1, y0 + 1);689}690691public void drawScanline(int x0, int x1, int y0) {692GeneralRenderer.doSetRect(sData, pw, x0, y0, x1 + 1, y0 + 1);693}694}695696class SetFillPathANY extends FillPath {697SetFillPathANY() {698super(SurfaceType.AnyColor, CompositeType.SrcNoEa,699SurfaceType.Any);700}701702public void FillPath(SunGraphics2D sg2d, SurfaceData sData,703int transx, int transy,704Path2D.Float p2df)705{706PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);707ProcessPath.fillPath(708new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),709sg2d.strokeHint),710p2df, transx, transy);711}712}713714class SetFillSpansANY extends FillSpans {715SetFillSpansANY() {716super(SurfaceType.AnyColor,717CompositeType.SrcNoEa,718SurfaceType.Any);719}720721public void FillSpans(SunGraphics2D sg2d, SurfaceData sData,722SpanIterator si)723{724PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);725726int[] span = new int[4];727while (si.nextSpan(span)) {728GeneralRenderer.doSetRect(sData, pw,729span[0], span[1], span[2], span[3]);730}731}732}733734class SetDrawLineANY extends DrawLine {735SetDrawLineANY() {736super(SurfaceType.AnyColor,737CompositeType.SrcNoEa,738SurfaceType.Any);739}740741public void DrawLine(SunGraphics2D sg2d, SurfaceData sData,742int x1, int y1, int x2, int y2)743{744PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);745746if (y1 >= y2) {747GeneralRenderer.doDrawLine(sData, pw, null,748sg2d.getCompClip(),749x2, y2, x1, y1);750} else {751GeneralRenderer.doDrawLine(sData, pw, null,752sg2d.getCompClip(),753x1, y1, x2, y2);754}755}756}757758class SetDrawPolygonsANY extends DrawPolygons {759SetDrawPolygonsANY() {760super(SurfaceType.AnyColor,761CompositeType.SrcNoEa,762SurfaceType.Any);763}764765public void DrawPolygons(SunGraphics2D sg2d, SurfaceData sData,766int[] xPoints, int[] yPoints,767int[] nPoints, int numPolys,768int transx, int transy,769boolean close)770{771PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);772773int off = 0;774Region clip = sg2d.getCompClip();775for (int i = 0; i < numPolys; i++) {776int numpts = nPoints[i];777GeneralRenderer.doDrawPoly(sData, pw,778xPoints, yPoints, off, numpts,779clip, transx, transy, close);780off += numpts;781}782}783}784785class SetDrawPathANY extends DrawPath {786SetDrawPathANY() {787super(SurfaceType.AnyColor,788CompositeType.SrcNoEa,789SurfaceType.Any);790}791792public void DrawPath(SunGraphics2D sg2d, SurfaceData sData,793int transx, int transy,794Path2D.Float p2df)795{796PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);797ProcessPath.drawPath(798new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),799sg2d.strokeHint),800p2df, transx, transy801);802}803}804805class SetDrawRectANY extends DrawRect {806SetDrawRectANY() {807super(SurfaceType.AnyColor,808CompositeType.SrcNoEa,809SurfaceType.Any);810}811812public void DrawRect(SunGraphics2D sg2d, SurfaceData sData,813int x, int y, int w, int h)814{815PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);816817GeneralRenderer.doDrawRect(pw, sg2d, sData, x, y, w, h);818}819}820821class XorFillRectANY extends FillRect {822XorFillRectANY() {823super(SurfaceType.AnyColor,824CompositeType.Xor,825SurfaceType.Any);826}827828public void FillRect(SunGraphics2D sg2d, SurfaceData sData,829int x, int y, int w, int h)830{831PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);832833Region r = sg2d.getCompClip().getBoundsIntersectionXYWH(x, y, w, h);834835GeneralRenderer.doSetRect(sData, pw,836r.getLoX(), r.getLoY(),837r.getHiX(), r.getHiY());838}839}840841class XorFillPathANY extends FillPath {842XorFillPathANY() {843super(SurfaceType.AnyColor, CompositeType.Xor,844SurfaceType.Any);845}846847public void FillPath(SunGraphics2D sg2d, SurfaceData sData,848int transx, int transy,849Path2D.Float p2df)850{851PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);852ProcessPath.fillPath(853new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),854sg2d.strokeHint),855p2df, transx, transy);856}857}858859class XorFillSpansANY extends FillSpans {860XorFillSpansANY() {861super(SurfaceType.AnyColor,862CompositeType.Xor,863SurfaceType.Any);864}865866public void FillSpans(SunGraphics2D sg2d, SurfaceData sData,867SpanIterator si)868{869PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);870871int[] span = new int[4];872while (si.nextSpan(span)) {873GeneralRenderer.doSetRect(sData, pw,874span[0], span[1], span[2], span[3]);875}876}877}878879class XorDrawLineANY extends DrawLine {880XorDrawLineANY() {881super(SurfaceType.AnyColor,882CompositeType.Xor,883SurfaceType.Any);884}885886public void DrawLine(SunGraphics2D sg2d, SurfaceData sData,887int x1, int y1, int x2, int y2)888{889PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);890891if (y1 >= y2) {892GeneralRenderer.doDrawLine(sData, pw, null,893sg2d.getCompClip(),894x2, y2, x1, y1);895} else {896GeneralRenderer.doDrawLine(sData, pw, null,897sg2d.getCompClip(),898x1, y1, x2, y2);899}900}901}902903class XorDrawPolygonsANY extends DrawPolygons {904XorDrawPolygonsANY() {905super(SurfaceType.AnyColor,906CompositeType.Xor,907SurfaceType.Any);908}909910public void DrawPolygons(SunGraphics2D sg2d, SurfaceData sData,911int[] xPoints, int[] yPoints,912int[] nPoints, int numPolys,913int transx, int transy,914boolean close)915{916PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);917918int off = 0;919Region clip = sg2d.getCompClip();920for (int i = 0; i < numPolys; i++) {921int numpts = nPoints[i];922GeneralRenderer.doDrawPoly(sData, pw,923xPoints, yPoints, off, numpts,924clip, transx, transy, close);925off += numpts;926}927}928}929930class XorDrawPathANY extends DrawPath {931XorDrawPathANY() {932super(SurfaceType.AnyColor,933CompositeType.Xor,934SurfaceType.Any);935}936937public void DrawPath(SunGraphics2D sg2d, SurfaceData sData,938int transx, int transy, Path2D.Float p2df)939{940PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);941ProcessPath.drawPath(942new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),943sg2d.strokeHint),944p2df, transx, transy945);946}947}948949class XorDrawRectANY extends DrawRect {950XorDrawRectANY() {951super(SurfaceType.AnyColor,952CompositeType.Xor,953SurfaceType.Any);954}955956public void DrawRect(SunGraphics2D sg2d, SurfaceData sData,957int x, int y, int w, int h)958{959PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);960961GeneralRenderer.doDrawRect(pw, sg2d, sData, x, y, w, h);962}963}964965class XorDrawGlyphListANY extends DrawGlyphList {966XorDrawGlyphListANY() {967super(SurfaceType.AnyColor,968CompositeType.Xor,969SurfaceType.Any);970}971972public void DrawGlyphList(SunGraphics2D sg2d, SurfaceData sData,973GlyphList gl, int fromGlyph, int toGlyph)974{975PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);976GeneralRenderer.doDrawGlyphList(sData, pw, gl, fromGlyph, toGlyph,977sg2d.getCompClip());978}979}980981class XorDrawGlyphListAAANY extends DrawGlyphListAA {982XorDrawGlyphListAAANY() {983super(SurfaceType.AnyColor,984CompositeType.Xor,985SurfaceType.Any);986}987988public void DrawGlyphListAA(SunGraphics2D sg2d, SurfaceData sData,989GlyphList gl, int fromGlyph, int toGlyph)990{991PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);992GeneralRenderer.doDrawGlyphList(sData, pw, gl, fromGlyph, toGlyph,993sg2d.getCompClip());994}995}996997abstract class PixelWriter {998protected WritableRaster dstRast;9991000public void setRaster(WritableRaster dstRast) {1001this.dstRast = dstRast;1002}10031004public abstract void writePixel(int x, int y);1005}10061007class SolidPixelWriter extends PixelWriter {1008protected Object srcData;10091010SolidPixelWriter(Object srcPixel) {1011this.srcData = srcPixel;1012}10131014public void writePixel(int x, int y) {1015dstRast.setDataElements(x, y, srcData);1016}1017}10181019abstract class XorPixelWriter extends PixelWriter {1020protected ColorModel dstCM;10211022public void writePixel(int x, int y) {1023Object dstPixel = dstRast.getDataElements(x, y, null);1024xorPixel(dstPixel);1025dstRast.setDataElements(x, y, dstPixel);1026}10271028protected abstract void xorPixel(Object pixData);10291030public static class ByteData extends XorPixelWriter {1031byte[] xorData;10321033ByteData(Object srcPixel, Object xorPixel) {1034this.xorData = (byte[]) srcPixel;1035xorPixel(xorPixel);1036this.xorData = (byte[]) xorPixel;1037}10381039protected void xorPixel(Object pixData) {1040byte[] dstData = (byte[]) pixData;1041for (int i = 0; i < dstData.length; i++) {1042dstData[i] ^= xorData[i];1043}1044}1045}10461047public static class ShortData extends XorPixelWriter {1048short[] xorData;10491050ShortData(Object srcPixel, Object xorPixel) {1051this.xorData = (short[]) srcPixel;1052xorPixel(xorPixel);1053this.xorData = (short[]) xorPixel;1054}10551056protected void xorPixel(Object pixData) {1057short[] dstData = (short[]) pixData;1058for (int i = 0; i < dstData.length; i++) {1059dstData[i] ^= xorData[i];1060}1061}1062}10631064public static class IntData extends XorPixelWriter {1065int[] xorData;10661067IntData(Object srcPixel, Object xorPixel) {1068this.xorData = (int[]) srcPixel;1069xorPixel(xorPixel);1070this.xorData = (int[]) xorPixel;1071}10721073protected void xorPixel(Object pixData) {1074int[] dstData = (int[]) pixData;1075for (int i = 0; i < dstData.length; i++) {1076dstData[i] ^= xorData[i];1077}1078}1079}10801081public static class FloatData extends XorPixelWriter {1082int[] xorData;10831084FloatData(Object srcPixel, Object xorPixel) {1085float[] srcData = (float[]) srcPixel;1086float[] xorData = (float[]) xorPixel;1087this.xorData = new int[srcData.length];1088for (int i = 0; i < srcData.length; i++) {1089this.xorData[i] = (Float.floatToIntBits(srcData[i]) ^1090Float.floatToIntBits(xorData[i]));1091}1092}10931094protected void xorPixel(Object pixData) {1095float[] dstData = (float[]) pixData;1096for (int i = 0; i < dstData.length; i++) {1097int v = Float.floatToIntBits(dstData[i]) ^ xorData[i];1098dstData[i] = Float.intBitsToFloat(v);1099}1100}1101}11021103public static class DoubleData extends XorPixelWriter {1104long[] xorData;11051106DoubleData(Object srcPixel, Object xorPixel) {1107double[] srcData = (double[]) srcPixel;1108double[] xorData = (double[]) xorPixel;1109this.xorData = new long[srcData.length];1110for (int i = 0; i < srcData.length; i++) {1111this.xorData[i] = (Double.doubleToLongBits(srcData[i]) ^1112Double.doubleToLongBits(xorData[i]));1113}1114}11151116protected void xorPixel(Object pixData) {1117double[] dstData = (double[]) pixData;1118for (int i = 0; i < dstData.length; i++) {1119long v = Double.doubleToLongBits(dstData[i]) ^ xorData[i];1120dstData[i] = Double.longBitsToDouble(v);1121}1122}1123}1124}112511261127