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/RegionClipSpanIterator.java
41159 views
1
/*
2
* Copyright (c) 1999, 2020, 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
29
/**
30
* This class clips a SpanIterator to a Region and outputs the
31
* resulting spans as another SpanIterator.
32
*
33
* Spans are output in the usual y/x order, unless the input span
34
* iterator doesn't conform to this order, or the iterator's span
35
* straddle more than one band of the Region used for clipping.
36
*
37
* Principle of operation:
38
*
39
* The iterator maintains a several cursors onto the RegionIterator
40
* in order to avoid having to buffer spans from the SpanIterator.
41
* They are:
42
* resetState The initial state of the RegionIterator
43
* lwm Low Water Mark, a running start point for
44
* processing each band. Usually goes down, but
45
* can be reset to resetState if a span has a lower
46
* start coordinate than the previous one.
47
* row The start of the current band of the RegionIterator
48
* box The current span of the current row
49
*
50
* The main nextSpan() loop implements a coroutine like structure, with
51
* three producers to get the next span, row and box calling each other
52
* to iterate through the span iterator and region.
53
*
54
* REMIND: Needs a native implementation!
55
*/
56
public class RegionClipSpanIterator implements SpanIterator {
57
58
// The inputs to the filter
59
Region rgn;
60
SpanIterator spanIter;
61
62
// The cursors that track the progress through the region
63
RegionIterator resetState;
64
RegionIterator lwm;
65
RegionIterator row;
66
RegionIterator box;
67
68
// The bounds of the current span iterator span
69
int spanlox, spanhix, spanloy, spanhiy;
70
71
// The extent of the region band marking the low water mark
72
int lwmloy, lwmhiy;
73
74
// The bounds of the current region box
75
int rgnlox, rgnloy, rgnhix, rgnhiy;
76
77
// The bounding box of the input Region. Used for click
78
// rejection of iterator spans
79
int rgnbndslox, rgnbndsloy, rgnbndshix, rgnbndshiy;
80
81
// The array used to hold coordinates from the region iterator
82
int[] rgnbox = new int[4];
83
84
// The array used to hold coordinates from the span iterator
85
int[] spanbox = new int[4];
86
87
// True if the next iterator span should be read on the next
88
// iteration of the main nextSpan() loop
89
boolean doNextSpan;
90
91
// True if the next region box should be read on the next
92
// iteration of the main nextSpan() loop
93
boolean doNextBox;
94
95
// True if there are no more spans or the Region is empty
96
boolean done = false;
97
98
/*
99
* Creates an instance that filters the spans generated by
100
* spanIter through the region described by rgn.
101
*/
102
public RegionClipSpanIterator(Region rgn, SpanIterator spanIter) {
103
104
this.spanIter = spanIter;
105
106
resetState = rgn.getIterator();
107
lwm = resetState.createCopy();
108
109
if (!lwm.nextYRange(rgnbox)) {
110
done = true;
111
return;
112
}
113
114
rgnloy = lwmloy = rgnbox[1];
115
rgnhiy = lwmhiy = rgnbox[3];
116
117
rgn.getBounds(rgnbox);
118
rgnbndslox = rgnbox[0];
119
rgnbndsloy = rgnbox[1];
120
rgnbndshix = rgnbox[2];
121
rgnbndshiy = rgnbox[3];
122
if (rgnbndslox >= rgnbndshix ||
123
rgnbndsloy >= rgnbndshiy) {
124
done = true;
125
return;
126
}
127
128
this.rgn = rgn;
129
130
131
row = lwm.createCopy();
132
box = row.createCopy();
133
doNextSpan = true;
134
doNextBox = false;
135
}
136
137
/*
138
* Gets the bbox of the available path segments, clipped to the
139
* Region.
140
*/
141
public void getPathBox(int[] pathbox) {
142
int[] rgnbox = new int[4];
143
rgn.getBounds(rgnbox);
144
spanIter.getPathBox(pathbox);
145
146
if (pathbox[0] < rgnbox[0]) {
147
pathbox[0] = rgnbox[0];
148
}
149
150
if (pathbox[1] < rgnbox[1]) {
151
pathbox[1] = rgnbox[1];
152
}
153
154
if (pathbox[2] > rgnbox[2]) {
155
pathbox[2] = rgnbox[2];
156
}
157
158
if (pathbox[3] > rgnbox[3]) {
159
pathbox[3] = rgnbox[3];
160
}
161
}
162
163
/*
164
* Intersects the path box with the given bbox.
165
* Returned spans are clipped to this region, or discarded
166
* altogether if they lie outside it.
167
*/
168
public void intersectClipBox(int lox, int loy, int hix, int hiy) {
169
spanIter.intersectClipBox(lox, loy, hix, hiy);
170
}
171
172
173
/*
174
* Fetches the next span that needs to be operated on.
175
* If the return value is false then there are no more spans.
176
*/
177
public boolean nextSpan(int[] resultbox) {
178
if (done) {
179
return false;
180
}
181
182
int resultlox, resultloy, resulthix, resulthiy;
183
boolean doNextRow = false;
184
185
// REMIND: Cache the coordinate inst vars used in this loop
186
// in locals vars.
187
while (true) {
188
// We've exhausted the current span so get the next one
189
if (doNextSpan) {
190
if (!spanIter.nextSpan(spanbox)) {
191
done = true;
192
return false;
193
} else {
194
spanlox = spanbox[0];
195
// Clip out spans that lie outside of the rgn's bounds
196
if (spanlox >= rgnbndshix) {
197
continue;
198
}
199
200
spanloy = spanbox[1];
201
if (spanloy >= rgnbndshiy) {
202
continue;
203
}
204
205
spanhix = spanbox[2];
206
if (spanhix <= rgnbndslox) {
207
continue;
208
}
209
210
spanhiy = spanbox[3];
211
if (spanhiy <= rgnbndsloy) {
212
continue;
213
}
214
}
215
// If the span starts higher up than the low-water mark,
216
// reset the lwm. This can only happen if spans aren't
217
// returned in strict y/x order, or the first time through.
218
if (lwmloy > spanloy) {
219
lwm.copyStateFrom(resetState);
220
lwm.nextYRange(rgnbox);
221
lwmloy = rgnbox[1];
222
lwmhiy = rgnbox[3];
223
}
224
// Skip to the first rgn row whose bottom edge is
225
// below the top of the current span. This will only
226
// execute >0 times when the current span starts in a
227
// lower region row than the previous one, or possibly the
228
// first time through.
229
while (lwmhiy <= spanloy) {
230
if (!lwm.nextYRange(rgnbox))
231
break;
232
lwmloy = rgnbox[1];
233
lwmhiy = rgnbox[3];
234
}
235
// If the row overlaps the span, process it, otherwise
236
// fetch another span
237
if (lwmhiy > spanloy && lwmloy < spanhiy) {
238
// Update the current row if it's different from the
239
// new lwm
240
if (rgnloy != lwmloy) {
241
row.copyStateFrom(lwm);
242
rgnloy = lwmloy;
243
rgnhiy = lwmhiy;
244
}
245
box.copyStateFrom(row);
246
doNextBox = true;
247
doNextSpan = false;
248
}
249
continue;
250
}
251
252
// The current row's spans are exhausted, do the next one
253
if (doNextRow) {
254
// Next time we either do the next span or the next box
255
doNextRow = false;
256
// Get the next row
257
boolean ok = row.nextYRange(rgnbox);
258
// If there was one, update the bounds
259
if (ok) {
260
rgnloy = rgnbox[1];
261
rgnhiy = rgnbox[3];
262
}
263
if (!ok || rgnloy >= spanhiy) {
264
// If we've exhausted the rows or this one is below the span,
265
// go onto the next span
266
doNextSpan = true;
267
}
268
else {
269
// Otherwise get the first box on this row
270
box.copyStateFrom(row);
271
doNextBox = true;
272
}
273
continue;
274
}
275
276
// Process the next box in the current row
277
if (doNextBox) {
278
boolean ok = box.nextXBand(rgnbox);
279
if (ok) {
280
rgnlox = rgnbox[0];
281
rgnhix = rgnbox[2];
282
}
283
if (!ok || rgnlox >= spanhix) {
284
// If there was no next rgn span or it's beyond the
285
// source span, go onto the next row or span
286
doNextBox = false;
287
if (rgnhiy >= spanhiy) {
288
// If the current row totally overlaps the span,
289
// go onto the next span
290
doNextSpan = true;
291
} else {
292
// otherwise go onto the next rgn row
293
doNextRow = true;
294
}
295
} else {
296
// Otherwise, if the new rgn span overlaps the
297
// spanbox, no need to get another box
298
doNextBox = rgnhix <= spanlox;
299
}
300
continue;
301
}
302
303
// Prepare to do the next box either on this call or
304
// or the subsequent one
305
doNextBox = true;
306
307
// Clip the current span against the current box
308
if (spanlox > rgnlox) {
309
resultlox = spanlox;
310
}
311
else {
312
resultlox = rgnlox;
313
}
314
315
if (spanloy > rgnloy) {
316
resultloy = spanloy;
317
}
318
else {
319
resultloy = rgnloy;
320
}
321
322
if (spanhix < rgnhix) {
323
resulthix = spanhix;
324
}
325
else {
326
resulthix = rgnhix;
327
}
328
329
if (spanhiy < rgnhiy) {
330
resulthiy = spanhiy;
331
}
332
else {
333
resulthiy = rgnhiy;
334
}
335
336
// If the result is empty, try then next box
337
// otherwise return the box.
338
// REMIND: I think by definition it's non-empty
339
// if we're here. Need to think about this some more.
340
if (resultlox >= resulthix ||
341
resultloy >= resulthiy) {
342
continue;
343
}
344
else {
345
break;
346
}
347
}
348
349
resultbox[0] = resultlox;
350
resultbox[1] = resultloy;
351
resultbox[2] = resulthix;
352
resultbox[3] = resulthiy;
353
return true;
354
355
}
356
357
358
/**
359
* This method tells the iterator that it may skip all spans
360
* whose Y range is completely above the indicated Y coordinate.
361
*/
362
public void skipDownTo(int y) {
363
spanIter.skipDownTo(y);
364
}
365
366
/**
367
* This method returns a native pointer to a function block that
368
* can be used by a native method to perform the same iteration
369
* cycle that the above methods provide while avoiding upcalls to
370
* the Java object.
371
* The definition of the structure whose pointer is returned by
372
* this method is defined in:
373
* <pre>
374
* src/share/native/sun/java2d/pipe/SpanIterator.h
375
* </pre>
376
*/
377
public long getNativeIterator() {
378
return 0;
379
}
380
}
381
382