David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1 | /***************************************************************************/ |
| 2 | /* */ |
| 3 | /* ttgload.c */ |
| 4 | /* */ |
| 5 | /* TrueType Glyph Loader (body). */ |
| 6 | /* */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 7 | /* Copyright 1996-2000 by */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 8 | /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
| 9 | /* */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 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 */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 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 Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 18 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 19 | #include <ft2build.h> |
| 20 | #include FT_INTERNAL_DEBUG_H |
| 21 | #include FT_INTERNAL_CALC_H |
| 22 | #include FT_INTERNAL_STREAM_H |
| 23 | #include FT_INTERNAL_SFNT_H |
| 24 | #include FT_TRUETYPE_TAGS_H |
| 25 | #include FT_OUTLINE_H |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 26 | |
David Turner | 8d3a401 | 2001-03-20 11:14:24 +0000 | [diff] [blame] | 27 | #include "ttgload.h" |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 28 | |
David Turner | a90663f | 2000-07-08 00:41:13 +0000 | [diff] [blame] | 29 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 30 | /*************************************************************************/ |
| 31 | /* */ |
| 32 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
| 33 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
| 34 | /* messages during execution. */ |
| 35 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 36 | #undef FT_COMPONENT |
| 37 | #define FT_COMPONENT trace_ttgload |
| 38 | |
| 39 | |
| 40 | /*************************************************************************/ |
| 41 | /* */ |
| 42 | /* Composite font flags. */ |
| 43 | /* */ |
| 44 | #define ARGS_ARE_WORDS 0x001 |
| 45 | #define ARGS_ARE_XY_VALUES 0x002 |
| 46 | #define ROUND_XY_TO_GRID 0x004 |
| 47 | #define WE_HAVE_A_SCALE 0x008 |
| 48 | /* reserved 0x010 */ |
| 49 | #define MORE_COMPONENTS 0x020 |
| 50 | #define WE_HAVE_AN_XY_SCALE 0x040 |
| 51 | #define WE_HAVE_A_2X2 0x080 |
| 52 | #define WE_HAVE_INSTR 0x100 |
| 53 | #define USE_MY_METRICS 0x200 |
| 54 | |
| 55 | |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 56 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 57 | /*************************************************************************/ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 58 | /* */ |
| 59 | /* <Function> */ |
| 60 | /* TT_Get_Metrics */ |
| 61 | /* */ |
| 62 | /* <Description> */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 63 | /* Returns the horizontal or vertical metrics in font units for a */ |
| 64 | /* given glyph. The metrics are the left side bearing (resp. top */ |
| 65 | /* side bearing) and advance width (resp. advance height). */ |
| 66 | /* */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 67 | /* <Input> */ |
| 68 | /* header :: A pointer to either the horizontal or vertical metrics */ |
| 69 | /* structure. */ |
| 70 | /* */ |
| 71 | /* index :: The glyph index. */ |
| 72 | /* */ |
| 73 | /* <Output> */ |
| 74 | /* bearing :: The bearing, either left side or top side. */ |
| 75 | /* */ |
| 76 | /* advance :: The advance width resp. advance height. */ |
| 77 | /* */ |
| 78 | /* <Note> */ |
| 79 | /* This function will much probably move to another component in the */ |
| 80 | /* near future, but I haven't decided which yet. */ |
| 81 | /* */ |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 82 | FT_LOCAL_DEF |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 83 | void TT_Get_Metrics( TT_HoriHeader* header, |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 84 | FT_UInt index, |
| 85 | FT_Short* bearing, |
| 86 | FT_UShort* advance ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 87 | { |
| 88 | TT_LongMetrics* longs_m; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 89 | FT_UShort k = header->number_Of_HMetrics; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 90 | |
| 91 | |
David Turner | b1aabf4 | 2000-11-30 23:48:22 +0000 | [diff] [blame] | 92 | if ( index < (FT_UInt)k ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 93 | { |
| 94 | longs_m = (TT_LongMetrics*)header->long_metrics + index; |
| 95 | *bearing = longs_m->bearing; |
| 96 | *advance = longs_m->advance; |
| 97 | } |
| 98 | else |
| 99 | { |
| 100 | *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k]; |
| 101 | *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance; |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | |
| 106 | /*************************************************************************/ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 107 | /* */ |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 108 | /* Returns the horizontal metrics in font units for a given glyph. If */ |
| 109 | /* `check' is true, take care of monospaced fonts by returning the */ |
| 110 | /* advance width maximum. */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 111 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 112 | static |
| 113 | void Get_HMetrics( TT_Face face, |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 114 | FT_UInt index, |
| 115 | FT_Bool check, |
| 116 | FT_Short* lsb, |
| 117 | FT_UShort* aw ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 118 | { |
| 119 | TT_Get_Metrics( &face->horizontal, index, lsb, aw ); |
| 120 | |
| 121 | if ( check && face->postscript.isFixedPitch ) |
| 122 | *aw = face->horizontal.advance_Width_Max; |
| 123 | } |
| 124 | |
| 125 | |
| 126 | /*************************************************************************/ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 127 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 128 | /* Returns the advance width table for a given pixel size if it is */ |
| 129 | /* found in the font's `hdmx' table (if any). */ |
| 130 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 131 | static |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 132 | FT_Byte* Get_Advance_Widths( TT_Face face, |
| 133 | FT_UShort ppem ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 134 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 135 | FT_UShort n; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 136 | |
| 137 | for ( n = 0; n < face->hdmx.num_records; n++ ) |
| 138 | if ( face->hdmx.records[n].ppem == ppem ) |
| 139 | return face->hdmx.records[n].widths; |
| 140 | |
| 141 | return NULL; |
| 142 | } |
| 143 | |
| 144 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 145 | #define cur_to_org( n, zone ) \ |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 146 | MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 147 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 148 | #define org_to_cur( n, zone ) \ |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 149 | MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 150 | |
| 151 | |
| 152 | /*************************************************************************/ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 153 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 154 | /* Translates an array of coordinates. */ |
| 155 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 156 | static |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 157 | void translate_array( FT_UInt n, |
| 158 | FT_Vector* coords, |
| 159 | FT_Pos delta_x, |
| 160 | FT_Pos delta_y ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 161 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 162 | FT_UInt k; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 163 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 164 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 165 | if ( delta_x ) |
| 166 | for ( k = 0; k < n; k++ ) |
| 167 | coords[k].x += delta_x; |
| 168 | |
| 169 | if ( delta_y ) |
| 170 | for ( k = 0; k < n; k++ ) |
| 171 | coords[k].y += delta_y; |
| 172 | } |
| 173 | |
| 174 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 175 | static |
| 176 | void tt_prepare_zone( TT_GlyphZone* zone, |
| 177 | FT_GlyphLoad* load, |
| 178 | FT_UInt start_point, |
| 179 | FT_UInt start_contour ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 180 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 181 | zone->n_points = load->outline.n_points - start_point; |
| 182 | zone->n_contours = load->outline.n_contours - start_contour; |
| 183 | zone->org = load->extra_points + start_point; |
| 184 | zone->cur = load->outline.points + start_point; |
| 185 | zone->tags = (FT_Byte*)load->outline.tags + start_point; |
| 186 | zone->contours = (FT_UShort*)load->outline.contours + start_contour; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 187 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 188 | |
| 189 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 190 | #undef IS_HINTED |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 191 | #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) |
| 192 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 193 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 194 | /*************************************************************************/ |
| 195 | /* */ |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 196 | /* The following functions are used by default with TrueType fonts. */ |
| 197 | /* However, they can be replaced by alternatives if we need to support */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 198 | /* TrueType-compressed formats (like MicroType) in the future. */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 199 | /* */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 200 | /*************************************************************************/ |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 201 | |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 202 | FT_CALLBACK_DEF |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 203 | FT_Error TT_Access_Glyph_Frame( TT_Loader* loader, |
| 204 | FT_UInt glyph_index, |
| 205 | FT_ULong offset, |
| 206 | FT_UInt byte_count ) |
| 207 | { |
Werner Lemberg | e72c9fe | 2000-07-31 18:59:02 +0000 | [diff] [blame] | 208 | FT_Error error; |
| 209 | FT_Stream stream = loader->stream; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 210 | |
Werner Lemberg | 353dfea | 2000-08-29 18:58:41 +0000 | [diff] [blame] | 211 | /* for non-debug mode */ |
| 212 | FT_UNUSED( glyph_index ); |
| 213 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 214 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 215 | FT_TRACE5(( "Glyph %ld\n", glyph_index )); |
Werner Lemberg | e72c9fe | 2000-07-31 18:59:02 +0000 | [diff] [blame] | 216 | |
| 217 | /* the following line sets the `error' variable through macros! */ |
| 218 | if ( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) ) |
| 219 | return error; |
| 220 | |
| 221 | return TT_Err_Ok; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 222 | } |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 223 | |
| 224 | |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 225 | FT_CALLBACK_DEF |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 226 | void TT_Forget_Glyph_Frame( TT_Loader* loader ) |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 227 | { |
| 228 | FT_Stream stream = loader->stream; |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 229 | |
| 230 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 231 | FORGET_Frame(); |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 232 | } |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 233 | |
| 234 | |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 235 | FT_CALLBACK_DEF |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 236 | FT_Error TT_Load_Glyph_Header( TT_Loader* loader ) |
| 237 | { |
| 238 | FT_Stream stream = loader->stream; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 239 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 240 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 241 | loader->n_contours = GET_Short(); |
| 242 | |
| 243 | loader->bbox.xMin = GET_Short(); |
| 244 | loader->bbox.yMin = GET_Short(); |
| 245 | loader->bbox.xMax = GET_Short(); |
| 246 | loader->bbox.yMax = GET_Short(); |
| 247 | |
| 248 | FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); |
| 249 | FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, |
| 250 | loader->bbox.xMax )); |
| 251 | FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, |
| 252 | loader->bbox.yMax )); |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 253 | |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 254 | return TT_Err_Ok; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 255 | } |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 256 | |
| 257 | |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 258 | FT_CALLBACK_DEF |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 259 | FT_Error TT_Load_Simple_Glyph( TT_Loader* load ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 260 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 261 | FT_Error error; |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 262 | FT_Stream stream = load->stream; |
| 263 | FT_GlyphLoader* gloader = load->gloader; |
| 264 | FT_Int n_contours = load->n_contours; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 265 | FT_Outline* outline; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 266 | TT_Face face = (TT_Face)load->face; |
| 267 | TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 268 | FT_UShort n_ins; |
| 269 | FT_Int n, n_points; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 270 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 271 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 272 | /* reading the contours endpoints & number of points */ |
| 273 | { |
| 274 | short* cur = gloader->current.outline.contours; |
| 275 | short* limit = cur + n_contours; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 276 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 277 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 278 | for ( ; cur < limit; cur++ ) |
| 279 | cur[0] = GET_UShort(); |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 280 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 281 | n_points = 0; |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 282 | if ( n_contours > 0 ) |
| 283 | n_points = cur[-1] + 1; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 284 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 285 | error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 ); |
| 286 | if ( error ) |
| 287 | goto Fail; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 288 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 289 | outline = &gloader->current.outline; |
| 290 | } |
| 291 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 292 | /* reading the bytecode instructions */ |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 293 | slot->control_len = 0; |
| 294 | slot->control_data = 0; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 295 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 296 | n_ins = GET_UShort(); |
| 297 | |
Werner Lemberg | 1c0d4ac | 2000-06-06 20:41:48 +0000 | [diff] [blame] | 298 | FT_TRACE5(( " Instructions size: %d\n", n_ins )); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 299 | |
| 300 | if ( n_ins > face->max_profile.maxSizeOfInstructions ) |
| 301 | { |
| 302 | FT_TRACE0(( "ERROR: Too many instructions!\n" )); |
| 303 | error = TT_Err_Too_Many_Ins; |
| 304 | goto Fail; |
| 305 | } |
| 306 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 307 | if ( stream->cursor + n_ins > stream->limit ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 308 | { |
| 309 | FT_TRACE0(( "ERROR: Instruction count mismatch!\n" )); |
| 310 | error = TT_Err_Too_Many_Ins; |
| 311 | goto Fail; |
| 312 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 313 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 314 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 315 | |
| 316 | if ( ( load->load_flags & |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 317 | ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 && |
| 318 | load->instructions ) |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 319 | { |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 320 | slot->control_len = n_ins; |
| 321 | slot->control_data = load->instructions; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 322 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 323 | MEM_Copy( load->instructions, stream->cursor, n_ins ); |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 324 | } |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 325 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 326 | #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 327 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 328 | stream->cursor += n_ins; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 329 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 330 | /* reading the point tags */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 331 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 332 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 333 | FT_Byte* flag = (FT_Byte*)outline->tags; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 334 | FT_Byte* limit = flag + n_points; |
| 335 | FT_Byte c, count; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 336 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 337 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 338 | for ( ; flag < limit; flag++ ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 339 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 340 | *flag = c = GET_Byte(); |
| 341 | if ( c & 8 ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 342 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 343 | for ( count = GET_Byte(); count > 0; count-- ) |
| 344 | *++flag = c; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 345 | } |
| 346 | } |
| 347 | } |
| 348 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 349 | /* reading the X coordinates */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 350 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 351 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 352 | FT_Vector* vec = outline->points; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 353 | FT_Vector* limit = vec + n_points; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 354 | FT_Byte* flag = (FT_Byte*)outline->tags; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 355 | FT_Pos x = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 356 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 357 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 358 | for ( ; vec < limit; vec++, flag++ ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 359 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 360 | FT_Pos y = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 361 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 362 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 363 | if ( *flag & 2 ) |
| 364 | { |
| 365 | y = GET_Byte(); |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 366 | if ( ( *flag & 16 ) == 0 ) |
| 367 | y = -y; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 368 | } |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 369 | else if ( ( *flag & 16 ) == 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 370 | y = GET_Short(); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 371 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 372 | x += y; |
| 373 | vec->x = x; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 374 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 375 | } |
| 376 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 377 | /* reading the Y coordinates */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 378 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 379 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 380 | FT_Vector* vec = gloader->current.outline.points; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 381 | FT_Vector* limit = vec + n_points; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 382 | FT_Byte* flag = (FT_Byte*)outline->tags; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 383 | FT_Pos x = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 384 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 385 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 386 | for ( ; vec < limit; vec++, flag++ ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 387 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 388 | FT_Pos y = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 389 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 390 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 391 | if ( *flag & 4 ) |
| 392 | { |
| 393 | y = GET_Byte(); |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 394 | if ( ( *flag & 32 ) == 0 ) |
| 395 | y = -y; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 396 | } |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 397 | else if ( ( *flag & 32 ) == 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 398 | y = GET_Short(); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 399 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 400 | x += y; |
| 401 | vec->y = x; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 402 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 403 | } |
| 404 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 405 | /* clear the touch tags */ |
| 406 | for ( n = 0; n < n_points; n++ ) |
| 407 | outline->tags[n] &= FT_Curve_Tag_On; |
| 408 | |
| 409 | outline->n_points = n_points; |
| 410 | outline->n_contours = n_contours; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 411 | |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 412 | Fail: |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 413 | return error; |
| 414 | } |
| 415 | |
| 416 | |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 417 | FT_CALLBACK_DEF |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 418 | FT_Error TT_Load_Composite_Glyph( TT_Loader* loader ) |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 419 | { |
| 420 | FT_Error error; |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 421 | FT_Stream stream = loader->stream; |
| 422 | FT_GlyphLoader* gloader = loader->gloader; |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 423 | FT_SubGlyph* subglyph; |
| 424 | FT_UInt num_subglyphs; |
| 425 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 426 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 427 | num_subglyphs = 0; |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 428 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 429 | do |
| 430 | { |
| 431 | FT_Fixed xx, xy, yy, yx; |
| 432 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 433 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 434 | /* check that we can load a new subglyph */ |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 435 | error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 ); |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 436 | if ( error ) |
| 437 | goto Fail; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 438 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 439 | subglyph = gloader->current.subglyphs + num_subglyphs; |
| 440 | |
| 441 | subglyph->arg1 = subglyph->arg2 = 0; |
| 442 | |
| 443 | subglyph->flags = GET_UShort(); |
| 444 | subglyph->index = GET_UShort(); |
| 445 | |
| 446 | /* read arguments */ |
| 447 | if ( subglyph->flags & ARGS_ARE_WORDS ) |
| 448 | { |
| 449 | subglyph->arg1 = GET_Short(); |
| 450 | subglyph->arg2 = GET_Short(); |
| 451 | } |
| 452 | else |
| 453 | { |
| 454 | subglyph->arg1 = GET_Char(); |
| 455 | subglyph->arg2 = GET_Char(); |
| 456 | } |
| 457 | |
| 458 | /* read transform */ |
| 459 | xx = yy = 0x10000L; |
| 460 | xy = yx = 0; |
| 461 | |
| 462 | if ( subglyph->flags & WE_HAVE_A_SCALE ) |
| 463 | { |
| 464 | xx = (FT_Fixed)GET_Short() << 2; |
| 465 | yy = xx; |
| 466 | } |
| 467 | else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) |
| 468 | { |
| 469 | xx = (FT_Fixed)GET_Short() << 2; |
| 470 | yy = (FT_Fixed)GET_Short() << 2; |
| 471 | } |
| 472 | else if ( subglyph->flags & WE_HAVE_A_2X2 ) |
| 473 | { |
| 474 | xx = (FT_Fixed)GET_Short() << 2; |
| 475 | xy = (FT_Fixed)GET_Short() << 2; |
| 476 | yx = (FT_Fixed)GET_Short() << 2; |
| 477 | yy = (FT_Fixed)GET_Short() << 2; |
| 478 | } |
| 479 | |
| 480 | subglyph->transform.xx = xx; |
| 481 | subglyph->transform.xy = xy; |
| 482 | subglyph->transform.yx = yx; |
| 483 | subglyph->transform.yy = yy; |
| 484 | |
| 485 | num_subglyphs++; |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 486 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 487 | } while ( subglyph->flags & MORE_COMPONENTS ); |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 488 | |
| 489 | gloader->current.num_subglyphs = num_subglyphs; |
| 490 | |
| 491 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
| 492 | { |
| 493 | /* we must undo the ACCESS_Frame in order to point to the */ |
| 494 | /* composite instructions, if we find some. */ |
| 495 | /* we will process them later... */ |
| 496 | /* */ |
Werner Lemberg | 914b289 | 2001-03-10 17:07:42 +0000 | [diff] [blame] | 497 | loader->ins_pos = (FT_ULong)( FILE_Pos() + |
| 498 | stream->cursor - stream->limit ); |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 499 | } |
| 500 | #endif |
| 501 | |
| 502 | Fail: |
| 503 | return error; |
| 504 | } |
| 505 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 506 | |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 507 | FT_LOCAL_DEF |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 508 | void TT_Init_Glyph_Loading( TT_Face face ) |
| 509 | { |
| 510 | face->access_glyph_frame = TT_Access_Glyph_Frame; |
| 511 | face->read_glyph_header = TT_Load_Glyph_Header; |
| 512 | face->read_simple_glyph = TT_Load_Simple_Glyph; |
| 513 | face->read_composite_glyph = TT_Load_Composite_Glyph; |
| 514 | face->forget_glyph_frame = TT_Forget_Glyph_Frame; |
| 515 | } |
| 516 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 517 | |
| 518 | /*************************************************************************/ |
| 519 | /* */ |
| 520 | /* <Function> */ |
| 521 | /* TT_Process_Simple_Glyph */ |
| 522 | /* */ |
| 523 | /* <Description> */ |
| 524 | /* Once a simple glyph has been loaded, it needs to be processed. */ |
| 525 | /* Usually, this means scaling and hinting through bytecode */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 526 | /* interpretation. */ |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 527 | /* */ |
| 528 | static |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 529 | FT_Error TT_Process_Simple_Glyph( TT_Loader* load, |
| 530 | FT_Bool debug ) |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 531 | { |
| 532 | FT_GlyphLoader* gloader = load->gloader; |
| 533 | FT_Outline* outline = &gloader->current.outline; |
| 534 | FT_UInt n_points = outline->n_points; |
| 535 | FT_UInt n_ins; |
| 536 | TT_GlyphZone* zone = &load->zone; |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 537 | FT_Error error = TT_Err_Ok; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 538 | |
Werner Lemberg | 58b17f9 | 2000-07-27 23:29:08 +0000 | [diff] [blame] | 539 | FT_UNUSED( debug ); /* used by truetype interpreter only */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 540 | |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 541 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 542 | n_ins = load->glyph->control_len; |
| 543 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 544 | /* add shadow points */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 545 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 546 | /* Now add the two shadow points at n and n + 1. */ |
| 547 | /* We need the left side bearing and advance width. */ |
| 548 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 549 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 550 | FT_Vector* pp1; |
| 551 | FT_Vector* pp2; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 552 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 553 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 554 | /* pp1 = xMin - lsb */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 555 | pp1 = outline->points + n_points; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 556 | pp1->x = load->bbox.xMin - load->left_bearing; |
| 557 | pp1->y = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 558 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 559 | /* pp2 = pp1 + aw */ |
| 560 | pp2 = pp1 + 1; |
| 561 | pp2->x = pp1->x + load->advance; |
| 562 | pp2->y = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 563 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 564 | outline->tags[n_points ] = 0; |
| 565 | outline->tags[n_points + 1] = 0; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 566 | } |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 567 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 568 | /* Note that we return two more points that are not */ |
| 569 | /* part of the glyph outline. */ |
| 570 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 571 | n_points += 2; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 572 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 573 | /* set up zone for hinting */ |
| 574 | tt_prepare_zone( zone, &gloader->current, 0, 0 ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 575 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 576 | /* eventually scale the glyph */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 577 | if ( !( load->load_flags & FT_LOAD_NO_SCALE ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 578 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 579 | FT_Vector* vec = zone->cur; |
| 580 | FT_Vector* limit = vec + n_points; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 581 | FT_Fixed x_scale = load->size->metrics.x_scale; |
| 582 | FT_Fixed y_scale = load->size->metrics.y_scale; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 583 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 584 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 585 | /* first scale the glyph points */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 586 | for ( ; vec < limit; vec++ ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 587 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 588 | vec->x = FT_MulFix( vec->x, x_scale ); |
| 589 | vec->y = FT_MulFix( vec->y, y_scale ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 590 | } |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 591 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 592 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 593 | cur_to_org( n_points, zone ); |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 594 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 595 | /* eventually hint the glyph */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 596 | if ( IS_HINTED( load->load_flags ) ) |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 597 | { |
| 598 | FT_Pos x = zone->org[n_points-2].x; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 599 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 600 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 601 | x = ( ( x + 32 ) & -64 ) - x; |
| 602 | translate_array( n_points, zone->org, x, 0 ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 603 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 604 | org_to_cur( n_points, zone ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 605 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 606 | zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 607 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 608 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 609 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 610 | /* now consider hinting */ |
| 611 | if ( n_ins > 0 ) |
| 612 | { |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 613 | error = TT_Set_CodeRange( load->exec, tt_coderange_glyph, |
| 614 | load->exec->glyphIns, n_ins ); |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 615 | if ( error ) |
| 616 | goto Exit; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 617 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 618 | load->exec->is_composite = FALSE; |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 619 | load->exec->pedantic_hinting = (FT_Bool)( load->load_flags & |
| 620 | FT_LOAD_PEDANTIC ); |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 621 | load->exec->pts = *zone; |
| 622 | load->exec->pts.n_points += 2; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 623 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 624 | error = TT_Run_Context( load->exec, debug ); |
| 625 | if ( error && load->exec->pedantic_hinting ) |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 626 | goto Exit; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 627 | |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 628 | error = TT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 629 | } |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 630 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 631 | #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 632 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 633 | } |
| 634 | |
| 635 | /* save glyph phantom points */ |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 636 | if ( !load->preserve_pps ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 637 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 638 | load->pp1 = zone->cur[n_points - 2]; |
| 639 | load->pp2 = zone->cur[n_points - 1]; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 640 | } |
| 641 | |
David Turner | 5fe4c00 | 2000-07-26 19:04:08 +0000 | [diff] [blame] | 642 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 643 | Exit: |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 644 | #endif |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 645 | return error; |
| 646 | } |
| 647 | |
| 648 | |
| 649 | /*************************************************************************/ |
| 650 | /* */ |
| 651 | /* <Function> */ |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 652 | /* load_truetype_glyph */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 653 | /* */ |
| 654 | /* <Description> */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 655 | /* Loads a given truetype glyph. Handles composites and uses a */ |
| 656 | /* TT_Loader object. */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 657 | /* */ |
| 658 | static |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 659 | FT_Error load_truetype_glyph( TT_Loader* loader, |
| 660 | FT_UInt glyph_index ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 661 | { |
Werner Lemberg | 321cd27 | 2000-07-27 11:20:20 +0000 | [diff] [blame] | 662 | |
| 663 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 664 | FT_Stream stream = loader->stream; |
Werner Lemberg | 321cd27 | 2000-07-27 11:20:20 +0000 | [diff] [blame] | 665 | #endif |
| 666 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 667 | FT_Error error; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 668 | TT_Face face = (TT_Face)loader->face; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 669 | FT_ULong offset; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 670 | FT_Int contours_count; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 671 | FT_UInt index, num_points, num_contours, count; |
| 672 | FT_Fixed x_scale, y_scale; |
| 673 | FT_ULong ins_offset; |
| 674 | FT_GlyphLoader* gloader = loader->gloader; |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 675 | FT_Bool opened_frame = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 676 | |
Werner Lemberg | 58b17f9 | 2000-07-27 23:29:08 +0000 | [diff] [blame] | 677 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 678 | /* check glyph index */ |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 679 | index = glyph_index; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 680 | if ( index >= (FT_UInt)face->root.num_glyphs ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 681 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 682 | error = TT_Err_Invalid_Glyph_Index; |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 683 | goto Exit; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 684 | } |
| 685 | |
David Turner | 861ba62 | 2000-02-15 12:54:51 +0000 | [diff] [blame] | 686 | loader->glyph_index = glyph_index; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 687 | num_contours = 0; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 688 | num_points = 0; |
| 689 | ins_offset = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 690 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 691 | x_scale = 0x10000L; |
| 692 | y_scale = 0x10000L; |
| 693 | if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 694 | { |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 695 | x_scale = loader->size->metrics.x_scale; |
| 696 | y_scale = loader->size->metrics.y_scale; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 697 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 698 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 699 | /* get horizontal metrics */ |
| 700 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 701 | FT_Short left_bearing; |
| 702 | FT_UShort advance_width; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 703 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 704 | |
David Turner | 71ec10e | 2000-02-10 16:09:35 +0000 | [diff] [blame] | 705 | Get_HMetrics( face, index, |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 706 | (FT_Bool)!(loader->load_flags & |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 707 | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH), |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 708 | &left_bearing, |
| 709 | &advance_width ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 710 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 711 | loader->left_bearing = left_bearing; |
| 712 | loader->advance = advance_width; |
| 713 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 714 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 715 | offset = face->glyph_locations[index]; |
| 716 | count = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 717 | |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 718 | if ( index < (FT_UInt)face->num_locations - 1 ) |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 719 | count = face->glyph_locations[index + 1] - offset; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 720 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 721 | if ( count == 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 722 | { |
| 723 | /* as described by Frederic Loyer, these are spaces, and */ |
| 724 | /* not the unknown glyph. */ |
| 725 | loader->bbox.xMin = 0; |
| 726 | loader->bbox.xMax = 0; |
| 727 | loader->bbox.yMin = 0; |
| 728 | loader->bbox.yMax = 0; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 729 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 730 | loader->pp1.x = 0; |
| 731 | loader->pp2.x = loader->advance; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 732 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 733 | if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 734 | loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 735 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 736 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 737 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 738 | if ( loader->exec ) |
David Turner | 7bb7fed | 2000-02-28 11:23:36 +0000 | [diff] [blame] | 739 | loader->exec->glyphSize = 0; |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 740 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 741 | #endif |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 742 | |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 743 | error = TT_Err_Ok; |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 744 | goto Exit; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 745 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 746 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 747 | offset = loader->glyf_offset + offset; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 748 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 749 | /* access glyph frame */ |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 750 | error = face->access_glyph_frame( loader, glyph_index, offset, count ); |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 751 | if ( error ) |
| 752 | goto Exit; |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 753 | |
| 754 | opened_frame = 1; |
| 755 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 756 | /* read first glyph header */ |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 757 | error = face->read_glyph_header( loader ); |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 758 | if ( error ) |
| 759 | goto Fail; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 760 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 761 | contours_count = loader->n_contours; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 762 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 763 | count -= 10; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 764 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 765 | loader->pp1.x = loader->bbox.xMin - loader->left_bearing; |
| 766 | loader->pp1.y = 0; |
| 767 | loader->pp2.x = loader->pp1.x + loader->advance; |
| 768 | loader->pp2.y = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 769 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 770 | if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 771 | { |
| 772 | loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); |
| 773 | loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); |
| 774 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 775 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 776 | /***********************************************************************/ |
| 777 | /***********************************************************************/ |
| 778 | /***********************************************************************/ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 779 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 780 | /* if it is a simple glyph, load it */ |
| 781 | |
| 782 | if ( contours_count >= 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 783 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 784 | /* check that we can add the contours to the glyph */ |
| 785 | error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count ); |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 786 | if ( error ) |
| 787 | goto Fail; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 788 | |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 789 | error = face->read_simple_glyph( loader ); |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 790 | if ( error ) |
| 791 | goto Fail; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 792 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 793 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 794 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 795 | { |
| 796 | TT_Size size = (TT_Size)loader->size; |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 797 | |
| 798 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 799 | error = TT_Process_Simple_Glyph( loader, |
| 800 | (FT_Bool)( size && size->debug ) ); |
| 801 | } |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 802 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 803 | #else |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 804 | |
David Turner | 5fe4c00 | 2000-07-26 19:04:08 +0000 | [diff] [blame] | 805 | error = TT_Process_Simple_Glyph( loader, 0 ); |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 806 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 807 | #endif |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 808 | |
| 809 | if ( error ) |
| 810 | goto Fail; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 811 | |
| 812 | FT_GlyphLoader_Add( gloader ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 813 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 814 | /* Note: We could have put the simple loader source there */ |
| 815 | /* but the code is fat enough already :-) */ |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 816 | } |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 817 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 818 | /***********************************************************************/ |
| 819 | /***********************************************************************/ |
| 820 | /***********************************************************************/ |
| 821 | |
| 822 | /* otherwise, load a composite! */ |
| 823 | else |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 824 | { |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 825 | TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph; |
| 826 | FT_UInt start_point, start_contour; |
David Turner | c6a9220 | 2000-07-04 18:12:13 +0000 | [diff] [blame] | 827 | FT_ULong ins_pos; /* position of composite instructions, if any */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 828 | |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 829 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 830 | /* for each subglyph, read composite header */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 831 | start_point = gloader->base.outline.n_points; |
| 832 | start_contour = gloader->base.outline.n_contours; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 833 | |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 834 | error = face->read_composite_glyph( loader ); |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 835 | if ( error ) |
| 836 | goto Fail; |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 837 | |
David Turner | c6a9220 | 2000-07-04 18:12:13 +0000 | [diff] [blame] | 838 | ins_pos = loader->ins_pos; |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 839 | face->forget_glyph_frame( loader ); |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 840 | opened_frame = 0; |
| 841 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 842 | /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 843 | /* `as is' in the glyph slot (the client application will be */ |
| 844 | /* responsible for interpreting this data)... */ |
| 845 | /* */ |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 846 | if ( loader->load_flags & FT_LOAD_NO_RECURSE ) |
| 847 | { |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 848 | /* set up remaining glyph fields */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 849 | FT_GlyphLoader_Add( gloader ); |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 850 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 851 | glyph->num_subglyphs = gloader->base.num_subglyphs; |
David Turner | 3475e7f | 2000-05-17 20:56:01 +0000 | [diff] [blame] | 852 | glyph->format = ft_glyph_format_composite; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 853 | glyph->subglyphs = gloader->base.subglyphs; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 854 | |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 855 | goto Exit; |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 856 | } |
| 857 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 858 | /*********************************************************************/ |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 859 | /*********************************************************************/ |
| 860 | /*********************************************************************/ |
| 861 | |
| 862 | /* Now, read each subglyph independently. */ |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 863 | { |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 864 | FT_Int n, num_base_points, num_new_points; |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 865 | FT_SubGlyph* subglyph = 0; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 866 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 867 | FT_UInt num_subglyphs = gloader->current.num_subglyphs; |
| 868 | FT_UInt num_base_subgs = gloader->base.num_subglyphs; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 869 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 870 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 871 | FT_GlyphLoader_Add( gloader ); |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 872 | |
David Turner | 74abee8 | 2000-06-27 23:31:53 +0000 | [diff] [blame] | 873 | for ( n = 0; n < (FT_Int)num_subglyphs; n++ ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 874 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 875 | FT_Vector pp1, pp2; |
| 876 | FT_Pos x, y; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 877 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 878 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 879 | /* Each time we call load_truetype_glyph in this loop, the */ |
| 880 | /* value of `gloader.base.subglyphs' can change due to table */ |
| 881 | /* reallocations. We thus need to recompute the subglyph */ |
| 882 | /* pointer on each iteration. */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 883 | subglyph = gloader->base.subglyphs + num_base_subgs + n; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 884 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 885 | pp1 = loader->pp1; |
| 886 | pp2 = loader->pp2; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 887 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 888 | num_base_points = gloader->base.outline.n_points; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 889 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 890 | error = load_truetype_glyph( loader, subglyph->index ); |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 891 | if ( error ) |
| 892 | goto Fail; |
David Turner | 3475e7f | 2000-05-17 20:56:01 +0000 | [diff] [blame] | 893 | |
David Turner | 61d6b2b | 2001-05-16 17:49:07 +0000 | [diff] [blame] | 894 | /* restore subglyph pointer */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 895 | subglyph = gloader->base.subglyphs + num_base_subgs + n; |
| 896 | |
David Turner | 7bb7fed | 2000-02-28 11:23:36 +0000 | [diff] [blame] | 897 | if ( subglyph->flags & USE_MY_METRICS ) |
| 898 | { |
| 899 | pp1 = loader->pp1; |
| 900 | pp2 = loader->pp2; |
| 901 | } |
| 902 | else |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 903 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 904 | loader->pp1 = pp1; |
| 905 | loader->pp2 = pp2; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 906 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 907 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 908 | num_points = gloader->base.outline.n_points; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 909 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 910 | num_new_points = num_points - num_base_points; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 911 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 912 | /* now perform the transform required for this subglyph */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 913 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 914 | if ( subglyph->flags & ( WE_HAVE_A_SCALE | |
| 915 | WE_HAVE_AN_XY_SCALE | |
| 916 | WE_HAVE_A_2X2 ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 917 | { |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 918 | FT_Vector* cur = gloader->base.outline.points + |
| 919 | num_base_points; |
| 920 | FT_Vector* org = gloader->base.extra_points + |
| 921 | num_base_points; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 922 | FT_Vector* limit = cur + num_new_points; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 923 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 924 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 925 | for ( ; cur < limit; cur++, org++ ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 926 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 927 | FT_Vector_Transform( cur, &subglyph->transform ); |
| 928 | FT_Vector_Transform( org, &subglyph->transform ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 929 | } |
| 930 | } |
| 931 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 932 | /* apply offset */ |
| 933 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 934 | if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 935 | { |
David Turner | 74abee8 | 2000-06-27 23:31:53 +0000 | [diff] [blame] | 936 | FT_UInt k = subglyph->arg1; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 937 | FT_UInt l = subglyph->arg2; |
| 938 | FT_Vector* p1; |
| 939 | FT_Vector* p2; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 940 | |
Werner Lemberg | deb4e98 | 2000-06-29 03:14:25 +0000 | [diff] [blame] | 941 | |
David Turner | 74abee8 | 2000-06-27 23:31:53 +0000 | [diff] [blame] | 942 | if ( start_point + k >= (FT_UInt)num_base_points || |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 943 | l >= (FT_UInt)num_new_points ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 944 | { |
| 945 | error = TT_Err_Invalid_Composite; |
| 946 | goto Fail; |
| 947 | } |
| 948 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 949 | l += num_base_points; |
| 950 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 951 | p1 = gloader->base.outline.points + start_point + k; |
| 952 | p2 = gloader->base.outline.points + start_point + l; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 953 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 954 | x = p1->x - p2->x; |
| 955 | y = p1->y - p2->y; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 956 | } |
| 957 | else |
| 958 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 959 | x = subglyph->arg1; |
| 960 | y = subglyph->arg2; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 961 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 962 | if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 963 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 964 | x = FT_MulFix( x, x_scale ); |
| 965 | y = FT_MulFix( y, y_scale ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 966 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 967 | if ( subglyph->flags & ROUND_XY_TO_GRID ) |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 968 | { |
| 969 | x = ( x + 32 ) & -64; |
| 970 | y = ( y + 32 ) & -64; |
| 971 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 972 | } |
| 973 | } |
| 974 | |
David Turner | 61d6b2b | 2001-05-16 17:49:07 +0000 | [diff] [blame] | 975 | if ( x | y ) |
| 976 | { |
| 977 | translate_array( num_new_points, |
| 978 | gloader->base.outline.points + num_base_points, |
| 979 | x, y ); |
| 980 | |
| 981 | translate_array( num_new_points, |
| 982 | gloader->base.extra_points + num_base_points, |
| 983 | x, y ); |
| 984 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 985 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 986 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 987 | /*******************************************************************/ |
| 988 | /*******************************************************************/ |
| 989 | /*******************************************************************/ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 990 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 991 | /* we have finished loading all sub-glyphs; now, look for */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 992 | /* instructions for this composite! */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 993 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 994 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 995 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 996 | if ( num_subglyphs > 0 && |
| 997 | loader->exec && |
David Turner | c6a9220 | 2000-07-04 18:12:13 +0000 | [diff] [blame] | 998 | ins_pos > 0 && |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 999 | subglyph->flags & WE_HAVE_INSTR ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1000 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1001 | FT_UShort n_ins; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1002 | TT_ExecContext exec = loader->exec; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1003 | TT_GlyphZone* pts; |
| 1004 | FT_Vector* pp1; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1005 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1006 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1007 | /* read size of instructions */ |
David Turner | c6a9220 | 2000-07-04 18:12:13 +0000 | [diff] [blame] | 1008 | if ( FILE_Seek( ins_pos ) || |
| 1009 | READ_UShort( n_ins ) ) |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1010 | goto Fail; |
Werner Lemberg | 1c0d4ac | 2000-06-06 20:41:48 +0000 | [diff] [blame] | 1011 | FT_TRACE5(( " Instructions size = %d\n", n_ins )); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1012 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 1013 | /* in some fonts? */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1014 | if ( n_ins == 0xFFFF ) |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1015 | n_ins = 0; |
| 1016 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1017 | /* check it */ |
| 1018 | if ( n_ins > face->max_profile.maxSizeOfInstructions ) |
| 1019 | { |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1020 | FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n", |
| 1021 | n_ins, subglyph->index )); |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1022 | return TT_Err_Too_Many_Ins; |
| 1023 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1024 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1025 | /* read the instructions */ |
| 1026 | if ( FILE_Read( exec->glyphIns, n_ins ) ) |
| 1027 | goto Fail; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1028 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1029 | glyph->control_data = exec->glyphIns; |
| 1030 | glyph->control_len = n_ins; |
| 1031 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1032 | error = TT_Set_CodeRange( exec, |
| 1033 | tt_coderange_glyph, |
| 1034 | exec->glyphIns, |
| 1035 | n_ins ); |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1036 | if ( error ) |
| 1037 | goto Fail; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1038 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1039 | /* prepare the execution context */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1040 | tt_prepare_zone( &exec->pts, &gloader->base, |
| 1041 | start_point, start_contour ); |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1042 | pts = &exec->pts; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1043 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1044 | pts->n_points = num_points + 2; |
David Turner | 43a2f65 | 2000-07-05 18:23:38 +0000 | [diff] [blame] | 1045 | pts->n_contours = gloader->base.outline.n_contours; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1046 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1047 | /* add phantom points */ |
| 1048 | pp1 = pts->cur + num_points; |
| 1049 | pp1[0] = loader->pp1; |
| 1050 | pp1[1] = loader->pp2; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1051 | |
Werner Lemberg | deb4e98 | 2000-06-29 03:14:25 +0000 | [diff] [blame] | 1052 | pts->tags[num_points ] = 0; |
David Turner | 41dbcbf | 2000-03-09 11:46:25 +0000 | [diff] [blame] | 1053 | pts->tags[num_points + 1] = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1054 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1055 | /* if hinting, round the phantom points */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1056 | if ( IS_HINTED( loader->load_flags ) ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1057 | { |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1058 | pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 ); |
| 1059 | pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 ); |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1060 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1061 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1062 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1063 | FT_UInt k; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1064 | |
| 1065 | |
David Turner | 43a2f65 | 2000-07-05 18:23:38 +0000 | [diff] [blame] | 1066 | for ( k = 0; k < num_points; k++ ) |
David Turner | 41dbcbf | 2000-03-09 11:46:25 +0000 | [diff] [blame] | 1067 | pts->tags[k] &= FT_Curve_Tag_On; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1068 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1069 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 1070 | cur_to_org( num_points + 2, pts ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1071 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1072 | /* now consider hinting */ |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1073 | if ( IS_HINTED( loader->load_flags ) && n_ins > 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1074 | { |
| 1075 | exec->is_composite = TRUE; |
| 1076 | exec->pedantic_hinting = |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1077 | (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1078 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1079 | error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug ); |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1080 | if ( error && exec->pedantic_hinting ) |
| 1081 | goto Fail; |
| 1082 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1083 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1084 | /* save glyph origin and advance points */ |
| 1085 | loader->pp1 = pp1[0]; |
| 1086 | loader->pp2 = pp1[1]; |
| 1087 | } |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1088 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1089 | #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1090 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1091 | } |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1092 | /* end of composite loading */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1093 | } |
| 1094 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1095 | /***********************************************************************/ |
| 1096 | /***********************************************************************/ |
| 1097 | /***********************************************************************/ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1098 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1099 | Fail: |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1100 | if ( opened_frame ) |
David Turner | 994d774 | 2000-06-25 04:49:19 +0000 | [diff] [blame] | 1101 | face->forget_glyph_frame( loader ); |
David Turner | 90f68b7 | 2000-06-23 12:26:14 +0000 | [diff] [blame] | 1102 | |
| 1103 | Exit: |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1104 | return error; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1105 | } |
| 1106 | |
| 1107 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1108 | static |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1109 | void compute_glyph_metrics( TT_Loader* loader, |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1110 | FT_UInt glyph_index ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1111 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1112 | FT_BBox bbox; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1113 | TT_Face face = (TT_Face)loader->face; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1114 | FT_Fixed x_scale, y_scale; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1115 | TT_GlyphSlot glyph = loader->glyph; |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1116 | TT_Size size = (TT_Size)loader->size; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1117 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1118 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1119 | x_scale = 0x10000L; |
| 1120 | y_scale = 0x10000L; |
| 1121 | if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1122 | { |
| 1123 | x_scale = size->root.metrics.x_scale; |
| 1124 | y_scale = size->root.metrics.y_scale; |
| 1125 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1126 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1127 | if ( glyph->format != ft_glyph_format_composite ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1128 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1129 | glyph->outline.flags &= ~ft_outline_single_pass; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1130 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1131 | /* copy outline to our glyph slot */ |
David Turner | 54e7574 | 2000-11-04 02:52:02 +0000 | [diff] [blame] | 1132 | FT_GlyphLoader_Copy_Points( glyph->internal->loader, loader->gloader ); |
| 1133 | glyph->outline = glyph->internal->loader->base.outline; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 1134 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1135 | /* translate array so that (0,0) is the glyph's origin */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1136 | FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1137 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1138 | FT_Outline_Get_CBox( &glyph->outline, &bbox ); |
| 1139 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1140 | if ( IS_HINTED( loader->load_flags ) ) |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1141 | { |
| 1142 | /* grid-fit the bounding box */ |
| 1143 | bbox.xMin &= -64; |
| 1144 | bbox.yMin &= -64; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1145 | bbox.xMax = ( bbox.xMax + 63 ) & -64; |
| 1146 | bbox.yMax = ( bbox.yMax + 63 ) & -64; |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1147 | } |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1148 | } |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1149 | else |
| 1150 | bbox = loader->bbox; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1151 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1152 | /* get the device-independent horizontal advance. It is scaled later */ |
| 1153 | /* by the base layer. */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1154 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1155 | FT_Pos advance = loader->advance; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1156 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1157 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 1158 | /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */ |
| 1159 | /* correctly support DynaLab fonts, which have an incorrect */ |
| 1160 | /* `advance_Width_Max' field! It is used, to my knowledge, */ |
| 1161 | /* exclusively in the X-TrueType font server. */ |
| 1162 | /* */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1163 | if ( face->postscript.isFixedPitch && |
| 1164 | ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1165 | advance = face->horizontal.advance_Width_Max; |
| 1166 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1167 | /* we need to return the advance in font units in linearHoriAdvance, */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1168 | /* it will be scaled later by the base layer. */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1169 | glyph->linearHoriAdvance = advance; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1170 | } |
| 1171 | |
| 1172 | glyph->metrics.horiBearingX = bbox.xMin; |
| 1173 | glyph->metrics.horiBearingY = bbox.yMax; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1174 | glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1175 | |
| 1176 | /* Now take care of vertical metrics. In the case where there is */ |
| 1177 | /* no vertical information within the font (relatively common), make */ |
| 1178 | /* up some metrics by `hand'... */ |
| 1179 | |
| 1180 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1181 | FT_Short top_bearing; /* vertical top side bearing (EM units) */ |
| 1182 | FT_UShort advance_height; /* vertical advance height (EM units) */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1183 | |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1184 | FT_Pos left; /* scaled vertical left side bearing */ |
| 1185 | FT_Pos Top; /* scaled original vertical top side bearing */ |
| 1186 | FT_Pos top; /* scaled vertical top side bearing */ |
| 1187 | FT_Pos advance; /* scaled vertical advance height */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1188 | |
| 1189 | |
| 1190 | /* Get the unscaled `tsb' and `ah' */ |
| 1191 | if ( face->vertical_info && |
| 1192 | face->vertical.number_Of_VMetrics > 0 ) |
| 1193 | { |
| 1194 | /* Don't assume that both the vertical header and vertical */ |
| 1195 | /* metrics are present in the same font :-) */ |
| 1196 | |
| 1197 | TT_Get_Metrics( (TT_HoriHeader*)&face->vertical, |
| 1198 | glyph_index, |
| 1199 | &top_bearing, |
| 1200 | &advance_height ); |
| 1201 | } |
| 1202 | else |
| 1203 | { |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1204 | /* Make up the distances from the horizontal header. */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1205 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1206 | /* NOTE: The OS/2 values are the only `portable' ones, */ |
| 1207 | /* which is why we use them, if there is an OS/2 */ |
| 1208 | /* table in the font. Otherwise, we use the */ |
| 1209 | /* values defined in the horizontal header. */ |
| 1210 | /* */ |
| 1211 | /* NOTE2: The sTypoDescender is negative, which is why */ |
| 1212 | /* we compute the baseline-to-baseline distance */ |
| 1213 | /* here with: */ |
| 1214 | /* ascender - descender + linegap */ |
| 1215 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1216 | if ( face->os2.version != 0xFFFF ) |
| 1217 | { |
| 1218 | top_bearing = face->os2.sTypoLineGap / 2; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1219 | advance_height = (FT_UShort)( face->os2.sTypoAscender - |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1220 | face->os2.sTypoDescender + |
| 1221 | face->os2.sTypoLineGap ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1222 | } |
| 1223 | else |
| 1224 | { |
| 1225 | top_bearing = face->horizontal.Line_Gap / 2; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1226 | advance_height = (FT_UShort)( face->horizontal.Ascender + |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1227 | face->horizontal.Descender + |
| 1228 | face->horizontal.Line_Gap ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1229 | } |
| 1230 | } |
| 1231 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1232 | /* We must adjust the top_bearing value from the bounding box given */ |
| 1233 | /* in the glyph header to te bounding box calculated with */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1234 | /* FT_Get_Outline_CBox(). */ |
David Turner | fc1f989 | 2000-01-07 18:44:50 +0000 | [diff] [blame] | 1235 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1236 | /* scale the metrics */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1237 | if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1238 | { |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1239 | Top = FT_MulFix( top_bearing, y_scale ); |
| 1240 | top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale ) |
| 1241 | - bbox.yMax; |
| 1242 | advance = FT_MulFix( advance_height, y_scale ); |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1243 | } |
| 1244 | else |
| 1245 | { |
David Turner | fc1f989 | 2000-01-07 18:44:50 +0000 | [diff] [blame] | 1246 | Top = top_bearing; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1247 | top = top_bearing + loader->bbox.yMax - bbox.yMax; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1248 | advance = advance_height; |
| 1249 | } |
| 1250 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1251 | /* set the advance height in design units. It is scaled later by */ |
| 1252 | /* the base layer. */ |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1253 | glyph->linearVertAdvance = advance_height; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1254 | |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1255 | /* XXX: for now, we have no better algorithm for the lsb, but it */ |
| 1256 | /* should work fine. */ |
| 1257 | /* */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1258 | left = ( bbox.xMin - bbox.xMax ) / 2; |
| 1259 | |
| 1260 | /* grid-fit them if necessary */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1261 | if ( IS_HINTED( loader->load_flags ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1262 | { |
| 1263 | left &= -64; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1264 | top = ( top + 63 ) & -64; |
| 1265 | advance = ( advance + 32 ) & -64; |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1266 | } |
| 1267 | |
| 1268 | glyph->metrics.vertBearingX = left; |
| 1269 | glyph->metrics.vertBearingY = top; |
| 1270 | glyph->metrics.vertAdvance = advance; |
| 1271 | } |
| 1272 | |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1273 | /* adjust advance width to the value contained in the hdmx table */ |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1274 | if ( !face->postscript.isFixedPitch && size && |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1275 | IS_HINTED( loader->load_flags ) ) |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1276 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1277 | FT_Byte* widths = Get_Advance_Widths( face, |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1278 | size->root.metrics.x_ppem ); |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1279 | |
| 1280 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1281 | if ( widths ) |
| 1282 | glyph->metrics.horiAdvance = widths[glyph_index] << 6; |
| 1283 | } |
| 1284 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1285 | /* set glyph dimensions */ |
| 1286 | glyph->metrics.width = bbox.xMax - bbox.xMin; |
| 1287 | glyph->metrics.height = bbox.yMax - bbox.yMin; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1288 | } |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1289 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1290 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1291 | /*************************************************************************/ |
| 1292 | /* */ |
| 1293 | /* <Function> */ |
| 1294 | /* TT_Load_Glyph */ |
| 1295 | /* */ |
| 1296 | /* <Description> */ |
| 1297 | /* A function used to load a single glyph within a given glyph slot, */ |
| 1298 | /* for a given size. */ |
| 1299 | /* */ |
| 1300 | /* <Input> */ |
| 1301 | /* glyph :: A handle to a target slot object where the glyph */ |
| 1302 | /* will be loaded. */ |
| 1303 | /* */ |
| 1304 | /* size :: A handle to the source face size at which the glyph */ |
| 1305 | /* must be scaled/loaded. */ |
| 1306 | /* */ |
| 1307 | /* glyph_index :: The index of the glyph in the font file. */ |
| 1308 | /* */ |
| 1309 | /* load_flags :: A flag indicating what to load for this glyph. The */ |
| 1310 | /* FT_LOAD_XXX constants can be used to control the */ |
| 1311 | /* glyph loading process (e.g., whether the outline */ |
| 1312 | /* should be scaled, whether to load bitmaps or not, */ |
| 1313 | /* whether to hint the outline, etc). */ |
| 1314 | /* */ |
| 1315 | /* <Return> */ |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1316 | /* FreeType error code. 0 means success. */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1317 | /* */ |
David Turner | 76a5f62 | 2000-11-04 01:55:49 +0000 | [diff] [blame] | 1318 | FT_LOCAL_DEF |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1319 | FT_Error TT_Load_Glyph( TT_Size size, |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1320 | TT_GlyphSlot glyph, |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1321 | FT_UShort glyph_index, |
| 1322 | FT_UInt load_flags ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1323 | { |
| 1324 | SFNT_Interface* sfnt; |
| 1325 | TT_Face face; |
| 1326 | FT_Stream stream; |
| 1327 | FT_Memory memory; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1328 | FT_Error error; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1329 | TT_Loader loader; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1330 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1331 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1332 | face = (TT_Face)glyph->face; |
| 1333 | sfnt = (SFNT_Interface*)face->sfnt; |
| 1334 | stream = face->root.stream; |
| 1335 | memory = face->root.memory; |
| 1336 | error = 0; |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1337 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1338 | if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) || |
| 1339 | ( load_flags & FT_LOAD_NO_RECURSE ) ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1340 | { |
| 1341 | size = NULL; |
| 1342 | load_flags |= FT_LOAD_NO_SCALE | |
| 1343 | FT_LOAD_NO_HINTING | |
| 1344 | FT_LOAD_NO_BITMAP; |
| 1345 | } |
| 1346 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 1347 | glyph->num_subglyphs = 0; |
| 1348 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1349 | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
Werner Lemberg | 4b68007 | 2000-11-07 06:30:29 +0000 | [diff] [blame] | 1350 | |
| 1351 | /* try to load embedded bitmap if any */ |
| 1352 | /* */ |
| 1353 | /* XXX: The convention should be emphasized in */ |
| 1354 | /* the documents because it can be confusing. */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1355 | if ( size && |
Werner Lemberg | 4b68007 | 2000-11-07 06:30:29 +0000 | [diff] [blame] | 1356 | size->strike_index != 0xFFFF && |
David Turner | f96594f | 2000-11-06 23:07:51 +0000 | [diff] [blame] | 1357 | sfnt->load_sbits && |
| 1358 | ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) |
| 1359 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1360 | { |
| 1361 | TT_SBit_Metrics metrics; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1362 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1363 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1364 | error = sfnt->load_sbit_image( face, |
David Turner | f96594f | 2000-11-06 23:07:51 +0000 | [diff] [blame] | 1365 | size->strike_index, |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1366 | glyph_index, |
David Turner | 109fcf6 | 2000-05-17 23:35:37 +0000 | [diff] [blame] | 1367 | load_flags, |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1368 | stream, |
| 1369 | &glyph->bitmap, |
| 1370 | &metrics ); |
| 1371 | if ( !error ) |
| 1372 | { |
| 1373 | glyph->outline.n_points = 0; |
| 1374 | glyph->outline.n_contours = 0; |
| 1375 | |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1376 | glyph->metrics.width = (FT_Pos)metrics.width << 6; |
| 1377 | glyph->metrics.height = (FT_Pos)metrics.height << 6; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1378 | |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1379 | glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; |
| 1380 | glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; |
| 1381 | glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1382 | |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1383 | glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; |
| 1384 | glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; |
| 1385 | glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1386 | |
| 1387 | glyph->format = ft_glyph_format_bitmap; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1388 | if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) |
| 1389 | { |
David Turner | e161ee4 | 2000-07-10 22:03:10 +0000 | [diff] [blame] | 1390 | glyph->bitmap_left = metrics.vertBearingX; |
| 1391 | glyph->bitmap_top = metrics.vertBearingY; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1392 | } |
| 1393 | else |
| 1394 | { |
David Turner | e161ee4 | 2000-07-10 22:03:10 +0000 | [diff] [blame] | 1395 | glyph->bitmap_left = metrics.horiBearingX; |
| 1396 | glyph->bitmap_top = metrics.horiBearingY; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1397 | } |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1398 | return error; |
| 1399 | } |
| 1400 | } |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1401 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1402 | #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
| 1403 | |
Werner Lemberg | 5811c7c | 2000-07-02 13:53:16 +0000 | [diff] [blame] | 1404 | /* seek to the beginning of the glyph table. For Type 42 fonts */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1405 | /* the table might be accessed from a Postscript stream or something */ |
| 1406 | /* else... */ |
| 1407 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1408 | error = face->goto_table( face, TTAG_glyf, stream, 0 ); |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1409 | if ( error ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1410 | { |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1411 | FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" )); |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 1412 | goto Exit; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1413 | } |
| 1414 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1415 | MEM_Set( &loader, 0, sizeof ( loader ) ); |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1416 | |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 1417 | /* update the glyph zone bounds */ |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 1418 | { |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1419 | FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader; |
Werner Lemberg | a929ba9 | 2000-06-25 06:47:11 +0000 | [diff] [blame] | 1420 | |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 1421 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1422 | loader.gloader = gloader; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 1423 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1424 | FT_GlyphLoader_Rewind( gloader ); |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 1425 | |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 1426 | tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 ); |
| 1427 | tt_prepare_zone( &loader.base, &gloader->base, 0, 0 ); |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 1428 | } |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 1429 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1430 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1431 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1432 | if ( size ) |
| 1433 | { |
| 1434 | /* query new execution context */ |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1435 | loader.exec = size->debug ? size->context : TT_New_Context( face ); |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1436 | if ( !loader.exec ) |
| 1437 | return TT_Err_Could_Not_Find_Context; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1438 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1439 | TT_Load_Context( loader.exec, face, size ); |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1440 | loader.instructions = loader.exec->glyphIns; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1441 | |
| 1442 | /* load default graphics state - if needed */ |
| 1443 | if ( size->GS.instruct_control & 2 ) |
| 1444 | loader.exec->GS = tt_default_graphics_state; |
| 1445 | } |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1446 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1447 | #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
| 1448 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1449 | /* clear all outline flags, except the `owner' one */ |
David Turner | 81bb4ad | 2000-06-28 04:19:49 +0000 | [diff] [blame] | 1450 | glyph->outline.flags = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1451 | |
David Turner | 04aa800 | 2000-06-01 03:27:48 +0000 | [diff] [blame] | 1452 | if ( size && size->root.metrics.y_ppem < 24 ) |
David Turner | 41dbcbf | 2000-03-09 11:46:25 +0000 | [diff] [blame] | 1453 | glyph->outline.flags |= ft_outline_high_precision; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1454 | |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1455 | /* let's initialize the rest of our loader now */ |
| 1456 | |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1457 | loader.load_flags = load_flags; |
| 1458 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1459 | loader.face = (FT_Face)face; |
| 1460 | loader.size = (FT_Size)size; |
| 1461 | loader.glyph = (FT_GlyphSlot)glyph; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1462 | loader.stream = stream; |
Werner Lemberg | bd5ae40 | 2000-07-05 04:32:02 +0000 | [diff] [blame] | 1463 | |
David Turner | c312861 | 2000-06-23 05:02:13 +0000 | [diff] [blame] | 1464 | loader.glyf_offset = FILE_Pos(); |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1465 | |
| 1466 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1467 | |
| 1468 | /* if the cvt program has disabled hinting, the argument */ |
| 1469 | /* is ignored. */ |
| 1470 | if ( size && ( size->GS.instruct_control & 1 ) ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1471 | loader.load_flags |= FT_LOAD_NO_HINTING; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1472 | |
| 1473 | #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1474 | |
| 1475 | /* Main loading loop */ |
David Turner | 3475e7f | 2000-05-17 20:56:01 +0000 | [diff] [blame] | 1476 | glyph->format = ft_glyph_format_outline; |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1477 | glyph->num_subglyphs = 0; |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1478 | error = load_truetype_glyph( &loader, glyph_index ); |
Werner Lemberg | 78575dc | 2000-06-12 19:36:41 +0000 | [diff] [blame] | 1479 | if ( !error ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1480 | compute_glyph_metrics( &loader, glyph_index ); |
| 1481 | |
| 1482 | #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1483 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1484 | if ( !size || !size->debug ) |
David Turner | 8f43c71 | 2000-02-02 12:16:19 +0000 | [diff] [blame] | 1485 | TT_Done_Context( loader.exec ); |
Werner Lemberg | dcd2e14 | 2000-06-25 07:43:15 +0000 | [diff] [blame] | 1486 | |
| 1487 | #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1488 | |
David Turner | 08fdac9 | 2000-02-21 16:01:33 +0000 | [diff] [blame] | 1489 | Exit: |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1490 | return error; |
| 1491 | } |
| 1492 | |
| 1493 | |
David Turner | d2b1f35 | 1999-12-16 23:11:37 +0000 | [diff] [blame] | 1494 | /* END */ |