1 /* Copyright (C) 2001-2006 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, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12  */
13 /* $Id: fapi_ft.c 10653 2010-01-28 14:32:52Z ken $ */
14 
15 /*
16    GhostScript Font API plug-in that allows fonts to be rendered by FreeType.
17    Started by Graham Asher, 6th June 2002.
18  */
19 
20 /* GhostScript headers. */
21 #include "stdio_.h"
22 #include "malloc_.h"
23 #include "ierrors.h"
24 #include "ifapi.h"
25 #include "write_t1.h"
26 #include "write_t2.h"
27 #include "math_.h"
28 #include "gserror.h"
29 #include "gxfixed.h"
30 
31 /* FreeType headers */
32 #include <ft2build.h>
33 #include FT_FREETYPE_H
34 #include FT_INCREMENTAL_H
35 #include FT_GLYPH_H
36 
37 /* Note: structure definitions here start with FF_, which stands for 'FAPI FreeType". */
38 
39 typedef struct FF_server_s
40 {
41     FAPI_server fapi_server;
42     FT_Library freetype_library;
43     FT_OutlineGlyph outline_glyph;
44     FT_BitmapGlyph bitmap_glyph;
45 } FF_server;
46 
47 typedef struct FF_face_s
48 {
49     FT_Face ft_face;
50 
51     /* If non-null, the incremental interface object passed to FreeType. */
52     FT_Incremental_InterfaceRec *ft_inc_int;
53 
54     /* Non-null if font data is owned by this object. */
55     unsigned char *font_data;
56 } FF_face;
57 
58 /* Here we define the struct FT_Incremental that is used as an opaque type
59  * inside FreeType. This structure has to have the tag FT_IncrementalRec_
60  * to be compatible with the functions defined in FT_Incremental_FuncsRec.
61  */
62 typedef struct FT_IncrementalRec_
63 {
64     FAPI_font *fapi_font;		/* The font. */
65 
66     /* If it is already in use glyph data is allocated on the heap. */
67     unsigned char *glyph_data;		/* A one-shot buffer for glyph data. */
68     size_t glyph_data_length;		/* Length in bytes of glyph_data. */
69     bool glyph_data_in_use;		/* True if glyph_data is already in use. */
70 
71     FT_Incremental_MetricsRec glyph_metrics; /* Incremental glyph metrics supplied by Ghostscript. */
72     unsigned long glyph_metrics_index;	/* contains data for this glyph index unless it is 0xFFFFFFFF. */
73     FAPI_metrics_type metrics_type;	/* determines whether metrics are replaced, added, etc. */
74 } FT_IncrementalRec;
75 
76 static FF_face *
new_face(FT_Face a_ft_face,FT_Incremental_InterfaceRec * a_ft_inc_int,unsigned char * a_font_data)77 new_face(FT_Face a_ft_face, FT_Incremental_InterfaceRec *a_ft_inc_int, unsigned char *a_font_data)
78 {
79     FF_face *face = (FF_face *)malloc(sizeof(FF_face));
80     if (face)
81     {
82 	face->ft_face = a_ft_face;
83 	face->ft_inc_int = a_ft_inc_int;
84 	face->font_data = a_font_data;
85     }
86     return face;
87 }
88 
89 static void
delete_face(FF_face * a_face)90 delete_face(FF_face *a_face)
91 {
92     if (a_face)
93     {
94 	FT_Done_Face(a_face->ft_face);
95 	free(a_face->ft_inc_int);
96 	free(a_face->font_data);
97 	free(a_face);
98     }
99 }
100 
101 static FT_IncrementalRec *
new_inc_int_info(FAPI_font * a_fapi_font)102 new_inc_int_info(FAPI_font *a_fapi_font)
103 {
104     FT_IncrementalRec *info = (FT_IncrementalRec*)malloc(sizeof(FT_IncrementalRec));
105     if (info)
106     {
107 	info->fapi_font = a_fapi_font;
108 	info->glyph_data = NULL;
109 	info->glyph_data_length = 0;
110 	info->glyph_data_in_use = false;
111 	info->glyph_metrics_index = 0xFFFFFFFF;
112 	info->metrics_type = FAPI_METRICS_NOTDEF;
113     }
114     return info;
115 }
116 
117 static void
delete_inc_int_info(FT_IncrementalRec * a_inc_int_info)118 delete_inc_int_info(FT_IncrementalRec *a_inc_int_info)
119 {
120     if (a_inc_int_info)
121     {
122 	free(a_inc_int_info->glyph_data);
123 	free(a_inc_int_info);
124     }
125 }
126 
127 static FT_Error
get_fapi_glyph_data(FT_Incremental a_info,FT_UInt a_index,FT_Data * a_data)128 get_fapi_glyph_data(FT_Incremental a_info, FT_UInt a_index, FT_Data *a_data)
129 {
130     FAPI_font *ff = a_info->fapi_font;
131     ushort length = 0;
132 
133     /* Tell the FAPI interface that we need to decrypt the glyph data. */
134     ff->need_decrypt = true;
135 
136     /* If glyph_data is already in use (as will happen for composite glyphs)
137      * create a new buffer on the heap.
138      */
139     if (a_info->glyph_data_in_use)
140     {
141 	unsigned char *buffer = NULL;
142 	length = ff->get_glyph(ff, a_index, NULL, 0);
143 	if (length == 65535)
144 	    return FT_Err_Invalid_Glyph_Index;
145 	buffer = malloc(length);
146 	if (!buffer)
147 	    return FT_Err_Out_Of_Memory;
148 	if (ff->get_glyph(ff, a_index, buffer, length) == 65535) {
149 	    free (buffer);
150 	    return FT_Err_Invalid_Glyph_Index;
151 	}
152 	a_data->pointer = buffer;
153     }
154     else
155     {
156 	/* Save ff->char_data, which is set to null by FAPI_FF_get_glyph as part of a hack to
157 	 * make the deprecated Type 2 endchar ('seac') work, so that it can be restored
158 	 * if we need to try again with a longer buffer.
159 	 */
160 	const void *saved_char_data = ff->char_data;
161 
162 	/* Get as much of the glyph data as possible into the buffer */
163 	length = ff->get_glyph(ff, a_index, a_info->glyph_data, (ushort)a_info->glyph_data_length);
164 
165 	/* If the buffer was too small enlarge it and try again. */
166 	if (length > a_info->glyph_data_length)
167 	{
168 	    a_info->glyph_data = realloc(a_info->glyph_data, length);
169 	    if (!a_info->glyph_data)
170 	    {
171 		a_info->glyph_data_length = 0;
172 		return FT_Err_Out_Of_Memory;
173 	    }
174 	    a_info->glyph_data_length = length;
175 	    ff->char_data = saved_char_data;
176 	    ff->get_glyph(ff, a_index, a_info->glyph_data, length);
177 	}
178 
179 	/* Set the returned pointer and length. */
180 	a_data->pointer = a_info->glyph_data;
181 
182 	a_info->glyph_data_in_use = true;
183     }
184 
185     a_data->length = length;
186     return 0;
187 }
188 
189 static void
free_fapi_glyph_data(FT_Incremental a_info,FT_Data * a_data)190 free_fapi_glyph_data(FT_Incremental a_info, FT_Data *a_data)
191 {
192     if (a_data->pointer == (const FT_Byte*)a_info->glyph_data)
193 	a_info->glyph_data_in_use = false;
194     else
195 	free((FT_Byte*)a_data->pointer);
196 }
197 
198 static FT_Error
get_fapi_glyph_metrics(FT_Incremental a_info,FT_UInt a_glyph_index,FT_Bool bVertical,FT_Incremental_MetricsRec * a_metrics)199 get_fapi_glyph_metrics(FT_Incremental a_info, FT_UInt a_glyph_index,
200 	FT_Bool bVertical, FT_Incremental_MetricsRec *a_metrics)
201 {
202     /* fixme : bVertical is not implemented. */
203     if (a_info->glyph_metrics_index == a_glyph_index)
204     {
205 	switch (a_info->metrics_type)
206 	{
207 	    case FAPI_METRICS_ADD:
208 		a_metrics->advance += a_info->glyph_metrics.advance;
209 		break;
210 	    case FAPI_METRICS_REPLACE_WIDTH:
211 		a_metrics->advance = a_info->glyph_metrics.advance;
212 		break;
213 	    case FAPI_METRICS_REPLACE:
214 		*a_metrics = a_info->glyph_metrics;
215 		break;
216 	    default:
217 		/* This can't happen. */
218 		return FT_Err_Invalid_Argument;
219 	}
220     }
221     return 0;
222 }
223 
224 static const
225 FT_Incremental_FuncsRec TheFAPIIncrementalInterfaceFuncs =
226 {
227     get_fapi_glyph_data,
228     free_fapi_glyph_data,
229     get_fapi_glyph_metrics
230 };
231 
232 static FT_Incremental_InterfaceRec *
new_inc_int(FAPI_font * a_fapi_font)233 new_inc_int(FAPI_font *a_fapi_font)
234 {
235     FT_Incremental_InterfaceRec *i =
236 	(FT_Incremental_InterfaceRec*) malloc(sizeof(FT_Incremental_InterfaceRec)); /* malloc!? /Tor */
237     if (i)
238     {
239 	i->object = (FT_Incremental)new_inc_int_info(a_fapi_font);
240 	i->funcs = &TheFAPIIncrementalInterfaceFuncs;
241     }
242     if (!i->object)
243     {
244 	free(i);
245 	i = NULL;
246     }
247     return i;
248 }
249 
250 static void
delete_inc_int(FT_Incremental_InterfaceRec * a_inc_int)251 delete_inc_int(FT_Incremental_InterfaceRec *a_inc_int)
252 {
253     if (a_inc_int)
254     {
255 	delete_inc_int_info(a_inc_int->object);
256 	free(a_inc_int);
257     }
258 }
259 
260 /* Convert FreeType error codes to GhostScript ones.
261  * Very rudimentary because most don't correspond.
262  */
263 static int
ft_to_gs_error(FT_Error a_error)264 ft_to_gs_error(FT_Error a_error)
265 {
266     if (a_error)
267     {
268 	if (a_error == FT_Err_Out_Of_Memory)
269 	    return e_VMerror;
270 	else
271 	    return e_unknownerror;
272     }
273     return 0;
274 }
275 
276 /* Load a glyph and optionally rasterize it. Return its metrics in a_metrics.
277  * If a_bitmap is true convert the glyph to a bitmap.
278  */
279 static FAPI_retcode
load_glyph(FAPI_font * a_fapi_font,const FAPI_char_ref * a_char_ref,FAPI_metrics * a_metrics,FT_Glyph * a_glyph,bool a_bitmap)280 load_glyph(FAPI_font *a_fapi_font, const FAPI_char_ref *a_char_ref,
281 	FAPI_metrics *a_metrics, FT_Glyph *a_glyph, bool a_bitmap)
282 {
283     FT_Error ft_error = 0;
284     FF_face *face = (FF_face*)a_fapi_font->server_font_data;
285     FT_Face ft_face = face->ft_face;
286     int index = a_char_ref->char_code;
287 
288     /* Save a_fapi_font->char_data, which is set to null by FAPI_FF_get_glyph as part of a hack to
289      * make the deprecated Type 2 endchar ('seac') work, so that it can be restored
290      * after the first call to FT_Load_Glyph.
291      */
292     const void *saved_char_data = a_fapi_font->char_data;
293 
294     if (!a_char_ref->is_glyph_index)
295     {
296 	if (ft_face->num_charmaps)
297 	    index = FT_Get_Char_Index(ft_face, index);
298 	else
299 	{
300 	    /* If there are no character maps and no glyph index, loading the glyph will still work
301 	     * properly if both glyph data and metrics are supplied by the incremental interface.
302 	     * In that case we use a dummy glyph index which will be passed
303 	     * back to FAPI_FF_get_glyph by get_fapi_glyph_data.
304 	     *
305 	     * Type 1 fonts don't use the code and can appear to FreeType to have only one glyph,
306 	     * so we have to set the index to 0.
307 	     *
308 	     * For other font types, FAPI_FF_get_glyph requires the character code
309 	     * when getting data.
310 	     */
311 	    if (a_fapi_font->is_type1)
312 		index = 0;
313 	    else
314 		index = a_char_ref->char_code;
315 	}
316     }
317 
318     /* Refresh the pointer to the FAPI_font held by the incremental interface. */
319     if (face->ft_inc_int)
320 	face->ft_inc_int->object->fapi_font = a_fapi_font;
321 
322     /* Store the overriding metrics if they have been supplied. */
323     if (face->ft_inc_int && a_char_ref->metrics_type != FAPI_METRICS_NOTDEF)
324     {
325 	FT_Incremental_MetricsRec *m = &face->ft_inc_int->object->glyph_metrics;
326 	m->bearing_x = a_char_ref->sb_x >> 16;
327 	m->bearing_y = a_char_ref->sb_y >> 16;
328 	m->advance = a_char_ref->aw_x >> 16;
329 	face->ft_inc_int->object->glyph_metrics_index = index;
330 	face->ft_inc_int->object->metrics_type = a_char_ref->metrics_type;
331     }
332 
333     ft_error = FT_Load_Glyph(ft_face, index, FT_LOAD_MONOCHROME | FT_LOAD_NO_SCALE);
334     if (!ft_error && a_metrics)
335     {
336 	a_metrics->bbox_x0 = ft_face->glyph->metrics.horiBearingX;
337 	a_metrics->bbox_y0 = ft_face->glyph->metrics.horiBearingY - ft_face->glyph->metrics.height;
338 	a_metrics->bbox_x1 = a_metrics->bbox_x0 + ft_face->glyph->metrics.width;
339 	a_metrics->bbox_y1 = a_metrics->bbox_y0 + ft_face->glyph->metrics.height;
340 	a_metrics->escapement = ft_face->glyph->metrics.horiAdvance;
341 	a_metrics->v_escapement = ft_face->glyph->metrics.vertAdvance;
342 	a_metrics->em_x = ft_face->units_per_EM;
343 	a_metrics->em_y = ft_face->units_per_EM;
344     }
345 
346     /* We have to load the glyph again, scale it correctly, and render it if we need a bitmap. */
347     if (!ft_error)
348     {
349 	a_fapi_font->char_data = saved_char_data;
350 	ft_error = FT_Load_Glyph(ft_face, index, a_bitmap ? FT_LOAD_MONOCHROME | FT_LOAD_RENDER: FT_LOAD_MONOCHROME);
351     }
352     if (!ft_error && a_glyph)
353 	ft_error = FT_Get_Glyph(ft_face->glyph, a_glyph);
354     if (ft_error == FT_Err_Too_Many_Hints) {
355 	eprintf1 ("TrueType glyph %d uses more instructions than the declared maximum in the font. Continuing, ignoring broken glyph\n", a_char_ref->char_code);
356 	ft_error = 0;
357     }
358     if (ft_error == FT_Err_Invalid_Argument) {
359 	eprintf1 ("TrueType parsing error in glyph %d in the font. Continuing, ignoring broken glyph\n", a_char_ref->char_code);
360 	ft_error = 0;
361     }
362     if (ft_error == FT_Err_Too_Many_Function_Defs) {
363 	eprintf1 ("TrueType instruction error in glyph %d in the font. Continuing, ignoring broken glyph\n", a_char_ref->char_code);
364 	ft_error = 0;
365     }
366     if (ft_error == FT_Err_Invalid_Glyph_Index) {
367 	eprintf1 ("FreeType is unable to find the glyph %d in the font. Continuing, ignoring missing glyph\n", a_char_ref->char_code);
368 	ft_error = 0;
369     }
370     return ft_to_gs_error(ft_error);
371 }
372 
373 /*
374  * Ensure that the rasterizer is open.
375  *
376  * In the case of FreeType this means creating the FreeType library object.
377  */
378 static FAPI_retcode
ensure_open(FAPI_server * a_server,const byte * server_param,int server_param_size)379 ensure_open(FAPI_server *a_server, const byte *server_param, int server_param_size)
380 {
381     FF_server *s = (FF_server*)a_server;
382     if (!s->freetype_library)
383     {
384 	FT_Error ft_error = FT_Init_FreeType(&s->freetype_library);
385 	if (ft_error)
386 	    return ft_to_gs_error(ft_error);
387     }
388     return 0;
389 }
390 
391 static void
transform_concat(FT_Matrix * a_A,const FT_Matrix * a_B)392 transform_concat(FT_Matrix *a_A, const FT_Matrix *a_B)
393 {
394     FT_Matrix result = *a_B;
395     FT_Matrix_Multiply(a_A, &result);
396     *a_A = result;
397 }
398 
399 /* Create a transform representing an angle defined as a vector. */
400 static void
make_rotation(FT_Matrix * a_transform,const FT_Vector * a_vector)401 make_rotation(FT_Matrix *a_transform, const FT_Vector *a_vector)
402 {
403     FT_Fixed length, cos, sin;
404     if (a_vector->x >= 0 && a_vector->y == 0)
405     {
406 	a_transform->xx = a_transform->yy = 65536;
407 	a_transform->xy = a_transform->yx = 0;
408 	return;
409     }
410 
411     length = FT_Vector_Length((FT_Vector*)a_vector);
412     cos = FT_DivFix(a_vector->x, length);
413     sin = FT_DivFix(a_vector->y, length);
414     a_transform->xx = a_transform->yy = cos;
415     a_transform->xy = -sin;
416     a_transform->yx = sin;
417 }
418 
419 /* Divide a transformation into a scaling part and a rotation-and-shear part.
420  * The scaling part is used for setting the pixel size for hinting.
421  */
422 static void
transform_decompose(FT_Matrix * a_transform,FT_Fixed * a_x_scale,FT_Fixed * a_y_scale)423 transform_decompose(FT_Matrix *a_transform, FT_Fixed *a_x_scale, FT_Fixed *a_y_scale)
424 {
425     float a = a_transform->xx / 65536.0;
426     float b = a_transform->xy / 65536.0;
427     float c = a_transform->yx / 65536.0;
428     float d = a_transform->yy / 65536.0;
429 
430     float scale = sqrt(fabs(a * d - b * c));
431 
432     a_transform->xx = a / scale * 65536.0;
433     a_transform->xy = b / scale * 65536.0;
434     a_transform->yx = c / scale * 65536.0;
435     a_transform->yy = d / scale * 65536.0;
436 
437     *a_x_scale = scale * 65536.0;
438     *a_y_scale = scale * 65536.0;
439 }
440 
441 /*
442  * Open a font and set its size.
443  */
444 static FAPI_retcode
get_scaled_font(FAPI_server * a_server,FAPI_font * a_font,const FAPI_font_scale * a_font_scale,const char * a_map,FAPI_descendant_code a_descendant_code)445 get_scaled_font(FAPI_server *a_server, FAPI_font *a_font,
446 	const FAPI_font_scale *a_font_scale,
447 	const char *a_map,
448 	FAPI_descendant_code a_descendant_code)
449 {
450     FF_server *s = (FF_server*)a_server;
451     FF_face *face = (FF_face*)a_font->server_font_data;
452     FT_Error ft_error = 0;
453 
454     /* dpf("get_scaled_font enter: is_type1=%d is_cid=%d font_file_path='%s' a_descendant_code=%d\n",
455        a_font->is_type1, a_font->is_cid, a_font->font_file_path ? a_font->font_file_path : "", a_descendant_code); */
456 
457     /* If this font is the top level font of an embedded CID type 0 font (font type 9)
458      * do nothing. See the comment in FAPI_prepare_font. The descendant fonts are
459      * passed in individually.
460      */
461     if (a_font->is_cid && a_font->is_type1 && a_font->font_file_path == NULL &&
462 	    (a_descendant_code == FAPI_TOPLEVEL_BEGIN ||
463 	     a_descendant_code == FAPI_TOPLEVEL_COMPLETE))
464     {
465 	/* dpf("get_scaled_font return 0\n"); */
466 	return 0;
467     }
468 
469     /* Create the face if it doesn't already exist. */
470     if (!face)
471     {
472 	FT_Face ft_face = NULL;
473 	FT_Parameter ft_param;
474 	FT_Incremental_InterfaceRec *ft_inc_int = NULL;
475 	unsigned char *own_font_data = NULL;
476 
477 	/* dpf("get_scaled_font creating face\n"); */
478 
479 	/* Load a typeface from a file. */
480 	if (a_font->font_file_path)
481 	{
482 	    ft_error = FT_New_Face(s->freetype_library, a_font->font_file_path, a_font->subfont, &ft_face);
483 	    if (!ft_error && ft_face)
484 		ft_error = FT_Select_Charmap(ft_face, ft_encoding_unicode);
485 	}
486 
487 	/* Load a typeface from a representation in GhostScript's memory. */
488 	else
489 	{
490 	    FT_Open_Args open_args;
491 	    open_args.flags = FT_OPEN_MEMORY;
492 
493 	    if (a_font->is_type1)
494 	    {
495 		long length;
496 		int type = a_font->get_word(a_font, FAPI_FONT_FEATURE_FontType, 0);
497 
498 		/* Tell the FAPI interface that we need to decrypt the /Subrs data. */
499 		a_font->need_decrypt = true;
500 
501 		/*
502 		   Serialise a type 1 font in PostScript source form, or
503 		   a Type 2 font in binary form, so that FreeType can read it.
504 		 */
505 		if (type == 1)
506 		    length = FF_serialize_type1_font(a_font, NULL, 0);
507 		else
508 		    length = FF_serialize_type2_font(a_font, NULL, 0);
509 		open_args.memory_base = own_font_data = malloc(length);
510 		if (!open_args.memory_base)
511 		    return e_VMerror;
512 		if (type == 1)
513 		    open_args.memory_size = FF_serialize_type1_font(a_font, own_font_data, length);
514 		else
515 		    open_args.memory_size = FF_serialize_type2_font(a_font, own_font_data, length);
516 		if (open_args.memory_size != length)
517 		    return_error(e_unregistered); /* Must not happen. */
518 		ft_inc_int = new_inc_int(a_font);
519 		if (!ft_inc_int)
520 		{
521 		    free(own_font_data);
522 		    return e_VMerror;
523 		}
524 	    }
525 
526 	    /* It must be type 42 (see code in FAPI_FF_get_glyph in zfapi.c). */
527 	    else
528 	    {
529 		/* Get the length of the TrueType data. */
530 		open_args.memory_size = a_font->get_long(a_font, FAPI_FONT_FEATURE_TT_size, 0);
531 		if (open_args.memory_size == 0)
532 		    return e_invalidfont;
533 
534 		/* Load the TrueType data into a single buffer. */
535 		open_args.memory_base = own_font_data = malloc(open_args.memory_size);
536 		if (!own_font_data)
537 		    return e_VMerror;
538 		if (a_font->serialize_tt_font(a_font, own_font_data, open_args.memory_size))
539 		    return e_invalidfont;
540 
541 		/* We always load incrementally. */
542 		ft_inc_int = new_inc_int(a_font);
543 		if (!ft_inc_int)
544 		{
545 		    free(own_font_data);
546 		    return e_VMerror;
547 		}
548 	    }
549 
550 	    if (ft_inc_int)
551 	    {
552 		open_args.flags = (FT_UInt)(open_args.flags | FT_OPEN_PARAMS);
553 		ft_param.tag = FT_PARAM_TAG_INCREMENTAL;
554 		ft_param.data = ft_inc_int;
555 		open_args.num_params = 1;
556 		open_args.params = &ft_param;
557 	    }
558 	    ft_error = FT_Open_Face(s->freetype_library, &open_args, a_font->subfont, &ft_face);
559 	}
560 
561 	if (ft_face)
562 	{
563 	    face = new_face(ft_face, ft_inc_int, own_font_data);
564 	    if (!face)
565 	    {
566 		free(own_font_data);
567 		FT_Done_Face(ft_face);
568 		delete_inc_int(ft_inc_int);
569 		return e_VMerror;
570 	    }
571 	    a_font->server_font_data = face;
572 	}
573 	else
574 	    a_font->server_font_data = NULL;
575     }
576 
577     /* Set the point size and transformation.
578      * The matrix is scaled by the shift specified in the server, 16,
579      * so we divide by 65536 when converting to a gs_matrix.
580      */
581     if (face)
582     {
583 	static const FT_Matrix ft_reflection = { 65536, 0, 0, -65536 };
584 	FT_Matrix ft_transform;
585 	FT_F26Dot6 width, height;
586 
587 	/* Convert the GS transform into an FT transform.
588 	 * Ignore the translation elements because they contain very large values
589 	 * derived from the current transformation matrix and so are of no use.
590 	 */
591 	ft_transform.xx = a_font_scale->matrix[0];
592 	ft_transform.xy = a_font_scale->matrix[2];
593 	ft_transform.yx = a_font_scale->matrix[1];
594 	ft_transform.yy = a_font_scale->matrix[3];
595 
596 	/* Split the transform into scale factors and a rotation-and-shear
597 	 * transform.
598 	 */
599 	transform_decompose(&ft_transform, &width, &height);
600 
601 	/* Convert width and height to 64ths of pixels and set the FreeType sizes. */
602 	width >>= 10;
603 	height >>= 10;
604 	ft_error = FT_Set_Char_Size(face->ft_face, width, height,
605 		a_font_scale->HWResolution[0] >> 16,
606 		a_font_scale->HWResolution[1] >> 16);
607 	if (ft_error)
608 	{
609 	    delete_face(face);
610 	    a_font->server_font_data = NULL;
611 	    return ft_to_gs_error(ft_error);
612 	}
613 
614 	/* Concatenate the transform to a reflection around (y=0) so that it
615 	 * produces a glyph that is upside down in FreeType terms, with its
616 	 * first row at the bottom. That is what GhostScript needs.
617 	 */
618 
619 	FT_Set_Transform(face->ft_face, &ft_transform, NULL);
620     }
621 
622     /* dpf("get_scaled_font return %d\n", a_font->server_font_data ? 0 : -1); */
623     return a_font->server_font_data ? 0 : -1;
624 }
625 
626 /*
627  * Return the name of a resource which maps names to character codes. Do this
628  * by setting a_decoding_id to point to a null-terminated string. The resource
629  * is in the 'decoding' directory in the directory named by /GenericResourceDir
630  * in lib/gs_res.ps.
631  */
632 static FAPI_retcode
get_decodingID(FAPI_server * a_server,FAPI_font * a_font,const char ** a_decoding_id)633 get_decodingID(FAPI_server *a_server, FAPI_font *a_font, const char** a_decoding_id)
634 {
635     *a_decoding_id = "Unicode";
636     return 0;
637 }
638 
639 /*
640  * Get the font bounding box in font units.
641  */
642 static FAPI_retcode
get_font_bbox(FAPI_server * a_server,FAPI_font * a_font,int a_box[4])643 get_font_bbox(FAPI_server *a_server, FAPI_font *a_font, int a_box[4])
644 {
645     FF_face *face = (FF_face*)a_font->server_font_data;
646     a_box[0] = face->ft_face->bbox.xMin;
647     a_box[1] = face->ft_face->bbox.yMin;
648     a_box[2] = face->ft_face->bbox.xMax;
649     a_box[3] = face->ft_face->bbox.yMax;
650     return 0;
651 }
652 
653 /*
654  * Return a boolean value in a_proportional stating whether the font is proportional
655  * or fixed-width.
656  */
657 static FAPI_retcode
get_font_proportional_feature(FAPI_server * a_server,FAPI_font * a_font,bool * a_proportional)658 get_font_proportional_feature(FAPI_server *a_server, FAPI_font *a_font, bool *a_proportional)
659 {
660     *a_proportional = true;
661     return 0;
662 }
663 
664 /* Convert the character name in a_char_ref.char_name to a character code or
665  * glyph index and put it in a_char_ref.char_code, setting
666  * a_char_ref.is_glyph_index as appropriate. If this is possible set a_result
667  * to true, otherwise set it to false.  The return value is a standard error
668  * return code.
669  */
670 static FAPI_retcode
can_retrieve_char_by_name(FAPI_server * a_server,FAPI_font * a_font,FAPI_char_ref * a_char_ref,bool * a_result)671 can_retrieve_char_by_name(FAPI_server *a_server, FAPI_font *a_font, FAPI_char_ref *a_char_ref, bool *a_result)
672 {
673     FF_face *face = (FF_face*)a_font->server_font_data;
674     char name[128];
675     if (FT_HAS_GLYPH_NAMES(face->ft_face) && a_char_ref->char_name_length < sizeof(name))
676     {
677 	memcpy(name, a_char_ref->char_name, a_char_ref->char_name_length);
678 	name[a_char_ref->char_name_length] = 0;
679 	a_char_ref->char_code = FT_Get_Name_Index(face->ft_face, name);
680 	*a_result = a_char_ref->char_code != 0;
681 	if (*a_result)
682 	    a_char_ref->is_glyph_index = true;
683     }
684     else
685 	*a_result = false;
686     return 0;
687 }
688 
689 /*
690  * Return non-zero if the metrics can be replaced.
691  */
692 static FAPI_retcode
can_replace_metrics(FAPI_server * a_server,FAPI_font * a_font,FAPI_char_ref * a_char_ref,int * a_result)693 can_replace_metrics(FAPI_server *a_server, FAPI_font *a_font, FAPI_char_ref *a_char_ref, int *a_result)
694 {
695     /* Replace metrics only if the metrics are supplied in font units. */
696     *a_result = a_char_ref->metrics_scale == 0;
697     return 0;
698 }
699 
700 /*
701  * Retrieve the metrics of a_char_ref and put them in a_metrics.
702  */
703 static FAPI_retcode
get_char_width(FAPI_server * a_server,FAPI_font * a_font,FAPI_char_ref * a_char_ref,FAPI_metrics * a_metrics)704 get_char_width(FAPI_server *a_server, FAPI_font *a_font, FAPI_char_ref *a_char_ref, FAPI_metrics *a_metrics)
705 {
706     return load_glyph(a_font, a_char_ref, a_metrics, NULL, false);
707 }
708 
709 /*
710  * Rasterize the character a_char and return its metrics. Do not return the
711  * bitmap but store this. It can be retrieved by a subsequent call to
712  * get_char_raster.
713  */
714 static FAPI_retcode
get_char_raster_metrics(FAPI_server * a_server,FAPI_font * a_font,FAPI_char_ref * a_char_ref,FAPI_metrics * a_metrics)715 get_char_raster_metrics(FAPI_server *a_server, FAPI_font *a_font,
716 	FAPI_char_ref *a_char_ref, FAPI_metrics *a_metrics)
717 {
718     FF_server *s = (FF_server*)a_server;
719     FAPI_retcode error = load_glyph(a_font, a_char_ref, a_metrics, (FT_Glyph*)&s->bitmap_glyph, true);
720     return error;
721 }
722 
723 /*
724  * Return the bitmap created by the last call to get_char_raster_metrics.
725  */
726 static FAPI_retcode
get_char_raster(FAPI_server * a_server,FAPI_raster * a_raster)727 get_char_raster(FAPI_server *a_server, FAPI_raster *a_raster)
728 {
729     FF_server *s = (FF_server*)a_server;
730     if (!s->bitmap_glyph)
731 	return_error(e_unregistered); /* Must not happen. */
732     a_raster->p = s->bitmap_glyph->bitmap.buffer;
733     a_raster->width = s->bitmap_glyph->bitmap.width;
734     a_raster->height = s->bitmap_glyph->bitmap.rows;
735     a_raster->line_step = s->bitmap_glyph->bitmap.pitch;
736     a_raster->orig_x = s->bitmap_glyph->left * 16;
737     a_raster->orig_y = s->bitmap_glyph->top * 16;
738     a_raster->left_indent = a_raster->top_indent = a_raster->black_height = a_raster->black_width = 0;
739     return 0;
740 }
741 
742 /*
743  * Create an outline for the character a_char and return its metrics. Do not
744  * return the outline but store this.
745  * It can be retrieved by a subsequent call to get_char_outline.
746  */
747 static FAPI_retcode
get_char_outline_metrics(FAPI_server * a_server,FAPI_font * a_font,FAPI_char_ref * a_char_ref,FAPI_metrics * a_metrics)748 get_char_outline_metrics(FAPI_server *a_server, FAPI_font *a_font,
749 	FAPI_char_ref *a_char_ref, FAPI_metrics *a_metrics)
750 {
751     FF_server *s = (FF_server*)a_server;
752     return load_glyph(a_font, a_char_ref, a_metrics, (FT_Glyph*)&s->outline_glyph, false);
753 }
754 
755 typedef struct FF_path_info_s
756 {
757     FAPI_path *path;
758     FracInt x;
759     FracInt y;
760 } FF_path_info;
761 
move_to(FT_Vector * aTo,void * aObject)762 static int move_to(FT_Vector *aTo, void *aObject)
763 {
764     FF_path_info *p = (FF_path_info*)aObject;
765 
766     /* FAPI expects that co-ordinates will be as implied by frac_shift
767      * in our case 16.16 fixed precision. True for 'low level' FT
768      * routines (apparently), it isn't true for these routines where
769      * FT returns a 26.6 format. Rescale to 16.16 so that FAPI will
770      * be able to convert to GS co-ordinates properly.
771      */
772     p->x = aTo->x << 10;
773     p->y = aTo->y << 10;
774 
775     return p->path->moveto(p->path, p->x, p->y) ? -1 : 0;
776 }
777 
line_to(FT_Vector * aTo,void * aObject)778 static int line_to(FT_Vector *aTo, void *aObject)
779 {
780     FF_path_info *p = (FF_path_info*)aObject;
781 
782     /* See move_to() above */
783     p->x = aTo->x << 10;
784     p->y = aTo->y << 10;
785 
786     return p->path->lineto(p->path, p->x, p->y) ? -1 : 0;
787 }
788 
conic_to(FT_Vector * aControl,FT_Vector * aTo,void * aObject)789 static int conic_to(FT_Vector *aControl, FT_Vector *aTo, void *aObject)
790 {
791     FF_path_info *p = (FF_path_info*)aObject;
792     floatp x, y, Controlx, Controly, Control1x, Control1y, Control2x, Control2y;
793 
794     /* More complivated than above, we need to do arithmetic on the
795      * co-ordinates, so we want them as floats and we will convert the
796      * result into 16.16 fixed precision for FAPI
797      *
798      * NB this code is funcitonally the same as the original, but I don't believe
799      * the comment (below) to be what the code is actually doing....
800      *
801      * Convert a quadratic spline to a cubic. Do this by changing the three points
802      * A, B and C to A, 1/3(B,A), 1/3(B,C), C - that is, the two cubic control points are
803      * a third of the way from the single quadratic control point to the end points. This
804      * gives the same curve as the original quadratic.
805      */
806 
807     x = aTo->x / 64;
808     p->x = float2fixed(x) << 8;
809     y = aTo->y / 64;
810     p->y = float2fixed(y) << 8;
811     Controlx = aControl->x / 64;
812     Controly = aControl->y / 64;
813 
814     Control1x = float2fixed((x + Controlx * 2) / 3) << 8;
815     Control1y = float2fixed((y + Controly * 2) / 3) << 8;
816     Control2x = float2fixed((x + Controlx * 2) / 3) << 8;
817     Control2y = float2fixed((y + Controly * 2) / 3) << 8;
818 
819     return p->path->curveto(p->path, Control1x,
820 	    Control1y,
821 	    Control2x,
822 	    Control2y,
823 	    p->x, p->y) ? -1 : 0;
824 }
825 
cubic_to(FT_Vector * aControl1,FT_Vector * aControl2,FT_Vector * aTo,void * aObject)826 static int cubic_to(FT_Vector *aControl1, FT_Vector *aControl2, FT_Vector *aTo, void *aObject)
827 {
828     FF_path_info *p = (FF_path_info*)aObject;
829     unsigned long Control1x, Control1y, Control2x, Control2y;
830 
831     /* See move_to() above */
832     p->x = aTo->x << 10;
833     p->y = aTo->y << 10;
834 
835     Control1x = aControl1->x << 10;
836     Control1y = aControl1->y << 10;
837     Control2x = aControl2->x << 10;
838     Control2y = aControl2->y << 10;
839     return p->path->curveto(p->path, Control1x, Control1y, Control2x, Control2y, p->x, p->y) ? -1 : 0;
840 
841     p->x = aTo->x;
842     p->y = aTo->y;
843     return p->path->curveto(p->path, aControl1->x, aControl1->y, aControl2->x, aControl2->y, aTo->x, aTo->y) ? -1 : 0;
844 }
845 
846 static const FT_Outline_Funcs TheFtOutlineFuncs =
847 {
848     move_to,
849     line_to,
850     conic_to,
851     cubic_to,
852     0,
853     0
854 };
855 
856 /*
857  * Return the outline created by the last call to get_char_outline_metrics.
858  */
859 static FAPI_retcode
get_char_outline(FAPI_server * a_server,FAPI_path * a_path)860 get_char_outline(FAPI_server *a_server, FAPI_path *a_path)
861 {
862     FF_server *s = (FF_server*)a_server;
863     FF_path_info p;
864     FT_Error ft_error = 0;
865     p.path = a_path;
866     p.x = 0;
867     p.y = 0;
868     ft_error = FT_Outline_Decompose(&s->outline_glyph->outline, &TheFtOutlineFuncs, &p);
869     a_path->closepath(a_path);
870     return ft_to_gs_error(ft_error);
871 }
872 
release_char_data(FAPI_server * a_server)873 static FAPI_retcode release_char_data(FAPI_server *a_server)
874 {
875     FF_server *s = (FF_server*)a_server;
876     FT_Done_Glyph(&s->outline_glyph->root);
877     FT_Done_Glyph(&s->bitmap_glyph->root);
878     s->outline_glyph = NULL;
879     s->bitmap_glyph = NULL;
880     return 0;
881 }
882 
883 static FAPI_retcode
release_typeface(FAPI_server * a_server,void * a_server_font_data)884 release_typeface(FAPI_server *a_server, void *a_server_font_data)
885 {
886     FF_face *face = (FF_face*)a_server_font_data;
887     delete_face(face);
888     return 0;
889 }
890 
891 static FAPI_retcode
check_cmap_for_GID(FAPI_server * server,uint * index)892 check_cmap_for_GID(FAPI_server *server, uint *index)
893 {
894     FF_server *s = (FF_server*)server;
895     FF_face *face = (FF_face*)(server->ff.server_font_data);
896     FT_Face ft_face = face->ft_face;
897 
898     *index = FT_Get_Char_Index(ft_face, *index);
899     return 0;
900 }
901 
902 static void gs_freetype_destroy(i_plugin_instance *a_instance, i_plugin_client_memory *a_memory);
903 
904 static const i_plugin_descriptor TheFreeTypeDescriptor =
905 {
906     "FAPI",
907     "FreeType",
908     gs_freetype_destroy
909 };
910 
911 static const FAPI_server TheFreeTypeServer =
912 {
913     { &TheFreeTypeDescriptor },
914     16, /* frac_shift */
915     {gs_no_id},
916     {0},
917     {1, 0, 0, 1, 0, 0},
918     ensure_open,
919     get_scaled_font,
920     get_decodingID,
921     get_font_bbox,
922     get_font_proportional_feature,
923     can_retrieve_char_by_name,
924     can_replace_metrics,
925     get_char_width,
926     get_char_raster_metrics,
927     get_char_raster,
928     get_char_outline_metrics,
929     get_char_outline,
930     release_char_data,
931     release_typeface,
932     check_cmap_for_GID
933 };
934 
935 plugin_instantiation_proc(gs_fapi_ft_instantiate);
936 
gs_fapi_ft_instantiate(i_plugin_client_memory * a_memory,i_plugin_instance ** a_plugin_instance)937 int gs_fapi_ft_instantiate( i_plugin_client_memory *a_memory, i_plugin_instance **a_plugin_instance)
938 {
939     FF_server *server = (FF_server*) a_memory->alloc(a_memory, sizeof (FF_server), "FF_server");
940     if (!server)
941 	return e_VMerror;
942     memset(server, 0, sizeof(*server));
943     server->fapi_server = TheFreeTypeServer;
944     *a_plugin_instance = &server->fapi_server.ig;
945     return 0;
946 }
947 
gs_freetype_destroy(i_plugin_instance * a_plugin_instance,i_plugin_client_memory * a_memory)948 static void gs_freetype_destroy(i_plugin_instance *a_plugin_instance, i_plugin_client_memory *a_memory)
949 {
950     FF_server *server = (FF_server *)a_plugin_instance;
951     FT_Done_Glyph(&server->outline_glyph->root);
952     FT_Done_Glyph(&server->bitmap_glyph->root);
953     FT_Done_FreeType(server->freetype_library);
954     a_memory->free(a_memory, server, "FF_server");
955 }
956