1 /*
2 * << H a r u --free pdf library >> -- PdfFonts.cpp
3 *
4 * Copyright (c) 1999-2003 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
5 *
6 * Permission to use, copy, modify, distribute and sell this software
7 * and its documentation for any purpose is hereby granted without fee,
8 * provided that the above copyright notice appear in all copies and
9 * that both that copyright notice and this permission notice appear
10 * in supporting documentation.
11 * It is provided "as is" without express or implied warranty.
12 *
13 */
14
15 #include <assert.h>
16 #include <new>
17 #include "libharu.h"
18
19 /*----------------------------------------------------------------------------*/
20 /*----- PdfFontBase class ----------------------------------------------------*/
21
PdfFontBase(PdfXref * xref)22 PdfFontBase::PdfFontBase(PdfXref *xref)
23 : PdfStream(xref)
24 {
25 fName = NULL;
26 fWritingMode = PDF_WMODE_HORIZONTAL;
27 }
28
~PdfFontBase()29 PdfFontBase::~PdfFontBase()
30 {
31 delete[] fName;
32 PDF_DEBUG_PRINT(("++ [%x] fName delete.\n", (int)fName));
33 }
34
35 pdf_text_width
TextWidth(const char * text)36 PdfFontBase::TextWidth(const char* text)
37 {
38 return TextWidths(text, NULL);
39 }
40
41 pdf_text_width
TextWidths(const char * text,unsigned int * widths)42 PdfFontBase::TextWidths(const char* text, unsigned int* widths)
43 {
44 pdf_text_width ret;
45
46 ret.width = 0;
47 ret.numchars = 0;
48 ret.numwords = 0;
49
50 return ret;
51 }
52
53 unsigned int
MeasureText(const char * text,double width,double fontsize,double charspace,double wordspace,double * realwdth)54 PdfFontBase::MeasureText(const char* text, double width,
55 double fontsize, double charspace, double wordspace, double* realwdth)
56 {
57 return 0;
58 }
59
60 /*----------------------------------------------------------------------------*/
61 /*----- PdfFontMgr class -----------------------------------------------------*/
62
PdfFontMgr(PdfXref * xref)63 PdfFontMgr::PdfFontMgr(PdfXref *xref)
64 {
65 assert(xref);
66
67 fXref = xref;
68 fList = NULL;
69 }
70
~PdfFontMgr()71 PdfFontMgr::~PdfFontMgr()
72 {
73 delete fList;
74 }
75
76 int
RegisterFont(PdfFont * font)77 PdfFontMgr::RegisterFont(PdfFont* font)
78 {
79 assert(font);
80
81 if (fList == NULL)
82 fList = new PdfList();
83
84 if (font->Name() == NULL)
85 throw PdfException(PDF_RUNTIME_ERROR,
86 "ERROR: PdfFontMgr::RegisterFont: "
87 "invalid font --name is null.");
88
89 if (GetFont(font->Name()) != NULL)
90 throw PdfException(PDF_RUNTIME_ERROR,
91 "ERROR: PdfFontMgr::RegisterFont: "
92 "duplicate font registration[%s]", font->Name());
93
94 if (font->GetObjectType() != PDF_OBJ_TYPE_INDIRECT)
95 throw PdfException(PDF_RUNTIME_ERROR,
96 "ERROR: PdfFontMgr::RegisterFont: "
97 "font must be indirect object[%s]", font->Name());
98
99 fList->AddItem(font);
100 return fList->CountItems() - 1;
101 }
102
103 PdfFont*
GetFont(const char * name)104 PdfFontMgr::GetFont(const char* name)
105 {
106 if (fList == NULL || name == NULL)
107 return NULL;
108
109 for (int i = 0; i < fList->CountItems(); i++) {
110 PdfFont* f = GetFont(i);
111 const char* fname = f->Name();
112 if (strcmp(name, fname) == 0) {
113 PDF_DEBUG_PRINT(("PdfFontMgr found font %s[%d]\n", fname, i));
114 return f;
115 }
116 }
117 return NULL;
118 }
119
120 /*----------------------------------------------------------------------------*/
121 /*----- PdfType1Font class ---------------------------------------------------*/
122
PdfType1Font(PdfXref * xref)123 PdfType1Font::PdfType1Font(PdfXref *xref)
124 : PdfFontBase(xref)
125 {
126 fValid = false;
127 fWidths = NULL;
128 fFontDef = NULL;
129 fEncoding = NULL;
130 fDescriptor = NULL;
131 fFirstChar = 0;
132 fLastChar = 0;
133 fMissingWidth = 0;
134 fFlags = 0;
135 }
136
137 void
SetAttributes(const char * name,PdfType1FontDef * fontdef,PdfEncodingDef * encoding)138 PdfType1Font::SetAttributes(const char* name, PdfType1FontDef* fontdef,
139 PdfEncodingDef* encoding)
140 {
141 assert(fValid == false);
142 assert(fontdef != false);
143
144 fFontDef = fontdef;
145 fEncoding = encoding;
146 PdfArray* width_array = NULL;
147 fFlags = fFontDef->Flags();
148
149 fName = new char[strlen(name) + 1];
150 PDF_DEBUG_PRINT(("++ [%x] fName new.\n", (int)fName));
151
152 strcpy(fName, name);
153 AddElement("Type", new PdfName("Font"));
154
155 if (!IsBase14Font()) {
156 width_array = new PdfArray(GetXref());
157 AddElement("Widths", width_array);
158 }
159
160 /* FONT_SPECIFIC encoding */
161 if (fEncoding == NULL || fEncoding->BaseEncoding() == PDF_FONT_SPECIFIC) {
162 fFirstChar = fFontDef->FirstChar();
163 fLastChar = fFontDef->LastChar();
164
165 PDF_DEBUG_PRINT(("PdfType1Font --FirstChar=%d, LastChar=%d \n",
166 fFirstChar, fLastChar));
167
168 if (fFontDef->DefaultEncoding() == PDF_FONT_SPECIFIC) {
169 fFlags ^= PDF_FONT_STD_CHARSET;
170 fFlags |= PDF_FONT_SYMBOLIC;
171 }
172 } else {
173 fFirstChar = fEncoding->FirstChar();
174 fLastChar = fEncoding->LastChar();
175 }
176
177 fWidths = new int[fLastChar - fFirstChar + 1];
178 PDF_DEBUG_PRINT(("++ [%x] PdfType1Font::fWidths new.\n", (int)fWidths));
179
180 if (fEncoding == NULL || fEncoding->BaseEncoding() == PDF_FONT_SPECIFIC) {
181 for (int i = fFirstChar, j = 0; i <= fLastChar; i++, j++) {
182
183 fWidths[j] = fFontDef->Widths(i);
184 if (!IsBase14Font())
185 width_array->Add(new PdfNumber(fWidths[j]));
186 }
187 } else {
188 for (unsigned int i = fEncoding->FirstChar(), j = 0;
189 i <= fEncoding->LastChar(); i++, j++) {
190 const char* char_name = fEncoding->GetCharName(i);
191
192 fWidths[j] = fFontDef->Widths(char_name);
193 PDF_DEBUG_PRINT(("PdfType1Font --char_name=%s, code=%d, "
194 "width=%d\n", char_name, i, fWidths[j]));
195 if (!IsBase14Font())
196 width_array->Add(new PdfNumber(fWidths[j]));
197 }
198 }
199 fMissingWidth = fFontDef->MissingWidth();
200
201 AddElement("Subtype", new PdfName("Type1"));
202 AddElement("BaseFont", new PdfName(fFontDef->BaseFont()));
203 AddElement("FirstChar", new PdfNumber(fFirstChar));
204 AddElement("LastChar", new PdfNumber(fLastChar));
205
206 if (fEncoding != NULL) {
207 PdfObject* obj = fEncoding->GetEncoding(this->GetXref());
208 if (obj != NULL)
209 AddElement("Encoding", obj);
210 }
211
212 if (!IsBase14Font())
213 CreateDescriptor();
214 else
215 fDescriptor = NULL;
216
217 fValid = true;
218 }
219
~PdfType1Font()220 PdfType1Font::~PdfType1Font()
221 {
222 PDF_DEBUG_PRINT(("++ [%x] PdfType1Font::fWidths delete.\n", (int)fWidths));
223 delete[] fWidths;
224 }
225
226 pdf_text_width
TextWidth(const char * text)227 PdfType1Font::TextWidth(const char* text)
228 {
229 return TextWidths(text, NULL);
230 }
231
232 pdf_text_width
TextWidths(const char * text,unsigned int * widths)233 PdfType1Font::TextWidths(const char* text, unsigned int* widths)
234 {
235 int len = strlen(text);
236 pdf_text_width ret;
237 unsigned int* tmp_widths = widths;
238
239 ret.width = 0;
240 ret.numchars = 0;
241 ret.numwords = 0;
242 const unsigned char* p = (const unsigned char*)text;
243
244 for (int i = 0; i < len; i++, p++) {
245 ret.width += CharWidth(*p);
246
247 if (tmp_widths != NULL) {
248 *tmp_widths = CharWidth(*p);
249 tmp_widths++;
250 }
251 ret.numchars++;
252 if (*p == ' ')
253 ret.numwords++;
254 }
255
256 return ret;
257 }
258
259 unsigned int
MeasureText(const char * text,double width,double fontsize,double charspace,double wordspace,double * realwidth)260 PdfType1Font::MeasureText(const char* text, double width,
261 double fontsize, double charspace, double wordspace, double* realwidth)
262 {
263 double w = 0;
264 int ln = strlen(text);
265 int tmp_ln = 0;
266 const char* tmp_char = text;
267
268 for (int i = 0; i < ln; i++) {
269 w += CharWidth(*tmp_char) * fontsize / 1000;
270 if (w > width)
271 {
272 if (tmp_ln > 0)
273 {
274 return (unsigned int)tmp_ln;
275 }
276 else
277 {
278 if (realwidth != NULL)
279 {
280 *realwidth = w;
281 }
282 return (unsigned int)i;
283 }
284 }
285 if (realwidth != NULL)
286 *realwidth = w;
287 if (i > 0)
288 w += charspace;
289 if (*tmp_char == ' ') {
290 w += wordspace;
291 tmp_ln = i + 1;
292 }
293 tmp_char++;
294 }
295
296 return (int)ln;
297 }
298
299 int
Ascent()300 PdfType1Font::Ascent()
301 {
302 return (GetValid() ? fFontDef->Ascent() : 0);
303 }
304
305 int
Descent()306 PdfType1Font::Descent()
307 {
308 return (GetValid() ? fFontDef->Descent() : 0);
309 }
310
311 bool
CreateDescriptor()312 PdfType1Font::CreateDescriptor()
313 {
314 /* if the font data is shared by other font objects, also FontDescripter
315 * data will be shared.
316 */
317 if (fFontDef->Descriptor() != NULL) {
318 fDescriptor = fFontDef->Descriptor();
319 AddElement("FontDescriptor", fDescriptor);
320 return false;
321 }
322
323 /* create font descriptor as a indirect object. */
324 fDescriptor = new PdfDictionary(GetXref());
325 GetXref()->AddObject(fDescriptor);
326 AddElement("FontDescriptor", fDescriptor);
327
328 fDescriptor->AddElement("Type", new PdfName("FontDescriptor"));
329 fDescriptor->AddElement("Ascent", new PdfNumber(fFontDef->Ascent()));
330 fDescriptor->AddElement("CapHeight", new PdfNumber(fFontDef->CapHeight()));
331 fDescriptor->AddElement("Descent", new PdfNumber(fFontDef->Descent()));
332
333 PdfArray *bbox = new PdfArray(GetXref());
334 fDescriptor->AddElement("FontBBox", bbox);
335 bbox->Add(fFontDef->FontBBox());
336 fDescriptor->AddElement("FontName", new PdfName(fFontDef->FontName()));
337
338 fDescriptor->AddElement("ItalicAngle",
339 new PdfNumber(fFontDef->ItalicAngle()));
340 fDescriptor->AddElement("StemV", new PdfNumber(fFontDef->StemV()));
341 fDescriptor->AddElement("Flags", new PdfNumber(fFlags));
342
343 if (strlen(fFontDef->CharSet()) > 0)
344 fDescriptor->AddElement("CharSet", new PdfName(fFontDef->CharSet()));
345 if (fFontDef->XHeight() != 0)
346 fDescriptor->AddElement("XHeight", new PdfNumber(fFontDef->XHeight()));
347
348 if (fFontDef->FontData() != NULL) {
349 /* create font file stream as a indirect object. */
350 PdfStream *font_file = new PdfStream(GetXref());
351 GetXref()->AddObject(font_file);
352 font_file->AddFilter(PDF_FILTER_DEFLATE);
353 fDescriptor->AddElement("FontFile", font_file);
354
355 fFontDef->FontData()->WriteToStream(font_file->GetStream());
356 font_file->AddElement("Length1", new PdfNumber(fFontDef->Length1()));
357 font_file->AddElement("Length2", new PdfNumber(fFontDef->Length2()));
358 font_file->AddElement("Length3", new PdfNumber(fFontDef->Length3()));
359 }
360
361 fFontDef->SetDescriptor(fDescriptor);
362
363 return true;
364 }
365
366 /*----------------------------------------------------------------------------*/
367
368