blob: b0fb52ba0d12186b98ca28b763702c2fd2d11f95 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.java2d.x11;
27
28import java.awt.Polygon;
29import java.awt.Shape;
30import java.awt.geom.AffineTransform;
31import java.awt.geom.PathIterator;
32import java.awt.geom.Path2D;
33import java.awt.geom.IllegalPathStateException;
34import sun.awt.SunToolkit;
35import sun.java2d.SunGraphics2D;
36import sun.java2d.SurfaceData;
37import sun.java2d.loops.GraphicsPrimitive;
38import sun.java2d.pipe.Region;
39import sun.java2d.pipe.PixelDrawPipe;
40import sun.java2d.pipe.PixelFillPipe;
41import sun.java2d.pipe.ShapeDrawPipe;
42import sun.java2d.pipe.SpanIterator;
43import sun.java2d.pipe.ShapeSpanIterator;
44import sun.java2d.pipe.LoopPipe;
45
46public class X11Renderer implements
47 PixelDrawPipe,
48 PixelFillPipe,
49 ShapeDrawPipe
50{
51 public static X11Renderer getInstance() {
52 return (GraphicsPrimitive.tracingEnabled()
53 ? new X11TracingRenderer()
54 : new X11Renderer());
55 }
56
57 private final long validate(SunGraphics2D sg2d) {
58 // NOTE: getCompClip() will revalidateAll() if the
59 // surfaceData is invalid. This should ensure that
60 // the clip and pixel that we are validating against
61 // are the most current.
62 //
63 // The assumption is that the pipeline after that
64 // revalidation will either be another X11 pipe
65 // (because the drawable format never changes on X11)
66 // or a null pipeline if the surface is disposed.
67 //
68 // Since we do not get the ops structure of the SurfaceData
69 // until the actual call down to the native level we will
70 // pick up the most recently validated copy.
71 // Note that if the surface is disposed, a NullSurfaceData
72 // (with null native data structure) will be set in
73 // sg2d, so we have to protect against it in native code.
74
75 X11SurfaceData x11sd = (X11SurfaceData)sg2d.surfaceData;
76 return x11sd.getRenderGC(sg2d.getCompClip(),
77 sg2d.compositeState, sg2d.composite,
78 sg2d.pixel);
79 }
80
81 native void XDrawLine(long pXSData, long xgc,
82 int x1, int y1, int x2, int y2);
83
84 public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) {
85 SunToolkit.awtLock();
86 try {
87 long xgc = validate(sg2d);
88 int transx = sg2d.transX;
89 int transy = sg2d.transY;
90 XDrawLine(sg2d.surfaceData.getNativeOps(), xgc,
91 x1+transx, y1+transy, x2+transx, y2+transy);
92 } finally {
93 SunToolkit.awtUnlock();
94 }
95 }
96
97 native void XDrawRect(long pXSData, long xgc,
98 int x, int y, int w, int h);
99
100 public void drawRect(SunGraphics2D sg2d,
101 int x, int y, int width, int height)
102 {
103 SunToolkit.awtLock();
104 try {
105 long xgc = validate(sg2d);
106 XDrawRect(sg2d.surfaceData.getNativeOps(), xgc,
107 x+sg2d.transX, y+sg2d.transY, width, height);
108 } finally {
109 SunToolkit.awtUnlock();
110 }
111 }
112
113 native void XDrawRoundRect(long pXSData, long xgc,
114 int x, int y, int w, int h,
115 int arcW, int arcH);
116
117 public void drawRoundRect(SunGraphics2D sg2d,
118 int x, int y, int width, int height,
119 int arcWidth, int arcHeight)
120 {
121 SunToolkit.awtLock();
122 try {
123 long xgc = validate(sg2d);
124 XDrawRoundRect(sg2d.surfaceData.getNativeOps(), xgc,
125 x+sg2d.transX, y+sg2d.transY, width, height,
126 arcWidth, arcHeight);
127 } finally {
128 SunToolkit.awtUnlock();
129 }
130 }
131
132 native void XDrawOval(long pXSData, long xgc,
133 int x, int y, int w, int h);
134
135 public void drawOval(SunGraphics2D sg2d,
136 int x, int y, int width, int height)
137 {
138 SunToolkit.awtLock();
139 try {
140 long xgc = validate(sg2d);
141 XDrawOval(sg2d.surfaceData.getNativeOps(), xgc,
142 x+sg2d.transX, y+sg2d.transY, width, height);
143 } finally {
144 SunToolkit.awtUnlock();
145 }
146 }
147
148 native void XDrawArc(long pXSData, long xgc,
149 int x, int y, int w, int h,
150 int angleStart, int angleExtent);
151
152 public void drawArc(SunGraphics2D sg2d,
153 int x, int y, int width, int height,
154 int startAngle, int arcAngle)
155 {
156 SunToolkit.awtLock();
157 try {
158 long xgc = validate(sg2d);
159 XDrawArc(sg2d.surfaceData.getNativeOps(), xgc,
160 x+sg2d.transX, y+sg2d.transY, width, height,
161 startAngle, arcAngle);
162 } finally {
163 SunToolkit.awtUnlock();
164 }
165 }
166
167 native void XDrawPoly(long pXSData, long xgc,
168 int transx, int transy,
169 int[] xpoints, int[] ypoints,
170 int npoints, boolean isclosed);
171
172 public void drawPolyline(SunGraphics2D sg2d,
173 int xpoints[], int ypoints[],
174 int npoints)
175 {
176 SunToolkit.awtLock();
177 try {
178 long xgc = validate(sg2d);
179 XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc,
180 sg2d.transX, sg2d.transY,
181 xpoints, ypoints, npoints, false);
182 } finally {
183 SunToolkit.awtUnlock();
184 }
185 }
186
187 public void drawPolygon(SunGraphics2D sg2d,
188 int xpoints[], int ypoints[],
189 int npoints)
190 {
191 SunToolkit.awtLock();
192 try {
193 long xgc = validate(sg2d);
194 XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc,
195 sg2d.transX, sg2d.transY,
196 xpoints, ypoints, npoints, true);
197 } finally {
198 SunToolkit.awtUnlock();
199 }
200 }
201
202 native void XFillRect(long pXSData, long xgc,
203 int x, int y, int w, int h);
204
205 public void fillRect(SunGraphics2D sg2d,
206 int x, int y, int width, int height)
207 {
208 SunToolkit.awtLock();
209 try {
210 long xgc = validate(sg2d);
211 XFillRect(sg2d.surfaceData.getNativeOps(), xgc,
212 x+sg2d.transX, y+sg2d.transY, width, height);
213 } finally {
214 SunToolkit.awtUnlock();
215 }
216 }
217
218 native void XFillRoundRect(long pXSData, long xgc,
219 int x, int y, int w, int h,
220 int arcW, int arcH);
221
222 public void fillRoundRect(SunGraphics2D sg2d,
223 int x, int y, int width, int height,
224 int arcWidth, int arcHeight)
225 {
226 SunToolkit.awtLock();
227 try {
228 long xgc = validate(sg2d);
229 XFillRoundRect(sg2d.surfaceData.getNativeOps(), xgc,
230 x+sg2d.transX, y+sg2d.transY, width, height,
231 arcWidth, arcHeight);
232 } finally {
233 SunToolkit.awtUnlock();
234 }
235 }
236
237 native void XFillOval(long pXSData, long xgc,
238 int x, int y, int w, int h);
239
240 public void fillOval(SunGraphics2D sg2d,
241 int x, int y, int width, int height)
242 {
243 SunToolkit.awtLock();
244 try {
245 long xgc = validate(sg2d);
246 XFillOval(sg2d.surfaceData.getNativeOps(), xgc,
247 x+sg2d.transX, y+sg2d.transY, width, height);
248 } finally {
249 SunToolkit.awtUnlock();
250 }
251 }
252
253 native void XFillArc(long pXSData, long xgc,
254 int x, int y, int w, int h,
255 int angleStart, int angleExtent);
256
257 public void fillArc(SunGraphics2D sg2d,
258 int x, int y, int width, int height,
259 int startAngle, int arcAngle)
260 {
261 SunToolkit.awtLock();
262 try {
263 long xgc = validate(sg2d);
264 XFillArc(sg2d.surfaceData.getNativeOps(), xgc,
265 x+sg2d.transX, y+sg2d.transY, width, height,
266 startAngle, arcAngle);
267 } finally {
268 SunToolkit.awtUnlock();
269 }
270 }
271
272 native void XFillPoly(long pXSData, long xgc,
273 int transx, int transy,
274 int[] xpoints, int[] ypoints,
275 int npoints);
276
277 public void fillPolygon(SunGraphics2D sg2d,
278 int xpoints[], int ypoints[],
279 int npoints)
280 {
281 SunToolkit.awtLock();
282 try {
283 long xgc = validate(sg2d);
284 XFillPoly(sg2d.surfaceData.getNativeOps(), xgc,
285 sg2d.transX, sg2d.transY, xpoints, ypoints, npoints);
286 } finally {
287 SunToolkit.awtUnlock();
288 }
289 }
290
291 native void XFillSpans(long pXSData, long xgc,
292 SpanIterator si, long iterator,
293 int transx, int transy);
294
295 native void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc,
296 int transX, int transY, Path2D.Float p2df,
297 boolean isFill);
298
299 private void doPath(SunGraphics2D sg2d, Shape s, boolean isFill) {
300 Path2D.Float p2df;
301 int transx, transy;
302 if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
303 if (s instanceof Path2D.Float) {
304 p2df = (Path2D.Float)s;
305 } else {
306 p2df = new Path2D.Float(s);
307 }
308 transx = sg2d.transX;
309 transy = sg2d.transY;
310 } else {
311 p2df = new Path2D.Float(s, sg2d.transform);
312 transx = 0;
313 transy = 0;
314 }
315 SunToolkit.awtLock();
316 try {
317 long xgc = validate(sg2d);
318 XDoPath(sg2d, sg2d.surfaceData.getNativeOps(), xgc,
319 transx, transy, p2df, isFill);
320 } finally {
321 SunToolkit.awtUnlock();
322 }
323 }
324
325 public void draw(SunGraphics2D sg2d, Shape s) {
326 if (sg2d.strokeState == sg2d.STROKE_THIN) {
327 // Delegate to drawPolygon() if possible...
328 if (s instanceof Polygon &&
329 sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE)
330 {
331 Polygon p = (Polygon) s;
332 drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
333 return;
334 }
335
336 // Otherwise we will use drawPath() for
337 // high-quality thin paths.
338 doPath(sg2d, s, false);
339 } else if (sg2d.strokeState < sg2d.STROKE_CUSTOM) {
340 // REMIND: X11 can handle uniform scaled wide lines
341 // and dashed lines itself if we set the appropriate
342 // XGC attributes (TBD).
343 ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
344 try {
345 SunToolkit.awtLock();
346 try {
347 long xgc = validate(sg2d);
348 XFillSpans(sg2d.surfaceData.getNativeOps(), xgc,
349 si, si.getNativeIterator(),
350 0, 0);
351 } finally {
352 SunToolkit.awtUnlock();
353 }
354 } finally {
355 si.dispose();
356 }
357 } else {
358 fill(sg2d, sg2d.stroke.createStrokedShape(s));
359 }
360 }
361
362 public void fill(SunGraphics2D sg2d, Shape s) {
363 if (sg2d.strokeState == sg2d.STROKE_THIN) {
364 // Delegate to fillPolygon() if possible...
365 if (s instanceof Polygon &&
366 sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE)
367 {
368 Polygon p = (Polygon) s;
369 fillPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
370 return;
371 }
372
373 // Otherwise we will use fillPath() for
374 // high-quality fills.
375 doPath(sg2d, s, true);
376 return;
377 }
378
379 AffineTransform at;
380 int transx, transy;
381 if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) {
382 // Transform (translation) will be done by XFillSpans
383 at = null;
384 transx = sg2d.transX;
385 transy = sg2d.transY;
386 } else {
387 // Transform will be done by the PathIterator
388 at = sg2d.transform;
389 transx = transy = 0;
390 }
391
392 ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
393 try {
394 // Subtract transx/y from the SSI clip to match the
395 // (potentially untranslated) geometry fed to it
396 Region clip = sg2d.getCompClip();
397 ssi.setOutputAreaXYXY(clip.getLoX() - transx,
398 clip.getLoY() - transy,
399 clip.getHiX() - transx,
400 clip.getHiY() - transy);
401 ssi.appendPath(s.getPathIterator(at));
402 SunToolkit.awtLock();
403 try {
404 long xgc = validate(sg2d);
405 XFillSpans(sg2d.surfaceData.getNativeOps(), xgc,
406 ssi, ssi.getNativeIterator(),
407 transx, transy);
408 } finally {
409 SunToolkit.awtUnlock();
410 }
411 } finally {
412 ssi.dispose();
413 }
414 }
415
416 native void devCopyArea(long sdOps, long xgc,
417 int srcx, int srcy,
418 int dstx, int dsty,
419 int w, int h);
420
421 public static class X11TracingRenderer extends X11Renderer {
422 void XDrawLine(long pXSData, long xgc,
423 int x1, int y1, int x2, int y2)
424 {
425 GraphicsPrimitive.tracePrimitive("X11DrawLine");
426 super.XDrawLine(pXSData, xgc, x1, y1, x2, y2);
427 }
428 void XDrawRect(long pXSData, long xgc,
429 int x, int y, int w, int h)
430 {
431 GraphicsPrimitive.tracePrimitive("X11DrawRect");
432 super.XDrawRect(pXSData, xgc, x, y, w, h);
433 }
434 void XDrawRoundRect(long pXSData, long xgc,
435 int x, int y, int w, int h,
436 int arcW, int arcH)
437 {
438 GraphicsPrimitive.tracePrimitive("X11DrawRoundRect");
439 super.XDrawRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH);
440 }
441 void XDrawOval(long pXSData, long xgc,
442 int x, int y, int w, int h)
443 {
444 GraphicsPrimitive.tracePrimitive("X11DrawOval");
445 super.XDrawOval(pXSData, xgc, x, y, w, h);
446 }
447 void XDrawArc(long pXSData, long xgc,
448 int x, int y, int w, int h,
449 int angleStart, int angleExtent)
450 {
451 GraphicsPrimitive.tracePrimitive("X11DrawArc");
452 super.XDrawArc(pXSData, xgc,
453 x, y, w, h, angleStart, angleExtent);
454 }
455 void XDrawPoly(long pXSData, long xgc,
456 int transx, int transy,
457 int[] xpoints, int[] ypoints,
458 int npoints, boolean isclosed)
459 {
460 GraphicsPrimitive.tracePrimitive("X11DrawPoly");
461 super.XDrawPoly(pXSData, xgc, transx, transy,
462 xpoints, ypoints, npoints, isclosed);
463 }
464 void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc,
465 int transX, int transY, Path2D.Float p2df,
466 boolean isFill)
467 {
468 GraphicsPrimitive.tracePrimitive(isFill ?
469 "X11FillPath" :
470 "X11DrawPath");
471 super.XDoPath(sg2d, pXSData, xgc, transX, transY, p2df, isFill);
472 }
473 void XFillRect(long pXSData, long xgc,
474 int x, int y, int w, int h)
475 {
476 GraphicsPrimitive.tracePrimitive("X11FillRect");
477 super.XFillRect(pXSData, xgc, x, y, w, h);
478 }
479 void XFillRoundRect(long pXSData, long xgc,
480 int x, int y, int w, int h,
481 int arcW, int arcH)
482 {
483 GraphicsPrimitive.tracePrimitive("X11FillRoundRect");
484 super.XFillRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH);
485 }
486 void XFillOval(long pXSData, long xgc,
487 int x, int y, int w, int h)
488 {
489 GraphicsPrimitive.tracePrimitive("X11FillOval");
490 super.XFillOval(pXSData, xgc, x, y, w, h);
491 }
492 void XFillArc(long pXSData, long xgc,
493 int x, int y, int w, int h,
494 int angleStart, int angleExtent)
495 {
496 GraphicsPrimitive.tracePrimitive("X11FillArc");
497 super.XFillArc(pXSData, xgc,
498 x, y, w, h, angleStart, angleExtent);
499 }
500 void XFillPoly(long pXSData, long xgc,
501 int transx, int transy,
502 int[] xpoints, int[] ypoints,
503 int npoints)
504 {
505 GraphicsPrimitive.tracePrimitive("X11FillPoly");
506 super.XFillPoly(pXSData, xgc,
507 transx, transy, xpoints, ypoints, npoints);
508 }
509 void XFillSpans(long pXSData, long xgc,
510 SpanIterator si, long iterator, int transx, int transy)
511 {
512 GraphicsPrimitive.tracePrimitive("X11FillSpans");
513 super.XFillSpans(pXSData, xgc,
514 si, iterator, transx, transy);
515 }
516 void devCopyArea(long sdOps, long xgc,
517 int srcx, int srcy,
518 int dstx, int dsty,
519 int w, int h)
520 {
521 GraphicsPrimitive.tracePrimitive("X11CopyArea");
522 super.devCopyArea(sdOps, xgc, srcx, srcy, dstx, dsty, w, h);
523 }
524 }
525}