001: /**
002: * Font.java
003: *
004: Copyright (c) 2007, Innovatics Inc.
005:
006: All rights reserved.
007:
008: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
009:
010: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
011: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
012:
013: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
014: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
015: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
016: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
017: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
018: EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
019: PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
020: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
021: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
022: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
023: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
024: */package com.pdfjet;
025:
026: import java.lang.*;
027: import java.io.*;
028: import java.text.*;
029: import java.util.*;
030: import java.util.zip.*;
031:
032: //>>>>pdfjet {
033: public class Font {
034:
035: protected String name = null;
036: protected int objNumber = 0;
037:
038: // The object number of the embedded font file
039: protected int fileObjNumber = -1;
040:
041: // Font attributes
042: protected double size = 12.0;
043: protected int unitsPerEm = 1000;
044: protected double ascent = 0.0;
045: protected double descent = 0.0;
046: protected double body_height = 0.0;
047:
048: // Font metrics
049: protected int[][] metrics = null;
050:
051: // Don't change the following default values!
052: protected boolean isStandard = true;
053: protected boolean kernPairs = false;
054: protected boolean isComposite = false;
055: protected int firstChar = 32;
056: protected int lastChar = 255;
057:
058: private PDF pdf = null;
059:
060: private boolean isCJK = false;
061: private int codePage = CodePage.CP1252;
062:
063: // Font bounding box
064: private double bBoxLLx = 0.0;
065: private double bBoxLLy = 0.0;
066: private double bBoxURx = 0.0;
067: private double bBoxURy = 0.0;
068:
069: private int[] advanceWidths = null;
070: private int[] glyphWidth = null;
071:
072: // Constructor for standard fonts
073: public Font(PDF pdf, String fontName) throws Exception {
074: this .pdf = pdf;
075: this .name = fontName;
076:
077: pdf.newobj();
078: pdf.append(pdf.buf, "<<\n");
079: pdf.append(pdf.buf, "/Type /Font\n");
080: pdf.append(pdf.buf, "/Subtype /Type1\n");
081: pdf.append(pdf.buf, "/BaseFont /");
082: pdf.append(pdf.buf, fontName);
083: pdf.append(pdf.buf, '\n');
084: if (fontName.equals("Symbol")
085: || fontName.equals("ZapfDingbats")) {
086: // Use the built-in encoding
087: } else {
088: pdf.append(pdf.buf, "/Encoding /WinAnsiEncoding\n");
089: }
090: pdf.append(pdf.buf, ">>\n");
091: pdf.endobj();
092: objNumber = pdf.objNumber;
093:
094: CoreFont font = (CoreFont) Class.forName(
095: "com.pdfjet." + name.replace('-', '_')).newInstance();
096: bBoxLLx = font.getBBoxLLx();
097: bBoxLLy = font.getBBoxLLy();
098: bBoxURx = font.getBBoxURx();
099: bBoxURy = font.getBBoxURy();
100: metrics = font.getMetrics();
101: ascent = bBoxURy * size / unitsPerEm;
102: descent = bBoxLLy * size / unitsPerEm;
103: body_height = ascent - descent;
104:
105: pdf.fonts.add(this );
106: }
107:
108: // Constructor for CJK fonts
109: public Font(PDF pdf, String fontName, int codePage)
110: throws Exception {
111: this .pdf = pdf;
112: this .name = fontName;
113: this .codePage = codePage;
114: isCJK = true;
115: isStandard = false;
116: isComposite = true;
117:
118: firstChar = 0x0020;
119: lastChar = 0xFFEE;
120:
121: // Font Descriptor
122: pdf.newobj();
123: pdf.append(pdf.buf, "<<\n");
124: pdf.append(pdf.buf, "/Type /FontDescriptor\n");
125: pdf.append(pdf.buf, "/FontName /");
126: pdf.append(pdf.buf, fontName);
127: pdf.append(pdf.buf, '\n');
128: pdf.append(pdf.buf, "/Flags 4\n");
129: pdf.append(pdf.buf, "/FontBBox [0 0 0 0]\n");
130: pdf.append(pdf.buf, ">>\n");
131: pdf.endobj();
132:
133: // CIDFont Dictionary
134: pdf.newobj();
135: pdf.append(pdf.buf, "<<\n");
136: pdf.append(pdf.buf, "/Type /Font\n");
137: pdf.append(pdf.buf, "/Subtype /CIDFontType0\n");
138: pdf.append(pdf.buf, "/BaseFont /");
139: pdf.append(pdf.buf, fontName);
140: pdf.append(pdf.buf, '\n');
141: pdf.append(pdf.buf, "/FontDescriptor ");
142: pdf.append(pdf.buf, pdf.objNumber - 1);
143: pdf.append(pdf.buf, " 0 R\n");
144: pdf.append(pdf.buf, "/CIDSystemInfo <<\n");
145: pdf.append(pdf.buf, "/Registry (Adobe)\n");
146: if (fontName.startsWith("AdobeMingStd")) {
147: pdf.append(pdf.buf, "/Ordering (CNS1)\n");
148: pdf.append(pdf.buf, "/Supplement 4\n");
149: } else if (fontName.startsWith("AdobeSongStd")) {
150: pdf.append(pdf.buf, "/Ordering (GB1)\n");
151: pdf.append(pdf.buf, "/Supplement 4\n");
152: } else if (fontName.startsWith("KozMinPro")) {
153: pdf.append(pdf.buf, "/Ordering (Japan1)\n");
154: pdf.append(pdf.buf, "/Supplement 4\n");
155: } else if (fontName.startsWith("AdobeMyungjoStd")) {
156: pdf.append(pdf.buf, "/Ordering (Korea1)\n");
157: pdf.append(pdf.buf, "/Supplement 1\n");
158: } else {
159: throw new Exception("Unsupported font: " + fontName);
160: }
161: pdf.append(pdf.buf, ">>\n");
162: pdf.append(pdf.buf, ">>\n");
163: pdf.endobj();
164:
165: // Type0 Font Dictionary
166: pdf.newobj();
167: pdf.append(pdf.buf, "<<\n");
168: pdf.append(pdf.buf, "/Type /Font\n");
169: pdf.append(pdf.buf, "/Subtype /Type0\n");
170: pdf.append(pdf.buf, "/BaseFont /");
171: if (fontName.startsWith("AdobeMingStd")) {
172: pdf.append(pdf.buf, fontName + "-UniCNS-UTF16-H\n");
173: pdf.append(pdf.buf, "/Encoding /UniCNS-UTF16-H\n");
174: } else if (fontName.startsWith("AdobeSongStd")) {
175: pdf.append(pdf.buf, fontName + "-UniGB-UTF16-H\n");
176: pdf.append(pdf.buf, "/Encoding /UniGB-UTF16-H\n");
177: } else if (fontName.startsWith("KozMinPro")) {
178: pdf.append(pdf.buf, fontName + "-UniJIS-UCS2-H\n");
179: pdf.append(pdf.buf, "/Encoding /UniJIS-UCS2-H\n");
180: } else if (fontName.startsWith("AdobeMyungjoStd")) {
181: pdf.append(pdf.buf, fontName + "-UniKS-UCS2-H\n");
182: pdf.append(pdf.buf, "/Encoding /UniKS-UCS2-H\n");
183: } else {
184: throw new Exception("Unsupported font: " + fontName);
185: }
186: pdf.append(pdf.buf, "/DescendantFonts [");
187: pdf.append(pdf.buf, pdf.objNumber - 1);
188: pdf.append(pdf.buf, " 0 R]\n");
189: pdf.append(pdf.buf, ">>\n");
190: pdf.endobj();
191: objNumber = pdf.objNumber;
192:
193: ascent = size;
194: descent = -ascent / 4;
195: body_height = ascent - descent;
196:
197: pdf.fonts.add(this );
198: }
199:
200: public void setSize(double fontSize) {
201: size = fontSize;
202: if (isCJK) {
203: ascent = size;
204: descent = -ascent / 4;
205: return;
206: }
207: ascent = bBoxURy * size / unitsPerEm;
208: descent = bBoxLLy * size / unitsPerEm;
209: body_height = ascent - descent;
210: }
211:
212: public void setKernPairs(boolean kernPairs) {
213: this .kernPairs = kernPairs;
214: }
215:
216: public double stringWidth(String str) {
217: int width = 0;
218: if (isCJK) {
219: return str.length() * ascent;
220: }
221:
222: for (int i = 0; i < str.length(); i++) {
223: int c1 = str.charAt(i);
224: if (isStandard == false) {
225: if (c1 < firstChar || c1 > lastChar) {
226: width += advanceWidths[0];
227: } else {
228: width += nonStandardFontGlyphWidth(c1);
229: }
230: continue;
231: }
232:
233: if (c1 < firstChar || c1 > lastChar) {
234: c1 = 32;
235: }
236: c1 -= 32;
237: width += metrics[c1][1];
238:
239: if (kernPairs == false)
240: continue;
241: if (name.startsWith("C") || // Courier
242: name.startsWith("S") || // Symbol
243: name.startsWith("Z")) { // ZapfDingbats
244: continue;
245: }
246:
247: if (i == str.length() - 1)
248: break;
249:
250: int c2 = str.charAt(i + 1);
251: if (c2 < firstChar || c2 > lastChar) {
252: c2 = 32;
253: }
254: for (int j = 2; j < metrics[c1].length; j += 2) {
255: if (metrics[c1][j] == c2) {
256: width += metrics[c1][j + 1];
257: break;
258: }
259: }
260: }
261:
262: return width * size / unitsPerEm;
263: }
264:
265: private int nonStandardFontGlyphWidth(int c1) {
266: int width = 0;
267:
268: if (isComposite) {
269: width = glyphWidth[c1];
270: } else {
271: if (c1 < 127) {
272: width = glyphWidth[c1];
273: } else {
274: if (codePage == 0) {
275: width = glyphWidth[CP1250.codes[c1 - 127]];
276: } else if (codePage == 1) {
277: width = glyphWidth[CP1251.codes[c1 - 127]];
278: } else if (codePage == 2) {
279: width = glyphWidth[CP1252.codes[c1 - 127]];
280: } else if (codePage == 3) {
281: width = glyphWidth[CP1253.codes[c1 - 127]];
282: } else if (codePage == 4) {
283: width = glyphWidth[CP1254.codes[c1 - 127]];
284: } else if (codePage == 7) {
285: width = glyphWidth[CP1257.codes[c1 - 127]];
286: }
287: }
288: }
289:
290: return width;
291: }
292:
293: } // End of Font.java
294: //>>>>}
|