Home | History | Annotate | Download | only in font
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 /**
     18  * @author Ilya S. Okomin
     19  * @version $Revision$
     20  */
     21 package org.apache.harmony.awt.gl.font;
     22 
     23 import java.awt.Font;
     24 import java.awt.peer.FontPeer;
     25 import java.io.File;
     26 import java.io.IOException;
     27 import java.util.Properties;
     28 import java.util.Vector;
     29 
     30 import org.apache.harmony.awt.gl.font.FontManager;
     31 import org.apache.harmony.awt.gl.font.FontProperty;
     32 import org.apache.harmony.awt.internal.nls.Messages;
     33 
     34 import android.util.Log;
     35 
     36 public class AndroidFontManager extends FontManager {
     37 
     38     // set of all available faces supported by a system
     39     String faces[];
     40 
     41     // weight names according to xlfd structure
     42     public static final String[] LINUX_WEIGHT_NAMES = {
     43             "black", "bold", "demibold", "medium", "light" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
     44     };
     45 
     46     // slant names according to xlfd structure
     47     public static final String[] LINUX_SLANT_NAMES = {
     48             "i", "o", "r" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
     49     };
     50 
     51     /** Singleton AndroidFontManager instance */
     52     public static final AndroidFontManager inst = new AndroidFontManager();
     53 
     54     private AndroidFontManager() {
     55         super();
     56         faces = new String[] {/*"PLAIN",*/ "NORMAL", "BOLD", "ITALIC", "BOLDITALIC"};
     57         initFontProperties();
     58     }
     59 
     60     public void initLCIDTable(){
     61     	throw new RuntimeException("Not implemented!");
     62     }
     63 
     64     /**
     65      * Returns temporary File object to store data from InputStream.
     66      * This File object saved to `~/.fonts/' folder that is included in the
     67      * list of folders searched for font files, and this is where user-specific
     68      * font files should be installed.
     69      */
     70     public File getTempFontFile()throws IOException{
     71         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$
     72         fontFile.deleteOnExit();
     73 
     74         return fontFile;
     75     }
     76 
     77     /**
     78      * Initializes fProperties array field for the current system configuration font
     79      * property file.
     80      *
     81      * RuntimeException is thrown if font property contains incorrect format of
     82      * xlfd string.
     83      *
     84      * @return true is success, false if font property doesn't exist or doesn't
     85      * contain roperties.
     86      */
     87     public boolean initFontProperties(){
     88         File fpFile = getFontPropertyFile();
     89         if (fpFile == null){
     90             return false;
     91         }
     92 
     93         Properties props = getProperties(fpFile);
     94         if (props == null){
     95             return false;
     96         }
     97 
     98         for (int i=0; i < LOGICAL_FONT_NAMES.length; i++){
     99             String lName = LOGICAL_FONT_NAMES[i];
    100             for (int j=0; j < STYLE_NAMES.length; j++){
    101                 String styleName = STYLE_NAMES[j];
    102                 Vector propsVector = new Vector();
    103 
    104                 // Number of entries for a logical font
    105                 int numComp = 0;
    106                 // Is more entries for this style and logical font name left
    107                 boolean moreEntries = true;
    108                 String value = null;
    109 
    110                 while(moreEntries){
    111                     // Component Font Mappings property name
    112                     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$
    113                     value = props.getProperty(property);
    114 
    115                     // If the StyleName is omitted, it's assumed to be plain
    116                     if ((j == 0) && (value == null)){
    117                         property = FONT_MAPPING_KEYS[1].replaceAll("LogicalFontName", lName).replaceAll("ComponentIndex", String.valueOf(numComp)); //$NON-NLS-1$ //$NON-NLS-2$
    118                         value = props.getProperty(property);
    119                     }
    120 
    121                     if (value != null){
    122                         String[] fields = parseXLFD(value);
    123 
    124                         if (fields == null){
    125                             // awt.08=xfld parse string error: {0}
    126                             throw new RuntimeException(Messages.getString("awt.08", value)); //$NON-NLS-1$
    127                         }
    128 
    129                         String fontName = fields[1];
    130                         String weight = fields[2];
    131                         String italic = fields[3];
    132 
    133                         int style = getBoldStyle(weight) | getItalicStyle(italic);
    134                         // Component Font Character Encodings property value
    135                         String encoding = props.getProperty(FONT_CHARACTER_ENCODING.replaceAll("LogicalFontName", lName).replaceAll("ComponentIndex", String.valueOf(numComp))); //$NON-NLS-1$ //$NON-NLS-2$
    136 
    137                         // Exclusion Ranges property value
    138                         String exclString = props.getProperty(EXCLUSION_RANGES.replaceAll("LogicalFontName", lName).replaceAll("ComponentIndex", String.valueOf(numComp))); //$NON-NLS-1$ //$NON-NLS-2$
    139                         int[] exclRange = parseIntervals(exclString);
    140 
    141                         FontProperty fp = new AndroidFontProperty(lName, styleName, null, fontName, value, style, exclRange, encoding);
    142 
    143                         propsVector.add(fp);
    144                         numComp++;
    145                     } else {
    146                         moreEntries = false;
    147                     }
    148                 }
    149                 fProperties.put(LOGICAL_FONT_NAMES[i] + "." + j, propsVector); //$NON-NLS-1$
    150             }
    151         }
    152 
    153         return true;
    154 
    155     }
    156 
    157     /**
    158      * Returns style according to the xlfd weight string.
    159      * If weight string is incorrect returned value is Font.PLAIN
    160      *
    161      * @param str weight name String
    162      */
    163     private int getBoldStyle(String str){
    164         for (int i = 0; i < LINUX_WEIGHT_NAMES.length;i++){
    165             if (str.equalsIgnoreCase(LINUX_WEIGHT_NAMES[i])){
    166                 return (i < 3) ? Font.BOLD : Font.PLAIN;
    167             }
    168         }
    169         return Font.PLAIN;
    170     }
    171 
    172     /**
    173      * Returns style according to the xlfd slant string.
    174      * If slant string is incorrect returned value is Font.PLAIN
    175      *
    176      * @param str slant name String
    177      */
    178     private int getItalicStyle(String str){
    179         for (int i = 0; i < LINUX_SLANT_NAMES.length;i++){
    180             if (str.equalsIgnoreCase(LINUX_SLANT_NAMES[i])){
    181                 return (i < 2) ? Font.ITALIC : Font.PLAIN;
    182             }
    183         }
    184         return Font.PLAIN;
    185     }
    186 
    187     /**
    188      * Parse xlfd string and returns array of Strings with separate xlfd
    189      * elements.<p>
    190      *
    191      * xlfd format:
    192      *      -Foundry-Family-Weight-Slant-Width-Style-PixelSize-PointSize-ResX-ResY-Spacing-AvgWidth-Registry-Encoding
    193      * @param xlfd String parameter in xlfd format
    194      */
    195     public static String[] parseXLFD(String xlfd){
    196         int fieldsCount = 14;
    197         String fieldsDelim = "-"; //$NON-NLS-1$
    198         String[] res = new String[fieldsCount];
    199         if (!xlfd.startsWith(fieldsDelim)){
    200             return null;
    201         }
    202 
    203         xlfd = xlfd.substring(1);
    204         int i=0;
    205         int pos;
    206         for (i=0; i < fieldsCount-1; i++){
    207             pos = xlfd.indexOf(fieldsDelim);
    208             if (pos != -1){
    209                 res[i] = xlfd.substring(0, pos);
    210                 xlfd = xlfd.substring(pos + 1);
    211             } else {
    212                 return null;
    213             }
    214         }
    215         pos = xlfd.indexOf(fieldsDelim);
    216 
    217         // check if no fields left
    218         if(pos != -1){
    219             return null;
    220         }
    221         res[fieldsCount-1] = xlfd;
    222 
    223         return res;
    224     }
    225 
    226     public int getFaceIndex(String faceName){
    227 
    228         for (int i = 0; i < faces.length; i++) {
    229             if(faces[i].equals(faceName)){
    230                 return i;
    231             }
    232         }
    233         return -1;
    234     }
    235 
    236     public String[] getAllFamilies(){
    237         if (allFamilies == null){
    238         	allFamilies = new String[]{"sans-serif", "serif", "monospace"};
    239         }
    240         return allFamilies;
    241     }
    242 
    243     public Font[] getAllFonts(){
    244         Font[] fonts = new Font[faces.length];
    245         for (int i =0; i < fonts.length;i++){
    246             fonts[i] = new Font(faces[i], Font.PLAIN, 1);
    247         }
    248         return fonts;
    249     }
    250 
    251     public FontPeer createPhysicalFontPeer(String name, int style, int size) {
    252         AndroidFont peer;
    253         int familyIndex = getFamilyIndex(name);
    254         if (familyIndex != -1){
    255             // !! we use family names from the list with cached families because
    256             // they are differ from the family names in xlfd structure, in xlfd
    257             // family names mostly in lower case.
    258             peer = new AndroidFont(getFamily(familyIndex), style, size);
    259             peer.setFamily(getFamily(familyIndex));
    260             return peer;
    261         }
    262         int faceIndex = getFaceIndex(name);
    263         if (faceIndex != -1){
    264 
    265             peer = new AndroidFont(name, style, size);
    266             return peer;
    267         }
    268 
    269         return null;
    270     }
    271 
    272     public FontPeer createDefaultFont(int style, int size) {
    273     	Log.i("DEFAULT FONT", Integer.toString(style));
    274         return new AndroidFont(DEFAULT_NAME, style, size);
    275     }
    276 
    277 }
    278