001: /*
002: * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.java2d.x11;
027:
028: import java.awt.Polygon;
029: import java.awt.Shape;
030: import java.awt.geom.AffineTransform;
031: import java.awt.geom.PathIterator;
032: import java.awt.geom.Path2D;
033: import java.awt.geom.IllegalPathStateException;
034: import sun.awt.SunToolkit;
035: import sun.java2d.SunGraphics2D;
036: import sun.java2d.SurfaceData;
037: import sun.java2d.loops.GraphicsPrimitive;
038: import sun.java2d.pipe.Region;
039: import sun.java2d.pipe.PixelDrawPipe;
040: import sun.java2d.pipe.PixelFillPipe;
041: import sun.java2d.pipe.ShapeDrawPipe;
042: import sun.java2d.pipe.SpanIterator;
043: import sun.java2d.pipe.ShapeSpanIterator;
044: import sun.java2d.pipe.LoopPipe;
045:
046: public class X11Renderer implements PixelDrawPipe, PixelFillPipe,
047: ShapeDrawPipe {
048: public static X11Renderer getInstance() {
049: return (GraphicsPrimitive.tracingEnabled() ? new X11TracingRenderer()
050: : new X11Renderer());
051: }
052:
053: private final long validate(SunGraphics2D sg2d) {
054: // NOTE: getCompClip() will revalidateAll() if the
055: // surfaceData is invalid. This should ensure that
056: // the clip and pixel that we are validating against
057: // are the most current.
058: //
059: // The assumption is that the pipeline after that
060: // revalidation will either be another X11 pipe
061: // (because the drawable format never changes on X11)
062: // or a null pipeline if the surface is disposed.
063: //
064: // Since we do not get the ops structure of the SurfaceData
065: // until the actual call down to the native level we will
066: // pick up the most recently validated copy.
067: // Note that if the surface is disposed, a NullSurfaceData
068: // (with null native data structure) will be set in
069: // sg2d, so we have to protect against it in native code.
070:
071: X11SurfaceData x11sd = (X11SurfaceData) sg2d.surfaceData;
072: return x11sd.getRenderGC(sg2d.getCompClip(),
073: sg2d.compositeState, sg2d.composite, sg2d.pixel);
074: }
075:
076: native void XDrawLine(long pXSData, long xgc, int x1, int y1,
077: int x2, int y2);
078:
079: public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2,
080: int y2) {
081: SunToolkit.awtLock();
082: try {
083: long xgc = validate(sg2d);
084: int transx = sg2d.transX;
085: int transy = sg2d.transY;
086: XDrawLine(sg2d.surfaceData.getNativeOps(), xgc,
087: x1 + transx, y1 + transy, x2 + transx, y2 + transy);
088: } finally {
089: SunToolkit.awtUnlock();
090: }
091: }
092:
093: native void XDrawRect(long pXSData, long xgc, int x, int y, int w,
094: int h);
095:
096: public void drawRect(SunGraphics2D sg2d, int x, int y, int width,
097: int height) {
098: SunToolkit.awtLock();
099: try {
100: long xgc = validate(sg2d);
101: XDrawRect(sg2d.surfaceData.getNativeOps(), xgc, x
102: + sg2d.transX, y + sg2d.transY, width, height);
103: } finally {
104: SunToolkit.awtUnlock();
105: }
106: }
107:
108: native void XDrawRoundRect(long pXSData, long xgc, int x, int y,
109: int w, int h, int arcW, int arcH);
110:
111: public void drawRoundRect(SunGraphics2D sg2d, int x, int y,
112: int width, int height, int arcWidth, int arcHeight) {
113: SunToolkit.awtLock();
114: try {
115: long xgc = validate(sg2d);
116: XDrawRoundRect(sg2d.surfaceData.getNativeOps(), xgc, x
117: + sg2d.transX, y + sg2d.transY, width, height,
118: arcWidth, arcHeight);
119: } finally {
120: SunToolkit.awtUnlock();
121: }
122: }
123:
124: native void XDrawOval(long pXSData, long xgc, int x, int y, int w,
125: int h);
126:
127: public void drawOval(SunGraphics2D sg2d, int x, int y, int width,
128: int height) {
129: SunToolkit.awtLock();
130: try {
131: long xgc = validate(sg2d);
132: XDrawOval(sg2d.surfaceData.getNativeOps(), xgc, x
133: + sg2d.transX, y + sg2d.transY, width, height);
134: } finally {
135: SunToolkit.awtUnlock();
136: }
137: }
138:
139: native void XDrawArc(long pXSData, long xgc, int x, int y, int w,
140: int h, int angleStart, int angleExtent);
141:
142: public void drawArc(SunGraphics2D sg2d, int x, int y, int width,
143: int height, int startAngle, int arcAngle) {
144: SunToolkit.awtLock();
145: try {
146: long xgc = validate(sg2d);
147: XDrawArc(sg2d.surfaceData.getNativeOps(), xgc, x
148: + sg2d.transX, y + sg2d.transY, width, height,
149: startAngle, arcAngle);
150: } finally {
151: SunToolkit.awtUnlock();
152: }
153: }
154:
155: native void XDrawPoly(long pXSData, long xgc, int transx,
156: int transy, int[] xpoints, int[] ypoints, int npoints,
157: boolean isclosed);
158:
159: public void drawPolyline(SunGraphics2D sg2d, int xpoints[],
160: int ypoints[], int npoints) {
161: SunToolkit.awtLock();
162: try {
163: long xgc = validate(sg2d);
164: XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc,
165: sg2d.transX, sg2d.transY, xpoints, ypoints,
166: npoints, false);
167: } finally {
168: SunToolkit.awtUnlock();
169: }
170: }
171:
172: public void drawPolygon(SunGraphics2D sg2d, int xpoints[],
173: int ypoints[], int npoints) {
174: SunToolkit.awtLock();
175: try {
176: long xgc = validate(sg2d);
177: XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc,
178: sg2d.transX, sg2d.transY, xpoints, ypoints,
179: npoints, true);
180: } finally {
181: SunToolkit.awtUnlock();
182: }
183: }
184:
185: native void XFillRect(long pXSData, long xgc, int x, int y, int w,
186: int h);
187:
188: public void fillRect(SunGraphics2D sg2d, int x, int y, int width,
189: int height) {
190: SunToolkit.awtLock();
191: try {
192: long xgc = validate(sg2d);
193: XFillRect(sg2d.surfaceData.getNativeOps(), xgc, x
194: + sg2d.transX, y + sg2d.transY, width, height);
195: } finally {
196: SunToolkit.awtUnlock();
197: }
198: }
199:
200: native void XFillRoundRect(long pXSData, long xgc, int x, int y,
201: int w, int h, int arcW, int arcH);
202:
203: public void fillRoundRect(SunGraphics2D sg2d, int x, int y,
204: int width, int height, int arcWidth, int arcHeight) {
205: SunToolkit.awtLock();
206: try {
207: long xgc = validate(sg2d);
208: XFillRoundRect(sg2d.surfaceData.getNativeOps(), xgc, x
209: + sg2d.transX, y + sg2d.transY, width, height,
210: arcWidth, arcHeight);
211: } finally {
212: SunToolkit.awtUnlock();
213: }
214: }
215:
216: native void XFillOval(long pXSData, long xgc, int x, int y, int w,
217: int h);
218:
219: public void fillOval(SunGraphics2D sg2d, int x, int y, int width,
220: int height) {
221: SunToolkit.awtLock();
222: try {
223: long xgc = validate(sg2d);
224: XFillOval(sg2d.surfaceData.getNativeOps(), xgc, x
225: + sg2d.transX, y + sg2d.transY, width, height);
226: } finally {
227: SunToolkit.awtUnlock();
228: }
229: }
230:
231: native void XFillArc(long pXSData, long xgc, int x, int y, int w,
232: int h, int angleStart, int angleExtent);
233:
234: public void fillArc(SunGraphics2D sg2d, int x, int y, int width,
235: int height, int startAngle, int arcAngle) {
236: SunToolkit.awtLock();
237: try {
238: long xgc = validate(sg2d);
239: XFillArc(sg2d.surfaceData.getNativeOps(), xgc, x
240: + sg2d.transX, y + sg2d.transY, width, height,
241: startAngle, arcAngle);
242: } finally {
243: SunToolkit.awtUnlock();
244: }
245: }
246:
247: native void XFillPoly(long pXSData, long xgc, int transx,
248: int transy, int[] xpoints, int[] ypoints, int npoints);
249:
250: public void fillPolygon(SunGraphics2D sg2d, int xpoints[],
251: int ypoints[], int npoints) {
252: SunToolkit.awtLock();
253: try {
254: long xgc = validate(sg2d);
255: XFillPoly(sg2d.surfaceData.getNativeOps(), xgc,
256: sg2d.transX, sg2d.transY, xpoints, ypoints, npoints);
257: } finally {
258: SunToolkit.awtUnlock();
259: }
260: }
261:
262: native void XFillSpans(long pXSData, long xgc, SpanIterator si,
263: long iterator, int transx, int transy);
264:
265: native void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc,
266: int transX, int transY, Path2D.Float p2df, boolean isFill);
267:
268: private void doPath(SunGraphics2D sg2d, Shape s, boolean isFill) {
269: Path2D.Float p2df;
270: int transx, transy;
271: if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
272: if (s instanceof Path2D.Float) {
273: p2df = (Path2D.Float) s;
274: } else {
275: p2df = new Path2D.Float(s);
276: }
277: transx = sg2d.transX;
278: transy = sg2d.transY;
279: } else {
280: p2df = new Path2D.Float(s, sg2d.transform);
281: transx = 0;
282: transy = 0;
283: }
284: SunToolkit.awtLock();
285: try {
286: long xgc = validate(sg2d);
287: XDoPath(sg2d, sg2d.surfaceData.getNativeOps(), xgc, transx,
288: transy, p2df, isFill);
289: } finally {
290: SunToolkit.awtUnlock();
291: }
292: }
293:
294: public void draw(SunGraphics2D sg2d, Shape s) {
295: if (sg2d.strokeState == sg2d.STROKE_THIN) {
296: // Delegate to drawPolygon() if possible...
297: if (s instanceof Polygon
298: && sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) {
299: Polygon p = (Polygon) s;
300: drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
301: return;
302: }
303:
304: // Otherwise we will use drawPath() for
305: // high-quality thin paths.
306: doPath(sg2d, s, false);
307: } else if (sg2d.strokeState < sg2d.STROKE_CUSTOM) {
308: // REMIND: X11 can handle uniform scaled wide lines
309: // and dashed lines itself if we set the appropriate
310: // XGC attributes (TBD).
311: ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
312: try {
313: SunToolkit.awtLock();
314: try {
315: long xgc = validate(sg2d);
316: XFillSpans(sg2d.surfaceData.getNativeOps(), xgc,
317: si, si.getNativeIterator(), 0, 0);
318: } finally {
319: SunToolkit.awtUnlock();
320: }
321: } finally {
322: si.dispose();
323: }
324: } else {
325: fill(sg2d, sg2d.stroke.createStrokedShape(s));
326: }
327: }
328:
329: public void fill(SunGraphics2D sg2d, Shape s) {
330: if (sg2d.strokeState == sg2d.STROKE_THIN) {
331: // Delegate to fillPolygon() if possible...
332: if (s instanceof Polygon
333: && sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) {
334: Polygon p = (Polygon) s;
335: fillPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
336: return;
337: }
338:
339: // Otherwise we will use fillPath() for
340: // high-quality fills.
341: doPath(sg2d, s, true);
342: return;
343: }
344:
345: AffineTransform at;
346: int transx, transy;
347: if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) {
348: // Transform (translation) will be done by XFillSpans
349: at = null;
350: transx = sg2d.transX;
351: transy = sg2d.transY;
352: } else {
353: // Transform will be done by the PathIterator
354: at = sg2d.transform;
355: transx = transy = 0;
356: }
357:
358: ShapeSpanIterator ssi = new ShapeSpanIterator(sg2d, false);
359: try {
360: // Subtract transx/y from the SSI clip to match the
361: // (potentially untranslated) geometry fed to it
362: Region clip = sg2d.getCompClip();
363: ssi.setOutputAreaXYXY(clip.getLoX() - transx, clip.getLoY()
364: - transy, clip.getHiX() - transx, clip.getHiY()
365: - transy);
366: ssi.appendPath(s.getPathIterator(at));
367: SunToolkit.awtLock();
368: try {
369: long xgc = validate(sg2d);
370: XFillSpans(sg2d.surfaceData.getNativeOps(), xgc, ssi,
371: ssi.getNativeIterator(), transx, transy);
372: } finally {
373: SunToolkit.awtUnlock();
374: }
375: } finally {
376: ssi.dispose();
377: }
378: }
379:
380: native void devCopyArea(long sdOps, long xgc, int srcx, int srcy,
381: int dstx, int dsty, int w, int h);
382:
383: public static class X11TracingRenderer extends X11Renderer {
384: void XDrawLine(long pXSData, long xgc, int x1, int y1, int x2,
385: int y2) {
386: GraphicsPrimitive.tracePrimitive("X11DrawLine");
387: super .XDrawLine(pXSData, xgc, x1, y1, x2, y2);
388: }
389:
390: void XDrawRect(long pXSData, long xgc, int x, int y, int w,
391: int h) {
392: GraphicsPrimitive.tracePrimitive("X11DrawRect");
393: super .XDrawRect(pXSData, xgc, x, y, w, h);
394: }
395:
396: void XDrawRoundRect(long pXSData, long xgc, int x, int y,
397: int w, int h, int arcW, int arcH) {
398: GraphicsPrimitive.tracePrimitive("X11DrawRoundRect");
399: super .XDrawRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH);
400: }
401:
402: void XDrawOval(long pXSData, long xgc, int x, int y, int w,
403: int h) {
404: GraphicsPrimitive.tracePrimitive("X11DrawOval");
405: super .XDrawOval(pXSData, xgc, x, y, w, h);
406: }
407:
408: void XDrawArc(long pXSData, long xgc, int x, int y, int w,
409: int h, int angleStart, int angleExtent) {
410: GraphicsPrimitive.tracePrimitive("X11DrawArc");
411: super .XDrawArc(pXSData, xgc, x, y, w, h, angleStart,
412: angleExtent);
413: }
414:
415: void XDrawPoly(long pXSData, long xgc, int transx, int transy,
416: int[] xpoints, int[] ypoints, int npoints,
417: boolean isclosed) {
418: GraphicsPrimitive.tracePrimitive("X11DrawPoly");
419: super .XDrawPoly(pXSData, xgc, transx, transy, xpoints,
420: ypoints, npoints, isclosed);
421: }
422:
423: void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc,
424: int transX, int transY, Path2D.Float p2df,
425: boolean isFill) {
426: GraphicsPrimitive.tracePrimitive(isFill ? "X11FillPath"
427: : "X11DrawPath");
428: super .XDoPath(sg2d, pXSData, xgc, transX, transY, p2df,
429: isFill);
430: }
431:
432: void XFillRect(long pXSData, long xgc, int x, int y, int w,
433: int h) {
434: GraphicsPrimitive.tracePrimitive("X11FillRect");
435: super .XFillRect(pXSData, xgc, x, y, w, h);
436: }
437:
438: void XFillRoundRect(long pXSData, long xgc, int x, int y,
439: int w, int h, int arcW, int arcH) {
440: GraphicsPrimitive.tracePrimitive("X11FillRoundRect");
441: super .XFillRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH);
442: }
443:
444: void XFillOval(long pXSData, long xgc, int x, int y, int w,
445: int h) {
446: GraphicsPrimitive.tracePrimitive("X11FillOval");
447: super .XFillOval(pXSData, xgc, x, y, w, h);
448: }
449:
450: void XFillArc(long pXSData, long xgc, int x, int y, int w,
451: int h, int angleStart, int angleExtent) {
452: GraphicsPrimitive.tracePrimitive("X11FillArc");
453: super .XFillArc(pXSData, xgc, x, y, w, h, angleStart,
454: angleExtent);
455: }
456:
457: void XFillPoly(long pXSData, long xgc, int transx, int transy,
458: int[] xpoints, int[] ypoints, int npoints) {
459: GraphicsPrimitive.tracePrimitive("X11FillPoly");
460: super .XFillPoly(pXSData, xgc, transx, transy, xpoints,
461: ypoints, npoints);
462: }
463:
464: void XFillSpans(long pXSData, long xgc, SpanIterator si,
465: long iterator, int transx, int transy) {
466: GraphicsPrimitive.tracePrimitive("X11FillSpans");
467: super
468: .XFillSpans(pXSData, xgc, si, iterator, transx,
469: transy);
470: }
471:
472: void devCopyArea(long sdOps, long xgc, int srcx, int srcy,
473: int dstx, int dsty, int w, int h) {
474: GraphicsPrimitive.tracePrimitive("X11CopyArea");
475: super.devCopyArea(sdOps, xgc, srcx, srcy, dstx, dsty, w, h);
476: }
477: }
478: }
|