Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 164 additions & 4 deletions batik-svggen/src/main/java/org/apache/batik/svggen/font/SVGFont.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ Licensed to the Apache Software Foundation (ASF) under one or more

package org.apache.batik.svggen.font;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Set;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

import org.apache.batik.svggen.font.table.CmapFormat;
import org.apache.batik.svggen.font.table.Feature;
Expand Down Expand Up @@ -261,6 +267,145 @@ protected static String getSVGFontFaceElement(Font font) {
return sb.toString();
}

/**
* Implements an Iterator interface to select required glyphs based on user
*
* @version $Id$
* @author <a href="mailto:[email protected]">Nilam Gaikwad</a>
*/
public static class GlyphSelector implements Iterator<Integer> {

static final int GLYPH_SELECTOR_LINEAR_RANGE = 1;
static final int GLYPH_SELECTOR_NON_LINEAR_RANGE = 2;

int type;
int startIndex, endIndex;
int currentIndex = 0;
List<Integer> requiredGlyphIndexes = null;

/**
* GlyphSelector Default constructore
*/
public GlyphSelector() {
init(-1,-1);
}

/**
* GlyphSelector constructor which prepare list of unicode glyph number
* to extract from TTF file.
*
* @param fileName A file containing unicode glyph number list.
*/
public GlyphSelector(String fileName) {
init(fileName);
}

/**
* Initializes glyphSelector list from given disk file.
*
* @param fileName File which contains list of unicode number of glyphs
* to extract from TTF file.
*/
protected void init(String fileName) {
/* This is non-linear glyph selector */
type = GLYPH_SELECTOR_NON_LINEAR_RANGE;

/* Populate array */
requiredGlyphIndexes = new ArrayList<Integer>();
requiredGlyphIndexes.clear();
currentIndex = 0;

try {
Scanner intList = new Scanner(new File(fileName));
while (intList.hasNext()) {
String s = intList.next();

if (s.length() > 0) {
int radix, p0, v;
boolean intParsingDone = false;
char[] cl = s.toCharArray();

if (cl[0] == '0' && (cl[1] == 'x' || cl[1] == 'X')) {
radix = 16;
p0 = 2;
} else {
radix = 10;
p0 = 0;
}
v = 0;
for (int i = p0; i < cl.length; i++) {
char c = cl[i];
if (c >= 'A' && c <= 'F')
v = v * radix + c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
v = v * radix + c - 'a' + 10;
else if (c >= '0' && c <= '9')
v = v * radix + c - '0';
else
break;
intParsingDone = true;
}
cl = null;

if (intParsingDone == false) {
System.err.printf("WARNING: Not-parsed string [%s]\n", s);
} else if (requiredGlyphIndexes.contains(v) == false) {
requiredGlyphIndexes.add(v);
} else {
System.err.printf("WARNING: Duplicate string [%s]\n", s);
}
}
}
intList.close();
} catch (FileNotFoundException e) {
System.err.println(e);
}
}

/**
* Initializes Unicode number extractor for given start-end range.
*
* @param start The starting unicode number from required glyphs.
* @param end The last unicode number from required glyphs.
*/
protected void init(int start, int end) {
type = GLYPH_SELECTOR_LINEAR_RANGE;
startIndex = start;
endIndex = end;
currentIndex = startIndex;
}

/**
* Returns true if there are additional unicode number to extract from TTF font
* Return false otherwise
*/
public boolean hasNext() {
boolean result = false;
if (type == GLYPH_SELECTOR_LINEAR_RANGE) {
if (currentIndex >= startIndex && currentIndex < endIndex)
result = true;
} else if (type == GLYPH_SELECTOR_NON_LINEAR_RANGE) {
if (currentIndex < requiredGlyphIndexes.size())
result = true;
}
return result;
}

/**
* Returns a unicode character number which user has required for glyph extraction
*/
public Integer next() {
Integer iVal = 0;
if (type == GLYPH_SELECTOR_LINEAR_RANGE) {
iVal = currentIndex;
} else if (type == GLYPH_SELECTOR_NON_LINEAR_RANGE) {
iVal = requiredGlyphIndexes.get(currentIndex);
}
currentIndex++;
return iVal;
}
}

/**
* Returns a &lt;font&gt;&#x2e;&#x2e;&#x2e;&lt;/font&gt; block,
* defining the specified font.
Expand All @@ -270,8 +415,9 @@ protected static String getSVGFontFaceElement(Font font) {
* @param first The first character in the output range
* @param last The last character in the output range
* @param forceAscii Force the use of the ASCII character map
* @param glyphSelector Iterator object which contains list of glyph indexs for extraction
*/
protected static void writeFontAsSVGFragment(PrintStream ps, Font font, String id, int first, int last, boolean autoRange, boolean forceAscii)
protected static void writeFontAsSVGFragment(PrintStream ps, Font font, String id, int first, int last, boolean autoRange, boolean forceAscii, GlyphSelector glyphSelector)
throws Exception {
// StringBuffer sb = new StringBuffer();
// int horiz_advance_x = font.getHmtxTable().getAdvanceWidth(
Expand Down Expand Up @@ -362,6 +508,7 @@ protected static void writeFontAsSVGFragment(PrintStream ps, Font font, String i
initialSubst, medialSubst, terminalSubst, ""));

try {
boolean glyphSelectorReInitRequired = (autoRange == true || ( first != -1 && last != -1));
if (first == -1) {
if (!autoRange) first = DEFAULT_FIRST;
else first = cmapFmt.getFirst();
Expand All @@ -371,9 +518,14 @@ protected static void writeFontAsSVGFragment(PrintStream ps, Font font, String i
else last = cmapFmt.getLast();
}

// Include our requested range
// Include our requested characters
Set glyphSet = new HashSet();
for (int i = first; i <= last; i++) {
if (glyphSelectorReInitRequired) {
glyphSelector.init(first, last);
}

while (glyphSelector.hasNext()) {
int i = glyphSelector.next().intValue();
int glyphIndex = cmapFmt.mapCharCode(i);
// ps.println(String.valueOf(i) + " -> " + String.valueOf(glyphIndex));
// if (font.getGlyphs()[glyphIndex] != null)
Expand Down Expand Up @@ -712,6 +864,7 @@ protected static void writeSvgTestCard(PrintStream ps, String fontFamily) {

public static final char ARG_KEY_START_CHAR = '-';
public static final String ARG_KEY_CHAR_RANGE_LOW = "-l";
public static final String ARG_REQUIRED_UNICODE_LIST = "-u";
public static final String ARG_KEY_CHAR_RANGE_HIGH = "-h";
public static final String ARG_KEY_ID = "-id";
public static final String ARG_KEY_ASCII = "-ascii";
Expand All @@ -728,13 +881,15 @@ public static void main(String[] args) {
String path = parseArgs(args, null);
String low = parseArgs(args, ARG_KEY_CHAR_RANGE_LOW);
String high = parseArgs(args, ARG_KEY_CHAR_RANGE_HIGH);
String unicodeCharListFile = parseArgs(args, ARG_REQUIRED_UNICODE_LIST);
String id = parseArgs(args, ARG_KEY_ID);
String ascii = parseArgs(args, ARG_KEY_ASCII);
String testCard = parseArgs(args, ARG_KEY_TESTCARD);
String outPath = parseArgs(args, ARG_KEY_OUTPUT_PATH);
String autoRange = parseArgs(args, ARG_KEY_AUTO_RANGE);
PrintStream ps = null;
FileOutputStream fos = null;
GlyphSelector gs = new GlyphSelector();

// What are we outputting to?
if (outPath != null) {
Expand All @@ -750,6 +905,10 @@ public static void main(String[] args) {
if (path != null) {
Font font = Font.create(path);

if (unicodeCharListFile != null) {
gs.init(unicodeCharListFile);
}

// Write the various parts of the SVG file
writeSvgBegin(ps);
writeSvgDefsBegin(ps);
Expand All @@ -760,7 +919,8 @@ public static void main(String[] args) {
(low != null ? Integer.parseInt(low) : -1),
(high != null ? Integer.parseInt(high) : -1),
(autoRange != null),
(ascii != null));
(ascii != null),
gs);
writeSvgDefsEnd(ps);
if (testCard != null) {
String fontFamily = font.getNameTable().getRecord(Table.nameFontFamilyName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# -----------------------------------------------------------------------------

SVGFont.config.usage = \
usage: java org.apache.batik.svggen.font.SVGFont <ttf-path> [-l <range-begin>] [-h <range-end>] [-autorange] [-ascii] [-id <id>] [-o <output-path>] [-testcard]
usage: java org.apache.batik.svggen.font.SVGFont <ttf-path> [-l <range-begin>] [-h <range-end>] [-autorange] [-ascii] [-id <id>] [-o <output-path>] [-testcard] [-u <unicode-list-file>]

SVGFont.config.svg.begin = \
<?xml version="1.0" standalone="no"?> \
Expand Down
6 changes: 5 additions & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,11 @@ JAVA=/usr/bin/java
<path refid="libs-classpath"/>
<pathelement location="resources"/>
</classpath>
<arg line="${args}"/>
<arg line="/usr/share/fonts/truetype/liberation2/LiberationMono-Regular.ttf"/>
<arg line="-u"/>
<arg line="list-h.txt"/>
<arg line="-o"/>
<arg line="out3.svg"/>
</java>
</target>

Expand Down