Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/java2d/pipe/BufferedRenderPipe.java
41159 views
1
/*
2
* Copyright (c) 2005, 2013, 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 accommodate 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 == SunGraphics2D.STROKE_THIN) {
512
if (s instanceof Polygon) {
513
if (sg2d.transformState < SunGraphics2D.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 <= SunGraphics2D.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 < SunGraphics2D.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 == SunGraphics2D.STROKE_THIN) {
551
// Here we are able to use fillPath() for
552
// high-quality fills.
553
Path2D.Float p2df;
554
if (sg2d.transformState <= SunGraphics2D.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 <= SunGraphics2D.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
}
602
603