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+
26+package sun.java2d.pipe;
27+
28+import java.awt.BasicStroke;
29+import java.awt.Polygon;
30+import java.awt.Shape;
31+import java.awt.geom.AffineTransform;
32+import java.awt.geom.Arc2D;
33+import java.awt.geom.Ellipse2D;
34+import java.awt.geom.Path2D;
35+import java.awt.geom.IllegalPathStateException;
36+import java.awt.geom.PathIterator;
37+import java.awt.geom.Rectangle2D;
38+import java.awt.geom.RoundRectangle2D;
39+import sun.java2d.SunGraphics2D;
40+import sun.java2d.loops.ProcessPath;
41+import 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+ */
55+public 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+}