Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libawt/java2d/loops/DrawParallelogram.c
41159 views
1
/*
2
* Copyright (c) 2008, 2010, 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
#include "math.h"
27
#include "GraphicsPrimitiveMgr.h"
28
#include "LineUtils.h"
29
#include "Trace.h"
30
#include "ParallelogramUtils.h"
31
32
#include "sun_java2d_loops_DrawParallelogram.h"
33
34
#define HANDLE_PGRAM_EDGE(X1, Y1, X2, Y2, \
35
pRasInfo, pixel, pPrim, pFunc, pCompInfo) \
36
do { \
37
jint ix1 = (jint) floor(X1); \
38
jint ix2 = (jint) floor(X2); \
39
jint iy1 = (jint) floor(Y1); \
40
jint iy2 = (jint) floor(Y2); \
41
LineUtils_ProcessLine(pRasInfo, pixel, \
42
pFunc, pPrim, pCompInfo, \
43
ix1, iy1, ix2, iy2, JNI_TRUE); \
44
} while (0)
45
46
typedef struct {
47
jdouble x0;
48
jdouble y0;
49
jdouble y1;
50
jdouble slope;
51
jlong dx;
52
jint ystart;
53
jint yend;
54
} EdgeInfo;
55
56
#define STORE_EDGE(pEDGE, X0, Y0, Y1, SLOPE, DELTAX) \
57
do { \
58
(pEDGE)->x0 = (X0); \
59
(pEDGE)->y0 = (Y0); \
60
(pEDGE)->y1 = (Y1); \
61
(pEDGE)->slope = (SLOPE); \
62
(pEDGE)->dx = (DELTAX); \
63
(pEDGE)->ystart = (jint) floor((Y0) + 0.5); \
64
(pEDGE)->yend = (jint) floor((Y1) + 0.5); \
65
} while (0)
66
67
#define STORE_PGRAM(pLTEDGE, pRTEDGE, \
68
X0, Y0, dX1, dY1, dX2, dY2, \
69
SLOPE1, SLOPE2, DELTAX1, DELTAX2) \
70
do { \
71
STORE_EDGE((pLTEDGE)+0, \
72
(X0), (Y0), (Y0) + (dY1), \
73
(SLOPE1), (DELTAX1)); \
74
STORE_EDGE((pRTEDGE)+0, \
75
(X0), (Y0), (Y0) + (dY2), \
76
(SLOPE2), (DELTAX2)); \
77
STORE_EDGE((pLTEDGE)+1, \
78
(X0) + (dX1), (Y0) + (dY1), (Y0) + (dY1) + (dY2), \
79
(SLOPE2), (DELTAX2)); \
80
STORE_EDGE((pRTEDGE)+1, \
81
(X0) + (dX2), (Y0) + (dY2), (Y0) + (dY1) + (dY2), \
82
(SLOPE1), (DELTAX1)); \
83
} while (0)
84
85
/*
86
* Class: sun_java2d_loops_DrawParallelogram
87
* Method: DrawParallelogram
88
* Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;DDDDDDDD)V
89
*/
90
JNIEXPORT void JNICALL
91
Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram
92
(JNIEnv *env, jobject self,
93
jobject sg2d, jobject sData,
94
jdouble x0, jdouble y0,
95
jdouble dx1, jdouble dy1,
96
jdouble dx2, jdouble dy2,
97
jdouble lw1, jdouble lw2)
98
{
99
SurfaceDataOps *sdOps;
100
SurfaceDataRasInfo rasInfo;
101
NativePrimitive *pPrim;
102
CompositeInfo compInfo;
103
jint pixel;
104
EdgeInfo edges[8];
105
EdgeInfo *active[4];
106
jint ix1, iy1, ix2, iy2;
107
jdouble ldx1, ldy1, ldx2, ldy2;
108
jdouble ox0, oy0;
109
110
/*
111
* Sort parallelogram by y values, ensure that each delta vector
112
* has a non-negative y delta.
113
*/
114
SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2,
115
v = lw1; lw1 = lw2; lw2 = v;);
116
117
// dx,dy for line width in the "1" and "2" directions.
118
ldx1 = dx1 * lw1;
119
ldy1 = dy1 * lw1;
120
ldx2 = dx2 * lw2;
121
ldy2 = dy2 * lw2;
122
123
// calculate origin of the outer parallelogram
124
ox0 = x0 - (ldx1 + ldx2) / 2.0;
125
oy0 = y0 - (ldy1 + ldy2) / 2.0;
126
127
PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2, JNI_FALSE);
128
iy1 = (jint) floor(oy0 + 0.5);
129
iy2 = (jint) floor(oy0 + dy1 + ldy1 + dy2 + ldy2 + 0.5);
130
131
pPrim = GetNativePrim(env, self);
132
if (pPrim == NULL) {
133
return;
134
}
135
pixel = GrPrim_Sg2dGetPixel(env, sg2d);
136
if (pPrim->pCompType->getCompInfo != NULL) {
137
GrPrim_Sg2dGetCompInfo(env, sg2d, pPrim, &compInfo);
138
}
139
140
sdOps = SurfaceData_GetOps(env, sData);
141
if (sdOps == NULL) {
142
return;
143
}
144
145
GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
146
SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
147
if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
148
rasInfo.bounds.x2 <= rasInfo.bounds.x1)
149
{
150
return;
151
}
152
153
if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
154
return;
155
}
156
157
ix1 = rasInfo.bounds.x1;
158
iy1 = rasInfo.bounds.y1;
159
ix2 = rasInfo.bounds.x2;
160
iy2 = rasInfo.bounds.y2;
161
if (ix2 > ix1 && iy2 > iy1) {
162
sdOps->GetRasInfo(env, sdOps, &rasInfo);
163
if (rasInfo.rasBase) {
164
jdouble lslope, rslope;
165
jlong ldx, rdx;
166
jint loy, hiy, numedges;
167
FillParallelogramFunc *pFill =
168
pPrim->funcs.drawparallelogram->fillpgram;
169
170
lslope = (dy1 == 0) ? 0 : dx1 / dy1;
171
rslope = (dy2 == 0) ? 0 : dx2 / dy2;
172
ldx = DblToLong(lslope);
173
rdx = DblToLong(rslope);
174
175
// Only need to generate 4 quads if the interior still
176
// has a hole in it (i.e. if the line width ratios were
177
// both less than 1.0)
178
if (lw1 < 1.0 && lw2 < 1.0) {
179
// If the line widths are both less than a pixel wide
180
// then we can use a drawline function instead for even
181
// more performance.
182
lw1 = sqrt(ldx1*ldx1 + ldy1*ldy1);
183
lw2 = sqrt(ldx2*ldx2 + ldy2*ldy2);
184
if (lw1 <= 1.0001 && lw2 <= 1.0001) {
185
jdouble x3, y3;
186
DrawLineFunc *pLine =
187
pPrim->funcs.drawparallelogram->drawline;
188
189
x3 = (dx1 += x0);
190
y3 = (dy1 += y0);
191
x3 += dx2;
192
y3 += dy2;
193
dx2 += x0;
194
dy2 += y0;
195
196
HANDLE_PGRAM_EDGE( x0, y0, dx1, dy1,
197
&rasInfo, pixel, pPrim, pLine, &compInfo);
198
HANDLE_PGRAM_EDGE(dx1, dy1, x3, y3,
199
&rasInfo, pixel, pPrim, pLine, &compInfo);
200
HANDLE_PGRAM_EDGE( x3, y3, dx2, dy2,
201
&rasInfo, pixel, pPrim, pLine, &compInfo);
202
HANDLE_PGRAM_EDGE(dx2, dy2, x0, y0,
203
&rasInfo, pixel, pPrim, pLine, &compInfo);
204
SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
205
SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
206
return;
207
}
208
209
// To simplify the edge management below we presort the
210
// inner and outer edges so that they are globally sorted
211
// from left to right. If you scan across the array of
212
// edges for a given Y range then the edges you encounter
213
// will be sorted in X as well.
214
// If AB are left top and bottom edges of outer parallelogram,
215
// and CD are the right pair of edges, and abcd are the
216
// corresponding inner parallelogram edges then we want them
217
// sorted as ABabcdCD to ensure this horizontal ordering.
218
// Conceptually it is like 2 pairs of nested parentheses.
219
STORE_PGRAM(edges + 2, edges + 4,
220
ox0 + ldx1 + ldx2, oy0 + ldy1 + ldy2,
221
dx1 - ldx1, dy1 - ldy1,
222
dx2 - ldx2, dy2 - ldy2,
223
lslope, rslope, ldx, rdx);
224
numedges = 8;
225
} else {
226
// The line width ratios were large enough to consume
227
// the entire hole in the middle of the parallelogram
228
// so we can just issue one large quad for the outer
229
// parallelogram.
230
numedges = 4;
231
}
232
233
// The outer parallelogram always goes in the first two
234
// and last two entries in the array so we either have
235
// ABabcdCD ordering for 8 edges or ABCD ordering for 4
236
// edges. See comment above where we store the inner
237
// parallelogram for a more complete description.
238
STORE_PGRAM(edges + 0, edges + numedges-2,
239
ox0, oy0,
240
dx1 + ldx1, dy1 + ldy1,
241
dx2 + ldx2, dy2 + ldy2,
242
lslope, rslope, ldx, rdx);
243
244
loy = edges[0].ystart;
245
if (loy < iy1) loy = iy1;
246
while (loy < iy2) {
247
jint numactive = 0;
248
jint cur;
249
250
hiy = iy2;
251
// Maintaining a sorted edge list is probably overkill for
252
// 4 or 8 edges. The indices chosen above for storing the
253
// inner and outer left and right edges already guarantee
254
// left to right ordering so we just need to scan for edges
255
// that overlap the current Y range (and also determine the
256
// maximum Y value for which the range is valid).
257
for (cur = 0; cur < numedges; cur++) {
258
EdgeInfo *pEdge = &edges[cur];
259
jint yend = pEdge->yend;
260
if (loy < yend) {
261
// This edge is still in play, have we reached it yet?
262
jint ystart = pEdge->ystart;
263
if (loy < ystart) {
264
// This edge is not active (yet)
265
// Stop before we get to the top of it
266
if (hiy > ystart) hiy = ystart;
267
} else {
268
// This edge is active, store it
269
active[numactive++] = pEdge;
270
// And stop when we get to the bottom of it
271
if (hiy > yend) hiy = yend;
272
}
273
}
274
}
275
#ifdef DEBUG
276
if ((numactive & 1) != 0) {
277
J2dTraceLn1(J2D_TRACE_ERROR,
278
"DrawParallelogram: "
279
"ODD NUMBER OF PGRAM EDGES (%d)!!",
280
numactive);
281
}
282
#endif
283
for (cur = 0; cur < numactive; cur += 2) {
284
EdgeInfo *pLeft = active[cur+0];
285
EdgeInfo *pRight = active[cur+1];
286
jlong lx = PGRAM_INIT_X(loy,
287
pLeft->x0, pLeft->y0,
288
pLeft->slope);
289
jlong rx = PGRAM_INIT_X(loy,
290
pRight->x0, pRight->y0,
291
pRight->slope);
292
(*pFill)(&rasInfo,
293
ix1, loy, ix2, hiy,
294
lx, pLeft->dx,
295
rx, pRight->dx,
296
pixel, pPrim, &compInfo);
297
}
298
loy = hiy;
299
}
300
}
301
SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
302
}
303
SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
304
}
305
306