--- /dev/null	2010-06-29 11:10:08.737208357 +0200
+++ openjdk/jdk/test/java/awt/font/InternationalFonts/InternationalFontsStyles.java	2011-01-17 17:06:44.452369000 +0100
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2011 Red Hat, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+
+import javax.imageio.ImageIO;
+
+/**
+ * @test
+ * @run main InternationalFontsStyles
+ * @author Pavel Tisnovsky
+ * 
+ * @summary This test check if selected international characters could be
+ *          properly rendered with various font styles and logical names.
+ * 
+ *          This regression test check if selected international characters
+ *          could be properly rendered using various styles and logical font
+ *          names - the test check rendering using all combinations of logical
+ *          font names (Font.SERIF, Font.SANS_SERIF, Font.MONOSPACED,
+ *          Font.DIALOG, Font.DIALOG_INPUT) and font styles (Font.PLAIN,
+ *          Font.BOLD, Font.ITALIC, Font.BOLD+Font.ITALIC).
+ * 
+ *          The test is based on rendering certain characters from selected code
+ *          pages into BufferedImage.
+ * 
+ *          When the shape of selected character does not exists or font
+ *          configuration is broken, only empty rectangle is rendered instead of
+ *          the selected character shape. This rectangle is filtered and then
+ *          the destination image is tested whether it is empty (=white).
+ * 
+ *          If test images with rendered characters needs to be created use
+ *          following flag: -create-images
+ * 
+ */
+public class InternationalFontsStyles
+{
+    // all logical font names which are tested
+    private static final String[] fontNames = {Font.SERIF, Font.SANS_SERIF, Font.MONOSPACED, Font.DIALOG, Font.DIALOG_INPUT};
+
+    // all font styles which are tested
+    private static final int[]    fontStyles = {Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD+Font.ITALIC};
+
+    // width and height of image where is each character rendered
+    private static int WIDTH = 200;
+    private static int HEIGHT = 200;
+
+    // font size used for rendering
+    private static final int FONT_SIZE = 160;
+
+    private static final int MINIMUM_HORIZONTAL_LINE_LENGTH = 70;
+    private static final int MINIMUM_VERTICAL_LINE_LENGTH = 80;
+    private static final int BLACK_WHITE_THRESHOLD = 128;
+    private static final int BLACK_PIXEL_COUNT_THRESHOLD = WIDTH * HEIGHT / 1000;
+
+    private static final String[][] testedStrings = {
+        {"Latin-1",    "abcdefABCDEF"},
+        {"Latin-2",    "\u011b\u0161\u010d\u0159\u017e\u00fd\u00e1\u00ed\u00e9\u00fa\u016f\u013e\u0148"},
+        {"Cyrilic",    "\u0414\u0417\u0418\u0472\u0424\u0425\u0470\u0460\u0426"},
+        {"Greek",      "\u03b2\u03be\u03b3\u03b4\u03c0\u03b5\u03c1\u03b6\u03a3\u03c3\u03c2\u03b7\u03c4\u03b8\u03c5\u03a9"},
+        {"Asia-Test1", "\u4f53\u4e2d\u6587\u7b26\u53f7"},
+        {"Asia-Test2", "\u7e41\u9ad4\u4e2d\u6587\u7b26\u865f"},
+        {"Asia-Test3", "\u65e5\u672c\u306e\u8c61\u5fb4"},
+        {"Asia-Test4", "\ud55c\uad6d\uc5b4\uae30\ud638"},
+    };
+
+    /**
+     * Returns string containing given font style. This style could
+     * be PLAIN, BOLD, ITALIC or combination of these styles.
+     *
+     * @param fontStyle selected font style, eg. Font.BOLD
+     * @return textual representation of font style
+     */
+    private static String getFontStyle(int fontStyle)
+    {
+        return new String[]
+        //   0        1       2          1+2
+        { "PLAIN", "BOLD", "ITALIC", "BOLD+ITALIC" }[fontStyle];
+    }
+
+    /**
+     * Creates test image a renders one big character to it.
+     * @param str string to be rendered
+     * @param fontStyle selected font style
+     * @param fontName selected font name
+     * @return
+     */
+    private BufferedImage createTestImage(String str, String fontName, int fontStyle) {
+        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_BYTE_GRAY);
+        Graphics2D gc = image.createGraphics();
+        gc.setBackground(Color.WHITE);
+        gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
+        gc.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+        gc.clearRect(0, 0, WIDTH, HEIGHT);
+        gc.setFont(new Font(fontName, fontStyle, FONT_SIZE));
+        gc.setColor(Color.BLACK);
+        gc.drawString(str, 0, HEIGHT - 40);
+        gc.dispose();
+        return image;
+    }
+
+    /**
+     * Creates destination image and then copies data from source image to it
+     * @param src source image
+     * @return destination image as copy of source image
+     */
+    private BufferedImage createDestinationImage(BufferedImage src)
+    {
+        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_BYTE_GRAY);
+        src.copyData(image.getRaster());
+        return image;
+    }
+
+    /**
+     * Removes long horizontal lines from image
+     */
+    private void removeHorizontalLines(BufferedImage image)
+    {
+        for (int y = 0; y < image.getHeight(); y++)
+        {
+            int startX = -1, endX = -1;
+            for (int x = 0; x < image.getWidth(); x++)
+            {
+                int color = image.getRaster().getSample(x, y, 0);
+                if (startX < 0 && color <= BLACK_WHITE_THRESHOLD) {
+                    startX = x;
+                    //System.out.println("> " + y + "\t" + x);
+                }
+                if (startX > 0 && endX < 0 && color > BLACK_WHITE_THRESHOLD)
+                {
+                    endX = x;
+                    //System.out.println("< " + y + "\t" + x);
+                }
+            }
+            // remove long horizontal line, but only if this line found detected in image
+            if (startX > 0 && endX > 0 && (endX - startX) > MINIMUM_HORIZONTAL_LINE_LENGTH)
+            {
+                for (int x = startX; x < endX; x++) {
+                    image.getRaster().setSample(x, y, 0, 255);
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes long vertical lines from image
+     */
+    private void removeVerticalLines(BufferedImage image)
+    {
+        for (int x = 0; x < image.getWidth(); x++)
+        {
+            int startY = -1, endY = -1;
+            for (int y = 0; y < image.getHeight(); y++)
+            {
+                int color = image.getRaster().getSample(x, y, 0);
+                if (startY < 0 && color <= BLACK_WHITE_THRESHOLD)
+                {
+                    startY = y;
+                }
+                if (startY > 0 && endY < 0 && color > BLACK_WHITE_THRESHOLD)
+                {
+                    endY = y;
+                    //System.out.println("< " + y + "\t" + x);
+                }
+            }
+            // remove long vertical line, but only if this line found detected in image
+            if (startY > 0 && endY > 0 && (endY - startY) > MINIMUM_VERTICAL_LINE_LENGTH)
+            {
+                for (int y = startY; y < endY; y++) {
+                    image.getRaster().setSample(x, y, 0, 255);
+                }
+            }
+        }
+    }
+
+    /**
+     * Test if image is almost empty (one large white area)
+     * @param image
+     * @return
+     */
+    private boolean isImageAlmostEmpty(BufferedImage image)
+    {
+        int blackPixelCount = 0;
+        for (int y = 0; y < image.getHeight(); y++)
+        {
+            for (int x = 0; x < image.getWidth(); x++)
+            {
+                if (image.getRaster().getSample(x, y, 0) < BLACK_WHITE_THRESHOLD)
+                {
+                    blackPixelCount++;
+                }
+            }
+        }
+        return blackPixelCount < BLACK_PIXEL_COUNT_THRESHOLD;
+    }
+
+    private String constructImageFileName(String fontName, int fontStyle, int code, String suffix)
+    {
+        return fontName + "_" + getFontStyle(fontStyle) + "_" + code + "_" + suffix + ".png";
+    }
+
+    public void runTest(boolean createImages) throws IOException
+    {
+        List<Integer> badCharacters = new ArrayList<Integer>();
+        for (String[] testedString : testedStrings)
+        {
+            for (String fontName : fontNames)
+            {
+                for (int fontStyle : fontStyles)
+                {
+                    System.out.format("check string %s rendered by font %s with style %s\n", testedString[1], fontName,
+                            getFontStyle(fontStyle));
+                    for (int i = 0; i < testedString[1].length(); i++)
+                    {
+                        String str = testedString[1].substring(i, 1 + i);
+                        int code = str.charAt(0);
+                        System.out.print(code + "\t");
+                        BufferedImage src = createTestImage(str, fontName, fontStyle);
+                        BufferedImage dst = createDestinationImage(src);
+                        removeHorizontalLines(dst);
+                        removeVerticalLines(dst);
+
+                        if (createImages /*|| true*/)
+                        {
+                            ImageIO.write(src, "png",
+                                    new File(constructImageFileName(fontName, fontStyle, code, "scr")));
+                            ImageIO.write(dst, "png",
+                                    new File(constructImageFileName(fontName, fontStyle, code, "dst")));
+                        }
+
+                        if (isImageAlmostEmpty(dst))
+                        {
+                            System.out.println("*** Error in rendering of character with code: " + code);
+                            badCharacters.add(Integer.valueOf(code));
+                        }
+                    }
+                    System.out.println();
+                }
+            }
+        }
+        // if at least one character is not rendered properly throw an exception
+        if (!badCharacters.isEmpty())
+        {
+            throw new RuntimeException("There are some broken characters: " + badCharacters.toString());
+        }
+        System.out.println("done!");
+    }
+
+    public static void main(String[] args) throws IOException
+    {
+        new InternationalFontsStyles().runTest(Arrays.asList(args).contains("-create-images"));
+    }
+}
