/* * Copyright (c) 2013 Allogy Interactive. * * Licensed 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. */ package com.sun.pdfview; import java.io.*; import java.util.*; public class AdobeGlyphList { /** provide a translation from a glyph name to the possible unicode values. */ static private HashMap<String, int[]> glyphToUnicodes; /** provide a translation from a unicode value to a glyph name. */ static private HashMap<Integer, String> unicodeToGlyph; /** the loader thread we are reading through. */ static Thread glyphLoaderThread = null; static { new AdobeGlyphList(); } /** * <p>private constructor to restrict creation to a singleton.</p> * * <p>We initialize by creating the storage and parsing the glyphlist * into the tables.</p> */ private AdobeGlyphList() { glyphToUnicodes = new HashMap<String, int[]>(4500); unicodeToGlyph = new HashMap<Integer, String>(4500); glyphLoaderThread = new Thread(new Runnable() { public void run() { int[] codes; StringTokenizer codeTokens; String glyphName; StringTokenizer tokens; ArrayList<String> unicodes = new ArrayList<String>(); InputStream istr = getClass().getResourceAsStream("/com/sun/pdfview/font/ttf/resource/glyphlist.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(istr)); String line = ""; while (line != null) { try { unicodes.clear(); line = reader.readLine(); if (line == null) { break; } line = line.trim(); if (line.length() > 0 && !line.startsWith("#")) { // ignore comment lines tokens = new StringTokenizer(line, ";"); glyphName = tokens.nextToken(); codeTokens = new StringTokenizer(tokens.nextToken(), " "); while (codeTokens.hasMoreTokens()) { unicodes.add(codeTokens.nextToken()); } codes = new int[unicodes.size()]; for (int i = 0; i < unicodes.size(); i++) { codes[i] = Integer.parseInt(unicodes.get(i), 16); unicodeToGlyph.put(new Integer(codes[i]), glyphName); } glyphToUnicodes.put(glyphName, codes); } } catch (IOException ex) { break; } } } }, "Adobe Glyph Loader Thread"); glyphLoaderThread.setDaemon(true); glyphLoaderThread.setPriority(Thread.MIN_PRIORITY); glyphLoaderThread.start(); } /** * translate a glyph name into the possible unicode values that it * might represent. It is possible to have more than one unicode * value for a single glyph name. * * @param glyphName * @return int[] */ public static int[] getUnicodeValues(String glyphName) { while (glyphLoaderThread != null && glyphLoaderThread.isAlive()) { synchronized (glyphToUnicodes) { try { glyphToUnicodes.wait(250); } catch (InterruptedException ex) { // ignore } } } return glyphToUnicodes.get(glyphName); } /** * return a single index for a glyph, though there may be multiples. * * @param glyphName * @return Integer */ public static Integer getGlyphNameIndex(String glyphName) { int [] unicodes = getUnicodeValues(glyphName); if (unicodes == null) { return null; } else { return new Integer(unicodes[0]); } } /** * translate a unicode value into a glyph name. It is possible for * different unicode values to translate into the same glyph name. * * @param unicode * @return String */ public static String getGlyphName(int unicode) { while (glyphLoaderThread != null && glyphLoaderThread.isAlive()) { synchronized (glyphToUnicodes) { try { glyphToUnicodes.wait(250); } catch (InterruptedException ex) { // ignore } } } return unicodeToGlyph.get(new Integer(unicode)); } }