blob: c8d1db79f453fa3dbd76b5900ede57962a19d307 [file] [log] [blame]
Werner Lemberg7fa51b52000-07-08 19:51:42 +00001/***************************************************************************/
2/* */
Werner Lembergb5084e12000-10-28 17:10:06 +00003/* t1gload.c */
Werner Lemberg7fa51b52000-07-08 19:51:42 +00004/* */
Werner Lembergb5084e12000-10-28 17:10:06 +00005/* Type 1 Glyph Loader (body). */
Werner Lemberg7fa51b52000-07-08 19:51:42 +00006/* */
Werner Lembergb442ca12003-04-23 15:50:27 +00007/* Copyright 1996-2001, 2002, 2003 by */
Werner Lemberg7fa51b52000-07-08 19:51:42 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
Werner Lembergcc069be2000-12-08 16:17:16 +000018
David Turner19ed8af2000-12-08 02:42:29 +000019#include <ft2build.h>
David Turner8d3a4012001-03-20 11:14:24 +000020#include "t1gload.h"
David Turner19ed8af2000-12-08 02:42:29 +000021#include FT_INTERNAL_DEBUG_H
22#include FT_INTERNAL_STREAM_H
23#include FT_OUTLINE_H
24#include FT_INTERNAL_POSTSCRIPT_AUX_H
Werner Lembergcc069be2000-12-08 16:17:16 +000025
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000026#include "t1errors.h"
27
Werner Lemberg7fa51b52000-07-08 19:51:42 +000028
29 /*************************************************************************/
30 /* */
31 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
32 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
33 /* messages during execution. */
34 /* */
35#undef FT_COMPONENT
Werner Lembergb5084e12000-10-28 17:10:06 +000036#define FT_COMPONENT trace_t1gload
Werner Lemberg7fa51b52000-07-08 19:51:42 +000037
38
Werner Lemberg7fa51b52000-07-08 19:51:42 +000039 /*************************************************************************/
40 /*************************************************************************/
41 /*************************************************************************/
42 /********** *********/
43 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
44 /********** *********/
45 /********** The following code is in charge of computing *********/
46 /********** the maximum advance width of the font. It *********/
47 /********** quickly processes each glyph charstring to *********/
48 /********** extract the value from either a `sbw' or `seac' *********/
49 /********** operator. *********/
50 /********** *********/
51 /*************************************************************************/
52 /*************************************************************************/
53 /*************************************************************************/
David Turner2dfb5ac2000-01-27 14:02:04 +000054
David Turner2dfb5ac2000-01-27 14:02:04 +000055
Werner Lemberg7f74a522002-07-26 09:09:10 +000056 FT_LOCAL_DEF( FT_Error )
57 T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder,
58 FT_UInt glyph_index,
59 FT_Data* char_string )
David Turner97488072000-08-22 22:36:33 +000060 {
Werner Lemberg7f74a522002-07-26 09:09:10 +000061 T1_Face face = (T1_Face)decoder->builder.face;
62 T1_Font type1 = &face->type1;
63 FT_Error error = 0;
64
David Turner34f1c2f2000-08-23 22:47:44 +000065
66 decoder->font_matrix = type1->font_matrix;
67 decoder->font_offset = type1->font_offset;
Werner Lemberg8728f292000-08-23 17:32:42 +000068
Graham Asherbd8b0852002-07-18 16:57:43 +000069#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg7f74a522002-07-26 09:09:10 +000070
71 /* For incremental fonts get the character data using the */
72 /* callback function. */
Graham Asherce121822002-08-01 15:29:17 +000073 if ( face->root.internal->incremental_interface )
74 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
75 face->root.internal->incremental_interface->object,
Werner Lemberg7f74a522002-07-26 09:09:10 +000076 glyph_index, char_string );
Graham Asherbd8b0852002-07-18 16:57:43 +000077 else
Werner Lemberg7f74a522002-07-26 09:09:10 +000078
Graham Asher46960df2003-02-13 17:49:27 +000079#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Graham Asherbd8b0852002-07-18 16:57:43 +000080
81 /* For ordinary fonts get the character data stored in the face record. */
82 {
83 char_string->pointer = type1->charstrings[glyph_index];
Werner Lembergfb4bfdd2003-12-13 18:42:31 +000084 char_string->length = (FT_Int)type1->charstrings_len[glyph_index];
Graham Asherbd8b0852002-07-18 16:57:43 +000085 }
86
Werner Lemberg7f74a522002-07-26 09:09:10 +000087 if ( !error )
88 error = decoder->funcs.parse_charstrings(
89 decoder, (FT_Byte*)char_string->pointer,
90 char_string->length );
Graham Asherbd8b0852002-07-18 16:57:43 +000091
92#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg7f74a522002-07-26 09:09:10 +000093
Graham Asherbd8b0852002-07-18 16:57:43 +000094 /* Incremental fonts can optionally override the metrics. */
Graham Asherce121822002-08-01 15:29:17 +000095 if ( !error && face->root.internal->incremental_interface &&
96 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
Graham Asherbd8b0852002-07-18 16:57:43 +000097 {
Graham Asherce121822002-08-01 15:29:17 +000098 FT_Incremental_MetricsRec metrics;
Werner Lemberg7f74a522002-07-26 09:09:10 +000099
Werner Lembergfb4bfdd2003-12-13 18:42:31 +0000100
Graham Asher46960df2003-02-13 17:49:27 +0000101 metrics.bearing_x = decoder->builder.left_bearing.x;
Werner Lembergb442ca12003-04-23 15:50:27 +0000102 metrics.bearing_y = decoder->builder.left_bearing.y;
103 metrics.advance = decoder->builder.advance.x;
Graham Asherce121822002-08-01 15:29:17 +0000104 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
105 face->root.internal->incremental_interface->object,
Graham Asher46960df2003-02-13 17:49:27 +0000106 glyph_index, FALSE, &metrics );
107 decoder->builder.left_bearing.x = metrics.bearing_x;
108 decoder->builder.left_bearing.y = metrics.bearing_y;
109 decoder->builder.advance.x = metrics.advance;
110 decoder->builder.advance.y = 0;
Graham Asherbd8b0852002-07-18 16:57:43 +0000111 }
Werner Lemberg7f74a522002-07-26 09:09:10 +0000112
Graham Asher46960df2003-02-13 17:49:27 +0000113#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Graham Asherbd8b0852002-07-18 16:57:43 +0000114
Werner Lembergfb4bfdd2003-12-13 18:42:31 +0000115 return error;
Graham Asherbd8b0852002-07-18 16:57:43 +0000116 }
117
118
119 FT_CALLBACK_DEF( FT_Error )
120 T1_Parse_Glyph( T1_Decoder decoder,
121 FT_UInt glyph_index )
122 {
Werner Lemberg3c403e42002-08-06 21:47:40 +0000123 FT_Data glyph_data;
David Turner87c0d302003-12-24 01:10:46 +0000124 FT_Error error = T1_Parse_Glyph_And_Get_Char_String(
Werner Lemberg3c403e42002-08-06 21:47:40 +0000125 decoder, glyph_index, &glyph_data );
126
Graham Asherce121822002-08-01 15:29:17 +0000127
128#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lembergfb4bfdd2003-12-13 18:42:31 +0000129
Werner Lemberg3c403e42002-08-06 21:47:40 +0000130 if ( !error )
Graham Asherce121822002-08-01 15:29:17 +0000131 {
Werner Lemberg3c403e42002-08-06 21:47:40 +0000132 T1_Face face = (T1_Face)decoder->builder.face;
Werner Lemberg7f74a522002-07-26 09:09:10 +0000133
134
Werner Lembergb442ca12003-04-23 15:50:27 +0000135 if ( face->root.internal->incremental_interface )
Werner Lemberg3c403e42002-08-06 21:47:40 +0000136 face->root.internal->incremental_interface->funcs->free_glyph_data(
137 face->root.internal->incremental_interface->object,
138 &glyph_data );
Graham Asherce121822002-08-01 15:29:17 +0000139 }
Werner Lembergfb4bfdd2003-12-13 18:42:31 +0000140
Graham Asher46960df2003-02-13 17:49:27 +0000141#endif /* FT_CONFIG_OPTION_INCREMENTAL */
Graham Asherce121822002-08-01 15:29:17 +0000142
143 return error;
David Turner97488072000-08-22 22:36:33 +0000144 }
145
Werner Lemberg8728f292000-08-23 17:32:42 +0000146
David Turnerbc82f1b2002-03-01 02:26:22 +0000147 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000148 T1_Compute_Max_Advance( T1_Face face,
Werner Lemberg73861972003-06-05 04:31:05 +0000149 FT_Pos* max_advance )
David Turner2dfb5ac2000-01-27 14:02:04 +0000150 {
Werner Lembergefa99612002-04-01 22:01:46 +0000151 FT_Error error;
152 T1_DecoderRec decoder;
153 FT_Int glyph_index;
154 T1_Font type1 = &face->type1;
David Turner4e7eeee2002-02-28 16:10:29 +0000155 PSAux_Service psaux = (PSAux_Service)face->psaux;
David Turner2dfb5ac2000-01-27 14:02:04 +0000156
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000157
David Turner2dfb5ac2000-01-27 14:02:04 +0000158 *max_advance = 0;
159
Werner Lemberg8728f292000-08-23 17:32:42 +0000160 /* initialize load decoder */
David Turner97488072000-08-22 22:36:33 +0000161 error = psaux->t1_decoder_funcs->init( &decoder,
162 (FT_Face)face,
163 0, /* size */
164 0, /* glyph slot */
165 (FT_Byte**)type1->glyph_names,
166 face->blend,
David Turner5893c1b2001-10-18 11:49:26 +0000167 0,
Werner Lemberg6b5c6692002-09-05 15:10:54 +0000168 FT_RENDER_MODE_NORMAL,
Werner Lembergb5084e12000-10-28 17:10:06 +0000169 T1_Parse_Glyph );
Werner Lembergd1b74752000-08-24 16:29:15 +0000170 if ( error )
David Turner34f1c2f2000-08-23 22:47:44 +0000171 return error;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000172
David Turner0dd34342000-02-02 12:20:53 +0000173 decoder.builder.metrics_only = 1;
174 decoder.builder.load_points = 0;
David Turner2dfb5ac2000-01-27 14:02:04 +0000175
David Turner97488072000-08-22 22:36:33 +0000176 decoder.num_subrs = type1->num_subrs;
177 decoder.subrs = type1->subrs;
178 decoder.subrs_len = type1->subrs_len;
179
David Turner11cfdd02002-04-17 09:37:59 +0000180 *max_advance = 0;
181
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000182 /* for each glyph, parse the glyph charstring and extract */
183 /* the advance width */
David Turner2dfb5ac2000-01-27 14:02:04 +0000184 for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
185 {
186 /* now get load the unscaled outline */
Werner Lembergb5084e12000-10-28 17:10:06 +0000187 error = T1_Parse_Glyph( &decoder, glyph_index );
David Turner11cfdd02002-04-17 09:37:59 +0000188 if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance )
189 *max_advance = decoder.builder.advance.x;
David Turner87c0d302003-12-24 01:10:46 +0000190
Werner Lemberg73861972003-06-05 04:31:05 +0000191 /* ignore the error if one occurred - skip to next glyph */
David Turner2dfb5ac2000-01-27 14:02:04 +0000192 }
193
Werner Lemberg1429db62001-04-02 23:54:01 +0000194 return T1_Err_Ok;
David Turner2dfb5ac2000-01-27 14:02:04 +0000195 }
196
197
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000198 /*************************************************************************/
199 /*************************************************************************/
200 /*************************************************************************/
201 /********** *********/
202 /********** UNHINTED GLYPH LOADER *********/
203 /********** *********/
204 /********** The following code is in charge of loading a *********/
205 /********** single outline. It completely ignores hinting *********/
206 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
207 /********** *********/
208 /********** The Type 1 hinter is located in `t1hint.c' *********/
209 /********** *********/
210 /*************************************************************************/
211 /*************************************************************************/
212 /*************************************************************************/
David Turner2dfb5ac2000-01-27 14:02:04 +0000213
214
David Turnerbc82f1b2002-03-01 02:26:22 +0000215 FT_LOCAL_DEF( FT_Error )
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000216 T1_Load_Glyph( T1_GlyphSlot glyph,
217 T1_Size size,
David Turner609e28c2002-04-19 15:13:47 +0000218 FT_UInt glyph_index,
David Turnerd1245c02002-08-27 22:34:20 +0000219 FT_Int32 load_flags )
David Turner2dfb5ac2000-01-27 14:02:04 +0000220 {
David Turner97488072000-08-22 22:36:33 +0000221 FT_Error error;
David Turner4e7eeee2002-02-28 16:10:29 +0000222 T1_DecoderRec decoder;
David Turner97488072000-08-22 22:36:33 +0000223 T1_Face face = (T1_Face)glyph->root.face;
224 FT_Bool hinting;
Werner Lembergefa99612002-04-01 22:01:46 +0000225 T1_Font type1 = &face->type1;
David Turner4e7eeee2002-02-28 16:10:29 +0000226 PSAux_Service psaux = (PSAux_Service)face->psaux;
227 const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;
David Turner2dfb5ac2000-01-27 14:02:04 +0000228
David Turner34f1c2f2000-08-23 22:47:44 +0000229 FT_Matrix font_matrix;
230 FT_Vector font_offset;
Graham Asherce121822002-08-01 15:29:17 +0000231 FT_Data glyph_data;
Werner Lemberg319c00d2003-04-23 19:48:24 +0000232#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +0000233 FT_Bool glyph_data_loaded = 0;
Werner Lemberg319c00d2003-04-23 19:48:24 +0000234#endif
Werner Lemberg3c403e42002-08-06 21:47:40 +0000235
Werner Lembergefa99612002-04-01 22:01:46 +0000236
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000237 if ( load_flags & FT_LOAD_NO_RECURSE )
David Turnered7f62a2000-03-28 11:19:28 +0000238 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
239
David Turner2dfb5ac2000-01-27 14:02:04 +0000240 glyph->x_scale = size->root.metrics.x_scale;
241 glyph->y_scale = size->root.metrics.y_scale;
242
243 glyph->root.outline.n_points = 0;
244 glyph->root.outline.n_contours = 0;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000245
David Turner8edbcab2001-06-19 08:28:24 +0000246 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
247 ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
David Turner2dfb5ac2000-01-27 14:02:04 +0000248
David Turnerb08fe2d2002-08-27 20:20:29 +0000249 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
David Turner2dfb5ac2000-01-27 14:02:04 +0000250
David Turner97488072000-08-22 22:36:33 +0000251 error = decoder_funcs->init( &decoder,
252 (FT_Face)face,
253 (FT_Size)size,
254 (FT_GlyphSlot)glyph,
255 (FT_Byte**)type1->glyph_names,
256 face->blend,
Werner Lembergc3b21602001-12-05 01:22:05 +0000257 FT_BOOL( hinting ),
David Turnerd1245c02002-08-27 22:34:20 +0000258 FT_LOAD_TARGET_MODE(load_flags),
Werner Lembergb5084e12000-10-28 17:10:06 +0000259 T1_Parse_Glyph );
Werner Lemberg8728f292000-08-23 17:32:42 +0000260 if ( error )
David Turner97488072000-08-22 22:36:33 +0000261 goto Exit;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000262
Werner Lemberg8eb03532001-06-19 23:03:41 +0000263 decoder.builder.no_recurse = FT_BOOL(
264 ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000265
David Turner97488072000-08-22 22:36:33 +0000266 decoder.num_subrs = type1->num_subrs;
267 decoder.subrs = type1->subrs;
268 decoder.subrs_len = type1->subrs_len;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000269
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000270 /* now load the unscaled outline */
Werner Lemberg7f74a522002-07-26 09:09:10 +0000271 error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index,
Graham Asherce121822002-08-01 15:29:17 +0000272 &glyph_data );
Werner Lemberg8728f292000-08-23 17:32:42 +0000273 if ( error )
David Turner97488072000-08-22 22:36:33 +0000274 goto Exit;
Werner Lemberg319c00d2003-04-23 19:48:24 +0000275#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg3c403e42002-08-06 21:47:40 +0000276 glyph_data_loaded = 1;
Werner Lemberg319c00d2003-04-23 19:48:24 +0000277#endif
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000278
David Turner34f1c2f2000-08-23 22:47:44 +0000279 font_matrix = decoder.font_matrix;
280 font_offset = decoder.font_offset;
281
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000282 /* save new glyph tables */
David Turner97488072000-08-22 22:36:33 +0000283 decoder_funcs->done( &decoder );
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000284
285 /* now, set the metrics -- this is rather simple, as */
286 /* the left side bearing is the xMin, and the top side */
287 /* bearing the yMax */
288 if ( !error )
David Turner2dfb5ac2000-01-27 14:02:04 +0000289 {
David Turnerb08fe2d2002-08-27 20:20:29 +0000290 glyph->root.outline.flags &= FT_OUTLINE_OWNER;
291 glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000292
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000293 /* for composite glyphs, return only left side bearing and */
294 /* advance width */
David Turnered7f62a2000-03-28 11:19:28 +0000295 if ( load_flags & FT_LOAD_NO_RECURSE )
David Turner2dfb5ac2000-01-27 14:02:04 +0000296 {
David Turner54e75742000-11-04 02:52:02 +0000297 FT_Slot_Internal internal = glyph->root.internal;
Werner Lemberg415235d2001-06-28 17:49:10 +0000298
299
David Turnered7f62a2000-03-28 11:19:28 +0000300 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
301 glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
Werner Lembergdc72aff2000-11-04 08:33:38 +0000302 internal->glyph_matrix = font_matrix;
303 internal->glyph_delta = font_offset;
304 internal->glyph_transformed = 1;
David Turner2dfb5ac2000-01-27 14:02:04 +0000305 }
David Turnered7f62a2000-03-28 11:19:28 +0000306 else
David Turner2dfb5ac2000-01-27 14:02:04 +0000307 {
Werner Lemberg8728f292000-08-23 17:32:42 +0000308 FT_BBox cbox;
309 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
Werner Lemberge8ff7692003-08-06 04:40:48 +0000310 FT_Vector advance;
David Turnere49ab252000-05-16 23:44:38 +0000311
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000312
David Turnered7f62a2000-03-28 11:19:28 +0000313 /* copy the _unscaled_ advance width */
Werner Lembergdc72aff2000-11-04 08:33:38 +0000314 metrics->horiAdvance = decoder.builder.advance.x;
315 glyph->root.linearHoriAdvance = decoder.builder.advance.x;
David Turner54e75742000-11-04 02:52:02 +0000316 glyph->root.internal->glyph_transformed = 0;
David Turnere49ab252000-05-16 23:44:38 +0000317
David Turnered7f62a2000-03-28 11:19:28 +0000318 /* make up vertical metrics */
319 metrics->vertBearingX = 0;
320 metrics->vertBearingY = 0;
321 metrics->vertAdvance = 0;
David Turnere49ab252000-05-16 23:44:38 +0000322
David Turnerb8817172000-09-15 17:17:17 +0000323 glyph->root.linearVertAdvance = 0;
324
David Turnerb08fe2d2002-08-27 20:20:29 +0000325 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
David Turnere49ab252000-05-16 23:44:38 +0000326
David Turnerd8723b42000-04-14 11:29:14 +0000327 if ( size && size->root.metrics.y_ppem < 24 )
David Turnerb08fe2d2002-08-27 20:20:29 +0000328 glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
David Turner82942cc2000-03-30 08:43:03 +0000329
David Turner85eb6692001-12-20 09:36:21 +0000330#if 1
Werner Lembergc3b21602001-12-05 01:22:05 +0000331 /* apply the font matrix, if any */
David Turner34f1c2f2000-08-23 22:47:44 +0000332 FT_Outline_Transform( &glyph->root.outline, &font_matrix );
David Turner24d70242000-08-17 01:09:06 +0000333
334 FT_Outline_Translate( &glyph->root.outline,
David Turner34f1c2f2000-08-23 22:47:44 +0000335 font_offset.x,
336 font_offset.y );
Werner Lemberge8ff7692003-08-06 04:40:48 +0000337
338 advance.x = metrics->horiAdvance;
Werner Lemberge52c4ba2003-08-06 17:27:14 +0000339 advance.y = 0;
340 FT_Vector_Transform( &advance, &font_matrix );
341 metrics->horiAdvance = advance.x + font_offset.x;
342 advance.x = 0;
Werner Lemberge8ff7692003-08-06 04:40:48 +0000343 advance.y = metrics->vertAdvance;
344 FT_Vector_Transform( &advance, &font_matrix );
Werner Lemberge52c4ba2003-08-06 17:27:14 +0000345 metrics->vertAdvance = advance.y + font_offset.y;
David Turner5893c1b2001-10-18 11:49:26 +0000346#endif
David Turnere49ab252000-05-16 23:44:38 +0000347
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000348 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnered7f62a2000-03-28 11:19:28 +0000349 {
350 /* scale the outline and the metrics */
David Turnerf9b8dec2000-06-16 19:34:52 +0000351 FT_Int n;
David Turnerf0df85b2000-06-22 00:17:42 +0000352 FT_Outline* cur = decoder.builder.base;
David Turnerf9b8dec2000-06-16 19:34:52 +0000353 FT_Vector* vec = cur->points;
354 FT_Fixed x_scale = glyph->x_scale;
355 FT_Fixed y_scale = glyph->y_scale;
David Turnere49ab252000-05-16 23:44:38 +0000356
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000357
Werner Lembergc3b21602001-12-05 01:22:05 +0000358 /* First of all, scale the points, if we are not hinting */
David Turner5893c1b2001-10-18 11:49:26 +0000359 if ( !hinting )
360 for ( n = cur->n_points; n > 0; n--, vec++ )
361 {
362 vec->x = FT_MulFix( vec->x, x_scale );
363 vec->y = FT_MulFix( vec->y, y_scale );
364 }
David Turnerd8723b42000-04-14 11:29:14 +0000365
366 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
David Turnere49ab252000-05-16 23:44:38 +0000367
David Turnered7f62a2000-03-28 11:19:28 +0000368 /* Then scale the metrics */
David Turnered7f62a2000-03-28 11:19:28 +0000369 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
Werner Lembergac39ecd2000-06-30 22:24:36 +0000370 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
David Turnere49ab252000-05-16 23:44:38 +0000371
David Turnered7f62a2000-03-28 11:19:28 +0000372 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
373 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
David Turnerbce29862001-12-14 14:52:58 +0000374
375 if ( hinting )
376 {
David Turner87c0d302003-12-24 01:10:46 +0000377 metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
378 metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
David Turnerbce29862001-12-14 14:52:58 +0000379
David Turner87c0d302003-12-24 01:10:46 +0000380 metrics->vertBearingX = FT_PIX_ROUND( metrics->vertBearingX );
381 metrics->vertBearingY = FT_PIX_ROUND( metrics->vertBearingY );
David Turnerbce29862001-12-14 14:52:58 +0000382 }
David Turnered7f62a2000-03-28 11:19:28 +0000383 }
David Turnerd8723b42000-04-14 11:29:14 +0000384
385 /* compute the other metrics */
386 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
David Turnere49ab252000-05-16 23:44:38 +0000387
David Turnerd8723b42000-04-14 11:29:14 +0000388 /* grid fit the bounding box if necessary */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000389 if ( hinting )
David Turnerd8723b42000-04-14 11:29:14 +0000390 {
David Turner87c0d302003-12-24 01:10:46 +0000391 cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
392 cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
393 cbox.xMax = FT_PIX_CEIL( cbox.xMax );
394 cbox.yMax = FT_PIX_CEIL( cbox.yMax );
David Turnerd8723b42000-04-14 11:29:14 +0000395 }
396
397 metrics->width = cbox.xMax - cbox.xMin;
398 metrics->height = cbox.yMax - cbox.yMin;
399
400 metrics->horiBearingX = cbox.xMin;
401 metrics->horiBearingY = cbox.yMax;
David Turner2dfb5ac2000-01-27 14:02:04 +0000402 }
Werner Lemberg415235d2001-06-28 17:49:10 +0000403
Werner Lemberge274cfd2001-03-04 21:53:08 +0000404 /* Set control data to the glyph charstrings. Note that this is */
405 /* _not_ zero-terminated. */
Graham Asherce121822002-08-01 15:29:17 +0000406 glyph->root.control_data = (FT_Byte*)glyph_data.pointer;
407 glyph->root.control_len = glyph_data.length;
David Turner2dfb5ac2000-01-27 14:02:04 +0000408 }
Werner Lemberg8728f292000-08-23 17:32:42 +0000409
Graham Asherce121822002-08-01 15:29:17 +0000410
David Turner97488072000-08-22 22:36:33 +0000411 Exit:
Graham Asherce121822002-08-01 15:29:17 +0000412
413#ifdef FT_CONFIG_OPTION_INCREMENTAL
414 if ( glyph_data_loaded && face->root.internal->incremental_interface )
415 {
416 face->root.internal->incremental_interface->funcs->free_glyph_data(
Werner Lemberg3c403e42002-08-06 21:47:40 +0000417 face->root.internal->incremental_interface->object,
418 &glyph_data );
Graham Asherce121822002-08-01 15:29:17 +0000419
420 /* Set the control data to null - it is no longer available if */
Werner Lemberg3c403e42002-08-06 21:47:40 +0000421 /* loaded incrementally. */
Graham Asherce121822002-08-01 15:29:17 +0000422 glyph->root.control_data = 0;
423 glyph->root.control_len = 0;
424 }
425#endif
426
David Turner2dfb5ac2000-01-27 14:02:04 +0000427 return error;
428 }
429
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000430
431/* END */