OSDN Git Service

binding with libharu.
[putex/putex.git] / src / texsourc / lib / libhpdf / src / hpdf_font_type1.c
1 /*
2  * << Haru Free PDF Library >> -- hpdf_font_type1.c
3  *
4  * URL: http://libharu.org
5  *
6  * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7  * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8  *
9  * Permission to use, copy, modify, distribute and sell this software
10  * and its documentation for any purpose is hereby granted without fee,
11  * provided that the above copyright notice appear in all copies and
12  * that both that copyright notice and this permission notice appear
13  * in supporting documentation.
14  * It is provided "as is" without express or implied warranty.
15  *
16  */
17
18 #include "hpdf_conf.h"
19 #include "hpdf_utils.h"
20 #include "hpdf_font.h"
21
22 static HPDF_STATUS
23 Type1Font_OnWrite  (HPDF_Dict    obj,
24           HPDF_Stream  stream);
25
26
27 static void
28 Type1Font_OnFree  (HPDF_Dict  obj);
29
30
31 static HPDF_TextWidth
32 Type1Font_TextWidth  (HPDF_Font        font,
33                       const HPDF_BYTE  *text,
34                       HPDF_UINT        len);
35
36
37 static HPDF_UINT
38 Type1Font_MeasureText  (HPDF_Font          font,
39                         const HPDF_BYTE   *text,
40                         HPDF_UINT          len,
41                         HPDF_REAL          width,
42                         HPDF_REAL          font_size,
43                         HPDF_REAL          char_space,
44                         HPDF_REAL          word_space,
45                         HPDF_BOOL          wordwrap,
46                         HPDF_REAL         *real_width);
47
48
49 static HPDF_STATUS
50 Type1Font_CreateDescriptor  (HPDF_MMgr  mmgr,
51                              HPDF_Font  font,
52                              HPDF_Xref  xref);
53
54
55 HPDF_Font
56 HPDF_Type1Font_New  (HPDF_MMgr        mmgr,
57                      HPDF_FontDef     fontdef,
58                      HPDF_Encoder     encoder,
59                      HPDF_Xref        xref)
60 {
61     HPDF_Dict font;
62     HPDF_FontAttr attr;
63     HPDF_Type1FontDefAttr fontdef_attr;
64     HPDF_BasicEncoderAttr encoder_attr;
65     HPDF_STATUS ret = 0;
66     HPDF_UINT i;
67
68     HPDF_PTRACE ((" HPDF_Type1Font_New\n"));
69
70     /* check whether the fontdef object and the encoder object is valid. */
71     if (encoder->type != HPDF_ENCODER_TYPE_SINGLE_BYTE) {
72         HPDF_SetError(mmgr->error, HPDF_INVALID_ENCODER_TYPE, 0);
73         return NULL;
74     }
75
76     if (fontdef->type != HPDF_FONTDEF_TYPE_TYPE1) {
77         HPDF_SetError(mmgr->error, HPDF_INVALID_FONTDEF_TYPE, 0);
78         return NULL;
79     }
80
81     font = HPDF_Dict_New (mmgr);
82     if (!font)
83         return NULL;
84
85     font->header.obj_class |= HPDF_OSUBCLASS_FONT;
86
87     attr = HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec));
88     if (!attr) {
89         HPDF_Dict_Free (font);
90         return NULL;
91     }
92
93     font->header.obj_class |= HPDF_OSUBCLASS_FONT;
94     font->write_fn = Type1Font_OnWrite;
95     font->free_fn = Type1Font_OnFree;
96
97     HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec));
98
99     font->attr = attr;
100     attr->type = HPDF_FONT_TYPE1;
101     attr->writing_mode = HPDF_WMODE_HORIZONTAL;
102     attr->text_width_fn = Type1Font_TextWidth;
103     attr->measure_text_fn = Type1Font_MeasureText;
104     attr->fontdef = fontdef;
105     attr->encoder = encoder;
106     attr->xref = xref;
107
108     /* singlebyte-font has a widths-array which is an array of 256 signed
109      * short integer.
110      */
111     attr->widths = HPDF_GetMem (mmgr, sizeof(HPDF_INT16) * 256);
112     if (!attr->widths) {
113         HPDF_Dict_Free (font);
114         return NULL;
115     }
116
117     encoder_attr = (HPDF_BasicEncoderAttr)encoder->attr;
118
119     HPDF_MemSet (attr->widths, 0, sizeof(HPDF_INT16) * 256);
120     for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) {
121         HPDF_UNICODE u = encoder_attr->unicode_map[i];
122
123         HPDF_UINT16 w = HPDF_Type1FontDef_GetWidth (fontdef, u);
124         attr->widths[i] = w;
125     }
126
127     fontdef_attr = (HPDF_Type1FontDefAttr)fontdef->attr;
128
129     ret += HPDF_Dict_AddName (font, "Type", "Font");
130     ret += HPDF_Dict_AddName (font, "BaseFont", fontdef->base_font);
131     ret += HPDF_Dict_AddName (font, "Subtype", "Type1");
132
133     if (!fontdef_attr->is_base14font) {
134         if (fontdef->missing_width != 0)
135             ret += HPDF_Dict_AddNumber (font, "MissingWidth",
136                     fontdef->missing_width);
137
138         ret += Type1Font_CreateDescriptor (mmgr, font, xref);
139     }
140
141     if (ret != HPDF_OK) {
142         HPDF_Dict_Free (font);
143         return NULL;
144     }
145
146     if (HPDF_Xref_Add (xref, font) != HPDF_OK)
147         return NULL;
148
149     return font;
150 }
151
152
153 static HPDF_STATUS
154 Type1Font_CreateDescriptor  (HPDF_MMgr  mmgr,
155                              HPDF_Font  font,
156                              HPDF_Xref  xref)
157 {
158     HPDF_FontAttr font_attr = (HPDF_FontAttr)font->attr;
159     HPDF_FontDef def = font_attr->fontdef;
160     HPDF_Type1FontDefAttr def_attr = (HPDF_Type1FontDefAttr)def->attr;
161
162     HPDF_PTRACE ((" HPDF_Type1Font_CreateDescriptor\n"));
163
164     if (!font_attr->fontdef->descriptor) {
165         HPDF_Dict descriptor = HPDF_Dict_New (mmgr);
166         HPDF_STATUS ret = 0;
167         HPDF_Array array;
168
169         if (!descriptor)
170             return HPDF_Error_GetCode (font->error);
171
172         ret += HPDF_Xref_Add (xref, descriptor);
173         ret += HPDF_Dict_AddName (descriptor, "Type", "FontDescriptor");
174         ret += HPDF_Dict_AddNumber (descriptor, "Ascent", def->ascent);
175         ret += HPDF_Dict_AddNumber (descriptor, "Descent", def->descent);
176         ret += HPDF_Dict_AddNumber (descriptor, "Flags", def->flags);
177
178         array = HPDF_Box_Array_New (mmgr, def->font_bbox);
179         ret += HPDF_Dict_Add (descriptor, "FontBBox", array);
180
181         ret += HPDF_Dict_AddName (descriptor, "FontName",
182                 font_attr->fontdef->base_font);
183         ret += HPDF_Dict_AddNumber (descriptor, "ItalicAngle",
184                 def->italic_angle);
185         ret += HPDF_Dict_AddNumber (descriptor, "StemV", def->stemv);
186         ret += HPDF_Dict_AddNumber (descriptor, "XHeight", def->x_height);
187
188         if (def_attr->char_set)
189             ret += HPDF_Dict_AddName (descriptor, "CharSet",
190                         def_attr->char_set);
191
192         if (ret != HPDF_OK)
193             return HPDF_Error_GetCode (font->error);
194
195         if (def_attr->font_data) {
196             HPDF_Dict font_data = HPDF_DictStream_New (mmgr, xref);
197
198             if (!font_data)
199                 return HPDF_Error_GetCode (font->error);
200
201             if (HPDF_Stream_WriteToStream (def_attr->font_data,
202                 font_data->stream, HPDF_STREAM_FILTER_NONE, NULL) != HPDF_OK)
203                 return HPDF_Error_GetCode (font->error);
204
205             ret += HPDF_Dict_Add (descriptor, "FontFile", font_data);
206             ret += HPDF_Dict_AddNumber (font_data, "Length1",
207                     def_attr->length1);
208             ret += HPDF_Dict_AddNumber (font_data, "Length2",
209                     def_attr->length2);
210             ret += HPDF_Dict_AddNumber (font_data, "Length3",
211                     def_attr->length3);
212
213             font_data->filter = font->filter;
214         }
215
216         if (ret != HPDF_OK)
217             return HPDF_Error_GetCode (font->error);
218
219         font_attr->fontdef->descriptor = descriptor;
220     }
221
222     return HPDF_Dict_Add (font, "FontDescriptor",
223             font_attr->fontdef->descriptor);
224 }
225
226
227 static HPDF_TextWidth
228 Type1Font_TextWidth  (HPDF_Font        font,
229                       const HPDF_BYTE  *text,
230                       HPDF_UINT        len)
231 {
232     HPDF_FontAttr attr = (HPDF_FontAttr)font->attr;
233     HPDF_TextWidth ret = {0, 0, 0, 0};
234     HPDF_UINT i;
235     HPDF_BYTE b = 0;
236
237     HPDF_PTRACE ((" HPDF_Type1Font_TextWidth\n"));
238
239     if (attr->widths) {
240         for (i = 0; i < len; i++) {
241             b = text[i];
242             ret.numchars++;
243             ret.width += attr->widths[b];
244
245             if (HPDF_IS_WHITE_SPACE(b)) {
246                 ret.numspace++;
247                 ret.numwords++;
248             }
249         }
250     } else
251         HPDF_SetError (font->error, HPDF_FONT_INVALID_WIDTHS_TABLE, 0);
252
253     /* 2006.08.19 add. */
254     if (HPDF_IS_WHITE_SPACE(b))
255         ; /* do nothing. */
256     else
257         ret.numwords++;
258
259     return ret;
260 }
261
262
263 static HPDF_UINT
264 Type1Font_MeasureText (HPDF_Font          font,
265                        const HPDF_BYTE   *text,
266                        HPDF_UINT          len,
267                        HPDF_REAL          width,
268                        HPDF_REAL          font_size,
269                        HPDF_REAL          char_space,
270                        HPDF_REAL          word_space,
271                        HPDF_BOOL          wordwrap,
272                        HPDF_REAL         *real_width)
273 {
274     HPDF_REAL w = 0;
275     HPDF_UINT tmp_len = 0;
276     HPDF_UINT i;
277     HPDF_FontAttr attr = (HPDF_FontAttr)font->attr;
278
279     HPDF_PTRACE ((" HPDF_Type1Font_MeasureText\n"));
280
281     for (i = 0; i < len; i++) {
282         HPDF_BYTE b = text[i];
283
284         if (HPDF_IS_WHITE_SPACE(b)) {
285             tmp_len = i + 1;
286
287             if (real_width)
288                 *real_width = w;
289
290             w += word_space;
291         } else if (!wordwrap) {
292             tmp_len = i;
293
294             if (real_width)
295                 *real_width = w;
296         }
297
298         w += attr->widths[b] * font_size / 1000;
299
300         /* 2006.08.04 break when it encountered  line feed */
301         if (w > width || b == 0x0A)
302             return tmp_len;
303
304         if (i > 0)
305             w += char_space;
306     }
307
308     /* all of text can be put in the specified width */
309     if (real_width)
310         *real_width = w;
311
312     return len;
313 }
314
315
316 static HPDF_STATUS
317 Type1Font_OnWrite  (HPDF_Dict    obj,
318           HPDF_Stream  stream)
319 {
320     HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr;
321     HPDF_Type1FontDefAttr fontdef_attr =
322                     (HPDF_Type1FontDefAttr)attr->fontdef->attr;
323     HPDF_BasicEncoderAttr encoder_attr =
324                     (HPDF_BasicEncoderAttr)attr->encoder->attr;
325     HPDF_UINT i;
326     HPDF_STATUS ret;
327     char buf[HPDF_TMP_BUF_SIZ];
328     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
329
330     HPDF_PTRACE ((" HPDF_Font_Type1Font_OnWrite\n"));
331
332     /* if font is base14-font these entries is not required */
333     if (!fontdef_attr->is_base14font || encoder_attr->has_differences) {
334         char *pbuf;
335
336         pbuf = (char *)HPDF_StrCpy (buf, "/FirstChar ", eptr);
337         pbuf = HPDF_IToA (pbuf, encoder_attr->first_char, eptr);
338         HPDF_StrCpy (pbuf, "\012", eptr);
339         if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
340             return ret;
341
342         pbuf = (char *)HPDF_StrCpy (buf, "/LastChar ", eptr);
343         pbuf = HPDF_IToA (pbuf, encoder_attr->last_char, eptr);
344         HPDF_StrCpy (pbuf, "\012", eptr);
345         if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
346             return ret;
347
348         /* Widths entry */
349         if ((ret = HPDF_Stream_WriteEscapeName (stream, "Widths")) != HPDF_OK)
350             return ret;
351
352         if ((ret = HPDF_Stream_WriteStr (stream, " [\012")) != HPDF_OK)
353             return ret;
354
355         pbuf = buf;
356         for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) {
357
358             pbuf = HPDF_IToA (pbuf, attr->widths[i], eptr);
359             *pbuf++ = ' ';
360
361             if ((i + 1) % 16 == 0) {
362                 HPDF_StrCpy(pbuf, "\012", eptr);
363                 if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
364                     return ret;
365                 pbuf = buf;
366             }
367         }
368
369         HPDF_StrCpy (pbuf, "]\012", eptr);
370
371         if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
372             return ret;
373     }
374
375     return attr->encoder->write_fn (attr->encoder, stream);
376 }
377
378
379 static void
380 Type1Font_OnFree  (HPDF_Dict  obj)
381 {
382     HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr;
383
384     HPDF_PTRACE ((" HPDF_Type1Font_OnFree\n"));
385
386     if (attr) {
387         if (attr->widths) {
388             HPDF_FreeMem (obj->mmgr, attr->widths);
389         }
390         HPDF_FreeMem (obj->mmgr, attr);
391     }
392 }
393
394