aboutsummaryrefslogtreecommitdiffstats
path: root/test/java/org/apache/fop
diff options
context:
space:
mode:
authorMehdi Houshmand <mehdi@apache.org>2012-06-26 09:14:25 +0000
committerMehdi Houshmand <mehdi@apache.org>2012-06-26 09:14:25 +0000
commit13a68b516babeccef8772be65b83b3de35e854e7 (patch)
tree3a88e836c8ea946307d9ab983c35f41d2ba88129 /test/java/org/apache/fop
parenta97e0be88b38483a36aa5101df08f370a5f53433 (diff)
parent63f9e3bd728b7692e577b4889de051c80fc5178c (diff)
downloadxmlgraphics-fop-13a68b516babeccef8772be65b83b3de35e854e7.tar.gz
xmlgraphics-fop-13a68b516babeccef8772be65b83b3de35e854e7.zip
Merged in trunk@1353397
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_URI_Unification@1353883 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test/java/org/apache/fop')
-rw-r--r--test/java/org/apache/fop/UtilityCodeTestSuite.java8
-rw-r--r--test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java4
-rw-r--r--test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java5
-rw-r--r--test/java/org/apache/fop/fonts/EncodingModeTestCase.java18
-rw-r--r--test/java/org/apache/fop/fonts/FOPFontsTestSuite.java42
-rw-r--r--test/java/org/apache/fop/fonts/truetype/FontFileReaderTestCase.java304
-rw-r--r--test/java/org/apache/fop/fonts/truetype/GlyfTableTestCase.java8
-rw-r--r--test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java435
-rw-r--r--test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java7
-rw-r--r--test/java/org/apache/fop/fonts/truetype/TTFSubSetFileTestCase.java76
-rw-r--r--test/java/org/apache/fop/fonts/truetype/TTFTableNameTestCase.java153
-rw-r--r--test/java/org/apache/fop/render/ps/RenderPSTestSuite.java43
-rw-r--r--test/java/org/apache/fop/render/ps/fonts/PSTTFGeneratorTestCase.java120
-rw-r--r--test/java/org/apache/fop/render/ps/fonts/PSTTFGlyphOutputStreamTestCase.java109
-rw-r--r--test/java/org/apache/fop/render/ps/fonts/PSTTFOutputStreamTestCase.java90
-rw-r--r--test/java/org/apache/fop/render/ps/fonts/PSTTFTableOutputStreamTestCase.java87
-rw-r--r--test/java/org/apache/fop/util/HexEncoderTestCase.java61
17 files changed, 1553 insertions, 17 deletions
diff --git a/test/java/org/apache/fop/UtilityCodeTestSuite.java b/test/java/org/apache/fop/UtilityCodeTestSuite.java
index cf6b8875d..762b86b14 100644
--- a/test/java/org/apache/fop/UtilityCodeTestSuite.java
+++ b/test/java/org/apache/fop/UtilityCodeTestSuite.java
@@ -28,10 +28,13 @@ import org.apache.fop.pdf.FileIDGeneratorTestCase;
import org.apache.fop.pdf.PDFDocumentGraphics2DTestCase;
import org.apache.fop.pdf.PDFEncryptionJCETestCase;
import org.apache.fop.pdf.PDFFactoryTestCase;
+import org.apache.fop.pdf.PDFNumberTestCase;
+import org.apache.fop.pdf.PDFObjectTestCase;
import org.apache.fop.traits.BorderPropsTestCase;
import org.apache.fop.util.BitmapImageUtilTestCase;
import org.apache.fop.util.ColorUtilTestCase;
import org.apache.fop.util.ElementListUtilsTestCase;
+import org.apache.fop.util.HexEncoderTestCase;
import org.apache.fop.util.XMLResourceBundleTestCase;
/**
@@ -49,7 +52,10 @@ import org.apache.fop.util.XMLResourceBundleTestCase;
PDFFactoryTestCase.class,
PDFEncryptionJCETestCase.class,
BitmapImageUtilTestCase.class,
- PDFDocumentGraphics2DTestCase.class
+ PDFDocumentGraphics2DTestCase.class,
+ PDFNumberTestCase.class,
+ PDFObjectTestCase.class,
+ HexEncoderTestCase.class
})
public class UtilityCodeTestSuite {
}
diff --git a/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java b/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java
index 35748743f..20212b002 100644
--- a/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java
+++ b/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java
@@ -47,8 +47,8 @@ public class DejaVuLGCSerifTestCase {
@Before
public void setUp() throws Exception {
File file = new File("test/resources/fonts/ttf/DejaVuLGCSerif.ttf");
- font = FontLoader.loadFont(file.toURI(), "", true, EncodingMode.AUTO, false, false,
- resolver);
+ font = FontLoader.loadFont(file.toURI(), "", true, EmbeddingMode.AUTO, EncodingMode.AUTO,
+ false, false, resolver);
}
/**
diff --git a/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java b/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java
index 2deec5a73..d156b908c 100644
--- a/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java
+++ b/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java
@@ -43,6 +43,7 @@ public class EmbedFontInfoTestCase {
private final boolean useAdvanced = false;
private final String subFontName = "Gladiator Bold";
private final EncodingMode encMode = EncodingMode.CID;
+ private final EmbeddingMode embedMode = EmbeddingMode.AUTO;
private final FontTriplet triplet = new FontTriplet(subFontName, "bold", Font.WEIGHT_BOLD);
@Before
@@ -50,7 +51,7 @@ public class EmbedFontInfoTestCase {
List<FontTriplet> triplets = new ArrayList<FontTriplet>();
triplets.add(triplet);
sut = new EmbedFontInfo(metricsURI, kerning, useAdvanced, triplets, embedURI, subFontName,
- encMode);
+ encMode, embedMode);
}
@Test
@@ -80,7 +81,7 @@ public class EmbedFontInfoTestCase {
@Test
public void testQuirkyBoundaryCasesIsEmbedded() {
sut = new EmbedFontInfo(metricsURI, kerning, useAdvanced, sut.getFontTriplets(), null,
- subFontName, encMode);
+ subFontName, encMode, embedMode);
sut.setEmbedded(true);
assertFalse(sut.isEmbedded());
diff --git a/test/java/org/apache/fop/fonts/EncodingModeTestCase.java b/test/java/org/apache/fop/fonts/EncodingModeTestCase.java
index 1ec22e1ef..8cab9eb8b 100644
--- a/test/java/org/apache/fop/fonts/EncodingModeTestCase.java
+++ b/test/java/org/apache/fop/fonts/EncodingModeTestCase.java
@@ -19,10 +19,13 @@
package org.apache.fop.fonts;
-import static org.junit.Assert.assertEquals;
-
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link EncodingMode}.
+ */
public class EncodingModeTestCase {
@Test
@@ -34,8 +37,13 @@ public class EncodingModeTestCase {
@Test
public void testGetValue() {
- assertEquals(EncodingMode.AUTO, EncodingMode.getEncodingMode("auto"));
- assertEquals(EncodingMode.SINGLE_BYTE, EncodingMode.getEncodingMode("single-byte"));
- assertEquals(EncodingMode.CID, EncodingMode.getEncodingMode("cid"));
+ assertEquals(EncodingMode.AUTO, EncodingMode.getValue("auto"));
+ assertEquals(EncodingMode.SINGLE_BYTE, EncodingMode.getValue("single-byte"));
+ assertEquals(EncodingMode.CID, EncodingMode.getValue("cid"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getValueMustCheckForIllegalArguments() {
+ EncodingMode.getValue("fail");
}
}
diff --git a/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java b/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java
new file mode 100644
index 000000000..8e1a0040d
--- /dev/null
+++ b/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import org.apache.fop.fonts.truetype.FontFileReaderTestCase;
+import org.apache.fop.fonts.truetype.TTFFileTestCase;
+import org.apache.fop.fonts.truetype.TTFSubSetFileTestCase;
+import org.apache.fop.fonts.truetype.TTFTableNameTestCase;
+
+/**
+ * A test suite designed for org.apache.fop.fonts.*
+ */
+@RunWith(Suite.class)
+@SuiteClasses({
+ EncodingModeTestCase.class,
+ FontFileReaderTestCase.class,
+ TTFFileTestCase.class,
+ TTFSubSetFileTestCase.class,
+ TTFTableNameTestCase.class })
+public final class FOPFontsTestSuite {
+}
diff --git a/test/java/org/apache/fop/fonts/truetype/FontFileReaderTestCase.java b/test/java/org/apache/fop/fonts/truetype/FontFileReaderTestCase.java
new file mode 100644
index 000000000..5c1fec175
--- /dev/null
+++ b/test/java/org/apache/fop/fonts/truetype/FontFileReaderTestCase.java
@@ -0,0 +1,304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts.truetype;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * A test class for org.apache.fop.truetype.FontFileReader
+ */
+public class FontFileReaderTestCase {
+ private FontFileReader fontReader;
+ private final InputStream in;
+ private final byte[] byteArray;
+
+ /**
+ * Constructor - initialises an array that only needs to be created once. It creates a byte[]
+ * of form { 0x00, 0x01, 0x02, 0x03..., 0xff};
+ */
+ public FontFileReaderTestCase() {
+ byteArray = new byte[256];
+ for (int i = 0; i < 256; i++) {
+ byteArray[i] = (byte) i;
+ }
+ in = new ByteArrayInputStream(byteArray);
+ }
+
+ /**
+ * sets up the test subject object for testing.
+ */
+ @Before
+ public void setUp() {
+ try {
+ fontReader = new FontFileReader(in);
+ } catch (Exception e) {
+ fail("Error: " + e.getMessage());
+ }
+ }
+
+ /**
+ * the "destructor" method.
+ *
+ */
+ public void tearDown() {
+ fontReader = null;
+ }
+
+ /**
+ * Test readTTFByte()
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFByte() throws IOException {
+ for (int i = 0; i < 256; i++) {
+ assertEquals((byte) i, fontReader.readTTFByte());
+ }
+ }
+
+ /**
+ * Test seekSet() - check that it moves to the correct position and enforce a failure case.
+ * @throws IOException exception
+ */
+ @Test
+ public void testSeekSet() throws IOException {
+ fontReader.seekSet(10);
+ assertEquals(10, fontReader.readTTFByte());
+ try {
+ fontReader.seekSet(257);
+ fail("FileFontReaderTest Failed testSeekSet");
+ } catch (IOException e) {
+ // Passed
+ }
+ }
+
+ /**
+ * Test skip() - check that it moves to the correct position and enforce a failure case.
+ * @throws IOException exception
+ */
+ @Test
+ public void testSkip() throws IOException {
+ fontReader.skip(100);
+ assertEquals(100, fontReader.readTTFByte());
+ try {
+ // 100 (seekAdd) + 1 (read() = 1 byte) + 156 = 257
+ fontReader.skip(156);
+ fail("FileFontReaderTest Failed testSkip");
+ } catch (IOException e) {
+ // Passed
+ }
+ }
+
+ /**
+ * Test getCurrentPos() - 3 checks:
+ * 1) test with seekSet(int)
+ * 2) test with skip(int)
+ * 3) test with a readTTFByte() (this moves the position by the size of the data being read)
+ * @throws IOException exception
+ */
+ @Test
+ public void testGetCurrentPos() throws IOException {
+ fontReader.seekSet(10);
+ fontReader.skip(100);
+ assertEquals(110, fontReader.getCurrentPos());
+ fontReader.readTTFByte();
+ assertEquals(111, fontReader.getCurrentPos());
+ }
+
+ /**
+ * Test getFileSize()
+ */
+ @Test
+ public void testGetFileSize() {
+ assertEquals(256, fontReader.getFileSize());
+ }
+
+ /**
+ * Test readTTFUByte()
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFUByte() throws IOException {
+ for (int i = 0; i < 256; i++) {
+ assertEquals(i, fontReader.readTTFUByte());
+ }
+ }
+
+ /**
+ * Test readTTFShort() - Test positive and negative numbers (two's compliment).
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFShort() throws IOException {
+ // 0x0001 = 1
+ assertEquals("Should have been 1 (0x0001)", 1, fontReader.readTTFShort());
+ // 0x0203 = 515
+ assertEquals(515, fontReader.readTTFShort());
+ // now test negative numbers
+ fontReader.seekSet(250);
+ // 0xfafb
+ assertEquals(-1285, fontReader.readTTFShort());
+ }
+
+ /**
+ * Test readTTFUShort() - Test positive and potentially negative numbers (two's compliment).
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFUShort() throws IOException {
+ // 0x0001
+ assertEquals(1, fontReader.readTTFUShort());
+ // 0x0203
+ assertEquals(515, fontReader.readTTFUShort());
+ // test potential negatives
+ fontReader.seekSet(250);
+ // 0xfafb
+ assertEquals((250 << 8) + 251, fontReader.readTTFUShort());
+ }
+
+ /**
+ * Test readTTFShort(int) - test reading ahead of current position and behind current position
+ * and in both cases ensure that our current position isn't changed.
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFShortWithArg() throws IOException {
+ // 0x6465
+ assertEquals(25701, fontReader.readTTFShort(100));
+ assertEquals(0, fontReader.getCurrentPos());
+ // read behind current position (and negative)
+ fontReader.seekSet(255);
+ // 0xfafb
+ assertEquals(-1285, fontReader.readTTFShort(250));
+ assertEquals(255, fontReader.getCurrentPos());
+ }
+
+ /**
+ * Test readTTFUShort(int arg) - test reading ahead of current position and behind current
+ * position and in both cases ensure that our current position isn't changed.
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFUShortWithArg() throws IOException {
+ // 0x6465
+ assertEquals(25701, fontReader.readTTFUShort(100));
+ assertEquals(0, fontReader.getCurrentPos());
+ // read behind current position (and potential negative)
+ fontReader.seekSet(255);
+ // 0xfafb
+ assertEquals(64251, fontReader.readTTFUShort(250));
+ assertEquals(255, fontReader.getCurrentPos());
+ }
+
+ /**
+ * Test readTTFLong()
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFLong() throws IOException {
+ // 0x00010203
+ assertEquals(66051, fontReader.readTTFLong());
+ // test negative numbers
+ fontReader.seekSet(250);
+ // 0xf0f1f2f3
+ assertEquals(-84148995, fontReader.readTTFLong());
+ }
+
+ /**
+ * Test readTTFULong()
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFULong() throws IOException {
+ // 0x00010203
+ assertEquals(66051, fontReader.readTTFULong());
+ // test negative numbers
+ fontReader.seekSet(250);
+ // 0xfafbfcfd
+ assertEquals(4210818301L, fontReader.readTTFULong());
+ }
+
+ /**
+ * Test readTTFString() - there are two paths to test here:
+ * 1) A null terminated string
+ * 2) A string not terminated with a null (we expect this to throw an EOFException)
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFString() throws IOException {
+ byte[] strByte = {(byte)'t', (byte)'e', (byte)'s', (byte)'t', 0x00};
+ fontReader = new FontFileReader(new ByteArrayInputStream(strByte));
+ assertEquals("test", fontReader.readTTFString());
+ try {
+ // not NUL terminated
+ byte[] strByteNoNull = {(byte)'t', (byte)'e', (byte)'s', (byte)'t'};
+ fontReader = new FontFileReader(new ByteArrayInputStream(strByteNoNull));
+ assertEquals("test", fontReader.readTTFString());
+ fail("FontFileReaderTest testReadTTFString Fails.");
+ } catch (EOFException e) {
+ // Pass
+ }
+ }
+
+ /**
+ * Test readTTFString(int arg)
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadTTFStringIntArg() throws IOException {
+ byte[] strByte = {(byte)'t', (byte)'e', (byte)'s', (byte)'t'};
+ fontReader = new FontFileReader(new ByteArrayInputStream(strByte));
+ assertEquals("test", fontReader.readTTFString(4));
+ try {
+ fontReader = new FontFileReader(new ByteArrayInputStream(strByte));
+ assertEquals("test", fontReader.readTTFString(5));
+ fail("FontFileReaderTest testReadTTFStringIntArg Fails.");
+ } catch (EOFException e) {
+ // Pass
+ }
+ }
+
+ /**
+ * Test readTTFString(int arg1, int arg2)
+ */
+ public void testReadTTFString2IntArgs() {
+ // currently the same as above
+ }
+
+ /**
+ * Test getBytes()
+ * @throws IOException exception
+ */
+ @Test
+ public void testGetBytes() throws IOException {
+ byte[] retrievedBytes = fontReader.getBytes(0, 256);
+ assertTrue(Arrays.equals(byteArray, retrievedBytes));
+ }
+}
diff --git a/test/java/org/apache/fop/fonts/truetype/GlyfTableTestCase.java b/test/java/org/apache/fop/fonts/truetype/GlyfTableTestCase.java
index 3f4d859e7..204803a32 100644
--- a/test/java/org/apache/fop/fonts/truetype/GlyfTableTestCase.java
+++ b/test/java/org/apache/fop/fonts/truetype/GlyfTableTestCase.java
@@ -148,10 +148,10 @@ public class GlyfTableTestCase {
private void setupSubsetReader(Map<Integer, Integer> glyphs) throws IOException {
TTFSubSetFile fontFile = new TTFSubSetFile();
- byte[] subsetFont = fontFile.readFont(originalFontReader, "Deja", glyphs);
- InputStream inputStream = new ByteArrayInputStream(subsetFont);
- subsetReader = new FontFileReader(inputStream);
- inputStream.close();
+ fontFile.readFont(originalFontReader, "Deja", glyphs);
+ byte[] subsetFont = fontFile.getFontSubset();
+ InputStream intputStream = new ByteArrayInputStream(subsetFont);
+ subsetReader = new FontFileReader(intputStream);
}
private void readLoca() throws IOException {
diff --git a/test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java b/test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java
new file mode 100644
index 000000000..e04347032
--- /dev/null
+++ b/test/java/org/apache/fop/fonts/truetype/TTFFileTestCase.java
@@ -0,0 +1,435 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts.truetype;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Class for testing org.apache.fop.fonts.truetype.TTFFile
+ */
+public class TTFFileTestCase {
+ // We only want to initialize the FontFileReader once (for performance reasons)
+ /** The truetype font file (DejaVuLGCSerif) */
+ protected final TTFFile dejavuTTFFile;
+ /** The FontFileReader for ttfFile (DejaVuLGCSerif) */
+ protected final FontFileReader dejavuReader;
+ /** The truetype font file (DroidSansMono) */
+ protected final TTFFile droidmonoTTFFile;
+ /** The FontFileReader for ttfFile (DroidSansMono) */
+ protected final FontFileReader droidmonoReader;
+
+
+ /**
+ * Constructor initialises FileFontReader to
+ * @throws IOException exception
+ */
+ public TTFFileTestCase() throws IOException {
+ dejavuTTFFile = new TTFFile();
+ InputStream dejaStream = new FileInputStream("test/resources/fonts/ttf/DejaVuLGCSerif.ttf");
+ dejavuReader = new FontFileReader(dejaStream);
+ dejavuTTFFile.readFont(dejavuReader);
+ dejaStream.close();
+
+ InputStream droidStream = new FileInputStream("test/resources/fonts/ttf/DroidSansMono.ttf");
+
+ droidmonoTTFFile = new TTFFile();
+ droidmonoReader = new FontFileReader(droidStream);
+ droidmonoTTFFile.readFont(droidmonoReader);
+ droidStream.close();
+ }
+
+ /**
+ * Test convertTTFUnit2PDFUnit() - The units per em retrieved reading the HEAD table from
+ * the font file. (DroidSansMono has the same units per em as DejaVu so no point testing it)
+ */
+ @Test
+ public void testConvertTTFUnit2PDFUnit() {
+ // DejaVu has 2048 units per em (PDF works in millipts, thus the 1000)
+ // test rational number
+ assertEquals(1000, dejavuTTFFile.convertTTFUnit2PDFUnit(2048));
+ // test smallest case, this should = 0.488 (round down to 0)
+ assertEquals(0, dejavuTTFFile.convertTTFUnit2PDFUnit(1));
+ // this should round up, but since it's millipts...
+ assertEquals(0, dejavuTTFFile.convertTTFUnit2PDFUnit(2));
+ // ensure behaviour is the same for negative numbers
+ assertEquals(0, dejavuTTFFile.convertTTFUnit2PDFUnit(-0));
+ assertEquals(-1000, dejavuTTFFile.convertTTFUnit2PDFUnit(-2048));
+ assertEquals(0, dejavuTTFFile.convertTTFUnit2PDFUnit(-1));
+ assertEquals(0, dejavuTTFFile.convertTTFUnit2PDFUnit(-2));
+ }
+
+ /**
+ * Test checkTTC()
+ * @throws IOException exception
+ */
+ @Test
+ public void testCheckTTC() throws IOException {
+ // DejaVu is not a TTC, thus this returns true
+ assertTrue(dejavuTTFFile.checkTTC(""));
+ assertTrue(droidmonoTTFFile.checkTTC(""));
+ /*
+ * Cannot reasonably test the rest of this method without an actual truetype collection
+ * because all methods in FontFileReader are "final" and thus mocking isn't possible.
+ */
+ }
+
+ /**
+ * Test getAnsiKerning() - Tests values retrieved from the kern table in the font file.
+ */
+ @Test
+ public void testGetAnsiKerning() {
+ Map<Integer, Map<Integer, Integer>> ansiKerning = dejavuTTFFile.getKerning();
+ if (ansiKerning.isEmpty()) {
+ fail();
+ }
+ Integer k1 = ansiKerning.get(Integer.valueOf('A')).get(
+ Integer.valueOf('T'));
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(-112), k1.intValue());
+ Integer k2 = ansiKerning.get(Integer.valueOf('Y')).get(Integer.valueOf('u'));
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(-178), k2.intValue());
+
+ // DroidSansMono doens't have kerning (it's mono-spaced)
+ ansiKerning = droidmonoTTFFile.getAnsiKerning();
+ if (!ansiKerning.isEmpty()) {
+ fail("DroidSansMono shouldn't have any kerning data.");
+ }
+ }
+
+ /**
+ * Test getCapHeight - there are several paths to test:
+ * 1) The PCLT table (if present)
+ * 2) The yMax (3rd) value, for the bounding box, for 'H' in the glyf table.
+ * if not the above:
+ * 3) The caps height in the OS/2 table
+ * Tests values retrieved from analysing the font file.
+ */
+ @Test
+ public void testGetCapHeight() {
+ // DejaVu doesn't have the PCLT table and so these have to be guessed
+ // The height is approximated to be the height of the "H" which for
+ // Deja = 1493 TTFunits
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(1493), dejavuTTFFile.getCapHeight());
+ // DroidSansMono doesn't have a PCLT table either
+ // height of "H" = 1462
+ assertEquals(droidmonoTTFFile.convertTTFUnit2PDFUnit(1462),
+ droidmonoTTFFile.getCapHeight());
+ }
+
+ /**
+ * Test getCharSetName() - check that it returns "WinAnsiEncoding".
+ */
+ @Test
+ public void testGetCharSetName() {
+ assertTrue("WinAnsiEncoding".equals(dejavuTTFFile.getCharSetName()));
+ assertTrue("WinAnsiEncoding".equals(droidmonoTTFFile.getCharSetName()));
+ }
+
+ /**
+ * Test getCharWidth() - Test values retrieved from the metrics in the glyf table in
+ * the font file.
+ */
+ @Test
+ public void testGetCharWidth() {
+ // Arbitrarily test a few values:
+ // The width of "H" (Unicode index 0x0048) is 1786
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(1786), dejavuTTFFile.getCharWidth(0x48));
+ // The width of "i" (unicode index 0x0069) is 655 TTFunits
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(655), dejavuTTFFile.getCharWidth(0x69));
+ // final check, "!" (unicode index 0x0021) is 823 TTFunits
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(823), dejavuTTFFile.getCharWidth(0x21));
+
+ // All the glyphs should be the same width in DroidSansMono (mono-spaced)
+ int charWidth = droidmonoTTFFile.convertTTFUnit2PDFUnit(1229);
+ for (int i = 0; i < 255; i++) {
+ assertEquals(charWidth, droidmonoTTFFile.getCharWidth(i));
+ }
+ }
+
+ /**
+ * TODO: add implementation to this test
+ */
+ public void testGetCMaps() {
+ }
+
+ /**
+ * Test getFamilyNames() - Test value retrieved from the name table in the font file.
+ */
+ @Test
+ public void testGetFamilyNames() {
+ assertEquals(1, dejavuTTFFile.getFamilyNames().size());
+ for (String name : dejavuTTFFile.getFamilyNames()) {
+ assertEquals("DejaVu LGC Serif", name);
+ }
+ assertEquals(1, droidmonoTTFFile.getFamilyNames().size());
+ for (String name : droidmonoTTFFile.getFamilyNames()) {
+ assertEquals("Droid Sans Mono", name);
+ }
+ }
+
+ /**
+ * Test getFirstChar() - TODO: implement a more intelligent test here.
+ */
+ @Test
+ public void testGetFirstChar() {
+ // Not really sure how to test this intelligently
+ assertEquals(0, dejavuTTFFile.getFirstChar());
+ assertEquals(0, droidmonoTTFFile.getFirstChar());
+ }
+
+ /**
+ * Test getFlags() - Test values retrieved from the POST table in the font file.
+ */
+ @Test
+ public void testGetFlags() {
+ /* DejaVu flags are:
+ * italic angle = 0
+ * fixed pitch = 0
+ * has serifs = true (default value; this font doesn't have a PCLT table)
+ */
+ int flags = dejavuTTFFile.getFlags();
+ assertEquals(0, flags & 64); // Italics angle = 0
+ assertEquals(32, flags & 32); // Adobe standard charset
+ assertEquals(0, flags & 2); // fixed pitch = 0
+ assertEquals(1, flags & 1); // has serifs = 1 (true)
+ /*
+ * Droid flags are:
+ * italic angle = 0
+ * fixed pitch = 1
+ * has serifs = true (default value; this font doesn't have a PCLT table)
+ */
+ flags = droidmonoTTFFile.getFlags();
+ assertEquals(0, flags & 64);
+ assertEquals(32, flags & 32);
+ assertEquals(2, flags & 2);
+ assertEquals(1, flags & 1);
+ }
+
+ /**
+ * Test getFontBBox() - Test values retrieved from values in the HEAD table in the font file.
+ */
+ @Test
+ public void testGetFontBBox() {
+ int[] bBox = dejavuTTFFile.getFontBBox();
+ /*
+ * The head table has the following values(DejaVu):
+ * xmin = -1576, ymin = -710, xmax = 3439, ymax = 2544
+ */
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(-1576), bBox[0]);
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(-710), bBox[1]);
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(3439), bBox[2]);
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(2544), bBox[3]);
+ /*
+ * The head table has the following values (DroidSansMono):
+ * xmin = -312, ymin= -555, xmax = 1315, ymax = 2163
+ */
+ bBox = droidmonoTTFFile.getFontBBox();
+ assertEquals(droidmonoTTFFile.convertTTFUnit2PDFUnit(-312), bBox[0]);
+ assertEquals(droidmonoTTFFile.convertTTFUnit2PDFUnit(-555), bBox[1]);
+ assertEquals(droidmonoTTFFile.convertTTFUnit2PDFUnit(1315), bBox[2]);
+ assertEquals(droidmonoTTFFile.convertTTFUnit2PDFUnit(2163), bBox[3]);
+ }
+
+ /**
+ * Test getFullName() - Test value retrieved from the name table in the font file.
+ */
+ @Test
+ public void testGetFullName() {
+ assertEquals("DejaVu LGC Serif", dejavuTTFFile.getFullName());
+ assertEquals("Droid Sans Mono", droidmonoTTFFile.getFullName());
+ }
+
+ /**
+ * Test getGlyphName - Test value retrieved from the POST table in the font file.
+ */
+ @Test
+ public void testGetGlyphName() {
+ assertEquals("H", dejavuTTFFile.getGlyphName(43));
+ assertEquals("H", droidmonoTTFFile.getGlyphName(43));
+ }
+
+ /**
+ * Test getItalicAngle() - Test value retrieved from the POST table in the font file.
+ */
+ @Test
+ public void testGetItalicAngle() {
+ assertEquals("0", dejavuTTFFile.getItalicAngle());
+ assertEquals("0", droidmonoTTFFile.getItalicAngle());
+ }
+
+ /**
+ * Test getKerning() - Test values retrieved from the kern table in the font file.
+ */
+ @Test
+ public void testGetKerning() {
+ Map<Integer, Map<Integer, Integer>> kerning = dejavuTTFFile.getKerning();
+ if (kerning.isEmpty()) {
+ fail();
+ }
+ Integer k1 = kerning.get(Integer.valueOf('A')).get(Integer.valueOf('T'));
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(-112), k1.intValue());
+ Integer k2 = kerning.get(Integer.valueOf('K')).get(Integer.valueOf('u'));
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(-45), k2.intValue());
+
+ // DroidSansMono has no kerning data (mono-spaced)
+ kerning = droidmonoTTFFile.getKerning();
+ if (!kerning.isEmpty()) {
+ fail("DroidSansMono shouldn't have any kerning data");
+ }
+ }
+
+ /**
+ * Test lastChar() - TODO: implement a more intelligent test
+ */
+ @Test
+ public void testLastChar() {
+ assertEquals(0xff, dejavuTTFFile.getLastChar());
+ assertEquals(0xff, droidmonoTTFFile.getLastChar());
+ }
+
+ /**
+ * Test getLowerCaseAscent() - There are several paths to test:
+ * 1) The values in the HHEA table (see code)
+ * 2) Fall back to values from the OS/2 table
+ * Test values retrieved from the font file.
+ */
+ @Test
+ public void testGetLowerCaseAscent() {
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(1556),
+ dejavuTTFFile.getLowerCaseAscent());
+ // Curiously the same value
+ assertEquals(droidmonoTTFFile.convertTTFUnit2PDFUnit(1556),
+ droidmonoTTFFile.getLowerCaseAscent());
+ }
+
+ /**
+ * Test getPostScriptName() - Test values retrieved from the post table in the font file.
+ */
+ @Test
+ public void testGetPostScriptName() {
+ assertEquals(PostScriptVersion.V2, dejavuTTFFile.getPostScriptVersion());
+ assertEquals(PostScriptVersion.V2, droidmonoTTFFile.getPostScriptVersion());
+ }
+
+ /**
+ * Test getStemV() - Undefined.
+ */
+ @Test
+ public void testGetStemV() {
+ // Undefined
+ assertEquals("0", dejavuTTFFile.getStemV());
+ assertEquals("0", droidmonoTTFFile.getStemV());
+ }
+
+ /**
+ * Test getSubFamilyName() - Test values retrieved from the name table in the font file.
+ */
+ @Test
+ public void testGetSubFamilyName() {
+ assertEquals("Book", dejavuTTFFile.getSubFamilyName());
+ assertEquals("Regular", droidmonoTTFFile.getSubFamilyName());
+ }
+
+ /**
+ * Test getTTCnames() - TODO: add implementation with TTC font.
+ */
+ public void testGetTTCnames() {
+ // Can't test with with DejaVu since it's not a TrueType Collection
+ }
+
+ /**
+ * Test getWeightClass() - Test value retrieved from the OS/2 table in the font file.
+ */
+ @Test
+ public void testGetWeightClass() {
+ // Retrieved from OS/2 table
+ assertEquals(400, dejavuTTFFile.getWeightClass());
+ assertEquals(400, droidmonoTTFFile.getWeightClass());
+ }
+
+ /**
+ * Test getWidths() - Test values retrieved from the hmtx table in the font file.
+ */
+ @Test
+ public void testGetWidths() {
+ int[] widths = dejavuTTFFile.getWidths();
+ // using the width of 'A' index = 36
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(1479), widths[36]);
+ // using the width of '|' index = 95
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(690), widths[95]);
+ widths = droidmonoTTFFile.getWidths();
+ // DroidSansMono should have all widths the same size (mono-spaced)
+ int width = droidmonoTTFFile.convertTTFUnit2PDFUnit(1229);
+ for (int i = 0; i < 255; i++) {
+ assertEquals(width, widths[i]);
+ }
+ }
+
+ /**
+ * Test getXHeight() - There are several paths to test:
+ * 1) The PCLT table (if available)
+ * 2) The yMax for the bounding box for 'x' in the glyf table.
+ * Fall back:
+ * 3) The xheight in the OS/2 table.
+ */
+ @Test
+ public void testGetXHeight() {
+ // Since there's no PCLT table, the height of 'x' is used for both DejaVu and DroidSansMono
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(1064), dejavuTTFFile.getXHeight());
+ assertEquals(droidmonoTTFFile.convertTTFUnit2PDFUnit(1098), droidmonoTTFFile.getXHeight());
+ }
+
+ /**
+ * Test isCFF() - TODO: add test for a CFF font.
+ */
+ @Test
+ public void testIsCFF() {
+ // Neither DejaVu nor DroidSansMono are a compact format font
+ assertEquals(false, dejavuTTFFile.isCFF());
+ assertEquals(false, droidmonoTTFFile.isCFF());
+ }
+
+ /**
+ * Test isEmbeddable() - Test value retrieved from the OS/2 table in the font file.
+ */
+ @Test
+ public void testIsEmbeddable() {
+ // Dejavu and DroidSansMono are both embeddable
+ assertEquals(true, dejavuTTFFile.isEmbeddable());
+ assertEquals(true, droidmonoTTFFile.isEmbeddable());
+ }
+
+ /**
+ * Test readFont() - Add implementation if necessary.
+ */
+ public void testReadFont() {
+ // I'm pretty sure we've tested this with all the other tests
+ }
+}
diff --git a/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java b/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java
index b1dc571f9..063d8c781 100644
--- a/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java
+++ b/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java
@@ -27,6 +27,7 @@ import org.junit.Test;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
+import org.apache.fop.fonts.EmbeddingMode;
import org.apache.fop.fonts.EncodingMode;
import static org.junit.Assert.assertFalse;
@@ -49,12 +50,12 @@ public class TTFFontLoaderTestCase {
boolean useKerning = true;
TTFFontLoader fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded,
- EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resourceResolver);
+ EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resourceResolver);
assertTrue(fontLoader.getFont().hasKerningInfo());
useKerning = false;
- fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, EncodingMode.AUTO,
- useKerning, useComplexScriptFeatures, resourceResolver);
+ fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, EmbeddingMode.AUTO,
+ EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resourceResolver);
assertFalse(fontLoader.getFont().hasKerningInfo());
}
}
diff --git a/test/java/org/apache/fop/fonts/truetype/TTFSubSetFileTestCase.java b/test/java/org/apache/fop/fonts/truetype/TTFSubSetFileTestCase.java
new file mode 100644
index 000000000..16bedad8d
--- /dev/null
+++ b/test/java/org/apache/fop/fonts/truetype/TTFSubSetFileTestCase.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts.truetype;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This class tests TTFSubSetFile
+ * TODO: Test with more than just a single font
+ */
+public class TTFSubSetFileTestCase extends TTFFileTestCase {
+ private TTFSubSetFile ttfSubset;
+ private byte[] subset;
+ /**
+ * Constructor
+ * @throws IOException exception
+ */
+ public TTFSubSetFileTestCase() throws IOException {
+ super();
+ }
+
+ /**
+ * setUp()
+ * @exception IOException file read error
+ */
+ @Before
+ public void setUp() throws IOException {
+ ttfSubset = new TTFSubSetFile();
+ Map<Integer, Integer> glyphs = new HashMap<Integer, Integer>();
+ for (int i = 0; i < 255; i++) {
+ glyphs.put(i, i);
+ }
+ ttfSubset.readFont(dejavuReader, "DejaVu", glyphs);
+ subset = ttfSubset.getFontSubset();
+ }
+ /**
+ * Test readFont(FontFileReader, String, Map) - Reads the font and tests the output by injecting
+ * it into a TTFFile object to check the validity of the file as a font. This currently doesn't
+ * create a cmap table, and so the font doesn't contain ALL of the mandatory tables.
+ * @throws IOException exception
+ */
+ @Test
+ public void testReadFont3Args() throws IOException {
+
+ ByteArrayInputStream byteArray = new ByteArrayInputStream(subset);
+ dejavuTTFFile.readFont(new FontFileReader(byteArray));
+ // Test a couple arbitrary values
+ assertEquals(dejavuTTFFile.convertTTFUnit2PDFUnit(-1576), dejavuTTFFile.getFontBBox()[0]);
+ assertEquals(dejavuTTFFile.getFullName(), "DejaVu LGC Serif");
+ }
+}
diff --git a/test/java/org/apache/fop/fonts/truetype/TTFTableNameTestCase.java b/test/java/org/apache/fop/fonts/truetype/TTFTableNameTestCase.java
new file mode 100644
index 000000000..b9066dc2d
--- /dev/null
+++ b/test/java/org/apache/fop/fonts/truetype/TTFTableNameTestCase.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts.truetype;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * This class tests the enum org.apache.fop.fonts.truetype.TTFTableName
+ *
+ */
+public class TTFTableNameTestCase {
+ /**
+ * Test getName() - tests that the getName() method returns the expected String as expected in
+ * the Directory Table.
+ * @exception IllegalAccessException error
+ */
+ @Test
+ public void testGetName() throws IllegalAccessException {
+ assertEquals("tableDirectory", TTFTableName.TABLE_DIRECTORY.getName());
+ assertEquals("EBDT", TTFTableName.EBDT.getName());
+ assertEquals("EBLC", TTFTableName.EBLC.getName());
+ assertEquals("EBSC", TTFTableName.EBSC.getName());
+ assertEquals("FFTM", TTFTableName.FFTM.getName());
+ assertEquals("GDEF", TTFTableName.GDEF.getName());
+ assertEquals("GPOS", TTFTableName.GPOS.getName());
+ assertEquals("GSUB", TTFTableName.GSUB.getName());
+ assertEquals("LTSH", TTFTableName.LTSH.getName());
+ assertEquals("OS/2", TTFTableName.OS2.getName());
+ assertEquals("PCLT", TTFTableName.PCLT.getName());
+ assertEquals("VDMX", TTFTableName.VDMX.getName());
+ assertEquals("cmap", TTFTableName.CMAP.getName());
+ assertEquals("cvt ", TTFTableName.CVT.getName());
+ assertEquals("fpgm", TTFTableName.FPGM.getName());
+ assertEquals("gasp", TTFTableName.GASP.getName());
+ assertEquals("glyf", TTFTableName.GLYF.getName());
+ assertEquals("hdmx", TTFTableName.HDMX.getName());
+ assertEquals("head", TTFTableName.HEAD.getName());
+ assertEquals("hhea", TTFTableName.HHEA.getName());
+ assertEquals("hmtx", TTFTableName.HMTX.getName());
+ assertEquals("kern", TTFTableName.KERN.getName());
+ assertEquals("loca", TTFTableName.LOCA.getName());
+ assertEquals("maxp", TTFTableName.MAXP.getName());
+ assertEquals("name", TTFTableName.NAME.getName());
+ assertEquals("post", TTFTableName.POST.getName());
+ assertEquals("prep", TTFTableName.PREP.getName());
+ assertEquals("vhea", TTFTableName.VHEA.getName());
+ assertEquals("vmtx", TTFTableName.VMTX.getName());
+ // make sure it works with other table names
+ TTFTableName test = TTFTableName.getValue("test");
+ assertEquals("test", test.getName());
+ }
+
+ /**
+ * Test getValue(String) - tests that the getValue(String) method returns the expected
+ * TTFTableNames value when it is given a String (name of a table).
+ * @exception IllegalAccessException error
+ */
+ @Test
+ public void testGetValue() throws IllegalAccessException {
+ assertEquals(TTFTableName.EBDT, TTFTableName.getValue("EBDT"));
+ assertEquals(TTFTableName.EBLC, TTFTableName.getValue("EBLC"));
+ assertEquals(TTFTableName.EBSC, TTFTableName.getValue("EBSC"));
+ assertEquals(TTFTableName.FFTM, TTFTableName.getValue("FFTM"));
+ assertEquals(TTFTableName.LTSH, TTFTableName.getValue("LTSH"));
+ assertEquals(TTFTableName.OS2, TTFTableName.getValue("OS/2"));
+ assertEquals(TTFTableName.PCLT, TTFTableName.getValue("PCLT"));
+ assertEquals(TTFTableName.VDMX, TTFTableName.getValue("VDMX"));
+ assertEquals(TTFTableName.CMAP, TTFTableName.getValue("cmap"));
+ assertEquals(TTFTableName.CVT, TTFTableName.getValue("cvt "));
+ assertEquals(TTFTableName.FPGM, TTFTableName.getValue("fpgm"));
+ assertEquals(TTFTableName.GASP, TTFTableName.getValue("gasp"));
+ assertEquals(TTFTableName.GLYF, TTFTableName.getValue("glyf"));
+ assertEquals(TTFTableName.HDMX, TTFTableName.getValue("hdmx"));
+ assertEquals(TTFTableName.HEAD, TTFTableName.getValue("head"));
+ assertEquals(TTFTableName.HHEA, TTFTableName.getValue("hhea"));
+ assertEquals(TTFTableName.HMTX, TTFTableName.getValue("hmtx"));
+ assertEquals(TTFTableName.KERN, TTFTableName.getValue("kern"));
+ assertEquals(TTFTableName.LOCA, TTFTableName.getValue("loca"));
+ assertEquals(TTFTableName.MAXP, TTFTableName.getValue("maxp"));
+ assertEquals(TTFTableName.NAME, TTFTableName.getValue("name"));
+ assertEquals(TTFTableName.POST, TTFTableName.getValue("post"));
+ assertEquals(TTFTableName.PREP, TTFTableName.getValue("prep"));
+ assertEquals(TTFTableName.VHEA, TTFTableName.getValue("vhea"));
+ assertEquals(TTFTableName.VMTX, TTFTableName.getValue("vmtx"));
+ // Test that we can store a random table name and it will not fail or throw an error.
+ TTFTableName test = TTFTableName.getValue("random");
+ assertTrue(test instanceof TTFTableName);
+ }
+
+ /**
+ * This class overrides hashCode() - we need to ensure it works properly by instantiating two
+ * objects and comparing their hash-codes.
+ * @exception IllegalAccessException error
+ */
+ @Test
+ public void testHashCode() throws IllegalAccessException {
+ TTFTableName a = TTFTableName.getValue("testObject");
+ TTFTableName b = TTFTableName.getValue("testObject");
+ assertTrue(a.hashCode() == b.hashCode());
+ TTFTableName c = TTFTableName.getValue("fail");
+ assertFalse(a.hashCode() == c.hashCode());
+ }
+
+ /**
+ * This class overrides equals(object) - we need to test:
+ * 1) Reflexivity
+ * 2) Symmetry
+ * 3) Transitivity
+ * 4) Consistency
+ * 5) check it fails if you put in a null value
+ * @throws IllegalAccessException error
+ */
+ @Test
+ public void testEquals() throws IllegalAccessException {
+ // Reflexivity
+ TTFTableName a = TTFTableName.getValue("test");
+ assertTrue(a.equals(a));
+ // Symmetry
+ TTFTableName b = TTFTableName.getValue("test");
+ assertTrue(a.equals(b));
+ assertTrue(b.equals(a));
+ // Transitivity (tested with symmetry)
+ // Consistency (test that a == b is true and that a == c fails)
+ TTFTableName c = TTFTableName.getValue("fail");
+ for (int i = 0; i < 100; i++) {
+ assertTrue(a.equals(b));
+ assertFalse(a.equals(c));
+ }
+ // check with null value
+ assertFalse(a.equals(null));
+ }
+}
diff --git a/test/java/org/apache/fop/render/ps/RenderPSTestSuite.java b/test/java/org/apache/fop/render/ps/RenderPSTestSuite.java
new file mode 100644
index 000000000..2e15bf91f
--- /dev/null
+++ b/test/java/org/apache/fop/render/ps/RenderPSTestSuite.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.ps;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import org.apache.fop.render.ps.fonts.PSTTFGeneratorTestCase;
+import org.apache.fop.render.ps.fonts.PSTTFGlyphOutputStreamTestCase;
+import org.apache.fop.render.ps.fonts.PSTTFOutputStreamTestCase;
+import org.apache.fop.render.ps.fonts.PSTTFTableOutputStreamTestCase;
+
+
+/**
+ * A test Suite for org.apache.fop.render.ps.*
+ */
+@RunWith(Suite.class)
+@SuiteClasses({
+ PSTTFGeneratorTestCase.class,
+ PSTTFOutputStreamTestCase.class,
+ PSTTFGlyphOutputStreamTestCase.class,
+ PSTTFTableOutputStreamTestCase.class
+})
+public final class RenderPSTestSuite {
+}
diff --git a/test/java/org/apache/fop/render/ps/fonts/PSTTFGeneratorTestCase.java b/test/java/org/apache/fop/render/ps/fonts/PSTTFGeneratorTestCase.java
new file mode 100644
index 000000000..f7f311ff8
--- /dev/null
+++ b/test/java/org/apache/fop/render/ps/fonts/PSTTFGeneratorTestCase.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.ps.fonts;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.xmlgraphics.ps.PSGenerator;
+
+/**
+ * The test class for org.apache.fop.render.ps.fonts.PSGenerator
+ */
+public class PSTTFGeneratorTestCase {
+ private PSTTFGenerator ttfGen;
+ private ByteArrayOutputStream out = new ByteArrayOutputStream();
+ private PSGenerator gen = new PSGenerator(out);
+ private byte[] byteArray;
+
+ /**
+ * Constructor
+ */
+ public PSTTFGeneratorTestCase() {
+ byteArray = new byte[65536];
+ for (int i = 0; i < 65536; i++) {
+ byteArray[i] = (byte) i;
+ }
+ }
+
+ @Before
+ public void setUp() {
+ ttfGen = new PSTTFGenerator(gen);
+ }
+
+ /**
+ * Tests startString() - starts the string in an appropriate way for a PostScript file.
+ * @exception IOException write error
+ */
+ @Test
+ public void testStartString() throws IOException {
+ ttfGen.startString();
+ assertEquals("<\n", out.toString());
+ }
+
+ /**
+ * Test streamBytes() - tests that strings are written to file in the proper format.
+ * @throws IOException write error.
+ */
+ @Test
+ public void testStreamBytes() throws IOException {
+ ttfGen.streamBytes(byteArray, 0, 16);
+ assertEquals("000102030405060708090A0B0C0D0E0F", out.toString());
+ /*
+ * 65520 is the closes multiple of 80 to 65535 (max string size in PS document) and since
+ * one byte takes up two characters, 65520 / 2 - 16 (16 bytes already written)= 32744.
+ */
+ ttfGen.streamBytes(byteArray, 0, 32744);
+ // Using a regex to ensure that the format is correct
+ assertTrue(out.toString().matches("([0-9A-F]{80}\n){819}"));
+ try {
+ ttfGen.streamBytes(byteArray, 0, PSTTFGenerator.MAX_BUFFER_SIZE + 1);
+ fail("Shouldn't be able to write more than MAX_BUFFER_SIZE to a PS document");
+ } catch (UnsupportedOperationException e) {
+ // PASS
+ }
+ }
+
+ /**
+ * Test reset() - reset should reset the line counter such that when reset() is invoked the
+ * following string streamed to the PS document should be 80 chars long.
+ * @throws IOException file write error.
+ */
+ @Test
+ public void testReset() throws IOException {
+ ttfGen.streamBytes(byteArray, 0, 40);
+ assertTrue(out.toString().matches("([0-9A-F]{80}\n)"));
+ ttfGen.streamBytes(byteArray, 0, 40);
+ assertTrue(out.toString().matches("([0-9A-F]{80}\n){2}"));
+
+ }
+
+ /**
+ * Test endString() - ensures strings are ended in the PostScript document in the correct
+ * format, a "00" needs to be appended to the end of a string.
+ * @throws IOException file write error
+ */
+ @Test
+ public void testEndString() throws IOException {
+ ttfGen.endString();
+ assertEquals("00\n> ", out.toString());
+ out.reset();
+ // we need to check that this doesn't write more than 80 chars per line
+ ttfGen.streamBytes(byteArray, 0, 40);
+ ttfGen.endString();
+ assertTrue(out.toString().matches("([0-9A-F]{80}\n)00\n> "));
+ }
+}
diff --git a/test/java/org/apache/fop/render/ps/fonts/PSTTFGlyphOutputStreamTestCase.java b/test/java/org/apache/fop/render/ps/fonts/PSTTFGlyphOutputStreamTestCase.java
new file mode 100644
index 000000000..82b4364c3
--- /dev/null
+++ b/test/java/org/apache/fop/render/ps/fonts/PSTTFGlyphOutputStreamTestCase.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.ps.fonts;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test class for PSTTFGlyphOutputStream
+ */
+public class PSTTFGlyphOutputStreamTestCase {
+ private PSTTFGenerator mockGen;
+ private PSTTFGlyphOutputStream glyphOut;
+
+ @Before
+ public void setUp() {
+ mockGen = mock(PSTTFGenerator.class);
+ glyphOut = new PSTTFGlyphOutputStream(mockGen);
+ }
+
+ /**
+ * Test startGlyphStream() - test that startGlyphStream() invokes reset() and startString() in
+ * PSTTFGenerator.
+ * @exception IOException file write error
+ */
+ @Test
+ public void testStartGlyphStream() throws IOException {
+ glyphOut.startGlyphStream();
+ verify(mockGen).startString();
+ }
+
+ /**
+ * Test streamGlyph(byte[],int,int) - tests several paths:
+ * 1) strings are properly appended
+ * 2) when total strings size > PSTTFGenerator.MAX_BUFFER_SIZE, the strings is closed and a new
+ * strings is started.
+ * 3) if a glyph of size > PSTTFGenerator.MAX_BUFFER_SIZE is attempted, an exception is thrown.
+ * @throws IOException file write error.
+ */
+ @Test
+ public void testStreamGlyph() throws IOException {
+ int byteArraySize = 10;
+ byte[] byteArray = new byte[byteArraySize];
+ int runs = 100;
+ for (int i = 0; i < runs; i++) {
+ glyphOut.streamGlyph(byteArray, 0, byteArraySize);
+ }
+ verify(mockGen, times(runs)).streamBytes(byteArray, 0, byteArraySize);
+
+ /*
+ * We want to run this for MAX_BUFFER_SIZE / byteArraySize so that go over the string
+ * boundary and enforce the ending and starting of a new string. Using mockito to ensure
+ * that this behaviour is performed in order (since this is an integral behavioural aspect)
+ */
+ int stringLimit = PSTTFGenerator.MAX_BUFFER_SIZE / byteArraySize;
+ for (int i = 0; i < stringLimit; i++) {
+ glyphOut.streamGlyph(byteArray, 0, byteArraySize);
+ }
+ InOrder inOrder = inOrder(mockGen);
+ inOrder.verify(mockGen, times(stringLimit)).streamBytes(byteArray, 0, byteArraySize);
+ inOrder.verify(mockGen).endString();
+ inOrder.verify(mockGen).startString();
+ inOrder.verify(mockGen, times(runs)).streamBytes(byteArray, 0, byteArraySize);
+
+ try {
+ glyphOut.streamGlyph(byteArray, 0, PSTTFGenerator.MAX_BUFFER_SIZE + 1);
+ fail("Shouldn't allow a length > PSTTFGenerator.MAX_BUFFER_SIZE");
+ } catch (UnsupportedOperationException e) {
+ // PASS
+ }
+ }
+
+ /**
+ * Test endGlyphStream() - tests that PSTTFGenerator.endString() is invoked when this method
+ * is called.
+ * @throws IOException file write exception
+ */
+ @Test
+ public void testEndGlyphStream() throws IOException {
+ glyphOut.endGlyphStream();
+ verify(mockGen).endString();
+ }
+}
diff --git a/test/java/org/apache/fop/render/ps/fonts/PSTTFOutputStreamTestCase.java b/test/java/org/apache/fop/render/ps/fonts/PSTTFOutputStreamTestCase.java
new file mode 100644
index 000000000..744f17f64
--- /dev/null
+++ b/test/java/org/apache/fop/render/ps/fonts/PSTTFOutputStreamTestCase.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.ps.fonts;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.apache.xmlgraphics.ps.PSGenerator;
+
+import org.apache.fop.fonts.truetype.TTFGlyphOutputStream;
+import org.apache.fop.fonts.truetype.TTFTableOutputStream;
+
+/**
+ * Tests PSTTFOuputStream
+ */
+public class PSTTFOutputStreamTestCase {
+ private PSGenerator gen;
+ private PSTTFOutputStream out;
+
+ /**
+ * Assigns an OutputStream to the PSGenerator.
+ */
+ @Before
+ public void setUp() {
+ gen = mock(PSGenerator.class);
+ out = new PSTTFOutputStream(gen);
+ }
+
+ /**
+ * Test startFontStream() - Just tests that the font is properly initiated in the PostScript
+ * document (in this case with "/sfnts[")
+ * @throws IOException write exception.
+ */
+ @Test
+ public void testStartFontStream() throws IOException {
+ out.startFontStream();
+ verify(gen).write("/sfnts[");
+ }
+
+ /**
+ * Test getTableOutputStream() - we need to test that the inheritance model is properly obeyed.
+ */
+ @Test
+ public void testGetTableOutputStream() {
+ TTFTableOutputStream tableOut = out.getTableOutputStream();
+ assertTrue(tableOut instanceof PSTTFTableOutputStream);
+ }
+
+ /**
+ * Test getGlyphOutputStream() - we need to test that the inheritance model is properly obeyed.
+ */
+ @Test
+ public void testGetGlyphOutputStream() {
+ TTFGlyphOutputStream glyphOut = out.getGlyphOutputStream();
+ assertTrue(glyphOut instanceof PSTTFGlyphOutputStream);
+ }
+
+ /**
+ * Test endFontStream()
+ * @exception IOException write error.
+ */
+ @Test
+ public void testEndFontStream() throws IOException {
+ out.endFontStream();
+ verify(gen).writeln("] def");
+ }
+}
diff --git a/test/java/org/apache/fop/render/ps/fonts/PSTTFTableOutputStreamTestCase.java b/test/java/org/apache/fop/render/ps/fonts/PSTTFTableOutputStreamTestCase.java
new file mode 100644
index 000000000..c20c3d8b1
--- /dev/null
+++ b/test/java/org/apache/fop/render/ps/fonts/PSTTFTableOutputStreamTestCase.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.ps.fonts;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Test class for unit testing PSTTFTableOutputStream
+ */
+public class PSTTFTableOutputStreamTestCase {
+ private PSTTFGenerator mockGen;
+ private PSTTFTableOutputStream tableOut;
+
+ @Before
+ public void setUp() {
+ mockGen = mock(PSTTFGenerator.class);
+ tableOut = new PSTTFTableOutputStream(mockGen);
+ }
+
+ /**
+ * Test streamTable() - several paths to test (2. and 3. test corner cases):
+ * 1) that a table of length < PSTTFGenerator.MAX_BUFFER_SIZE invokes the correct methods in
+ * PSTTFGenerator.
+ * 2) that a table of length > PSTTFGenerator.MAX_BUFFER_SIZE and
+ * length == n * PSTTFGenerator.MAX_BUFFER_SIZE is split up and the methods in PSTTFGenerator
+ * are invoked.
+ * 3) that a table of length > PSTTFGenerator.MAX_BUFFER_SIZE but
+ * length != n * PSTTFGenerator.MAX_BUFFER_SIZE is split up and the methods in PSTTFGenerator
+ * are invoked.
+ * @throws IOException file write error.
+ */
+ @Test
+ public void testStreamTable() throws IOException {
+ byte[] byteArray = new byte[PSTTFGenerator.MAX_BUFFER_SIZE * 3];
+ tableOut.streamTable(byteArray, 0, 10);
+ InOrder inOrder = inOrder(mockGen);
+ inOrder.verify(mockGen).startString();
+ inOrder.verify(mockGen).streamBytes(byteArray, 0, 10);
+ inOrder.verify(mockGen).endString();
+
+ setUp(); // reset all all the method calls
+ /* We're going to run this 3 times to ensure the proper method calls are invoked and all
+ * the bytes are streamed */
+ tableOut.streamTable(byteArray, 0, byteArray.length);
+ inOrder = inOrder(mockGen);
+ for (int i = 0; i < 3; i++) {
+ int offset = PSTTFGenerator.MAX_BUFFER_SIZE * i;
+ inOrder.verify(mockGen).startString();
+ inOrder.verify(mockGen).streamBytes(byteArray, offset, PSTTFGenerator.MAX_BUFFER_SIZE);
+ inOrder.verify(mockGen).endString();
+ }
+
+ setUp(); // reset all the method calls
+ tableOut.streamTable(byteArray, 0, PSTTFGenerator.MAX_BUFFER_SIZE + 1);
+ inOrder = inOrder(mockGen);
+ inOrder.verify(mockGen).startString();
+ inOrder.verify(mockGen).streamBytes(byteArray, 0, PSTTFGenerator.MAX_BUFFER_SIZE);
+ inOrder.verify(mockGen).endString();
+ inOrder.verify(mockGen).startString();
+ inOrder.verify(mockGen).streamBytes(byteArray, PSTTFGenerator.MAX_BUFFER_SIZE, 1);
+ inOrder.verify(mockGen).endString();
+ }
+}
diff --git a/test/java/org/apache/fop/util/HexEncoderTestCase.java b/test/java/org/apache/fop/util/HexEncoderTestCase.java
new file mode 100644
index 000000000..cb366abdf
--- /dev/null
+++ b/test/java/org/apache/fop/util/HexEncoderTestCase.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test case for the conversion of characters into hex-encoded strings.
+ */
+public class HexEncoderTestCase {
+
+ /**
+ * Tests that characters are properly encoded into hex strings.
+ */
+ @Test
+ public void testEncodeChar() {
+ char[] digits = new char[] {'0', '0', '0', '0'};
+ for (int c = 0; c <= 0xFFFF; c++) {
+ assertEquals(new String(digits), HexEncoder.encode((char) c));
+ increment(digits);
+ }
+ }
+
+ private static void increment(char[] digits) {
+ int d = 4;
+ do {
+ d--;
+ digits[d] = successor(digits[d]);
+ } while (digits[d] == '0' && d > 0);
+ }
+
+ private static char successor(char d) {
+ if (d == '9') {
+ return 'A';
+ } else if (d == 'F') {
+ return '0';
+ } else {
+ return (char) (d + 1);
+ }
+ }
+
+}