Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java
41153 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 6766342
27
* @summary Tests clipping invariance for AA rectangle and line primitives
28
* @run main RenderClipTest -strict -readfile 6766342.tests
29
* @run main RenderClipTest -rectsuite -count 10
30
*/
31
32
import java.awt.*;
33
import java.awt.geom.*;
34
import java.awt.image.*;
35
import java.awt.event.*;
36
import java.util.Vector;
37
import java.io.*;
38
39
public class RenderClipTest {
40
public static double randDblCoord() {
41
return Math.random()*60 - 10;
42
}
43
44
public static float randFltCoord() {
45
return (float) randDblCoord();
46
}
47
48
public static int randIntCoord() {
49
return (int) Math.round(randDblCoord());
50
}
51
52
public static int randInt(int n) {
53
return ((int) (Math.random() * (n*4))) >> 2;
54
}
55
56
static int numtests;
57
static int numerrors;
58
static int numfillfailures;
59
static int numstrokefailures;
60
static int maxerr;
61
62
static boolean useAA;
63
static boolean strokePure;
64
static boolean testFill;
65
static boolean testDraw;
66
static boolean silent;
67
static boolean verbose;
68
static boolean strict;
69
static boolean showErrors;
70
static float lw;
71
static double rot;
72
73
static BufferedImage imgref;
74
static BufferedImage imgtst;
75
76
static Graphics2D grefclear;
77
static Graphics2D gtstclear;
78
static Graphics2D grefrender;
79
static Graphics2D gtstrender;
80
81
public static abstract class AnnotatedRenderOp {
82
public static AnnotatedRenderOp parse(String str) {
83
AnnotatedRenderOp ar;
84
if (((ar = Cubic.tryparse(str)) != null) ||
85
((ar = Quad.tryparse(str)) != null) ||
86
((ar = Poly.tryparse(str)) != null) ||
87
((ar = Path.tryparse(str)) != null) ||
88
((ar = Rect.tryparse(str)) != null) ||
89
((ar = Line.tryparse(str)) != null) ||
90
((ar = RectMethod.tryparse(str)) != null) ||
91
((ar = LineMethod.tryparse(str)) != null))
92
{
93
return ar;
94
}
95
System.err.println("Unable to parse shape: "+str);
96
return null;
97
}
98
99
public abstract void randomize();
100
101
public abstract void fill(Graphics2D g2d);
102
103
public abstract void draw(Graphics2D g2d);
104
}
105
106
public static abstract class AnnotatedShapeOp extends AnnotatedRenderOp {
107
public abstract Shape getShape();
108
109
public void fill(Graphics2D g2d) {
110
g2d.fill(getShape());
111
}
112
113
public void draw(Graphics2D g2d) {
114
g2d.draw(getShape());
115
}
116
}
117
118
public static void usage(String err) {
119
if (err != null) {
120
System.err.println(err);
121
}
122
System.err.println("usage: java RenderClipTest "+
123
"[-read[file F]] [-rectsuite] [-fill] [-draw]");
124
System.err.println(" "+
125
"[-aa] [-pure] [-lw N] [-rot N]");
126
System.err.println(" "+
127
"[-rectmethod] [-linemethod] [-rect] [-line]");
128
System.err.println(" "+
129
"[-cubic] [-quad] [-poly] [-path]");
130
System.err.println(" "+
131
"[-silent] [-verbose] [-showerr] [-count N]");
132
System.err.println(" "+
133
"[-strict] [-usage]");
134
System.err.println(" -read Read test data from stdin");
135
System.err.println(" -readfile F Read test data from file F");
136
System.err.println(" -rectsuite Run a suite of rect/line tests");
137
System.err.println(" -fill Test g.fill*(...)");
138
System.err.println(" -draw Test g.draw*(...)");
139
System.err.println(" -aa Use antialiased rendering");
140
System.err.println(" -pure Use STROKE_PURE hint");
141
System.err.println(" -lw N Test line widths of N "+
142
"(default 1.0)");
143
System.err.println(" -rot N Test rotation by N degrees "+
144
"(default 0.0)");
145
System.err.println(" -rectmethod Test fillRect/drawRect methods");
146
System.err.println(" -linemethod Test drawLine method");
147
System.err.println(" -rect Test Rectangle2D shapes");
148
System.err.println(" -line Test Line2D shapes");
149
System.err.println(" -cubic Test CubicCurve2D shapes");
150
System.err.println(" -quad Test QuadCurve2D shapes");
151
System.err.println(" -poly Test Polygon shapes");
152
System.err.println(" -path Test GeneralPath shapes");
153
System.err.println(" -silent Do not print out error curves");
154
System.err.println(" -verbose Print out progress info");
155
System.err.println(" -showerr Display errors on screen");
156
System.err.println(" -count N N tests per shape, then exit "+
157
"(default 1000)");
158
System.err.println(" -strict All failures are important");
159
System.err.println(" -usage Print this help, then exit");
160
System.exit((err != null) ? -1 : 0);
161
}
162
163
public static void main(String argv[]) {
164
boolean readTests = false;
165
String readFile = null;
166
boolean rectsuite = false;
167
int count = 1000;
168
lw = 1.0f;
169
rot = 0.0;
170
Vector<AnnotatedRenderOp> testOps = new Vector<AnnotatedRenderOp>();
171
for (int i = 0; i < argv.length; i++) {
172
String arg = argv[i].toLowerCase();
173
if (arg.equals("-aa")) {
174
useAA = true;
175
} else if (arg.equals("-pure")) {
176
strokePure = true;
177
} else if (arg.equals("-fill")) {
178
testFill = true;
179
} else if (arg.equals("-draw")) {
180
testDraw = true;
181
} else if (arg.equals("-lw")) {
182
if (i+1 >= argv.length) {
183
usage("Missing argument: "+argv[i]);
184
}
185
lw = Float.parseFloat(argv[++i]);
186
} else if (arg.equals("-rot")) {
187
if (i+1 >= argv.length) {
188
usage("Missing argument: "+argv[i]);
189
}
190
rot = Double.parseDouble(argv[++i]);
191
} else if (arg.equals("-cubic")) {
192
testOps.add(new Cubic());
193
} else if (arg.equals("-quad")) {
194
testOps.add(new Quad());
195
} else if (arg.equals("-poly")) {
196
testOps.add(new Poly());
197
} else if (arg.equals("-path")) {
198
testOps.add(new Path());
199
} else if (arg.equals("-rect")) {
200
testOps.add(new Rect());
201
} else if (arg.equals("-line")) {
202
testOps.add(new Line());
203
} else if (arg.equals("-rectmethod")) {
204
testOps.add(new RectMethod());
205
} else if (arg.equals("-linemethod")) {
206
testOps.add(new LineMethod());
207
} else if (arg.equals("-verbose")) {
208
verbose = true;
209
} else if (arg.equals("-strict")) {
210
strict = true;
211
} else if (arg.equals("-silent")) {
212
silent = true;
213
} else if (arg.equals("-showerr")) {
214
showErrors = true;
215
} else if (arg.equals("-readfile")) {
216
if (i+1 >= argv.length) {
217
usage("Missing argument: "+argv[i]);
218
}
219
readTests = true;
220
readFile = argv[++i];
221
} else if (arg.equals("-read")) {
222
readTests = true;
223
readFile = null;
224
} else if (arg.equals("-rectsuite")) {
225
rectsuite = true;
226
} else if (arg.equals("-count")) {
227
if (i+1 >= argv.length) {
228
usage("Missing argument: "+argv[i]);
229
}
230
count = Integer.parseInt(argv[++i]);
231
} else if (arg.equals("-usage")) {
232
usage(null);
233
} else {
234
usage("Unknown argument: "+argv[i]);
235
}
236
}
237
if (readTests) {
238
if (rectsuite || testDraw || testFill ||
239
useAA || strokePure ||
240
lw != 1.0f || rot != 0.0 ||
241
testOps.size() > 0)
242
{
243
usage("Should not specify test types with -read options");
244
}
245
} else if (rectsuite) {
246
if (testDraw || testFill ||
247
useAA || strokePure ||
248
lw != 1.0f || rot != 0.0 ||
249
testOps.size() > 0)
250
{
251
usage("Should not specify test types with -rectsuite option");
252
}
253
} else {
254
if (!testDraw && !testFill) {
255
usage("No work: Must specify one or both of "+
256
"-fill or -draw");
257
}
258
if (testOps.size() == 0) {
259
usage("No work: Must specify one or more of "+
260
"-rect[method], -line[method], "+
261
"-cubic, -quad, -poly, or -path");
262
}
263
}
264
initImages();
265
if (readTests) {
266
try {
267
InputStream is;
268
if (readFile == null) {
269
is = System.in;
270
} else {
271
File f =
272
new File(System.getProperty("test.src", "."),
273
readFile);
274
is = new FileInputStream(f);
275
}
276
parseAndRun(is);
277
} catch (IOException e) {
278
throw new RuntimeException(e);
279
}
280
} else if (rectsuite) {
281
runRectSuite(count);
282
} else {
283
initGCs();
284
for (int k = 0; k < testOps.size(); k++) {
285
AnnotatedRenderOp ar = testOps.get(k);
286
runRandomTests(ar, count);
287
}
288
disposeGCs();
289
}
290
grefclear.dispose();
291
gtstclear.dispose();
292
grefclear = gtstclear = null;
293
reportStatistics();
294
}
295
296
public static int reportStatistics() {
297
String connector = "";
298
if (numfillfailures > 0) {
299
System.out.print(numfillfailures+" fills ");
300
connector = "and ";
301
}
302
if (numstrokefailures > 0) {
303
System.out.print(connector+numstrokefailures+" strokes ");
304
}
305
int totalfailures = numfillfailures + numstrokefailures;
306
if (totalfailures == 0) {
307
System.out.print("0 ");
308
}
309
System.out.println("out of "+numtests+" tests failed...");
310
int critical = numerrors;
311
if (strict) {
312
critical += totalfailures;
313
}
314
if (critical > 0) {
315
throw new RuntimeException(critical+" tests had critical errors");
316
}
317
System.out.println("No tests had critical errors");
318
return (numerrors+totalfailures);
319
}
320
321
public static void runRectSuite(int count) {
322
AnnotatedRenderOp ops[] = {
323
new Rect(),
324
new RectMethod(),
325
new Line(),
326
new LineMethod(),
327
};
328
// Sometimes different fill algorithms are chosen for
329
// thin and wide line modes, make sure we test both...
330
float filllinewidths[] = { 0.0f, 2.0f };
331
float drawlinewidths[] = { 0.0f, 0.5f, 1.0f,
332
2.0f, 2.5f,
333
5.0f, 5.3f };
334
double rotations[] = { 0.0, 15.0, 90.0,
335
135.0, 180.0,
336
200.0, 270.0,
337
300.0};
338
for (AnnotatedRenderOp ar: ops) {
339
for (double r: rotations) {
340
rot = r;
341
for (int i = 0; i < 8; i++) {
342
float linewidths[];
343
if ((i & 1) == 0) {
344
if ((ar instanceof Line) ||
345
(ar instanceof LineMethod))
346
{
347
continue;
348
}
349
testFill = true;
350
testDraw = false;
351
linewidths = filllinewidths;
352
} else {
353
testFill = false;
354
testDraw = true;
355
linewidths = drawlinewidths;
356
}
357
useAA = ((i & 2) != 0);
358
strokePure = ((i & 4) != 0);
359
for (float w : linewidths) {
360
lw = w;
361
runSuiteTests(ar, count);
362
}
363
}
364
}
365
}
366
}
367
368
public static void runSuiteTests(AnnotatedRenderOp ar, int count) {
369
if (verbose) {
370
System.out.print("Running ");
371
System.out.print(testFill ? "Fill " : "Draw ");
372
System.out.print(BaseName(ar));
373
if (useAA) {
374
System.out.print(" AA");
375
}
376
if (strokePure) {
377
System.out.print(" Pure");
378
}
379
if (lw != 1.0f) {
380
System.out.print(" lw="+lw);
381
}
382
if (rot != 0.0f) {
383
System.out.print(" rot="+rot);
384
}
385
System.out.println();
386
}
387
initGCs();
388
runRandomTests(ar, count);
389
disposeGCs();
390
}
391
392
public static String BaseName(AnnotatedRenderOp ar) {
393
String s = ar.toString();
394
int leftparen = s.indexOf('(');
395
if (leftparen >= 0) {
396
s = s.substring(0, leftparen);
397
}
398
return s;
399
}
400
401
public static void runRandomTests(AnnotatedRenderOp ar, int count) {
402
for (int i = 0; i < count; i++) {
403
ar.randomize();
404
if (testDraw) {
405
test(ar, false);
406
}
407
if (testFill) {
408
test(ar, true);
409
}
410
}
411
}
412
413
public static void initImages() {
414
imgref = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
415
imgtst = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
416
grefclear = imgref.createGraphics();
417
gtstclear = imgtst.createGraphics();
418
grefclear.setColor(Color.white);
419
gtstclear.setColor(Color.white);
420
}
421
422
public static void initGCs() {
423
grefrender = imgref.createGraphics();
424
gtstrender = imgtst.createGraphics();
425
gtstrender.clipRect(10, 10, 20, 20);
426
grefrender.setColor(Color.blue);
427
gtstrender.setColor(Color.blue);
428
if (lw != 1.0f) {
429
BasicStroke bs = new BasicStroke(lw);
430
grefrender.setStroke(bs);
431
gtstrender.setStroke(bs);
432
}
433
if (rot != 0.0) {
434
double rotrad = Math.toRadians(rot);
435
grefrender.rotate(rotrad, 20, 20);
436
gtstrender.rotate(rotrad, 20, 20);
437
}
438
if (strokePure) {
439
grefrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
440
RenderingHints.VALUE_STROKE_PURE);
441
gtstrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
442
RenderingHints.VALUE_STROKE_PURE);
443
}
444
if (useAA) {
445
grefrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
446
RenderingHints.VALUE_ANTIALIAS_ON);
447
gtstrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
448
RenderingHints.VALUE_ANTIALIAS_ON);
449
maxerr = 1;
450
}
451
}
452
453
public static void disposeGCs() {
454
grefrender.dispose();
455
gtstrender.dispose();
456
grefrender = gtstrender = null;
457
}
458
459
public static void parseAndRun(InputStream in) throws IOException {
460
BufferedReader br = new BufferedReader(new InputStreamReader(in));
461
String str;
462
while ((str = br.readLine()) != null) {
463
if (str.startsWith("Stroked ") || str.startsWith("Filled ")) {
464
parseTest(str);
465
continue;
466
}
467
if (str.startsWith("Running ")) {
468
continue;
469
}
470
if (str.startsWith("Failed: ")) {
471
continue;
472
}
473
if (str.indexOf(" out of ") > 0 &&
474
str.indexOf(" tests failed...") > 0)
475
{
476
continue;
477
}
478
if (str.indexOf(" tests had critical errors") > 0) {
479
continue;
480
}
481
System.err.println("Unparseable line: "+str);
482
}
483
}
484
485
public static void parseTest(String origstr) {
486
String str = origstr;
487
boolean isfill = false;
488
useAA = strokePure = false;
489
lw = 1.0f;
490
rot = 0.0;
491
if (str.startsWith("Stroked ")) {
492
str = str.substring(8);
493
isfill = false;
494
} else if (str.startsWith("Filled ")) {
495
str = str.substring(7);
496
isfill = true;
497
} else {
498
System.err.println("Unparseable test line: "+origstr);
499
}
500
if (str.startsWith("AA ")) {
501
str = str.substring(3);
502
useAA = true;
503
}
504
if (str.startsWith("Pure ")) {
505
str = str.substring(5);
506
strokePure = true;
507
}
508
if (str.startsWith("Lw=")) {
509
int index = str.indexOf(' ', 3);
510
if (index > 0) {
511
lw = Float.parseFloat(str.substring(3, index));
512
str = str.substring(index+1);
513
}
514
}
515
if (str.startsWith("Rot=")) {
516
int index = str.indexOf(' ', 4);
517
if (index > 0) {
518
rot = Double.parseDouble(str.substring(4, index));
519
str = str.substring(index+1);
520
}
521
}
522
AnnotatedRenderOp ar = AnnotatedRenderOp.parse(str);
523
if (ar != null) {
524
initGCs();
525
test(ar, isfill);
526
disposeGCs();
527
} else {
528
System.err.println("Unparseable test line: "+origstr);
529
}
530
}
531
532
public static void test(AnnotatedRenderOp ar, boolean isfill) {
533
grefclear.fillRect(0, 0, 40, 40);
534
gtstclear.fillRect(0, 0, 40, 40);
535
if (isfill) {
536
ar.fill(grefrender);
537
ar.fill(gtstrender);
538
} else {
539
ar.draw(grefrender);
540
ar.draw(gtstrender);
541
}
542
check(imgref, imgtst, ar, isfill);
543
}
544
545
public static int[] getData(BufferedImage img) {
546
Raster r = img.getRaster();
547
DataBufferInt dbi = (DataBufferInt) r.getDataBuffer();
548
return dbi.getData();
549
}
550
551
public static int getScan(BufferedImage img) {
552
Raster r = img.getRaster();
553
SinglePixelPackedSampleModel sppsm =
554
(SinglePixelPackedSampleModel) r.getSampleModel();
555
return sppsm.getScanlineStride();
556
}
557
558
public static int getOffset(BufferedImage img) {
559
Raster r = img.getRaster();
560
SinglePixelPackedSampleModel sppsm =
561
(SinglePixelPackedSampleModel) r.getSampleModel();
562
return sppsm.getOffset(-r.getSampleModelTranslateX(),
563
-r.getSampleModelTranslateY());
564
}
565
566
final static int opaque = 0xff000000;
567
final static int whitergb = Color.white.getRGB();
568
569
public static final int maxdiff(int rgb1, int rgb2) {
570
int maxd = 0;
571
for (int i = 0; i < 32; i += 8) {
572
int c1 = (rgb1 >> i) & 0xff;
573
int c2 = (rgb2 >> i) & 0xff;
574
int d = Math.abs(c1-c2);
575
if (maxd < d) {
576
maxd = d;
577
}
578
}
579
return maxd;
580
}
581
582
public static void check(BufferedImage imgref, BufferedImage imgtst,
583
AnnotatedRenderOp ar, boolean wasfill)
584
{
585
numtests++;
586
int dataref[] = getData(imgref);
587
int datatst[] = getData(imgtst);
588
int scanref = getScan(imgref);
589
int scantst = getScan(imgtst);
590
int offref = getOffset(imgref);
591
int offtst = getOffset(imgtst);
592
593
// We want to check for errors outside the clip at a higher
594
// priority than errors involving different pixels touched
595
// inside the clip.
596
597
// Check above clip
598
if (check(ar, wasfill,
599
null, 0, 0,
600
datatst, scantst, offtst,
601
0, 0, 40, 10))
602
{
603
return;
604
}
605
// Check below clip
606
if (check(ar, wasfill,
607
null, 0, 0,
608
datatst, scantst, offtst,
609
0, 30, 40, 40))
610
{
611
return;
612
}
613
// Check left of clip
614
if (check(ar, wasfill,
615
null, 0, 0,
616
datatst, scantst, offtst,
617
0, 10, 10, 30))
618
{
619
return;
620
}
621
// Check right of clip
622
if (check(ar, wasfill,
623
null, 0, 0,
624
datatst, scantst, offtst,
625
30, 10, 40, 30))
626
{
627
return;
628
}
629
// Check inside clip
630
check(ar, wasfill,
631
dataref, scanref, offref,
632
datatst, scantst, offtst,
633
10, 10, 30, 30);
634
}
635
636
public static boolean check(AnnotatedRenderOp ar, boolean wasfill,
637
int dataref[], int scanref, int offref,
638
int datatst[], int scantst, int offtst,
639
int x0, int y0, int x1, int y1)
640
{
641
offref += scanref * y0;
642
offtst += scantst * y0;
643
for (int y = y0; y < y1; y++) {
644
for (int x = x0; x < x1; x++) {
645
boolean failed;
646
String reason;
647
int rgbref;
648
int rgbtst;
649
650
rgbtst = datatst[offtst+x] | opaque;
651
if (dataref == null) {
652
/* Outside of clip, must be white, no error tolerance */
653
rgbref = whitergb;
654
failed = (rgbtst != rgbref);
655
reason = "stray pixel rendered outside of clip";
656
} else {
657
/* Inside of clip, check for maxerr delta in components */
658
rgbref = dataref[offref+x] | opaque;
659
failed = (rgbref != rgbtst &&
660
maxdiff(rgbref, rgbtst) > maxerr);
661
reason = "different pixel rendered inside clip";
662
}
663
if (failed) {
664
if (dataref == null) {
665
numerrors++;
666
}
667
if (wasfill) {
668
numfillfailures++;
669
} else {
670
numstrokefailures++;
671
}
672
if (!silent) {
673
System.out.println("Failed: "+reason+" at "+x+", "+y+
674
" ["+Integer.toHexString(rgbref)+
675
" != "+Integer.toHexString(rgbtst)+
676
"]");
677
System.out.print(wasfill ? "Filled " : "Stroked ");
678
if (useAA) System.out.print("AA ");
679
if (strokePure) System.out.print("Pure ");
680
if (lw != 1) System.out.print("Lw="+lw+" ");
681
if (rot != 0) System.out.print("Rot="+rot+" ");
682
System.out.println(ar);
683
}
684
if (showErrors) {
685
show(imgref, imgtst);
686
}
687
return true;
688
}
689
}
690
offref += scanref;
691
offtst += scantst;
692
}
693
return false;
694
}
695
696
static ErrorWindow errw;
697
698
public static void show(BufferedImage imgref, BufferedImage imgtst) {
699
ErrorWindow errw = new ErrorWindow();
700
errw.setImages(imgref, imgtst);
701
errw.setVisible(true);
702
errw.waitForHide();
703
errw.dispose();
704
}
705
706
public static class Cubic extends AnnotatedShapeOp {
707
public static Cubic tryparse(String str) {
708
str = str.trim();
709
if (!str.startsWith("Cubic(")) {
710
return null;
711
}
712
str = str.substring(6);
713
double coords[] = new double[8];
714
boolean foundparen = false;
715
for (int i = 0; i < coords.length; i++) {
716
int index = str.indexOf(",");
717
if (index < 0) {
718
if (i < coords.length-1) {
719
return null;
720
}
721
index = str.indexOf(")");
722
if (index < 0) {
723
return null;
724
}
725
foundparen = true;
726
}
727
String num = str.substring(0, index);
728
try {
729
coords[i] = Double.parseDouble(num);
730
} catch (NumberFormatException nfe) {
731
return null;
732
}
733
str = str.substring(index+1);
734
}
735
if (!foundparen || str.length() > 0) {
736
return null;
737
}
738
Cubic c = new Cubic();
739
c.cubic.setCurve(coords[0], coords[1],
740
coords[2], coords[3],
741
coords[4], coords[5],
742
coords[6], coords[7]);
743
return c;
744
}
745
746
private CubicCurve2D cubic = new CubicCurve2D.Double();
747
748
public void randomize() {
749
cubic.setCurve(randDblCoord(), randDblCoord(),
750
randDblCoord(), randDblCoord(),
751
randDblCoord(), randDblCoord(),
752
randDblCoord(), randDblCoord());
753
}
754
755
public Shape getShape() {
756
return cubic;
757
}
758
759
public String toString() {
760
return ("Cubic("+
761
cubic.getX1()+", "+
762
cubic.getY1()+", "+
763
cubic.getCtrlX1()+", "+
764
cubic.getCtrlY1()+", "+
765
cubic.getCtrlX2()+", "+
766
cubic.getCtrlY2()+", "+
767
cubic.getX2()+", "+
768
cubic.getY2()
769
+")");
770
}
771
}
772
773
public static class Quad extends AnnotatedShapeOp {
774
public static Quad tryparse(String str) {
775
str = str.trim();
776
if (!str.startsWith("Quad(")) {
777
return null;
778
}
779
str = str.substring(5);
780
double coords[] = new double[6];
781
boolean foundparen = false;
782
for (int i = 0; i < coords.length; i++) {
783
int index = str.indexOf(",");
784
if (index < 0) {
785
if (i < coords.length-1) {
786
return null;
787
}
788
index = str.indexOf(")");
789
if (index < 0) {
790
return null;
791
}
792
foundparen = true;
793
}
794
String num = str.substring(0, index);
795
try {
796
coords[i] = Double.parseDouble(num);
797
} catch (NumberFormatException nfe) {
798
return null;
799
}
800
str = str.substring(index+1);
801
}
802
if (!foundparen || str.length() > 0) {
803
return null;
804
}
805
Quad c = new Quad();
806
c.quad.setCurve(coords[0], coords[1],
807
coords[2], coords[3],
808
coords[4], coords[5]);
809
return c;
810
}
811
812
private QuadCurve2D quad = new QuadCurve2D.Double();
813
814
public void randomize() {
815
quad.setCurve(randDblCoord(), randDblCoord(),
816
randDblCoord(), randDblCoord(),
817
randDblCoord(), randDblCoord());
818
}
819
820
public Shape getShape() {
821
return quad;
822
}
823
824
public String toString() {
825
return ("Quad("+
826
quad.getX1()+", "+
827
quad.getY1()+", "+
828
quad.getCtrlX()+", "+
829
quad.getCtrlY()+", "+
830
quad.getX2()+", "+
831
quad.getY2()
832
+")");
833
}
834
}
835
836
public static class Poly extends AnnotatedShapeOp {
837
public static Poly tryparse(String str) {
838
str = str.trim();
839
if (!str.startsWith("Poly(")) {
840
return null;
841
}
842
str = str.substring(5);
843
Polygon p = new Polygon();
844
while (true) {
845
int x, y;
846
str = str.trim();
847
if (str.startsWith(")")) {
848
str = str.substring(1);
849
break;
850
}
851
if (p.npoints > 0) {
852
if (str.startsWith(",")) {
853
str = str.substring(2).trim();
854
} else {
855
return null;
856
}
857
}
858
if (str.startsWith("[")) {
859
str = str.substring(1);
860
} else {
861
return null;
862
}
863
int index = str.indexOf(",");
864
if (index < 0) {
865
return null;
866
}
867
String num = str.substring(0, index);
868
try {
869
x = Integer.parseInt(num);
870
} catch (NumberFormatException nfe) {
871
return null;
872
}
873
str = str.substring(index+1);
874
index = str.indexOf("]");
875
if (index < 0) {
876
return null;
877
}
878
num = str.substring(0, index).trim();
879
try {
880
y = Integer.parseInt(num);
881
} catch (NumberFormatException nfe) {
882
return null;
883
}
884
str = str.substring(index+1);
885
p.addPoint(x, y);
886
}
887
if (str.length() > 0) {
888
return null;
889
}
890
if (p.npoints < 3) {
891
return null;
892
}
893
return new Poly(p);
894
}
895
896
private Polygon poly;
897
898
public Poly() {
899
this.poly = new Polygon();
900
}
901
902
private Poly(Polygon p) {
903
this.poly = p;
904
}
905
906
public void randomize() {
907
poly.reset();
908
poly.addPoint(randIntCoord(), randIntCoord());
909
poly.addPoint(randIntCoord(), randIntCoord());
910
poly.addPoint(randIntCoord(), randIntCoord());
911
poly.addPoint(randIntCoord(), randIntCoord());
912
poly.addPoint(randIntCoord(), randIntCoord());
913
}
914
915
public Shape getShape() {
916
return poly;
917
}
918
919
public String toString() {
920
StringBuffer sb = new StringBuffer(100);
921
sb.append("Poly(");
922
for (int i = 0; i < poly.npoints; i++) {
923
if (i != 0) {
924
sb.append(", ");
925
}
926
sb.append("[");
927
sb.append(poly.xpoints[i]);
928
sb.append(", ");
929
sb.append(poly.ypoints[i]);
930
sb.append("]");
931
}
932
sb.append(")");
933
return sb.toString();
934
}
935
}
936
937
public static class Path extends AnnotatedShapeOp {
938
public static Path tryparse(String str) {
939
str = str.trim();
940
if (!str.startsWith("Path(")) {
941
return null;
942
}
943
str = str.substring(5);
944
GeneralPath gp = new GeneralPath();
945
float coords[] = new float[6];
946
int numsegs = 0;
947
while (true) {
948
int type;
949
int n;
950
str = str.trim();
951
if (str.startsWith(")")) {
952
str = str.substring(1);
953
break;
954
}
955
if (str.startsWith("M[")) {
956
type = PathIterator.SEG_MOVETO;
957
n = 2;
958
} else if (str.startsWith("L[")) {
959
type = PathIterator.SEG_LINETO;
960
n = 2;
961
} else if (str.startsWith("Q[")) {
962
type = PathIterator.SEG_QUADTO;
963
n = 4;
964
} else if (str.startsWith("C[")) {
965
type = PathIterator.SEG_CUBICTO;
966
n = 6;
967
} else if (str.startsWith("E[")) {
968
type = PathIterator.SEG_CLOSE;
969
n = 0;
970
} else {
971
return null;
972
}
973
str = str.substring(2);
974
if (n == 0) {
975
if (str.startsWith("]")) {
976
str = str.substring(1);
977
} else {
978
return null;
979
}
980
}
981
for (int i = 0; i < n; i++) {
982
int index;
983
if (i < n-1) {
984
index = str.indexOf(",");
985
} else {
986
index = str.indexOf("]");
987
}
988
if (index < 0) {
989
return null;
990
}
991
String num = str.substring(0, index);
992
try {
993
coords[i] = Float.parseFloat(num);
994
} catch (NumberFormatException nfe) {
995
return null;
996
}
997
str = str.substring(index+1).trim();
998
}
999
switch (type) {
1000
case PathIterator.SEG_MOVETO:
1001
gp.moveTo(coords[0], coords[1]);
1002
break;
1003
case PathIterator.SEG_LINETO:
1004
gp.lineTo(coords[0], coords[1]);
1005
break;
1006
case PathIterator.SEG_QUADTO:
1007
gp.quadTo(coords[0], coords[1],
1008
coords[2], coords[3]);
1009
break;
1010
case PathIterator.SEG_CUBICTO:
1011
gp.curveTo(coords[0], coords[1],
1012
coords[2], coords[3],
1013
coords[4], coords[5]);
1014
break;
1015
case PathIterator.SEG_CLOSE:
1016
gp.closePath();
1017
break;
1018
}
1019
numsegs++;
1020
}
1021
if (str.length() > 0) {
1022
return null;
1023
}
1024
if (numsegs < 2) {
1025
return null;
1026
}
1027
return new Path(gp);
1028
}
1029
1030
private GeneralPath path;
1031
1032
public Path() {
1033
this.path = new GeneralPath();
1034
}
1035
1036
private Path(GeneralPath gp) {
1037
this.path = gp;
1038
}
1039
1040
public void randomize() {
1041
path.reset();
1042
path.moveTo(randFltCoord(), randFltCoord());
1043
for (int i = randInt(5)+3; i > 0; --i) {
1044
switch(randInt(5)) {
1045
case 0:
1046
path.moveTo(randFltCoord(), randFltCoord());
1047
break;
1048
case 1:
1049
path.lineTo(randFltCoord(), randFltCoord());
1050
break;
1051
case 2:
1052
path.quadTo(randFltCoord(), randFltCoord(),
1053
randFltCoord(), randFltCoord());
1054
break;
1055
case 3:
1056
path.curveTo(randFltCoord(), randFltCoord(),
1057
randFltCoord(), randFltCoord(),
1058
randFltCoord(), randFltCoord());
1059
break;
1060
case 4:
1061
path.closePath();
1062
break;
1063
}
1064
}
1065
}
1066
1067
public Shape getShape() {
1068
return path;
1069
}
1070
1071
public String toString() {
1072
StringBuffer sb = new StringBuffer(100);
1073
sb.append("Path(");
1074
PathIterator pi = path.getPathIterator(null);
1075
float coords[] = new float[6];
1076
boolean first = true;
1077
while (!pi.isDone()) {
1078
int n;
1079
char c;
1080
switch(pi.currentSegment(coords)) {
1081
case PathIterator.SEG_MOVETO:
1082
c = 'M';
1083
n = 2;
1084
break;
1085
case PathIterator.SEG_LINETO:
1086
c = 'L';
1087
n = 2;
1088
break;
1089
case PathIterator.SEG_QUADTO:
1090
c = 'Q';
1091
n = 4;
1092
break;
1093
case PathIterator.SEG_CUBICTO:
1094
c = 'C';
1095
n = 6;
1096
break;
1097
case PathIterator.SEG_CLOSE:
1098
c = 'E';
1099
n = 0;
1100
break;
1101
default:
1102
throw new InternalError("Unknown segment!");
1103
}
1104
sb.append(c);
1105
sb.append("[");
1106
for (int i = 0; i < n; i++) {
1107
if (i != 0) {
1108
sb.append(",");
1109
}
1110
sb.append(coords[i]);
1111
}
1112
sb.append("]");
1113
pi.next();
1114
}
1115
sb.append(")");
1116
return sb.toString();
1117
}
1118
}
1119
1120
public static class Rect extends AnnotatedShapeOp {
1121
public static Rect tryparse(String str) {
1122
str = str.trim();
1123
if (!str.startsWith("Rect(")) {
1124
return null;
1125
}
1126
str = str.substring(5);
1127
double coords[] = new double[4];
1128
boolean foundparen = false;
1129
for (int i = 0; i < coords.length; i++) {
1130
int index = str.indexOf(",");
1131
if (index < 0) {
1132
if (i < coords.length-1) {
1133
return null;
1134
}
1135
index = str.indexOf(")");
1136
if (index < 0) {
1137
return null;
1138
}
1139
foundparen = true;
1140
}
1141
String num = str.substring(0, index);
1142
try {
1143
coords[i] = Double.parseDouble(num);
1144
} catch (NumberFormatException nfe) {
1145
return null;
1146
}
1147
str = str.substring(index+1);
1148
}
1149
if (!foundparen || str.length() > 0) {
1150
return null;
1151
}
1152
Rect r = new Rect();
1153
r.rect.setRect(coords[0], coords[1],
1154
coords[2], coords[3]);
1155
return r;
1156
}
1157
1158
private Rectangle2D rect = new Rectangle2D.Double();
1159
1160
public void randomize() {
1161
rect.setRect(randDblCoord(), randDblCoord(),
1162
randDblCoord(), randDblCoord());
1163
}
1164
1165
public Shape getShape() {
1166
return rect;
1167
}
1168
1169
public String toString() {
1170
return ("Rect("+
1171
rect.getX()+", "+
1172
rect.getY()+", "+
1173
rect.getWidth()+", "+
1174
rect.getHeight()
1175
+")");
1176
}
1177
}
1178
1179
public static class Line extends AnnotatedShapeOp {
1180
public static Line tryparse(String str) {
1181
str = str.trim();
1182
if (!str.startsWith("Line(")) {
1183
return null;
1184
}
1185
str = str.substring(5);
1186
double coords[] = new double[4];
1187
boolean foundparen = false;
1188
for (int i = 0; i < coords.length; i++) {
1189
int index = str.indexOf(",");
1190
if (index < 0) {
1191
if (i < coords.length-1) {
1192
return null;
1193
}
1194
index = str.indexOf(")");
1195
if (index < 0) {
1196
return null;
1197
}
1198
foundparen = true;
1199
}
1200
String num = str.substring(0, index);
1201
try {
1202
coords[i] = Double.parseDouble(num);
1203
} catch (NumberFormatException nfe) {
1204
return null;
1205
}
1206
str = str.substring(index+1);
1207
}
1208
if (!foundparen || str.length() > 0) {
1209
return null;
1210
}
1211
Line l = new Line();
1212
l.line.setLine(coords[0], coords[1],
1213
coords[2], coords[3]);
1214
return l;
1215
}
1216
1217
private Line2D line = new Line2D.Double();
1218
1219
public void randomize() {
1220
line.setLine(randDblCoord(), randDblCoord(),
1221
randDblCoord(), randDblCoord());
1222
}
1223
1224
public Shape getShape() {
1225
return line;
1226
}
1227
1228
public String toString() {
1229
return ("Line("+
1230
line.getX1()+", "+
1231
line.getY1()+", "+
1232
line.getX2()+", "+
1233
line.getY2()
1234
+")");
1235
}
1236
}
1237
1238
public static class RectMethod extends AnnotatedRenderOp {
1239
public static RectMethod tryparse(String str) {
1240
str = str.trim();
1241
if (!str.startsWith("RectMethod(")) {
1242
return null;
1243
}
1244
str = str.substring(11);
1245
int coords[] = new int[4];
1246
boolean foundparen = false;
1247
for (int i = 0; i < coords.length; i++) {
1248
int index = str.indexOf(",");
1249
if (index < 0) {
1250
if (i < coords.length-1) {
1251
return null;
1252
}
1253
index = str.indexOf(")");
1254
if (index < 0) {
1255
return null;
1256
}
1257
foundparen = true;
1258
}
1259
String num = str.substring(0, index).trim();
1260
try {
1261
coords[i] = Integer.parseInt(num);
1262
} catch (NumberFormatException nfe) {
1263
return null;
1264
}
1265
str = str.substring(index+1);
1266
}
1267
if (!foundparen || str.length() > 0) {
1268
return null;
1269
}
1270
RectMethod rm = new RectMethod();
1271
rm.rect.setBounds(coords[0], coords[1],
1272
coords[2], coords[3]);
1273
return rm;
1274
}
1275
1276
private Rectangle rect = new Rectangle();
1277
1278
public void randomize() {
1279
rect.setBounds(randIntCoord(), randIntCoord(),
1280
randIntCoord(), randIntCoord());
1281
}
1282
1283
public void fill(Graphics2D g2d) {
1284
g2d.fillRect(rect.x, rect.y, rect.width, rect.height);
1285
}
1286
1287
public void draw(Graphics2D g2d) {
1288
g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
1289
}
1290
1291
public String toString() {
1292
return ("RectMethod("+
1293
rect.x+", "+
1294
rect.y+", "+
1295
rect.width+", "+
1296
rect.height
1297
+")");
1298
}
1299
}
1300
1301
public static class LineMethod extends AnnotatedRenderOp {
1302
public static LineMethod tryparse(String str) {
1303
str = str.trim();
1304
if (!str.startsWith("LineMethod(")) {
1305
return null;
1306
}
1307
str = str.substring(11);
1308
int coords[] = new int[4];
1309
boolean foundparen = false;
1310
for (int i = 0; i < coords.length; i++) {
1311
int index = str.indexOf(",");
1312
if (index < 0) {
1313
if (i < coords.length-1) {
1314
return null;
1315
}
1316
index = str.indexOf(")");
1317
if (index < 0) {
1318
return null;
1319
}
1320
foundparen = true;
1321
}
1322
String num = str.substring(0, index).trim();
1323
try {
1324
coords[i] = Integer.parseInt(num);
1325
} catch (NumberFormatException nfe) {
1326
return null;
1327
}
1328
str = str.substring(index+1);
1329
}
1330
if (!foundparen || str.length() > 0) {
1331
return null;
1332
}
1333
LineMethod lm = new LineMethod();
1334
lm.line = coords;
1335
return lm;
1336
}
1337
1338
private int line[] = new int[4];
1339
1340
public void randomize() {
1341
line[0] = randIntCoord();
1342
line[1] = randIntCoord();
1343
line[2] = randIntCoord();
1344
line[3] = randIntCoord();
1345
}
1346
1347
public void fill(Graphics2D g2d) {
1348
}
1349
1350
public void draw(Graphics2D g2d) {
1351
g2d.drawLine(line[0], line[1], line[2], line[3]);
1352
}
1353
1354
public String toString() {
1355
return ("LineMethod("+
1356
line[0]+", "+
1357
line[1]+", "+
1358
line[2]+", "+
1359
line[3]
1360
+")");
1361
}
1362
}
1363
1364
public static class ErrorWindow extends Frame {
1365
ImageCanvas unclipped;
1366
ImageCanvas reference;
1367
ImageCanvas actual;
1368
ImageCanvas diff;
1369
1370
public ErrorWindow() {
1371
super("Error Comparison Window");
1372
1373
unclipped = new ImageCanvas();
1374
reference = new ImageCanvas();
1375
actual = new ImageCanvas();
1376
diff = new ImageCanvas();
1377
1378
setLayout(new SmartGridLayout(0, 2, 5, 5));
1379
addImagePanel(unclipped, "Unclipped rendering");
1380
addImagePanel(reference, "Clipped reference");
1381
addImagePanel(actual, "Actual clipped");
1382
addImagePanel(diff, "Difference");
1383
1384
addWindowListener(new WindowAdapter() {
1385
public void windowClosing(WindowEvent e) {
1386
setVisible(false);
1387
}
1388
});
1389
}
1390
1391
public void addImagePanel(ImageCanvas ic, String label) {
1392
add(ic);
1393
add(new Label(label));
1394
}
1395
1396
public void setImages(BufferedImage imgref, BufferedImage imgtst) {
1397
unclipped.setImage(imgref);
1398
reference.setReference(imgref);
1399
actual.setImage(imgtst);
1400
diff.setDiff(reference.getImage(), imgtst);
1401
invalidate();
1402
pack();
1403
repaint();
1404
}
1405
1406
public void setVisible(boolean vis) {
1407
super.setVisible(vis);
1408
synchronized (this) {
1409
notifyAll();
1410
}
1411
}
1412
1413
public synchronized void waitForHide() {
1414
while (isShowing()) {
1415
try {
1416
wait();
1417
} catch (InterruptedException e) {
1418
System.exit(2);
1419
}
1420
}
1421
}
1422
}
1423
1424
public static class SmartGridLayout implements LayoutManager {
1425
int rows;
1426
int cols;
1427
int hgap;
1428
int vgap;
1429
1430
public SmartGridLayout(int r, int c, int h, int v) {
1431
this.rows = r;
1432
this.cols = c;
1433
this.hgap = h;
1434
this.vgap = v;
1435
}
1436
1437
public void addLayoutComponent(String name, Component comp) {
1438
}
1439
1440
public void removeLayoutComponent(Component comp) {
1441
}
1442
1443
public int[][] getGridSizes(Container parent, boolean min) {
1444
int ncomponents = parent.getComponentCount();
1445
int nrows = rows;
1446
int ncols = cols;
1447
1448
if (nrows > 0) {
1449
ncols = (ncomponents + nrows - 1) / nrows;
1450
} else {
1451
nrows = (ncomponents + ncols - 1) / ncols;
1452
}
1453
int widths[] = new int[ncols+1];
1454
int heights[] = new int[nrows+1];
1455
int x = 0;
1456
int y = 0;
1457
for (int i = 0 ; i < ncomponents ; i++) {
1458
Component comp = parent.getComponent(i);
1459
Dimension d = (min
1460
? comp.getMinimumSize()
1461
: comp.getPreferredSize());
1462
if (widths[x] < d.width) {
1463
widths[x] = d.width;
1464
}
1465
if (heights[y] < d.height) {
1466
heights[y] = d.height;
1467
}
1468
x++;
1469
if (x >= ncols) {
1470
x = 0;
1471
y++;
1472
}
1473
}
1474
for (int i = 0; i < ncols; i++) {
1475
widths[ncols] += widths[i];
1476
}
1477
for (int i = 0; i < nrows; i++) {
1478
heights[nrows] += heights[i];
1479
}
1480
return new int[][] { widths, heights };
1481
}
1482
1483
public Dimension getSize(Container parent, boolean min) {
1484
int sizes[][] = getGridSizes(parent, min);
1485
int widths[] = sizes[0];
1486
int heights[] = sizes[1];
1487
int nrows = heights.length-1;
1488
int ncols = widths.length-1;
1489
int w = widths[ncols];
1490
int h = heights[nrows];
1491
Insets insets = parent.getInsets();
1492
return new Dimension(insets.left+insets.right + w+(ncols+1)*hgap,
1493
insets.top+insets.bottom + h+(nrows+1)*vgap);
1494
}
1495
1496
public Dimension preferredLayoutSize(Container parent) {
1497
return getSize(parent, false);
1498
}
1499
1500
public Dimension minimumLayoutSize(Container parent) {
1501
return getSize(parent, true);
1502
}
1503
1504
public void layoutContainer(Container parent) {
1505
int pref[][] = getGridSizes(parent, false);
1506
int min[][] = getGridSizes(parent, true);
1507
int minwidths[] = min[0];
1508
int minheights[] = min[1];
1509
int prefwidths[] = pref[0];
1510
int prefheights[] = pref[1];
1511
int nrows = minheights.length - 1;
1512
int ncols = minwidths.length - 1;
1513
Insets insets = parent.getInsets();
1514
int w = parent.getWidth() - insets.left - insets.right;
1515
int h = parent.getHeight() - insets.top - insets.bottom;
1516
w = w - (ncols+1)*hgap;
1517
h = h - (nrows+1)*vgap;
1518
int widths[] = calculateSizes(w, ncols, minwidths, prefwidths);
1519
int heights[] = calculateSizes(h, nrows, minheights, prefheights);
1520
int ncomponents = parent.getComponentCount();
1521
int x = insets.left + hgap;
1522
int y = insets.top + vgap;
1523
int r = 0;
1524
int c = 0;
1525
for (int i = 0; i < ncomponents; i++) {
1526
parent.getComponent(i).setBounds(x, y, widths[c], heights[r]);
1527
x += widths[c++] + hgap;
1528
if (c >= ncols) {
1529
c = 0;
1530
x = insets.left + hgap;
1531
y += heights[r++] + vgap;
1532
if (r >= nrows) {
1533
// just in case
1534
break;
1535
}
1536
}
1537
}
1538
}
1539
1540
public static int[] calculateSizes(int total, int num,
1541
int minsizes[], int prefsizes[])
1542
{
1543
if (total <= minsizes[num]) {
1544
return minsizes;
1545
}
1546
if (total >= prefsizes[num]) {
1547
return prefsizes;
1548
}
1549
int sizes[] = new int[total];
1550
int prevhappy = 0;
1551
int nhappy = 0;
1552
int happysize = 0;
1553
do {
1554
int addsize = (total - happysize) / (num - nhappy);
1555
happysize = 0;
1556
for (int i = 0; i < num; i++) {
1557
if (sizes[i] >= prefsizes[i] ||
1558
minsizes[i] + addsize > prefsizes[i])
1559
{
1560
happysize += (sizes[i] = prefsizes[i]);
1561
nhappy++;
1562
} else {
1563
sizes[i] = minsizes[i] + addsize;
1564
}
1565
}
1566
} while (nhappy < num && nhappy > prevhappy);
1567
return sizes;
1568
}
1569
}
1570
1571
public static class ImageCanvas extends Canvas {
1572
BufferedImage image;
1573
1574
public void setImage(BufferedImage img) {
1575
this.image = img;
1576
}
1577
1578
public BufferedImage getImage() {
1579
return image;
1580
}
1581
1582
public void checkImage(int w, int h) {
1583
if (image == null ||
1584
image.getWidth() < w ||
1585
image.getHeight() < h)
1586
{
1587
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
1588
}
1589
}
1590
1591
public void setReference(BufferedImage img) {
1592
checkImage(img.getWidth(), img.getHeight());
1593
Graphics g = image.createGraphics();
1594
g.drawImage(img, 0, 0, null);
1595
g.setColor(Color.white);
1596
g.fillRect(0, 0, 30, 10);
1597
g.fillRect(30, 0, 10, 30);
1598
g.fillRect(10, 30, 30, 10);
1599
g.fillRect(0, 10, 10, 30);
1600
g.dispose();
1601
}
1602
1603
public void setDiff(BufferedImage imgref, BufferedImage imgtst) {
1604
int w = Math.max(imgref.getWidth(), imgtst.getWidth());
1605
int h = Math.max(imgref.getHeight(), imgtst.getHeight());
1606
checkImage(w, h);
1607
Graphics g = image.createGraphics();
1608
g.drawImage(imgref, 0, 0, null);
1609
g.setXORMode(Color.white);
1610
g.drawImage(imgtst, 0, 0, null);
1611
g.setPaintMode();
1612
g.setColor(new Color(1f, 1f, 0f, 0.25f));
1613
g.fillRect(10, 10, 20, 20);
1614
g.setColor(new Color(1f, 0f, 0f, 0.25f));
1615
g.fillRect(0, 0, 30, 10);
1616
g.fillRect(30, 0, 10, 30);
1617
g.fillRect(10, 30, 30, 10);
1618
g.fillRect(0, 10, 10, 30);
1619
g.dispose();
1620
}
1621
1622
public Dimension getPreferredSize() {
1623
if (image == null) {
1624
return new Dimension();
1625
} else {
1626
return new Dimension(image.getWidth(), image.getHeight());
1627
}
1628
}
1629
1630
public void paint(Graphics g) {
1631
g.drawImage(image, 0, 0, null);
1632
}
1633
}
1634
}
1635
1636