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