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