History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/java2d/pipe/BufferedRenderPipe.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/java2d/pipe/BufferedRenderPipe.java+601−0
@@ -0,0 +1,601 @@
1/*
2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.java2d.pipe;
27
28import java.awt.BasicStroke;
29import java.awt.Polygon;
30import java.awt.Shape;
31import java.awt.geom.AffineTransform;
32import java.awt.geom.Arc2D;
33import java.awt.geom.Ellipse2D;
34import java.awt.geom.Path2D;
35import java.awt.geom.IllegalPathStateException;
36import java.awt.geom.PathIterator;
37import java.awt.geom.Rectangle2D;
38import java.awt.geom.RoundRectangle2D;
39import sun.java2d.SunGraphics2D;
40import sun.java2d.loops.ProcessPath;
41import static sun.java2d.pipe.BufferedOpCodes.*;
42
43/**
44 * Base class for enqueuing rendering operations in a single-threaded
45 * rendering environment. Instead of each operation being rendered
46 * immediately by the underlying graphics library, the operation will be
47 * added to the provided RenderQueue, which will be processed at a later
48 * time by a single thread.
49 *
50 * This class provides implementations of drawLine(), drawRect(), drawPoly(),
51 * fillRect(), draw(Shape), and fill(Shape), which are useful for a
52 * hardware-accelerated renderer. The other draw*() and fill*() methods
53 * simply delegate to draw(Shape) and fill(Shape), respectively.
54 */
55public abstract class BufferedRenderPipe
56 implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, ParallelogramPipe
57{
58 ParallelogramPipe aapgrampipe = new AAParallelogramPipe();
59
60 static final int BYTES_PER_POLY_POINT = 8;
61 static final int BYTES_PER_SCANLINE = 12;
62 static final int BYTES_PER_SPAN = 16;
63
64 protected RenderQueue rq;
65 protected RenderBuffer buf;
66 private BufferedDrawHandler drawHandler;
67
68 public BufferedRenderPipe(RenderQueue rq) {
69 this.rq = rq;
70 this.buf = rq.getBuffer();
71 this.drawHandler = new BufferedDrawHandler();
72 }
73
74 public ParallelogramPipe getAAParallelogramPipe() {
75 return aapgrampipe;
76 }
77
78 /**
79 * Validates the state in the provided SunGraphics2D object and sets up
80 * any special resources for this operation (e.g. enabling gradient
81 * shading).
82 */
83 protected abstract void validateContext(SunGraphics2D sg2d);
84 protected abstract void validateContextAA(SunGraphics2D sg2d);
85
86 public void drawLine(SunGraphics2D sg2d,
87 int x1, int y1, int x2, int y2)
88 {
89 int transx = sg2d.transX;
90 int transy = sg2d.transY;
91 rq.lock();
92 try {
93 validateContext(sg2d);
94 rq.ensureCapacity(20);
95 buf.putInt(DRAW_LINE);
96 buf.putInt(x1 + transx);
97 buf.putInt(y1 + transy);
98 buf.putInt(x2 + transx);
99 buf.putInt(y2 + transy);
100 } finally {
101 rq.unlock();
102 }
103 }
104
105 public void drawRect(SunGraphics2D sg2d,
106 int x, int y, int width, int height)
107 {
108 rq.lock();
109 try {
110 validateContext(sg2d);
111 rq.ensureCapacity(20);
112 buf.putInt(DRAW_RECT);
113 buf.putInt(x + sg2d.transX);
114 buf.putInt(y + sg2d.transY);
115 buf.putInt(width);
116 buf.putInt(height);
117 } finally {
118 rq.unlock();
119 }
120 }
121
122 public void fillRect(SunGraphics2D sg2d,
123 int x, int y, int width, int height)
124 {
125 rq.lock();
126 try {
127 validateContext(sg2d);
128 rq.ensureCapacity(20);
129 buf.putInt(FILL_RECT);
130 buf.putInt(x + sg2d.transX);
131 buf.putInt(y + sg2d.transY);
132 buf.putInt(width);
133 buf.putInt(height);
134 } finally {
135 rq.unlock();
136 }
137 }
138
139 public void drawRoundRect(SunGraphics2D sg2d,
140 int x, int y, int width, int height,
141 int arcWidth, int arcHeight)
142 {
143 draw(sg2d, new RoundRectangle2D.Float(x, y, width, height,
144 arcWidth, arcHeight));
145 }
146
147 public void fillRoundRect(SunGraphics2D sg2d,
148 int x, int y, int width, int height,
149 int arcWidth, int arcHeight)
150 {
151 fill(sg2d, new RoundRectangle2D.Float(x, y, width, height,
152 arcWidth, arcHeight));
153 }
154
155 public void drawOval(SunGraphics2D sg2d,
156 int x, int y, int width, int height)
157 {
158 draw(sg2d, new Ellipse2D.Float(x, y, width, height));
159 }
160
161 public void fillOval(SunGraphics2D sg2d,
162 int x, int y, int width, int height)
163 {
164 fill(sg2d, new Ellipse2D.Float(x, y, width, height));
165 }
166
167 public void drawArc(SunGraphics2D sg2d,
168 int x, int y, int width, int height,
169 int startAngle, int arcAngle)
170 {
171 draw(sg2d, new Arc2D.Float(x, y, width, height,
172 startAngle, arcAngle,
173 Arc2D.OPEN));
174 }
175
176 public void fillArc(SunGraphics2D sg2d,
177 int x, int y, int width, int height,
178 int startAngle, int arcAngle)
179 {
180 fill(sg2d, new Arc2D.Float(x, y, width, height,
181 startAngle, arcAngle,
182 Arc2D.PIE));
183 }
184
185 protected void drawPoly(final SunGraphics2D sg2d,
186 final int[] xPoints, final int[] yPoints,
187 final int nPoints, final boolean isClosed)
188 {
189 if (xPoints == null || yPoints == null) {
190 throw new NullPointerException("coordinate array");
191 }
192 if (xPoints.length < nPoints || yPoints.length < nPoints) {
193 throw new ArrayIndexOutOfBoundsException("coordinate array");
194 }
195
196 if (nPoints < 2) {
197 // render nothing
198 return;
199 } else if (nPoints == 2 && !isClosed) {
200 // render a simple line
201 drawLine(sg2d, xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
202 return;
203 }
204
205 rq.lock();
206 try {
207 validateContext(sg2d);
208
209 int pointBytesRequired = nPoints * BYTES_PER_POLY_POINT;
210 int totalBytesRequired = 20 + pointBytesRequired;
211
212 if (totalBytesRequired <= buf.capacity()) {
213 if (totalBytesRequired > buf.remaining()) {
214 // process the queue first and then enqueue the points
215 rq.flushNow();
216 }
217 buf.putInt(DRAW_POLY);
218 // enqueue parameters
219 buf.putInt(nPoints);
220 buf.putInt(isClosed ? 1 : 0);
221 buf.putInt(sg2d.transX);
222 buf.putInt(sg2d.transY);
223 // enqueue the points
224 buf.put(xPoints, 0, nPoints);
225 buf.put(yPoints, 0, nPoints);
226 } else {
227 // queue is too small to accomodate all points; perform the
228 // operation directly on the queue flushing thread
229 rq.flushAndInvokeNow(new Runnable() {
230 public void run() {
231 drawPoly(xPoints, yPoints,
232 nPoints, isClosed,
233 sg2d.transX, sg2d.transY);
234 }
235 });
236 }
237 } finally {
238 rq.unlock();
239 }
240 }
241
242 protected abstract void drawPoly(int[] xPoints, int[] yPoints,
243 int nPoints, boolean isClosed,
244 int transX, int transY);
245
246 public void drawPolyline(SunGraphics2D sg2d,
247 int[] xPoints, int[] yPoints,
248 int nPoints)
249 {
250 drawPoly(sg2d, xPoints, yPoints, nPoints, false);
251 }
252
253 public void drawPolygon(SunGraphics2D sg2d,
254 int[] xPoints, int[] yPoints,
255 int nPoints)
256 {
257 drawPoly(sg2d, xPoints, yPoints, nPoints, true);
258 }
259
260 public void fillPolygon(SunGraphics2D sg2d,
261 int[] xPoints, int[] yPoints,
262 int nPoints)
263 {
264 fill(sg2d, new Polygon(xPoints, yPoints, nPoints));
265 }
266
267 private class BufferedDrawHandler
268 extends ProcessPath.DrawHandler
269 {
270 BufferedDrawHandler() {
271 // these are bogus values; the caller will use validate()
272 // to ensure that they are set properly prior to each usage
273 super(0, 0, 0, 0);
274 }
275
276 /**
277 * This method needs to be called prior to each draw/fillPath()
278 * operation to ensure the clip bounds are up to date.
279 */
280 void validate(SunGraphics2D sg2d) {
281 Region clip = sg2d.getCompClip();
282 setBounds(clip.getLoX(), clip.getLoY(),
283 clip.getHiX(), clip.getHiY(),
284 sg2d.strokeHint);
285 }
286
287 /**
288 * drawPath() support...
289 */
290
291 public void drawLine(int x1, int y1, int x2, int y2) {
292 // assert rq.lock.isHeldByCurrentThread();
293 rq.ensureCapacity(20);
294 buf.putInt(DRAW_LINE);
295 buf.putInt(x1);
296 buf.putInt(y1);
297 buf.putInt(x2);
298 buf.putInt(y2);
299 }
300
301 public void drawPixel(int x, int y) {
302 // assert rq.lock.isHeldByCurrentThread();
303 rq.ensureCapacity(12);
304 buf.putInt(DRAW_PIXEL);
305 buf.putInt(x);
306 buf.putInt(y);
307 }
308
309 /**
310 * fillPath() support...
311 */
312
313 private int scanlineCount;
314 private int scanlineCountIndex;
315 private int remainingScanlines;
316
317 private void resetFillPath() {
318 buf.putInt(DRAW_SCANLINES);
319 scanlineCountIndex = buf.position();
320 buf.putInt(0);
321 scanlineCount = 0;
322 remainingScanlines = buf.remaining() / BYTES_PER_SCANLINE;
323 }
324
325 private void updateScanlineCount() {
326 buf.putInt(scanlineCountIndex, scanlineCount);
327 }
328
329 /**
330 * Called from fillPath() to indicate that we are about to
331 * start issuing drawScanline() calls.
332 */
333 public void startFillPath() {
334 rq.ensureCapacity(20); // to ensure room for at least a scanline
335 resetFillPath();
336 }
337
338 public void drawScanline(int x1, int x2, int y) {
339 if (remainingScanlines == 0) {
340 updateScanlineCount();
341 rq.flushNow();
342 resetFillPath();
343 }
344 buf.putInt(x1);
345 buf.putInt(x2);
346 buf.putInt(y);
347 scanlineCount++;
348 remainingScanlines--;
349 }
350
351 /**
352 * Called from fillPath() to indicate that we are done
353 * issuing drawScanline() calls.
354 */
355 public void endFillPath() {
356 updateScanlineCount();
357 }
358 }
359
360 protected void drawPath(SunGraphics2D sg2d,
361 Path2D.Float p2df, int transx, int transy)
362 {
363 rq.lock();
364 try {
365 validateContext(sg2d);
366 drawHandler.validate(sg2d);
367 ProcessPath.drawPath(drawHandler, p2df, transx, transy);
368 } finally {
369 rq.unlock();
370 }
371 }
372
373 protected void fillPath(SunGraphics2D sg2d,
374 Path2D.Float p2df, int transx, int transy)
375 {
376 rq.lock();
377 try {
378 validateContext(sg2d);
379 drawHandler.validate(sg2d);
380 drawHandler.startFillPath();
381 ProcessPath.fillPath(drawHandler, p2df, transx, transy);
382 drawHandler.endFillPath();
383 } finally {
384 rq.unlock();
385 }
386 }
387
388 private native int fillSpans(RenderQueue rq, long buf,
389 int pos, int limit,
390 SpanIterator si, long iterator,
391 int transx, int transy);
392
393 protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
394 int transx, int transy)
395 {
396 rq.lock();
397 try {
398 validateContext(sg2d);
399 rq.ensureCapacity(24); // so that we have room for at least a span
400 int newpos = fillSpans(rq, buf.getAddress(),
401 buf.position(), buf.capacity(),
402 si, si.getNativeIterator(),
403 transx, transy);
404 buf.position(newpos);
405 } finally {
406 rq.unlock();
407 }
408 }
409
410 public void fillParallelogram(SunGraphics2D sg2d,
411 double ux1, double uy1,
412 double ux2, double uy2,
413 double x, double y,
414 double dx1, double dy1,
415 double dx2, double dy2)
416 {
417 rq.lock();
418 try {
419 validateContext(sg2d);
420 rq.ensureCapacity(28);
421 buf.putInt(FILL_PARALLELOGRAM);
422 buf.putFloat((float) x);
423 buf.putFloat((float) y);
424 buf.putFloat((float) dx1);
425 buf.putFloat((float) dy1);
426 buf.putFloat((float) dx2);
427 buf.putFloat((float) dy2);
428 } finally {
429 rq.unlock();
430 }
431 }
432
433 public void drawParallelogram(SunGraphics2D sg2d,
434 double ux1, double uy1,
435 double ux2, double uy2,
436 double x, double y,
437 double dx1, double dy1,
438 double dx2, double dy2,
439 double lw1, double lw2)
440 {
441 rq.lock();
442 try {
443 validateContext(sg2d);
444 rq.ensureCapacity(36);
445 buf.putInt(DRAW_PARALLELOGRAM);
446 buf.putFloat((float) x);
447 buf.putFloat((float) y);
448 buf.putFloat((float) dx1);
449 buf.putFloat((float) dy1);
450 buf.putFloat((float) dx2);
451 buf.putFloat((float) dy2);
452 buf.putFloat((float) lw1);
453 buf.putFloat((float) lw2);
454 } finally {
455 rq.unlock();
456 }
457 }
458
459 private class AAParallelogramPipe implements ParallelogramPipe {
460 public void fillParallelogram(SunGraphics2D sg2d,
461 double ux1, double uy1,
462 double ux2, double uy2,
463 double x, double y,
464 double dx1, double dy1,
465 double dx2, double dy2)
466 {
467 rq.lock();
468 try {
469 validateContextAA(sg2d);
470 rq.ensureCapacity(28);
471 buf.putInt(FILL_AAPARALLELOGRAM);
472 buf.putFloat((float) x);
473 buf.putFloat((float) y);
474 buf.putFloat((float) dx1);
475 buf.putFloat((float) dy1);
476 buf.putFloat((float) dx2);
477 buf.putFloat((float) dy2);
478 } finally {
479 rq.unlock();
480 }
481 }
482
483 public void drawParallelogram(SunGraphics2D sg2d,
484 double ux1, double uy1,
485 double ux2, double uy2,
486 double x, double y,
487 double dx1, double dy1,
488 double dx2, double dy2,
489 double lw1, double lw2)
490 {
491 rq.lock();
492 try {
493 validateContextAA(sg2d);
494 rq.ensureCapacity(36);
495 buf.putInt(DRAW_AAPARALLELOGRAM);
496 buf.putFloat((float) x);
497 buf.putFloat((float) y);
498 buf.putFloat((float) dx1);
499 buf.putFloat((float) dy1);
500 buf.putFloat((float) dx2);
501 buf.putFloat((float) dy2);
502 buf.putFloat((float) lw1);
503 buf.putFloat((float) lw2);
504 } finally {
505 rq.unlock();
506 }
507 }
508 }
509
510 public void draw(SunGraphics2D sg2d, Shape s) {
511 if (sg2d.strokeState == sg2d.STROKE_THIN) {
512 if (s instanceof Polygon) {
513 if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) {
514 Polygon p = (Polygon)s;
515 drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
516 return;
517 }
518 }
519 Path2D.Float p2df;
520 int transx, transy;
521 if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
522 if (s instanceof Path2D.Float) {
523 p2df = (Path2D.Float)s;
524 } else {
525 p2df = new Path2D.Float(s);
526 }
527 transx = sg2d.transX;
528 transy = sg2d.transY;
529 } else {
530 p2df = new Path2D.Float(s, sg2d.transform);
531 transx = 0;
532 transy = 0;
533 }
534 drawPath(sg2d, p2df, transx, transy);
535 } else if (sg2d.strokeState < sg2d.STROKE_CUSTOM) {
536 ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
537 try {
538 fillSpans(sg2d, si, 0, 0);
539 } finally {
540 si.dispose();
541 }
542 } else {
543 fill(sg2d, sg2d.stroke.createStrokedShape(s));
544 }
545 }
546
547 public void fill(SunGraphics2D sg2d, Shape s) {
548 int transx, transy;
549
550 if (sg2d.strokeState == sg2d.STROKE_THIN) {
551 // Here we are able to use fillPath() for
552 // high-quality fills.
553 Path2D.Float p2df;
554 if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
555 if (s instanceof Path2D.Float) {
556 p2df = (Path2D.Float)s;
557 } else {
558 p2df = new Path2D.Float(s);
559 }
560 transx = sg2d.transX;
561 transy = sg2d.transY;
562 } else {
563 p2df = new Path2D.Float(s, sg2d.transform);
564 transx = 0;
565 transy = 0;
566 }
567 fillPath(sg2d, p2df, transx, transy);
568 return;
569 }
570
571 AffineTransform at;
572 if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
573 // Transform (translation) will be done by FillSpans (we could
574 // delegate to fillPolygon() here, but most hardware accelerated
575 // libraries cannot handle non-convex polygons, so we will use
576 // the FillSpans approach by default)
577 at = null;
578 transx = sg2d.transX;
579 transy = sg2d.transY;
580 } else {
581 // Transform will be done by the PathIterator
582 at = sg2d.transform;
583 transx = transy = 0;
584 }
585
586 ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
587 try {
588 // Subtract transx/y from the SSI clip to match the
589 // (potentially untranslated) geometry fed to it
590 Region clip = sg2d.getCompClip();
591 ssi.setOutputAreaXYXY(clip.getLoX() - transx,
592 clip.getLoY() - transy,
593 clip.getHiX() - transx,
594 clip.getHiY() - transy);
595 ssi.appendPath(s.getPathIterator(at));
596 fillSpans(sg2d, ssi, transx, transy);
597 } finally {
598 ssi.dispose();
599 }
600 }
601}