blob: 98d3f96fe881cff661d93d650697727927c76f71 [file] [log] [blame]
Werner Lemberg7fa51b52000-07-08 19:51:42 +00001/***************************************************************************/
2/* */
3/* z1gload.c */
4/* */
5/* Experimental Type 1 Glyph Loader (body). */
6/* */
7/* Copyright 1996-2000 by */
8/* 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
David Turner2dfb5ac2000-01-27 14:02:04 +000018
David Turnera90663f2000-07-08 00:41:13 +000019#ifdef FT_FLAT_COMPILE
Werner Lemberg7fa51b52000-07-08 19:51:42 +000020
David Turnera90663f2000-07-08 00:41:13 +000021#include "z1gload.h"
Werner Lemberg7fa51b52000-07-08 19:51:42 +000022
David Turnera90663f2000-07-08 00:41:13 +000023#else
Werner Lemberg7fa51b52000-07-08 19:51:42 +000024
David Turnera90663f2000-07-08 00:41:13 +000025#include <type1z/z1gload.h>
Werner Lemberg7fa51b52000-07-08 19:51:42 +000026
David Turnera90663f2000-07-08 00:41:13 +000027#endif
28
Werner Lemberg7fa51b52000-07-08 19:51:42 +000029
David Turnerefce08d2000-05-11 18:23:52 +000030#include <freetype/internal/ftdebug.h>
31#include <freetype/internal/ftstream.h>
David Turnerf9ca2bb2000-06-30 23:12:55 +000032#include <freetype/ftoutln.h>
David Turner97488072000-08-22 22:36:33 +000033#include <freetype/internal/psaux.h>
34
David Turner2dfb5ac2000-01-27 14:02:04 +000035
Werner Lemberg7fa51b52000-07-08 19:51:42 +000036#include <string.h> /* for strcmp() */
David Turner95bec282000-02-15 12:55:57 +000037
Werner Lemberg7fa51b52000-07-08 19:51:42 +000038
39 /*************************************************************************/
40 /* */
41 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
42 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
43 /* messages during execution. */
44 /* */
45#undef FT_COMPONENT
46#define FT_COMPONENT trace_z1gload
47
48
David Turner2dfb5ac2000-01-27 14:02:04 +000049
Werner Lemberg7fa51b52000-07-08 19:51:42 +000050 /*************************************************************************/
51 /*************************************************************************/
52 /*************************************************************************/
53 /********** *********/
54 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
55 /********** *********/
56 /********** The following code is in charge of computing *********/
57 /********** the maximum advance width of the font. It *********/
58 /********** quickly processes each glyph charstring to *********/
59 /********** extract the value from either a `sbw' or `seac' *********/
60 /********** operator. *********/
61 /********** *********/
62 /*************************************************************************/
63 /*************************************************************************/
64 /*************************************************************************/
David Turner2dfb5ac2000-01-27 14:02:04 +000065
David Turner2dfb5ac2000-01-27 14:02:04 +000066
David Turner97488072000-08-22 22:36:33 +000067 static
68 FT_Error Z1_Parse_Glyph( T1_Decoder* decoder,
69 FT_UInt glyph_index )
70 {
71 T1_Face face = (T1_Face)decoder->builder.face;
72 T1_Font* type1 = &face->type1;
73
David Turnera39acf52000-08-23 02:47:57 +000074 return decoder->funcs.parse_charstrings( decoder,
David Turner97488072000-08-22 22:36:33 +000075 type1->charstrings [glyph_index],
76 type1->charstrings_len[glyph_index] );
77 }
78
David Turner2dfb5ac2000-01-27 14:02:04 +000079 LOCAL_FUNC
David Turner728da1c2000-06-27 23:21:51 +000080 FT_Error Z1_Compute_Max_Advance( T1_Face face,
Werner Lemberg7fa51b52000-07-08 19:51:42 +000081 FT_Int* max_advance )
David Turner2dfb5ac2000-01-27 14:02:04 +000082 {
David Turner97488072000-08-22 22:36:33 +000083 FT_Error error;
84 T1_Decoder decoder;
85 FT_Int glyph_index;
86 T1_Font* type1 = &face->type1;
87 PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
David Turner2dfb5ac2000-01-27 14:02:04 +000088
Werner Lemberg7fa51b52000-07-08 19:51:42 +000089
David Turner2dfb5ac2000-01-27 14:02:04 +000090 *max_advance = 0;
91
Werner Lemberg7fa51b52000-07-08 19:51:42 +000092 /* Initialize load decoder */
David Turner97488072000-08-22 22:36:33 +000093 error = psaux->t1_decoder_funcs->init( &decoder,
94 (FT_Face)face,
95 0, /* size */
96 0, /* glyph slot */
97 (FT_Byte**)type1->glyph_names,
98 face->blend,
99 Z1_Parse_Glyph );
David Turner2dfb5ac2000-01-27 14:02:04 +0000100
David Turner0dd34342000-02-02 12:20:53 +0000101 decoder.builder.metrics_only = 1;
102 decoder.builder.load_points = 0;
David Turner2dfb5ac2000-01-27 14:02:04 +0000103
David Turner97488072000-08-22 22:36:33 +0000104 decoder.num_subrs = type1->num_subrs;
105 decoder.subrs = type1->subrs;
106 decoder.subrs_len = type1->subrs_len;
107
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000108 /* for each glyph, parse the glyph charstring and extract */
109 /* the advance width */
David Turner2dfb5ac2000-01-27 14:02:04 +0000110 for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
111 {
112 /* now get load the unscaled outline */
David Turner97488072000-08-22 22:36:33 +0000113 error = Z1_Parse_Glyph( &decoder, glyph_index );
David Turner2dfb5ac2000-01-27 14:02:04 +0000114 /* ignore the error if one occured - skip to next glyph */
David Turner2dfb5ac2000-01-27 14:02:04 +0000115 }
116
117 *max_advance = decoder.builder.advance.x;
118 return T1_Err_Ok;
119 }
120
121
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000122 /*************************************************************************/
123 /*************************************************************************/
124 /*************************************************************************/
125 /********** *********/
126 /********** UNHINTED GLYPH LOADER *********/
127 /********** *********/
128 /********** The following code is in charge of loading a *********/
129 /********** single outline. It completely ignores hinting *********/
130 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
131 /********** *********/
132 /********** The Type 1 hinter is located in `t1hint.c' *********/
133 /********** *********/
134 /*************************************************************************/
135 /*************************************************************************/
136 /*************************************************************************/
David Turner2dfb5ac2000-01-27 14:02:04 +0000137
138
David Turner2dfb5ac2000-01-27 14:02:04 +0000139 LOCAL_FUNC
David Turner728da1c2000-06-27 23:21:51 +0000140 FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
141 Z1_Size size,
David Turnerf9b8dec2000-06-16 19:34:52 +0000142 FT_Int glyph_index,
143 FT_Int load_flags )
David Turner2dfb5ac2000-01-27 14:02:04 +0000144 {
David Turner97488072000-08-22 22:36:33 +0000145 FT_Error error;
146 T1_Decoder decoder;
147 T1_Face face = (T1_Face)glyph->root.face;
148 FT_Bool hinting;
149 T1_Font* type1 = &face->type1;
150 PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
151 const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
David Turner2dfb5ac2000-01-27 14:02:04 +0000152
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000153
154 if ( load_flags & FT_LOAD_NO_RECURSE )
David Turnered7f62a2000-03-28 11:19:28 +0000155 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
156
David Turner2dfb5ac2000-01-27 14:02:04 +0000157 glyph->x_scale = size->root.metrics.x_scale;
158 glyph->y_scale = size->root.metrics.y_scale;
159
160 glyph->root.outline.n_points = 0;
161 glyph->root.outline.n_contours = 0;
162
163 hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
164 ( load_flags & FT_LOAD_NO_HINTING ) == 0;
165
David Turner728da1c2000-06-27 23:21:51 +0000166 glyph->root.format = ft_glyph_format_outline;
David Turner2dfb5ac2000-01-27 14:02:04 +0000167
David Turner97488072000-08-22 22:36:33 +0000168 error = decoder_funcs->init( &decoder,
169 (FT_Face)face,
170 (FT_Size)size,
171 (FT_GlyphSlot)glyph,
172 (FT_Byte**)type1->glyph_names,
173 face->blend,
174 Z1_Parse_Glyph );
175 if (error)
176 goto Exit;
177
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000178 decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
179
David Turner97488072000-08-22 22:36:33 +0000180 decoder.num_subrs = type1->num_subrs;
181 decoder.subrs = type1->subrs;
182 decoder.subrs_len = type1->subrs_len;
183
184
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000185 /* now load the unscaled outline */
David Turner97488072000-08-22 22:36:33 +0000186 error = Z1_Parse_Glyph( &decoder, glyph_index );
187 if (error)
188 goto Exit;
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000189
190 /* save new glyph tables */
David Turner97488072000-08-22 22:36:33 +0000191 decoder_funcs->done( &decoder );
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000192
193 /* now, set the metrics -- this is rather simple, as */
194 /* the left side bearing is the xMin, and the top side */
195 /* bearing the yMax */
196 if ( !error )
David Turner2dfb5ac2000-01-27 14:02:04 +0000197 {
David Turnerc49f69c2000-07-20 03:44:50 +0000198 glyph->root.outline.flags &= ft_outline_owner;
199 glyph->root.outline.flags |= ft_outline_reverse_fill;
200
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000201 /* for composite glyphs, return only left side bearing and */
202 /* advance width */
David Turnered7f62a2000-03-28 11:19:28 +0000203 if ( load_flags & FT_LOAD_NO_RECURSE )
David Turner2dfb5ac2000-01-27 14:02:04 +0000204 {
David Turnered7f62a2000-03-28 11:19:28 +0000205 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
206 glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
David Turner2dfb5ac2000-01-27 14:02:04 +0000207 }
David Turnered7f62a2000-03-28 11:19:28 +0000208 else
David Turner2dfb5ac2000-01-27 14:02:04 +0000209 {
David Turnered7f62a2000-03-28 11:19:28 +0000210 FT_BBox cbox;
211 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
David Turnere49ab252000-05-16 23:44:38 +0000212
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000213
David Turnered7f62a2000-03-28 11:19:28 +0000214 /* copy the _unscaled_ advance width */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000215 metrics->horiAdvance = decoder.builder.advance.x;
David Turnere49ab252000-05-16 23:44:38 +0000216
David Turnered7f62a2000-03-28 11:19:28 +0000217 /* make up vertical metrics */
218 metrics->vertBearingX = 0;
219 metrics->vertBearingY = 0;
220 metrics->vertAdvance = 0;
David Turnere49ab252000-05-16 23:44:38 +0000221
David Turnered7f62a2000-03-28 11:19:28 +0000222 glyph->root.format = ft_glyph_format_outline;
David Turnere49ab252000-05-16 23:44:38 +0000223
David Turnerd8723b42000-04-14 11:29:14 +0000224 if ( size && size->root.metrics.y_ppem < 24 )
David Turnered7f62a2000-03-28 11:19:28 +0000225 glyph->root.outline.flags |= ft_outline_high_precision;
David Turner82942cc2000-03-30 08:43:03 +0000226
David Turner24d70242000-08-17 01:09:06 +0000227 /* apply the font matrix */
228 FT_Outline_Transform( &glyph->root.outline,
229 &face->type1.font_matrix );
230
231 FT_Outline_Translate( &glyph->root.outline,
232 face->type1.font_offset.x,
233 face->type1.font_offset.y );
234
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000235#if 0
David Turnered7f62a2000-03-28 11:19:28 +0000236 glyph->root.outline.second_pass = TRUE;
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000237 glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
David Turnered7f62a2000-03-28 11:19:28 +0000238 glyph->root.outline.dropout_mode = 2;
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000239#endif /* 0 */
David Turnere49ab252000-05-16 23:44:38 +0000240
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000241 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
David Turnered7f62a2000-03-28 11:19:28 +0000242 {
243 /* scale the outline and the metrics */
David Turnerf9b8dec2000-06-16 19:34:52 +0000244 FT_Int n;
David Turnerf0df85b2000-06-22 00:17:42 +0000245 FT_Outline* cur = decoder.builder.base;
David Turnerf9b8dec2000-06-16 19:34:52 +0000246 FT_Vector* vec = cur->points;
247 FT_Fixed x_scale = glyph->x_scale;
248 FT_Fixed y_scale = glyph->y_scale;
David Turnere49ab252000-05-16 23:44:38 +0000249
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000250
David Turnered7f62a2000-03-28 11:19:28 +0000251 /* First of all, scale the points */
252 for ( n = cur->n_points; n > 0; n--, vec++ )
253 {
254 vec->x = FT_MulFix( vec->x, x_scale );
255 vec->y = FT_MulFix( vec->y, y_scale );
256 }
David Turnerd8723b42000-04-14 11:29:14 +0000257
258 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
David Turnere49ab252000-05-16 23:44:38 +0000259
David Turnered7f62a2000-03-28 11:19:28 +0000260 /* Then scale the metrics */
David Turnered7f62a2000-03-28 11:19:28 +0000261 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
Werner Lembergac39ecd2000-06-30 22:24:36 +0000262 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
David Turnere49ab252000-05-16 23:44:38 +0000263
David Turnered7f62a2000-03-28 11:19:28 +0000264 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
265 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
David Turnered7f62a2000-03-28 11:19:28 +0000266 }
David Turnerd8723b42000-04-14 11:29:14 +0000267
268 /* compute the other metrics */
269 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
David Turnere49ab252000-05-16 23:44:38 +0000270
David Turnerd8723b42000-04-14 11:29:14 +0000271 /* grid fit the bounding box if necessary */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000272 if ( hinting )
David Turnerd8723b42000-04-14 11:29:14 +0000273 {
274 cbox.xMin &= -64;
275 cbox.yMin &= -64;
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000276 cbox.xMax = ( cbox.xMax+63 ) & -64;
277 cbox.yMax = ( cbox.yMax+63 ) & -64;
David Turnerd8723b42000-04-14 11:29:14 +0000278 }
279
280 metrics->width = cbox.xMax - cbox.xMin;
281 metrics->height = cbox.yMax - cbox.yMin;
282
283 metrics->horiBearingX = cbox.xMin;
284 metrics->horiBearingY = cbox.yMax;
David Turner2dfb5ac2000-01-27 14:02:04 +0000285 }
286 }
David Turner97488072000-08-22 22:36:33 +0000287 Exit:
David Turner2dfb5ac2000-01-27 14:02:04 +0000288 return error;
289 }
290
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000291
292/* END */