1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2
3 Copyright (C) 2002-2014 by Jin-Hwan Cho and Shunsaku Hirata,
4 the dvipdfmx project team.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include "system.h"
26 #include "mem.h"
27 #include "error.h"
28 #include "numbers.h"
29
30 #include "pdfobj.h"
31
32 #include "sfnt.h"
33 #include "tt_table.h"
34 #include "tt_post.h"
35 #include "tt_aux.h"
36
37 static int verbose = 0;
38
tt_aux_set_verbose(void)39 void tt_aux_set_verbose(void)
40 {
41 ++verbose;
42 }
43
ttc_read_offset(sfnt * sfont,int ttc_idx)44 ULONG ttc_read_offset (sfnt *sfont, int ttc_idx)
45 {
46 ULONG offset = 0, num_dirs = 0;
47
48 if (sfont == NULL || sfont->stream == NULL)
49 ERROR("file not opened");
50
51 if (sfont->type != SFNT_TYPE_TTC)
52 ERROR("ttc_read_offset(): invalid font type");
53
54 sfnt_seek_set (sfont, 4); /* skip version tag */
55
56 /* version = */ sfnt_get_ulong(sfont);
57 num_dirs = sfnt_get_ulong(sfont);
58 if (ttc_idx < 0 || ttc_idx > num_dirs - 1)
59 ERROR("Invalid TTC index number");
60
61 sfnt_seek_set (sfont, 12 + ttc_idx * 4);
62 offset = sfnt_get_ulong (sfont);
63
64 return offset;
65 }
66
67 /*
68 Build FontDescriptor (except FontName) from TrueType tables:
69
70 Most information found in FontDescriptor is used only when automatic
71 font substitution is needed. (in the case of missing/broken font data)
72 Some PDF viewers may ignore embedded TrueType glyph data. Especially,
73 any embedded TrueType data for CID-keyed (CIDFontType 2) font is ignored
74 by PDF viewers that only support PDF versions 1.2 or earlier.
75
76 We use those tables to obtain various values of FontDescriptor.
77
78 head: required
79
80 xMin, xMax, yMin, yMax - FontBBox
81 unitsPerEm - conversion to PDF unit (points). see PDFUNIT bellow.
82 The head table must exist in any TrueType font.
83
84 hhea: required
85
86 When the OS/2 table (Windows and OS/2 only) is not available,
87 Ascender and Descender values can be used to estimate Ascent
88 and Descent. The hhea table is required for all TrueType fonts.
89 MaxWidth can be obtained from this table.
90
91 OS/2: required for Windows and OS/2 TrueType, and OpenType
92
93 fsType - liscensing information
94 sCapHeight - CapHeight (version 2 only)
95
96 The sCapHeight is only available in newer TrueType fonts which has
97 version 2 OS/2 table and generally not available. Instead, we can
98 use height of uppercase letter `H'. But we don't use it, we simply
99 use Ascent value.
100
101 sTypoAscender, sTypoDescender - Ascent and Descent
102 usWeightClass - roughly estimate StemV.
103
104 Estimation is based on the following expression:
105
106 stemv = (os2->usWeightClass/65)*(os2->usWeightClass/65)+50
107
108 . I've found this expression in some Adobe document (lost). We use
109 this expression also, otherwise, we must analyze glyph data.
110
111 xAvgCharWidth - AvgWidth (optional)
112 sFamilyClass - Flags
113 sFamilyClass and panose - Panose in Style dictionary (optional)
114
115 post: required
116
117 italicAngle - ItalicAngle
118
119 */
120
121
122 #ifndef PDFUNIT
123 #define PDFUNIT(v) (ROUND((1000.0*(v))/(head->unitsPerEm),1))
124 #endif
125
126 /* Flags: should not come here */
127 #define FIXEDWIDTH (1 << 0) /* Fixed-width font */
128 #define SERIF (1 << 1) /* Serif font */
129 #define SYMBOLIC (1 << 2) /* Symbolic font */
130 #define SCRIPT (1 << 3) /* Script font */
131 #define STANDARD (1 << 5) /* Uses the Adobe Standard Character Set */
132 #define ITALIC (1 << 6) /* Italic */
133 #define ALLCAP (1 << 16) /* All-cap font */
134 #define SMALLCAP (1 << 17) /* Small-cap font */
135 #define FORCEBOLD (1 << 18) /* Force bold at small text sizes */
tt_get_fontdesc(sfnt * sfont,int * embed,int stemv,int type,const char * fontname)136 pdf_obj *tt_get_fontdesc (sfnt *sfont, int *embed, int stemv, int type, const char* fontname)
137 {
138 pdf_obj *descriptor = NULL;
139 pdf_obj *bbox = NULL;
140 int flag = SYMBOLIC;
141 /* TrueType tables */
142 struct tt_head_table *head;
143 struct tt_os2__table *os2;
144 struct tt_post_table *post;
145
146 if (!sfont) {
147 ERROR("font file not opened");
148 }
149
150 os2 = tt_read_os2__table(sfont);
151 head = tt_read_head_table(sfont);
152 post = tt_read_post_table(sfont);
153 if (!post) {
154 if (os2)
155 RELEASE(os2);
156 RELEASE(head);
157 return NULL;
158 }
159
160 descriptor = pdf_new_dict();
161 pdf_add_dict (descriptor,
162 pdf_new_name ("Type"),
163 pdf_new_name ("FontDescriptor"));
164
165 if (*embed && os2) {
166 /*
167 License:
168
169 "Preview & Print embedding" (0x004) requires the document containing
170 Preview & Print font to be opened in read-only mode. However, licensing
171 information are lost when fonts are embedded in PDF document and
172 the only way to make the PDF document "read-only" is to encrypt it.
173 But we have no support for encryption yet. We do not embed any fonts
174 with "Preview & Print embedding" setting.
175
176 2001/11/22: Changed to allow `Preview & Print' only fonts embedding
177
178 2006/04/19: Added support for always_embed option
179 */
180 if (os2->fsType == 0x0000 || (os2->fsType & 0x0008)) {
181 /* the least restrictive license granted takes precedence. */
182 *embed = 1;
183 } else if (os2->fsType & 0x0004) {
184 if (verbose > 0)
185 WARN("Font \"%s\" permits \"Preview & Print\" embedding only **\n", fontname);
186 *embed = 1;
187 } else {
188 if (always_embed) {
189 if (verbose > 0)
190 WARN("Font \"%s\" may be subject to embedding restrictions **\n", fontname);
191 *embed = 1;
192 }
193 else {
194 if (verbose > 0)
195 WARN("Embedding of font \"%s\" disabled due to license restrictions", fontname);
196 *embed = 0;
197 }
198 }
199 }
200
201 if (os2) {
202 pdf_add_dict (descriptor,
203 pdf_new_name ("Ascent"),
204 pdf_new_number (PDFUNIT(os2->sTypoAscender)));
205 pdf_add_dict (descriptor,
206 pdf_new_name ("Descent"),
207 pdf_new_number (PDFUNIT(os2->sTypoDescender)));
208 if (stemv < 0) /* if not given by the option '-v' */
209 stemv = (os2->usWeightClass/65.)*(os2->usWeightClass/65.)+50;
210 pdf_add_dict (descriptor,
211 pdf_new_name ("StemV"),
212 pdf_new_number (stemv));
213 if (os2->version == 0x0002) {
214 pdf_add_dict (descriptor,
215 pdf_new_name("CapHeight"),
216 pdf_new_number(PDFUNIT(os2->sCapHeight)));
217 /* optional */
218 pdf_add_dict (descriptor,
219 pdf_new_name("XHeight"),
220 pdf_new_number(PDFUNIT(os2->sxHeight)));
221 } else { /* arbitrary */
222 pdf_add_dict (descriptor,
223 pdf_new_name("CapHeight"),
224 pdf_new_number(PDFUNIT(os2->sTypoAscender)));
225 }
226 /* optional */
227 if (os2->xAvgCharWidth != 0) {
228 pdf_add_dict (descriptor,
229 pdf_new_name ("AvgWidth"),
230 pdf_new_number (PDFUNIT(os2->xAvgCharWidth)));
231 }
232 }
233
234 /* BoundingBox (array) */
235 bbox = pdf_new_array ();
236 pdf_add_array (bbox, pdf_new_number (PDFUNIT(head->xMin)));
237 pdf_add_array (bbox, pdf_new_number (PDFUNIT(head->yMin)));
238 pdf_add_array (bbox, pdf_new_number (PDFUNIT(head->xMax)));
239 pdf_add_array (bbox, pdf_new_number (PDFUNIT(head->yMax)));
240 pdf_add_dict (descriptor, pdf_new_name ("FontBBox"), bbox);
241
242 /* post */
243 pdf_add_dict (descriptor,
244 pdf_new_name ("ItalicAngle"),
245 pdf_new_number(fixed(post->italicAngle)));
246
247 /* Flags */
248 if (os2) {
249 if (os2->fsSelection & (1 << 0))
250 flag |= ITALIC;
251 if (os2->fsSelection & (1 << 5))
252 flag |= FORCEBOLD;
253 if (((os2->sFamilyClass >> 8) & 0xff) != 8)
254 flag |= SERIF;
255 if (((os2->sFamilyClass >> 8) & 0xff) == 10)
256 flag |= SCRIPT;
257 if (post->isFixedPitch)
258 flag |= FIXEDWIDTH;
259 }
260
261 pdf_add_dict (descriptor,
262 pdf_new_name ("Flags"),
263 pdf_new_number (flag));
264
265 /* insert panose if you want */
266 if (type == 0 && os2) { /* cid-keyed font - add panose */
267 pdf_obj *styledict = NULL;
268 unsigned char panose[12];
269
270 panose[0] = os2->sFamilyClass >> 8;
271 panose[1] = os2->sFamilyClass & 0xff;
272 memcpy(panose+2, os2->panose, 10);
273
274 styledict = pdf_new_dict ();
275 pdf_add_dict (styledict, pdf_new_name ("Panose"),
276 pdf_new_string (panose, 12));
277 pdf_add_dict (descriptor, pdf_new_name ("Style"), styledict);
278 }
279
280 RELEASE(head);
281 if (os2)
282 RELEASE(os2);
283 tt_release_post_table(post);
284
285 return descriptor;
286 }
287
288