1 /***************************************************************************/
5 /* FreeType PFR object methods (body). */
7 /* Copyright 2002 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
25 #include FT_INTERNAL_DEBUG_H
30 #define FT_COMPONENT trace_pfr
33 /*************************************************************************/
34 /*************************************************************************/
36 /***** FACE OBJECT METHODS *****/
38 /*************************************************************************/
39 /*************************************************************************/
42 pfr_face_done( PFR_Face face )
44 FT_Memory memory = face->root.driver->root.memory;
46 /* we don't want dangling pointers */
47 face->root.family_name = NULL;
48 face->root.style_name = NULL;
50 /* finalize the physical font record */
51 pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) );
53 /* no need to finalize the logical font or the header */
54 FT_FREE( face->root.available_sizes );
58 FT_LOCAL_DEF( FT_Error )
59 pfr_face_init( FT_Stream stream,
63 FT_Parameter* params )
67 FT_UNUSED( num_params );
71 /* load the header and check it */
72 error = pfr_header_load( &face->header, stream );
76 if ( !pfr_header_check( &face->header ) )
78 FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" ));
79 error = PFR_Err_Unknown_File_Format;
83 /* check face index */
88 error = pfr_log_font_count( stream,
89 face->header.log_dir_offset,
94 face->root.num_faces = num_faces;
100 if ( face_index >= face->root.num_faces )
102 FT_ERROR(( "pfr_face_init: invalid face index\n" ));
103 error = PFR_Err_Invalid_Argument;
108 error = pfr_log_font_load(
109 &face->log_font, stream, face_index,
110 face->header.log_dir_offset,
111 FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
115 /* now load the physical font descriptor */
116 error = pfr_phy_font_load( &face->phy_font, stream,
117 face->log_font.phys_offset,
118 face->log_font.phys_size );
122 /* now, set-up all root face fields */
124 FT_Face root = FT_FACE( face );
125 PFR_PhyFont phy_font = &face->phy_font;
128 root->face_index = face_index;
129 root->num_glyphs = phy_font->num_chars;
130 root->face_flags = FT_FACE_FLAG_SCALABLE;
132 if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
133 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
135 if ( phy_font->flags & PFR_PHY_VERTICAL )
136 root->face_flags |= FT_FACE_FLAG_VERTICAL;
138 root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
140 if ( phy_font->num_strikes > 0 )
141 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
143 if ( phy_font->num_kern_pairs > 0 )
144 root->face_flags |= FT_FACE_FLAG_KERNING;
146 /* if no family name was found in the "undocumented" auxiliary
147 * data, use the font ID instead. This sucks but is better than
150 root->family_name = phy_font->family_name;
151 if ( root->family_name == NULL )
152 root->family_name = phy_font->font_id;
154 /* note that the style name can be NULL in certain PFR fonts,
155 * probably meaning "Regular"
157 root->style_name = phy_font->style_name;
159 root->num_fixed_sizes = 0;
160 root->available_sizes = 0;
162 root->bbox = phy_font->bbox;
163 root->units_per_EM = (FT_UShort)phy_font->outline_resolution;
164 root->ascender = (FT_Short) phy_font->bbox.yMax;
165 root->descender = (FT_Short) phy_font->bbox.yMin;
166 root->height = (FT_Short)
167 ( ( ( root->ascender - root->descender ) * 12 )
170 if ( phy_font->num_strikes > 0 )
172 FT_UInt n, count = phy_font->num_strikes;
173 FT_Bitmap_Size* size;
175 FT_Memory memory = root->stream->memory;
178 if ( FT_NEW_ARRAY( root->available_sizes, count ) )
181 size = root->available_sizes;
182 strike = phy_font->strikes;
183 for ( n = 0; n < count; n++, size++, strike++ )
185 size->height = (FT_UShort) strike->y_ppm;
186 size->width = (FT_UShort) strike->x_ppm;
188 root->num_fixed_sizes = count;
191 /* now compute maximum advance width */
192 if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )
193 root->max_advance_width = (FT_Short)phy_font->standard_advance;
197 FT_UInt count = phy_font->num_chars;
198 PFR_Char gchar = phy_font->chars;
201 for ( ; count > 0; count--, gchar++ )
203 if ( max < gchar->advance )
204 max = gchar->advance;
207 root->max_advance_width = (FT_Short)max;
210 root->max_advance_height = root->height;
212 root->underline_position = (FT_Short)( - root->units_per_EM / 10 );
213 root->underline_thickness = (FT_Short)( root->units_per_EM / 30 );
217 FT_CharMapRec charmap;
221 charmap.platform_id = 3;
222 charmap.encoding_id = 1;
223 charmap.encoding = FT_ENCODING_UNICODE;
225 FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );
228 /* Select default charmap */
229 if (root->num_charmaps)
230 root->charmap = root->charmaps[0];
234 /* check whether we've loaded any kerning pairs */
235 if ( phy_font->num_kern_pairs )
236 root->face_flags |= FT_FACE_FLAG_KERNING;
244 /*************************************************************************/
245 /*************************************************************************/
247 /***** SLOT OBJECT METHOD *****/
249 /*************************************************************************/
250 /*************************************************************************/
252 FT_LOCAL_DEF( FT_Error )
253 pfr_slot_init( PFR_Slot slot )
255 FT_GlyphLoader loader = slot->root.internal->loader;
257 pfr_glyph_init( &slot->glyph, loader );
264 pfr_slot_done( PFR_Slot slot )
266 pfr_glyph_done( &slot->glyph );
270 FT_LOCAL_DEF( FT_Error )
271 pfr_slot_load( PFR_Slot slot,
274 FT_Int32 load_flags )
277 PFR_Face face = (PFR_Face)slot->root.face;
279 FT_Outline* outline = &slot->root.outline;
285 /* check that the glyph index is correct */
286 FT_ASSERT( gindex < face->phy_font.num_chars );
288 /* try to load an embedded bitmap */
289 if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 )
291 error = pfr_slot_load_bitmap( slot, size, gindex );
296 if ( load_flags & FT_LOAD_SBITS_ONLY )
298 error = FT_Err_Invalid_Argument;
302 gchar = face->phy_font.chars + gindex;
303 slot->root.format = FT_GLYPH_FORMAT_OUTLINE;
304 outline->n_points = 0;
305 outline->n_contours = 0;
306 gps_offset = face->header.gps_section_offset;
308 /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */
309 error = pfr_glyph_load( &slot->glyph, face->root.stream,
310 gps_offset, gchar->gps_offset, gchar->gps_size );
315 FT_Glyph_Metrics* metrics = &slot->root.metrics;
317 FT_Int em_metrics, em_outline;
321 scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
323 /* copy outline data */
324 *outline = slot->glyph.loader->base.outline;
326 outline->flags &= ~FT_OUTLINE_OWNER;
327 outline->flags |= FT_OUTLINE_REVERSE_FILL;
329 if ( size && size->root.metrics.y_ppem < 24 )
330 outline->flags |= FT_OUTLINE_HIGH_PRECISION;
332 /* compute the advance vector */
333 metrics->horiAdvance = 0;
334 metrics->vertAdvance = 0;
336 advance = gchar->advance;
337 em_metrics = face->phy_font.metrics_resolution;
338 em_outline = face->phy_font.outline_resolution;
340 if ( em_metrics != em_outline )
341 advance = FT_MulDiv( advance, em_outline, em_metrics );
343 if ( face->phy_font.flags & PFR_PHY_VERTICAL )
344 metrics->vertAdvance = advance;
346 metrics->horiAdvance = advance;
348 slot->root.linearHoriAdvance = metrics->horiAdvance;
349 slot->root.linearVertAdvance = metrics->vertAdvance;
351 /* make-up vertical metrics(?) */
352 metrics->vertBearingX = 0;
353 metrics->vertBearingY = 0;
355 /* scale when needed */
359 FT_Fixed x_scale = size->root.metrics.x_scale;
360 FT_Fixed y_scale = size->root.metrics.y_scale;
361 FT_Vector* vec = outline->points;
364 /* scale outline points */
365 for ( n = 0; n < outline->n_points; n++, vec++ )
367 vec->x = FT_MulFix( vec->x, x_scale );
368 vec->y = FT_MulFix( vec->y, y_scale );
371 /* scale the advance */
372 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
373 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
376 /* compute the rest of the metrics */
377 FT_Outline_Get_CBox( outline, &cbox );
379 metrics->width = cbox.xMax - cbox.xMin;
380 metrics->height = cbox.yMax - cbox.yMin;
381 metrics->horiBearingX = cbox.xMin;
382 metrics->horiBearingY = cbox.yMax - metrics->height;
390 /*************************************************************************/
391 /*************************************************************************/
393 /***** KERNING METHOD *****/
395 /*************************************************************************/
396 /*************************************************************************/
398 FT_LOCAL_DEF( FT_Error )
399 pfr_face_get_kerning( PFR_Face face,
405 PFR_PhyFont phy_font = &face->phy_font;
406 PFR_KernItem item = phy_font->kern_items;
407 FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 );
413 /* find the kerning item containing our pair */
416 if ( item->pair1 <= idx && idx <= item->pair2 )
427 /* perform simply binary search within the item */
428 FT_UInt min, mid, max;
429 FT_Stream stream = face->root.stream;
433 if ( FT_STREAM_SEEK( item->offset ) ||
434 FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
438 max = item->pair_count;
441 FT_UInt char1, char2, charcode;
444 mid = ( min + max ) >> 1;
445 p = stream->cursor + mid*item->pair_size;
447 if ( item->flags & PFR_KERN_2BYTE_CHAR )
449 char1 = FT_NEXT_USHORT( p );
450 char2 = FT_NEXT_USHORT( p );
454 char1 = FT_NEXT_USHORT( p );
455 char2 = FT_NEXT_USHORT( p );
457 charcode = PFR_KERN_INDEX( char1, char2 );
459 if ( idx == charcode )
461 if ( item->flags & PFR_KERN_2BYTE_ADJ )
462 kerning->x = item->base_adj + FT_NEXT_SHORT( p );
464 kerning->x = item->base_adj + FT_NEXT_CHAR( p );
468 if ( idx > charcode )