2e510e04bd
Reviewed-by: dholmes, trebari, jdv
890 lines
32 KiB
Java
890 lines
32 KiB
Java
/*
|
|
* Copyright (c) 2015, Oracle and/or its affiliates. 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.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2013-2014 IBM Corporation and Others. All Rights Reserved.
|
|
*/
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Composite;
|
|
import java.awt.Font;
|
|
import java.awt.FontFormatException;
|
|
import java.awt.FontMetrics;
|
|
import java.awt.Graphics;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.GraphicsConfiguration;
|
|
import java.awt.Image;
|
|
import java.awt.Paint;
|
|
import java.awt.Rectangle;
|
|
import java.awt.RenderingHints;
|
|
import java.awt.RenderingHints.Key;
|
|
import java.awt.Shape;
|
|
import java.awt.Stroke;
|
|
import java.awt.font.FontRenderContext;
|
|
import java.awt.font.GlyphVector;
|
|
import java.awt.font.TextLayout;
|
|
import java.awt.geom.AffineTransform;
|
|
import java.awt.image.BufferedImage;
|
|
import java.awt.image.BufferedImageOp;
|
|
import java.awt.image.ImageObserver;
|
|
import java.awt.image.RenderedImage;
|
|
import java.awt.image.renderable.RenderableImage;
|
|
import java.io.BufferedInputStream;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.text.AttributedCharacterIterator;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.MissingResourceException;
|
|
import java.util.TreeMap;
|
|
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.NamedNodeMap;
|
|
import org.w3c.dom.Node;
|
|
import org.w3c.dom.NodeList;
|
|
import org.xml.sax.SAXException;
|
|
|
|
/**
|
|
* This test runs against a test XML file. It opens the fonts and attempts
|
|
* to shape and layout glyphs.
|
|
* Note that the test is highly environment dependent- you must have
|
|
* the same versions of the same fonts available or the test will fail.
|
|
*
|
|
* It is similar to letest which is part of ICU.
|
|
* For reference, here are some reference items:
|
|
* ICU's test file:
|
|
* http://source.icu-project.org/repos/icu/icu/trunk/source/test/testdata/letest.xml
|
|
* ICU's readme for the similar test:
|
|
* http://source.icu-project.org/repos/icu/icu/trunk/source/test/letest/readme.html
|
|
*
|
|
* @bug 8054203
|
|
* @test
|
|
* @summary manual test of layout engine behavior. Takes an XML control file.
|
|
* @compile TestLayoutVsICU.java
|
|
* @author srl
|
|
* @run main/manual
|
|
*/
|
|
public class TestLayoutVsICU {
|
|
|
|
public static boolean OPT_DRAW = false;
|
|
public static boolean OPT_VERBOSE = false;
|
|
public static boolean OPT_FAILMISSING = false;
|
|
public static boolean OPT_NOTHROW= false; // if true - don't stop on failure
|
|
|
|
public static int docs = 0; // # docs processed
|
|
public static int skipped = 0; // cases skipped due to bad font
|
|
public static int total = 0; // cases processed
|
|
public static int bad = 0; // cases with errs
|
|
|
|
public static final String XML_LAYOUT_TESTS = "layout-tests"; // top level
|
|
public static final String XML_TEST_CASE = "test-case";
|
|
public static final String XML_TEST_FONT = "test-font";
|
|
public static final String XML_TEST_TEXT = "test-text";
|
|
public static final String XML_RESULT_GLYPHS = "result-glyphs";
|
|
public static final String XML_ID = "id";
|
|
public static final String XML_SCRIPT = "script";
|
|
public static final String XML_NAME = "name";
|
|
public static final String XML_VERSION = "version";
|
|
public static final String XML_CHECKSUM = "checksum";
|
|
public static final String XML_RESULT_INDICES = "result-indices";
|
|
public static final String XML_RESULT_POSITIONS = "result-positions";
|
|
|
|
/**
|
|
* @param args
|
|
* @throws IOException
|
|
* @throws SAXException
|
|
* @throws ParserConfigurationException
|
|
*/
|
|
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
|
|
System.out.println("Java " + System.getProperty("java.version") + " from " + System.getProperty("java.vendor"));
|
|
TestLayoutVsICU tlvi = null;
|
|
for(String arg : args) {
|
|
if(arg.equals("-d")) {
|
|
OPT_DRAW = true;
|
|
} else if(arg.equals("-n")) {
|
|
OPT_NOTHROW = true;
|
|
} else if(arg.equals("-v")) {
|
|
OPT_VERBOSE = true;
|
|
} else if(arg.equals("-f")) {
|
|
OPT_FAILMISSING = true;
|
|
} else {
|
|
if(tlvi == null) {
|
|
tlvi = new TestLayoutVsICU();
|
|
}
|
|
try {
|
|
tlvi.show(arg);
|
|
} finally {
|
|
if(OPT_VERBOSE) {
|
|
System.out.println("# done with " + arg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(tlvi == null) {
|
|
throw new IllegalArgumentException("No XML input. Usage: " + TestLayoutVsICU.class.getSimpleName() + " [-d][-v][-f] letest.xml ...");
|
|
} else {
|
|
System.out.println("\n\nRESULTS:\n");
|
|
System.out.println(skipped+"\tskipped due to missing font");
|
|
System.out.println(total+"\ttested of which:");
|
|
System.out.println(bad+"\twere bad");
|
|
|
|
if(bad>0) {
|
|
throw new InternalError("One or more failure(s)");
|
|
}
|
|
}
|
|
}
|
|
|
|
String id;
|
|
|
|
private void show(String arg) throws ParserConfigurationException, SAXException, IOException {
|
|
id = "<none>";
|
|
File xmlFile = new File(arg);
|
|
if(!xmlFile.exists()) {
|
|
throw new FileNotFoundException("Can't open input XML file " + arg);
|
|
}
|
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
DocumentBuilder db = dbf.newDocumentBuilder();
|
|
if(OPT_VERBOSE) {
|
|
System.out.println("# Parsing " + xmlFile.getAbsolutePath());
|
|
}
|
|
Document doc = db.parse(xmlFile);
|
|
Element e = doc.getDocumentElement();
|
|
if(!XML_LAYOUT_TESTS.equals(e.getNodeName())) {
|
|
throw new IllegalArgumentException("Document " + xmlFile.getAbsolutePath() + " does not have <layout-tests> as its base");
|
|
}
|
|
|
|
NodeList testCases = e.getElementsByTagName(XML_TEST_CASE);
|
|
for(int caseNo=0;caseNo<testCases.getLength();caseNo++) {
|
|
final Node testCase = testCases.item(caseNo);
|
|
final Map<String,String> testCaseAttrs = attrs(testCase);
|
|
id = testCaseAttrs.get(XML_ID);
|
|
final String script = testCaseAttrs.get(XML_SCRIPT);
|
|
String testText = null;
|
|
Integer[] expectGlyphs = null;
|
|
Integer[] expectIndices = null;
|
|
Map<String,String> fontAttrs = null;
|
|
if(OPT_VERBOSE) {
|
|
System.out.println("#"+caseNo+" id="+id + ", script="+script);
|
|
}
|
|
NodeList children = testCase.getChildNodes();
|
|
for(int sub=0;sub<children.getLength();sub++) {
|
|
Node n = children.item(sub);
|
|
if(n.getNodeType()!=Node.ELEMENT_NODE) continue;
|
|
String nn = n.getNodeName();
|
|
if(nn.equals(XML_TEST_FONT)) {
|
|
fontAttrs = attrs(n);
|
|
} else if(nn.equals(XML_TEST_TEXT)) {
|
|
testText = n.getTextContent();
|
|
} else if(nn.equals(XML_RESULT_GLYPHS)) {
|
|
String hex = n.getTextContent();
|
|
expectGlyphs = parseHexArray(hex);
|
|
} else if(nn.equals(XML_RESULT_INDICES)) {
|
|
String hex = n.getTextContent();
|
|
expectIndices = parseHexArray(hex);
|
|
} else if(OPT_VERBOSE) {
|
|
System.out.println("Ignoring node " + nn);
|
|
}
|
|
}
|
|
if(fontAttrs == null) {
|
|
throw new IllegalArgumentException(id + " Missing node " + XML_TEST_FONT);
|
|
}
|
|
if(testText == null) {
|
|
throw new IllegalArgumentException(id + " Missing node " + XML_TEST_TEXT);
|
|
}
|
|
|
|
String fontName = fontAttrs.get(XML_NAME);
|
|
Font f = getFont(fontName, fontAttrs);
|
|
if(f==null) {
|
|
if(OPT_FAILMISSING) {
|
|
throw new MissingResourceException("Missing font, abort test", Font.class.getName(), fontName);
|
|
}
|
|
System.out.println("Skipping " + id + " because font is missing: " + fontName);
|
|
skipped++;
|
|
continue;
|
|
}
|
|
FontRenderContext frc = new FontRenderContext(null, true, true);
|
|
TextLayout tl = new TextLayout(testText,f,frc);
|
|
final List<GlyphVector> glyphs = new ArrayList<GlyphVector>();
|
|
Graphics2D myg2 = new Graphics2D(){
|
|
|
|
@Override
|
|
public void draw(Shape s) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean drawImage(Image img, AffineTransform xform,
|
|
ImageObserver obs) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void drawImage(BufferedImage img,
|
|
BufferedImageOp op, int x, int y) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawRenderedImage(RenderedImage img,
|
|
AffineTransform xform) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawRenderableImage(RenderableImage img,
|
|
AffineTransform xform) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawString(String str, int x, int y) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawString(String str, float x, float y) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawString(
|
|
AttributedCharacterIterator iterator, int x, int y) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawString(
|
|
AttributedCharacterIterator iterator, float x,
|
|
float y) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawGlyphVector(GlyphVector g, float x, float y) {
|
|
if(x!=0.0 || y!=0.0) {
|
|
throw new InternalError("x,y should be 0 but got " + x+","+y);
|
|
}
|
|
//System.err.println("dGV : " + g.toString() + " @ "+x+","+y);
|
|
glyphs.add(g);
|
|
}
|
|
|
|
@Override
|
|
public void fill(Shape s) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public GraphicsConfiguration getDeviceConfiguration() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setComposite(Composite comp) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setPaint(Paint paint) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setStroke(Stroke s) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setRenderingHint(Key hintKey, Object hintValue) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public Object getRenderingHint(Key hintKey) {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setRenderingHints(Map<?, ?> hints) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void addRenderingHints(Map<?, ?> hints) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public RenderingHints getRenderingHints() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void translate(int x, int y) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void translate(double tx, double ty) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void rotate(double theta) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void rotate(double theta, double x, double y) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void scale(double sx, double sy) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void shear(double shx, double shy) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void transform(AffineTransform Tx) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setTransform(AffineTransform Tx) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public AffineTransform getTransform() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Paint getPaint() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Composite getComposite() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setBackground(Color color) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public Color getBackground() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Stroke getStroke() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void clip(Shape s) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public FontRenderContext getFontRenderContext() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Graphics create() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Color getColor() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setColor(Color c) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setPaintMode() {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setXORMode(Color c1) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public Font getFont() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setFont(Font font) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public FontMetrics getFontMetrics(Font f) {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Rectangle getClipBounds() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void clipRect(int x, int y, int width, int height) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setClip(int x, int y, int width, int height) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public Shape getClip() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setClip(Shape clip) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void copyArea(int x, int y, int width, int height,
|
|
int dx, int dy) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawLine(int x1, int y1, int x2, int y2) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void fillRect(int x, int y, int width, int height) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void clearRect(int x, int y, int width, int height) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawRoundRect(int x, int y, int width,
|
|
int height, int arcWidth, int arcHeight) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void fillRoundRect(int x, int y, int width,
|
|
int height, int arcWidth, int arcHeight) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawOval(int x, int y, int width, int height) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void fillOval(int x, int y, int width, int height) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawArc(int x, int y, int width, int height,
|
|
int startAngle, int arcAngle) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void fillArc(int x, int y, int width, int height,
|
|
int startAngle, int arcAngle) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawPolyline(int[] xPoints, int[] yPoints,
|
|
int nPoints) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void drawPolygon(int[] xPoints, int[] yPoints,
|
|
int nPoints) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public void fillPolygon(int[] xPoints, int[] yPoints,
|
|
int nPoints) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean drawImage(Image img, int x, int y,
|
|
ImageObserver observer) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean drawImage(Image img, int x, int y,
|
|
int width, int height, ImageObserver observer) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean drawImage(Image img, int x, int y,
|
|
Color bgcolor, ImageObserver observer) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean drawImage(Image img, int x, int y,
|
|
int width, int height, Color bgcolor,
|
|
ImageObserver observer) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean drawImage(Image img, int dx1, int dy1,
|
|
int dx2, int dy2, int sx1, int sy1, int sx2,
|
|
int sy2, ImageObserver observer) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean drawImage(Image img, int dx1, int dy1,
|
|
int dx2, int dy2, int sx1, int sy1, int sx2,
|
|
int sy2, Color bgcolor, ImageObserver observer) {
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void dispose() {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
|
|
};
|
|
tl.draw(myg2, 0, 0);
|
|
if(glyphs.size() != 1) {
|
|
err("drew " + glyphs.size() + " times - expected 1");
|
|
total++;
|
|
bad++;
|
|
continue;
|
|
}
|
|
boolean isBad = false;
|
|
GlyphVector gv = glyphs.get(0);
|
|
|
|
// GLYPHS
|
|
int gotGlyphs[] = gv.getGlyphCodes(0, gv.getNumGlyphs(), new int[gv.getNumGlyphs()]);
|
|
|
|
int count = Math.min(gotGlyphs.length, expectGlyphs.length); // go up to this count
|
|
|
|
for(int i=0;i<count;i++) {
|
|
if(gotGlyphs[i]!=expectGlyphs[i]) {
|
|
err("@"+i+" - got \tglyph 0x" + Integer.toHexString(gotGlyphs[i]) + " wanted 0x" + Integer.toHexString(expectGlyphs[i]));
|
|
isBad=true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// INDICES
|
|
int gotIndices[] = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), new int[gv.getNumGlyphs()]);
|
|
for(int i=0;i<count;i++) {
|
|
if(gotIndices[i]!=expectIndices[i]) {
|
|
err("@"+i+" - got \tindex 0x" + Integer.toHexString(gotGlyphs[i]) + " wanted 0x" + Integer.toHexString(expectGlyphs[i]));
|
|
isBad=true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// COUNT
|
|
if(gotGlyphs.length != expectGlyphs.length) {
|
|
System.out.println("Got " + gotGlyphs.length + " wanted " + expectGlyphs.length + " glyphs");
|
|
isBad=true;
|
|
} else {
|
|
if(OPT_VERBOSE) {
|
|
System.out.println(">> OK: " + gotGlyphs.length + " glyphs");
|
|
}
|
|
}
|
|
|
|
|
|
if(isBad) {
|
|
bad++;
|
|
System.out.println("* FAIL: " + id + " /\t" + fontName);
|
|
} else {
|
|
System.out.println("* OK : " + id + " /\t" + fontName);
|
|
}
|
|
total++;
|
|
}
|
|
}
|
|
|
|
|
|
private boolean verifyFont(File f, Map<String, String> fontAttrs) {
|
|
InputStream fis = null;
|
|
String fontName = fontAttrs.get(XML_NAME);
|
|
int count=0;
|
|
try {
|
|
fis = new BufferedInputStream(new FileInputStream(f));
|
|
|
|
int i = 0;
|
|
int r;
|
|
try {
|
|
while((r=fis.read())!=-1) {
|
|
i+=(int)r;
|
|
count++;
|
|
}
|
|
} catch (IOException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
return false;
|
|
}
|
|
if(OPT_VERBOSE) {
|
|
System.out.println("for " + f.getAbsolutePath() + " chks = 0x" + Integer.toHexString(i) + " size=" + count);
|
|
}
|
|
String theirStr = fontAttrs.get("rchecksum");
|
|
|
|
String ourStr = Integer.toHexString(i).toLowerCase();
|
|
|
|
if(theirStr!=null) {
|
|
if(theirStr.startsWith("0x")) {
|
|
theirStr = theirStr.substring(2).toLowerCase();
|
|
} else {
|
|
theirStr = theirStr.toLowerCase();
|
|
}
|
|
long theirs = Integer.parseInt(theirStr, 16);
|
|
if(theirs != i) {
|
|
err("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but file said " + theirs +" (0x"+theirStr+") - perhaps a different font?");
|
|
return false;
|
|
} else {
|
|
if(OPT_VERBOSE) {
|
|
System.out.println(" rchecksum for " + fontName + " OK");
|
|
}
|
|
return true;
|
|
}
|
|
} else {
|
|
//if(OPT_VERBOSE) {
|
|
System.err.println("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but rchecksum was MISSING. Old ICU data?");
|
|
//}
|
|
}
|
|
} catch (FileNotFoundException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
return false;
|
|
} finally {
|
|
try {
|
|
fis.close();
|
|
} catch (IOException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
private Integer[] parseHexArray(String hex) {
|
|
List<Integer> ret = new ArrayList<Integer>();
|
|
String items[] = hex.split("[\\s,]");
|
|
for(String i : items) {
|
|
if(i.isEmpty()) continue;
|
|
if(i.startsWith("0x")) {
|
|
i = i.substring(2);
|
|
}
|
|
ret.add(Integer.parseInt(i, 16));
|
|
}
|
|
return ret.toArray(new Integer[0]);
|
|
}
|
|
|
|
|
|
private void err(String string) {
|
|
if(OPT_NOTHROW) {
|
|
System.out.println(id+" ERROR: " + string +" (continuing due to -n)");
|
|
} else {
|
|
throw new InternalError(id+ ": " + string);
|
|
}
|
|
}
|
|
|
|
|
|
private Font getFont(String fontName, Map<String, String> fontAttrs) {
|
|
Font f;
|
|
if(false)
|
|
try {
|
|
f = Font.getFont(fontName);
|
|
if(f!=null) {
|
|
if(OPT_VERBOSE) {
|
|
System.out.println("Loaded default path to " + fontName);
|
|
}
|
|
return f;
|
|
}
|
|
} catch(Throwable t) {
|
|
if(OPT_VERBOSE) {
|
|
t.printStackTrace();
|
|
System.out.println("problem loading font " + fontName + " - " + t.toString());
|
|
}
|
|
}
|
|
|
|
File homeDir = new File(System.getProperty("user.home"));
|
|
File fontDir = new File(homeDir, "fonts");
|
|
File fontFile = new File(fontDir, fontName);
|
|
//System.out.println("## trying " + fontFile.getAbsolutePath());
|
|
if(fontFile.canRead()) {
|
|
try {
|
|
if(!verifyFont(fontFile,fontAttrs)) {
|
|
System.out.println("Warning: failed to verify " + fontName);
|
|
}
|
|
f = Font.createFont(Font.TRUETYPE_FONT, fontFile);
|
|
if(f!=null & OPT_VERBOSE) {
|
|
System.out.println("> loaded from " + fontFile.getAbsolutePath() + " - " + f.toString());
|
|
}
|
|
return f;
|
|
} catch (FontFormatException e) {
|
|
if(OPT_VERBOSE) {
|
|
e.printStackTrace();
|
|
System.out.println("problem loading font " + fontName + " - " + e.toString());
|
|
}
|
|
} catch (IOException e) {
|
|
if(OPT_VERBOSE) {
|
|
e.printStackTrace();
|
|
System.out.println("problem loading font " + fontName + " - " + e.toString());
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
private static Map<String, String> attrs(Node testCase) {
|
|
Map<String,String> rv = new TreeMap<String,String>();
|
|
NamedNodeMap nnm = testCase.getAttributes();
|
|
for(int i=0;i<nnm.getLength();i++) {
|
|
Node n = nnm.item(i);
|
|
String k = n.getNodeName();
|
|
String v = n.getNodeValue();
|
|
rv.put(k, v);
|
|
}
|
|
return rv;
|
|
}
|
|
}
|