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/PixelToParallelogramConverter.java
41159 views
1
/*
2
* Copyright (c) 2008, 2018, 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.Shape;
29
import java.awt.BasicStroke;
30
import java.awt.geom.Line2D;
31
import java.awt.geom.Rectangle2D;
32
import java.awt.geom.AffineTransform;
33
import sun.java2d.SunGraphics2D;
34
import sun.awt.SunHints;
35
36
/**
37
* This class converts calls to the basic pixel rendering methods
38
* into calls to the methods on a ParallelogramPipe.
39
* Most calls are transformed into calls to the fill(Shape) method
40
* by the parent PixelToShapeConverter class, but some calls are
41
* transformed into calls to fill/drawParallelogram().
42
*/
43
public class PixelToParallelogramConverter extends PixelToShapeConverter
44
implements ShapeDrawPipe
45
{
46
ParallelogramPipe outrenderer;
47
double minPenSize;
48
double normPosition;
49
double normRoundingBias;
50
boolean adjustfill;
51
52
/**
53
* @param shapepipe pipeline to forward shape calls to
54
* @param pgrampipe pipeline to forward parallelogram calls to
55
* (and drawLine calls if possible)
56
* @param minPenSize minimum pen size for dropout control
57
* @param normPosition sub-pixel location to normalize endpoints
58
* for STROKE_NORMALIZE cases
59
* @param adjustfill boolean to control whethere normalization
60
* constants are also applied to fill operations
61
* (normally true for non-AA, false for AA)
62
*/
63
public PixelToParallelogramConverter(ShapeDrawPipe shapepipe,
64
ParallelogramPipe pgrampipe,
65
double minPenSize,
66
double normPosition,
67
boolean adjustfill)
68
{
69
super(shapepipe);
70
outrenderer = pgrampipe;
71
this.minPenSize = minPenSize;
72
this.normPosition = normPosition;
73
this.normRoundingBias = 0.5 - normPosition;
74
this.adjustfill = adjustfill;
75
}
76
77
public void drawLine(SunGraphics2D sg2d,
78
int x1, int y1, int x2, int y2)
79
{
80
if (!drawGeneralLine(sg2d, x1, y1, x2, y2)) {
81
super.drawLine(sg2d, x1, y1, x2, y2);
82
}
83
}
84
85
public void drawRect(SunGraphics2D sg2d,
86
int x, int y, int w, int h)
87
{
88
if (w >= 0 && h >= 0) {
89
if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
90
BasicStroke bs = ((BasicStroke) sg2d.stroke);
91
if (w > 0 && h > 0) {
92
if (bs.getLineJoin() == BasicStroke.JOIN_MITER &&
93
bs.getDashArray() == null)
94
{
95
double lw = bs.getLineWidth();
96
drawRectangle(sg2d, x, y, w, h, lw);
97
return;
98
}
99
} else {
100
// Note: This calls the integer version which
101
// will verify that the local drawLine optimizations
102
// work and call super.drawLine(), if not.
103
drawLine(sg2d, x, y, x+w, y+h);
104
return;
105
}
106
}
107
super.drawRect(sg2d, x, y, w, h);
108
}
109
}
110
111
public void fillRect(SunGraphics2D sg2d,
112
int x, int y, int w, int h)
113
{
114
if (w > 0 && h > 0) {
115
fillRectangle(sg2d, x, y, w, h);
116
}
117
}
118
119
public void draw(SunGraphics2D sg2d, Shape s) {
120
if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
121
BasicStroke bs = ((BasicStroke) sg2d.stroke);
122
if (s instanceof Rectangle2D) {
123
if (bs.getLineJoin() == BasicStroke.JOIN_MITER &&
124
bs.getDashArray() == null)
125
{
126
Rectangle2D r2d = (Rectangle2D) s;
127
double w = r2d.getWidth();
128
double h = r2d.getHeight();
129
double x = r2d.getX();
130
double y = r2d.getY();
131
if (w >= 0 && h >= 0) {
132
double lw = bs.getLineWidth();
133
drawRectangle(sg2d, x, y, w, h, lw);
134
}
135
return;
136
}
137
} else if (s instanceof Line2D) {
138
Line2D l2d = (Line2D) s;
139
if (drawGeneralLine(sg2d,
140
l2d.getX1(), l2d.getY1(),
141
l2d.getX2(), l2d.getY2()))
142
{
143
return;
144
}
145
}
146
}
147
148
outpipe.draw(sg2d, s);
149
}
150
151
public void fill(SunGraphics2D sg2d, Shape s) {
152
if (s instanceof Rectangle2D) {
153
Rectangle2D r2d = (Rectangle2D) s;
154
double w = r2d.getWidth();
155
double h = r2d.getHeight();
156
if (w > 0 && h > 0) {
157
double x = r2d.getX();
158
double y = r2d.getY();
159
fillRectangle(sg2d, x, y, w, h);
160
}
161
return;
162
}
163
164
outpipe.fill(sg2d, s);
165
}
166
167
static double len(double x, double y) {
168
return ((x == 0) ? Math.abs(y)
169
: ((y == 0) ? Math.abs(x)
170
: Math.sqrt(x * x + y * y)));
171
}
172
173
double normalize(double v) {
174
return Math.floor(v + normRoundingBias) + normPosition;
175
}
176
177
public boolean drawGeneralLine(SunGraphics2D sg2d,
178
double ux1, double uy1,
179
double ux2, double uy2)
180
{
181
if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM ||
182
sg2d.strokeState == SunGraphics2D.STROKE_THINDASHED)
183
{
184
return false;
185
}
186
BasicStroke bs = (BasicStroke) sg2d.stroke;
187
int cap = bs.getEndCap();
188
if (cap == BasicStroke.CAP_ROUND || bs.getDashArray() != null) {
189
// TODO: we could construct the GeneralPath directly
190
// for CAP_ROUND and save a lot of processing in that case...
191
// And again, we would need to deal with dropout control...
192
return false;
193
}
194
double lw = bs.getLineWidth();
195
// Save the original dx, dy in case we need it to transform
196
// the linewidth as a perpendicular vector below
197
double dx = ux2 - ux1;
198
double dy = uy2 - uy1;
199
double x1, y1, x2, y2;
200
switch (sg2d.transformState) {
201
case SunGraphics2D.TRANSFORM_GENERIC:
202
case SunGraphics2D.TRANSFORM_TRANSLATESCALE:
203
{
204
double[] coords = {ux1, uy1, ux2, uy2};
205
sg2d.transform.transform(coords, 0, coords, 0, 2);
206
x1 = coords[0];
207
y1 = coords[1];
208
x2 = coords[2];
209
y2 = coords[3];
210
}
211
break;
212
case SunGraphics2D.TRANSFORM_ANY_TRANSLATE:
213
case SunGraphics2D.TRANSFORM_INT_TRANSLATE:
214
{
215
double tx = sg2d.transform.getTranslateX();
216
double ty = sg2d.transform.getTranslateY();
217
x1 = ux1 + tx;
218
y1 = uy1 + ty;
219
x2 = ux2 + tx;
220
y2 = uy2 + ty;
221
}
222
break;
223
case SunGraphics2D.TRANSFORM_ISIDENT:
224
x1 = ux1;
225
y1 = uy1;
226
x2 = ux2;
227
y2 = uy2;
228
break;
229
default:
230
throw new InternalError("unknown TRANSFORM state...");
231
}
232
if (sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE) {
233
if (sg2d.strokeState == SunGraphics2D.STROKE_THIN &&
234
outrenderer instanceof PixelDrawPipe)
235
{
236
// PixelDrawPipes will add sg2d.transXY so we need to factor
237
// that out...
238
int ix1 = (int) Math.floor(x1 - sg2d.transX);
239
int iy1 = (int) Math.floor(y1 - sg2d.transY);
240
int ix2 = (int) Math.floor(x2 - sg2d.transX);
241
int iy2 = (int) Math.floor(y2 - sg2d.transY);
242
((PixelDrawPipe)outrenderer).drawLine(sg2d, ix1, iy1, ix2, iy2);
243
return true;
244
}
245
x1 = normalize(x1);
246
y1 = normalize(y1);
247
x2 = normalize(x2);
248
y2 = normalize(y2);
249
}
250
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
251
// Transform the linewidth...
252
// calculate the scaling factor for a unit vector
253
// perpendicular to the original user space line.
254
double len = len(dx, dy);
255
if (len == 0) {
256
dx = len = 1;
257
// dy = 0; already
258
}
259
// delta transform the transposed (90 degree rotated) unit vector
260
double[] unitvector = {dy/len, -dx/len};
261
sg2d.transform.deltaTransform(unitvector, 0, unitvector, 0, 1);
262
lw *= len(unitvector[0], unitvector[1]);
263
}
264
lw = Math.max(lw, minPenSize);
265
dx = x2 - x1;
266
dy = y2 - y1;
267
double len = len(dx, dy);
268
double udx, udy;
269
if (len == 0) {
270
if (cap == BasicStroke.CAP_BUTT) {
271
return true;
272
}
273
udx = lw;
274
udy = 0;
275
} else {
276
udx = lw * dx / len;
277
udy = lw * dy / len;
278
}
279
double px = x1 + udy / 2.0;
280
double py = y1 - udx / 2.0;
281
if (cap == BasicStroke.CAP_SQUARE) {
282
px -= udx / 2.0;
283
py -= udy / 2.0;
284
dx += udx;
285
dy += udy;
286
}
287
outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
288
px, py, -udy, udx, dx, dy);
289
return true;
290
}
291
292
public void fillRectangle(SunGraphics2D sg2d,
293
double rx, double ry,
294
double rw, double rh)
295
{
296
double px, py;
297
double dx1, dy1, dx2, dy2;
298
AffineTransform txform = sg2d.transform;
299
dx1 = txform.getScaleX();
300
dy1 = txform.getShearY();
301
dx2 = txform.getShearX();
302
dy2 = txform.getScaleY();
303
px = rx * dx1 + ry * dx2 + txform.getTranslateX();
304
py = rx * dy1 + ry * dy2 + txform.getTranslateY();
305
dx1 *= rw;
306
dy1 *= rw;
307
dx2 *= rh;
308
dy2 *= rh;
309
if (adjustfill &&
310
sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
311
sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
312
{
313
double newx = normalize(px);
314
double newy = normalize(py);
315
dx1 = normalize(px + dx1) - newx;
316
dy1 = normalize(py + dy1) - newy;
317
dx2 = normalize(px + dx2) - newx;
318
dy2 = normalize(py + dy2) - newy;
319
px = newx;
320
py = newy;
321
}
322
outrenderer.fillParallelogram(sg2d, rx, ry, rx+rw, ry+rh,
323
px, py, dx1, dy1, dx2, dy2);
324
}
325
326
public void drawRectangle(SunGraphics2D sg2d,
327
double rx, double ry,
328
double rw, double rh,
329
double lw)
330
{
331
double px, py;
332
double dx1, dy1, dx2, dy2;
333
double lw1, lw2;
334
AffineTransform txform = sg2d.transform;
335
dx1 = txform.getScaleX();
336
dy1 = txform.getShearY();
337
dx2 = txform.getShearX();
338
dy2 = txform.getScaleY();
339
px = rx * dx1 + ry * dx2 + txform.getTranslateX();
340
py = rx * dy1 + ry * dy2 + txform.getTranslateY();
341
// lw along dx1,dy1 scale by transformed length of dx2,dy2 vectors
342
// and vice versa
343
lw1 = len(dx1, dy1) * lw;
344
lw2 = len(dx2, dy2) * lw;
345
dx1 *= rw;
346
dy1 *= rw;
347
dx2 *= rh;
348
dy2 *= rh;
349
if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
350
sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
351
{
352
double newx = normalize(px);
353
double newy = normalize(py);
354
dx1 = normalize(px + dx1) - newx;
355
dy1 = normalize(py + dy1) - newy;
356
dx2 = normalize(px + dx2) - newx;
357
dy2 = normalize(py + dy2) - newy;
358
px = newx;
359
py = newy;
360
}
361
lw1 = Math.max(lw1, minPenSize);
362
lw2 = Math.max(lw2, minPenSize);
363
double len1 = len(dx1, dy1);
364
double len2 = len(dx2, dy2);
365
if (lw1 >= len1 || lw2 >= len2) {
366
// The line widths are large enough to consume the
367
// entire hole in the middle of the parallelogram
368
// so we can just fill the outer parallelogram.
369
fillOuterParallelogram(sg2d,
370
rx, ry, rx+rw, ry+rh,
371
px, py, dx1, dy1, dx2, dy2,
372
len1, len2, lw1, lw2);
373
} else {
374
outrenderer.drawParallelogram(sg2d,
375
rx, ry, rx+rw, ry+rh,
376
px, py, dx1, dy1, dx2, dy2,
377
lw1 / len1, lw2 / len2);
378
}
379
}
380
381
/**
382
* This utility function handles the case where a drawRectangle
383
* operation discovered that the interior hole in the rectangle
384
* or parallelogram has been completely filled in by the stroke
385
* width. It calculates the outer parallelogram of the stroke
386
* and issues a single fillParallelogram request to fill it.
387
*/
388
public void fillOuterParallelogram(SunGraphics2D sg2d,
389
double ux1, double uy1,
390
double ux2, double uy2,
391
double px, double py,
392
double dx1, double dy1,
393
double dx2, double dy2,
394
double len1, double len2,
395
double lw1, double lw2)
396
{
397
double udx1 = dx1 / len1;
398
double udy1 = dy1 / len1;
399
double udx2 = dx2 / len2;
400
double udy2 = dy2 / len2;
401
if (len1 == 0) {
402
// len1 is 0, replace udxy1 with perpendicular of udxy2
403
if (len2 == 0) {
404
// both are 0, use a unit Y vector for udxy2
405
udx2 = 0;
406
udy2 = 1;
407
}
408
udx1 = udy2;
409
udy1 = -udx2;
410
} else if (len2 == 0) {
411
// len2 is 0, replace udxy2 with perpendicular of udxy1
412
udx2 = udy1;
413
udy2 = -udx1;
414
}
415
udx1 *= lw1;
416
udy1 *= lw1;
417
udx2 *= lw2;
418
udy2 *= lw2;
419
px -= (udx1 + udx2) / 2;
420
py -= (udy1 + udy2) / 2;
421
dx1 += udx1;
422
dy1 += udy1;
423
dx2 += udx2;
424
dy2 += udy2;
425
426
outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
427
px, py, dx1, dy1, dx2, dy2);
428
}
429
}
430
431