/* * 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. */ /** * @author Ilya S. Okomin * @version $Revision$ */ package org.apache.harmony.awt.gl.font; import java.awt.Font; import java.awt.peer.FontPeer; import java.io.File; import java.io.IOException; import java.util.Properties; import java.util.Vector; import org.apache.harmony.awt.gl.font.FontManager; import org.apache.harmony.awt.gl.font.FontProperty; import org.apache.harmony.awt.internal.nls.Messages; import android.util.Log; public class AndroidFontManager extends FontManager { // set of all available faces supported by a system String faces[]; // weight names according to xlfd structure public static final String[] LINUX_WEIGHT_NAMES = { "black", "bold", "demibold", "medium", "light" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ }; // slant names according to xlfd structure public static final String[] LINUX_SLANT_NAMES = { "i", "o", "r" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ }; /** Singleton AndroidFontManager instance */ public static final AndroidFontManager inst = new AndroidFontManager(); private AndroidFontManager() { super(); faces = new String[] {/*"PLAIN",*/ "NORMAL", "BOLD", "ITALIC", "BOLDITALIC"}; initFontProperties(); } public void initLCIDTable(){ throw new RuntimeException("Not implemented!"); } /** * Returns temporary File object to store data from InputStream. * This File object saved to `~/.fonts/' folder that is included in the * list of folders searched for font files, and this is where user-specific * font files should be installed. */ public File getTempFontFile()throws IOException{ File fontFile = File.createTempFile("jFont", ".ttf", new File(System.getProperty("user.home") +"/.fonts")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ fontFile.deleteOnExit(); return fontFile; } /** * Initializes fProperties array field for the current system configuration font * property file. * * RuntimeException is thrown if font property contains incorrect format of * xlfd string. * * @return true is success, false if font property doesn't exist or doesn't * contain roperties. */ public boolean initFontProperties(){ File fpFile = getFontPropertyFile(); if (fpFile == null){ return false; } Properties props = getProperties(fpFile); if (props == null){ return false; } for (int i=0; i < LOGICAL_FONT_NAMES.length; i++){ String lName = LOGICAL_FONT_NAMES[i]; for (int j=0; j < STYLE_NAMES.length; j++){ String styleName = STYLE_NAMES[j]; Vector propsVector = new Vector(); // Number of entries for a logical font int numComp = 0; // Is more entries for this style and logical font name left boolean moreEntries = true; String value = null; while(moreEntries){ // Component Font Mappings property name String property = FONT_MAPPING_KEYS[0].replaceAll("LogicalFontName", lName).replaceAll("StyleName", styleName).replaceAll("ComponentIndex", String.valueOf(numComp)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ value = props.getProperty(property); // If the StyleName is omitted, it's assumed to be plain if ((j == 0) && (value == null)){ property = FONT_MAPPING_KEYS[1].replaceAll("LogicalFontName", lName).replaceAll("ComponentIndex", String.valueOf(numComp)); //$NON-NLS-1$ //$NON-NLS-2$ value = props.getProperty(property); } if (value != null){ String[] fields = parseXLFD(value); if (fields == null){ // awt.08=xfld parse string error: {0} throw new RuntimeException(Messages.getString("awt.08", value)); //$NON-NLS-1$ } String fontName = fields[1]; String weight = fields[2]; String italic = fields[3]; int style = getBoldStyle(weight) | getItalicStyle(italic); // Component Font Character Encodings property value String encoding = props.getProperty(FONT_CHARACTER_ENCODING.replaceAll("LogicalFontName", lName).replaceAll("ComponentIndex", String.valueOf(numComp))); //$NON-NLS-1$ //$NON-NLS-2$ // Exclusion Ranges property value String exclString = props.getProperty(EXCLUSION_RANGES.replaceAll("LogicalFontName", lName).replaceAll("ComponentIndex", String.valueOf(numComp))); //$NON-NLS-1$ //$NON-NLS-2$ int[] exclRange = parseIntervals(exclString); FontProperty fp = new AndroidFontProperty(lName, styleName, null, fontName, value, style, exclRange, encoding); propsVector.add(fp); numComp++; } else { moreEntries = false; } } fProperties.put(LOGICAL_FONT_NAMES[i] + "." + j, propsVector); //$NON-NLS-1$ } } return true; } /** * Returns style according to the xlfd weight string. * If weight string is incorrect returned value is Font.PLAIN * * @param str weight name String */ private int getBoldStyle(String str){ for (int i = 0; i < LINUX_WEIGHT_NAMES.length;i++){ if (str.equalsIgnoreCase(LINUX_WEIGHT_NAMES[i])){ return (i < 3) ? Font.BOLD : Font.PLAIN; } } return Font.PLAIN; } /** * Returns style according to the xlfd slant string. * If slant string is incorrect returned value is Font.PLAIN * * @param str slant name String */ private int getItalicStyle(String str){ for (int i = 0; i < LINUX_SLANT_NAMES.length;i++){ if (str.equalsIgnoreCase(LINUX_SLANT_NAMES[i])){ return (i < 2) ? Font.ITALIC : Font.PLAIN; } } return Font.PLAIN; } /** * Parse xlfd string and returns array of Strings with separate xlfd * elements.<p> * * xlfd format: * -Foundry-Family-Weight-Slant-Width-Style-PixelSize-PointSize-ResX-ResY-Spacing-AvgWidth-Registry-Encoding * @param xlfd String parameter in xlfd format */ public static String[] parseXLFD(String xlfd){ int fieldsCount = 14; String fieldsDelim = "-"; //$NON-NLS-1$ String[] res = new String[fieldsCount]; if (!xlfd.startsWith(fieldsDelim)){ return null; } xlfd = xlfd.substring(1); int i=0; int pos; for (i=0; i < fieldsCount-1; i++){ pos = xlfd.indexOf(fieldsDelim); if (pos != -1){ res[i] = xlfd.substring(0, pos); xlfd = xlfd.substring(pos + 1); } else { return null; } } pos = xlfd.indexOf(fieldsDelim); // check if no fields left if(pos != -1){ return null; } res[fieldsCount-1] = xlfd; return res; } public int getFaceIndex(String faceName){ for (int i = 0; i < faces.length; i++) { if(faces[i].equals(faceName)){ return i; } } return -1; } public String[] getAllFamilies(){ if (allFamilies == null){ allFamilies = new String[]{"sans-serif", "serif", "monospace"}; } return allFamilies; } public Font[] getAllFonts(){ Font[] fonts = new Font[faces.length]; for (int i =0; i < fonts.length;i++){ fonts[i] = new Font(faces[i], Font.PLAIN, 1); } return fonts; } public FontPeer createPhysicalFontPeer(String name, int style, int size) { AndroidFont peer; int familyIndex = getFamilyIndex(name); if (familyIndex != -1){ // !! we use family names from the list with cached families because // they are differ from the family names in xlfd structure, in xlfd // family names mostly in lower case. peer = new AndroidFont(getFamily(familyIndex), style, size); peer.setFamily(getFamily(familyIndex)); return peer; } int faceIndex = getFaceIndex(name); if (faceIndex != -1){ peer = new AndroidFont(name, style, size); return peer; } return null; } public FontPeer createDefaultFont(int style, int size) { Log.i("DEFAULT FONT", Integer.toString(style)); return new AndroidFont(DEFAULT_NAME, style, size); } }