KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > it > stefanochizzolini > clown > documents > contents > fonts > Font


1 /*
2   Copyright © 2006,2007 Stefano Chizzolini. http://clown.stefanochizzolini.it
3
4   Contributors:
5     * Stefano Chizzolini (original code developer, info@stefanochizzolini.it):
6       contributed code is Copyright © 2006,2007 by Stefano Chizzolini.
7
8   This file should be part of the source code distribution of "PDF Clown library"
9   (the Program): see the accompanying README files for more info.
10
11   This Program is free software; you can redistribute it and/or modify it under
12   the terms of the GNU General Public License as published by the Free Software
13   Foundation; either version 2 of the License, or (at your option) any later version.
14
15   This Program is distributed in the hope that it will be useful, but WITHOUT ANY
16   WARRANTY, either expressed or implied; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more details.
18
19   You should have received a copy of the GNU General Public License along with this
20   Program (see README files); if not, go to the GNU website (http://www.gnu.org/).
21
22   Redistribution and use, with or without modification, are permitted provided that such
23   redistributions retain the above copyright notice, license and disclaimer, along with
24   this list of conditions.
25 */

26
27 package it.stefanochizzolini.clown.documents.contents.fonts;
28
29 import it.stefanochizzolini.clown.documents.Document;
30 import it.stefanochizzolini.clown.files.File;
31 import it.stefanochizzolini.clown.objects.IPdfNumber;
32 import it.stefanochizzolini.clown.objects.PdfArray;
33 import it.stefanochizzolini.clown.objects.PdfDictionary;
34 import it.stefanochizzolini.clown.objects.PdfDirectObject;
35 import it.stefanochizzolini.clown.objects.PdfName;
36 import it.stefanochizzolini.clown.objects.PdfObjectWrapper;
37 import it.stefanochizzolini.clown.objects.PdfReference;
38 import it.stefanochizzolini.clown.objects.PdfStream;
39
40 import java.util.EnumSet JavaDoc;
41 import java.util.Hashtable JavaDoc;
42
43 /**
44   Abstract font [PDF:1.6:5.4].
45 */

46 public abstract class Font
47   extends PdfObjectWrapper<PdfDictionary>
48 {
49   // <class>
50
// <classes>
51
/**
52     Font descriptor flags [PDF:1.6:5.7.1].
53   */

54   public enum FlagsEnum
55   {
56     // <class>
57
// <static>
58
// <fields>
59
/**
60       All glyphs have the same width.
61     */

62     FixedPitch(0x1),
63     /**
64       Glyphs have serifs.
65     */

66     Serif(0x2),
67     /**
68       Font contains glyphs outside the Adobe standard Latin character set.
69     */

70     Symbolic(0x4),
71     /**
72       Glyphs resemble cursive handwriting.
73     */

74     Script(0x8),
75     /**
76       Font uses the Adobe standard Latin character set.
77     */

78     Nonsymbolic(0x20),
79     /**
80       Glyphs have dominant vertical strokes that are slanted.
81     */

82     Italic(0x40),
83     /**
84       Font contains no lowercase letters.
85     */

86     AllCap(0x10000),
87     /**
88       Font contains both uppercase and lowercase letters.
89     */

90     SmallCap(0x20000),
91     /**
92       Thicken bold glyphs at small text sizes.
93     */

94     ForceBold(0x40000);
95     // </fields>
96
// </static>
97

98     // <dynamic>
99
// <fields>
100
/**
101       <h3>Remarks</h3>
102       <p>Bitwise code MUST be explicitly distinct from the ordinal position of the enum constant
103       as they don't coincide.</p>
104     */

105     private int code;
106     // </fields>
107

108     // <constructors>
109
private FlagsEnum(
110       int code
111       )
112     {this.code = code;}
113     // </constructors>
114

115     // <interface>
116
// <public>
117
public int getCode(
118       )
119     {return code;}
120     // </public>
121
// </interface>
122
// </dynamic>
123
// </class>
124
}
125   // </classes>
126

127   // <static>
128
// <interface>
129
// <public>
130
/**
131     Gets the scaling factor to be applied to unscaled metrics to get actual measures.
132   */

133   public static final double getScalingFactor(
134     double size
135     )
136   {return (0.001 * size);}
137
138   /**
139     Wraps a font reference into a font object.
140     @param reference Reference to a font object.
141     @return Font object associated to the reference.
142   */

143   public static final Font wrap(
144     PdfReference reference
145     )
146   {
147     /*
148       NOTE: This is a factory method for any font-derived object.
149     */

150     if(reference == null)
151       return null;
152
153     PdfDictionary fontData = (PdfDictionary)reference.getDataObject();
154     PdfName fontType = (PdfName)fontData.get(PdfName.Subtype);
155
156     {
157       // Has the font been already instantiated?
158
/*
159         NOTE: Font structures are reified as complex objects, both IO- and CPU-intensive to load.
160         So, it's convenient to retrieve them from a common cache whenever possible.
161       */

162       Hashtable JavaDoc cache = reference.getIndirectObject().getFile().getDocument().cache;
163       if(cache.containsKey(reference))
164       {return (Font)cache.get(reference);}
165     }
166
167     // Is it a Type 1 font?
168
if(fontType.equals(PdfName.Type1)) // Type 1.
169
{
170       // Is it a standard Type 1 font?
171
if(fontData.get(PdfName.FirstChar) == null) // Standard Type 1.
172
{return new StandardType1Font(reference);}
173       else // Custom Type 1.
174
{
175         PdfDictionary fontDescriptor = (PdfDictionary)File.resolve(fontData.get(PdfName.FontDescriptor));
176         // Is it a plain-old Type 1 font?
177
if(fontDescriptor.containsKey(PdfName.FontFile)) // Plain-old Type 1.
178
{return new Type1Font(reference);}
179         else // Compact Font Format Type 1.
180
{
181           PdfName fontFileSubtype = (PdfName)((PdfStream)File.resolve(fontDescriptor.get(PdfName.FontFile3))).getHeader().get(PdfName.Subtype);
182           if(fontFileSubtype.equals(PdfName.Type1C)) // Stand-alone CFF.
183
{return new Type1Font(reference);}
184           else if(fontFileSubtype.equals(PdfName.OpenType)) // OpenType-wrapped CFF.
185
{return new OpenTypeFont(reference);}
186           else // Unknown.
187
{return null;}
188         }
189       }
190     }
191     // Is it a TrueType font?
192
else if(fontType.equals(PdfName.TrueType)) // TrueType.
193
{return new OpenTypeFont(reference);}
194     else // Unknown.
195
{return null;}
196   }
197   // </public>
198
// </interface>
199
// </static>
200

201   // <dynamic>
202
// <constructors>
203
protected Font(
204     Document context
205     )
206   {
207     super(
208       context.getFile(),
209       new PdfDictionary(
210         new PdfName[]{PdfName.Type},
211         new PdfDirectObject[]{PdfName.Font}
212         )
213       );
214     initialize();
215   }
216
217   protected Font(
218     PdfDirectObject baseObject
219     )
220   {
221     super(
222       baseObject,
223       null // NO container. NOTE: this is a simplification (the spec [PDF:1.6] doesn't apparently prescribe the use of an indirect object for font dictionary, whilst the general practice is as such. If an exception occurs, you'll need to specify the proper container).
224
);
225     initialize();
226   }
227   // </constructors>
228

229   // <interface>
230
// <public>
231
public final boolean equals(
232     Font object
233     )
234   {
235     return (
236       getType() == object.getType()
237         && getName() == object.getName()
238       );
239   }
240
241   /**
242     Gets the vertical offset from the baseline to the ascender line (ascent).
243   */

244   public double getAscent(
245     double size
246     )
247   {
248     return (((IPdfNumber)File.resolve(
249       ((PdfDictionary)File.resolve(
250         getBaseDataObject().get(PdfName.FontDescriptor)
251         )).get(PdfName.Ascent)
252       )).getNumberValue()) * getScalingFactor(size);
253   }
254
255   /**
256     Gets the vertical offset from the baseline to the descender line (descent).
257   */

258   public double getDescent(
259     double size
260     )
261   {
262     return (((IPdfNumber)File.resolve(
263       ((PdfDictionary)File.resolve(
264         getBaseDataObject().get(PdfName.FontDescriptor)
265         )).get(PdfName.Descent)
266       )).getNumberValue()) * getScalingFactor(size);
267   }
268
269   /**
270     Gets the font descriptor flags.
271   */

272   public EnumSet JavaDoc<FlagsEnum> getFlags(
273     )
274   {
275     int flagMask = (int)((IPdfNumber)File.resolve(
276       ((PdfDictionary)File.resolve(
277         getBaseDataObject().get(PdfName.FontDescriptor)
278         )).get(PdfName.Flags)
279       )).getNumberValue();
280
281     EnumSet JavaDoc<FlagsEnum> flags = EnumSet.noneOf(FlagsEnum.class);
282     for(FlagsEnum flag : FlagsEnum.values())
283     {
284       if((flag.getCode() & flagMask) != 0)
285       {flags.add(flag);}
286     }
287
288     return flags;
289   }
290
291   /**
292     Gets the width (kerning inclusive) of the given text, scaled to the given font size.
293   */

294   public final double getKernedWidth(
295     String JavaDoc text,
296     double size
297     )
298   {return (getWidth(text) + getKerning(text)) * getScalingFactor(size);}
299
300   /**
301     Gets the unscaled kerning width between two given characters.
302   */

303   public abstract int getKerning(
304     char textChar1,
305     char textChar2
306     );
307
308   /**
309     Gets the unscaled kerning width inside the given text.
310   */

311   public abstract int getKerning(
312     String JavaDoc text
313     );
314
315   /**
316     Gets the kerning width inside the given text, scaled to the given font size.
317   */

318   public final double getKerning(
319     String JavaDoc text,
320     double size
321     )
322   {return getKerning(text) * getScalingFactor(size);}
323
324   /**
325     Gets the actual line height.
326   */

327   public double getLineHeight(
328     double size
329     )
330   {
331     PdfDictionary descriptor = (PdfDictionary)File.resolve(
332       getBaseDataObject().get(PdfName.FontDescriptor)
333       );
334
335     return (
336       ((IPdfNumber)File.resolve(
337         descriptor.get(PdfName.Ascent)
338         )).getNumberValue()
339       + Math.abs(((IPdfNumber)File.resolve(
340         descriptor.get(PdfName.Descent)
341         )).getNumberValue())
342       ) * getScalingFactor(size);
343   }
344
345   /**
346     Gets the PostScript name of the font.
347   */

348   public final String JavaDoc getName(
349     )
350   {return ((PdfName)getBaseDataObject().get(PdfName.BaseFont)).toString();}
351
352   /**
353     Gets the font type.
354   */

355   public final String JavaDoc getType(
356     )
357   {return ((PdfName)getBaseDataObject().get(PdfName.Subtype)).toString();}
358
359   /**
360     Gets the unscaled width of the given character.
361   */

362   public abstract int getWidth(
363     char textChar
364     );
365
366   /**
367     Gets the unscaled width (kerning exclusive) of the given text.
368   */

369   public abstract int getWidth(
370     String JavaDoc text
371     );
372
373   /**
374     Gets the width (kerning exclusive) of the given text, scaled to the given font size.
375   */

376   public final double getWidth(
377     String JavaDoc text,
378     double size
379     )
380   {return getWidth(text) * getScalingFactor(size);}
381   // </public>
382

383   // <private>
384
private void initialize(
385     )
386   {
387     // Put the newly instantiated font into the common cache!
388
/*
389       NOTE: Font structures are reified as complex objects, both IO- and CPU-intensive to load.
390       So, it's convenient to put them into a common cache for later reuse.
391     */

392     getDocument().cache.put((PdfReference)getBaseObject(),this);
393   }
394   // </private>
395
// </interface>
396
// </dynamic>
397
// </class>
398
}
Popular Tags