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