1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /*
18 GhostScript Font API plug-in that allows fonts to be rendered by FreeType.
19 Started by Graham Asher, 6th June 2002.
20 */
21
22 /* GhostScript headers. */
23 #include "stdio_.h"
24 #include "malloc_.h"
25 #include "write_t1.h"
26 #include "write_t2.h"
27 #include "math_.h"
28 #include "gserrors.h"
29 #include "gsmemory.h"
30 #include "gsmalloc.h"
31 #include "gxfixed.h"
32 #include "gdebug.h"
33 #include "gxbitmap.h"
34 #include "gsmchunk.h"
35 #include "gxfont.h"
36 #include "gxfont1.h"
37
38 #include "stream.h"
39 #include "gxiodev.h" /* must come after stream.h */
40
41 #include "gsfname.h"
42
43 #include "gxfapi.h"
44
45
46 /* FreeType headers */
47 #include <ft2build.h>
48 #include FT_FREETYPE_H
49 #include FT_INCREMENTAL_H
50 #include FT_GLYPH_H
51 #include FT_SYSTEM_H
52 #include FT_MODULE_H
53 #include FT_TRIGONOMETRY_H
54 #include FT_BBOX_H
55 #include FT_OUTLINE_H
56 #include FT_IMAGE_H
57 #include FT_BITMAP_H
58 #include FT_TRUETYPE_DRIVER_H
59 #include FT_MULTIPLE_MASTERS_H
60 #include FT_TYPE1_TABLES_H
61
62 /* Note: structure definitions here start with FF_, which stands for 'FAPI FreeType". */
63
64 #define ft_emprintf(m,s) { outflush(m); emprintf(m, s); outflush(m); }
65 #define ft_emprintf1(m,s,d) { outflush(m); emprintf1(m, s, d); outflush(m); }
66
67 typedef struct ff_server_s
68 {
69 gs_fapi_server fapi_server;
70 FT_Library freetype_library;
71 FT_OutlineGlyph outline_glyph;
72 FT_BitmapGlyph bitmap_glyph;
73 gs_memory_t *mem;
74 FT_Memory ftmemory;
75 struct FT_MemoryRec_ ftmemory_rec;
76 } ff_server;
77
78
79
80 typedef struct ff_face_s
81 {
82 FT_Face ft_face;
83
84 /* Currently in force scaling/transform for this face */
85 FT_Matrix ft_transform;
86 FT_F26Dot6 width, height;
87 FT_UInt horz_res;
88 FT_UInt vert_res;
89
90 /* If non-null, the incremental interface object passed to FreeType. */
91 FT_Incremental_InterfaceRec *ft_inc_int;
92 /* If non-null, we're using a custom stream object for Freetype to read the font file */
93 FT_Stream ftstrm;
94 /* Non-null if font data is owned by this object. */
95 unsigned char *font_data;
96 int font_data_len;
97 bool data_owned;
98 ff_server *server;
99 } ff_face;
100
101 /* Here we define the struct FT_Incremental that is used as an opaque type
102 * inside FreeType. This structure has to have the tag FT_IncrementalRec_
103 * to be compatible with the functions defined in FT_Incremental_FuncsRec.
104 */
105 typedef struct FT_IncrementalRec_
106 {
107 gs_fapi_font *fapi_font; /* The font. */
108
109 /* If it is already in use glyph data is allocated on the heap. */
110 unsigned char *glyph_data; /* A one-shot buffer for glyph data. */
111 size_t glyph_data_length; /* Length in bytes of glyph_data. */
112 bool glyph_data_in_use; /* True if glyph_data is already in use. */
113
114 FT_Incremental_MetricsRec glyph_metrics; /* Incremental glyph metrics supplied by Ghostscript. */
115 unsigned long glyph_metrics_index; /* contains data for this glyph index unless it is 0xFFFFFFFF. */
116 gs_fapi_metrics_type metrics_type; /* determines whether metrics are replaced, added, etc. */
117 } FT_IncrementalRec;
118
119
120 static void
121 delete_inc_int(gs_fapi_server * a_server,
122 FT_Incremental_InterfaceRec * a_inc_int);
123
124 static void
125 delete_inc_int_info(gs_fapi_server * a_server,
126 FT_IncrementalRec * a_inc_int_info);
127
128 static void *
FF_alloc(FT_Memory memory,long size)129 FF_alloc(FT_Memory memory, long size)
130 {
131 gs_memory_t *mem = (gs_memory_t *) memory->user;
132
133 return (gs_malloc(mem, size, 1, "FF_alloc"));
134 }
135
136 static void *
FF_realloc(FT_Memory memory,long cur_size,long new_size,void * block)137 FF_realloc(FT_Memory memory, long cur_size, long new_size, void *block)
138 {
139 gs_memory_t *mem = (gs_memory_t *) memory->user;
140 void *tmp;
141
142 if (cur_size == new_size) {
143 return (block);
144 }
145
146 tmp = gs_malloc(mem, new_size, 1, "FF_realloc");
147 if (tmp && block) {
148 memcpy(tmp, block, min(cur_size, new_size));
149
150 gs_free(mem, block, 0, 0, "FF_realloc");
151 }
152
153 return (tmp);
154 }
155
156 static void
FF_free(FT_Memory memory,void * block)157 FF_free(FT_Memory memory, void *block)
158 {
159 gs_memory_t *mem = (gs_memory_t *) memory->user;
160
161 gs_free(mem, block, 0, 0, "FF_free");
162 }
163
164 /* The following three functions are used in providing a custom stream
165 * object to Freetype, so file access happens through Ghostscript's
166 * file i/o. Most importantly, this gives Freetype direct access to
167 * files in the romfs
168 */
169 static FT_ULong
FF_stream_read(FT_Stream str,unsigned long offset,unsigned char * buffer,unsigned long count)170 FF_stream_read(FT_Stream str, unsigned long offset, unsigned char *buffer,
171 unsigned long count)
172 {
173 stream *ps = (stream *) str->descriptor.pointer;
174 unsigned int rlen = 0;
175 int status = 0;
176
177 if (sseek(ps, (gs_offset_t)offset) < 0)
178 return_error(-1);
179
180 if (count) {
181 status = sgets(ps, buffer, count, &rlen);
182
183 if (status < 0 && status != EOFC)
184 return_error (-1);
185 }
186 return (rlen);
187 }
188
189 static void
FF_stream_close(FT_Stream str)190 FF_stream_close(FT_Stream str)
191 {
192 stream *ps = (stream *) str->descriptor.pointer;
193
194 (void)sclose(ps);
195 }
196
197 extern const uint file_default_buffer_size;
198
199 static int
FF_open_read_stream(gs_memory_t * mem,char * fname,FT_Stream * fts)200 FF_open_read_stream(gs_memory_t * mem, char *fname, FT_Stream * fts)
201 {
202 int code = 0;
203 gs_parsed_file_name_t pfn;
204 stream *ps = (stream *)NULL;
205 gs_offset_t length;
206 FT_Stream ftstrm = NULL;
207
208 code = gs_parse_file_name(&pfn, (const char *)fname, strlen(fname), mem);
209 if (code < 0) {
210 goto error_out;
211 }
212
213 if (!pfn.fname) {
214 code = gs_error_undefinedfilename;
215 goto error_out;
216 }
217
218 if (pfn.iodev == NULL) {
219 pfn.iodev = iodev_default(mem);
220 }
221
222 if (pfn.iodev) {
223 gx_io_device *const iodev = pfn.iodev;
224
225 iodev_proc_open_file((*open_file)) = iodev->procs.open_file;
226
227 if (open_file) {
228 code = open_file(iodev, pfn.fname, pfn.len, "r", &ps, mem);
229 if (code < 0) {
230 goto error_out;
231 }
232 }
233 else {
234 code =
235 file_open_stream(pfn.fname, pfn.len, "r",
236 file_default_buffer_size, &ps, pfn.iodev,
237 pfn.iodev->procs.gp_fopen, mem);
238 if (code < 0) {
239 goto error_out;
240 }
241 }
242 }
243 else {
244 goto error_out;
245 }
246
247 if ((code = savailable(ps, &length)) < 0) {
248 goto error_out;
249 }
250
251 ftstrm = gs_malloc(mem, sizeof(FT_StreamRec), 1, "FF_open_read_stream");
252 if (!ftstrm) {
253 code = gs_error_VMerror;
254 goto error_out;
255 }
256 memset(ftstrm, 0x00, sizeof(FT_StreamRec));
257
258 ftstrm->descriptor.pointer = ps;
259 ftstrm->read = FF_stream_read;
260 ftstrm->close = FF_stream_close;
261 ftstrm->size = (long)length;
262 *fts = ftstrm;
263
264 error_out:
265 if (code < 0) {
266 if (ps)
267 (void)sclose(ps);
268 if (ftstrm)
269 gs_free(mem, ftstrm, 0, 0, "FF_open_read_stream");
270 }
271 return (code);
272 }
273
274
275 static ff_face *
new_face(gs_fapi_server * a_server,FT_Face a_ft_face,FT_Incremental_InterfaceRec * a_ft_inc_int,FT_Stream ftstrm,unsigned char * a_font_data,int a_font_data_len,bool data_owned)276 new_face(gs_fapi_server * a_server, FT_Face a_ft_face,
277 FT_Incremental_InterfaceRec * a_ft_inc_int, FT_Stream ftstrm,
278 unsigned char *a_font_data, int a_font_data_len, bool data_owned)
279 {
280 ff_server *s = (ff_server *) a_server;
281
282 ff_face *face = (ff_face *) FF_alloc(s->ftmemory, sizeof(ff_face));
283
284 if (face) {
285 face->ft_face = a_ft_face;
286 face->ft_inc_int = a_ft_inc_int;
287 face->font_data = a_font_data;
288 face->font_data_len = a_font_data_len;
289 face->data_owned = data_owned;
290 face->ftstrm = ftstrm;
291 face->server = (ff_server *) a_server;
292 }
293 return face;
294 }
295
296 static void
delete_face(gs_fapi_server * a_server,ff_face * a_face)297 delete_face(gs_fapi_server * a_server, ff_face * a_face)
298 {
299 if (a_face) {
300 ff_server *s = (ff_server *) a_server;
301 if (a_face->ft_inc_int) {
302 FT_Incremental a_info = a_face->ft_inc_int->object;
303
304 if (a_info->glyph_data) {
305 gs_free(s->mem, a_info->glyph_data, 0, 0, "delete_face");
306 }
307 a_info->glyph_data = NULL;
308 a_info->glyph_data_length = 0;
309 delete_inc_int(a_server, a_face->ft_inc_int);
310 a_face->ft_inc_int = NULL;
311 }
312 FT_Done_Face(a_face->ft_face);
313
314 FF_free(s->ftmemory, a_face->ft_inc_int);
315 if (a_face->data_owned)
316 FF_free(s->ftmemory, a_face->font_data);
317 if (a_face->ftstrm) {
318 FF_free(s->ftmemory, a_face->ftstrm);
319 }
320 FF_free(s->ftmemory, a_face);
321 }
322 }
323
324 static FT_IncrementalRec *
new_inc_int_info(gs_fapi_server * a_server,gs_fapi_font * a_fapi_font)325 new_inc_int_info(gs_fapi_server * a_server, gs_fapi_font * a_fapi_font)
326 {
327 ff_server *s = (ff_server *) a_server;
328
329 FT_IncrementalRec *info =
330 (FT_IncrementalRec *) FF_alloc(s->ftmemory,
331 sizeof(FT_IncrementalRec));
332 if (info) {
333 info->fapi_font = a_fapi_font;
334 info->glyph_data = NULL;
335 info->glyph_data_length = 0;
336 info->glyph_data_in_use = false;
337 info->glyph_metrics_index = 0xFFFFFFFF;
338 info->metrics_type = gs_fapi_metrics_notdef;
339 }
340 return info;
341 }
342
343 static void
delete_inc_int_info(gs_fapi_server * a_server,FT_IncrementalRec * a_inc_int_info)344 delete_inc_int_info(gs_fapi_server * a_server,
345 FT_IncrementalRec * a_inc_int_info)
346 {
347 ff_server *s = (ff_server *) a_server;
348
349 if (a_inc_int_info) {
350 FF_free(s->ftmemory, a_inc_int_info->glyph_data);
351 FF_free(s->ftmemory, a_inc_int_info);
352 }
353 }
354
355 static FT_Error
get_fapi_glyph_data(FT_Incremental a_info,FT_UInt a_index,FT_Data * a_data)356 get_fapi_glyph_data(FT_Incremental a_info, FT_UInt a_index, FT_Data * a_data)
357 {
358 gs_fapi_font *ff = a_info->fapi_font;
359 int length = 0;
360 ff_face *face = (ff_face *) ff->server_font_data;
361 gs_memory_t *mem = (gs_memory_t *) face->server->mem;
362
363 /* Tell the FAPI interface that we need to decrypt the glyph data. */
364 ff->need_decrypt = true;
365
366 /* If glyph_data is already in use (as will happen for composite glyphs)
367 * create a new buffer on the heap.
368 */
369 if (a_info->glyph_data_in_use) {
370 unsigned char *buffer = NULL;
371
372 length = ff->get_glyph(ff, a_index, NULL, 0);
373 if (length == gs_fapi_glyph_invalid_format
374 || length == gs_fapi_glyph_invalid_index)
375 return FT_Err_Invalid_Glyph_Index;
376
377 buffer = gs_malloc(mem, length, 1, "get_fapi_glyph_data");
378 if (!buffer)
379 return FT_Err_Out_Of_Memory;
380
381 length = ff->get_glyph(ff, a_index, buffer, length);
382 if (length == gs_fapi_glyph_invalid_format) {
383 gs_free((gs_memory_t *) mem, buffer, 0, 0,
384 "get_fapi_glyph_data");
385 return FT_Err_Invalid_Glyph_Index;
386 }
387 a_data->pointer = buffer;
388 }
389 else {
390 /* Save ff->char_data, which is set to null by FAPI_FF_get_glyph as part of a hack to
391 * make the deprecated Type 2 endchar ('seac') work, so that it can be restored
392 * if we need to try again with a longer buffer.
393 */
394 const void *saved_char_data = ff->char_data;
395
396 /* Get as much of the glyph data as possible into the buffer */
397 length =
398 ff->get_glyph(ff, a_index, a_info->glyph_data,
399 (ushort) a_info->glyph_data_length);
400 if (length == gs_fapi_glyph_invalid_format) {
401 ff->char_data = saved_char_data;
402 return FT_Err_Unknown_File_Format;
403 }
404
405 if (length == gs_fapi_glyph_invalid_index) {
406 ff->char_data = saved_char_data;
407 return FT_Err_Invalid_Glyph_Index;
408 }
409
410 /* If the buffer was too small enlarge it and try again. */
411 if (length > a_info->glyph_data_length) {
412 if (a_info->glyph_data) {
413 gs_free((gs_memory_t *) mem,
414 a_info->glyph_data, 0, 0, "get_fapi_glyph_data");
415 }
416
417 a_info->glyph_data =
418 gs_malloc(mem, length, 1, "get_fapi_glyph_data");
419
420 if (!a_info->glyph_data) {
421 a_info->glyph_data_length = 0;
422 return FT_Err_Out_Of_Memory;
423 }
424 a_info->glyph_data_length = length;
425 ff->char_data = saved_char_data;
426 length = ff->get_glyph(ff, a_index, a_info->glyph_data, length);
427 if (length == gs_fapi_glyph_invalid_format)
428 return FT_Err_Unknown_File_Format;
429 if (length == gs_fapi_glyph_invalid_index)
430 return FT_Err_Invalid_Glyph_Index;
431 }
432
433 /* Set the returned pointer and length. */
434 a_data->pointer = a_info->glyph_data;
435
436 a_info->glyph_data_in_use = true;
437 }
438
439 a_data->length = length;
440 return 0;
441 }
442
443 static void
free_fapi_glyph_data(FT_Incremental a_info,FT_Data * a_data)444 free_fapi_glyph_data(FT_Incremental a_info, FT_Data * a_data)
445 {
446 gs_fapi_font *ff = a_info->fapi_font;
447 ff_face *face = (ff_face *) ff->server_font_data;
448 gs_memory_t *mem = (gs_memory_t *) face->server->mem;
449
450 if (a_data->pointer == (const FT_Byte *)a_info->glyph_data)
451 a_info->glyph_data_in_use = false;
452 else
453 gs_free(mem, (FT_Byte *) a_data->pointer, 0, 0, "free_fapi_glyph_data");
454 }
455
456 static FT_Error
get_fapi_glyph_metrics(FT_Incremental a_info,FT_UInt a_glyph_index,FT_Bool bVertical,FT_Incremental_MetricsRec * a_metrics)457 get_fapi_glyph_metrics(FT_Incremental a_info, FT_UInt a_glyph_index,
458 FT_Bool bVertical,
459 FT_Incremental_MetricsRec * a_metrics)
460 {
461 /* FreeType will create synthetic vertical metrics, including a vertical
462 * advance, if none is present. We don't want this, so if the font uses Truetype outlines
463 * and the WMode is not 1 (vertical) we ignore the advance by setting it to 0
464 */
465 if (bVertical && !a_info->fapi_font->is_type1)
466 a_metrics->advance = 0;
467
468 if (a_info->glyph_metrics_index == a_glyph_index) {
469 switch (a_info->metrics_type) {
470 case gs_fapi_metrics_add:
471 a_metrics->advance += a_info->glyph_metrics.advance;
472 break;
473 case gs_fapi_metrics_replace_width:
474 a_metrics->advance = a_info->glyph_metrics.advance;
475 break;
476 case gs_fapi_metrics_replace:
477 *a_metrics = a_info->glyph_metrics;
478 /* We are replacing the horizontal metrics, so the vertical must be 0 */
479 a_metrics->advance_v = 0;
480 break;
481 default:
482 /* This can't happen. */
483 return FT_Err_Invalid_Argument;
484 }
485 }
486 return 0;
487 }
488
489 static const FT_Incremental_FuncsRec TheFAPIIncrementalInterfaceFuncs = {
490 get_fapi_glyph_data,
491 free_fapi_glyph_data,
492 get_fapi_glyph_metrics
493 };
494
495 static FT_Incremental_InterfaceRec *
new_inc_int(gs_fapi_server * a_server,gs_fapi_font * a_fapi_font)496 new_inc_int(gs_fapi_server * a_server, gs_fapi_font * a_fapi_font)
497 {
498 ff_server *s = (ff_server *) a_server;
499
500 FT_Incremental_InterfaceRec *i =
501 (FT_Incremental_InterfaceRec *) FF_alloc(s->ftmemory,
502 sizeof
503 (FT_Incremental_InterfaceRec));
504 if (i) {
505 i->funcs = &TheFAPIIncrementalInterfaceFuncs;
506 i->object = (FT_Incremental) new_inc_int_info(a_server, a_fapi_font);
507
508 if (!i->object) {
509 FF_free(s->ftmemory, i);
510 i = NULL;
511 }
512 }
513 return i;
514 }
515
516 static void
delete_inc_int(gs_fapi_server * a_server,FT_Incremental_InterfaceRec * a_inc_int)517 delete_inc_int(gs_fapi_server * a_server,
518 FT_Incremental_InterfaceRec * a_inc_int)
519 {
520 ff_server *s = (ff_server *) a_server;
521
522 if (a_inc_int) {
523 delete_inc_int_info(a_server, a_inc_int->object);
524 FF_free(s->ftmemory, a_inc_int);
525 }
526 }
527
528 /* Convert FreeType error codes to GhostScript ones.
529 * Very rudimentary because most don't correspond.
530 */
531 static int
ft_to_gs_error(FT_Error a_error)532 ft_to_gs_error(FT_Error a_error)
533 {
534 if (a_error) {
535 if (a_error == FT_Err_Out_Of_Memory)
536 return_error(gs_error_VMerror);
537 else
538 return_error(gs_error_unknownerror);
539 }
540 return 0;
541 }
542
543 /* Load a glyph and optionally rasterize it. Return its metrics in a_metrics.
544 * If a_bitmap is true convert the glyph to a bitmap.
545 */
546 static gs_fapi_retcode
load_glyph(gs_fapi_server * a_server,gs_fapi_font * a_fapi_font,const gs_fapi_char_ref * a_char_ref,gs_fapi_metrics * a_metrics,FT_Glyph * a_glyph,bool a_bitmap,int max_bitmap)547 load_glyph(gs_fapi_server * a_server, gs_fapi_font * a_fapi_font,
548 const gs_fapi_char_ref * a_char_ref, gs_fapi_metrics * a_metrics,
549 FT_Glyph * a_glyph, bool a_bitmap, int max_bitmap)
550 {
551 ff_server *s = (ff_server *) a_server;
552 FT_Error ft_error = 0;
553 FT_Error ft_error_fb = 1;
554 ff_face *face = (ff_face *) a_fapi_font->server_font_data;
555 FT_Face ft_face = face->ft_face;
556 int index = a_char_ref->char_codes[0];
557 FT_Long w;
558 FT_Long h;
559 FT_Long fflags;
560 FT_Int32 load_flags = 0;
561 FT_Vector delta = {0,0};
562
563 /* Save a_fapi_font->char_data, which is set to null by FAPI_FF_get_glyph as part of a hack to
564 * make the deprecated Type 2 endchar ('seac') work, so that it can be restored
565 * after the first call to FT_Load_Glyph.
566 */
567 const void *saved_char_data = a_fapi_font->char_data;
568 const int saved_char_data_len = a_fapi_font->char_data_len;
569
570 if (s->bitmap_glyph) {
571 FT_Bitmap_Done(s->freetype_library, &s->bitmap_glyph->bitmap);
572 FF_free(s->ftmemory, s->bitmap_glyph);
573 s->bitmap_glyph = NULL;
574 }
575 if (s->outline_glyph) {
576 FT_Outline_Done(s->freetype_library, &s->outline_glyph->outline);
577 FF_free(s->ftmemory, s->outline_glyph);
578 s->outline_glyph = NULL;
579 }
580
581 if (!a_char_ref->is_glyph_index) {
582 if (ft_face->num_charmaps)
583 index = FT_Get_Char_Index(ft_face, index);
584 else {
585 /* If there are no character maps and no glyph index, loading the glyph will still work
586 * properly if both glyph data and metrics are supplied by the incremental interface.
587 * In that case we use a dummy glyph index which will be passed
588 * back to FAPI_FF_get_glyph by get_fapi_glyph_data.
589 *
590 * Type 1 fonts don't use the code and can appear to FreeType to have only one glyph,
591 * so we have to set the index to 0.
592 *
593 * For other font types, FAPI_FF_get_glyph requires the character code
594 * when getting data.
595 */
596 if (a_fapi_font->is_type1)
597 index = 0;
598 else
599 index = a_char_ref->char_codes[0];
600 }
601 }
602 else {
603 /* This is a heuristic to try to avoid using the TTF notdef (empty rectangle), and replace it
604 with a non-marking glyph instead. This is only required for fonts where we don't use the
605 FT incremental interface - when we are using the incremental interface, we handle it in
606 our own glyph lookup code.
607 */
608 if (!a_fapi_font->is_cid && !face->ft_inc_int &&
609 (index == 0 ||
610 (a_char_ref->client_char_code != gs_no_char &&
611 FT_Get_Char_Index(ft_face, a_char_ref->client_char_code) <= 0))) {
612 int tmp_ind;
613
614 if ((tmp_ind = FT_Get_Char_Index(ft_face, 32)) > 0) {
615 index = tmp_ind;
616 }
617 }
618 }
619 /* Refresh the pointer to the FAPI_font held by the incremental interface. */
620 if (face->ft_inc_int)
621 face->ft_inc_int->object->fapi_font = a_fapi_font;
622
623 /* Store the overriding metrics if they have been supplied. */
624 if (face->ft_inc_int
625 && a_char_ref->metrics_type != gs_fapi_metrics_notdef) {
626
627 FT_Incremental_MetricsRec *m =
628 &face->ft_inc_int->object->glyph_metrics;
629 m->bearing_x = a_char_ref->sb_x >> 16;
630 m->bearing_y = a_char_ref->sb_y >> 16;
631 m->advance = a_char_ref->aw_x >> 16;
632 face->ft_inc_int->object->glyph_metrics_index = index;
633 face->ft_inc_int->object->metrics_type = a_char_ref->metrics_type;
634
635 /* we only want this for fonts with TT outlines */
636 if (!a_fapi_font->is_type1) {
637 delta.y = 0;
638 delta.x = FT_MulFix(a_char_ref->sb_x, ft_face->size->metrics.x_scale);
639 FT_Vector_Transform( &delta, &face->ft_transform);
640 }
641 }
642 else if (face->ft_inc_int)
643 /* Make sure we don't leave this set to the last value, as we may then use inappropriate metrics values */
644 face->ft_inc_int->object->glyph_metrics_index = 0xFFFFFFFF;
645
646 /* We have to load the glyph, scale it correctly, and render it if we need a bitmap. */
647 if (!ft_error) {
648 /* We disable loading bitmaps because if we allow it then FreeType invents metrics for them, which messes up our glyph positioning */
649 /* Also the bitmaps tend to look somewhat different (though more readable) than FreeType's rendering. By disabling them we */
650 /* maintain consistency better. (FT_LOAD_NO_BITMAP) */
651 a_fapi_font->char_data = saved_char_data;
652 if (!a_fapi_font->is_mtx_skipped && !a_fapi_font->is_type1) {
653 /* grid_fit == 1 is the default - use font's native hints
654 * with freetype, 1 & 3 are, in practice, the same.
655 */
656
657 if (a_server->grid_fit == 0) {
658 load_flags = FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
659 }
660 else if (a_server->grid_fit == 2) {
661 load_flags = FT_LOAD_FORCE_AUTOHINT;
662 }
663 load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_NO_BITMAP | FT_LOAD_LINEAR_DESIGN;
664 }
665 else {
666 /* Current FreeType hinting for type 1 fonts is so poor we are actually better off without it (fewer files render incorrectly) (FT_LOAD_NO_HINTING) */
667 /* We also need to disable hinting for XL format embedded truetypes */
668 load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_LINEAR_DESIGN;
669 }
670
671 ft_error = FT_Load_Glyph(ft_face, index, load_flags);
672 if (ft_error == FT_Err_Unknown_File_Format) {
673 return index + 1;
674 }
675 }
676
677 if (ft_error == FT_Err_Invalid_Argument
678 || ft_error == FT_Err_Invalid_Reference
679 || ft_error == FT_Err_Invalid_Glyph_Index
680 || (ft_error >= FT_Err_Invalid_Opcode
681 && ft_error <= FT_Err_Too_Many_Instruction_Defs)) {
682
683 a_fapi_font->char_data = saved_char_data;
684
685 /* We want to prevent hinting, even for a "tricky" font - it shouldn't matter for the notdef */
686 fflags = ft_face->face_flags;
687 ft_face->face_flags &= ~FT_FACE_FLAG_TRICKY;
688 load_flags |= FT_LOAD_NO_HINTING;
689 ft_error = FT_Load_Glyph(ft_face, index, load_flags);
690
691 ft_face->face_flags = fflags;
692 }
693
694 if (ft_error == FT_Err_Out_Of_Memory
695 || ft_error == FT_Err_Array_Too_Large) {
696 return (gs_error_VMerror);
697 }
698
699 /* If FT gives us an error, try to fall back to the notdef - if that doesn't work, we'll throw an error over to Ghostscript */
700 if (ft_error) {
701 gs_string notdef_str;
702
703 notdef_str.data = (byte *)".notdef";
704 notdef_str.size = 7;
705
706 a_fapi_font->char_data = (void *)(¬def_str);
707 a_fapi_font->char_data_len = 0;
708
709 /* We want to prevent hinting, even for a "tricky" font - it shouldn't matter for the notdef */
710 fflags = ft_face->face_flags;
711 ft_face->face_flags &= ~FT_FACE_FLAG_TRICKY;
712
713 ft_error_fb = FT_Load_Glyph(ft_face, 0, load_flags);
714
715 ft_face->face_flags = fflags;
716
717 a_fapi_font->char_data = saved_char_data;
718 a_fapi_font->char_data_len = saved_char_data_len;
719 }
720
721 if ((!ft_error || !ft_error_fb) && (delta.x != 0 || delta.y != 0)) {
722 FT_Outline_Translate( &ft_face->glyph->outline, delta.x >> 16, delta.y >> 16 );
723 }
724
725 /* Previously we interpreted the glyph unscaled, and derived the metrics from that. Now we only interpret it
726 * once, and work out the metrics from the scaled/hinted outline.
727 */
728 if ((!ft_error || !ft_error_fb) && a_metrics) {
729 FT_Long hx;
730 FT_Long hy;
731 FT_Long vadv;
732
733 /* In order to get the metrics in the form we need them, we have to remove the size scaling
734 * the resolution scaling, and convert to points.
735 */
736 hx = (FT_Long) (((double)ft_face->glyph->metrics.horiBearingX *
737 ft_face->units_per_EM * 72.0) /
738 ((double)face->width * face->horz_res));
739 hy = (FT_Long) (((double)ft_face->glyph->metrics.horiBearingY *
740 ft_face->units_per_EM * 72.0) /
741 ((double)face->height * face->vert_res));
742
743 w = (FT_Long) (((double)ft_face->glyph->metrics.width *
744 ft_face->units_per_EM * 72.0) / ((double)face->width *
745 face->horz_res));
746 h = (FT_Long) (((double)ft_face->glyph->metrics.height *
747 ft_face->units_per_EM * 72.0) /
748 ((double)face->height * face->vert_res));
749
750 /* Ugly. FreeType creates verticla metrics for TT fonts, normally we override them in the
751 * metrics callbacks, but those only work for incremental interface fonts, and TrueType fonts
752 * loaded as CIDFont replacements are not incrementally handled. So here, if its a CIDFont, and
753 * its not type 1 outlines, and its not a vertical mode fotn, ignore the advance.
754 */
755 if (a_fapi_font->is_type1
756 || ((a_fapi_font->full_font_buf || a_fapi_font->font_file_path)
757 && a_fapi_font->is_vertical && FT_HAS_VERTICAL(ft_face))) {
758
759 vadv = ft_face->glyph->linearVertAdvance;
760 }
761 else {
762 vadv = 0;
763 }
764
765 a_metrics->bbox_x0 = hx;
766 a_metrics->bbox_y0 = hy - h;
767 a_metrics->bbox_x1 = a_metrics->bbox_x0 + w;
768 a_metrics->bbox_y1 = a_metrics->bbox_y0 + h;
769 a_metrics->escapement = ft_face->glyph->linearHoriAdvance;
770 a_metrics->v_escapement = vadv;
771 a_metrics->em_x = ft_face->units_per_EM;
772 a_metrics->em_y = ft_face->units_per_EM;
773 }
774
775 if ((!ft_error || !ft_error_fb)) {
776
777 FT_BBox cbox;
778
779 /* compute the control box, and grid fit it - lifted from ft_raster1_render() */
780 FT_Outline_Get_CBox(&ft_face->glyph->outline, &cbox);
781
782 /* These round operations are only to preserve behaviour compared to the 9.00 release
783 which used the bitmap dimensions as calculated by Freetype.
784 But FT_PIX_FLOOR/FT_PIX_CEIL aren't public.
785 */
786 cbox.xMin = ((cbox.xMin) & ~63); /* FT_PIX_FLOOR( cbox.xMin ) */
787 cbox.yMin = ((cbox.yMin) & ~63);
788 cbox.xMax = (((cbox.xMax) + 63) & ~63);
789 cbox.yMax = (((cbox.yMax) + 63) & ~63); /* FT_PIX_CEIL( cbox.yMax ) */
790
791 w = (FT_UInt) ((cbox.xMax - cbox.xMin) >> 6);
792 h = (FT_UInt) ((cbox.yMax - cbox.yMin) >> 6);
793
794 if (!a_fapi_font->metrics_only && a_bitmap == true && ft_face->glyph->format != FT_GLYPH_FORMAT_BITMAP
795 && ft_face->glyph->format != FT_GLYPH_FORMAT_COMPOSITE) {
796 if ((bitmap_raster(w) * h) < max_bitmap) {
797 FT_Render_Mode mode = FT_RENDER_MODE_MONO;
798
799 ft_error = FT_Render_Glyph(ft_face->glyph, mode);
800 }
801 else {
802 (*a_glyph) = NULL;
803 return (gs_error_VMerror);
804 }
805 }
806 }
807
808 if (!a_fapi_font->metrics_only) {
809 /* The following works around the fact that at the scales we deal with
810 * these values may not fit in a 16.16 fixed point value, and thus cause
811 * freetype to error due to overflow - but we don't use these values
812 * and neither does freetype, we can set them to zero and avoid the error
813 */
814 ft_face->glyph->advance.x = ft_face->glyph->advance.y = 0;
815 if ((!ft_error || !ft_error_fb) && a_glyph) {
816 ft_error = FT_Get_Glyph(ft_face->glyph, a_glyph);
817 }
818 else {
819 if (ft_face->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
820 FT_BitmapGlyph bmg;
821
822 ft_error = FT_Get_Glyph(ft_face->glyph, (FT_Glyph *) & bmg);
823 if (!ft_error) {
824 FT_Bitmap_Done(s->freetype_library, &bmg->bitmap);
825 FF_free(s->ftmemory, bmg);
826 }
827 }
828 else {
829 FT_OutlineGlyph olg;
830
831 ft_error = FT_Get_Glyph(ft_face->glyph, (FT_Glyph *) & olg);
832 if (!ft_error) {
833 FT_Outline_Done(s->freetype_library, &olg->outline);
834 FF_free(s->ftmemory, olg);
835 }
836 }
837 }
838 }
839
840 if (ft_error == FT_Err_Too_Many_Hints) {
841 #ifdef DEBUG
842 if (gs_debug_c('1')) {
843 ft_emprintf1(a_fapi_font->memory,
844 "TrueType glyph %"PRId64" uses more instructions than the declared maximum in the font.",
845 a_char_ref->char_codes[0]);
846
847 if (!ft_error_fb) {
848 ft_emprintf(a_fapi_font->memory,
849 " Continuing, falling back to notdef\n\n");
850 }
851 }
852 #endif
853 if (!ft_error_fb)
854 ft_error = 0;
855 }
856 if (ft_error == FT_Err_Invalid_Argument) {
857 #ifdef DEBUG
858 if (gs_debug_c('1')) {
859 ft_emprintf1(a_fapi_font->memory,
860 "TrueType parsing error in glyph %"PRId64" in the font.",
861 a_char_ref->char_codes[0]);
862
863 if (!ft_error_fb) {
864 ft_emprintf(a_fapi_font->memory,
865 " Continuing, falling back to notdef\n\n");
866 }
867 }
868 #endif
869 if (!ft_error_fb)
870 ft_error = 0;
871 }
872 if (ft_error == FT_Err_Too_Many_Function_Defs) {
873 #ifdef DEBUG
874 if (gs_debug_c('1')) {
875 ft_emprintf1(a_fapi_font->memory,
876 "TrueType instruction error in glyph %"PRId64" in the font.",
877 a_char_ref->char_codes[0]);
878
879 if (!ft_error_fb) {
880 ft_emprintf(a_fapi_font->memory,
881 " Continuing, falling back to notdef\n\n");
882 }
883 }
884 #endif
885 if (!ft_error_fb)
886 ft_error = 0;
887 }
888 if (ft_error == FT_Err_Invalid_Glyph_Index) {
889 #ifdef DEBUG
890 if (gs_debug_c('1')) {
891 ft_emprintf1(a_fapi_font->memory,
892 "FreeType is unable to find the glyph %"PRId64" in the font.",
893 a_char_ref->char_codes[0]);
894
895 if (!ft_error_fb) {
896 ft_emprintf(a_fapi_font->memory,
897 " Continuing, falling back to notdef\n\n");
898 }
899 }
900 #endif
901 if (!ft_error_fb)
902 ft_error = 0;
903 }
904 return ft_to_gs_error(ft_error);
905 }
906
907 /*
908 * Ensure that the rasterizer is open.
909 *
910 * In the case of FreeType this means creating the FreeType library object.
911 */
912 static gs_fapi_retcode
gs_fapi_ft_ensure_open(gs_fapi_server * a_server,const char * server_param,int server_param_size)913 gs_fapi_ft_ensure_open(gs_fapi_server * a_server, const char * server_param,
914 int server_param_size)
915 {
916 ff_server *s = (ff_server *) a_server;
917 FT_UInt tt_ins_version = TT_INTERPRETER_VERSION_35;
918 FT_Error ft_error;
919
920 if (s->freetype_library)
921 return 0;
922
923 /* As we want FT to use our memory management, we cannot use the convenience of
924 * FT_Init_FreeType(), we have to do each stage "manually"
925 */
926 s->ftmemory->user = s->mem;
927 s->ftmemory->alloc = FF_alloc;
928 s->ftmemory->free = FF_free;
929 s->ftmemory->realloc = FF_realloc;
930
931 ft_error = FT_New_Library(s->ftmemory, &s->freetype_library);
932 if (ft_error)
933 return ft_to_gs_error(ft_error);
934
935 FT_Add_Default_Modules(s->freetype_library);
936 FT_Property_Set( s->freetype_library, "truetype", "interpreter-version", &tt_ins_version);
937
938 return 0;
939 }
940
941 #if 0 /* Not currently used */
942 static void
943 transform_concat(FT_Matrix * a_A, const FT_Matrix * a_B)
944 {
945 FT_Matrix result = *a_B;
946
947 FT_Matrix_Multiply(a_A, &result);
948 *a_A = result;
949 }
950
951 /* Create a transform representing an angle defined as a vector. */
952 static void
953 make_rotation(FT_Matrix * a_transform, const FT_Vector * a_vector)
954 {
955 FT_Fixed length, cos, sin;
956
957 if (a_vector->x >= 0 && a_vector->y == 0) {
958 a_transform->xx = a_transform->yy = 65536;
959 a_transform->xy = a_transform->yx = 0;
960 return;
961 }
962
963 length = FT_Vector_Length((FT_Vector *) a_vector);
964 cos = FT_DivFix(a_vector->x, length);
965 sin = FT_DivFix(a_vector->y, length);
966 a_transform->xx = a_transform->yy = cos;
967 a_transform->xy = -sin;
968 a_transform->yx = sin;
969 }
970 #endif /* Not currently used */
971
972 /* Divide a transformation into a scaling part and a rotation-and-shear part.
973 * The scaling part is used for setting the pixel size for hinting.
974 */
975 static void
transform_decompose(FT_Matrix * a_transform,FT_UInt * xresp,FT_UInt * yresp,FT_Fixed * a_x_scale,FT_Fixed * a_y_scale,int units_per_EM)976 transform_decompose(FT_Matrix * a_transform, FT_UInt * xresp, FT_UInt * yresp,
977 FT_Fixed * a_x_scale, FT_Fixed * a_y_scale, int units_per_EM)
978 {
979 double scalex, scaley, fact = 1.0;
980 double factx = 1.0, facty = 1.0;
981 FT_Matrix ftscale_mat;
982 FT_UInt xres;
983 FT_UInt yres;
984 /* We have to account for units_per_EM as we fiddle with the scaling
985 * in order to avoid underflow (mostly in the TTF hinting code), but
986 * we also want to clamp to a lower value (512, admittedly arrived at
987 * via experimentation) in order to preserve the fidelity of the outlines.
988 */
989 double upe = units_per_EM > 512 ? (float)units_per_EM : 512.0;
990
991 scalex = hypot((double)a_transform->xx, (double)a_transform->xy);
992 scaley = hypot((double)a_transform->yx, (double)a_transform->yy);
993
994 /* In addition to all the wrangling below, we have to make sure that
995 * that the contents of a_transform can also be understood by Freetype.
996 */
997 if (scalex < 64.0 || scaley < 64.0) {
998 factx = 64.0/scalex;
999 facty = 64.0/scaley;
1000
1001 ftscale_mat.xx = (FT_Fixed)(a_transform->xx * factx);
1002 ftscale_mat.xy = (FT_Fixed)(a_transform->xy * facty);
1003 ftscale_mat.yx = (FT_Fixed)(a_transform->yx * factx);
1004 ftscale_mat.yy = (FT_Fixed)(a_transform->yy * facty);
1005 memcpy(a_transform, &ftscale_mat, sizeof(ftscale_mat));
1006 scalex = hypot((double)a_transform->xx, (double)a_transform->xy);
1007 scaley = hypot((double)a_transform->yx, (double)a_transform->yy);
1008 }
1009
1010 if (*xresp != *yresp) {
1011 /* To get good results, we have to pull the implicit scaling from
1012 * non-square resolutions, and apply it in the matrix. This means
1013 * we get the correct "shearing" effect for rotated glyphs.
1014 * The previous solution was only effective for for glyphs whose
1015 * axes were coincident with the axes of the page.
1016 */
1017 bool use_x = true;
1018
1019 if (*xresp < *yresp) {
1020 use_x = false;
1021 }
1022
1023 ftscale_mat.xx =
1024 (int)(((double)(*xresp) /
1025 ((double)(use_x ? (*xresp) : (*yresp)))) * 65536);
1026 ftscale_mat.xy = ftscale_mat.yx = 0;
1027 ftscale_mat.yy =
1028 (int)(((double)(*yresp) /
1029 ((double)(use_x ? (*xresp) : (*yresp)))) * 65536);
1030
1031 FT_Matrix_Multiply(&ftscale_mat, a_transform);
1032
1033 xres = yres = (use_x ? (*xresp) : (*yresp));
1034 xres = (FT_UInt)(xres / factx);
1035 yres = (FT_UInt)(yres / facty);
1036 }
1037 else {
1038 /* Life is considerably easier when square resolutions are in use! */
1039 xres = (FT_UInt)(*xresp / factx);
1040 yres = (FT_UInt)(*yresp / facty);
1041 }
1042
1043 scalex *= 1.0 / 65536.0;
1044 scaley *= 1.0 / 65536.0;
1045
1046 if (scalex < scaley) {
1047 scaley = scalex;
1048 }
1049 else if (scalex > scaley) {
1050 scalex = scaley;
1051 }
1052
1053 /* FT clamps the width and height to a lower limit of 1.0 units
1054 * (note: as FT stores it in 64ths of a unit, that is 64)
1055 * So if either the width or the height are <1.0 here, we scale
1056 * the width and height appropriately, and then compensate using
1057 * the "final" matrix for FT
1058 */
1059 /* We use 1 1/64th to calculate the scale, so that we *guarantee* the
1060 * scalex/y we calculate will be >64 after rounding.
1061 */
1062
1063 if (scalex < 10.0) {
1064 fact = 10.016 / scalex;
1065 scalex = scalex * fact;
1066 scaley = scaley * fact;
1067 }
1068
1069 /* see above */
1070 if (scalex * xres < 2268.0 / 64.0) {
1071 fact = (2400.0 / 64.0) / (xres * scalex);
1072 scaley *= fact;
1073 scalex *= fact;
1074 }
1075
1076 /* see above */
1077 fact = 1.0;
1078 while (scaley * yres > (double)upe * 72.0 && (xres > 0 && yres > 0)
1079 && (scalex > 0.0 && scaley > 0.0)) {
1080 if (scaley < yres) {
1081 xres >>= 1;
1082 yres >>= 1;
1083 fact *= 2.0;
1084 }
1085 else {
1086 scalex /= 1.25;
1087 scaley /= 1.25;
1088 }
1089 }
1090
1091 ftscale_mat.xx = (FT_Fixed) ((65536.0 / scalex) * fact);
1092 ftscale_mat.xy = 0;
1093 ftscale_mat.yx = 0;
1094 ftscale_mat.yy = (FT_Fixed) ((65536.0 / scaley) * fact);
1095
1096 FT_Matrix_Multiply(a_transform, &ftscale_mat);
1097 memcpy(a_transform, &ftscale_mat, sizeof(FT_Matrix));
1098
1099 *xresp = xres;
1100 *yresp = yres;
1101 /* Return values ready scaled for FT */
1102 *a_x_scale = (FT_Fixed) (scalex * 64);
1103 *a_y_scale = (FT_Fixed) (scaley * 64);
1104 }
1105
1106 /*
1107 * Open a font and set its size.
1108 */
1109 static gs_fapi_retcode
gs_fapi_ft_get_scaled_font(gs_fapi_server * a_server,gs_fapi_font * a_font,const gs_fapi_font_scale * a_font_scale,const char * a_map,gs_fapi_descendant_code a_descendant_code)1110 gs_fapi_ft_get_scaled_font(gs_fapi_server * a_server, gs_fapi_font * a_font,
1111 const gs_fapi_font_scale * a_font_scale,
1112 const char *a_map, gs_fapi_descendant_code a_descendant_code)
1113 {
1114 ff_server *s = (ff_server *) a_server;
1115 ff_face *face = (ff_face *) a_font->server_font_data;
1116 FT_Error ft_error = 0;
1117 int i, j;
1118 FT_CharMap cmap = NULL;
1119 bool data_owned = true;
1120
1121 if (s->bitmap_glyph) {
1122 FT_Bitmap_Done(s->freetype_library, &s->bitmap_glyph->bitmap);
1123 FF_free(s->ftmemory, s->bitmap_glyph);
1124 s->bitmap_glyph = NULL;
1125 }
1126 if (s->outline_glyph) {
1127 FT_Outline_Done(s->freetype_library, &s->outline_glyph->outline);
1128 FF_free(s->ftmemory, s->outline_glyph);
1129 s->outline_glyph = NULL;
1130 }
1131
1132 /* dpf("gs_fapi_ft_get_scaled_font enter: is_type1=%d is_cid=%d font_file_path='%s' a_descendant_code=%d\n",
1133 a_font->is_type1, a_font->is_cid, a_font->font_file_path ? a_font->font_file_path : "", a_descendant_code); */
1134
1135 /* If this font is the top level font of an embedded CID type 0 font (font type 9)
1136 * do nothing. See the comment in FAPI_prepare_font. The descendant fonts are
1137 * passed in individually.
1138 */
1139 if (a_font->is_cid && a_font->is_type1 && a_font->font_file_path == NULL
1140 && (a_descendant_code == gs_fapi_toplevel_begin
1141 || a_descendant_code == gs_fapi_toplevel_complete)) {
1142 /* dpf("gs_fapi_ft_get_scaled_font return 0\n"); */
1143 return 0;
1144 }
1145
1146 /* Create the face if it doesn't already exist. */
1147 if (!face) {
1148 FT_Face ft_face = NULL;
1149 FT_Parameter ft_param;
1150 FT_Incremental_InterfaceRec *ft_inc_int = NULL;
1151 unsigned char *own_font_data = NULL;
1152 int own_font_data_len = -1;
1153 FT_Stream ft_strm = NULL;
1154
1155 /* dpf("gs_fapi_ft_get_scaled_font creating face\n"); */
1156
1157 if (a_font->full_font_buf) {
1158
1159 own_font_data =
1160 gs_malloc(((gs_memory_t *) (s->ftmemory->user)),
1161 a_font->full_font_buf_len, 1,
1162 "gs_fapi_ft_get_scaled_font - full font buf");
1163 if (!own_font_data) {
1164 return_error(gs_error_VMerror);
1165 }
1166
1167 own_font_data_len = a_font->full_font_buf_len;
1168 memcpy(own_font_data, a_font->full_font_buf,
1169 a_font->full_font_buf_len);
1170
1171 ft_error =
1172 FT_New_Memory_Face(s->freetype_library,
1173 (const FT_Byte *)own_font_data,
1174 own_font_data_len, a_font->subfont,
1175 &ft_face);
1176
1177 if (ft_error) {
1178 gs_memory_t * mem = (gs_memory_t *) s->ftmemory->user;
1179 gs_free(mem, own_font_data, 0, 0, "FF_open_read_stream");
1180 return ft_to_gs_error(ft_error);
1181 }
1182 }
1183 /* Load a typeface from a file. */
1184 else if (a_font->font_file_path) {
1185 FT_Open_Args args;
1186 int code;
1187
1188 memset(&args, 0x00, sizeof(args));
1189
1190 if ((code =
1191 FF_open_read_stream((gs_memory_t *) (s->ftmemory->user),
1192 (char *)a_font->font_file_path,
1193 &ft_strm)) < 0) {
1194 return (code);
1195 }
1196
1197 args.flags = FT_OPEN_STREAM;
1198 args.stream = ft_strm;
1199
1200 ft_error =
1201 FT_Open_Face(s->freetype_library, &args, a_font->subfont,
1202 &ft_face);
1203 if (ft_error) {
1204 /* in the event of an error, Freetype should cleanup the stream */
1205 return ft_to_gs_error(ft_error);
1206 }
1207 }
1208
1209 /* Load a typeface from a representation in GhostScript's memory. */
1210 else {
1211 FT_Open_Args open_args;
1212
1213 open_args.flags = FT_OPEN_MEMORY;
1214 open_args.stream = NULL;
1215
1216 if (a_font->is_type1) {
1217 long length;
1218 int type =
1219 a_font->get_word(a_font, gs_fapi_font_feature_FontType,
1220 0);
1221
1222 /* Tell the FAPI interface that we need to decrypt the /Subrs data. */
1223 a_font->need_decrypt = true;
1224
1225 /*
1226 Serialise a type 1 font in PostScript source form, or
1227 a Type 2 font in binary form, so that FreeType can read it.
1228 */
1229 if (type == 1)
1230 length = gs_fapi_serialize_type1_font(a_font, NULL, 0);
1231 else
1232 length = gs_fapi_serialize_type2_font(a_font, NULL, 0);
1233 open_args.memory_base = own_font_data =
1234 FF_alloc(s->ftmemory, length);
1235 if (!open_args.memory_base)
1236 return_error(gs_error_VMerror);
1237 own_font_data_len = length;
1238 if (type == 1)
1239 open_args.memory_size =
1240 gs_fapi_serialize_type1_font(a_font, own_font_data,
1241 length);
1242 else
1243 open_args.memory_size =
1244 gs_fapi_serialize_type2_font(a_font, own_font_data,
1245 length);
1246 if (open_args.memory_size != length)
1247 return_error(gs_error_unregistered); /* Must not happen. */
1248 ft_inc_int = new_inc_int(a_server, a_font);
1249 if (!ft_inc_int) {
1250 FF_free(s->ftmemory, own_font_data);
1251 return_error(gs_error_VMerror);
1252 }
1253 }
1254
1255 /* It must be type 42 (see code in FAPI_FF_get_glyph in zfapi.c). */
1256 else {
1257 /* Get the length of the TrueType data. */
1258 open_args.memory_size =
1259 a_font->get_long(a_font, gs_fapi_font_feature_TT_size, 0);
1260 if (open_args.memory_size == 0)
1261 return_error(gs_error_invalidfont);
1262
1263 /* Load the TrueType data into a single buffer. */
1264 open_args.memory_base = own_font_data =
1265 FF_alloc(s->ftmemory, open_args.memory_size);
1266 if (!own_font_data)
1267 return_error(gs_error_VMerror);
1268
1269 own_font_data_len = open_args.memory_size;
1270
1271 if (a_font->
1272 serialize_tt_font(a_font, own_font_data,
1273 open_args.memory_size))
1274 return_error(gs_error_invalidfont);
1275
1276 /* We always load incrementally. */
1277 ft_inc_int = new_inc_int(a_server, a_font);
1278 if (!ft_inc_int) {
1279 FF_free(s->ftmemory, own_font_data);
1280 return_error(gs_error_VMerror);
1281 }
1282 }
1283
1284 if (ft_inc_int) {
1285 open_args.flags =
1286 (FT_UInt) (open_args.flags | FT_OPEN_PARAMS);
1287 ft_param.tag = FT_PARAM_TAG_INCREMENTAL;
1288 ft_param.data = ft_inc_int;
1289 open_args.num_params = 1;
1290 open_args.params = &ft_param;
1291 }
1292 ft_error =
1293 FT_Open_Face(s->freetype_library, &open_args, a_font->subfont,
1294 &ft_face);
1295 if (ft_error) {
1296 delete_inc_int (a_server, ft_inc_int);
1297 FF_free(s->ftmemory, own_font_data);
1298 return ft_to_gs_error(ft_error);
1299 }
1300 }
1301
1302 if (ft_face) {
1303 face =
1304 new_face(a_server, ft_face, ft_inc_int, ft_strm,
1305 own_font_data, own_font_data_len, data_owned);
1306 if (!face) {
1307 FF_free(s->ftmemory, own_font_data);
1308 FT_Done_Face(ft_face);
1309 delete_inc_int(a_server, ft_inc_int);
1310 return_error(gs_error_VMerror);
1311 }
1312 a_font->server_font_data = face;
1313 }
1314 else
1315 a_font->server_font_data = NULL;
1316 }
1317
1318 /* Set the point size and transformation.
1319 * The matrix is scaled by the shift specified in the server, 16,
1320 * so we divide by 65536 when converting to a gs_matrix.
1321 */
1322 if (face) {
1323 /* Convert the GS transform into an FT transform.
1324 * Ignore the translation elements because they contain very large values
1325 * derived from the current transformation matrix and so are of no use.
1326 */
1327 face->ft_transform.xx = a_font_scale->matrix[0];
1328 face->ft_transform.xy = a_font_scale->matrix[2];
1329 face->ft_transform.yx = a_font_scale->matrix[1];
1330 face->ft_transform.yy = a_font_scale->matrix[3];
1331
1332 face->horz_res = a_font_scale->HWResolution[0] >> 16;
1333 face->vert_res = a_font_scale->HWResolution[1] >> 16;
1334
1335 /* Split the transform into scale factors and a rotation-and-shear
1336 * transform.
1337 */
1338 transform_decompose(&face->ft_transform, &face->horz_res,
1339 &face->vert_res, &face->width, &face->height, face->ft_face->units_per_EM);
1340
1341 ft_error = FT_Set_Char_Size(face->ft_face, face->width, face->height,
1342 face->horz_res, face->vert_res);
1343
1344 if (ft_error) {
1345 /* The code originally cleaned up the face data here, but the "top level"
1346 font object still has references to the face data, and we've no way
1347 to tell it it's gone. So we defer releasing the data until the garbage
1348 collector collects the font object, and the font's finalize call will
1349 free the data correctly for us.
1350 */
1351 return ft_to_gs_error(ft_error);
1352 }
1353
1354 /* Concatenate the transform to a reflection around (y=0) so that it
1355 * produces a glyph that is upside down in FreeType terms, with its
1356 * first row at the bottom. That is what GhostScript needs.
1357 */
1358
1359 FT_Set_Transform(face->ft_face, &face->ft_transform, NULL);
1360
1361 if (!a_font->is_type1) {
1362 for (i = 0; i < GS_FAPI_NUM_TTF_CMAP_REQ && !cmap; i++) {
1363 if (a_font->ttf_cmap_req[i].platform_id > 0) {
1364 for (j = 0; j < face->ft_face->num_charmaps; j++) {
1365 if (face->ft_face->charmaps[j]->platform_id == a_font->ttf_cmap_req[i].platform_id
1366 && face->ft_face->charmaps[j]->encoding_id == a_font->ttf_cmap_req[i].encoding_id) {
1367
1368 cmap = face->ft_face->charmaps[j];
1369 break;
1370 }
1371 }
1372 }
1373 else {
1374 break;
1375 }
1376 }
1377 if (cmap) {
1378 (void)FT_Set_Charmap(face->ft_face, cmap);
1379 }
1380 else if (a_font->full_font_buf != NULL || a_font->font_file_path != NULL) {
1381 /* If we've passed a complete TTF to Freetype, but *haven't* requested a
1382 * specific cmap table above, try to use a Unicode one
1383 * If that doesn't work, just leave the default in place.
1384 */
1385 (void)FT_Select_Charmap(face->ft_face, ft_encoding_unicode);
1386 }
1387 /* For PDF, we have to know which cmap table actually was selected */
1388 if (face->ft_face->charmap != NULL) {
1389 a_font->ttf_cmap_selected.platform_id = face->ft_face->charmap->platform_id;
1390 a_font->ttf_cmap_selected.encoding_id = face->ft_face->charmap->encoding_id;
1391 }
1392 else {
1393 /* Just in case */
1394 a_font->ttf_cmap_selected.platform_id = -1;
1395 a_font->ttf_cmap_selected.encoding_id = -1;
1396 }
1397 }
1398 else {
1399 /* Just in case */
1400 a_font->ttf_cmap_selected.platform_id = -1;
1401 a_font->ttf_cmap_selected.encoding_id = -1;
1402 }
1403 }
1404
1405 /* dpf("gs_fapi_ft_get_scaled_font return %d\n", a_font->server_font_data ? 0 : -1); */
1406 return a_font->server_font_data ? 0 : -1;
1407 }
1408
1409 /*
1410 * Return the name of a resource which maps names to character codes. Do this
1411 * by setting a_decoding_id to point to a null-terminated string. The resource
1412 * is in the 'decoding' directory in the directory named by /GenericResourceDir
1413 * in lib/gs_res.ps.
1414 */
1415 static gs_fapi_retcode
gs_fapi_ft_get_decodingID(gs_fapi_server * a_server,gs_fapi_font * a_font,const char ** a_decoding_id)1416 gs_fapi_ft_get_decodingID(gs_fapi_server * a_server, gs_fapi_font * a_font,
1417 const char **a_decoding_id)
1418 {
1419 *a_decoding_id = "Unicode";
1420 return 0;
1421 }
1422
1423 /*
1424 * Get the font bounding box in font units.
1425 */
1426 static gs_fapi_retcode
gs_fapi_ft_get_font_bbox(gs_fapi_server * a_server,gs_fapi_font * a_font,int a_box[4],int unitsPerEm[2])1427 gs_fapi_ft_get_font_bbox(gs_fapi_server * a_server, gs_fapi_font * a_font, int a_box[4], int unitsPerEm[2])
1428 {
1429 ff_face *face = (ff_face *) a_font->server_font_data;
1430
1431 a_box[0] = face->ft_face->bbox.xMin;
1432 a_box[1] = face->ft_face->bbox.yMin;
1433 a_box[2] = face->ft_face->bbox.xMax;
1434 a_box[3] = face->ft_face->bbox.yMax;
1435
1436 unitsPerEm[0] = unitsPerEm[1] = face->ft_face->units_per_EM;
1437
1438 return 0;
1439 }
1440
1441 /*
1442 * Return a boolean value in a_proportional stating whether the font is proportional
1443 * or fixed-width.
1444 */
1445 static gs_fapi_retcode
gs_fapi_ft_get_font_proportional_feature(gs_fapi_server * a_server,gs_fapi_font * a_font,bool * a_proportional)1446 gs_fapi_ft_get_font_proportional_feature(gs_fapi_server * a_server,
1447 gs_fapi_font * a_font, bool * a_proportional)
1448 {
1449 *a_proportional = true;
1450 return 0;
1451 }
1452
1453 /* Convert the character name in a_char_ref.char_name to a character code or
1454 * glyph index and put it in a_char_ref.char_code, setting
1455 * a_char_ref.is_glyph_index as appropriate. If this is possible set a_result
1456 * to true, otherwise set it to false. The return value is a standard error
1457 * return code.
1458 */
1459 static gs_fapi_retcode
gs_fapi_ft_can_retrieve_char_by_name(gs_fapi_server * a_server,gs_fapi_font * a_font,gs_fapi_char_ref * a_char_ref,bool * a_result)1460 gs_fapi_ft_can_retrieve_char_by_name(gs_fapi_server * a_server, gs_fapi_font * a_font,
1461 gs_fapi_char_ref * a_char_ref, bool * a_result)
1462 {
1463 ff_face *face = (ff_face *) a_font->server_font_data;
1464 char name[128];
1465
1466 if (FT_HAS_GLYPH_NAMES(face->ft_face)
1467 && a_char_ref->char_name_length < sizeof(name)) {
1468 memcpy(name, a_char_ref->char_name, a_char_ref->char_name_length);
1469 name[a_char_ref->char_name_length] = 0;
1470 a_char_ref->char_codes[0] = FT_Get_Name_Index(face->ft_face, name);
1471 *a_result = a_char_ref->char_codes[0] != 0;
1472 if (*a_result)
1473 a_char_ref->is_glyph_index = true;
1474 }
1475 else
1476 *a_result = false;
1477 return 0;
1478 }
1479
1480 /*
1481 * Return non-zero if the metrics can be replaced.
1482 */
1483 static gs_fapi_retcode
gs_fapi_ft_can_replace_metrics(gs_fapi_server * a_server,gs_fapi_font * a_font,gs_fapi_char_ref * a_char_ref,int * a_result)1484 gs_fapi_ft_can_replace_metrics(gs_fapi_server * a_server, gs_fapi_font * a_font,
1485 gs_fapi_char_ref * a_char_ref, int *a_result)
1486 {
1487 /* Replace metrics only if the metrics are supplied in font units. */
1488 *a_result = 1;
1489 return 0;
1490 }
1491
1492 /*
1493 * Retrieve the metrics of a_char_ref and put them in a_metrics.
1494 */
1495 static gs_fapi_retcode
gs_fapi_ft_get_char_width(gs_fapi_server * a_server,gs_fapi_font * a_font,gs_fapi_char_ref * a_char_ref,gs_fapi_metrics * a_metrics)1496 gs_fapi_ft_get_char_width(gs_fapi_server * a_server, gs_fapi_font * a_font,
1497 gs_fapi_char_ref * a_char_ref, gs_fapi_metrics * a_metrics)
1498 {
1499 ff_server *s = (ff_server *) a_server;
1500
1501 return load_glyph(a_server, a_font, a_char_ref, a_metrics,
1502 (FT_Glyph *) & s->outline_glyph,
1503 false, a_server->max_bitmap);
1504 }
1505
1506 static gs_fapi_retcode
gs_fapi_ft_get_fontmatrix(gs_fapi_server * server,gs_matrix * m)1507 gs_fapi_ft_get_fontmatrix(gs_fapi_server * server, gs_matrix * m)
1508 {
1509 m->xx = 1.0;
1510 m->xy = 0.0;
1511 m->yx = 0.0;
1512 m->yy = 1.0;
1513 m->tx = 0.0;
1514 m->ty = 0.0;
1515 return 0;
1516 }
1517
1518 /*
1519 * Rasterize the character a_char and return its metrics. Do not return the
1520 * bitmap but store this. It can be retrieved by a subsequent call to
1521 * gs_fapi_ft_get_char_raster.
1522 */
1523 static gs_fapi_retcode
gs_fapi_ft_get_char_raster_metrics(gs_fapi_server * a_server,gs_fapi_font * a_font,gs_fapi_char_ref * a_char_ref,gs_fapi_metrics * a_metrics)1524 gs_fapi_ft_get_char_raster_metrics(gs_fapi_server * a_server, gs_fapi_font * a_font,
1525 gs_fapi_char_ref * a_char_ref,
1526 gs_fapi_metrics * a_metrics)
1527 {
1528 ff_server *s = (ff_server *) a_server;
1529 gs_fapi_retcode error =
1530 load_glyph(a_server, a_font, a_char_ref, a_metrics,
1531 (FT_Glyph *) & s->bitmap_glyph, true,
1532 a_server->max_bitmap);
1533 return error;
1534 }
1535
1536 /*
1537 * Return the bitmap created by the last call to gs_fapi_ft_get_char_raster_metrics.
1538 */
1539 static gs_fapi_retcode
gs_fapi_ft_get_char_raster(gs_fapi_server * a_server,gs_fapi_raster * a_raster)1540 gs_fapi_ft_get_char_raster(gs_fapi_server * a_server, gs_fapi_raster * a_raster)
1541 {
1542 ff_server *s = (ff_server *) a_server;
1543
1544 if (!s->bitmap_glyph)
1545 return(gs_error_unregistered);
1546 a_raster->p = s->bitmap_glyph->bitmap.buffer;
1547 a_raster->width = s->bitmap_glyph->bitmap.width;
1548 a_raster->height = s->bitmap_glyph->bitmap.rows;
1549 a_raster->line_step = s->bitmap_glyph->bitmap.pitch;
1550 a_raster->orig_x = s->bitmap_glyph->left * 16;
1551 a_raster->orig_y = s->bitmap_glyph->top * 16;
1552 a_raster->left_indent = a_raster->top_indent = a_raster->black_height =
1553 a_raster->black_width = 0;
1554 return 0;
1555 }
1556
1557 /*
1558 * Create an outline for the character a_char and return its metrics. Do not
1559 * return the outline but store this.
1560 * It can be retrieved by a subsequent call to gs_fapi_ft_get_char_outline.
1561 */
1562 static gs_fapi_retcode
gs_fapi_ft_get_char_outline_metrics(gs_fapi_server * a_server,gs_fapi_font * a_font,gs_fapi_char_ref * a_char_ref,gs_fapi_metrics * a_metrics)1563 gs_fapi_ft_get_char_outline_metrics(gs_fapi_server * a_server, gs_fapi_font * a_font,
1564 gs_fapi_char_ref * a_char_ref,
1565 gs_fapi_metrics * a_metrics)
1566 {
1567 ff_server *s = (ff_server *) a_server;
1568
1569 return load_glyph(a_server, a_font, a_char_ref, a_metrics,
1570 (FT_Glyph *) & s->outline_glyph, false,
1571 a_server->max_bitmap);
1572 }
1573
1574 typedef struct FF_path_info_s
1575 {
1576 gs_fapi_path *path;
1577 int64_t x;
1578 int64_t y;
1579 FT_Vector currentp;
1580 } FF_path_info;
1581
1582 static inline int
FF_points_equal(const FT_Vector * p1,const FT_Vector * p2)1583 FF_points_equal(const FT_Vector *p1, const FT_Vector *p2)
1584 {
1585 if (p1->x == p2->x && p1->y == p2->y)
1586 return 1;
1587 else
1588 return 0;
1589 }
1590
1591 static int
move_to(const FT_Vector * aTo,void * aObject)1592 move_to(const FT_Vector * aTo, void *aObject)
1593 {
1594 FF_path_info *p = (FF_path_info *) aObject;
1595
1596 p->currentp = *aTo;
1597
1598 /* FAPI expects that co-ordinates will be as implied by frac_shift
1599 * in our case 16.16 fixed precision. True for 'low level' FT
1600 * routines (apparently), it isn't true for these routines where
1601 * FT returns a 26.6 format. Rescale to 16.16 so that FAPI will
1602 * be able to convert to GS co-ordinates properly.
1603 */
1604 /* FAPI now expects these coordinates in 32.32 */
1605 p->x = ((int64_t) aTo->x) << 26;
1606 p->y = ((int64_t) aTo->y) << 26;
1607
1608 return p->path->moveto(p->path, p->x, p->y) ? -1 : 0;
1609 }
1610
1611 static int
line_to(const FT_Vector * aTo,void * aObject)1612 line_to(const FT_Vector * aTo, void *aObject)
1613 {
1614 FF_path_info *p = (FF_path_info *) aObject;
1615
1616 if (!FF_points_equal(&p->currentp, aTo)) {
1617 p->currentp = *aTo;
1618
1619 /* See move_to() above */
1620 p->x = ((int64_t) aTo->x) << 26;
1621 p->y = ((int64_t) aTo->y) << 26;
1622
1623 return p->path->lineto(p->path, p->x, p->y) ? -1 : 0;
1624 }
1625 return 0;
1626 }
1627
1628 static int
conic_to(const FT_Vector * aControl,const FT_Vector * aTo,void * aObject)1629 conic_to(const FT_Vector * aControl, const FT_Vector * aTo, void *aObject)
1630 {
1631 FF_path_info *p = (FF_path_info *) aObject;
1632 double x, y, Controlx, Controly;
1633 int64_t Control1x, Control1y, Control2x, Control2y;
1634 double sx, sy;
1635
1636 if (!FF_points_equal(&p->currentp, aControl) ||
1637 !FF_points_equal(&p->currentp, aTo) ||
1638 !FF_points_equal(aControl, aTo)) {
1639 p->currentp = *aTo;
1640
1641 /* More complicated than above, we need to do arithmetic on the
1642 * co-ordinates, so we want them as floats and we will convert the
1643 * result into 16.16 fixed precision for FAPI
1644 *
1645 * NB this code is funcitonally the same as the original, but I don't believe
1646 * the comment (below) to be what the code is actually doing....
1647 *
1648 * NB2: the comment below was wrong, even though the code was correct(!!)
1649 * The comment has now been amended.
1650 *
1651 * Convert a quadratic spline to a cubic. Do this by changing the three points
1652 * A, B and C to A, 2/3(B,A), 2/3(B,C), C - that is, the two cubic control points are
1653 * a third of the way from the single quadratic control point to the end points. This
1654 * gives the same curve as the original quadratic.
1655 */
1656
1657 sx = (double) (p->x >> 32);
1658 sy = (double) (p->y >> 32);
1659
1660 x = aTo->x / 64.0;
1661 p->x = ((int64_t) float2fixed(x)) << 24;
1662 y = aTo->y / 64.0;
1663 p->y = ((int64_t) float2fixed(y)) << 24;
1664 Controlx = aControl->x / 64.0;
1665 Controly = aControl->y / 64.0;
1666
1667 Control1x = ((int64_t) float2fixed((sx + Controlx * 2) / 3)) << 24;
1668 Control1y = ((int64_t) float2fixed((sy + Controly * 2) / 3)) << 24;
1669 Control2x = ((int64_t) float2fixed((x + Controlx * 2) / 3)) << 24;
1670 Control2y = ((int64_t) float2fixed((y + Controly * 2) / 3)) << 24;
1671
1672 return p->path->curveto(p->path, Control1x,
1673 Control1y,
1674 Control2x, Control2y, p->x, p->y) ? -1 : 0;
1675 }
1676 return 0;
1677 }
1678
1679 static int
cubic_to(const FT_Vector * aControl1,const FT_Vector * aControl2,const FT_Vector * aTo,void * aObject)1680 cubic_to(const FT_Vector * aControl1, const FT_Vector * aControl2,
1681 const FT_Vector * aTo, void *aObject)
1682 {
1683 FF_path_info *p = (FF_path_info *) aObject;
1684 int64_t Control1x, Control1y, Control2x, Control2y;
1685
1686 if (!FF_points_equal(&p->currentp, aControl1) ||
1687 !FF_points_equal(&p->currentp, aControl2) ||
1688 !FF_points_equal(&p->currentp, aTo) ||
1689 !FF_points_equal(aControl1, aControl2) ||
1690 !FF_points_equal(aControl1, aTo) ||
1691 !FF_points_equal(aControl2, aTo)) {
1692 p->currentp = *aTo;
1693
1694 /* See move_to() above */
1695 p->x = ((int64_t) aTo->x) << 26;
1696 p->y = ((int64_t) aTo->y) << 26;
1697
1698 Control1x = ((int64_t) aControl1->x) << 26;
1699 Control1y = ((int64_t) aControl1->y) << 26;
1700 Control2x = ((int64_t) aControl2->x) << 26;
1701 Control2y = ((int64_t) aControl2->y) << 26;
1702 return p->path->curveto(p->path, Control1x, Control1y, Control2x,
1703 Control2y, p->x, p->y) ? -1 : 0;
1704 }
1705 return 0;
1706 }
1707
1708 static const FT_Outline_Funcs TheFtOutlineFuncs = {
1709 move_to,
1710 line_to,
1711 conic_to,
1712 cubic_to,
1713 0,
1714 0
1715 };
1716
1717 /*
1718 * Return the outline created by the last call to gs_fapi_ft_get_char_outline_metrics.
1719 */
1720 static gs_fapi_retcode
gs_fapi_ft_get_char_outline(gs_fapi_server * a_server,gs_fapi_path * a_path)1721 gs_fapi_ft_get_char_outline(gs_fapi_server * a_server, gs_fapi_path * a_path)
1722 {
1723 ff_server *s = (ff_server *) a_server;
1724 FF_path_info p;
1725 FT_Error ft_error = 0;
1726
1727 p.path = a_path;
1728 p.x = 0;
1729 p.y = 0;
1730 /* If we got an error during glyph creation, we can get
1731 * here with s->outline_glyph == NULL
1732 */
1733 if (s->outline_glyph) {
1734 ft_error =
1735 FT_Outline_Decompose(&s->outline_glyph->outline, &TheFtOutlineFuncs,
1736 &p);
1737 }
1738 else {
1739 a_path->moveto(a_path, 0, 0);
1740 }
1741
1742 if (a_path->gs_error == 0)
1743 a_path->closepath(a_path);
1744 return ft_to_gs_error(ft_error);
1745 }
1746
1747 static gs_fapi_retcode
gs_fapi_ft_release_char_data(gs_fapi_server * a_server)1748 gs_fapi_ft_release_char_data(gs_fapi_server * a_server)
1749 {
1750 ff_server *s = (ff_server *) a_server;
1751
1752 if (s->outline_glyph) {
1753 FT_Outline_Done(s->freetype_library, &s->outline_glyph->outline);
1754 FF_free(s->ftmemory, s->outline_glyph);
1755 }
1756
1757 if (s->bitmap_glyph) {
1758 FT_Bitmap_Done(s->freetype_library, &s->bitmap_glyph->bitmap);
1759 FF_free(s->ftmemory, s->bitmap_glyph);
1760 }
1761
1762 s->outline_glyph = NULL;
1763 s->bitmap_glyph = NULL;
1764 return 0;
1765 }
1766
1767 static gs_fapi_retcode
gs_fapi_ft_release_typeface(gs_fapi_server * a_server,void * a_server_font_data)1768 gs_fapi_ft_release_typeface(gs_fapi_server * a_server, void *a_server_font_data)
1769 {
1770 ff_face *face = (ff_face *) a_server_font_data;
1771
1772 delete_face(a_server, face);
1773 return 0;
1774 }
1775
1776 static gs_fapi_retcode
gs_fapi_ft_check_cmap_for_GID(gs_fapi_server * server,uint * index)1777 gs_fapi_ft_check_cmap_for_GID(gs_fapi_server * server, uint * index)
1778 {
1779 ff_face *face = (ff_face *) (server->ff.server_font_data);
1780 FT_Face ft_face = face->ft_face;
1781
1782 *index = FT_Get_Char_Index(ft_face, *index);
1783 return 0;
1784 }
1785
1786 static gs_fapi_retcode
gs_fapi_ft_set_mm_weight_vector(gs_fapi_server * server,gs_fapi_font * ff,float * wvector,int length)1787 gs_fapi_ft_set_mm_weight_vector(gs_fapi_server *server, gs_fapi_font *ff, float *wvector, int length)
1788 {
1789 #if defined(SHARE_FT) && SHARE_FT == 1 && \
1790 FREETYPE_MAJOR <= 2 && FREETYPE_MINOR <= 9 && FREETYPE_PATCH <= 1
1791
1792 return gs_error_invalidaccess;
1793 #else
1794 ff_face *face = (ff_face *) ff->server_font_data;
1795 FT_Fixed nwv[16] = {0};
1796 FT_Fixed cwv[16] = {0};
1797 FT_UInt len = 16;
1798 int i;
1799 bool setit = false;
1800 FT_Error ft_error;
1801 (void)server;
1802
1803 ft_error = FT_Get_MM_WeightVector(face->ft_face, &len, cwv);
1804 if (ft_error != 0) return_error(gs_error_invalidaccess);
1805
1806 for (i = 0; i < length; i++) {
1807 nwv[i] = (FT_Fixed)(wvector[i] * 65536.0);
1808 if (nwv[i] != cwv[i]) {
1809 setit = true;
1810 }
1811 }
1812
1813 if (setit == true) {
1814 ft_error = FT_Set_MM_WeightVector(face->ft_face, length, nwv);
1815 if (ft_error != 0) return_error(gs_error_invalidaccess);
1816 }
1817
1818 return 0;
1819 #endif
1820 }
1821
1822 static void gs_fapi_freetype_destroy(gs_fapi_server ** serv);
1823
1824 static const gs_fapi_server_descriptor freetypedescriptor = {
1825 (const char *)"FAPI",
1826 (const char *)"FreeType",
1827 gs_fapi_freetype_destroy
1828 };
1829
1830 static const gs_fapi_server freetypeserver = {
1831 {&freetypedescriptor},
1832 NULL, /* client_ctx_p */
1833 16, /* frac_shift */
1834 {gs_no_id},
1835 {0},
1836 0,
1837 false,
1838 1,
1839 {1, 0, 0, 1, 0, 0},
1840 gs_fapi_ft_ensure_open,
1841 gs_fapi_ft_get_scaled_font,
1842 gs_fapi_ft_get_decodingID,
1843 gs_fapi_ft_get_font_bbox,
1844 gs_fapi_ft_get_font_proportional_feature,
1845 gs_fapi_ft_can_retrieve_char_by_name,
1846 gs_fapi_ft_can_replace_metrics,
1847 NULL, /* can_simulate_style */
1848 gs_fapi_ft_get_fontmatrix,
1849 gs_fapi_ft_get_char_width,
1850 gs_fapi_ft_get_char_raster_metrics,
1851 gs_fapi_ft_get_char_raster,
1852 gs_fapi_ft_get_char_outline_metrics,
1853 gs_fapi_ft_get_char_outline,
1854 gs_fapi_ft_release_char_data,
1855 gs_fapi_ft_release_typeface,
1856 gs_fapi_ft_check_cmap_for_GID,
1857 NULL, /* get_font_info */
1858 gs_fapi_ft_set_mm_weight_vector,
1859 };
1860
1861 int gs_fapi_ft_init(gs_memory_t * mem, gs_fapi_server ** server);
1862
1863 int
gs_fapi_ft_init(gs_memory_t * mem,gs_fapi_server ** server)1864 gs_fapi_ft_init(gs_memory_t * mem, gs_fapi_server ** server)
1865 {
1866 ff_server *serv;
1867 int code = 0;
1868 gs_memory_t *cmem = mem->non_gc_memory;
1869
1870 code = gs_memory_chunk_wrap(&(cmem), mem);
1871 if (code != 0) {
1872 return (code);
1873 }
1874
1875
1876 serv = (ff_server *) gs_alloc_bytes_immovable(cmem, sizeof(ff_server), "gs_fapi_ft_init");
1877 if (!serv) {
1878 gs_memory_chunk_release(cmem);
1879 return_error(gs_error_VMerror);
1880 }
1881 memset(serv, 0, sizeof(*serv));
1882 serv->mem = cmem;
1883 serv->fapi_server = freetypeserver;
1884
1885 serv->ftmemory = (FT_Memory) (&(serv->ftmemory_rec));
1886
1887 (*server) = (gs_fapi_server *) serv;
1888 return (0);
1889 }
1890
1891
1892 void
gs_fapi_freetype_destroy(gs_fapi_server ** serv)1893 gs_fapi_freetype_destroy(gs_fapi_server ** serv)
1894 {
1895 ff_server *server = (ff_server *) * serv;
1896 gs_memory_t *cmem = server->mem;
1897
1898 FT_Done_Glyph(&server->outline_glyph->root);
1899 FT_Done_Glyph(&server->bitmap_glyph->root);
1900
1901 /* As with initialization: since we're supplying memory management to
1902 * FT, we cannot just to use FT_Done_FreeType (), we have to use
1903 * FT_Done_Library () and then discard the memory ourselves
1904 */
1905 FT_Done_Library(server->freetype_library);
1906 gs_free(cmem, *serv, 0, 0, "gs_fapi_freetype_destroy: ff_server");
1907 *serv = NULL;
1908 gs_memory_chunk_release(cmem);
1909 }
1910