source: trunk/tests/SWT/java/SWT005_01.java

Last change on this file was 12, checked in by lpino, 18 years ago
  • Initial commit
File size: 22.1 KB
Line 
1/*
2 * SWT005_01.java
3 */
4
5/*
6 * Copyright (c) 2002, 2004 EclipseOS2 Team.
7 * This file is made available under the terms of the Common Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/cpl-v10.html
10 */
11
12import org.eclipse.swt.*;
13import org.eclipse.swt.widgets.*;
14import org.eclipse.swt.events.*;
15import org.eclipse.swt.graphics.*;
16import org.eclipse.swt.layout.*;
17
18import java.util.ArrayList;
19import java.util.Iterator;
20
21/**
22 * This testcase tests font drawing capabilities.
23 *
24 * Pages #1, #2 and #3
25 * -------------------
26 *
27 * These pages test different ways of font creation, functionality of
28 * the font matching algorithm, font drawing (i.e. Font, FontData classes
29 * and their methods, GC.drawString()), and also various FontMetrics.get*()
30 * methods and GC.stringExtent().
31 *
32 * The first font drawn is the system default font (used when the requested
33 * font is not found). The second font is the default font with the "strikeout"
34 * emphasis. The third font is the widget default font. All other fonts represent
35 * different font families drawin in four basic styles.
36 *
37 * Every font is demonstrated using a string that describes it. The description
38 * string contains:
39 * - the requested font height in points;
40 * - the requested font family;
41 * - the requested style (B = Bold, I = Italic);
42 * - the additional info in square or curly brackets.
43 *
44 * Fonts drawn on the page #1 are created using the height, family name and style.
45 * Fonts drawn on the page #2 are created from fonts on the page #1 using
46 * the crossplatform string representation of the font (FontData.toString()).
47 * Fonts drawn on the page #3 are created from fonts on the page #1 using
48 * their FontData objects directly (not through the string representation).
49 *
50 * Fonts used to draw strings on page #1 should match fonts drawn on pages
51 * #2 and #3. Font description strings should also match (except the third
52 * font from the top) and only the additional info differs depending on the
53 * page number:
54 *
55 * - page #1: font metrics (common and OS-specific) are drawn in square
56 * brackets:
57 * * font style (B for bold and/or I for italic, or none)
58 * * true font size (calculated as (ascent + descent) * 72 / dpi) for
59 * outline fonts and taken from font metrics for bitmap fonts)
60 * * true font face name (OS/2 only)
61 * * FontMetrics.getHeight(), which should be a sum of:
62 * + FontMetrics.getLeading()
63 * + FontMetrics.getAccent()
64 * + FontMetrics.getDescent()
65 * * FontMetrics.getAverageCharWidth()
66 * * Unique internal system font ID (OS/2 only, zero in other cases)
67 * - pages #2 and #3: the crossplatform string representation of the font
68 * (FontData.toString()) is drawn in curly brackets.
69 *
70 * Also:
71 *
72 * - dark red string box corners should exactly match the edges
73 * of the string background (cyan) area (lay down on these edges);
74 * - letters should "sit" on the red (base) line along the string;
75 * - letter tops should be near the blue (accent) line along the string.
76 *
77 * Page #4
78 * -------
79 *
80 * This page tests GC.stringExtent(), GC.getAdvanceWidth() and
81 * GC.getCharWidth():
82 *
83 * a) title should be drawn in the default window font;
84 * b) dark red string/char box corners should exactly match the edges
85 * of the string/char background area (lay down on these edges);
86 * c) letters drawn on the alternating background should be placed
87 * exactly under letters drawn on the cyan background;
88 * d) white and yellow strips should match widths of char bounding boxes
89 * and can overlap for some font styles, their width corresponds to
90 * the x field of the Point returned by gc.stringExtent();
91 * e) red and dark red strips should match advance widths of chars and
92 * should not overlap, their width corresponds to gc.getAdvanceWidth();
93 * f) blue and dark blue strips should be equal or shorter (but not longer)
94 * than red ones, their width corresponds to gc.getCharWidth().
95 *
96 * Note that due to errors in calculation of font metrics in the
97 * OS/2 font engine c) is not true for Type 1 and TrueType fonts --
98 * strings drawn as a whole can differ in total length from strings
99 * drawn char by char. Also, the width of chars of monospaced TrueType
100 * fonts from one family can slightly differ (it can be seen on the third
101 * column where the Courier New family is drawn) although it must be equal.
102 * These things will be fixed in the future.
103 *
104 * Page #5
105 * -------
106 *
107 * This page tests the ability to change fonts of Control objects.
108 * It enables the Change chekbox at the left bottom of the Shell:
109 *
110 * - when Change is uncheked the Next button is drawn in the default
111 * button font
112 * - when Change is checked the Next button is drawn in the Times
113 * New Roman Bold font.
114 *
115 * The string drawn at the top of the Shell should reflect the font
116 * change and be of the same font as the Next button. The text drawn
117 * is the FontData.toString() of the button's Font object. Note that
118 * this text always contains the family name of the existing font that
119 * matched the request we made when created an alternate font for the next
120 * button, even if we request non-existent one. This is because the
121 * information about the requested font family is discarded when the font
122 * is sent to the control object and then read back.
123 *
124 */
125
126public class SWT005_01 extends SWTTestCase {
127
128static {
129 STEP = "005";
130 TEST = "01";
131 DESC = "Fonts";
132}
133
134public static void main (String [] args) {
135 go (new SWT005_01 ());
136}
137
138int page = 1;
139final static int LAST_PAGE = 5;
140
141Button next, prev, change;
142
143boolean drawCheckers = false;
144boolean drawMetrics = true;
145boolean changeFont = false;
146Image background = null;
147
148String [] fontDescs1 = {
149 "11.nonexistent",
150 "9.WarpSans",
151 "18.Times New Roman",
152 "10.Lucida Sans Typewriter",
153 "13.Helv",
154 "0.Arial Black"
155};
156
157String [] fontDescs2 = {
158 "24.Helv", // bitmap font
159 "24.Helvetica", // type1 font (in OS/2)
160 "24.Courier New", // truetype fonr
161};
162
163ArrayList fonts1_1 = new ArrayList();
164ArrayList fonts1_2 = new ArrayList();
165ArrayList fonts1_3 = new ArrayList();
166ArrayList fonts2 = new ArrayList();
167
168Font nextFont;
169
170static String platform = SWT.getPlatform();;
171Class fmHndCls;
172Class fdCls;
173
174Shell createTopShell (Display display) {
175 return new Shell (display,
176 SWT.SHELL_TRIM | SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND); // | SWT.NO_MERGE_PAINTS);
177}
178
179void initComponents () {
180 /* create fonts for 1st drawFont() */
181 FontData fd = new FontData();
182 // uninitialized font
183 fonts1_1.add (new Font (display, fd));
184 // striked out font
185 fd.setName ("<striked out>");
186 setStrikeOut (fd);
187 fonts1_1.add (new Font (display, fd));
188 // system font
189 fonts1_1.add (display.getSystemFont());
190 // other fonts
191 createFonts (fontDescs1, fonts1_1);
192
193 /* create fonts for 2nd and 3rd drawFont() */
194 Iterator it = fonts1_1.iterator();
195 while (it.hasNext()) {
196 Font f = (Font) it.next();
197 fd = f.getFontData() [0];
198 fonts1_2.add (new Font (display, new FontData (fd.toString())));
199 fonts1_3.add (new Font (display, fd));
200 }
201
202 /* create fonts for testFont() */
203 createFonts (fontDescs2, fonts2);
204
205 nextFont = new Font (display, "<unknown_font>", 12, SWT.ITALIC);
206
207 shell.addDisposeListener (new DisposeListener () {
208 public void widgetDisposed (DisposeEvent e) {
209 destroyFonts (fonts1_1);
210 destroyFonts (fonts1_2);
211 destroyFonts (fonts1_3);
212 destroyFonts (fonts2);
213 nextFont.dispose();
214 if (background != null) background.dispose();
215 }
216 });
217
218 shell.addPaintListener(new PaintListener () {
219 public void paintControl(PaintEvent event) {
220 GC gc = event.gc;
221
222 System.out.println ("Font before PAINT: " + gc.getFont().getFontData()[0]);
223
224 Rectangle r = new Rectangle (event.x, event.y, event.width, event.height);
225 gc.setClipping (r);
226
227 drawGrid (gc,
228 (r.x / 20) * 20, (r.y / 20) * 20,
229 r.width + 20, r.height + 20, 10);
230
231 Iterator it;
232 int x, y, i;
233 switch (page) {
234 case 1:
235 case 2:
236 case 3:
237 y = 10;
238 it =
239 page == 1 ? fonts1_1.iterator() :
240 page == 2 ? fonts1_2.iterator() :
241 fonts1_3.iterator();
242 while (it.hasNext()) {
243 Font f = (Font) it.next();
244 y += drawFont (gc, f, 10, y) + 2;
245 }
246 break;
247 case 4:
248 x = 10; y = 10; i = 0;
249 it = fonts2.iterator();
250 while (it.hasNext()) {
251 if (i % 4 == 0) {
252 gc.setFont (null);
253 String str = fontDescs2 [i / 4] + ": ";
254 switch (i / 4) {
255 case 0: str += "Bitmap font"; break;
256 case 1: str += "Type 1 font (only in OS/2)"; break;
257 case 2: str += "TrueType font"; break;
258 }
259 gc.drawString (str, x, y, true);
260 y += 30;
261 }
262 Font f = (Font) it.next();
263 y += testFont (gc, f, x, y) + 5;
264 i ++;
265 if (i % 4 == 0) {
266 x += SWT005_01.this.display.getDPI().x * 25 * 8 / 72;
267 y = 10;
268 }
269 }
270 break;
271 case 5: {
272 Font f = next.getFont();
273 gc.setFont (f);
274 String str =
275 "This is the font from the Next button:\n" +
276 f.getFontData()[0] + "\n\n" +
277 "Check the Change checkbox at the bottom to change it.\n";
278 y = 10;
279 gc.drawText (str, 10, y);
280 y += gc.textExtent(str).y;
281 y += testTextBox(gc, 10, y, 0) + 10;
282 y += testTextBox(gc, 10, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB | SWT.DRAW_MNEMONIC) + 10;
283 y += testTextBox(gc, 10, y, SWT.DRAW_DELIMITER) + 10;
284 y += testTextBox(gc, 10, y, SWT.DRAW_TAB) + 10;
285 y += testTextBox(gc, 10, y, SWT.DRAW_MNEMONIC) + 10;
286 break;
287 }
288 }
289 System.out.println ("Font after PAINT: " + gc.getFont().getFontData()[0]);
290 }
291 });
292
293 Composite group1 = new Composite (shell, SWT.NO_BACKGROUND);
294 group1.setLayout (new FillLayout (SWT.HORIZONTAL));
295
296 prev = new Button (group1, SWT.PUSH);
297 prev.setText ("< Previous");
298 prev.setEnabled (false);
299 prev.addSelectionListener (new SelectionAdapter () {
300 public void widgetSelected (SelectionEvent e) {
301 if (page > 1) {
302 page --;
303 updateTitle();
304 }
305 if (page == 1) prev.setEnabled (false);
306 if (page == LAST_PAGE - 1) next.setEnabled (true);
307 change.setEnabled (page == 5);
308 }
309 });
310 next = new Button (group1, SWT.PUSH);
311 next.setText ("Next >");
312 next.addSelectionListener (new SelectionAdapter () {
313 public void widgetSelected (SelectionEvent e) {
314 if (page < LAST_PAGE) {
315 page ++;
316 updateTitle();
317 }
318 if (page == LAST_PAGE) next.setEnabled (false);
319 if (page == 2) prev.setEnabled (true);
320 change.setEnabled (page == 5);
321 }
322 });
323 updateTitle();
324
325 Composite group2 = new Composite (shell, SWT.NO_BACKGROUND);
326 group2.setLayout (new FillLayout (SWT.HORIZONTAL));
327
328 Button checks = new Button (group2, SWT.CHECK);
329 checks.setText ("Checkers");
330 checks.setSelection (drawCheckers);
331 checks.addSelectionListener (new SelectionAdapter() {
332 public void widgetSelected (SelectionEvent e) {
333 drawCheckers = ((Button)e.widget).getSelection();
334 shell.redraw();
335 }
336 });
337 Button metrics = new Button (group2, SWT.CHECK);
338 metrics.setText ("Metrics");
339 metrics.setSelection (drawMetrics);
340 metrics.addSelectionListener (new SelectionAdapter() {
341 public void widgetSelected (SelectionEvent e) {
342 drawMetrics = ((Button)e.widget).getSelection();
343 shell.redraw();
344 }
345 });
346 change = new Button (group2, SWT.CHECK);
347 change.setText ("Change");
348 change.setSelection (changeFont);
349 change.setEnabled (false);
350 change.addSelectionListener (new SelectionAdapter() {
351 public void widgetSelected (SelectionEvent e) {
352 changeFont = ((Button)e.widget).getSelection();
353 if (changeFont) next.setFont (nextFont);
354 else next.setFont (null);
355 shell.layout();
356 shell.redraw();
357 }
358 });
359
360 FormData fdata = new FormData();
361 fdata.right = new FormAttachment (100, -10);
362 fdata.bottom = new FormAttachment (100, -10);
363 group1.setLayoutData (fdata);
364
365 fdata = new FormData();
366 fdata.left = new FormAttachment (0, 10);
367 fdata.bottom = new FormAttachment (100, -10);
368 group2.setLayoutData (fdata);
369
370 FormLayout formLayout = new FormLayout ();
371 shell.setLayout (formLayout);
372
373 shell.setMaximized (true);
374}
375
376void updateTitle () {
377 setTitle ("page #" + page + " of " + LAST_PAGE);
378 shell.redraw ();
379}
380
381void createFonts (String[] fontDescs, ArrayList fonts) {
382 for (int i = 0; i < fontDescs.length; i++) {
383 String desc = fontDescs [i];
384 int height = 0;
385 int pnt = desc.indexOf ('.');
386 if (pnt >= 0) {
387 try {
388 height = Integer.parseInt (desc.substring (0, pnt));
389 } catch (NumberFormatException x) {
390 }
391 }
392 String name = desc.substring (pnt + 1);
393 for (int j = 0; j < 4; j ++) {
394 fonts.add (new Font (display, new FontData (name, height, j)));
395 }
396 }
397}
398
399void destroyFonts (ArrayList fonts) {
400 Iterator it = fonts.iterator();
401 while (it.hasNext()) {
402 Font f = (Font) it.next();
403 if (!f.equals (display.getSystemFont())) f.dispose();
404 }
405}
406
407int drawFont (GC gc, Font f, int x0, int y0) {
408 FontData fd = f.getFontData() [0];
409 String str = " " + fd.getHeight() + ".";
410 String name;
411 if (f.equals (display.getSystemFont())) name = "<System Font>";
412 else name = fd.getName();
413 str += name.length() == 0 ? "<uninitialized>" : name;
414 int style = fd.getStyle();
415 if (style != SWT.NORMAL) {
416 str += " [";
417 if ((style & SWT.BOLD) != 0) str += "B";
418 if ((style & SWT.ITALIC) != 0) str += "I";
419 str += "]";
420 }
421
422 gc.setFont (f);
423 FontMetrics fm = gc.getFontMetrics();
424 str += " " + getAdditionalFontInfo (fd, fm);
425
426 Point box = gc.stringExtent (str);
427 int hh = box.y / 3;
428
429 gc.setForeground (display.getSystemColor (SWT.COLOR_BLACK));
430 gc.setBackground (display.getSystemColor (SWT.COLOR_CYAN));
431 gc.drawString (str, x0, y0, !drawMetrics);
432
433 if (drawMetrics) {
434 drawCorners (gc, x0, y0, box.x - 1, box.y - 1, hh);
435
436 int h;
437 h = fm.getHeight() - fm.getDescent();
438 gc.setForeground (display.getSystemColor (SWT.COLOR_RED));
439 gc.drawLine (x0, y0 + h, x0 + box.x - 1, y0 + h);
440 h = fm.getLeading();
441 gc.setForeground (display.getSystemColor (SWT.COLOR_BLUE));
442 gc.drawLine (x0, y0 + h, x0 + box.x - 1, y0 + h);
443 }
444
445 return fm.getHeight();
446}
447
448void setStrikeOut (FontData fd) {
449 if (fdCls == null) {
450 fdCls = fd.getClass();
451 }
452 try {
453 if (platform.equals ("pm")) {
454 fdCls.getField ("fsSelection").setShort (fd, (short)0x0010 /* FATTR_SEL_STRIKEOUT */);
455 } else if (platform.equals ("win32")) {
456 Object data = fdCls.getField ("data").get (fd);
457 data.getClass().getField ("lfStrikeOut").setByte (data, (byte)1);
458 }
459 } catch (NoSuchFieldException x) {
460 } catch (IllegalAccessException x) {
461 }
462}
463
464String getAdditionalFontInfo (FontData fd, FontMetrics fm) {
465 if (fmHndCls == null) {
466 fmHndCls = fm.handle.getClass();
467 }
468
469 String str = null;
470 if (page == 1) {
471 int lMatch = 0;
472 int actualHeight = 0;
473 String faceName = "<not_available>";
474
475 Point dpi = display.getDPI();
476 actualHeight =
477 Math.round ((float)((fm.getAscent() + fm.getDescent()) * 72) / dpi.y);
478
479 if (platform.equals ("pm")) {
480 short fsDefn;
481 short sNominalPointSize;
482 byte[] szFacename = null;
483 try {
484 lMatch = fmHndCls.getField ("lMatch").getInt (fm.handle);
485 fsDefn = fmHndCls.getField ("fsDefn").getShort (fm.handle);
486 sNominalPointSize = fmHndCls.getField ("sNominalPointSize").getShort (fm.handle);
487 szFacename = (byte[])fmHndCls.getField ("szFacename").get (fm.handle);
488
489 if ((fsDefn & 0x0001 /* OS.FM_DEFN_OUTLINE */) == 0) {
490 actualHeight = sNominalPointSize / 10;
491 }
492 int i = 0;
493 while (szFacename [i] != 0) i++;
494 faceName = new String (szFacename, 0, i);
495 } catch (NoSuchFieldException x) {
496 } catch (IllegalAccessException x) {
497 }
498 }
499 str = "[" +
500 actualHeight + "." +
501 faceName + ";" +
502 fm.getHeight() + "=" +
503 fm.getLeading() + "+" + fm.getAscent() + "+" + fm.getDescent() + ";" +
504 fm.getAverageCharWidth() + ";" +
505 lMatch +
506 "] ";
507 } else {
508 str = "{" + fd.toString() + "} ";
509 }
510 return str;
511}
512
513int testFont (GC gc, Font f, int x0, int y0) {
514 gc.setFont (f);
515 String str = "1234 abcd ABCD";
516 Point ext = gc.stringExtent (str);
517 gc.setBackground (display.getSystemColor (SWT.COLOR_CYAN));
518 gc.drawString (str, x0, y0, !drawMetrics);
519 if (drawMetrics) drawCorners (gc, x0, y0, ext.x - 1, ext.y - 1, 3);
520
521 int x = x0, y = y0 + ext.y, y1 = y + ext.y;
522 char[] chars = new char [str.length()];
523 str.getChars(0, str.length(), chars, 0);
524 for (int i = 0; i < chars.length; i++) {
525 char ch = chars [i];
526 String s = new String (chars, i, 1);
527 Point e = gc.stringExtent (s);
528 gc.setBackground (display.getSystemColor (
529 i % 2 == 0 ? SWT.COLOR_WHITE : SWT.COLOR_YELLOW));
530 gc.drawString (s, x, y, !drawMetrics);
531 if (drawMetrics) {
532 drawCorners (gc, x, y, e.x - 1, e.y - 1, 3);
533 int dy;
534 gc.setBackground (display.getSystemColor (
535 i % 2 == 0 ? SWT.COLOR_WHITE : SWT.COLOR_DARK_YELLOW));
536 dy = (i % 2 == 0) ? 3 : 6;
537 gc.fillRectangle (x, y1 + dy, e.x, 3);
538 gc.setBackground (display.getSystemColor (
539 i % 2 == 0 ? SWT.COLOR_RED : SWT.COLOR_DARK_RED));
540 dy = (i % 2 == 0) ? 12 : 15;
541 gc.fillRectangle (x, y1 + dy, gc.getAdvanceWidth (ch), 3);
542 gc.setBackground (display.getSystemColor (
543 i % 2 == 0 ? SWT.COLOR_BLUE : SWT.COLOR_DARK_BLUE));
544 dy = (i % 2 == 0) ? 21 : 24;
545 gc.fillRectangle (x, y1 + dy, gc.getCharWidth (ch), 3);
546 }
547 x += gc.getAdvanceWidth (ch);
548 }
549 return y1 + 30 - y0;
550}
551
552int testTextBox (GC gc, int x0, int y0, int flags) {
553 if (drawMetrics) flags &= ~SWT.DRAW_TRANSPARENT;
554 else flags |= SWT.DRAW_TRANSPARENT;
555
556 String str = "";
557 if ((flags & SWT.DRAW_DELIMITER) != 0) str += " DRAW_DELIMITER";
558 if ((flags & SWT.DRAW_MNEMONIC) != 0) str += " DRAW_MNEMONIC";
559 if ((flags & SWT.DRAW_TAB) != 0) str += " DRAW_TAB";
560 if ((flags & SWT.DRAW_TRANSPARENT) != 0) str += " DRAW_TRANSPARENT";
561 if (str.length() == 0) str = "Flags: none\n\n";
562 else str = "Flags: " + str + "\n\n";
563 str +=
564 "* &One Mnemonic [\\n]\n" +
565 "* Trying &Two M&nemonics [\\r]\r" +
566 "* Regular Line [\\r\\n]\r\n" +
567 "* Spaced Line [\\n\\r]\n\r" +
568 "*\tTabbed Line\n" +
569 "\t1\t2\t3\t4\n" +
570 "*\t\tDouble Tabbed Line";
571
572 Point pnt = gc.textExtent(str, flags);
573 gc.setForeground (display.getSystemColor (SWT.COLOR_BLACK));
574 gc.setBackground (display.getSystemColor (SWT.COLOR_CYAN));
575 gc.drawText(str, x0, y0, flags);
576 if (drawMetrics) {
577 gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
578 gc.drawRectangle(x0, y0, pnt.x - 1, pnt.y - 1);
579 }
580 return pnt.y;
581}
582
583void drawCorners (GC gc, int x, int y, int dx, int dy, int size) {
584 Color c = gc.getForeground();
585 gc.setForeground (display.getSystemColor (SWT.COLOR_DARK_RED));
586 gc.drawPolyline (
587 new int[] {x, y + size, x, y, x + size, y});
588 gc.drawPolyline (
589 new int[] {x + dx, y + dy - size, x + dx, y + dy, x + dx - size, y + dy});
590 gc.setForeground (c);
591}
592
593void drawGrid (GC gc, int x0, int y0, int width, int height, int step) {
594 if (drawCheckers) {
595 if (background == null) {
596 int w = 20, h = 20;
597 Display display = Display.getDefault();
598 background = new Image (display, w, h);
599 GC bgc = new GC (background);
600 bgc.setBackground (display.getSystemColor (SWT.COLOR_WHITE));
601 bgc.fillRectangle(0, 0, 10, 10);
602 bgc.fillRectangle(10, 10, 10, 10);
603 bgc.setBackground (display.getSystemColor (SWT.COLOR_GRAY));
604 bgc.fillRectangle(10, 0, 10, 10);
605 bgc.fillRectangle(0, 10, 10, 10);
606 bgc.dispose();
607 }
608 Rectangle r = background.getBounds();
609 for (int y = 0; y <= height; y += r.height)
610 for (int x = 0; x <= width; x += r.width)
611 gc.drawImage (background, x0 + x, y0 + y);
612 } else {
613 gc.fillRectangle (gc.getClipping());
614 }
615}
616
617}
618
Note: See TracBrowser for help on using the repository browser.