Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/java2d/marlin/MarlinTileGenerator.java
41159 views
1
/*
2
* Copyright (c) 2007, 2021, 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.marlin;
27
28
import java.util.Arrays;
29
import sun.java2d.pipe.AATileGenerator;
30
import jdk.internal.misc.Unsafe;
31
32
final class MarlinTileGenerator implements AATileGenerator, MarlinConst {
33
34
private static final boolean DISABLE_BLEND = false;
35
36
private static final int MAX_TILE_ALPHA_SUM = TILE_W * TILE_H * MAX_AA_ALPHA;
37
38
private static final int TH_AA_ALPHA_FILL_EMPTY = ((MAX_AA_ALPHA + 1) / 3); // 33%
39
private static final int TH_AA_ALPHA_FILL_FULL = ((MAX_AA_ALPHA + 1) * 2 / 3); // 66%
40
41
private static final int FILL_TILE_W = TILE_W >> 1; // half tile width
42
43
static {
44
if (MAX_TILE_ALPHA_SUM <= 0) {
45
throw new IllegalStateException("Invalid MAX_TILE_ALPHA_SUM: " + MAX_TILE_ALPHA_SUM);
46
}
47
if (DO_TRACE) {
48
MarlinUtils.logInfo("MAX_AA_ALPHA : " + MAX_AA_ALPHA);
49
MarlinUtils.logInfo("TH_AA_ALPHA_FILL_EMPTY : " + TH_AA_ALPHA_FILL_EMPTY);
50
MarlinUtils.logInfo("TH_AA_ALPHA_FILL_FULL : " + TH_AA_ALPHA_FILL_FULL);
51
MarlinUtils.logInfo("FILL_TILE_W : " + FILL_TILE_W);
52
}
53
}
54
55
private final Renderer renderer;
56
private final MarlinCache cache;
57
private int x, y;
58
59
// per-thread renderer stats
60
final RendererStats rdrStats;
61
62
MarlinTileGenerator(final RendererStats stats, final Renderer r,
63
final MarlinCache cache)
64
{
65
this.rdrStats = stats;
66
this.renderer = r;
67
this.cache = cache;
68
}
69
70
MarlinTileGenerator init() {
71
this.x = cache.bboxX0;
72
this.y = cache.bboxY0;
73
74
return this; // fluent API
75
}
76
77
/**
78
* Disposes this tile generator:
79
* clean up before reusing this instance
80
*/
81
@Override
82
public void dispose() {
83
if (DO_MONITORS) {
84
// called from AAShapePipe.renderTiles() (render tiles end):
85
rdrStats.mon_pipe_renderTiles.stop();
86
}
87
// dispose cache:
88
cache.dispose();
89
// dispose renderer and recycle the RendererContext instance:
90
renderer.dispose();
91
}
92
93
void getBbox(int[] bbox) {
94
bbox[0] = cache.bboxX0;
95
bbox[1] = cache.bboxY0;
96
bbox[2] = cache.bboxX1;
97
bbox[3] = cache.bboxY1;
98
}
99
100
/**
101
* Gets the width of the tiles that the generator batches output into.
102
* @return the width of the standard alpha tile
103
*/
104
@Override
105
public int getTileWidth() {
106
if (DO_MONITORS) {
107
// called from AAShapePipe.renderTiles() (render tiles start):
108
rdrStats.mon_pipe_renderTiles.start();
109
}
110
return TILE_W;
111
}
112
113
/**
114
* Gets the height of the tiles that the generator batches output into.
115
* @return the height of the standard alpha tile
116
*/
117
@Override
118
public int getTileHeight() {
119
return TILE_H;
120
}
121
122
/**
123
* Gets the typical alpha value that will characterize the current
124
* tile.
125
* The answer may be 0x00 to indicate that the current tile has
126
* no coverage in any of its pixels, or it may be 0xff to indicate
127
* that the current tile is completely covered by the path, or any
128
* other value to indicate non-trivial coverage cases.
129
* @return 0x00 for no coverage, 0xff for total coverage, or any other
130
* value for partial coverage of the tile
131
*/
132
@Override
133
public int getTypicalAlpha() {
134
if (DISABLE_BLEND) {
135
// always return empty tiles to disable blending operations
136
return 0x00;
137
}
138
int al = cache.alphaSumInTile(x);
139
// Note: if we have a filled rectangle that doesn't end on a tile
140
// border, we could still return 0xff, even though al!=maxTileAlphaSum
141
// This is because if we return 0xff, our users will fill a rectangle
142
// starting at x,y that has width = Math.min(TILE_SIZE, bboxX1-x),
143
// and height min(TILE_SIZE,bboxY1-y), which is what should happen.
144
// However, to support this, we would have to use 2 Math.min's
145
// and 2 multiplications per tile, instead of just 2 multiplications
146
// to compute maxTileAlphaSum. The savings offered would probably
147
// not be worth it, considering how rare this case is.
148
// Note: I have not tested this, so in the future if it is determined
149
// that it is worth it, it should be implemented. Perhaps this method's
150
// interface should be changed to take arguments the width and height
151
// of the current tile. This would eliminate the 2 Math.min calls that
152
// would be needed here, since our caller needs to compute these 2
153
// values anyway.
154
final int alpha = (al == 0x00 ? 0x00
155
: (al == MAX_TILE_ALPHA_SUM ? 0xff : 0x80));
156
if (DO_STATS) {
157
rdrStats.hist_tile_generator_alpha.add(alpha);
158
}
159
return alpha;
160
}
161
162
/**
163
* Skips the current tile and moves on to the next tile.
164
* Either this method, or the getAlpha() method should be called
165
* once per tile, but not both.
166
*/
167
@Override
168
public void nextTile() {
169
if ((x += TILE_W) >= cache.bboxX1) {
170
x = cache.bboxX0;
171
y += TILE_H;
172
173
if (y < cache.bboxY1) {
174
// compute for the tile line
175
// [ y; max(y + TILE_SIZE, bboxY1) ]
176
renderer.endRendering(y);
177
}
178
}
179
}
180
181
/**
182
* Gets the alpha coverage values for the current tile.
183
* Either this method, or the nextTile() method should be called
184
* once per tile, but not both.
185
*/
186
@Override
187
public void getAlpha(final byte[] tile, final int offset,
188
final int rowstride)
189
{
190
if (cache.useRLE) {
191
getAlphaRLE(tile, offset, rowstride);
192
} else {
193
getAlphaNoRLE(tile, offset, rowstride);
194
}
195
}
196
197
/**
198
* Gets the alpha coverage values for the current tile.
199
* Either this method, or the nextTile() method should be called
200
* once per tile, but not both.
201
*/
202
private void getAlphaNoRLE(final byte[] tile, final int offset,
203
final int rowstride)
204
{
205
if (DO_MONITORS) {
206
rdrStats.mon_ptg_getAlpha.start();
207
}
208
209
// local vars for performance:
210
final MarlinCache _cache = this.cache;
211
final long[] rowAAChunkIndex = _cache.rowAAChunkIndex;
212
final int[] rowAAx0 = _cache.rowAAx0;
213
final int[] rowAAx1 = _cache.rowAAx1;
214
215
final int x0 = this.x;
216
final int x1 = FloatMath.min(x0 + TILE_W, _cache.bboxX1);
217
218
// note: process tile line [0 - 32[
219
final int y0 = 0;
220
final int y1 = FloatMath.min(this.y + TILE_H, _cache.bboxY1) - this.y;
221
222
if (DO_LOG_BOUNDS) {
223
MarlinUtils.logInfo("getAlpha = [" + x0 + " ... " + x1
224
+ "[ [" + y0 + " ... " + y1 + "[");
225
}
226
227
final Unsafe _unsafe = OffHeapArray.UNSAFE;
228
final long SIZE = 1L;
229
final long addr_rowAA = _cache.rowAAChunk.address;
230
long addr;
231
232
final int skipRowPixels = (rowstride - (x1 - x0));
233
234
int aax0, aax1, end;
235
int idx = offset;
236
237
for (int cy = y0, cx; cy < y1; cy++) {
238
// empty line (default)
239
cx = x0;
240
241
aax1 = rowAAx1[cy]; // exclusive
242
243
// quick check if there is AA data
244
// corresponding to this tile [x0; x1[
245
if (aax1 > x0) {
246
aax0 = rowAAx0[cy]; // inclusive
247
248
if (aax0 < x1) {
249
// note: cx is the cursor pointer in the tile array
250
// (left to right)
251
cx = aax0;
252
253
// ensure cx >= x0
254
if (cx <= x0) {
255
cx = x0;
256
} else {
257
// fill line start until first AA pixel rowAA exclusive:
258
for (end = x0; end < cx; end++) {
259
tile[idx++] = 0;
260
}
261
}
262
263
// now: cx >= x0 and cx >= aax0
264
265
// Copy AA data (sum alpha data):
266
addr = addr_rowAA + rowAAChunkIndex[cy] + (cx - aax0);
267
268
for (end = (aax1 <= x1) ? aax1 : x1; cx < end; cx++) {
269
// cx inside tile[x0; x1[ :
270
tile[idx++] = _unsafe.getByte(addr); // [0-255]
271
addr += SIZE;
272
}
273
}
274
}
275
276
// fill line end
277
while (cx < x1) {
278
tile[idx++] = 0;
279
cx++;
280
}
281
282
if (DO_TRACE) {
283
for (int i = idx - (x1 - x0); i < idx; i++) {
284
System.out.print(hex(tile[i], 2));
285
}
286
System.out.println();
287
}
288
289
idx += skipRowPixels;
290
}
291
292
nextTile();
293
294
if (DO_MONITORS) {
295
rdrStats.mon_ptg_getAlpha.stop();
296
}
297
}
298
299
/**
300
* Gets the alpha coverage values for the current tile.
301
* Either this method, or the nextTile() method should be called
302
* once per tile, but not both.
303
*/
304
private void getAlphaRLE(final byte[] tile, final int offset,
305
final int rowstride)
306
{
307
if (DO_MONITORS) {
308
rdrStats.mon_ptg_getAlpha.start();
309
}
310
311
// Decode run-length encoded alpha mask data
312
// The data for row j begins at cache.rowOffsetsRLE[j]
313
// and is encoded as a set of 2-byte pairs (val, runLen)
314
// terminated by a (0, 0) pair.
315
316
// local vars for performance:
317
final MarlinCache _cache = this.cache;
318
final long[] rowAAChunkIndex = _cache.rowAAChunkIndex;
319
final int[] rowAAx0 = _cache.rowAAx0;
320
final int[] rowAAx1 = _cache.rowAAx1;
321
final int[] rowAAEnc = _cache.rowAAEnc;
322
final long[] rowAALen = _cache.rowAALen;
323
final long[] rowAAPos = _cache.rowAAPos;
324
325
final int x0 = this.x;
326
final int x1 = FloatMath.min(x0 + TILE_W, _cache.bboxX1);
327
final int w = x1 - x0;
328
329
// note: process tile line [0 - 32[
330
final int y0 = 0;
331
final int y1 = FloatMath.min(this.y + TILE_H, _cache.bboxY1) - this.y;
332
333
if (DO_LOG_BOUNDS) {
334
MarlinUtils.logInfo("getAlpha = [" + x0 + " ... " + x1
335
+ "[ [" + y0 + " ... " + y1 + "[");
336
}
337
338
// avoid too small area: fill is not faster !
339
final int clearTile;
340
final byte refVal;
341
final int area;
342
343
if ((w >= FILL_TILE_W) && (area = w * y1) > 64) { // 64 / 4 ie 16 words min (faster)
344
final int alphaSum = cache.alphaSumInTile(x0);
345
346
if (alphaSum < area * TH_AA_ALPHA_FILL_EMPTY) {
347
clearTile = 1;
348
refVal = 0;
349
} else if (alphaSum > area * TH_AA_ALPHA_FILL_FULL) {
350
clearTile = 2;
351
refVal = (byte)0xff;
352
} else {
353
clearTile = 0;
354
refVal = 0;
355
}
356
} else {
357
clearTile = 0;
358
refVal = 0;
359
}
360
361
final Unsafe _unsafe = OffHeapArray.UNSAFE;
362
final long SIZE_BYTE = 1L;
363
final long SIZE_INT = 4L;
364
final long addr_rowAA = _cache.rowAAChunk.address;
365
long addr, addr_row, last_addr, addr_end;
366
367
final int skipRowPixels = (rowstride - w);
368
369
int cx, cy, cx1;
370
int rx0, rx1, runLen, end;
371
int packed;
372
byte val;
373
int idx = offset;
374
375
switch (clearTile) {
376
case 1: // 0x00
377
// Clear full tile rows:
378
Arrays.fill(tile, offset, offset + (y1 * rowstride), refVal);
379
380
for (cy = y0; cy < y1; cy++) {
381
// empty line (default)
382
cx = x0;
383
384
if (rowAAEnc[cy] == 0) {
385
// Raw encoding:
386
387
final int aax1 = rowAAx1[cy]; // exclusive
388
389
// quick check if there is AA data
390
// corresponding to this tile [x0; x1[
391
if (aax1 > x0) {
392
final int aax0 = rowAAx0[cy]; // inclusive
393
394
if (aax0 < x1) {
395
// note: cx is the cursor pointer in the tile array
396
// (left to right)
397
cx = aax0;
398
399
// ensure cx >= x0
400
if (cx <= x0) {
401
cx = x0;
402
} else {
403
// skip line start until first AA pixel rowAA exclusive:
404
idx += (cx - x0); // > 0
405
}
406
407
// now: cx >= x0 and cx >= aax0
408
409
// Copy AA data (sum alpha data):
410
addr = addr_rowAA + rowAAChunkIndex[cy] + (cx - aax0);
411
412
for (end = (aax1 <= x1) ? aax1 : x1; cx < end; cx++) {
413
tile[idx++] = _unsafe.getByte(addr); // [0-255]
414
addr += SIZE_BYTE;
415
}
416
}
417
}
418
} else {
419
// RLE encoding:
420
421
// quick check if there is AA data
422
// corresponding to this tile [x0; x1[
423
if (rowAAx1[cy] > x0) { // last pixel exclusive
424
425
cx = rowAAx0[cy]; // inclusive
426
if (cx > x1) {
427
cx = x1;
428
}
429
430
// skip line start until first AA pixel rowAA exclusive:
431
if (cx > x0) {
432
idx += (cx - x0); // > 0
433
}
434
435
// get row address:
436
addr_row = addr_rowAA + rowAAChunkIndex[cy];
437
// get row end address:
438
addr_end = addr_row + rowAALen[cy]; // coded length
439
440
// reuse previous iteration position:
441
addr = addr_row + rowAAPos[cy];
442
443
last_addr = 0L;
444
445
while ((cx < x1) && (addr < addr_end)) {
446
// keep current position:
447
last_addr = addr;
448
449
// packed value:
450
packed = _unsafe.getInt(addr);
451
452
// last exclusive pixel x-coordinate:
453
cx1 = (packed >> 8);
454
// as bytes:
455
addr += SIZE_INT;
456
457
rx0 = cx;
458
if (rx0 < x0) {
459
rx0 = x0;
460
}
461
rx1 = cx = cx1;
462
if (rx1 > x1) {
463
rx1 = x1;
464
cx = x1; // fix last x
465
}
466
// adjust runLen:
467
runLen = rx1 - rx0;
468
469
// ensure rx1 > rx0:
470
if (runLen > 0) {
471
packed &= 0xFF; // [0-255]
472
473
if (packed == 0)
474
{
475
idx += runLen;
476
continue;
477
}
478
val = (byte) packed; // [0-255]
479
do {
480
tile[idx++] = val;
481
} while (--runLen > 0);
482
}
483
}
484
485
// Update last position in RLE entries:
486
if (last_addr != 0L) {
487
// Fix x0:
488
rowAAx0[cy] = cx; // inclusive
489
// Fix position:
490
rowAAPos[cy] = (last_addr - addr_row);
491
}
492
}
493
}
494
495
// skip line end
496
if (cx < x1) {
497
idx += (x1 - cx); // > 0
498
}
499
500
if (DO_TRACE) {
501
for (int i = idx - (x1 - x0); i < idx; i++) {
502
System.out.print(hex(tile[i], 2));
503
}
504
System.out.println();
505
}
506
507
idx += skipRowPixels;
508
}
509
break;
510
511
case 0:
512
default:
513
for (cy = y0; cy < y1; cy++) {
514
// empty line (default)
515
cx = x0;
516
517
if (rowAAEnc[cy] == 0) {
518
// Raw encoding:
519
520
final int aax1 = rowAAx1[cy]; // exclusive
521
522
// quick check if there is AA data
523
// corresponding to this tile [x0; x1[
524
if (aax1 > x0) {
525
final int aax0 = rowAAx0[cy]; // inclusive
526
527
if (aax0 < x1) {
528
// note: cx is the cursor pointer in the tile array
529
// (left to right)
530
cx = aax0;
531
532
// ensure cx >= x0
533
if (cx <= x0) {
534
cx = x0;
535
} else {
536
for (end = x0; end < cx; end++) {
537
tile[idx++] = 0;
538
}
539
}
540
541
// now: cx >= x0 and cx >= aax0
542
543
// Copy AA data (sum alpha data):
544
addr = addr_rowAA + rowAAChunkIndex[cy] + (cx - aax0);
545
546
for (end = (aax1 <= x1) ? aax1 : x1; cx < end; cx++) {
547
tile[idx++] = _unsafe.getByte(addr); // [0-255]
548
addr += SIZE_BYTE;
549
}
550
}
551
}
552
} else {
553
// RLE encoding:
554
555
// quick check if there is AA data
556
// corresponding to this tile [x0; x1[
557
if (rowAAx1[cy] > x0) { // last pixel exclusive
558
559
cx = rowAAx0[cy]; // inclusive
560
if (cx > x1) {
561
cx = x1;
562
}
563
564
// fill line start until first AA pixel rowAA exclusive:
565
for (end = x0; end < cx; end++) {
566
tile[idx++] = 0;
567
}
568
569
// get row address:
570
addr_row = addr_rowAA + rowAAChunkIndex[cy];
571
// get row end address:
572
addr_end = addr_row + rowAALen[cy]; // coded length
573
574
// reuse previous iteration position:
575
addr = addr_row + rowAAPos[cy];
576
577
last_addr = 0L;
578
579
while ((cx < x1) && (addr < addr_end)) {
580
// keep current position:
581
last_addr = addr;
582
583
// packed value:
584
packed = _unsafe.getInt(addr);
585
586
// last exclusive pixel x-coordinate:
587
cx1 = (packed >> 8);
588
// as bytes:
589
addr += SIZE_INT;
590
591
rx0 = cx;
592
if (rx0 < x0) {
593
rx0 = x0;
594
}
595
rx1 = cx = cx1;
596
if (rx1 > x1) {
597
rx1 = x1;
598
cx = x1; // fix last x
599
}
600
// adjust runLen:
601
runLen = rx1 - rx0;
602
603
// ensure rx1 > rx0:
604
if (runLen > 0) {
605
packed &= 0xFF; // [0-255]
606
607
val = (byte) packed; // [0-255]
608
do {
609
tile[idx++] = val;
610
} while (--runLen > 0);
611
}
612
}
613
614
// Update last position in RLE entries:
615
if (last_addr != 0L) {
616
// Fix x0:
617
rowAAx0[cy] = cx; // inclusive
618
// Fix position:
619
rowAAPos[cy] = (last_addr - addr_row);
620
}
621
}
622
}
623
624
// fill line end
625
while (cx < x1) {
626
tile[idx++] = 0;
627
cx++;
628
}
629
630
if (DO_TRACE) {
631
for (int i = idx - (x1 - x0); i < idx; i++) {
632
System.out.print(hex(tile[i], 2));
633
}
634
System.out.println();
635
}
636
637
idx += skipRowPixels;
638
}
639
break;
640
641
case 2: // 0xFF
642
// Fill full tile rows:
643
Arrays.fill(tile, offset, offset + (y1 * rowstride), refVal);
644
645
for (cy = y0; cy < y1; cy++) {
646
// empty line (default)
647
cx = x0;
648
649
if (rowAAEnc[cy] == 0) {
650
// Raw encoding:
651
652
final int aax1 = rowAAx1[cy]; // exclusive
653
654
// quick check if there is AA data
655
// corresponding to this tile [x0; x1[
656
if (aax1 > x0) {
657
final int aax0 = rowAAx0[cy]; // inclusive
658
659
if (aax0 < x1) {
660
// note: cx is the cursor pointer in the tile array
661
// (left to right)
662
cx = aax0;
663
664
// ensure cx >= x0
665
if (cx <= x0) {
666
cx = x0;
667
} else {
668
// fill line start until first AA pixel rowAA exclusive:
669
for (end = x0; end < cx; end++) {
670
tile[idx++] = 0;
671
}
672
}
673
674
// now: cx >= x0 and cx >= aax0
675
676
// Copy AA data (sum alpha data):
677
addr = addr_rowAA + rowAAChunkIndex[cy] + (cx - aax0);
678
679
for (end = (aax1 <= x1) ? aax1 : x1; cx < end; cx++) {
680
tile[idx++] = _unsafe.getByte(addr); // [0-255]
681
addr += SIZE_BYTE;
682
}
683
}
684
}
685
} else {
686
// RLE encoding:
687
688
// quick check if there is AA data
689
// corresponding to this tile [x0; x1[
690
if (rowAAx1[cy] > x0) { // last pixel exclusive
691
692
cx = rowAAx0[cy]; // inclusive
693
if (cx > x1) {
694
cx = x1;
695
}
696
697
// fill line start until first AA pixel rowAA exclusive:
698
for (end = x0; end < cx; end++) {
699
tile[idx++] = 0;
700
}
701
702
// get row address:
703
addr_row = addr_rowAA + rowAAChunkIndex[cy];
704
// get row end address:
705
addr_end = addr_row + rowAALen[cy]; // coded length
706
707
// reuse previous iteration position:
708
addr = addr_row + rowAAPos[cy];
709
710
last_addr = 0L;
711
712
while ((cx < x1) && (addr < addr_end)) {
713
// keep current position:
714
last_addr = addr;
715
716
// packed value:
717
packed = _unsafe.getInt(addr);
718
719
// last exclusive pixel x-coordinate:
720
cx1 = (packed >> 8);
721
// as bytes:
722
addr += SIZE_INT;
723
724
rx0 = cx;
725
if (rx0 < x0) {
726
rx0 = x0;
727
}
728
rx1 = cx = cx1;
729
if (rx1 > x1) {
730
rx1 = x1;
731
cx = x1; // fix last x
732
}
733
// adjust runLen:
734
runLen = rx1 - rx0;
735
736
// ensure rx1 > rx0:
737
if (runLen > 0) {
738
packed &= 0xFF; // [0-255]
739
740
if (packed == 0xFF)
741
{
742
idx += runLen;
743
continue;
744
}
745
val = (byte) packed; // [0-255]
746
do {
747
tile[idx++] = val;
748
} while (--runLen > 0);
749
}
750
}
751
752
// Update last position in RLE entries:
753
if (last_addr != 0L) {
754
// Fix x0:
755
rowAAx0[cy] = cx; // inclusive
756
// Fix position:
757
rowAAPos[cy] = (last_addr - addr_row);
758
}
759
}
760
}
761
762
// fill line end
763
while (cx < x1) {
764
tile[idx++] = 0;
765
cx++;
766
}
767
768
if (DO_TRACE) {
769
for (int i = idx - (x1 - x0); i < idx; i++) {
770
System.out.print(hex(tile[i], 2));
771
}
772
System.out.println();
773
}
774
775
idx += skipRowPixels;
776
}
777
}
778
779
nextTile();
780
781
if (DO_MONITORS) {
782
rdrStats.mon_ptg_getAlpha.stop();
783
}
784
}
785
786
static String hex(int v, int d) {
787
String s = Integer.toHexString(v);
788
while (s.length() < d) {
789
s = "0" + s;
790
}
791
return s.substring(0, d);
792
}
793
}
794
795