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