Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/applets/DitherTest/DitherTest.java
38827 views
1
/*
2
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
*
8
* - Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
*
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* - Neither the name of Oracle nor the names of its
16
* contributors may be used to endorse or promote products derived
17
* from this software without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32
/*
33
* This source code is provided to illustrate the usage of a given feature
34
* or technique and has been deliberately simplified. Additional steps
35
* required for a production-quality application, such as security checks,
36
* input validation and proper error handling, might not be present in
37
* this sample code.
38
*/
39
40
41
42
import java.applet.Applet;
43
import java.awt.AWTEvent;
44
import java.awt.BorderLayout;
45
import java.awt.Button;
46
import java.awt.Canvas;
47
import java.awt.Choice;
48
import java.awt.Color;
49
import java.awt.Dimension;
50
import java.awt.FlowLayout;
51
import java.awt.FontMetrics;
52
import java.awt.Frame;
53
import java.awt.Graphics;
54
import java.awt.Image;
55
import java.awt.Label;
56
import java.awt.LayoutManager;
57
import java.awt.Panel;
58
import java.awt.TextField;
59
import java.awt.Toolkit;
60
import java.awt.event.ActionEvent;
61
import java.awt.event.ActionListener;
62
import java.awt.event.KeyEvent;
63
import java.awt.event.TextEvent;
64
import java.awt.image.ColorModel;
65
import java.awt.image.MemoryImageSource;
66
67
68
enum DitherMethod {
69
70
NOOP, RED, GREEN, BLUE, ALPHA, SATURATION
71
};
72
73
74
@SuppressWarnings("serial")
75
public class DitherTest extends Applet implements Runnable {
76
77
private Thread runner;
78
private DitherControls XControls;
79
private DitherControls YControls;
80
private DitherCanvas canvas;
81
82
public static void main(String args[]) {
83
Frame f = new Frame("DitherTest");
84
DitherTest ditherTest = new DitherTest();
85
ditherTest.init();
86
f.add("Center", ditherTest);
87
f.pack();
88
f.setVisible(true);
89
ditherTest.start();
90
}
91
92
@Override
93
public void init() {
94
String xspec = null, yspec = null;
95
int xvals[] = new int[2];
96
int yvals[] = new int[2];
97
98
try {
99
xspec = getParameter("xaxis");
100
yspec = getParameter("yaxis");
101
} catch (NullPointerException ignored) {
102
//only occurs if run as application
103
}
104
105
if (xspec == null) {
106
xspec = "red";
107
}
108
if (yspec == null) {
109
yspec = "blue";
110
}
111
DitherMethod xmethod = colorMethod(xspec, xvals);
112
DitherMethod ymethod = colorMethod(yspec, yvals);
113
114
setLayout(new BorderLayout());
115
XControls = new DitherControls(this, xvals[0], xvals[1],
116
xmethod, false);
117
YControls = new DitherControls(this, yvals[0], yvals[1],
118
ymethod, true);
119
YControls.addRenderButton();
120
add("North", XControls);
121
add("South", YControls);
122
add("Center", canvas = new DitherCanvas());
123
}
124
125
private DitherMethod colorMethod(String s, int vals[]) {
126
DitherMethod method = DitherMethod.NOOP;
127
if (s == null) {
128
s = "";
129
}
130
String lower = s.toLowerCase();
131
132
for (DitherMethod m : DitherMethod.values()) {
133
if (lower.startsWith(m.toString().toLowerCase())) {
134
method = m;
135
lower = lower.substring(m.toString().length());
136
}
137
}
138
if (method == DitherMethod.NOOP) {
139
vals[0] = 0;
140
vals[1] = 0;
141
return method;
142
}
143
int begval = 0;
144
int endval = 255;
145
try {
146
int dash = lower.indexOf('-');
147
if (dash < 0) {
148
endval = Integer.parseInt(lower);
149
} else {
150
begval = Integer.parseInt(lower.substring(0, dash));
151
endval = Integer.parseInt(lower.substring(dash + 1));
152
}
153
} catch (NumberFormatException ignored) {
154
}
155
156
if (begval < 0) {
157
begval = 0;
158
} else if (begval > 255) {
159
begval = 255;
160
}
161
162
if (endval < 0) {
163
endval = 0;
164
} else if (endval > 255) {
165
endval = 255;
166
}
167
168
vals[0] = begval;
169
vals[1] = endval;
170
return method;
171
}
172
173
/**
174
* Calculates and returns the image. Halts the calculation and returns
175
* null if the Applet is stopped during the calculation.
176
*/
177
private Image calculateImage() {
178
Thread me = Thread.currentThread();
179
180
int width = canvas.getSize().width;
181
int height = canvas.getSize().height;
182
int xvals[] = new int[2];
183
int yvals[] = new int[2];
184
int xmethod = XControls.getParams(xvals);
185
int ymethod = YControls.getParams(yvals);
186
int pixels[] = new int[width * height];
187
int c[] = new int[4]; //temporarily holds R,G,B,A information
188
int index = 0;
189
for (int j = 0; j < height; j++) {
190
for (int i = 0; i < width; i++) {
191
c[0] = c[1] = c[2] = 0;
192
c[3] = 255;
193
if (xmethod < ymethod) {
194
applyMethod(c, xmethod, i, width, xvals);
195
applyMethod(c, ymethod, j, height, yvals);
196
} else {
197
applyMethod(c, ymethod, j, height, yvals);
198
applyMethod(c, xmethod, i, width, xvals);
199
}
200
pixels[index++] = ((c[3] << 24) | (c[0] << 16) | (c[1] << 8)
201
| c[2]);
202
}
203
204
// Poll once per row to see if we've been told to stop.
205
if (runner != me) {
206
return null;
207
}
208
}
209
return createImage(new MemoryImageSource(width, height,
210
ColorModel.getRGBdefault(), pixels, 0, width));
211
}
212
213
private void applyMethod(int c[], int methodIndex, int step,
214
int total, int vals[]) {
215
DitherMethod method = DitherMethod.values()[methodIndex];
216
if (method == DitherMethod.NOOP) {
217
return;
218
}
219
int val = ((total < 2)
220
? vals[0]
221
: vals[0] + ((vals[1] - vals[0]) * step / (total - 1)));
222
switch (method) {
223
case RED:
224
c[0] = val;
225
break;
226
case GREEN:
227
c[1] = val;
228
break;
229
case BLUE:
230
c[2] = val;
231
break;
232
case ALPHA:
233
c[3] = val;
234
break;
235
case SATURATION:
236
int max = Math.max(Math.max(c[0], c[1]), c[2]);
237
int min = max * (255 - val) / 255;
238
if (c[0] == 0) {
239
c[0] = min;
240
}
241
if (c[1] == 0) {
242
c[1] = min;
243
}
244
if (c[2] == 0) {
245
c[2] = min;
246
}
247
break;
248
}
249
}
250
251
@Override
252
public void start() {
253
runner = new Thread(this);
254
runner.start();
255
}
256
257
@Override
258
public void run() {
259
canvas.setImage(null); // Wipe previous image
260
Image img = calculateImage();
261
if (img != null && runner == Thread.currentThread()) {
262
canvas.setImage(img);
263
}
264
}
265
266
@Override
267
public void stop() {
268
runner = null;
269
}
270
271
@Override
272
public void destroy() {
273
remove(XControls);
274
remove(YControls);
275
remove(canvas);
276
}
277
278
@Override
279
public String getAppletInfo() {
280
return "An interactive demonstration of dithering.";
281
}
282
283
@Override
284
public String[][] getParameterInfo() {
285
String[][] info = {
286
{ "xaxis", "{RED, GREEN, BLUE, ALPHA, SATURATION}",
287
"The color of the Y axis. Default is RED." },
288
{ "yaxis", "{RED, GREEN, BLUE, ALPHA, SATURATION}",
289
"The color of the X axis. Default is BLUE." }
290
};
291
return info;
292
}
293
}
294
295
296
@SuppressWarnings("serial")
297
class DitherCanvas extends Canvas {
298
299
private Image img;
300
private static String calcString = "Calculating...";
301
302
@Override
303
public void paint(Graphics g) {
304
int w = getSize().width;
305
int h = getSize().height;
306
if (img == null) {
307
super.paint(g);
308
g.setColor(Color.black);
309
FontMetrics fm = g.getFontMetrics();
310
int x = (w - fm.stringWidth(calcString)) / 2;
311
int y = h / 2;
312
g.drawString(calcString, x, y);
313
} else {
314
g.drawImage(img, 0, 0, w, h, this);
315
}
316
}
317
318
@Override
319
public void update(Graphics g) {
320
paint(g);
321
}
322
323
@Override
324
public Dimension getMinimumSize() {
325
return new Dimension(20, 20);
326
}
327
328
@Override
329
public Dimension getPreferredSize() {
330
return new Dimension(200, 200);
331
}
332
333
public Image getImage() {
334
return img;
335
}
336
337
public void setImage(Image img) {
338
this.img = img;
339
repaint();
340
}
341
}
342
343
344
@SuppressWarnings("serial")
345
class DitherControls extends Panel implements ActionListener {
346
347
private CardinalTextField start;
348
private CardinalTextField end;
349
private Button button;
350
private Choice choice;
351
private DitherTest applet;
352
private static LayoutManager dcLayout = new FlowLayout(FlowLayout.CENTER,
353
10, 5);
354
355
public DitherControls(DitherTest app, int s, int e, DitherMethod type,
356
boolean vertical) {
357
applet = app;
358
setLayout(dcLayout);
359
add(new Label(vertical ? "Vertical" : "Horizontal"));
360
add(choice = new Choice());
361
for (DitherMethod m : DitherMethod.values()) {
362
choice.addItem(m.toString().substring(0, 1)
363
+ m.toString().substring(1).toLowerCase());
364
}
365
choice.select(type.ordinal());
366
add(start = new CardinalTextField(Integer.toString(s), 4));
367
add(end = new CardinalTextField(Integer.toString(e), 4));
368
}
369
370
/* puts on the button */
371
public void addRenderButton() {
372
add(button = new Button("New Image"));
373
button.addActionListener(this);
374
}
375
376
/* retrieves data from the user input fields */
377
public int getParams(int vals[]) {
378
try {
379
vals[0] = scale(Integer.parseInt(start.getText()));
380
} catch (NumberFormatException nfe) {
381
vals[0] = 0;
382
}
383
try {
384
vals[1] = scale(Integer.parseInt(end.getText()));
385
} catch (NumberFormatException nfe) {
386
vals[1] = 255;
387
}
388
return choice.getSelectedIndex();
389
}
390
391
/* fits the number between 0 and 255 inclusive */
392
private int scale(int number) {
393
if (number < 0) {
394
number = 0;
395
} else if (number > 255) {
396
number = 255;
397
}
398
return number;
399
}
400
401
/* called when user clicks the button */
402
@Override
403
public void actionPerformed(ActionEvent e) {
404
if (e.getSource() == button) {
405
applet.start();
406
}
407
}
408
}
409
410
411
@SuppressWarnings("serial")
412
class CardinalTextField extends TextField {
413
414
String oldText = null;
415
416
public CardinalTextField(String text, int columns) {
417
super(text, columns);
418
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.TEXT_EVENT_MASK);
419
oldText = getText();
420
}
421
422
// Consume non-digit KeyTyped events
423
// Note that processTextEvent kind of eliminates the need for this
424
// function, but this is neater, since ideally, it would prevent
425
// the text from appearing at all. Sigh. See bugid 4100317/4114565.
426
//
427
@Override
428
protected void processEvent(AWTEvent evt) {
429
int id = evt.getID();
430
if (id != KeyEvent.KEY_TYPED) {
431
super.processEvent(evt);
432
return;
433
}
434
435
KeyEvent kevt = (KeyEvent) evt;
436
char c = kevt.getKeyChar();
437
438
// Digits, backspace, and delete are okay
439
// Note that the minus sign is not allowed (neither is decimal)
440
if (Character.isDigit(c) || (c == '\b') || (c == '\u007f')) {
441
super.processEvent(evt);
442
return;
443
}
444
445
Toolkit.getDefaultToolkit().beep();
446
kevt.consume();
447
}
448
449
// Should consume TextEvents for non-integer Strings
450
// Store away the text in the tf for every TextEvent
451
// so we can revert to it on a TextEvent (paste, or
452
// legal key in the wrong location) with bad text
453
//
454
// Note: it would be easy to extend this to an eight-bit
455
// TextField (range 0-255), but I'll leave it as-is.
456
//
457
@Override
458
protected void processTextEvent(TextEvent te) {
459
// The empty string is okay, too
460
String newText = getText();
461
if (newText.equals("") || textIsCardinal(newText)) {
462
oldText = newText;
463
super.processTextEvent(te);
464
return;
465
}
466
467
Toolkit.getDefaultToolkit().beep();
468
setText(oldText);
469
}
470
471
// Returns true for Cardinal (non-negative) numbers
472
// Note that the empty string is not allowed
473
private boolean textIsCardinal(String textToCheck) {
474
try {
475
return Integer.parseInt(textToCheck, 10) >= 0;
476
} catch (NumberFormatException nfe) {
477
return false;
478
}
479
}
480
}
481
482