summaryrefslogtreecommitdiffstats
path: root/awt/org/apache/harmony/awt/gl/font/AndroidFontManager.java
blob: 063a25699ede829a6b2d25a007952536ecb95428 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
 *  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);
    }

}