001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Ilya S. Okomin
019: * @version $Revision$
020: */package org.apache.harmony.awt.gl.font;
021:
022: import java.awt.Font;
023: import java.awt.Toolkit;
024: import java.awt.font.FontRenderContext;
025: import java.awt.font.LineMetrics;
026: import java.awt.geom.AffineTransform;
027: import java.awt.geom.Rectangle2D;
028: import java.io.IOException;
029: import java.io.File;
030: import java.util.Hashtable;
031: import java.util.Locale;
032:
033: import org.apache.harmony.awt.ContextStorage;
034: import org.apache.harmony.awt.gl.CommonGraphics2DFactory;
035: import org.apache.harmony.awt.gl.font.FontManager;
036: import org.apache.harmony.awt.gl.font.FontPeerImpl;
037: import org.apache.harmony.awt.gl.font.Glyph;
038: import org.apache.harmony.awt.gl.font.LineMetricsImpl;
039: import org.apache.harmony.awt.internal.nls.Messages;
040: import org.apache.harmony.awt.wtk.linux.LinuxWindowFactory;
041:
042: /**
043: * Linux platform font peer implementation based on Xft and FreeType libraries.
044: */
045: public class LinuxFont extends FontPeerImpl {
046:
047: // Pairs of [begin, end],[..].. unicode ranges values
048: private int[] fontUnicodeRanges;
049:
050: // table with loaded cached Glyphs
051: private Hashtable glyphs = new Hashtable();
052:
053: // X11 display value
054: private long display = 0;
055:
056: // X11 screen value
057: private int screen = 0;
058:
059: // native antialiased font handle
060: private long aaFont = 0;
061:
062: public LinuxFont(String fontName, int fontStyle, int fontSize) {
063: /*
064: * Workaround : to initialize awt platform-dependent fields and libraries.
065: */
066: Toolkit.getDefaultToolkit();
067:
068: this .name = fontName;
069: this .size = fontSize;
070: this .style = fontStyle;
071:
072: this .display = ((LinuxWindowFactory) ContextStorage
073: .getWindowFactory()).getDisplay();
074: this .screen = ((LinuxWindowFactory) ContextStorage
075: .getWindowFactory()).getScreen();
076:
077: pFont = LinuxNativeFont.initializeFont(this , name, style, size,
078: null);
079:
080: initLinuxFont();
081: }
082:
083: /**
084: * Initializes some native dependent font information, e.g. number of glyphs,
085: * font metrics, italic angle etc.
086: */
087: public void initLinuxFont() {
088: if (pFont != 0) {
089: this .numGlyphs = LinuxNativeFont.getNumGlyphsNative(pFont);
090: this .italicAngle = LinuxNativeFont.getItalicAngleNative(
091: pFont, this .fontType);
092: }
093:
094: this .nlm = new LinuxLineMetrics(this , " "); //$NON-NLS-1$
095:
096: this .ascent = nlm.getLogicalAscent();
097: this .descent = nlm.getLogicalDescent();
098: this .height = nlm.getHeight();
099: this .leading = nlm.getLogicalLeading();
100: this .maxAdvance = nlm.getLogicalMaxCharWidth();
101:
102: if (this .fontType == FontManager.FONT_TYPE_T1) {
103: this .defaultChar = 1;
104: } else {
105: this .defaultChar = 0;
106: }
107:
108: this .maxCharBounds = new Rectangle2D.Float(0, -nlm.getAscent(),
109: nlm.getMaxCharWidth(), this .height);
110:
111: // addGlyphs((char) 0x20, (char) 0x7E);
112:
113: }
114:
115: public boolean canDisplay(char chr) {
116: // TODO: to improve performance there is a sence to implement get
117: // unicode ranges to check if char can be displayed without
118: // native calls in isGlyphExists() method
119:
120: return isGlyphExists(chr);
121: }
122:
123: public LineMetrics getLineMetrics(String str,
124: FontRenderContext frc, AffineTransform at) {
125:
126: AffineTransform frcAt = null;
127: // Initialize baseline offsets
128: nlm.getBaselineOffsets();
129: if (frc != null)
130: frcAt = frc.getTransform();
131:
132: LineMetricsImpl lm = (LineMetricsImpl) (this .nlm.clone());
133: lm.setNumChars(str.length());
134:
135: if ((at != null) && (!at.isIdentity())) {
136: if (frcAt != null)
137: at.concatenate(frcAt);
138: lm.scale((float) at.getScaleX(), (float) at.getScaleY());
139: } else if ((frcAt != null) && (!frcAt.isIdentity())) {
140: lm.scale((float) frcAt.getScaleX(), (float) frcAt
141: .getScaleY());
142: }
143:
144: return lm;
145: }
146:
147: public String getPSName() {
148: if ((pFont != 0) && (psName == null)) {
149: psName = LinuxNativeFont.getFontPSNameNative(pFont);
150: }
151: return psName;
152: }
153:
154: public String getFamily(Locale l) {
155: // TODO: implement localized family
156: if (fontType == FontManager.FONT_TYPE_TT) {
157: return this .getFamily();
158: }
159:
160: return this .fontFamilyName;
161: }
162:
163: public String getFontName(Locale l) {
164: if ((pFont == 0) || (this .fontType == FontManager.FONT_TYPE_T1)) {
165: return this .name;
166: }
167:
168: return this .getFontName();
169: }
170:
171: public int getMissingGlyphCode() {
172: return getDefaultGlyph().getGlyphCode();
173: }
174:
175: public Glyph getGlyph(char index) {
176: Glyph result = null;
177:
178: Object key = new Integer(index);
179: if (glyphs.containsKey(key)) {
180: result = (Glyph) glyphs.get(key);
181: } else {
182: if (this .addGlyph(index)) {
183: result = (Glyph) glyphs.get(key);
184: } else {
185: result = this .getDefaultGlyph();
186: }
187: }
188:
189: return result;
190: }
191:
192: public Glyph getDefaultGlyph() {
193: Glyph result;
194: Object key = new Integer(defaultChar);
195: if (glyphs.containsKey(key)) {
196: result = (Glyph) glyphs.get(key);
197: } else {
198: if (this .fontType == FontManager.FONT_TYPE_T1) {
199: // !! Type1 has no default glyphs
200: glyphs.put(key,
201: new LinuxGlyph(defaultChar, defaultChar));
202: result = (Glyph) glyphs.get(key);
203: } else {
204: int code = LinuxNativeFont.getGlyphCodeNative(
205: this .pFont, defaultChar, this .display);
206: glyphs.put(key, new LinuxGlyph(this .pFont, this
207: .getSize(), defaultChar, code));
208: result = (Glyph) glyphs.get(key);
209: }
210: }
211:
212: return result;
213: }
214:
215: /**
216: * Disposes native font handle. If this font peer was created from InputStream
217: * temporary created font resource file is deleted.
218: */
219: public void dispose() {
220: String tempDirName;
221: if (pFont != 0) {
222: LinuxNativeFont.pFontFree(pFont, display);
223: pFont = 0;
224:
225: if (isCreatedFromStream()) {
226: File fontFile = new File(getTempFontFileName());
227: tempDirName = fontFile.getParent();
228: fontFile.delete();
229: LinuxNativeFont.RemoveFontResource(tempDirName);
230: }
231: }
232: }
233:
234: /**
235: * Add glyph to cached Glyph objects in this LinuxFont object.
236: *
237: * @param uChar the specified character
238: * @return true if glyph of the specified character exists in this
239: * LinuxFont or this character is escape sequence character.
240: */
241: public boolean addGlyph(char uChar) {
242: boolean result = false;
243: boolean isEscape = false;
244:
245: isEscape = ((uChar == '\t') || (uChar == '\n') || (uChar == '\r'));
246:
247: int glyphCode = LinuxNativeFont.getGlyphCodeNative(this .pFont,
248: uChar, display);
249: if (isEscape || (glyphCode != 0xFFFF)) {
250: glyphs.put(new Integer(uChar), new LinuxGlyph(this .pFont,
251: this .getSize(), uChar, glyphCode));
252: result = true;
253: }
254: return result;
255: }
256:
257: /**
258: * Adds range of existing glyphs to this LinuxFont object
259: *
260: * @param uFirst the lowest range's bound, inclusive
261: * @param uLast the highest range's bound, exclusive
262: */
263: public void addGlyphs(char uFirst, char uLast) {
264: char index = uFirst;
265: if (uLast < uFirst) {
266: // awt.09=min range bound value is grater than max range bound
267: throw new IllegalArgumentException(Messages
268: .getString("awt.09")); //$NON-NLS-1$
269: }
270: while (index < uLast) {
271: addGlyph(index);
272: index++;
273: }
274: }
275:
276: /**
277: * Returns true if specified character has corresopnding glyph, false otherwise.
278: *
279: * @param uIndex specified char
280: */
281: public boolean isGlyphExists(char uIndex) {
282:
283: /* for (int i = 0; i < fontUnicodeRanges.length - 1; i += 2) {
284: if (uIndex <= fontUnicodeRanges[i + 1]) {
285: if (uIndex >= fontUnicodeRanges[i]) {
286: return true;
287: } else {
288: return false;
289: }
290: }
291: }*/
292: int code = LinuxNativeFont.getGlyphCodeNative(this
293: .getFontHandle(), uIndex, display);
294: return (code != 0xFFFF);
295: }
296:
297: /**
298: * Returns an array of unicode ranges that are supported by this LinuxFont.
299: */
300: public int[] getUnicodeRanges() {
301: int[] ranges = new int[fontUnicodeRanges.length];
302: System.arraycopy(fontUnicodeRanges, 0, ranges, 0,
303: fontUnicodeRanges.length);
304:
305: return ranges;
306: }
307:
308: /**
309: * Return Font object if it was successfully embedded in System
310: */
311: public static Font embedFont(String absolutePath)
312: throws IOException {
313: return LinuxNativeFont.embedFont(absolutePath);
314: }
315:
316: public String getFontName() {
317: if ((pFont != 0) && (faceName == null)) {
318: if (this .fontType == FontManager.FONT_TYPE_T1) {
319: faceName = getFamily();
320: } else {
321: faceName = LinuxNativeFont.getFontNameNative(pFont);
322: }
323: }
324: return faceName;
325: }
326:
327: public String getFamily() {
328: if ((pFont != 0) && (fontFamilyName == null)) {
329: fontFamilyName = LinuxNativeFont.getFamilyNative(pFont);
330: }
331: return fontFamilyName;
332: }
333:
334: /**
335: * Returns initiated FontExtraMetrics instance of this WindowsFont.
336: */
337: public FontExtraMetrics getExtraMetrics() {
338: if (extraMetrix == null) {
339: float[] metrics = LinuxNativeFont.getExtraMetricsNative(
340: pFont, size, fontType);
341: if (metrics == null) {
342: return null;
343: }
344:
345: //!! for Type1 fonts 'x' char width used as average char width
346: if (fontType == FontManager.FONT_TYPE_T1) {
347: metrics[0] = this .charWidth('x');
348: }
349:
350: extraMetrix = new FontExtraMetrics(metrics);
351: }
352:
353: return extraMetrix;
354: }
355:
356: /**
357: * Returns native font handle of this font peer.
358: */
359: public long getFontHandle(boolean isAntialiased) {
360: if (!isAntialiased) {
361: return this .getFontHandle();
362: } else {
363: if (aaFont == 0) {
364: aaFont = LinuxNativeFont.getAntialiasedFont(pFont,
365: this .display, true);
366: }
367: return aaFont;
368: }
369: }
370: }
|