Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4348 → Rev 4349

/contrib/sdk/sources/freetype/src/cff/cf2arrst.c
0,0 → 1,241
/***************************************************************************/
/* */
/* cf2arrst.c */
/* */
/* Adobe's code for Array Stacks (body). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H
 
#include "cf2glue.h"
#include "cf2arrst.h"
 
#include "cf2error.h"
 
 
/*
* CF2_ArrStack uses an error pointer, to enable shared errors.
* Shared errors are necessary when multiple objects allow the program
* to continue after detecting errors. Only the first error should be
* recorded.
*/
 
FT_LOCAL_DEF( void )
cf2_arrstack_init( CF2_ArrStack arrstack,
FT_Memory memory,
FT_Error* error,
size_t sizeItem )
{
FT_ASSERT( arrstack != NULL );
 
/* initialize the structure */
arrstack->memory = memory;
arrstack->error = error;
arrstack->sizeItem = sizeItem;
arrstack->allocated = 0;
arrstack->chunk = 10; /* chunks of 10 items */
arrstack->count = 0;
arrstack->totalSize = 0;
arrstack->ptr = NULL;
}
 
 
FT_LOCAL_DEF( void )
cf2_arrstack_finalize( CF2_ArrStack arrstack )
{
FT_Memory memory = arrstack->memory; /* for FT_FREE */
 
 
FT_ASSERT( arrstack != NULL );
 
arrstack->allocated = 0;
arrstack->count = 0;
arrstack->totalSize = 0;
 
/* free the data buffer */
FT_FREE( arrstack->ptr );
}
 
 
/* allocate or reallocate the buffer size; */
/* return false on memory error */
static FT_Bool
cf2_arrstack_setNumElements( CF2_ArrStack arrstack,
size_t numElements )
{
FT_ASSERT( arrstack != NULL );
 
{
FT_Error error = FT_Err_Ok; /* for FT_REALLOC */
FT_Memory memory = arrstack->memory; /* for FT_REALLOC */
 
FT_Long newSize = (FT_Long)( numElements * arrstack->sizeItem );
 
 
if ( numElements > LONG_MAX / arrstack->sizeItem )
goto exit;
 
 
FT_ASSERT( newSize > 0 ); /* avoid realloc with zero size */
 
if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) )
{
arrstack->allocated = numElements;
arrstack->totalSize = newSize;
 
if ( arrstack->count > numElements )
{
/* we truncated the list! */
CF2_SET_ERROR( arrstack->error, Stack_Overflow );
arrstack->count = numElements;
return FALSE;
}
 
return TRUE; /* success */
}
}
 
exit:
/* if there's not already an error, store this one */
CF2_SET_ERROR( arrstack->error, Out_Of_Memory );
 
return FALSE;
}
 
 
/* set the count, ensuring allocation is sufficient */
FT_LOCAL_DEF( void )
cf2_arrstack_setCount( CF2_ArrStack arrstack,
size_t numElements )
{
FT_ASSERT( arrstack != NULL );
 
if ( numElements > arrstack->allocated )
{
/* expand the allocation first */
if ( !cf2_arrstack_setNumElements( arrstack, numElements ) )
return;
}
 
arrstack->count = numElements;
}
 
 
/* clear the count */
FT_LOCAL_DEF( void )
cf2_arrstack_clear( CF2_ArrStack arrstack )
{
FT_ASSERT( arrstack != NULL );
 
arrstack->count = 0;
}
 
 
/* current number of items */
FT_LOCAL_DEF( size_t )
cf2_arrstack_size( const CF2_ArrStack arrstack )
{
FT_ASSERT( arrstack != NULL );
 
return arrstack->count;
}
 
 
FT_LOCAL_DEF( void* )
cf2_arrstack_getBuffer( const CF2_ArrStack arrstack )
{
FT_ASSERT( arrstack != NULL );
 
return arrstack->ptr;
}
 
 
/* return pointer to the given element */
FT_LOCAL_DEF( void* )
cf2_arrstack_getPointer( const CF2_ArrStack arrstack,
size_t idx )
{
void* newPtr;
 
 
FT_ASSERT( arrstack != NULL );
 
if ( idx >= arrstack->count )
{
/* overflow */
CF2_SET_ERROR( arrstack->error, Stack_Overflow );
idx = 0; /* choose safe default */
}
 
newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem;
 
return newPtr;
}
 
 
/* push (append) an element at the end of the list; */
/* return false on memory error */
/* TODO: should there be a length param for extra checking? */
FT_LOCAL_DEF( void )
cf2_arrstack_push( CF2_ArrStack arrstack,
const void* ptr )
{
FT_ASSERT( arrstack != NULL );
 
if ( arrstack->count == arrstack->allocated )
{
/* grow the buffer by one chunk */
if ( !cf2_arrstack_setNumElements(
arrstack, arrstack->allocated + arrstack->chunk ) )
{
/* on error, ignore the push */
return;
}
}
 
FT_ASSERT( ptr != NULL );
 
{
size_t offset = arrstack->count * arrstack->sizeItem;
void* newPtr = (FT_Byte*)arrstack->ptr + offset;
 
 
FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem );
arrstack->count += 1;
}
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2arrst.h
0,0 → 1,100
/***************************************************************************/
/* */
/* cf2arrst.h */
/* */
/* Adobe's code for Array Stacks (specification). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2ARRST_H__
#define __CF2ARRST_H__
 
 
#include "cf2error.h"
 
 
FT_BEGIN_HEADER
 
 
/* need to define the struct here (not opaque) so it can be allocated by */
/* clients */
typedef struct CF2_ArrStackRec_
{
FT_Memory memory;
FT_Error* error;
 
size_t sizeItem; /* bytes per element */
size_t allocated; /* items allocated */
size_t chunk; /* allocation increment in items */
size_t count; /* number of elements allocated */
size_t totalSize; /* total bytes allocated */
 
void* ptr; /* ptr to data */
 
} CF2_ArrStackRec, *CF2_ArrStack;
 
 
FT_LOCAL( void )
cf2_arrstack_init( CF2_ArrStack arrstack,
FT_Memory memory,
FT_Error* error,
size_t sizeItem );
FT_LOCAL( void )
cf2_arrstack_finalize( CF2_ArrStack arrstack );
 
FT_LOCAL( void )
cf2_arrstack_setCount( CF2_ArrStack arrstack,
size_t numElements );
FT_LOCAL( void )
cf2_arrstack_clear( CF2_ArrStack arrstack );
FT_LOCAL( size_t )
cf2_arrstack_size( const CF2_ArrStack arrstack );
 
FT_LOCAL( void* )
cf2_arrstack_getBuffer( const CF2_ArrStack arrstack );
FT_LOCAL( void* )
cf2_arrstack_getPointer( const CF2_ArrStack arrstack,
size_t idx );
 
FT_LOCAL( void )
cf2_arrstack_push( CF2_ArrStack arrstack,
const void* ptr );
 
 
FT_END_HEADER
 
 
#endif /* __CF2ARRST_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2blues.c
0,0 → 1,578
/***************************************************************************/
/* */
/* cf2blues.c */
/* */
/* Adobe's code for handling Blue Zones (body). */
/* */
/* Copyright 2009-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H
 
#include "cf2blues.h"
#include "cf2hints.h"
#include "cf2font.h"
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cf2blues
 
 
/*
* For blue values, the FreeType parser produces an array of integers,
* while the Adobe CFF engine produces an array of fixed.
* Define a macro to convert FreeType to fixed.
*/
#define cf2_blueToFixed( x ) cf2_intToFixed( x )
 
 
FT_LOCAL_DEF( void )
cf2_blues_init( CF2_Blues blues,
CF2_Font font )
{
/* pointer to parsed font object */
CFF_Decoder* decoder = font->decoder;
 
CF2_Fixed zoneHeight;
CF2_Fixed maxZoneHeight = 0;
CF2_Fixed csUnitsPerPixel;
 
size_t numBlueValues;
size_t numOtherBlues;
size_t numFamilyBlues;
size_t numFamilyOtherBlues;
 
FT_Pos* blueValues;
FT_Pos* otherBlues;
FT_Pos* familyBlues;
FT_Pos* familyOtherBlues;
 
size_t i;
CF2_Fixed emBoxBottom, emBoxTop;
 
CF2_Int unitsPerEm = font->unitsPerEm;
 
 
if ( unitsPerEm == 0 )
unitsPerEm = 1000;
 
FT_ZERO( blues );
blues->scale = font->innerTransform.d;
 
cf2_getBlueMetrics( decoder,
&blues->blueScale,
&blues->blueShift,
&blues->blueFuzz );
 
cf2_getBlueValues( decoder, &numBlueValues, &blueValues );
cf2_getOtherBlues( decoder, &numOtherBlues, &otherBlues );
cf2_getFamilyBlues( decoder, &numFamilyBlues, &familyBlues );
cf2_getFamilyOtherBlues( decoder, &numFamilyOtherBlues, &familyOtherBlues );
 
/*
* synthetic em box hint heuristic
*
* Apply this when ideographic dictionary (LanguageGroup 1) has no
* real alignment zones. Adobe tools generate dummy zones at -250 and
* 1100 for a 1000 unit em. Fonts with ICF-based alignment zones
* should not enable the heuristic. When the heuristic is enabled,
* the font's blue zones are ignored.
*
*/
 
/* get em box from OS/2 typoAscender/Descender */
/* TODO: FreeType does not parse these metrics. Skip them for now. */
#if 0
FCM_getHorizontalLineMetrics( &e,
font->font,
&ascender,
&descender,
&linegap );
if ( ascender - descender == unitsPerEm )
{
emBoxBottom = cf2_intToFixed( descender );
emBoxTop = cf2_intToFixed( ascender );
}
else
#endif
{
emBoxBottom = CF2_ICF_Bottom;
emBoxTop = CF2_ICF_Top;
}
 
if ( cf2_getLanguageGroup( decoder ) == 1 &&
( numBlueValues == 0 ||
( numBlueValues == 4 &&
cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
cf2_blueToFixed( blueValues[2] ) > emBoxTop &&
cf2_blueToFixed( blueValues[3] ) > emBoxTop ) ) )
{
/*
* Construct hint edges suitable for synthetic ghost hints at top
* and bottom of em box. +-CF2_MIN_COUNTER allows for unhinted
* features above or below the last hinted edge. This also gives a
* net 1 pixel boost to the height of ideographic glyphs.
*
* Note: Adjust synthetic hints outward by epsilon (0x.0001) to
* avoid interference. E.g., some fonts have real hints at
* 880 and -120.
*/
 
blues->emBoxBottomEdge.csCoord = emBoxBottom - CF2_FIXED_EPSILON;
blues->emBoxBottomEdge.dsCoord = cf2_fixedRound(
FT_MulFix(
blues->emBoxBottomEdge.csCoord,
blues->scale ) ) -
CF2_MIN_COUNTER;
blues->emBoxBottomEdge.scale = blues->scale;
blues->emBoxBottomEdge.flags = CF2_GhostBottom |
CF2_Locked |
CF2_Synthetic;
 
blues->emBoxTopEdge.csCoord = emBoxTop + CF2_FIXED_EPSILON +
2 * font->darkenY;
blues->emBoxTopEdge.dsCoord = cf2_fixedRound(
FT_MulFix(
blues->emBoxTopEdge.csCoord,
blues->scale ) ) +
CF2_MIN_COUNTER;
blues->emBoxTopEdge.scale = blues->scale;
blues->emBoxTopEdge.flags = CF2_GhostTop |
CF2_Locked |
CF2_Synthetic;
 
blues->doEmBoxHints = TRUE; /* enable the heuristic */
 
return;
}
 
/* copy `BlueValues' and `OtherBlues' to a combined array of top and */
/* bottom zones */
for ( i = 0; i < numBlueValues; i += 2 )
{
blues->zone[blues->count].csBottomEdge =
cf2_blueToFixed( blueValues[i] );
blues->zone[blues->count].csTopEdge =
cf2_blueToFixed( blueValues[i + 1] );
 
zoneHeight = blues->zone[blues->count].csTopEdge -
blues->zone[blues->count].csBottomEdge;
 
if ( zoneHeight < 0 )
{
FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
continue; /* reject this zone */
}
 
if ( zoneHeight > maxZoneHeight )
{
/* take maximum before darkening adjustment */
/* so overshoot suppression point doesn't change */
maxZoneHeight = zoneHeight;
}
 
/* adjust both edges of top zone upward by twice darkening amount */
if ( i != 0 )
{
blues->zone[blues->count].csTopEdge += 2 * font->darkenY;
blues->zone[blues->count].csBottomEdge += 2 * font->darkenY;
}
 
/* first `BlueValue' is bottom zone; others are top */
if ( i == 0 )
{
blues->zone[blues->count].bottomZone =
TRUE;
blues->zone[blues->count].csFlatEdge =
blues->zone[blues->count].csTopEdge;
}
else
{
blues->zone[blues->count].bottomZone =
FALSE;
blues->zone[blues->count].csFlatEdge =
blues->zone[blues->count].csBottomEdge;
}
 
blues->count += 1;
}
 
for ( i = 0; i < numOtherBlues; i += 2 )
{
blues->zone[blues->count].csBottomEdge =
cf2_blueToFixed( otherBlues[i] );
blues->zone[blues->count].csTopEdge =
cf2_blueToFixed( otherBlues[i + 1] );
 
zoneHeight = blues->zone[blues->count].csTopEdge -
blues->zone[blues->count].csBottomEdge;
 
if ( zoneHeight < 0 )
{
FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
continue; /* reject this zone */
}
 
if ( zoneHeight > maxZoneHeight )
{
/* take maximum before darkening adjustment */
/* so overshoot suppression point doesn't change */
maxZoneHeight = zoneHeight;
}
 
/* Note: bottom zones are not adjusted for darkening amount */
 
/* all OtherBlues are bottom zone */
blues->zone[blues->count].bottomZone =
TRUE;
blues->zone[blues->count].csFlatEdge =
blues->zone[blues->count].csTopEdge;
 
blues->count += 1;
}
 
/* Adjust for FamilyBlues */
 
/* Search for the nearest flat edge in `FamilyBlues' or */
/* `FamilyOtherBlues'. According to the Black Book, any matching edge */
/* must be within one device pixel */
 
csUnitsPerPixel = FT_DivFix( cf2_intToFixed( 1 ), blues->scale );
 
/* loop on all zones in this font */
for ( i = 0; i < blues->count; i++ )
{
size_t j;
CF2_Fixed minDiff;
CF2_Fixed flatFamilyEdge, diff;
/* value for this font */
CF2_Fixed flatEdge = blues->zone[i].csFlatEdge;
 
 
if ( blues->zone[i].bottomZone )
{
/* In a bottom zone, the top edge is the flat edge. */
/* Search `FamilyOtherBlues' for bottom zones; look for closest */
/* Family edge that is within the one pixel threshold. */
 
minDiff = CF2_FIXED_MAX;
 
for ( j = 0; j < numFamilyOtherBlues; j += 2 )
{
/* top edge */
flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
 
diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
 
if ( diff < minDiff && diff < csUnitsPerPixel )
{
blues->zone[i].csFlatEdge = flatFamilyEdge;
minDiff = diff;
 
if ( diff == 0 )
break;
}
}
 
/* check the first member of FamilyBlues, which is a bottom zone */
if ( numFamilyBlues >= 2 )
{
/* top edge */
flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
 
diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
 
if ( diff < minDiff && diff < csUnitsPerPixel )
blues->zone[i].csFlatEdge = flatFamilyEdge;
}
}
else
{
/* In a top zone, the bottom edge is the flat edge. */
/* Search `FamilyBlues' for top zones; skip first zone, which is a */
/* bottom zone; look for closest Family edge that is within the */
/* one pixel threshold */
 
minDiff = CF2_FIXED_MAX;
 
for ( j = 2; j < numFamilyBlues; j += 2 )
{
/* bottom edge */
flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
 
/* adjust edges of top zone upward by twice darkening amount */
flatFamilyEdge += 2 * font->darkenY; /* bottom edge */
 
diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
 
if ( diff < minDiff && diff < csUnitsPerPixel )
{
blues->zone[i].csFlatEdge = flatFamilyEdge;
minDiff = diff;
 
if ( diff == 0 )
break;
}
}
}
}
 
/* TODO: enforce separation of zones, including BlueFuzz */
 
/* Adjust BlueScale; similar to AdjustBlueScale() in coretype */
/* `bcsetup.c'. */
 
if ( maxZoneHeight > 0 )
{
if ( blues->blueScale > FT_DivFix( cf2_intToFixed( 1 ),
maxZoneHeight ) )
{
/* clamp at maximum scale */
blues->blueScale = FT_DivFix( cf2_intToFixed( 1 ),
maxZoneHeight );
}
 
/*
* TODO: Revisit the bug fix for 613448. The minimum scale
* requirement catches a number of library fonts. For
* example, with default BlueScale (.039625) and 0.4 minimum,
* the test below catches any font with maxZoneHeight < 10.1.
* There are library fonts ranging from 2 to 10 that get
* caught, including e.g., Eurostile LT Std Medium with
* maxZoneHeight of 6.
*
*/
#if 0
if ( blueScale < .4 / maxZoneHeight )
{
tetraphilia_assert( 0 );
/* clamp at minimum scale, per bug 0613448 fix */
blueScale = .4 / maxZoneHeight;
}
#endif
 
}
 
/*
* Suppress overshoot and boost blue zones at small sizes. Boost
* amount varies linearly from 0.5 pixel near 0 to 0 pixel at
* blueScale cutoff.
* Note: This boost amount is different from the coretype heuristic.
*
*/
 
if ( blues->scale < blues->blueScale )
{
blues->suppressOvershoot = TRUE;
 
/* Change rounding threshold for `dsFlatEdge'. */
/* Note: constant changed from 0.5 to 0.6 to avoid a problem with */
/* 10ppem Arial */
 
blues->boost = FT_MulFix(
cf2_floatToFixed( .6 ),
( cf2_intToFixed( 1 ) -
FT_DivFix( blues->scale,
blues->blueScale ) ) );
if ( blues->boost > 0x7FFF )
{
/* boost must remain less than 0.5, or baseline could go negative */
blues->boost = 0x7FFF;
}
}
 
/* boost and darkening have similar effects; don't do both */
if ( font->stemDarkened )
blues->boost = 0;
 
/* set device space alignment for each zone; */
/* apply boost amount before rounding flat edge */
 
for ( i = 0; i < blues->count; i++ )
{
if ( blues->zone[i].bottomZone )
blues->zone[i].dsFlatEdge = cf2_fixedRound(
FT_MulFix(
blues->zone[i].csFlatEdge,
blues->scale ) -
blues->boost );
else
blues->zone[i].dsFlatEdge = cf2_fixedRound(
FT_MulFix(
blues->zone[i].csFlatEdge,
blues->scale ) +
blues->boost );
}
}
 
 
/*
* Check whether `stemHint' is captured by one of the blue zones.
*
* Zero, one or both edges may be valid; only valid edges can be
* captured. For compatibility with CoolType, search top and bottom
* zones in the same pass (see `BlueLock'). If a hint is captured,
* return true and position the edge(s) in one of 3 ways:
*
* 1) If `BlueScale' suppresses overshoot, position the captured edge
* at the flat edge of the zone.
* 2) If overshoot is not suppressed and `BlueShift' requires
* overshoot, position the captured edge a minimum of 1 device pixel
* from the flat edge.
* 3) If overshoot is not suppressed or required, position the captured
* edge at the nearest device pixel.
*
*/
FT_LOCAL_DEF( FT_Bool )
cf2_blues_capture( const CF2_Blues blues,
CF2_Hint bottomHintEdge,
CF2_Hint topHintEdge )
{
/* TODO: validate? */
CF2_Fixed csFuzz = blues->blueFuzz;
 
/* new position of captured edge */
CF2_Fixed dsNew;
 
/* amount that hint is moved when positioned */
CF2_Fixed dsMove = 0;
 
FT_Bool captured = FALSE;
CF2_UInt i;
 
 
/* assert edge flags are consistent */
FT_ASSERT( !cf2_hint_isTop( bottomHintEdge ) &&
!cf2_hint_isBottom( topHintEdge ) );
 
/* TODO: search once without blue fuzz for compatibility with coretype? */
for ( i = 0; i < blues->count; i++ )
{
if ( blues->zone[i].bottomZone &&
cf2_hint_isBottom( bottomHintEdge ) )
{
if ( ( blues->zone[i].csBottomEdge - csFuzz ) <=
bottomHintEdge->csCoord &&
bottomHintEdge->csCoord <=
( blues->zone[i].csTopEdge + csFuzz ) )
{
/* bottom edge captured by bottom zone */
 
if ( blues->suppressOvershoot )
dsNew = blues->zone[i].dsFlatEdge;
 
else if ( ( blues->zone[i].csTopEdge - bottomHintEdge->csCoord ) >=
blues->blueShift )
{
/* guarantee minimum of 1 pixel overshoot */
dsNew = FT_MIN(
cf2_fixedRound( bottomHintEdge->dsCoord ),
blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) );
}
 
else
{
/* simply round captured edge */
dsNew = cf2_fixedRound( bottomHintEdge->dsCoord );
}
 
dsMove = dsNew - bottomHintEdge->dsCoord;
captured = TRUE;
 
break;
}
}
 
if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) )
{
if ( ( blues->zone[i].csBottomEdge - csFuzz ) <=
topHintEdge->csCoord &&
topHintEdge->csCoord <=
( blues->zone[i].csTopEdge + csFuzz ) )
{
/* top edge captured by top zone */
 
if ( blues->suppressOvershoot )
dsNew = blues->zone[i].dsFlatEdge;
 
else if ( ( topHintEdge->csCoord - blues->zone[i].csBottomEdge ) >=
blues->blueShift )
{
/* guarantee minimum of 1 pixel overshoot */
dsNew = FT_MAX(
cf2_fixedRound( topHintEdge->dsCoord ),
blues->zone[i].dsFlatEdge + cf2_intToFixed( 1 ) );
}
 
else
{
/* simply round captured edge */
dsNew = cf2_fixedRound( topHintEdge->dsCoord );
}
 
dsMove = dsNew - topHintEdge->dsCoord;
captured = TRUE;
 
break;
}
}
}
 
if ( captured )
{
/* move both edges and flag them `locked' */
if ( cf2_hint_isValid( bottomHintEdge ) )
{
bottomHintEdge->dsCoord += dsMove;
cf2_hint_lock( bottomHintEdge );
}
 
if ( cf2_hint_isValid( topHintEdge ) )
{
topHintEdge->dsCoord += dsMove;
cf2_hint_lock( topHintEdge );
}
}
 
return captured;
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2blues.h
0,0 → 1,185
/***************************************************************************/
/* */
/* cf2blues.h */
/* */
/* Adobe's code for handling Blue Zones (specification). */
/* */
/* Copyright 2009-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
/*
* A `CF2_Blues' object stores the blue zones (horizontal alignment
* zones) of a font. These are specified in the CFF private dictionary
* by `BlueValues', `OtherBlues', `FamilyBlues', and `FamilyOtherBlues'.
* Each zone is defined by a top and bottom edge in character space.
* Further, each zone is either a top zone or a bottom zone, as recorded
* by `bottomZone'.
*
* The maximum number of `BlueValues' and `FamilyBlues' is 7 each.
* However, these are combined to produce a total of 7 zones.
* Similarly, the maximum number of `OtherBlues' and `FamilyOtherBlues'
* is 5 and these are combined to produce an additional 5 zones.
*
* Blue zones are used to `capture' hints and force them to a common
* alignment point. This alignment is recorded in device space in
* `dsFlatEdge'. Except for this value, a `CF2_Blues' object could be
* constructed independently of scaling. Construction may occur once
* the matrix is known. Other features implemented in the Capture
* method are overshoot suppression, overshoot enforcement, and Blue
* Boost.
*
* Capture is determined by `BlueValues' and `OtherBlues', but the
* alignment point may be adjusted to the scaled flat edge of
* `FamilyBlues' or `FamilyOtherBlues'. No alignment is done to the
* curved edge of a zone.
*
*/
 
 
#ifndef __CF2BLUES_H__
#define __CF2BLUES_H__
 
 
#include "cf2glue.h"
 
 
FT_BEGIN_HEADER
 
 
/*
* `CF2_Hint' is shared by `cf2hints.h' and
* `cf2blues.h', but `cf2blues.h' depends on
* `cf2hints.h', so define it here. Note: The typedef is in
* `cf2glue.h'.
*
*/
enum
{
CF2_GhostBottom = 0x1, /* a single bottom edge */
CF2_GhostTop = 0x2, /* a single top edge */
CF2_PairBottom = 0x4, /* the bottom edge of a stem hint */
CF2_PairTop = 0x8, /* the top edge of a stem hint */
CF2_Locked = 0x10, /* this edge has been aligned */
/* by a blue zone */
CF2_Synthetic = 0x20 /* this edge was synthesized */
};
 
 
/*
* Default value for OS/2 typoAscender/Descender when their difference
* is not equal to `unitsPerEm'. The default is based on -250 and 1100
* in `CF2_Blues', assuming 1000 units per em here.
*
*/
enum
{
CF2_ICF_Top = cf2_intToFixed( 880 ),
CF2_ICF_Bottom = cf2_intToFixed( -120 )
};
 
 
/*
* Constant used for hint adjustment and for synthetic em box hint
* placement.
*/
#define CF2_MIN_COUNTER cf2_floatToFixed( 0.5 )
 
 
/* shared typedef is in cf2glue.h */
struct CF2_HintRec_
{
CF2_UInt flags; /* attributes of the edge */
size_t index; /* index in original stem hint array */
/* (if not synthetic) */
CF2_Fixed csCoord;
CF2_Fixed dsCoord;
CF2_Fixed scale;
};
 
 
typedef struct CF2_BlueRec_
{
CF2_Fixed csBottomEdge;
CF2_Fixed csTopEdge;
CF2_Fixed csFlatEdge; /* may be from either local or Family zones */
CF2_Fixed dsFlatEdge; /* top edge of bottom zone or bottom edge */
/* of top zone (rounded) */
FT_Bool bottomZone;
 
} CF2_BlueRec;
 
 
/* max total blue zones is 12 */
enum
{
CF2_MAX_BLUES = 7,
CF2_MAX_OTHERBLUES = 5
};
 
 
typedef struct CF2_BluesRec_
{
CF2_Fixed scale;
CF2_UInt count;
FT_Bool suppressOvershoot;
FT_Bool doEmBoxHints;
 
CF2_Fixed blueScale;
CF2_Fixed blueShift;
CF2_Fixed blueFuzz;
 
CF2_Fixed boost;
 
CF2_HintRec emBoxTopEdge;
CF2_HintRec emBoxBottomEdge;
 
CF2_BlueRec zone[CF2_MAX_BLUES + CF2_MAX_OTHERBLUES];
 
} CF2_BluesRec, *CF2_Blues;
 
 
FT_LOCAL( void )
cf2_blues_init( CF2_Blues blues,
CF2_Font font );
FT_LOCAL( FT_Bool )
cf2_blues_capture( const CF2_Blues blues,
CF2_Hint bottomHintEdge,
CF2_Hint topHintEdge );
 
 
FT_END_HEADER
 
 
#endif /* __CF2BLUES_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2error.c
0,0 → 1,52
/***************************************************************************/
/* */
/* cf2error.c */
/* */
/* Adobe's code for error handling (body). */
/* */
/* Copyright 2006-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include "cf2error.h"
 
 
FT_LOCAL_DEF( void )
cf2_setError( FT_Error* error,
FT_Error value )
{
if ( error && *error == 0 )
*error = value;
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2error.h
0,0 → 1,119
/***************************************************************************/
/* */
/* cf2error.h */
/* */
/* Adobe's code for error handling (specification). */
/* */
/* Copyright 2006-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2ERROR_H__
#define __CF2ERROR_H__
 
 
#include FT_MODULE_ERRORS_H
 
#undef __FTERRORS_H__
 
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX CF2_Err_
#define FT_ERR_BASE FT_Mod_Err_CF2
 
 
#include FT_ERRORS_H
#include "cf2ft.h"
 
 
FT_BEGIN_HEADER
 
 
/*
* A poor-man error facility.
*
* This code being written in vanilla C, doesn't have the luxury of a
* language-supported exception mechanism such as the one available in
* Java. Instead, we are stuck with using error codes that must be
* carefully managed and preserved. However, it is convenient for us to
* model our error mechanism on a Java-like exception mechanism.
* When we assign an error code we are thus `throwing' an error.
*
* The perservation of an error code is done by coding convention.
* Upon a function call if the error code is anything other than
* `FT_Err_Ok', which is guaranteed to be zero, we
* will return without altering that error. This will allow the
* error to propogate and be handled at the appropriate location in
* the code.
*
* This allows a style of code where the error code is initialized
* up front and a block of calls are made with the error code only
* being checked after the block. If a new error occurs, the original
* error will be preserved and a functional no-op should result in any
* subsequent function that has an initial error code not equal to
* `FT_Err_Ok'.
*
* Errors are encoded by calling the `FT_THROW' macro. For example,
*
* {
* FT_Error e;
*
*
* ...
* e = FT_THROW( Out_Of_Memory );
* }
*
*/
 
 
/* Set error code to a particular value. */
FT_LOCAL( void )
cf2_setError( FT_Error* error,
FT_Error value );
 
 
/*
* A macro that conditionally sets an error code.
*
* This macro will first check whether `error' is set;
* if not, it will set it to `e'.
*
*/
#define CF2_SET_ERROR( error, e ) \
cf2_setError( error, FT_THROW( e ) )
 
 
FT_END_HEADER
 
 
#endif /* __CF2ERROR_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2fixed.h
0,0 → 1,95
/***************************************************************************/
/* */
/* cf2fixed.h */
/* */
/* Adobe's code for Fixed Point Mathematics (specification only). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2FIXED_H__
#define __CF2FIXED_H__
 
 
FT_BEGIN_HEADER
 
 
/* rasterizer integer and fixed point arithmetic must be 32-bit */
 
#define CF2_Fixed CF2_F16Dot16
typedef FT_Int32 CF2_Frac; /* 2.30 fixed point */
 
 
#define CF2_FIXED_MAX ( (CF2_Fixed)0x7FFFFFFFL )
#define CF2_FIXED_MIN ( (CF2_Fixed)0x80000000L )
#define CF2_FIXED_ONE 0x10000L
#define CF2_FIXED_EPSILON 0x0001
 
/* in C 89, left and right shift of negative numbers is */
/* implementation specific behaviour in the general case */
 
#define cf2_intToFixed( i ) \
( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) )
#define cf2_fixedToInt( x ) \
( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
#define cf2_fixedRound( x ) \
( (CF2_Fixed)( ( (x) + 0x8000 ) & 0xFFFF0000L ) )
#define cf2_floatToFixed( f ) \
( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
#define cf2_fixedAbs( x ) \
( (x) < 0 ? -(x) : (x) )
#define cf2_fixedFloor( x ) \
( (CF2_Fixed)( (x) & 0xFFFF0000L ) )
#define cf2_fixedFraction( x ) \
( (x) - cf2_fixedFloor( x ) )
#define cf2_fracToFixed( x ) \
( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 ) \
: ( ( (x) + 0x2000 ) >> 14 ) )
 
 
/* signed numeric types */
typedef enum CF2_NumberType_
{
CF2_NumberFixed, /* 16.16 */
CF2_NumberFrac, /* 2.30 */
CF2_NumberInt /* 32.0 */
 
} CF2_NumberType;
 
 
FT_END_HEADER
 
 
#endif /* __CF2FIXED_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2font.c
0,0 → 1,403
/***************************************************************************/
/* */
/* cf2font.c */
/* */
/* Adobe's code for font instances (body). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
 
#include "cf2glue.h"
#include "cf2font.h"
#include "cf2error.h"
#include "cf2intrp.h"
 
 
/* Compute a stem darkening amount in character space. */
static void
cf2_computeDarkening( CF2_Fixed emRatio,
CF2_Fixed ppem,
CF2_Fixed stemWidth,
CF2_Fixed* darkenAmount,
CF2_Fixed boldenAmount,
FT_Bool stemDarkened )
{
/* Internal calculations are done in units per thousand for */
/* convenience. */
CF2_Fixed stemWidthPer1000, scaledStem;
 
 
*darkenAmount = 0;
 
if ( boldenAmount == 0 && !stemDarkened )
return;
 
/* protect against range problems and divide by zero */
if ( emRatio < cf2_floatToFixed( .01 ) )
return;
 
if ( stemDarkened )
{
/* convert from true character space to 1000 unit character space; */
/* add synthetic emboldening effect */
 
/* we have to assure that the computation of `scaledStem' */
/* and `stemWidthPer1000' don't overflow */
 
stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
 
if ( emRatio > CF2_FIXED_ONE &&
stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
{
stemWidthPer1000 = 0; /* to pacify compiler */
scaledStem = cf2_intToFixed( 2333 );
}
else
{
scaledStem = FT_MulFix( stemWidthPer1000, ppem );
 
if ( ppem > CF2_FIXED_ONE &&
scaledStem <= stemWidthPer1000 )
scaledStem = cf2_intToFixed( 2333 );
}
 
/*
* Total darkening amount is computed in 1000 unit character space
* using the modified 5 part curve as Avalon rasterizer.
* The darkening amount is smaller for thicker stems.
* It becomes zero when the stem is thicker than 2.333 pixels.
*
* In Avalon rasterizer,
*
* darkenAmount = 0.5 pixels if scaledStem <= 0.5 pixels,
* darkenAmount = 0.333 pixels if 1 <= scaledStem <= 1.667 pixels,
* darkenAmount = 0 pixel if scaledStem >= 2.333 pixels,
*
* and piecewise linear in-between.
*
*/
if ( scaledStem < cf2_intToFixed( 500 ) )
*darkenAmount = FT_DivFix( cf2_intToFixed( 400 ), ppem );
 
else if ( scaledStem < cf2_intToFixed( 1000 ) )
*darkenAmount = FT_DivFix( cf2_intToFixed( 525 ), ppem ) -
FT_MulFix( stemWidthPer1000,
cf2_floatToFixed( .25 ) );
 
else if ( scaledStem < cf2_intToFixed( 1667 ) )
*darkenAmount = FT_DivFix( cf2_intToFixed( 275 ), ppem );
 
else if ( scaledStem < cf2_intToFixed( 2333 ) )
*darkenAmount = FT_DivFix( cf2_intToFixed( 963 ), ppem ) -
FT_MulFix( stemWidthPer1000,
cf2_floatToFixed( .413 ) );
 
/* use half the amount on each side and convert back to true */
/* character space */
*darkenAmount = FT_DivFix( *darkenAmount, 2 * emRatio );
}
 
/* add synthetic emboldening effect in character space */
*darkenAmount += boldenAmount / 2;
}
 
 
/* set up values for the current FontDict and matrix */
 
/* caller's transform is adjusted for subpixel positioning */
static void
cf2_font_setup( CF2_Font font,
const CF2_Matrix* transform )
{
/* pointer to parsed font object */
CFF_Decoder* decoder = font->decoder;
 
FT_Bool needExtraSetup;
 
/* character space units */
CF2_Fixed boldenX = font->syntheticEmboldeningAmountX;
CF2_Fixed boldenY = font->syntheticEmboldeningAmountY;
 
CF2_Fixed ppem;
 
 
/* clear previous error */
font->error = FT_Err_Ok;
 
/* if a CID fontDict has changed, we need to recompute some cached */
/* data */
needExtraSetup =
(FT_Bool)( font->lastSubfont != cf2_getSubfont( decoder ) );
 
/* if ppem has changed, we need to recompute some cached data */
/* note: because of CID font matrix concatenation, ppem and transform */
/* do not necessarily track. */
ppem = cf2_getPpemY( decoder );
if ( font->ppem != ppem )
{
font->ppem = ppem;
needExtraSetup = TRUE;
}
 
/* copy hinted flag on each call */
font->hinted = (FT_Bool)( font->renderingFlags & CF2_FlagsHinted );
 
/* determine if transform has changed; */
/* include Fontmatrix but ignore translation */
if ( ft_memcmp( transform,
&font->currentTransform,
4 * sizeof ( CF2_Fixed ) ) != 0 )
{
/* save `key' information for `cache of one' matrix data; */
/* save client transform, without the translation */
font->currentTransform = *transform;
font->currentTransform.tx =
font->currentTransform.ty = cf2_intToFixed( 0 );
 
/* TODO: FreeType transform is simple scalar; for now, use identity */
/* for outer */
font->innerTransform = *transform;
font->outerTransform.a =
font->outerTransform.d = cf2_intToFixed( 1 );
font->outerTransform.b =
font->outerTransform.c = cf2_intToFixed( 0 );
 
needExtraSetup = TRUE;
}
 
/*
* font->darkened is set to true if there is a stem darkening request or
* the font is synthetic emboldened.
* font->darkened controls whether to adjust blue zones, winding order,
* and hinting.
*
*/
if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) )
{
font->stemDarkened =
(FT_Bool)( font->renderingFlags & CF2_FlagsDarkened );
 
/* blue zones depend on darkened flag */
needExtraSetup = TRUE;
}
 
/* recompute variables that are dependent on transform or FontDict or */
/* darken flag */
if ( needExtraSetup )
{
/* StdVW is found in the private dictionary; */
/* recompute darkening amounts whenever private dictionary or */
/* transform change */
/* Note: a rendering flag turns darkening on or off, so we want to */
/* store the `on' amounts; */
/* darkening amount is computed in character space */
/* TODO: testing size-dependent darkening here; */
/* what to do for rotations? */
 
CF2_Fixed emRatio;
CF2_Fixed stdHW;
CF2_Int unitsPerEm = font->unitsPerEm;
 
 
if ( unitsPerEm == 0 )
unitsPerEm = 1000;
 
ppem = FT_MAX( cf2_intToFixed( 4 ),
font->ppem ); /* use minimum ppem of 4 */
 
#if 0
/* since vstem is measured in the x-direction, we use the `a' member */
/* of the fontMatrix */
emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->a );
#endif
 
/* Freetype does not preserve the fontMatrix when parsing; use */
/* unitsPerEm instead. */
/* TODO: check precision of this */
emRatio = cf2_intToFixed( 1000 ) / unitsPerEm;
font->stdVW = cf2_getStdVW( decoder );
 
if ( font->stdVW <= 0 )
font->stdVW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
 
if ( boldenX > 0 )
{
/* Ensure that boldenX is at least 1 pixel for synthetic bold font */
/* (similar to what Avalon does) */
boldenX = FT_MAX( boldenX,
FT_DivFix( cf2_intToFixed( unitsPerEm ), ppem ) );
 
/* Synthetic emboldening adds at least 1 pixel to darkenX, while */
/* stem darkening adds at most half pixel. Since the purpose of */
/* stem darkening (readability at small sizes) is met with */
/* synthetic emboldening, no need to add stem darkening for a */
/* synthetic bold font. */
cf2_computeDarkening( emRatio,
ppem,
font->stdVW,
&font->darkenX,
boldenX,
FALSE );
}
else
cf2_computeDarkening( emRatio,
ppem,
font->stdVW,
&font->darkenX,
0,
font->stemDarkened );
 
#if 0
/* since hstem is measured in the y-direction, we use the `d' member */
/* of the fontMatrix */
/* TODO: use the same units per em as above; check this */
emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->d );
#endif
 
/* set the default stem width, because it must be the same for all */
/* family members; */
/* choose a constant for StdHW that depends on font contrast */
stdHW = cf2_getStdHW( decoder );
 
if ( stdHW > 0 && font->stdVW > 2 * stdHW )
font->stdHW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
else
{
/* low contrast font gets less hstem darkening */
font->stdHW = FT_DivFix( cf2_intToFixed( 110 ), emRatio );
}
 
cf2_computeDarkening( emRatio,
ppem,
font->stdHW,
&font->darkenY,
boldenY,
font->stemDarkened );
 
if ( font->darkenX != 0 || font->darkenY != 0 )
font->darkened = TRUE;
else
font->darkened = FALSE;
 
font->reverseWinding = FALSE; /* initial expectation is CCW */
 
/* compute blue zones for this instance */
cf2_blues_init( &font->blues, font );
}
}
 
 
/* equivalent to AdobeGetOutline */
FT_LOCAL_DEF( FT_Error )
cf2_getGlyphOutline( CF2_Font font,
CF2_Buffer charstring,
const CF2_Matrix* transform,
CF2_F16Dot16* glyphWidth )
{
FT_Error lastError = FT_Err_Ok;
 
FT_Vector translation;
 
#if 0
FT_Vector advancePoint;
#endif
 
CF2_Fixed advWidth = 0;
FT_Bool needWinding;
 
 
/* Note: use both integer and fraction for outlines. This allows bbox */
/* to come out directly. */
 
translation.x = transform->tx;
translation.y = transform->ty;
 
/* set up values based on transform */
cf2_font_setup( font, transform );
if ( font->error )
goto exit; /* setup encountered an error */
 
/* reset darken direction */
font->reverseWinding = FALSE;
 
/* winding order only affects darkening */
needWinding = font->darkened;
 
while ( 1 )
{
/* reset output buffer */
cf2_outline_reset( &font->outline );
 
/* build the outline, passing the full translation */
cf2_interpT2CharString( font,
charstring,
(CF2_OutlineCallbacks)&font->outline,
&translation,
FALSE,
0,
0,
&advWidth );
 
if ( font->error )
goto exit;
 
if ( !needWinding )
break;
 
/* check winding order */
if ( font->outline.root.windingMomentum >= 0 ) /* CFF is CCW */
break;
 
/* invert darkening and render again */
/* TODO: this should be a parameter to getOutline-computeOffset */
font->reverseWinding = TRUE;
 
needWinding = FALSE; /* exit after next iteration */
}
 
/* finish storing client outline */
cf2_outline_close( &font->outline );
 
exit:
/* FreeType just wants the advance width; there is no translation */
*glyphWidth = advWidth;
 
/* free resources and collect errors from objects we've used */
cf2_setError( &font->error, lastError );
 
return font->error;
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2font.h
0,0 → 1,114
/***************************************************************************/
/* */
/* cf2font.h */
/* */
/* Adobe's code for font instances (specification). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2FONT_H__
#define __CF2FONT_H__
 
 
#include "cf2ft.h"
#include "cf2blues.h"
 
 
FT_BEGIN_HEADER
 
 
#define CF2_OPERAND_STACK_SIZE 48
#define CF2_MAX_SUBR 10 /* maximum subroutine nesting */
 
 
/* typedef is in `cf2glue.h' */
struct CF2_FontRec_
{
FT_Memory memory;
FT_Error error; /* shared error for this instance */
 
CF2_RenderingFlags renderingFlags;
 
/* variables that depend on Transform: */
/* the following have zero translation; */
/* inner * outer = font * original */
 
CF2_Matrix currentTransform; /* original client matrix */
CF2_Matrix innerTransform; /* for hinting; erect, scaled */
CF2_Matrix outerTransform; /* post hinting; includes rotations */
CF2_Fixed ppem; /* transform-dependent */
 
CF2_Int unitsPerEm;
 
CF2_Fixed syntheticEmboldeningAmountX; /* character space units */
CF2_Fixed syntheticEmboldeningAmountY; /* character space units */
 
/* FreeType related members */
CF2_OutlineRec outline; /* freetype glyph outline functions */
CFF_Decoder* decoder;
CFF_SubFont lastSubfont; /* FreeType parsed data; */
/* top font or subfont */
 
/* these flags can vary from one call to the next */
FT_Bool hinted;
FT_Bool darkened; /* true if stemDarkened or synthetic bold */
/* i.e. darkenX != 0 || darkenY != 0 */
FT_Bool stemDarkened;
 
/* variables that depend on both FontDict and Transform */
CF2_Fixed stdVW; /* in character space; depends on dict entry */
CF2_Fixed stdHW; /* in character space; depends on dict entry */
CF2_Fixed darkenX; /* character space units */
CF2_Fixed darkenY; /* depends on transform */
/* and private dict (StdVW) */
FT_Bool reverseWinding; /* darken assuming */
/* counterclockwise winding */
 
CF2_BluesRec blues; /* computed zone data */
};
 
 
FT_LOCAL( FT_Error )
cf2_getGlyphOutline( CF2_Font font,
CF2_Buffer charstring,
const CF2_Matrix* transform,
CF2_F16Dot16* glyphWidth );
 
 
FT_END_HEADER
 
 
#endif /* __CF2FONT_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2ft.c
0,0 → 1,639
/***************************************************************************/
/* */
/* cf2ft.c */
/* */
/* FreeType Glue Component to Adobe's Interpreter (body). */
/* */
/* Copyright 2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H
 
#include "cf2font.h"
#include "cf2error.h"
 
 
#define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */
 
 
/*
* This check should avoid most internal overflow cases. Clients should
* generally respond to `Glyph_Too_Big' by getting a glyph outline
* at EM size, scaling it and filling it as a graphics operation.
*
*/
static FT_Error
cf2_checkTransform( const CF2_Matrix* transform,
CF2_Int unitsPerEm )
{
CF2_Fixed maxScale;
 
 
FT_ASSERT( unitsPerEm > 0 );
 
FT_ASSERT( transform->a > 0 && transform->d > 0 );
FT_ASSERT( transform->b == 0 && transform->c == 0 );
FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
 
if ( unitsPerEm > 0x7FFF )
return FT_THROW( Glyph_Too_Big );
 
maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
 
if ( transform->a > maxScale || transform->d > maxScale )
return FT_THROW( Glyph_Too_Big );
 
return FT_Err_Ok;
}
 
 
static void
cf2_setGlyphWidth( CF2_Outline outline,
CF2_Fixed width )
{
CFF_Decoder* decoder = outline->decoder;
 
 
FT_ASSERT( decoder );
 
decoder->glyph_width = cf2_fixedToInt( width );
}
 
 
/* Clean up font instance. */
static void
cf2_free_instance( void* ptr )
{
CF2_Font font = (CF2_Font)ptr;
 
 
if ( font )
{
FT_Memory memory = font->memory;
 
 
(void)memory;
}
}
 
 
/********************************************/
/* */
/* functions for handling client outline; */
/* FreeType uses coordinates in 26.6 format */
/* */
/********************************************/
 
static void
cf2_builder_moveTo( CF2_OutlineCallbacks callbacks,
const CF2_CallbackParams params )
{
/* downcast the object pointer */
CF2_Outline outline = (CF2_Outline)callbacks;
CFF_Builder* builder;
 
(void)params; /* only used in debug mode */
 
 
FT_ASSERT( outline && outline->decoder );
FT_ASSERT( params->op == CF2_PathOpMoveTo );
 
builder = &outline->decoder->builder;
 
/* note: two successive moves simply close the contour twice */
cff_builder_close_contour( builder );
builder->path_begun = 0;
}
 
 
static void
cf2_builder_lineTo( CF2_OutlineCallbacks callbacks,
const CF2_CallbackParams params )
{
/* downcast the object pointer */
CF2_Outline outline = (CF2_Outline)callbacks;
CFF_Builder* builder;
 
 
FT_ASSERT( outline && outline->decoder );
FT_ASSERT( params->op == CF2_PathOpLineTo );
 
builder = &outline->decoder->builder;
 
if ( !builder->path_begun )
{
/* record the move before the line; also check points and set */
/* `path_begun' */
cff_builder_start_point( builder,
params->pt0.x,
params->pt0.y );
}
 
/* `cff_builder_add_point1' includes a check_points call for one point */
cff_builder_add_point1( builder,
params->pt1.x,
params->pt1.y );
}
 
 
static void
cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks,
const CF2_CallbackParams params )
{
/* downcast the object pointer */
CF2_Outline outline = (CF2_Outline)callbacks;
CFF_Builder* builder;
 
 
FT_ASSERT( outline && outline->decoder );
FT_ASSERT( params->op == CF2_PathOpCubeTo );
 
builder = &outline->decoder->builder;
 
if ( !builder->path_begun )
{
/* record the move before the line; also check points and set */
/* `path_begun' */
cff_builder_start_point( builder,
params->pt0.x,
params->pt0.y );
}
 
/* prepare room for 3 points: 2 off-curve, 1 on-curve */
cff_check_points( builder, 3 );
 
cff_builder_add_point( builder,
params->pt1.x,
params->pt1.y, 0 );
cff_builder_add_point( builder,
params->pt2.x,
params->pt2.y, 0 );
cff_builder_add_point( builder,
params->pt3.x,
params->pt3.y, 1 );
}
 
 
static void
cf2_outline_init( CF2_Outline outline,
FT_Memory memory,
FT_Error* error )
{
FT_MEM_ZERO( outline, sizeof ( CF2_OutlineRec ) );
 
outline->root.memory = memory;
outline->root.error = error;
 
outline->root.moveTo = cf2_builder_moveTo;
outline->root.lineTo = cf2_builder_lineTo;
outline->root.cubeTo = cf2_builder_cubeTo;
}
 
 
/* get scaling and hint flag from GlyphSlot */
static void
cf2_getScaleAndHintFlag( CFF_Decoder* decoder,
CF2_Fixed* x_scale,
CF2_Fixed* y_scale,
FT_Bool* hinted,
FT_Bool* scaled )
{
FT_ASSERT( decoder && decoder->builder.glyph );
 
/* note: FreeType scale includes a factor of 64 */
*hinted = decoder->builder.glyph->hint;
*scaled = decoder->builder.glyph->scaled;
 
if ( *hinted )
{
*x_scale = FT_DivFix( decoder->builder.glyph->x_scale,
cf2_intToFixed( 64 ) );
*y_scale = FT_DivFix( decoder->builder.glyph->y_scale,
cf2_intToFixed( 64 ) );
}
else
{
/* for unhinted outlines, `cff_slot_load' does the scaling, */
/* thus render at `unity' scale */
 
*x_scale = 0x0400; /* 1/64 as 16.16 */
*y_scale = 0x0400;
}
}
 
 
/* get units per em from `FT_Face' */
/* TODO: should handle font matrix concatenation? */
static FT_UShort
cf2_getUnitsPerEm( CFF_Decoder* decoder )
{
FT_ASSERT( decoder && decoder->builder.face );
FT_ASSERT( decoder->builder.face->root.units_per_EM );
 
return decoder->builder.face->root.units_per_EM;
}
 
 
/* Main entry point: Render one glyph. */
FT_LOCAL_DEF( FT_Error )
cf2_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
FT_ULong charstring_len )
{
FT_Memory memory;
FT_Error error = FT_Err_Ok;
CF2_Font font;
 
 
FT_ASSERT( decoder && decoder->cff );
 
memory = decoder->builder.memory;
 
/* CF2 data is saved here across glyphs */
font = (CF2_Font)decoder->cff->cf2_instance.data;
 
/* on first glyph, allocate instance structure */
if ( decoder->cff->cf2_instance.data == NULL )
{
decoder->cff->cf2_instance.finalizer =
(FT_Generic_Finalizer)cf2_free_instance;
 
if ( FT_ALLOC( decoder->cff->cf2_instance.data,
sizeof ( CF2_FontRec ) ) )
return FT_THROW( Out_Of_Memory );
 
font = (CF2_Font)decoder->cff->cf2_instance.data;
 
font->memory = memory;
 
/* initialize a client outline, to be shared by each glyph rendered */
cf2_outline_init( &font->outline, font->memory, &font->error );
}
 
/* save decoder; it is a stack variable and will be different on each */
/* call */
font->decoder = decoder;
font->outline.decoder = decoder;
 
{
/* build parameters for Adobe engine */
 
CFF_Builder* builder = &decoder->builder;
CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face );
 
/* local error */
FT_Error error2 = FT_Err_Ok;
CF2_BufferRec buf;
CF2_Matrix transform;
CF2_F16Dot16 glyphWidth;
 
FT_Bool hinted;
FT_Bool scaled;
 
 
/* FreeType has already looked up the GID; convert to */
/* `RegionBuffer', assuming that the input has been validated */
FT_ASSERT( charstring_base + charstring_len >= charstring_base );
 
FT_ZERO( &buf );
buf.start =
buf.ptr = charstring_base;
buf.end = charstring_base + charstring_len;
 
FT_ZERO( &transform );
 
cf2_getScaleAndHintFlag( decoder,
&transform.a,
&transform.d,
&hinted,
&scaled );
 
font->renderingFlags = 0;
if ( hinted )
font->renderingFlags |= CF2_FlagsHinted;
if ( scaled && !driver->no_stem_darkening )
font->renderingFlags |= CF2_FlagsDarkened;
 
/* now get an outline for this glyph; */
/* also get units per em to validate scale */
font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
 
error2 = cf2_checkTransform( &transform, font->unitsPerEm );
if ( error2 )
return error2;
 
error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
if ( error2 )
return FT_ERR( Invalid_File_Format );
 
cf2_setGlyphWidth( &font->outline, glyphWidth );
 
return FT_Err_Ok;
}
}
 
 
/* get pointer to current FreeType subfont (based on current glyphID) */
FT_LOCAL_DEF( CFF_SubFont )
cf2_getSubfont( CFF_Decoder* decoder )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
return decoder->current_subfont;
}
 
 
/* get `y_ppem' from `CFF_Size' */
FT_LOCAL_DEF( CF2_Fixed )
cf2_getPpemY( CFF_Decoder* decoder )
{
FT_ASSERT( decoder &&
decoder->builder.face &&
decoder->builder.face->root.size );
FT_ASSERT( decoder->builder.face->root.size->metrics.y_ppem );
 
return cf2_intToFixed(
decoder->builder.face->root.size->metrics.y_ppem );
}
 
 
/* get standard stem widths for the current subfont; */
/* FreeType stores these as integer font units */
/* (note: variable names seem swapped) */
FT_LOCAL_DEF( CF2_Fixed )
cf2_getStdVW( CFF_Decoder* decoder )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
return cf2_intToFixed(
decoder->current_subfont->private_dict.standard_height );
}
 
 
FT_LOCAL_DEF( CF2_Fixed )
cf2_getStdHW( CFF_Decoder* decoder )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
return cf2_intToFixed(
decoder->current_subfont->private_dict.standard_width );
}
 
 
/* note: FreeType stores 1000 times the actual value for `BlueScale' */
FT_LOCAL_DEF( void )
cf2_getBlueMetrics( CFF_Decoder* decoder,
CF2_Fixed* blueScale,
CF2_Fixed* blueShift,
CF2_Fixed* blueFuzz )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
*blueScale = FT_DivFix(
decoder->current_subfont->private_dict.blue_scale,
cf2_intToFixed( 1000 ) );
*blueShift = cf2_intToFixed(
decoder->current_subfont->private_dict.blue_shift );
*blueFuzz = cf2_intToFixed(
decoder->current_subfont->private_dict.blue_fuzz );
}
 
 
/* get blue values counts and arrays; the FreeType parser has validated */
/* the counts and verified that each is an even number */
FT_LOCAL_DEF( void )
cf2_getBlueValues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
*count = decoder->current_subfont->private_dict.num_blue_values;
*data = (FT_Pos*)
&decoder->current_subfont->private_dict.blue_values;
}
 
 
FT_LOCAL_DEF( void )
cf2_getOtherBlues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
*count = decoder->current_subfont->private_dict.num_other_blues;
*data = (FT_Pos*)
&decoder->current_subfont->private_dict.other_blues;
}
 
 
FT_LOCAL_DEF( void )
cf2_getFamilyBlues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
*count = decoder->current_subfont->private_dict.num_family_blues;
*data = (FT_Pos*)
&decoder->current_subfont->private_dict.family_blues;
}
 
 
FT_LOCAL_DEF( void )
cf2_getFamilyOtherBlues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
*count = decoder->current_subfont->private_dict.num_family_other_blues;
*data = (FT_Pos*)
&decoder->current_subfont->private_dict.family_other_blues;
}
 
 
FT_LOCAL_DEF( CF2_Int )
cf2_getLanguageGroup( CFF_Decoder* decoder )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
return decoder->current_subfont->private_dict.language_group;
}
 
 
/* convert unbiased subroutine index to `CF2_Buffer' and */
/* return 0 on success */
FT_LOCAL_DEF( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
CF2_UInt idx,
CF2_Buffer buf )
{
FT_ASSERT( decoder && decoder->globals );
 
FT_ZERO( buf );
 
idx += decoder->globals_bias;
if ( idx >= decoder->num_globals )
return TRUE; /* error */
 
buf->start =
buf->ptr = decoder->globals[idx];
buf->end = decoder->globals[idx + 1];
 
return FALSE; /* success */
}
 
 
/* convert AdobeStandardEncoding code to CF2_Buffer; */
/* used for seac component */
FT_LOCAL_DEF( FT_Error )
cf2_getSeacComponent( CFF_Decoder* decoder,
CF2_UInt code,
CF2_Buffer buf )
{
CF2_Int gid;
FT_Byte* charstring;
FT_ULong len;
FT_Error error;
 
 
FT_ASSERT( decoder );
 
FT_ZERO( buf );
 
gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
if ( gid < 0 )
return FT_THROW( Invalid_Glyph_Format );
 
error = cff_get_glyph_data( decoder->builder.face,
gid,
&charstring,
&len );
/* TODO: for now, just pass the FreeType error through */
if ( error )
return error;
 
/* assume input has been validated */
FT_ASSERT( charstring + len >= charstring );
 
buf->start = charstring;
buf->end = charstring + len;
buf->ptr = buf->start;
 
return FT_Err_Ok;
}
 
 
FT_LOCAL_DEF( void )
cf2_freeSeacComponent( CFF_Decoder* decoder,
CF2_Buffer buf )
{
FT_ASSERT( decoder );
 
cff_free_glyph_data( decoder->builder.face,
(FT_Byte**)&buf->start,
(FT_ULong)( buf->end - buf->start ) );
}
 
 
FT_LOCAL_DEF( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
CF2_UInt idx,
CF2_Buffer buf )
{
FT_ASSERT( decoder && decoder->locals );
 
FT_ZERO( buf );
 
idx += decoder->locals_bias;
if ( idx >= decoder->num_locals )
return TRUE; /* error */
 
buf->start =
buf->ptr = decoder->locals[idx];
buf->end = decoder->locals[idx + 1];
 
return FALSE; /* success */
}
 
 
FT_LOCAL_DEF( CF2_Fixed )
cf2_getDefaultWidthX( CFF_Decoder* decoder )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
return cf2_intToFixed(
decoder->current_subfont->private_dict.default_width );
}
 
 
FT_LOCAL_DEF( CF2_Fixed )
cf2_getNominalWidthX( CFF_Decoder* decoder )
{
FT_ASSERT( decoder && decoder->current_subfont );
 
return cf2_intToFixed(
decoder->current_subfont->private_dict.nominal_width );
}
 
 
FT_LOCAL_DEF( void )
cf2_outline_reset( CF2_Outline outline )
{
CFF_Decoder* decoder = outline->decoder;
 
 
FT_ASSERT( decoder );
 
outline->root.windingMomentum = 0;
 
FT_GlyphLoader_Rewind( decoder->builder.loader );
}
 
 
FT_LOCAL_DEF( void )
cf2_outline_close( CF2_Outline outline )
{
CFF_Decoder* decoder = outline->decoder;
 
 
FT_ASSERT( decoder );
 
cff_builder_close_contour( &decoder->builder );
 
FT_GlyphLoader_Add( decoder->builder.loader );
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2ft.h
0,0 → 1,147
/***************************************************************************/
/* */
/* cf2ft.h */
/* */
/* FreeType Glue Component to Adobe's Interpreter (specification). */
/* */
/* Copyright 2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2FT_H__
#define __CF2FT_H__
 
 
#include "cf2types.h"
 
 
/* TODO: disable asserts for now */
#define CF2_NDEBUG
 
 
#include FT_SYSTEM_H
 
#include "cf2glue.h"
#include "cffgload.h" /* for CFF_Decoder */
 
 
FT_BEGIN_HEADER
 
 
FT_LOCAL( FT_Error )
cf2_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
FT_ULong charstring_len );
 
FT_LOCAL( CFF_SubFont )
cf2_getSubfont( CFF_Decoder* decoder );
 
 
FT_LOCAL( CF2_Fixed )
cf2_getPpemY( CFF_Decoder* decoder );
FT_LOCAL( CF2_Fixed )
cf2_getStdVW( CFF_Decoder* decoder );
FT_LOCAL( CF2_Fixed )
cf2_getStdHW( CFF_Decoder* decoder );
 
FT_LOCAL( void )
cf2_getBlueMetrics( CFF_Decoder* decoder,
CF2_Fixed* blueScale,
CF2_Fixed* blueShift,
CF2_Fixed* blueFuzz );
FT_LOCAL( void )
cf2_getBlueValues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data );
FT_LOCAL( void )
cf2_getOtherBlues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data );
FT_LOCAL( void )
cf2_getFamilyBlues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data );
FT_LOCAL( void )
cf2_getFamilyOtherBlues( CFF_Decoder* decoder,
size_t* count,
FT_Pos* *data );
 
FT_LOCAL( CF2_Int )
cf2_getLanguageGroup( CFF_Decoder* decoder );
 
FT_LOCAL( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
CF2_UInt idx,
CF2_Buffer buf );
FT_LOCAL( FT_Error )
cf2_getSeacComponent( CFF_Decoder* decoder,
CF2_UInt code,
CF2_Buffer buf );
FT_LOCAL( void )
cf2_freeSeacComponent( CFF_Decoder* decoder,
CF2_Buffer buf );
FT_LOCAL( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
CF2_UInt idx,
CF2_Buffer buf );
 
FT_LOCAL( CF2_Fixed )
cf2_getDefaultWidthX( CFF_Decoder* decoder );
FT_LOCAL( CF2_Fixed )
cf2_getNominalWidthX( CFF_Decoder* decoder );
 
 
/*
* FreeType client outline
*
* process output from the charstring interpreter
*/
typedef struct CF2_OutlineRec_
{
CF2_OutlineCallbacksRec root; /* base class must be first */
CFF_Decoder* decoder;
 
} CF2_OutlineRec, *CF2_Outline;
 
 
FT_LOCAL( void )
cf2_outline_reset( CF2_Outline outline );
FT_LOCAL( void )
cf2_outline_close( CF2_Outline outline );
 
 
FT_END_HEADER
 
 
#endif /* __CF2FT_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2glue.h
0,0 → 1,144
/***************************************************************************/
/* */
/* cf2glue.h */
/* */
/* Adobe's code for shared stuff (specification only). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2GLUE_H__
#define __CF2GLUE_H__
 
 
/* common includes for other modules */
#include "cf2error.h"
#include "cf2fixed.h"
#include "cf2arrst.h"
#include "cf2read.h"
 
 
FT_BEGIN_HEADER
 
 
/* rendering parameters */
 
/* apply hints to rendered glyphs */
#define CF2_FlagsHinted 1
/* for testing */
#define CF2_FlagsDarkened 2
 
/* type for holding the flags */
typedef CF2_Int CF2_RenderingFlags;
 
 
/* elements of a glyph outline */
typedef enum CF2_PathOp_
{
CF2_PathOpMoveTo = 1, /* change the current point */
CF2_PathOpLineTo = 2, /* line */
CF2_PathOpQuadTo = 3, /* quadratic curve */
CF2_PathOpCubeTo = 4 /* cubic curve */
 
} CF2_PathOp;
 
 
/* a matrix of fixed point values */
typedef struct CF2_Matrix_
{
CF2_F16Dot16 a;
CF2_F16Dot16 b;
CF2_F16Dot16 c;
CF2_F16Dot16 d;
CF2_F16Dot16 tx;
CF2_F16Dot16 ty;
 
} CF2_Matrix;
 
 
/* these typedefs are needed by more than one header file */
/* and gcc compiler doesn't allow redefinition */
typedef struct CF2_FontRec_ CF2_FontRec, *CF2_Font;
typedef struct CF2_HintRec_ CF2_HintRec, *CF2_Hint;
 
 
/* A common structure for all callback parameters. */
/* */
/* Some members may be unused. For example, `pt0' is not used for */
/* `moveTo' and `pt3' is not used for `quadTo'. The initial point `pt0' */
/* is included for each path element for generality; curve conversions */
/* need it. The `op' parameter allows one function to handle multiple */
/* element types. */
 
typedef struct CF2_CallbackParamsRec_
{
FT_Vector pt0;
FT_Vector pt1;
FT_Vector pt2;
FT_Vector pt3;
 
CF2_Int op;
 
} CF2_CallbackParamsRec, *CF2_CallbackParams;
 
 
/* forward reference */
typedef struct CF2_OutlineCallbacksRec_ CF2_OutlineCallbacksRec,
*CF2_OutlineCallbacks;
 
/* callback function pointers */
typedef void
(*CF2_Callback_Type)( CF2_OutlineCallbacks callbacks,
const CF2_CallbackParams params );
 
 
struct CF2_OutlineCallbacksRec_
{
CF2_Callback_Type moveTo;
CF2_Callback_Type lineTo;
CF2_Callback_Type quadTo;
CF2_Callback_Type cubeTo;
 
CF2_Int windingMomentum; /* for winding order detection */
 
FT_Memory memory;
FT_Error* error;
};
 
 
FT_END_HEADER
 
 
#endif /* __CF2GLUE_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2hints.c
0,0 → 1,1734
/***************************************************************************/
/* */
/* cf2hints.c */
/* */
/* Adobe's code for handling CFF hints (body). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H
 
#include "cf2glue.h"
#include "cf2font.h"
#include "cf2hints.h"
#include "cf2intrp.h"
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cf2hints
 
 
typedef struct CF2_HintMoveRec_
{
size_t j; /* index of upper hint map edge */
CF2_Fixed moveUp; /* adjustment to optimum position */
 
} CF2_HintMoveRec, *CF2_HintMove;
 
 
/* Compute angular momentum for winding order detection. It is called */
/* for all lines and curves, but not necessarily in element order. */
static CF2_Int
cf2_getWindingMomentum( CF2_Fixed x1,
CF2_Fixed y1,
CF2_Fixed x2,
CF2_Fixed y2 )
{
/* cross product of pt1 position from origin with pt2 position from */
/* pt1; we reduce the precision so that the result fits into 32 bits */
 
return ( x1 >> 16 ) * ( ( y2 - y1 ) >> 16 ) -
( y1 >> 16 ) * ( ( x2 - x1 ) >> 16 );
}
 
 
/*
* Construct from a StemHint; this is used as a parameter to
* `cf2_blues_capture'.
* `hintOrigin' is the character space displacement of a seac accent.
* Adjust stem hint for darkening here.
*
*/
static void
cf2_hint_init( CF2_Hint hint,
const CF2_ArrStack stemHintArray,
size_t indexStemHint,
const CF2_Font font,
CF2_Fixed hintOrigin,
CF2_Fixed scale,
FT_Bool bottom )
{
CF2_Fixed width;
const CF2_StemHintRec* stemHint;
 
 
FT_ZERO( hint );
 
stemHint = (const CF2_StemHintRec*)cf2_arrstack_getPointer(
stemHintArray,
indexStemHint );
 
width = stemHint->max - stemHint->min;
 
if ( width == cf2_intToFixed( -21 ) )
{
/* ghost bottom */
 
if ( bottom )
{
hint->csCoord = stemHint->max;
hint->flags = CF2_GhostBottom;
}
else
hint->flags = 0;
}
 
else if ( width == cf2_intToFixed( -20 ) )
{
/* ghost top */
 
if ( bottom )
hint->flags = 0;
else
{
hint->csCoord = stemHint->min;
hint->flags = CF2_GhostTop;
}
}
 
else if ( width < 0 )
{
/* inverted pair */
 
/*
* Hints with negative widths were produced by an early version of a
* non-Adobe font tool. The Type 2 spec allows edge (ghost) hints
* with negative widths, but says
*
* All other negative widths have undefined meaning.
*
* CoolType has a silent workaround that negates the hint width; for
* permissive mode, we do the same here.
*
* Note: Such fonts cannot use ghost hints, but should otherwise work.
* Note: Some poor hints in our faux fonts can produce negative
* widths at some blends. For example, see a light weight of
* `u' in ASerifMM.
*
*/
if ( bottom )
{
hint->csCoord = stemHint->max;
hint->flags = CF2_PairBottom;
}
else
{
hint->csCoord = stemHint->min;
hint->flags = CF2_PairTop;
}
}
 
else
{
/* normal pair */
 
if ( bottom )
{
hint->csCoord = stemHint->min;
hint->flags = CF2_PairBottom;
}
else
{
hint->csCoord = stemHint->max;
hint->flags = CF2_PairTop;
}
}
 
/* Now that ghost hints have been detected, adjust this edge for */
/* darkening. Bottoms are not changed; tops are incremented by twice */
/* `darkenY'. */
if ( cf2_hint_isTop( hint ) )
hint->csCoord += 2 * font->darkenY;
 
hint->csCoord += hintOrigin;
hint->scale = scale;
hint->index = indexStemHint; /* index in original stem hint array */
 
/* if original stem hint has been used, use the same position */
if ( hint->flags != 0 && stemHint->used )
{
if ( cf2_hint_isTop( hint ) )
hint->dsCoord = stemHint->maxDS;
else
hint->dsCoord = stemHint->minDS;
 
cf2_hint_lock( hint );
}
else
hint->dsCoord = FT_MulFix( hint->csCoord, scale );
}
 
 
/* initialize an invalid hint map element */
static void
cf2_hint_initZero( CF2_Hint hint )
{
FT_ZERO( hint );
}
 
 
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isValid( const CF2_Hint hint )
{
return (FT_Bool)( hint->flags != 0 );
}
 
 
static FT_Bool
cf2_hint_isPair( const CF2_Hint hint )
{
return (FT_Bool)( ( hint->flags &
( CF2_PairBottom | CF2_PairTop ) ) != 0 );
}
 
 
static FT_Bool
cf2_hint_isPairTop( const CF2_Hint hint )
{
return (FT_Bool)( ( hint->flags & CF2_PairTop ) != 0 );
}
 
 
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isTop( const CF2_Hint hint )
{
return (FT_Bool)( ( hint->flags &
( CF2_PairTop | CF2_GhostTop ) ) != 0 );
}
 
 
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isBottom( const CF2_Hint hint )
{
return (FT_Bool)( ( hint->flags &
( CF2_PairBottom | CF2_GhostBottom ) ) != 0 );
}
 
 
static FT_Bool
cf2_hint_isLocked( const CF2_Hint hint )
{
return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 );
}
 
 
static FT_Bool
cf2_hint_isSynthetic( const CF2_Hint hint )
{
return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 );
}
 
 
FT_LOCAL_DEF( void )
cf2_hint_lock( CF2_Hint hint )
{
hint->flags |= CF2_Locked;
}
 
 
FT_LOCAL_DEF( void )
cf2_hintmap_init( CF2_HintMap hintmap,
CF2_Font font,
CF2_HintMap initialMap,
CF2_ArrStack hintMoves,
CF2_Fixed scale )
{
FT_ZERO( hintmap );
 
/* copy parameters from font instance */
hintmap->hinted = font->hinted;
hintmap->scale = scale;
hintmap->font = font;
hintmap->initialHintMap = initialMap;
/* will clear in `cf2_hintmap_adjustHints' */
hintmap->hintMoves = hintMoves;
}
 
 
static FT_Bool
cf2_hintmap_isValid( const CF2_HintMap hintmap )
{
return hintmap->isValid;
}
 
 
/* transform character space coordinate to device space using hint map */
static CF2_Fixed
cf2_hintmap_map( CF2_HintMap hintmap,
CF2_Fixed csCoord )
{
FT_ASSERT( hintmap->isValid ); /* must call Build before Map */
FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
 
if ( hintmap->count == 0 || ! hintmap->hinted )
{
/* there are no hints; use uniform scale and zero offset */
return FT_MulFix( csCoord, hintmap->scale );
}
else
{
/* start linear search from last hit */
CF2_UInt i = hintmap->lastIndex;
 
 
/* search up */
while ( i < hintmap->count - 1 &&
csCoord >= hintmap->edge[i + 1].csCoord )
i += 1;
 
/* search down */
while ( i > 0 && csCoord < hintmap->edge[i].csCoord )
i -= 1;
 
hintmap->lastIndex = i;
 
if ( i == 0 && csCoord < hintmap->edge[0].csCoord )
{
/* special case for points below first edge: use uniform scale */
return FT_MulFix( csCoord - hintmap->edge[0].csCoord,
hintmap->scale ) +
hintmap->edge[0].dsCoord;
}
else
{
/*
* Note: entries with duplicate csCoord are allowed.
* Use edge[i], the highest entry where csCoord >= entry[i].csCoord
*/
return FT_MulFix( csCoord - hintmap->edge[i].csCoord,
hintmap->edge[i].scale ) +
hintmap->edge[i].dsCoord;
}
}
}
 
 
/*
* This hinting policy moves a hint pair in device space so that one of
* its two edges is on a device pixel boundary (its fractional part is
* zero). `cf2_hintmap_insertHint' guarantees no overlap in CS
* space. Ensure here that there is no overlap in DS.
*
* In the first pass, edges are adjusted relative to adjacent hints.
* Those that are below have already been adjusted. Those that are
* above have not yet been adjusted. If a hint above blocks an
* adjustment to an optimal position, we will try again in a second
* pass. The second pass is top-down.
*
*/
 
static void
cf2_hintmap_adjustHints( CF2_HintMap hintmap )
{
size_t i, j;
 
 
cf2_arrstack_clear( hintmap->hintMoves ); /* working storage */
 
/*
* First pass is bottom-up (font hint order) without look-ahead.
* Locked edges are already adjusted.
* Unlocked edges begin with dsCoord from `initialHintMap'.
* Save edges that are not optimally adjusted in `hintMoves' array,
* and process them in second pass.
*/
 
for ( i = 0; i < hintmap->count; i++ )
{
FT_Bool isPair = cf2_hint_isPair( &hintmap->edge[i] );
 
 
/* index of upper edge (same value for ghost hint) */
j = isPair ? i + 1 : i;
 
FT_ASSERT( j < hintmap->count );
FT_ASSERT( cf2_hint_isValid( &hintmap->edge[i] ) );
FT_ASSERT( cf2_hint_isValid( &hintmap->edge[j] ) );
FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) ==
cf2_hint_isLocked( &hintmap->edge[j] ) );
 
if ( !cf2_hint_isLocked( &hintmap->edge[i] ) )
{
/* hint edge is not locked, we can adjust it */
CF2_Fixed fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord );
CF2_Fixed fracUp = cf2_fixedFraction( hintmap->edge[j].dsCoord );
 
/* calculate all four possibilities; moves down are negative */
CF2_Fixed downMoveDown = 0 - fracDown;
CF2_Fixed upMoveDown = 0 - fracUp;
CF2_Fixed downMoveUp = fracDown == 0
? 0
: cf2_intToFixed( 1 ) - fracDown;
CF2_Fixed upMoveUp = fracUp == 0
? 0
: cf2_intToFixed( 1 ) - fracUp;
 
/* smallest move up */
CF2_Fixed moveUp = FT_MIN( downMoveUp, upMoveUp );
/* smallest move down */
CF2_Fixed moveDown = FT_MAX( downMoveDown, upMoveDown );
 
/* final amount to move edge or edge pair */
CF2_Fixed move;
 
CF2_Fixed downMinCounter = CF2_MIN_COUNTER;
CF2_Fixed upMinCounter = CF2_MIN_COUNTER;
FT_Bool saveEdge = FALSE;
 
 
/* minimum counter constraint doesn't apply when adjacent edges */
/* are synthetic */
/* TODO: doesn't seem a big effect; for now, reduce the code */
#if 0
if ( i == 0 ||
cf2_hint_isSynthetic( &hintmap->edge[i - 1] ) )
downMinCounter = 0;
 
if ( j >= hintmap->count - 1 ||
cf2_hint_isSynthetic( &hintmap->edge[j + 1] ) )
upMinCounter = 0;
#endif
 
/* is there room to move up? */
/* there is if we are at top of array or the next edge is at or */
/* beyond proposed move up? */
if ( j >= hintmap->count - 1 ||
hintmap->edge[j + 1].dsCoord >=
hintmap->edge[j].dsCoord + moveUp + upMinCounter )
{
/* there is room to move up; is there also room to move down? */
if ( i == 0 ||
hintmap->edge[i - 1].dsCoord <=
hintmap->edge[i].dsCoord + moveDown - downMinCounter )
{
/* move smaller absolute amount */
move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */
}
else
move = moveUp;
}
else
{
/* is there room to move down? */
if ( i == 0 ||
hintmap->edge[i - 1].dsCoord <=
hintmap->edge[i].dsCoord + moveDown - downMinCounter )
{
move = moveDown;
/* true if non-optimum move */
saveEdge = (FT_Bool)( moveUp < -moveDown );
}
else
{
/* no room to move either way without overlapping or reducing */
/* the counter too much */
move = 0;
saveEdge = TRUE;
}
}
 
/* Identify non-moves and moves down that aren't optimal, and save */
/* them for second pass. */
/* Do this only if there is an unlocked edge above (which could */
/* possibly move). */
if ( saveEdge &&
j < hintmap->count - 1 &&
!cf2_hint_isLocked( &hintmap->edge[j + 1] ) )
{
CF2_HintMoveRec savedMove;
 
 
savedMove.j = j;
/* desired adjustment in second pass */
savedMove.moveUp = moveUp - move;
 
cf2_arrstack_push( hintmap->hintMoves, &savedMove );
}
 
/* move the edge(s) */
hintmap->edge[i].dsCoord += move;
if ( isPair )
hintmap->edge[j].dsCoord += move;
}
 
/* assert there are no overlaps in device space */
FT_ASSERT( i == 0 ||
hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord );
FT_ASSERT( i < j ||
hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord );
 
/* adjust the scales, avoiding divide by zero */
if ( i > 0 )
{
if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord )
hintmap->edge[i - 1].scale =
FT_DivFix(
hintmap->edge[i].dsCoord - hintmap->edge[i - 1].dsCoord,
hintmap->edge[i].csCoord - hintmap->edge[i - 1].csCoord );
}
 
if ( isPair )
{
if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord )
hintmap->edge[j - 1].scale =
FT_DivFix(
hintmap->edge[j].dsCoord - hintmap->edge[j - 1].dsCoord,
hintmap->edge[j].csCoord - hintmap->edge[j - 1].csCoord );
 
i += 1; /* skip upper edge on next loop */
}
}
 
/* second pass tries to move non-optimal hints up, in case there is */
/* room now */
for ( i = cf2_arrstack_size( hintmap->hintMoves ); i > 0; i-- )
{
CF2_HintMove hintMove = (CF2_HintMove)
cf2_arrstack_getPointer( hintmap->hintMoves, i - 1 );
 
 
j = hintMove->j;
 
/* this was tested before the push, above */
FT_ASSERT( j < hintmap->count - 1 );
 
/* is there room to move up? */
if ( hintmap->edge[j + 1].dsCoord >=
hintmap->edge[j].dsCoord + hintMove->moveUp + CF2_MIN_COUNTER )
{
/* there is more room now, move edge up */
hintmap->edge[j].dsCoord += hintMove->moveUp;
 
if ( cf2_hint_isPair( &hintmap->edge[j] ) )
{
FT_ASSERT( j > 0 );
hintmap->edge[j - 1].dsCoord += hintMove->moveUp;
}
}
}
}
 
 
/* insert hint edges into map, sorted by csCoord */
static void
cf2_hintmap_insertHint( CF2_HintMap hintmap,
CF2_Hint bottomHintEdge,
CF2_Hint topHintEdge )
{
CF2_UInt indexInsert;
 
/* set default values, then check for edge hints */
FT_Bool isPair = TRUE;
CF2_Hint firstHintEdge = bottomHintEdge;
CF2_Hint secondHintEdge = topHintEdge;
 
 
/* one or none of the input params may be invalid when dealing with */
/* edge hints; at least one edge must be valid */
FT_ASSERT( cf2_hint_isValid( bottomHintEdge ) ||
cf2_hint_isValid( topHintEdge ) );
 
/* determine how many and which edges to insert */
if ( !cf2_hint_isValid( bottomHintEdge ) )
{
/* insert only the top edge */
firstHintEdge = topHintEdge;
isPair = FALSE;
}
else if ( !cf2_hint_isValid( topHintEdge ) )
{
/* insert only the bottom edge */
isPair = FALSE;
}
 
/* paired edges must be in proper order */
FT_ASSERT( !isPair ||
topHintEdge->csCoord >= bottomHintEdge->csCoord );
 
/* linear search to find index value of insertion point */
indexInsert = 0;
for ( ; indexInsert < hintmap->count; indexInsert++ )
{
if ( hintmap->edge[indexInsert].csCoord > firstHintEdge->csCoord )
break;
}
 
/*
* Discard any hints that overlap in character space. Most often,
* this is while building the initial map, but in theory, it can also
* occur because of darkening.
*
*/
if ( indexInsert < hintmap->count )
{
/* we are inserting before an existing edge: */
/* verify that a new pair does not straddle the next edge */
if ( isPair &&
hintmap->edge[indexInsert].csCoord < secondHintEdge->csCoord )
return; /* ignore overlapping stem hint */
 
/* verify that we are not inserting between paired edges */
if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) )
return; /* ignore overlapping stem hint */
}
 
/* recompute device space locations using initial hint map */
if ( cf2_hintmap_isValid( hintmap->initialHintMap ) &&
!cf2_hint_isLocked( firstHintEdge ) )
{
if ( isPair )
{
/* Use hint map to position the center of stem, and nominal scale */
/* to position the two edges. This preserves the stem width. */
CF2_Fixed midpoint = cf2_hintmap_map(
hintmap->initialHintMap,
( secondHintEdge->csCoord +
firstHintEdge->csCoord ) / 2 );
CF2_Fixed halfWidth = FT_MulFix(
( secondHintEdge->csCoord -
firstHintEdge->csCoord ) / 2,
hintmap->scale );
 
 
firstHintEdge->dsCoord = midpoint - halfWidth;
secondHintEdge->dsCoord = midpoint + halfWidth;
}
else
firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap,
firstHintEdge->csCoord );
}
 
/* discard any hints that overlap in device space; this can occur */
/* because locked hints have been moved to align with blue zones */
if ( indexInsert > 0 )
{
/* we are inserting after an existing edge */
if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord )
return;
}
 
if ( indexInsert < hintmap->count )
{
/* we are inserting before an existing edge */
if ( isPair )
{
if ( secondHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
return;
}
else
{
if ( firstHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
return;
}
}
 
/* make room to insert */
{
CF2_Int iSrc = hintmap->count - 1;
CF2_Int iDst = isPair ? hintmap->count + 1 : hintmap->count;
 
CF2_Int count = hintmap->count - indexInsert;
 
 
if ( iDst >= CF2_MAX_HINT_EDGES )
{
FT_TRACE4(( "cf2_hintmap_insertHint: too many hintmaps\n" ));
return;
}
 
while ( count-- )
hintmap->edge[iDst--] = hintmap->edge[iSrc--];
 
/* insert first edge */
hintmap->edge[indexInsert] = *firstHintEdge; /* copy struct */
hintmap->count += 1;
 
if ( isPair )
{
/* insert second edge */
hintmap->edge[indexInsert + 1] = *secondHintEdge; /* copy struct */
hintmap->count += 1;
}
}
 
return;
}
 
 
/*
* Build a map from hints and mask.
*
* This function may recur one level if `hintmap->initialHintMap' is not yet
* valid.
* If `initialMap' is true, simply build initial map.
*
* Synthetic hints are used in two ways. A hint at zero is inserted, if
* needed, in the initial hint map, to prevent translations from
* propagating across the origin. If synthetic em box hints are enabled
* for ideographic dictionaries, then they are inserted in all hint
* maps, including the initial one.
*
*/
FT_LOCAL_DEF( void )
cf2_hintmap_build( CF2_HintMap hintmap,
CF2_ArrStack hStemHintArray,
CF2_ArrStack vStemHintArray,
CF2_HintMask hintMask,
CF2_Fixed hintOrigin,
FT_Bool initialMap )
{
FT_Byte* maskPtr;
 
CF2_Font font = hintmap->font;
CF2_HintMaskRec tempHintMask;
 
size_t bitCount, i;
FT_Byte maskByte;
 
 
/* check whether initial map is constructed */
if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) )
{
/* make recursive call with initialHintMap and temporary mask; */
/* temporary mask will get all bits set, below */
cf2_hintmask_init( &tempHintMask, hintMask->error );
cf2_hintmap_build( hintmap->initialHintMap,
hStemHintArray,
vStemHintArray,
&tempHintMask,
hintOrigin,
TRUE );
}
 
if ( !cf2_hintmask_isValid( hintMask ) )
{
/* without a hint mask, assume all hints are active */
cf2_hintmask_setAll( hintMask,
cf2_arrstack_size( hStemHintArray ) +
cf2_arrstack_size( vStemHintArray ) );
}
 
/* begin by clearing the map */
hintmap->count = 0;
hintmap->lastIndex = 0;
 
/* make a copy of the hint mask so we can modify it */
tempHintMask = *hintMask;
maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
 
/* use the hStem hints only, which are first in the mask */
/* TODO: compare this to cffhintmaskGetBitCount */
bitCount = cf2_arrstack_size( hStemHintArray );
 
/* synthetic embox hints get highest priority */
if ( font->blues.doEmBoxHints )
{
CF2_HintRec dummy;
 
 
cf2_hint_initZero( &dummy ); /* invalid hint map element */
 
/* ghost bottom */
cf2_hintmap_insertHint( hintmap,
&font->blues.emBoxBottomEdge,
&dummy );
/* ghost top */
cf2_hintmap_insertHint( hintmap,
&dummy,
&font->blues.emBoxTopEdge );
}
 
/* insert hints captured by a blue zone or already locked (higher */
/* priority) */
for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
{
if ( maskByte & *maskPtr )
{
/* expand StemHint into two `CF2_Hint' elements */
CF2_HintRec bottomHintEdge, topHintEdge;
 
 
cf2_hint_init( &bottomHintEdge,
hStemHintArray,
i,
font,
hintOrigin,
hintmap->scale,
TRUE /* bottom */ );
cf2_hint_init( &topHintEdge,
hStemHintArray,
i,
font,
hintOrigin,
hintmap->scale,
FALSE /* top */ );
 
if ( cf2_hint_isLocked( &bottomHintEdge ) ||
cf2_hint_isLocked( &topHintEdge ) ||
cf2_blues_capture( &font->blues,
&bottomHintEdge,
&topHintEdge ) )
{
/* insert captured hint into map */
cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
 
*maskPtr &= ~maskByte; /* turn off the bit for this hint */
}
}
 
if ( ( i & 7 ) == 7 )
{
/* move to next mask byte */
maskPtr++;
maskByte = 0x80;
}
else
maskByte >>= 1;
}
 
/* initial hint map includes only captured hints plus maybe one at 0 */
 
/*
* TODO: There is a problem here because we are trying to build a
* single hint map containing all captured hints. It is
* possible for there to be conflicts between captured hints,
* either because of darkening or because the hints are in
* separate hint zones (we are ignoring hint zones for the
* initial map). An example of the latter is MinionPro-Regular
* v2.030 glyph 883 (Greek Capital Alpha with Psili) at 15ppem.
* A stem hint for the psili conflicts with the top edge hint
* for the base character. The stem hint gets priority because
* of its sort order. In glyph 884 (Greek Capital Alpha with
* Psili and Oxia), the top of the base character gets a stem
* hint, and the psili does not. This creates different initial
* maps for the two glyphs resulting in different renderings of
* the base character. Will probably defer this either as not
* worth the cost or as a font bug. I don't think there is any
* good reason for an accent to be captured by an alignment
* zone. -darnold 2/12/10
*/
 
if ( initialMap )
{
/* Apply a heuristic that inserts a point for (0,0), unless it's */
/* already covered by a mapping. This locks the baseline for glyphs */
/* that have no baseline hints. */
 
if ( hintmap->count == 0 ||
hintmap->edge[0].csCoord > 0 ||
hintmap->edge[hintmap->count - 1].csCoord < 0 )
{
/* all edges are above 0 or all edges are below 0; */
/* construct a locked edge hint at 0 */
 
CF2_HintRec edge, invalid;
 
 
cf2_hint_initZero( &edge );
 
edge.flags = CF2_GhostBottom |
CF2_Locked |
CF2_Synthetic;
edge.scale = hintmap->scale;
 
cf2_hint_initZero( &invalid );
cf2_hintmap_insertHint( hintmap, &edge, &invalid );
}
}
else
{
/* insert remaining hints */
 
maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
 
for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
{
if ( maskByte & *maskPtr )
{
CF2_HintRec bottomHintEdge, topHintEdge;
 
 
cf2_hint_init( &bottomHintEdge,
hStemHintArray,
i,
font,
hintOrigin,
hintmap->scale,
TRUE /* bottom */ );
cf2_hint_init( &topHintEdge,
hStemHintArray,
i,
font,
hintOrigin,
hintmap->scale,
FALSE /* top */ );
 
cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
}
 
if ( ( i & 7 ) == 7 )
{
/* move to next mask byte */
maskPtr++;
maskByte = 0x80;
}
else
maskByte >>= 1;
}
}
 
/*
* Note: The following line is a convenient place to break when
* debugging hinting. Examine `hintmap->edge' for the list of
* enabled hints, then step over the call to see the effect of
* adjustment. We stop here first on the recursive call that
* creates the initial map, and then on each counter group and
* hint zone.
*/
 
/* adjust positions of hint edges that are not locked to blue zones */
cf2_hintmap_adjustHints( hintmap );
 
/* save the position of all hints that were used in this hint map; */
/* if we use them again, we'll locate them in the same position */
if ( !initialMap )
{
for ( i = 0; i < hintmap->count; i++ )
{
if ( !cf2_hint_isSynthetic( &hintmap->edge[i] ) )
{
/* Note: include both valid and invalid edges */
/* Note: top and bottom edges are copied back separately */
CF2_StemHint stemhint = (CF2_StemHint)
cf2_arrstack_getPointer( hStemHintArray,
hintmap->edge[i].index );
 
 
if ( cf2_hint_isTop( &hintmap->edge[i] ) )
stemhint->maxDS = hintmap->edge[i].dsCoord;
else
stemhint->minDS = hintmap->edge[i].dsCoord;
 
stemhint->used = TRUE;
}
}
}
 
/* hint map is ready to use */
hintmap->isValid = TRUE;
 
/* remember this mask has been used */
cf2_hintmask_setNew( hintMask, FALSE );
}
 
 
FT_LOCAL_DEF( void )
cf2_glyphpath_init( CF2_GlyphPath glyphpath,
CF2_Font font,
CF2_OutlineCallbacks callbacks,
CF2_Fixed scaleY,
/* CF2_Fixed hShift, */
CF2_ArrStack hStemHintArray,
CF2_ArrStack vStemHintArray,
CF2_HintMask hintMask,
CF2_Fixed hintOriginY,
const CF2_Blues blues,
const FT_Vector* fractionalTranslation )
{
FT_ZERO( glyphpath );
 
glyphpath->font = font;
glyphpath->callbacks = callbacks;
 
cf2_arrstack_init( &glyphpath->hintMoves,
font->memory,
&font->error,
sizeof ( CF2_HintMoveRec ) );
 
cf2_hintmap_init( &glyphpath->initialHintMap,
font,
&glyphpath->initialHintMap,
&glyphpath->hintMoves,
scaleY );
cf2_hintmap_init( &glyphpath->firstHintMap,
font,
&glyphpath->initialHintMap,
&glyphpath->hintMoves,
scaleY );
cf2_hintmap_init( &glyphpath->hintMap,
font,
&glyphpath->initialHintMap,
&glyphpath->hintMoves,
scaleY );
 
glyphpath->scaleX = font->innerTransform.a;
glyphpath->scaleC = font->innerTransform.c;
glyphpath->scaleY = font->innerTransform.d;
 
glyphpath->fractionalTranslation = *fractionalTranslation;
 
#if 0
glyphpath->hShift = hShift; /* for fauxing */
#endif
 
glyphpath->hStemHintArray = hStemHintArray;
glyphpath->vStemHintArray = vStemHintArray;
glyphpath->hintMask = hintMask; /* ptr to current mask */
glyphpath->hintOriginY = hintOriginY;
glyphpath->blues = blues;
glyphpath->darken = font->darkened; /* TODO: should we make copies? */
glyphpath->xOffset = font->darkenX;
glyphpath->yOffset = font->darkenY;
glyphpath->miterLimit = 2 * FT_MAX(
cf2_fixedAbs( glyphpath->xOffset ),
cf2_fixedAbs( glyphpath->yOffset ) );
 
/* .1 character space unit */
glyphpath->snapThreshold = cf2_floatToFixed( 0.1f );
 
glyphpath->moveIsPending = TRUE;
glyphpath->pathIsOpen = FALSE;
glyphpath->elemIsQueued = FALSE;
}
 
 
FT_LOCAL_DEF( void )
cf2_glyphpath_finalize( CF2_GlyphPath glyphpath )
{
cf2_arrstack_finalize( &glyphpath->hintMoves );
}
 
 
/*
* Hint point in y-direction and apply outerTransform.
* Input `current' hint map (which is actually delayed by one element).
* Input x,y point in Character Space.
* Output x,y point in Device Space, including translation.
*/
static void
cf2_glyphpath_hintPoint( CF2_GlyphPath glyphpath,
CF2_HintMap hintmap,
FT_Vector* ppt,
CF2_Fixed x,
CF2_Fixed y )
{
FT_Vector pt; /* hinted point in upright DS */
 
 
pt.x = FT_MulFix( glyphpath->scaleX, x ) +
FT_MulFix( glyphpath->scaleC, y );
pt.y = cf2_hintmap_map( hintmap, y );
 
ppt->x = FT_MulFix( glyphpath->font->outerTransform.a, pt.x ) +
FT_MulFix( glyphpath->font->outerTransform.c, pt.y ) +
glyphpath->fractionalTranslation.x;
ppt->y = FT_MulFix( glyphpath->font->outerTransform.b, pt.x ) +
FT_MulFix( glyphpath->font->outerTransform.d, pt.y ) +
glyphpath->fractionalTranslation.y;
}
 
 
/*
* From two line segments, (u1,u2) and (v1,v2), compute a point of
* intersection on the corresponding lines.
* Return false if no intersection is found, or if the intersection is
* too far away from the ends of the line segments, u2 and v1.
*
*/
static FT_Bool
cf2_glyphpath_computeIntersection( CF2_GlyphPath glyphpath,
const FT_Vector* u1,
const FT_Vector* u2,
const FT_Vector* v1,
const FT_Vector* v2,
FT_Vector* intersection )
{
/*
* Let `u' be a zero-based vector from the first segment, `v' from the
* second segment.
* Let `w 'be the zero-based vector from `u1' to `v1'.
* `perp' is the `perpendicular dot product'; see
* http://mathworld.wolfram.com/PerpDotProduct.html.
* `s' is the parameter for the parametric line for the first segment
* (`u').
*
* See notation in
* http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm.
* Calculations are done in 16.16, but must handle the squaring of
* line lengths in character space. We scale all vectors by 1/32 to
* avoid overflow. This allows values up to 4095 to be squared. The
* scale factor cancels in the divide.
*
* TODO: the scale factor could be computed from UnitsPerEm.
*
*/
 
#define cf2_perp( a, b ) \
( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) )
 
/* round and divide by 32 */
#define CF2_CS_SCALE( x ) \
( ( (x) + 0x10 ) >> 5 )
 
FT_Vector u, v, w; /* scaled vectors */
CF2_Fixed denominator, s;
 
 
u.x = CF2_CS_SCALE( u2->x - u1->x );
u.y = CF2_CS_SCALE( u2->y - u1->y );
v.x = CF2_CS_SCALE( v2->x - v1->x );
v.y = CF2_CS_SCALE( v2->y - v1->y );
w.x = CF2_CS_SCALE( v1->x - u1->x );
w.y = CF2_CS_SCALE( v1->y - u1->y );
 
denominator = cf2_perp( u, v );
 
if ( denominator == 0 )
return FALSE; /* parallel or coincident lines */
 
s = FT_DivFix( cf2_perp( w, v ), denominator );
 
intersection->x = u1->x + FT_MulFix( s, u2->x - u1->x );
intersection->y = u1->y + FT_MulFix( s, u2->y - u1->y );
 
/*
* Special case snapping for horizontal and vertical lines.
* This cleans up intersections and reduces problems with winding
* order detection.
* Sample case is sbc cd KozGoPr6N-Medium.otf 20 16685.
* Note: these calculations are in character space.
*
*/
 
if ( u1->x == u2->x &&
cf2_fixedAbs( intersection->x - u1->x ) < glyphpath->snapThreshold )
intersection->x = u1->x;
if ( u1->y == u2->y &&
cf2_fixedAbs( intersection->y - u1->y ) < glyphpath->snapThreshold )
intersection->y = u1->y;
 
if ( v1->x == v2->x &&
cf2_fixedAbs( intersection->x - v1->x ) < glyphpath->snapThreshold )
intersection->x = v1->x;
if ( v1->y == v2->y &&
cf2_fixedAbs( intersection->y - v1->y ) < glyphpath->snapThreshold )
intersection->y = v1->y;
 
/* limit the intersection distance from midpoint of u2 and v1 */
if ( cf2_fixedAbs( intersection->x - ( u2->x + v1->x ) / 2 ) >
glyphpath->miterLimit ||
cf2_fixedAbs( intersection->y - ( u2->y + v1->y ) / 2 ) >
glyphpath->miterLimit )
return FALSE;
 
return TRUE;
}
 
 
/*
* Push the cached element (glyphpath->prevElem*) to the outline
* consumer. When a darkening offset is used, the end point of the
* cached element may be adjusted to an intersection point or it may be
* connected by a line to the current element. This calculation must
* use a HintMap that was valid at the time the element was saved. For
* the first point in a subpath, that is a saved HintMap. For most
* elements, it just means the caller has delayed building a HintMap
* from the current HintMask.
*
* Transform each point with outerTransform and call the outline
* callbacks. This is a general 3x3 transform:
*
* x' = a*x + c*y + tx, y' = b*x + d*y + ty
*
* but it uses 4 elements from CF2_Font and the translation part
* from CF2_GlyphPath.
*
*/
static void
cf2_glyphpath_pushPrevElem( CF2_GlyphPath glyphpath,
CF2_HintMap hintmap,
FT_Vector* nextP0,
FT_Vector nextP1,
FT_Bool close )
{
CF2_CallbackParamsRec params;
 
FT_Vector* prevP0;
FT_Vector* prevP1;
 
FT_Vector intersection = { 0, 0 };
FT_Bool useIntersection = FALSE;
 
 
FT_ASSERT( glyphpath->prevElemOp == CF2_PathOpLineTo ||
glyphpath->prevElemOp == CF2_PathOpCubeTo );
 
if ( glyphpath->prevElemOp == CF2_PathOpLineTo )
{
prevP0 = &glyphpath->prevElemP0;
prevP1 = &glyphpath->prevElemP1;
}
else
{
prevP0 = &glyphpath->prevElemP2;
prevP1 = &glyphpath->prevElemP3;
}
 
/* optimization: if previous and next elements are offset by the same */
/* amount, then there will be no gap, and no need to compute an */
/* intersection. */
if ( prevP1->x != nextP0->x || prevP1->y != nextP0->y )
{
/* previous element does not join next element: */
/* adjust end point of previous element to the intersection */
useIntersection = cf2_glyphpath_computeIntersection( glyphpath,
prevP0,
prevP1,
nextP0,
&nextP1,
&intersection );
if ( useIntersection )
{
/* modify the last point of the cached element (either line or */
/* curve) */
*prevP1 = intersection;
}
}
 
params.pt0 = glyphpath->currentDS;
 
switch( glyphpath->prevElemOp )
{
case CF2_PathOpLineTo:
params.op = CF2_PathOpLineTo;
 
/* note: pt2 and pt3 are unused */
cf2_glyphpath_hintPoint( glyphpath,
hintmap,
&params.pt1,
glyphpath->prevElemP1.x,
glyphpath->prevElemP1.y );
 
glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
 
glyphpath->currentDS = params.pt1;
 
break;
 
case CF2_PathOpCubeTo:
params.op = CF2_PathOpCubeTo;
 
/* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */
cf2_glyphpath_hintPoint( glyphpath,
hintmap,
&params.pt1,
glyphpath->prevElemP1.x,
glyphpath->prevElemP1.y );
cf2_glyphpath_hintPoint( glyphpath,
hintmap,
&params.pt2,
glyphpath->prevElemP2.x,
glyphpath->prevElemP2.y );
cf2_glyphpath_hintPoint( glyphpath,
hintmap,
&params.pt3,
glyphpath->prevElemP3.x,
glyphpath->prevElemP3.y );
 
glyphpath->callbacks->cubeTo( glyphpath->callbacks, &params );
 
glyphpath->currentDS = params.pt3;
 
break;
}
 
if ( !useIntersection || close )
{
/* insert connecting line between end of previous element and start */
/* of current one */
/* note: at the end of a subpath, we might do both, so use `nextP0' */
/* before we change it, below */
 
cf2_glyphpath_hintPoint( glyphpath,
hintmap,
&params.pt1,
nextP0->x,
nextP0->y );
 
if ( params.pt1.x != glyphpath->currentDS.x ||
params.pt1.y != glyphpath->currentDS.y )
{
/* length is nonzero */
params.op = CF2_PathOpLineTo;
params.pt0 = glyphpath->currentDS;
 
/* note: pt2 and pt3 are unused */
glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
 
glyphpath->currentDS = params.pt1;
}
}
 
if ( useIntersection )
{
/* return intersection point to caller */
*nextP0 = intersection;
}
}
 
 
/* push a MoveTo element based on current point and offset of current */
/* element */
static void
cf2_glyphpath_pushMove( CF2_GlyphPath glyphpath,
FT_Vector start )
{
CF2_CallbackParamsRec params;
 
 
params.op = CF2_PathOpMoveTo;
params.pt0 = glyphpath->currentDS;
 
/* Test if move has really happened yet; it would have called */
/* `cf2_hintmap_build' to set `isValid'. */
if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) )
{
/* we are here iff first subpath is missing a moveto operator: */
/* synthesize first moveTo to finish initialization of hintMap */
cf2_glyphpath_moveTo( glyphpath,
glyphpath->start.x,
glyphpath->start.y );
}
 
cf2_glyphpath_hintPoint( glyphpath,
&glyphpath->hintMap,
&params.pt1,
start.x,
start.y );
 
/* note: pt2 and pt3 are unused */
glyphpath->callbacks->moveTo( glyphpath->callbacks, &params );
 
glyphpath->currentDS = params.pt1;
glyphpath->offsetStart0 = start;
}
 
 
/*
* All coordinates are in character space.
* On input, (x1, y1) and (x2, y2) give line segment.
* On output, (x, y) give offset vector.
* We use a piecewise approximation to trig functions.
*
* TODO: Offset true perpendicular and proper length
* supply the y-translation for hinting here, too,
* that adds yOffset unconditionally to *y.
*/
static void
cf2_glyphpath_computeOffset( CF2_GlyphPath glyphpath,
CF2_Fixed x1,
CF2_Fixed y1,
CF2_Fixed x2,
CF2_Fixed y2,
CF2_Fixed* x,
CF2_Fixed* y )
{
CF2_Fixed dx = x2 - x1;
CF2_Fixed dy = y2 - y1;
 
 
/* note: negative offsets don't work here; negate deltas to change */
/* quadrants, below */
if ( glyphpath->font->reverseWinding )
{
dx = -dx;
dy = -dy;
}
 
*x = *y = 0;
 
if ( !glyphpath->darken )
return;
 
/* add momentum for this path element */
glyphpath->callbacks->windingMomentum +=
cf2_getWindingMomentum( x1, y1, x2, y2 );
 
/* note: allow mixed integer and fixed multiplication here */
if ( dx >= 0 )
{
if ( dy >= 0 )
{
/* first quadrant, +x +y */
 
if ( dx > 2 * dy )
{
/* +x */
*x = 0;
*y = 0;
}
else if ( dy > 2 * dx )
{
/* +y */
*x = glyphpath->xOffset;
*y = glyphpath->yOffset;
}
else
{
/* +x +y */
*x = FT_MulFix( cf2_floatToFixed( 0.7 ),
glyphpath->xOffset );
*y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ),
glyphpath->yOffset );
}
}
else
{
/* fourth quadrant, +x -y */
 
if ( dx > -2 * dy )
{
/* +x */
*x = 0;
*y = 0;
}
else if ( -dy > 2 * dx )
{
/* -y */
*x = -glyphpath->xOffset;
*y = glyphpath->yOffset;
}
else
{
/* +x -y */
*x = FT_MulFix( cf2_floatToFixed( -0.7 ),
glyphpath->xOffset );
*y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ),
glyphpath->yOffset );
}
}
}
else
{
if ( dy >= 0 )
{
/* second quadrant, -x +y */
 
if ( -dx > 2 * dy )
{
/* -x */
*x = 0;
*y = 2 * glyphpath->yOffset;
}
else if ( dy > -2 * dx )
{
/* +y */
*x = glyphpath->xOffset;
*y = glyphpath->yOffset;
}
else
{
/* -x +y */
*x = FT_MulFix( cf2_floatToFixed( 0.7 ),
glyphpath->xOffset );
*y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ),
glyphpath->yOffset );
}
}
else
{
/* third quadrant, -x -y */
 
if ( -dx > -2 * dy )
{
/* -x */
*x = 0;
*y = 2 * glyphpath->yOffset;
}
else if ( -dy > -2 * dx )
{
/* -y */
*x = -glyphpath->xOffset;
*y = glyphpath->xOffset;
}
else
{
/* -x -y */
*x = FT_MulFix( cf2_floatToFixed( -0.7 ),
glyphpath->xOffset );
*y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ),
glyphpath->yOffset );
}
}
}
}
 
 
FT_LOCAL_DEF( void )
cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
CF2_Fixed x,
CF2_Fixed y )
{
cf2_glyphpath_closeOpenPath( glyphpath );
 
/* save the parameters of the move for later, when we'll know how to */
/* offset it; */
/* also save last move point */
glyphpath->currentCS.x = glyphpath->start.x = x;
glyphpath->currentCS.y = glyphpath->start.y = y;
 
glyphpath->moveIsPending = TRUE;
 
/* ensure we have a valid map with current mask */
if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) ||
cf2_hintmask_isNew( glyphpath->hintMask ) )
cf2_hintmap_build( &glyphpath->hintMap,
glyphpath->hStemHintArray,
glyphpath->vStemHintArray,
glyphpath->hintMask,
glyphpath->hintOriginY,
FALSE );
 
/* save a copy of current HintMap to use when drawing initial point */
glyphpath->firstHintMap = glyphpath->hintMap; /* structure copy */
}
 
 
FT_LOCAL_DEF( void )
cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath,
CF2_Fixed x,
CF2_Fixed y )
{
CF2_Fixed xOffset, yOffset;
FT_Vector P0, P1;
 
 
/* can't compute offset of zero length line, so ignore them */
if ( glyphpath->currentCS.x == x && glyphpath->currentCS.y == y )
return;
 
cf2_glyphpath_computeOffset( glyphpath,
glyphpath->currentCS.x,
glyphpath->currentCS.y,
x,
y,
&xOffset,
&yOffset );
 
/* construct offset points */
P0.x = glyphpath->currentCS.x + xOffset;
P0.y = glyphpath->currentCS.y + yOffset;
P1.x = x + xOffset;
P1.y = y + yOffset;
 
if ( glyphpath->moveIsPending )
{
/* emit offset 1st point as MoveTo */
cf2_glyphpath_pushMove( glyphpath, P0 );
 
glyphpath->moveIsPending = FALSE; /* adjust state machine */
glyphpath->pathIsOpen = TRUE;
 
glyphpath->offsetStart1 = P1; /* record second point */
}
 
if ( glyphpath->elemIsQueued )
{
FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
 
cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->hintMap,
&P0,
P1,
FALSE );
}
 
/* queue the current element with offset points */
glyphpath->elemIsQueued = TRUE;
glyphpath->prevElemOp = CF2_PathOpLineTo;
glyphpath->prevElemP0 = P0;
glyphpath->prevElemP1 = P1;
 
/* update current map */
if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
cf2_hintmap_build( &glyphpath->hintMap,
glyphpath->hStemHintArray,
glyphpath->vStemHintArray,
glyphpath->hintMask,
glyphpath->hintOriginY,
FALSE );
 
glyphpath->currentCS.x = x; /* pre-offset current point */
glyphpath->currentCS.y = y;
}
 
 
FT_LOCAL_DEF( void )
cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath,
CF2_Fixed x1,
CF2_Fixed y1,
CF2_Fixed x2,
CF2_Fixed y2,
CF2_Fixed x3,
CF2_Fixed y3 )
{
CF2_Fixed xOffset1, yOffset1, xOffset3, yOffset3;
FT_Vector P0, P1, P2, P3;
 
 
/* TODO: ignore zero length portions of curve?? */
cf2_glyphpath_computeOffset( glyphpath,
glyphpath->currentCS.x,
glyphpath->currentCS.y,
x1,
y1,
&xOffset1,
&yOffset1 );
cf2_glyphpath_computeOffset( glyphpath,
x2,
y2,
x3,
y3,
&xOffset3,
&yOffset3 );
 
/* add momentum from the middle segment */
glyphpath->callbacks->windingMomentum +=
cf2_getWindingMomentum( x1, y1, x2, y2 );
 
/* construct offset points */
P0.x = glyphpath->currentCS.x + xOffset1;
P0.y = glyphpath->currentCS.y + yOffset1;
P1.x = x1 + xOffset1;
P1.y = y1 + yOffset1;
/* note: preserve angle of final segment by using offset3 at both ends */
P2.x = x2 + xOffset3;
P2.y = y2 + yOffset3;
P3.x = x3 + xOffset3;
P3.y = y3 + yOffset3;
 
if ( glyphpath->moveIsPending )
{
/* emit offset 1st point as MoveTo */
cf2_glyphpath_pushMove( glyphpath, P0 );
 
glyphpath->moveIsPending = FALSE;
glyphpath->pathIsOpen = TRUE;
 
glyphpath->offsetStart1 = P1; /* record second point */
}
 
if ( glyphpath->elemIsQueued )
{
FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
 
cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->hintMap,
&P0,
P1,
FALSE );
}
 
/* queue the current element with offset points */
glyphpath->elemIsQueued = TRUE;
glyphpath->prevElemOp = CF2_PathOpCubeTo;
glyphpath->prevElemP0 = P0;
glyphpath->prevElemP1 = P1;
glyphpath->prevElemP2 = P2;
glyphpath->prevElemP3 = P3;
 
/* update current map */
if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
cf2_hintmap_build( &glyphpath->hintMap,
glyphpath->hStemHintArray,
glyphpath->vStemHintArray,
glyphpath->hintMask,
glyphpath->hintOriginY,
FALSE );
 
glyphpath->currentCS.x = x3; /* pre-offset current point */
glyphpath->currentCS.y = y3;
}
 
 
FT_LOCAL_DEF( void )
cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath )
{
if ( glyphpath->pathIsOpen )
{
FT_ASSERT( cf2_hintmap_isValid( &glyphpath->firstHintMap ) );
 
/* since we need to apply an offset to the implicit lineto, we make */
/* it explicit here */
cf2_glyphpath_lineTo( glyphpath,
glyphpath->start.x,
glyphpath->start.y );
 
/* Draw previous element (the explicit LineTo we just created, */
/* above) and connect it to the start point, but with the offset we */
/* saved from the first element. */
/* Use the saved HintMap, too. */
FT_ASSERT( glyphpath->elemIsQueued );
 
cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->firstHintMap,
&glyphpath->offsetStart0,
glyphpath->offsetStart1,
TRUE );
 
/* reset state machine */
glyphpath->moveIsPending = TRUE;
glyphpath->pathIsOpen = FALSE;
glyphpath->elemIsQueued = FALSE;
}
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2hints.h
0,0 → 1,287
/***************************************************************************/
/* */
/* cf2hints.h */
/* */
/* Adobe's code for handling CFF hints (body). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2HINTS_H__
#define __CF2HINTS_H__
 
 
FT_BEGIN_HEADER
 
 
enum
{
CF2_MAX_HINTS = 96 /* maximum # of hints */
};
 
 
/*
* A HintMask object stores a bit mask that specifies which hints in the
* charstring are active at a given time. Hints in CFF must be declared
* at the start, before any drawing operators, with horizontal hints
* preceding vertical hints. The HintMask is ordered the same way, with
* horizontal hints immediately followed by vertical hints. Clients are
* responsible for knowing how many of each type are present.
*
* The maximum total number of hints is 96, as specified by the CFF
* specification.
*
* A HintMask is built 0 or more times while interpreting a charstring, by
* the HintMask operator. There is only one HintMask, but it is built or
* rebuilt each time there is a hint substitution (HintMask operator) in
* the charstring. A default HintMask with all bits set is built if there
* has been no HintMask operator prior to the first drawing operator.
*
*/
 
typedef struct CF2_HintMaskRec_
{
FT_Error* error;
 
FT_Bool isValid;
FT_Bool isNew;
 
size_t bitCount;
size_t byteCount;
 
FT_Byte mask[( CF2_MAX_HINTS + 7 ) / 8];
 
} CF2_HintMaskRec, *CF2_HintMask;
 
 
typedef struct CF2_StemHintRec_
{
FT_Bool used; /* DS positions are valid */
 
CF2_Fixed min; /* original character space value */
CF2_Fixed max;
 
CF2_Fixed minDS; /* DS position after first use */
CF2_Fixed maxDS;
 
} CF2_StemHintRec, *CF2_StemHint;
 
 
/*
* A HintMap object stores a piecewise linear function for mapping
* y-coordinates from character space to device space, providing
* appropriate pixel alignment to stem edges.
*
* The map is implemented as an array of `CF2_Hint' elements, each
* representing an edge. When edges are paired, as from stem hints, the
* bottom edge must immediately precede the top edge in the array.
* Element character space AND device space positions must both increase
* monotonically in the array. `CF2_Hint' elements are also used as
* parameters to `cf2_blues_capture'.
*
* The `cf2_hintmap_build' method must be called before any drawing
* operation (beginning with a Move operator) and at each hint
* substitution (HintMask operator).
*
* The `cf2_hintmap_map' method is called to transform y-coordinates at
* each drawing operation (move, line, curve).
*
*/
 
/* TODO: make this a CF2_ArrStack and add a deep copy method */
enum
{
CF2_MAX_HINT_EDGES = CF2_MAX_HINTS * 2
};
 
 
typedef struct CF2_HintMapRec_
{
CF2_Font font;
 
/* initial map based on blue zones */
struct CF2_HintMapRec_* initialHintMap;
 
/* working storage for 2nd pass adjustHints */
CF2_ArrStack hintMoves;
 
FT_Bool isValid;
FT_Bool hinted;
 
CF2_Fixed scale;
CF2_UInt count;
 
/* start search from this index */
CF2_UInt lastIndex;
 
CF2_HintRec edge[CF2_MAX_HINT_EDGES]; /* 192 */
 
} CF2_HintMapRec, *CF2_HintMap;
 
 
FT_LOCAL( FT_Bool )
cf2_hint_isValid( const CF2_Hint hint );
FT_LOCAL( FT_Bool )
cf2_hint_isTop( const CF2_Hint hint );
FT_LOCAL( FT_Bool )
cf2_hint_isBottom( const CF2_Hint hint );
FT_LOCAL( void )
cf2_hint_lock( CF2_Hint hint );
 
 
FT_LOCAL( void )
cf2_hintmap_init( CF2_HintMap hintmap,
CF2_Font font,
CF2_HintMap initialMap,
CF2_ArrStack hintMoves,
CF2_Fixed scale );
FT_LOCAL( void )
cf2_hintmap_build( CF2_HintMap hintmap,
CF2_ArrStack hStemHintArray,
CF2_ArrStack vStemHintArray,
CF2_HintMask hintMask,
CF2_Fixed hintOrigin,
FT_Bool initialMap );
 
 
/*
* GlyphPath is a wrapper for drawing operations that scales the
* coordinates according to the render matrix and HintMap. It also tracks
* open paths to control ClosePath and to insert MoveTo for broken fonts.
*
*/
typedef struct CF2_GlyphPathRec_
{
/* TODO: gather some of these into a hinting context */
 
CF2_Font font; /* font instance */
CF2_OutlineCallbacks callbacks; /* outline consumer */
 
 
CF2_HintMapRec hintMap; /* current hint map */
CF2_HintMapRec firstHintMap; /* saved copy */
CF2_HintMapRec initialHintMap; /* based on all captured hints */
 
CF2_ArrStackRec hintMoves; /* list of hint moves for 2nd pass */
 
CF2_Fixed scaleX; /* matrix a */
CF2_Fixed scaleC; /* matrix c */
CF2_Fixed scaleY; /* matrix d */
 
FT_Vector fractionalTranslation; /* including deviceXScale */
#if 0
CF2_Fixed hShift; /* character space horizontal shift */
/* (for fauxing) */
#endif
 
FT_Bool pathIsOpen; /* true after MoveTo */
FT_Bool darken; /* true if stem darkening */
FT_Bool moveIsPending; /* true between MoveTo and offset MoveTo */
 
/* references used to call `cf2_hintmap_build', if necessary */
CF2_ArrStack hStemHintArray;
CF2_ArrStack vStemHintArray;
CF2_HintMask hintMask; /* ptr to the current mask */
CF2_Fixed hintOriginY; /* copy of current origin */
const CF2_BluesRec* blues;
 
CF2_Fixed xOffset; /* character space offsets */
CF2_Fixed yOffset;
 
/* character space miter limit threshold */
CF2_Fixed miterLimit;
/* vertical/horzizontal snap distance in character space */
CF2_Fixed snapThreshold;
 
FT_Vector offsetStart0; /* first and second points of first */
FT_Vector offsetStart1; /* element with offset applied */
 
/* current point, character space, before offset */
FT_Vector currentCS;
/* current point, device space */
FT_Vector currentDS;
FT_Vector start; /* start point of subpath */
 
/* the following members constitute the `queue' of one element */
FT_Bool elemIsQueued;
CF2_Int prevElemOp;
 
FT_Vector prevElemP0;
FT_Vector prevElemP1;
FT_Vector prevElemP2;
FT_Vector prevElemP3;
 
} CF2_GlyphPathRec, *CF2_GlyphPath;
 
 
FT_LOCAL( void )
cf2_glyphpath_init( CF2_GlyphPath glyphpath,
CF2_Font font,
CF2_OutlineCallbacks callbacks,
CF2_Fixed scaleY,
/* CF2_Fixed hShift, */
CF2_ArrStack hStemHintArray,
CF2_ArrStack vStemHintArray,
CF2_HintMask hintMask,
CF2_Fixed hintOrigin,
const CF2_Blues blues,
const FT_Vector* fractionalTranslation );
FT_LOCAL( void )
cf2_glyphpath_finalize( CF2_GlyphPath glyphpath );
 
FT_LOCAL( void )
cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
CF2_Fixed x,
CF2_Fixed y );
FT_LOCAL( void )
cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath,
CF2_Fixed x,
CF2_Fixed y );
FT_LOCAL( void )
cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath,
CF2_Fixed x1,
CF2_Fixed y1,
CF2_Fixed x2,
CF2_Fixed y2,
CF2_Fixed x3,
CF2_Fixed y3 );
FT_LOCAL( void )
cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath );
 
 
FT_END_HEADER
 
 
#endif /* __CF2HINTS_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2intrp.c
0,0 → 1,1538
/***************************************************************************/
/* */
/* cf2intrp.c */
/* */
/* Adobe's CFF Interpreter (body). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H
 
#include "cf2glue.h"
#include "cf2font.h"
#include "cf2stack.h"
#include "cf2hints.h"
 
#include "cf2error.h"
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cf2interp
 
 
/* some operators are not implemented yet */
#define CF2_FIXME FT_TRACE4(( "cf2_interpT2CharString:" \
" operator not implemented yet\n" ))
 
 
 
FT_LOCAL_DEF( void )
cf2_hintmask_init( CF2_HintMask hintmask,
FT_Error* error )
{
FT_ZERO( hintmask );
 
hintmask->error = error;
}
 
 
FT_LOCAL_DEF( FT_Bool )
cf2_hintmask_isValid( const CF2_HintMask hintmask )
{
return hintmask->isValid;
}
 
 
FT_LOCAL_DEF( FT_Bool )
cf2_hintmask_isNew( const CF2_HintMask hintmask )
{
return hintmask->isNew;
}
 
 
FT_LOCAL_DEF( void )
cf2_hintmask_setNew( CF2_HintMask hintmask,
FT_Bool val )
{
hintmask->isNew = val;
}
 
 
/* clients call `getMaskPtr' in order to iterate */
/* through hint mask */
 
FT_LOCAL_DEF( FT_Byte* )
cf2_hintmask_getMaskPtr( CF2_HintMask hintmask )
{
return hintmask->mask;
}
 
 
static size_t
cf2_hintmask_setCounts( CF2_HintMask hintmask,
size_t bitCount )
{
if ( bitCount > CF2_MAX_HINTS )
{
/* total of h and v stems must be <= 96 */
CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
return 0;
}
 
hintmask->bitCount = bitCount;
hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
 
hintmask->isValid = TRUE;
hintmask->isNew = TRUE;
 
return bitCount;
}
 
 
/* consume the hintmask bytes from the charstring, advancing the src */
/* pointer */
static void
cf2_hintmask_read( CF2_HintMask hintmask,
CF2_Buffer charstring,
size_t bitCount )
{
size_t i;
 
#ifndef CF2_NDEBUG
/* these are the bits in the final mask byte that should be zero */
/* Note: this variable is only used in an assert expression below */
/* and then only if CF2_NDEBUG is not defined */
CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
#endif
 
 
/* initialize counts and isValid */
if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
return;
 
FT_ASSERT( hintmask->byteCount > 0 );
 
FT_TRACE4(( " (maskbytes:" ));
 
/* set mask and advance interpreter's charstring pointer */
for ( i = 0; i < hintmask->byteCount; i++ )
{
hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
}
 
FT_TRACE4(( ")\n" ));
 
/* assert any unused bits in last byte are zero unless there's a prior */
/* error */
/* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
#ifndef CF2_NDEBUG
FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
*hintmask->error );
#endif
}
 
 
FT_LOCAL_DEF( void )
cf2_hintmask_setAll( CF2_HintMask hintmask,
size_t bitCount )
{
size_t i;
CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
 
 
/* initialize counts and isValid */
if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
return;
 
FT_ASSERT( hintmask->byteCount > 0 );
FT_ASSERT( hintmask->byteCount <
sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
 
/* set mask to all ones */
for ( i = 0; i < hintmask->byteCount; i++ )
hintmask->mask[i] = 0xFF;
 
/* clear unused bits */
/* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
hintmask->mask[hintmask->byteCount - 1] &= ~mask;
}
 
 
/* Type2 charstring opcodes */
enum
{
cf2_cmdRESERVED_0, /* 0 */
cf2_cmdHSTEM, /* 1 */
cf2_cmdRESERVED_2, /* 2 */
cf2_cmdVSTEM, /* 3 */
cf2_cmdVMOVETO, /* 4 */
cf2_cmdRLINETO, /* 5 */
cf2_cmdHLINETO, /* 6 */
cf2_cmdVLINETO, /* 7 */
cf2_cmdRRCURVETO, /* 8 */
cf2_cmdRESERVED_9, /* 9 */
cf2_cmdCALLSUBR, /* 10 */
cf2_cmdRETURN, /* 11 */
cf2_cmdESC, /* 12 */
cf2_cmdRESERVED_13, /* 13 */
cf2_cmdENDCHAR, /* 14 */
cf2_cmdRESERVED_15, /* 15 */
cf2_cmdRESERVED_16, /* 16 */
cf2_cmdRESERVED_17, /* 17 */
cf2_cmdHSTEMHM, /* 18 */
cf2_cmdHINTMASK, /* 19 */
cf2_cmdCNTRMASK, /* 20 */
cf2_cmdRMOVETO, /* 21 */
cf2_cmdHMOVETO, /* 22 */
cf2_cmdVSTEMHM, /* 23 */
cf2_cmdRCURVELINE, /* 24 */
cf2_cmdRLINECURVE, /* 25 */
cf2_cmdVVCURVETO, /* 26 */
cf2_cmdHHCURVETO, /* 27 */
cf2_cmdEXTENDEDNMBR, /* 28 */
cf2_cmdCALLGSUBR, /* 29 */
cf2_cmdVHCURVETO, /* 30 */
cf2_cmdHVCURVETO /* 31 */
};
 
enum
{
cf2_escDOTSECTION, /* 0 */
cf2_escRESERVED_1, /* 1 */
cf2_escRESERVED_2, /* 2 */
cf2_escAND, /* 3 */
cf2_escOR, /* 4 */
cf2_escNOT, /* 5 */
cf2_escRESERVED_6, /* 6 */
cf2_escRESERVED_7, /* 7 */
cf2_escRESERVED_8, /* 8 */
cf2_escABS, /* 9 */
cf2_escADD, /* 10 like otherADD */
cf2_escSUB, /* 11 like otherSUB */
cf2_escDIV, /* 12 */
cf2_escRESERVED_13, /* 13 */
cf2_escNEG, /* 14 */
cf2_escEQ, /* 15 */
cf2_escRESERVED_16, /* 16 */
cf2_escRESERVED_17, /* 17 */
cf2_escDROP, /* 18 */
cf2_escRESERVED_19, /* 19 */
cf2_escPUT, /* 20 like otherPUT */
cf2_escGET, /* 21 like otherGET */
cf2_escIFELSE, /* 22 like otherIFELSE */
cf2_escRANDOM, /* 23 like otherRANDOM */
cf2_escMUL, /* 24 like otherMUL */
cf2_escRESERVED_25, /* 25 */
cf2_escSQRT, /* 26 */
cf2_escDUP, /* 27 like otherDUP */
cf2_escEXCH, /* 28 like otherEXCH */
cf2_escINDEX, /* 29 */
cf2_escROLL, /* 30 */
cf2_escRESERVED_31, /* 31 */
cf2_escRESERVED_32, /* 32 */
cf2_escRESERVED_33, /* 33 */
cf2_escHFLEX, /* 34 */
cf2_escFLEX, /* 35 */
cf2_escHFLEX1, /* 36 */
cf2_escFLEX1 /* 37 */
};
 
 
/* `stemHintArray' does not change once we start drawing the outline. */
static void
cf2_doStems( const CF2_Font font,
CF2_Stack opStack,
CF2_ArrStack stemHintArray,
CF2_Fixed* width,
FT_Bool* haveWidth,
CF2_Fixed hintOffset )
{
CF2_UInt i;
CF2_UInt count = cf2_stack_count( opStack );
FT_Bool hasWidthArg = (FT_Bool)( count & 1 );
 
/* variable accumulates delta values from operand stack */
CF2_Fixed position = hintOffset;
 
if ( hasWidthArg && ! *haveWidth )
*width = cf2_stack_getReal( opStack, 0 ) +
cf2_getNominalWidthX( font->decoder );
 
if ( font->decoder->width_only )
goto exit;
 
for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
{
/* construct a CF2_StemHint and push it onto the list */
CF2_StemHintRec stemhint;
 
 
stemhint.min =
position += cf2_stack_getReal( opStack, i );
stemhint.max =
position += cf2_stack_getReal( opStack, i + 1 );
 
stemhint.used = FALSE;
stemhint.maxDS =
stemhint.minDS = 0;
 
cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
}
 
cf2_stack_clear( opStack );
 
exit:
/* cf2_doStems must define a width (may be default) */
*haveWidth = TRUE;
}
 
 
static void
cf2_doFlex( CF2_Stack opStack,
CF2_Fixed* curX,
CF2_Fixed* curY,
CF2_GlyphPath glyphPath,
const FT_Bool* readFromStack,
FT_Bool doConditionalLastRead )
{
CF2_Fixed vals[14];
CF2_UInt index;
FT_Bool isHFlex;
CF2_Int top, i, j;
 
 
vals[0] = *curX;
vals[1] = *curY;
index = 0;
isHFlex = readFromStack[9] == FALSE;
top = isHFlex ? 9 : 10;
 
for ( i = 0; i < top; i++ )
{
vals[i + 2] = vals[i];
if ( readFromStack[i] )
vals[i + 2] += cf2_stack_getReal( opStack, index++ );
}
 
if ( isHFlex )
vals[9 + 2] = *curY;
 
if ( doConditionalLastRead )
{
FT_Bool lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) >
cf2_fixedAbs( vals[11] - *curY ) );
CF2_Fixed lastVal = cf2_stack_getReal( opStack, index );
 
 
if ( lastIsX )
{
vals[12] = vals[10] + lastVal;
vals[13] = *curY;
}
else
{
vals[12] = *curX;
vals[13] = vals[11] + lastVal;
}
}
else
{
if ( readFromStack[10] )
vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ );
else
vals[12] = *curX;
 
if ( readFromStack[11] )
vals[13] = vals[11] + cf2_stack_getReal( opStack, index );
else
vals[13] = *curY;
}
 
for ( j = 0; j < 2; j++ )
cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
vals[j * 6 + 3],
vals[j * 6 + 4],
vals[j * 6 + 5],
vals[j * 6 + 6],
vals[j * 6 + 7] );
 
cf2_stack_clear( opStack );
 
*curX = vals[12];
*curY = vals[13];
}
 
 
/*
* `error' is a shared error code used by many objects in this
* routine. Before the code continues from an error, it must check and
* record the error in `*error'. The idea is that this shared
* error code will record the first error encountered. If testing
* for an error anyway, the cost of `goto exit' is small, so we do it,
* even if continuing would be safe. In this case, `lastError' is
* set, so the testing and storing can be done in one place, at `exit'.
*
* Continuing after an error is intended for objects which do their own
* testing of `*error', e.g., array stack functions. This allows us to
* avoid an extra test after the call.
*
* Unimplemented opcodes are ignored.
*
*/
FT_LOCAL_DEF( void )
cf2_interpT2CharString( CF2_Font font,
CF2_Buffer buf,
CF2_OutlineCallbacks callbacks,
const FT_Vector* translation,
FT_Bool doingSeac,
CF2_Fixed curX,
CF2_Fixed curY,
CF2_Fixed* width )
{
/* lastError is used for errors that are immediately tested */
FT_Error lastError = FT_Err_Ok;
 
/* pointer to parsed font object */
CFF_Decoder* decoder = font->decoder;
 
FT_Error* error = &font->error;
FT_Memory memory = font->memory;
 
CF2_Fixed scaleY = font->innerTransform.d;
CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder );
 
/* save this for hinting seac accents */
CF2_Fixed hintOriginY = curY;
 
CF2_Stack opStack = NULL;
FT_Byte op1; /* first opcode byte */
 
/* instruction limit; 20,000,000 matches Avalon */
FT_UInt32 instructionLimit = 20000000UL;
 
CF2_ArrStackRec subrStack;
 
FT_Bool haveWidth;
CF2_Buffer charstring = NULL;
 
CF2_Int charstringIndex = -1; /* initialize to empty */
 
/* TODO: placeholders for hint structures */
 
/* objects used for hinting */
CF2_ArrStackRec hStemHintArray;
CF2_ArrStackRec vStemHintArray;
 
CF2_HintMaskRec hintMask;
CF2_GlyphPathRec glyphPath;
 
 
/* initialize the remaining objects */
cf2_arrstack_init( &subrStack,
memory,
error,
sizeof ( CF2_BufferRec ) );
cf2_arrstack_init( &hStemHintArray,
memory,
error,
sizeof ( CF2_StemHintRec ) );
cf2_arrstack_init( &vStemHintArray,
memory,
error,
sizeof ( CF2_StemHintRec ) );
 
/* initialize CF2_StemHint arrays */
cf2_hintmask_init( &hintMask, error );
 
/* initialize path map to manage drawing operations */
 
/* Note: last 4 params are used to handle `MoveToPermissive', which */
/* may need to call `hintMap.Build' */
/* TODO: MoveToPermissive is gone; are these still needed? */
cf2_glyphpath_init( &glyphPath,
font,
callbacks,
scaleY,
/* hShift, */
&hStemHintArray,
&vStemHintArray,
&hintMask,
hintOriginY,
&font->blues,
translation );
 
/*
* Initialize state for width parsing. From the CFF Spec:
*
* The first stack-clearing operator, which must be one of hstem,
* hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
* rmoveto, or endchar, takes an additional argument - the width (as
* described earlier), which may be expressed as zero or one numeric
* argument.
*
* What we implement here uses the first validly specified width, but
* does not detect errors for specifying more than one width.
*
* If one of the above operators occurs without explicitly specifying
* a width, we assume the default width.
*
*/
haveWidth = FALSE;
*width = cf2_getDefaultWidthX( decoder );
 
/*
* Note: at this point, all pointers to resources must be NULL
* and all local objects must be initialized.
* There must be no branches to exit: above this point.
*
*/
 
/* allocate an operand stack */
opStack = cf2_stack_init( memory, error );
if ( !opStack )
{
lastError = FT_THROW( Out_Of_Memory );
goto exit;
}
 
/* initialize subroutine stack by placing top level charstring as */
/* first element (max depth plus one for the charstring) */
/* Note: Caller owns and must finalize the first charstring. */
/* Our copy of it does not change that requirement. */
cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
 
charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
*charstring = *buf; /* structure copy */
 
charstringIndex = 0; /* entry is valid now */
 
/* catch errors so far */
if ( *error )
goto exit;
 
/* main interpreter loop */
while ( 1 )
{
if ( cf2_buf_isEnd( charstring ) )
{
/* If we've reached the end of the charstring, simulate a */
/* cf2_cmdRETURN or cf2_cmdENDCHAR. */
if ( charstringIndex )
op1 = cf2_cmdRETURN; /* end of buffer for subroutine */
else
op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
}
else
op1 = (FT_Byte)cf2_buf_readByte( charstring );
 
/* check for errors once per loop */
if ( *error )
goto exit;
 
instructionLimit--;
if ( instructionLimit == 0 )
{
lastError = FT_THROW( Invalid_Glyph_Format );
goto exit;
}
 
switch( op1 )
{
case cf2_cmdRESERVED_0:
case cf2_cmdRESERVED_2:
case cf2_cmdRESERVED_9:
case cf2_cmdRESERVED_13:
case cf2_cmdRESERVED_15:
case cf2_cmdRESERVED_16:
case cf2_cmdRESERVED_17:
/* we may get here if we have a prior error */
FT_TRACE4(( " unknown op (%d)\n", op1 ));
break;
 
case cf2_cmdHSTEMHM:
case cf2_cmdHSTEM:
FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
 
/* never add hints after the mask is computed */
if ( cf2_hintmask_isValid( &hintMask ) )
FT_TRACE4(( "cf2_interpT2CharString:"
" invalid horizontal hint mask\n" ));
 
cf2_doStems( font,
opStack,
&hStemHintArray,
width,
&haveWidth,
0 );
 
if ( font->decoder->width_only )
goto exit;
 
break;
 
case cf2_cmdVSTEMHM:
case cf2_cmdVSTEM:
FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
 
/* never add hints after the mask is computed */
if ( cf2_hintmask_isValid( &hintMask ) )
FT_TRACE4(( "cf2_interpT2CharString:"
" invalid vertical hint mask\n" ));
 
cf2_doStems( font,
opStack,
&vStemHintArray,
width,
&haveWidth,
0 );
 
if ( font->decoder->width_only )
goto exit;
 
break;
 
case cf2_cmdVMOVETO:
FT_TRACE4(( " vmoveto\n" ));
 
if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
*width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
 
/* width is defined or default after this */
haveWidth = TRUE;
 
if ( font->decoder->width_only )
goto exit;
 
curY += cf2_stack_popFixed( opStack );
 
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
 
break;
 
case cf2_cmdRLINETO:
{
CF2_UInt index;
CF2_UInt count = cf2_stack_count( opStack );
 
 
FT_TRACE4(( " rlineto\n" ));
 
for ( index = 0; index < count; index += 2 )
{
curX += cf2_stack_getReal( opStack, index + 0 );
curY += cf2_stack_getReal( opStack, index + 1 );
 
cf2_glyphpath_lineTo( &glyphPath, curX, curY );
}
 
cf2_stack_clear( opStack );
}
continue; /* no need to clear stack again */
 
case cf2_cmdHLINETO:
case cf2_cmdVLINETO:
{
CF2_UInt index;
CF2_UInt count = cf2_stack_count( opStack );
 
FT_Bool isX = op1 == cf2_cmdHLINETO;
 
 
FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
 
for ( index = 0; index < count; index++ )
{
CF2_Fixed v = cf2_stack_getReal( opStack, index );
 
 
if ( isX )
curX += v;
else
curY += v;
 
isX = !isX;
 
cf2_glyphpath_lineTo( &glyphPath, curX, curY );
}
 
cf2_stack_clear( opStack );
}
continue;
 
case cf2_cmdRCURVELINE:
case cf2_cmdRRCURVETO:
{
CF2_UInt count = cf2_stack_count( opStack );
CF2_UInt index = 0;
 
 
FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
: " rrcurveto\n" ));
 
while ( index + 6 <= count )
{
CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
 
 
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
 
curX = x3;
curY = y3;
index += 6;
}
 
if ( op1 == cf2_cmdRCURVELINE )
{
curX += cf2_stack_getReal( opStack, index + 0 );
curY += cf2_stack_getReal( opStack, index + 1 );
 
cf2_glyphpath_lineTo( &glyphPath, curX, curY );
}
 
cf2_stack_clear( opStack );
}
continue; /* no need to clear stack again */
 
case cf2_cmdCALLGSUBR:
case cf2_cmdCALLSUBR:
{
CF2_UInt subrIndex;
 
 
FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
: " callsubr" ));
 
if ( charstringIndex > CF2_MAX_SUBR )
{
/* max subr plus one for charstring */
lastError = FT_THROW( Invalid_Glyph_Format );
goto exit; /* overflow of stack */
}
 
/* push our current CFF charstring region on subrStack */
charstring = (CF2_Buffer)
cf2_arrstack_getPointer( &subrStack,
charstringIndex + 1 );
 
/* set up the new CFF region and pointer */
subrIndex = cf2_stack_popInt( opStack );
 
switch ( op1 )
{
case cf2_cmdCALLGSUBR:
FT_TRACE4(( "(%d)\n", subrIndex + decoder->globals_bias ));
 
if ( cf2_initGlobalRegionBuffer( decoder,
subrIndex,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
goto exit; /* subroutine lookup or stream error */
}
break;
 
default:
/* cf2_cmdCALLSUBR */
FT_TRACE4(( "(%d)\n", subrIndex + decoder->locals_bias ));
 
if ( cf2_initLocalRegionBuffer( decoder,
subrIndex,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
goto exit; /* subroutine lookup or stream error */
}
}
 
charstringIndex += 1; /* entry is valid now */
}
continue; /* do not clear the stack */
 
case cf2_cmdRETURN:
FT_TRACE4(( " return\n" ));
 
if ( charstringIndex < 1 )
{
/* Note: cannot return from top charstring */
lastError = FT_THROW( Invalid_Glyph_Format );
goto exit; /* underflow of stack */
}
 
/* restore position in previous charstring */
charstring = (CF2_Buffer)
cf2_arrstack_getPointer( &subrStack,
--charstringIndex );
continue; /* do not clear the stack */
 
case cf2_cmdESC:
{
FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring );
 
 
switch ( op2 )
{
case cf2_escDOTSECTION:
/* something about `flip type of locking' -- ignore it */
FT_TRACE4(( " dotsection\n" ));
 
break;
 
/* TODO: should these operators be supported? */
case cf2_escAND: /* in spec */
FT_TRACE4(( " and\n" ));
 
CF2_FIXME;
break;
 
case cf2_escOR: /* in spec */
FT_TRACE4(( " or\n" ));
 
CF2_FIXME;
break;
 
case cf2_escNOT: /* in spec */
FT_TRACE4(( " not\n" ));
 
CF2_FIXME;
break;
 
case cf2_escABS: /* in spec */
FT_TRACE4(( " abs\n" ));
 
CF2_FIXME;
break;
 
case cf2_escADD: /* in spec */
FT_TRACE4(( " add\n" ));
 
CF2_FIXME;
break;
 
case cf2_escSUB: /* in spec */
FT_TRACE4(( " sub\n" ));
 
CF2_FIXME;
break;
 
case cf2_escDIV: /* in spec */
FT_TRACE4(( " div\n" ));
 
CF2_FIXME;
break;
 
case cf2_escNEG: /* in spec */
FT_TRACE4(( " neg\n" ));
 
CF2_FIXME;
break;
 
case cf2_escEQ: /* in spec */
FT_TRACE4(( " eq\n" ));
 
CF2_FIXME;
break;
 
case cf2_escDROP: /* in spec */
FT_TRACE4(( " drop\n" ));
 
CF2_FIXME;
break;
 
case cf2_escPUT: /* in spec */
FT_TRACE4(( " put\n" ));
 
CF2_FIXME;
break;
 
case cf2_escGET: /* in spec */
FT_TRACE4(( " get\n" ));
 
CF2_FIXME;
break;
 
case cf2_escIFELSE: /* in spec */
FT_TRACE4(( " ifelse\n" ));
 
CF2_FIXME;
break;
 
case cf2_escRANDOM: /* in spec */
FT_TRACE4(( " random\n" ));
 
CF2_FIXME;
break;
 
case cf2_escMUL: /* in spec */
FT_TRACE4(( " mul\n" ));
 
CF2_FIXME;
break;
 
case cf2_escSQRT: /* in spec */
FT_TRACE4(( " sqrt\n" ));
 
CF2_FIXME;
break;
 
case cf2_escDUP: /* in spec */
FT_TRACE4(( " dup\n" ));
 
CF2_FIXME;
break;
 
case cf2_escEXCH: /* in spec */
FT_TRACE4(( " exch\n" ));
 
CF2_FIXME;
break;
 
case cf2_escINDEX: /* in spec */
FT_TRACE4(( " index\n" ));
 
CF2_FIXME;
break;
 
case cf2_escROLL: /* in spec */
FT_TRACE4(( " roll\n" ));
 
CF2_FIXME;
break;
 
case cf2_escHFLEX:
{
static const FT_Bool readFromStack[12] =
{
TRUE /* dx1 */, FALSE /* dy1 */,
TRUE /* dx2 */, TRUE /* dy2 */,
TRUE /* dx3 */, FALSE /* dy3 */,
TRUE /* dx4 */, FALSE /* dy4 */,
TRUE /* dx5 */, FALSE /* dy5 */,
TRUE /* dx6 */, FALSE /* dy6 */
};
 
 
FT_TRACE4(( " hflex\n" ));
 
cf2_doFlex( opStack,
&curX,
&curY,
&glyphPath,
readFromStack,
FALSE /* doConditionalLastRead */ );
}
continue;
 
case cf2_escFLEX:
{
static const FT_Bool readFromStack[12] =
{
TRUE /* dx1 */, TRUE /* dy1 */,
TRUE /* dx2 */, TRUE /* dy2 */,
TRUE /* dx3 */, TRUE /* dy3 */,
TRUE /* dx4 */, TRUE /* dy4 */,
TRUE /* dx5 */, TRUE /* dy5 */,
TRUE /* dx6 */, TRUE /* dy6 */
};
 
 
FT_TRACE4(( " flex\n" ));
 
cf2_doFlex( opStack,
&curX,
&curY,
&glyphPath,
readFromStack,
FALSE /* doConditionalLastRead */ );
}
break; /* TODO: why is this not a continue? */
 
case cf2_escHFLEX1:
{
static const FT_Bool readFromStack[12] =
{
TRUE /* dx1 */, TRUE /* dy1 */,
TRUE /* dx2 */, TRUE /* dy2 */,
TRUE /* dx3 */, FALSE /* dy3 */,
TRUE /* dx4 */, FALSE /* dy4 */,
TRUE /* dx5 */, TRUE /* dy5 */,
TRUE /* dx6 */, FALSE /* dy6 */
};
 
 
FT_TRACE4(( " hflex1\n" ));
 
cf2_doFlex( opStack,
&curX,
&curY,
&glyphPath,
readFromStack,
FALSE /* doConditionalLastRead */ );
}
continue;
 
case cf2_escFLEX1:
{
static const FT_Bool readFromStack[12] =
{
TRUE /* dx1 */, TRUE /* dy1 */,
TRUE /* dx2 */, TRUE /* dy2 */,
TRUE /* dx3 */, TRUE /* dy3 */,
TRUE /* dx4 */, TRUE /* dy4 */,
TRUE /* dx5 */, TRUE /* dy5 */,
FALSE /* dx6 */, FALSE /* dy6 */
};
 
 
FT_TRACE4(( " flex1\n" ));
 
cf2_doFlex( opStack,
&curX,
&curY,
&glyphPath,
readFromStack,
TRUE /* doConditionalLastRead */ );
}
continue;
 
case cf2_escRESERVED_1:
case cf2_escRESERVED_2:
case cf2_escRESERVED_6:
case cf2_escRESERVED_7:
case cf2_escRESERVED_8:
case cf2_escRESERVED_13:
case cf2_escRESERVED_16:
case cf2_escRESERVED_17:
case cf2_escRESERVED_19:
case cf2_escRESERVED_25:
case cf2_escRESERVED_31:
case cf2_escRESERVED_32:
case cf2_escRESERVED_33:
default:
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
 
}; /* end of switch statement checking `op2' */
 
} /* case cf2_cmdESC */
break;
 
case cf2_cmdENDCHAR:
FT_TRACE4(( " endchar\n" ));
 
if ( cf2_stack_count( opStack ) == 1 ||
cf2_stack_count( opStack ) == 5 )
{
if ( !haveWidth )
*width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
}
 
/* width is defined or default after this */
haveWidth = TRUE;
 
if ( font->decoder->width_only )
goto exit;
 
/* close path if still open */
cf2_glyphpath_closeOpenPath( &glyphPath );
 
if ( cf2_stack_count( opStack ) > 1 )
{
/* must be either 4 or 5 -- */
/* this is a (deprecated) implied `seac' operator */
 
CF2_UInt achar;
CF2_UInt bchar;
CF2_BufferRec component;
CF2_Fixed dummyWidth; /* ignore component width */
FT_Error error2;
 
 
if ( doingSeac )
{
lastError = FT_THROW( Invalid_Glyph_Format );
goto exit; /* nested seac */
}
 
achar = cf2_stack_popInt( opStack );
bchar = cf2_stack_popInt( opStack );
 
curY = cf2_stack_popFixed( opStack );
curX = cf2_stack_popFixed( opStack );
 
error2 = cf2_getSeacComponent( decoder, achar, &component );
if ( error2 )
{
lastError = error2; /* pass FreeType error through */
goto exit;
}
cf2_interpT2CharString( font,
&component,
callbacks,
translation,
TRUE,
curX,
curY,
&dummyWidth );
cf2_freeSeacComponent( decoder, &component );
 
error2 = cf2_getSeacComponent( decoder, bchar, &component );
if ( error2 )
{
lastError = error2; /* pass FreeType error through */
goto exit;
}
cf2_interpT2CharString( font,
&component,
callbacks,
translation,
TRUE,
0,
0,
&dummyWidth );
cf2_freeSeacComponent( decoder, &component );
}
goto exit;
 
case cf2_cmdCNTRMASK:
case cf2_cmdHINTMASK:
/* the final \n in the tracing message gets added in */
/* `cf2_hintmask_read' (which also traces the mask bytes) */
FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
 
/* if there are arguments on the stack, there this is an */
/* implied cf2_cmdVSTEMHM */
if ( cf2_stack_count( opStack ) != 0 )
{
/* never add hints after the mask is computed */
if ( cf2_hintmask_isValid( &hintMask ) )
FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
}
 
cf2_doStems( font,
opStack,
&vStemHintArray,
width,
&haveWidth,
0 );
 
if ( font->decoder->width_only )
goto exit;
 
if ( op1 == cf2_cmdHINTMASK )
{
/* consume the hint mask bytes which follow the operator */
cf2_hintmask_read( &hintMask,
charstring,
cf2_arrstack_size( &hStemHintArray ) +
cf2_arrstack_size( &vStemHintArray ) );
}
else
{
/*
* Consume the counter mask bytes which follow the operator:
* Build a temporary hint map, just to place and lock those
* stems participating in the counter mask. These are most
* likely the dominant hstems, and are grouped together in a
* few counter groups, not necessarily in correspondence
* with the hint groups. This reduces the chances of
* conflicts between hstems that are initially placed in
* separate hint groups and then brought together. The
* positions are copied back to `hStemHintArray', so we can
* discard `counterMask' and `counterHintMap'.
*
*/
CF2_HintMapRec counterHintMap;
CF2_HintMaskRec counterMask;
 
 
cf2_hintmap_init( &counterHintMap,
font,
&glyphPath.initialHintMap,
&glyphPath.hintMoves,
scaleY );
cf2_hintmask_init( &counterMask, error );
 
cf2_hintmask_read( &counterMask,
charstring,
cf2_arrstack_size( &hStemHintArray ) +
cf2_arrstack_size( &vStemHintArray ) );
cf2_hintmap_build( &counterHintMap,
&hStemHintArray,
&vStemHintArray,
&counterMask,
0,
FALSE );
}
break;
 
case cf2_cmdRMOVETO:
FT_TRACE4(( " rmoveto\n" ));
 
if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
*width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
 
/* width is defined or default after this */
haveWidth = TRUE;
 
if ( font->decoder->width_only )
goto exit;
 
curY += cf2_stack_popFixed( opStack );
curX += cf2_stack_popFixed( opStack );
 
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
 
break;
 
case cf2_cmdHMOVETO:
FT_TRACE4(( " hmoveto\n" ));
 
if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
*width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
 
/* width is defined or default after this */
haveWidth = TRUE;
 
if ( font->decoder->width_only )
goto exit;
 
curX += cf2_stack_popFixed( opStack );
 
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
 
break;
 
case cf2_cmdRLINECURVE:
{
CF2_UInt count = cf2_stack_count( opStack );
CF2_UInt index = 0;
 
 
FT_TRACE4(( " rlinecurve\n" ));
 
while ( index + 6 < count )
{
curX += cf2_stack_getReal( opStack, index + 0 );
curY += cf2_stack_getReal( opStack, index + 1 );
 
cf2_glyphpath_lineTo( &glyphPath, curX, curY );
index += 2;
}
 
while ( index < count )
{
CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
 
 
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
 
curX = x3;
curY = y3;
index += 6;
}
 
cf2_stack_clear( opStack );
}
continue; /* no need to clear stack again */
 
case cf2_cmdVVCURVETO:
{
CF2_UInt count = cf2_stack_count( opStack );
CF2_UInt index = 0;
 
 
FT_TRACE4(( " vvcurveto\n" ));
 
while ( index < count )
{
CF2_Fixed x1, y1, x2, y2, x3, y3;
 
 
if ( ( count - index ) & 1 )
{
x1 = cf2_stack_getReal( opStack, index ) + curX;
 
++index;
}
else
x1 = curX;
 
y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
x3 = x2;
y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
 
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
 
curX = x3;
curY = y3;
index += 4;
}
 
cf2_stack_clear( opStack );
}
continue; /* no need to clear stack again */
 
case cf2_cmdHHCURVETO:
{
CF2_UInt count = cf2_stack_count( opStack );
CF2_UInt index = 0;
 
 
FT_TRACE4(( " hhcurveto\n" ));
 
while ( index < count )
{
CF2_Fixed x1, y1, x2, y2, x3, y3;
 
 
if ( ( count - index ) & 1 )
{
y1 = cf2_stack_getReal( opStack, index ) + curY;
 
++index;
}
else
y1 = curY;
 
x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
y3 = y2;
 
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
 
curX = x3;
curY = y3;
index += 4;
}
 
cf2_stack_clear( opStack );
}
continue; /* no need to clear stack again */
 
case cf2_cmdVHCURVETO:
case cf2_cmdHVCURVETO:
{
CF2_UInt count = cf2_stack_count( opStack );
CF2_UInt index = 0;
 
FT_Bool alternate = op1 == cf2_cmdHVCURVETO;
 
 
FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
 
while ( index < count )
{
CF2_Fixed x1, x2, x3, y1, y2, y3;
 
 
if ( alternate )
{
x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
y1 = curY;
x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
 
if ( count - index == 5 )
{
x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
 
++index;
}
else
x3 = x2;
 
alternate = FALSE;
}
else
{
x1 = curX;
y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
 
if ( count - index == 5 )
{
y3 = cf2_stack_getReal( opStack, index + 4 ) + y2;
 
++index;
}
else
y3 = y2;
 
alternate = TRUE;
}
 
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
 
curX = x3;
curY = y3;
index += 4;
}
 
cf2_stack_clear( opStack );
}
continue; /* no need to clear stack again */
 
case cf2_cmdEXTENDEDNMBR:
{
CF2_Int v;
 
 
v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) |
cf2_buf_readByte( charstring ) );
 
FT_TRACE4(( " %d", v ));
 
cf2_stack_pushInt( opStack, v );
}
continue;
 
default:
/* numbers */
{
if ( /* op1 >= 32 && */ op1 <= 246 )
{
CF2_Int v;
 
 
v = op1 - 139;
 
FT_TRACE4(( " %d", v ));
 
/* -107 .. 107 */
cf2_stack_pushInt( opStack, v );
}
 
else if ( /* op1 >= 247 && */ op1 <= 250 )
{
CF2_Int v;
 
 
v = op1;
v -= 247;
v *= 256;
v += cf2_buf_readByte( charstring );
v += 108;
 
FT_TRACE4(( " %d", v ));
 
/* 108 .. 1131 */
cf2_stack_pushInt( opStack, v );
}
 
else if ( /* op1 >= 251 && */ op1 <= 254 )
{
CF2_Int v;
 
 
v = op1;
v -= 251;
v *= 256;
v += cf2_buf_readByte( charstring );
v = -v - 108;
 
FT_TRACE4(( " %d", v ));
 
/* -1131 .. -108 */
cf2_stack_pushInt( opStack, v );
}
 
else /* op1 == 255 */
{
CF2_Fixed v;
 
 
v = (CF2_Fixed)
( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) |
( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) |
( (FT_UInt32)cf2_buf_readByte( charstring ) << 8 ) |
(FT_UInt32)cf2_buf_readByte( charstring ) );
 
FT_TRACE4(( " %.2f", v / 65536.0 ));
 
cf2_stack_pushFixed( opStack, v );
}
}
continue; /* don't clear stack */
 
} /* end of switch statement checking `op1' */
 
cf2_stack_clear( opStack );
 
} /* end of main interpreter loop */
 
/* we get here if the charstring ends without cf2_cmdENDCHAR */
FT_TRACE4(( "cf2_interpT2CharString:"
" charstring ends without ENDCHAR\n" ));
 
exit:
/* check whether last error seen is also the first one */
cf2_setError( error, lastError );
 
/* free resources from objects we've used */
cf2_glyphpath_finalize( &glyphPath );
cf2_arrstack_finalize( &vStemHintArray );
cf2_arrstack_finalize( &hStemHintArray );
cf2_arrstack_finalize( &subrStack );
cf2_stack_free( opStack );
 
FT_TRACE4(( "\n" ));
 
return;
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2intrp.h
0,0 → 1,83
/***************************************************************************/
/* */
/* cf2font.h */
/* */
/* Adobe's CFF Interpreter (specification). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2INTRP_H__
#define __CF2INTRP_H__
 
 
#include "cf2ft.h"
#include "cf2hints.h"
 
 
FT_BEGIN_HEADER
 
 
FT_LOCAL( void )
cf2_hintmask_init( CF2_HintMask hintmask,
FT_Error* error );
FT_LOCAL( FT_Bool )
cf2_hintmask_isValid( const CF2_HintMask hintmask );
FT_LOCAL( FT_Bool )
cf2_hintmask_isNew( const CF2_HintMask hintmask );
FT_LOCAL( void )
cf2_hintmask_setNew( CF2_HintMask hintmask,
FT_Bool val );
FT_LOCAL( FT_Byte* )
cf2_hintmask_getMaskPtr( CF2_HintMask hintmask );
FT_LOCAL( void )
cf2_hintmask_setAll( CF2_HintMask hintmask,
size_t bitCount );
 
FT_LOCAL( void )
cf2_interpT2CharString( CF2_Font font,
CF2_Buffer charstring,
CF2_OutlineCallbacks callbacks,
const FT_Vector* translation,
FT_Bool doingSeac,
CF2_Fixed curX,
CF2_Fixed curY,
CF2_Fixed* width );
 
 
FT_END_HEADER
 
 
#endif /* __CF2INTRP_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2read.c
0,0 → 1,112
/***************************************************************************/
/* */
/* cf2read.c */
/* */
/* Adobe's code for stream handling (body). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H
 
#include "cf2glue.h"
 
#include "cf2error.h"
 
 
/* Define CF2_IO_FAIL as 1 to enable random errors and random */
/* value errors in I/O. */
#define CF2_IO_FAIL 0
 
 
#if CF2_IO_FAIL
 
/* set the .00 value to a nonzero probability */
static int
randomError2( void )
{
/* for region buffer ReadByte (interp) function */
return (double)rand() / RAND_MAX < .00;
}
 
/* set the .00 value to a nonzero probability */
static CF2_Int
randomValue()
{
return (double)rand() / RAND_MAX < .00 ? rand() : 0;
}
 
#endif /* CF2_IO_FAIL */
 
 
/* Region Buffer */
/* */
/* Can be constructed from a copied buffer managed by */
/* `FCM_getDatablock'. */
/* Reads bytes with check for end of buffer. */
 
/* reading past the end of the buffer sets error and returns zero */
FT_LOCAL_DEF( CF2_Int )
cf2_buf_readByte( CF2_Buffer buf )
{
if ( buf->ptr < buf->end )
{
#if CF2_IO_FAIL
if ( randomError2() )
{
CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
return 0;
}
 
return *(buf->ptr)++ + randomValue();
#else
return *(buf->ptr)++;
#endif
}
else
{
CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
return 0;
}
}
 
 
/* note: end condition can occur without error */
FT_LOCAL_DEF( FT_Bool )
cf2_buf_isEnd( CF2_Buffer buf )
{
return (FT_Bool)( buf->ptr >= buf->end );
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2read.h
0,0 → 1,68
/***************************************************************************/
/* */
/* cf2read.h */
/* */
/* Adobe's code for stream handling (specification). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2READ_H__
#define __CF2READ_H__
 
 
FT_BEGIN_HEADER
 
 
typedef struct CF2_BufferRec_
{
FT_Error* error;
const FT_Byte* start;
const FT_Byte* end;
const FT_Byte* ptr;
 
} CF2_BufferRec, *CF2_Buffer;
 
 
FT_LOCAL( CF2_Int )
cf2_buf_readByte( CF2_Buffer buf );
FT_LOCAL( FT_Bool )
cf2_buf_isEnd( CF2_Buffer buf );
 
 
FT_END_HEADER
 
 
#endif /* __CF2READ_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2stack.c
0,0 → 1,205
/***************************************************************************/
/* */
/* cf2stack.c */
/* */
/* Adobe's code for emulating a CFF stack (body). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H
 
#include "cf2glue.h"
#include "cf2font.h"
#include "cf2stack.h"
 
#include "cf2error.h"
 
 
/* Allocate and initialize an instance of CF2_Stack. */
/* Note: This function returns NULL on error (does not set */
/* `error'). */
FT_LOCAL_DEF( CF2_Stack )
cf2_stack_init( FT_Memory memory,
FT_Error* e )
{
FT_Error error = FT_Err_Ok; /* for FT_QNEW */
 
CF2_Stack stack = NULL;
 
 
if ( !FT_QNEW( stack ) )
{
/* initialize the structure; FT_QNEW zeroes it */
stack->memory = memory;
stack->error = e;
stack->top = &stack->buffer[0]; /* empty stack */
}
 
return stack;
}
 
 
FT_LOCAL_DEF( void )
cf2_stack_free( CF2_Stack stack )
{
if ( stack )
{
FT_Memory memory = stack->memory;
 
 
/* free the main structure */
FT_FREE( stack );
}
}
 
 
FT_LOCAL_DEF( CF2_UInt )
cf2_stack_count( CF2_Stack stack )
{
return (CF2_UInt)( stack->top - &stack->buffer[0] );
}
 
 
FT_LOCAL_DEF( void )
cf2_stack_pushInt( CF2_Stack stack,
CF2_Int val )
{
if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
{
CF2_SET_ERROR( stack->error, Stack_Overflow );
return; /* stack overflow */
}
 
stack->top->u.i = val;
stack->top->type = CF2_NumberInt;
++stack->top;
}
 
 
FT_LOCAL_DEF( void )
cf2_stack_pushFixed( CF2_Stack stack,
CF2_Fixed val )
{
if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
{
CF2_SET_ERROR( stack->error, Stack_Overflow );
return; /* stack overflow */
}
 
stack->top->u.r = val;
stack->top->type = CF2_NumberFixed;
++stack->top;
}
 
 
/* this function is only allowed to pop an integer type */
FT_LOCAL_DEF( CF2_Int )
cf2_stack_popInt( CF2_Stack stack )
{
if ( stack->top == &stack->buffer[0] )
{
CF2_SET_ERROR( stack->error, Stack_Underflow );
return 0; /* underflow */
}
if ( stack->top[-1].type != CF2_NumberInt )
{
CF2_SET_ERROR( stack->error, Syntax_Error );
return 0; /* type mismatch */
}
 
--stack->top;
 
return stack->top->u.i;
}
 
 
/* Note: type mismatch is silently cast */
/* TODO: check this */
FT_LOCAL_DEF( CF2_Fixed )
cf2_stack_popFixed( CF2_Stack stack )
{
if ( stack->top == &stack->buffer[0] )
{
CF2_SET_ERROR( stack->error, Stack_Underflow );
return cf2_intToFixed( 0 ); /* underflow */
}
 
--stack->top;
 
switch ( stack->top->type )
{
case CF2_NumberInt:
return cf2_intToFixed( stack->top->u.i );
case CF2_NumberFrac:
return cf2_fracToFixed( stack->top->u.f );
default:
return stack->top->u.r;
}
}
 
 
/* Note: type mismatch is silently cast */
/* TODO: check this */
FT_LOCAL_DEF( CF2_Fixed )
cf2_stack_getReal( CF2_Stack stack,
CF2_UInt idx )
{
FT_ASSERT( cf2_stack_count( stack ) <= CF2_OPERAND_STACK_SIZE );
 
if ( idx >= cf2_stack_count( stack ) )
{
CF2_SET_ERROR( stack->error, Stack_Overflow );
return cf2_intToFixed( 0 ); /* bounds error */
}
 
switch ( stack->buffer[idx].type )
{
case CF2_NumberInt:
return cf2_intToFixed( stack->buffer[idx].u.i );
case CF2_NumberFrac:
return cf2_fracToFixed( stack->buffer[idx].u.f );
default:
return stack->buffer[idx].u.r;
}
}
 
 
FT_LOCAL_DEF( void )
cf2_stack_clear( CF2_Stack stack )
{
stack->top = &stack->buffer[0];
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2stack.h
0,0 → 1,106
/***************************************************************************/
/* */
/* cf2stack.h */
/* */
/* Adobe's code for emulating a CFF stack (specification). */
/* */
/* Copyright 2007-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2STACK_H__
#define __CF2STACK_H__
 
 
FT_BEGIN_HEADER
 
 
/* CFF operand stack; specified maximum of 48 or 192 values */
typedef struct CF2_StackNumber_
{
union
{
CF2_Fixed r; /* 16.16 fixed point */
CF2_Frac f; /* 2.30 fixed point (for font matrix) */
CF2_Int i;
} u;
 
CF2_NumberType type;
 
} CF2_StackNumber;
 
 
typedef struct CF2_StackRec_
{
FT_Memory memory;
FT_Error* error;
CF2_StackNumber buffer[CF2_OPERAND_STACK_SIZE];
CF2_StackNumber* top;
 
} CF2_StackRec, *CF2_Stack;
 
 
FT_LOCAL( CF2_Stack )
cf2_stack_init( FT_Memory memory,
FT_Error* error );
FT_LOCAL( void )
cf2_stack_free( CF2_Stack stack );
 
FT_LOCAL( CF2_UInt )
cf2_stack_count( CF2_Stack stack );
 
FT_LOCAL( void )
cf2_stack_pushInt( CF2_Stack stack,
CF2_Int val );
FT_LOCAL( void )
cf2_stack_pushFixed( CF2_Stack stack,
CF2_Fixed val );
 
FT_LOCAL( CF2_Int )
cf2_stack_popInt( CF2_Stack stack );
FT_LOCAL( CF2_Fixed )
cf2_stack_popFixed( CF2_Stack stack );
 
FT_LOCAL( CF2_Fixed )
cf2_stack_getReal( CF2_Stack stack,
CF2_UInt idx );
 
FT_LOCAL( void )
cf2_stack_clear( CF2_Stack stack );
 
 
FT_END_HEADER
 
 
#endif /* __CF2STACK_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cf2types.h
0,0 → 1,78
/***************************************************************************/
/* */
/* cf2types.h */
/* */
/* Adobe's code for defining data types (specification only). */
/* */
/* Copyright 2011-2013 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
/* herein (collectively, the "Work") is made available, and may only be */
/* used, modified, and distributed under the FreeType Project License, */
/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
/* FreeType Project License, each contributor to the Work hereby grants */
/* to any individual or legal entity exercising permissions granted by */
/* the FreeType Project License and this section (hereafter, "You" or */
/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
/* royalty-free, irrevocable (except as stated in this section) patent */
/* license to make, have made, use, offer to sell, sell, import, and */
/* otherwise transfer the Work, where such license applies only to those */
/* patent claims licensable by such contributor that are necessarily */
/* infringed by their contribution(s) alone or by combination of their */
/* contribution(s) with the Work to which such contribution(s) was */
/* submitted. If You institute patent litigation against any entity */
/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
/* the Work or a contribution incorporated within the Work constitutes */
/* direct or contributory patent infringement, then any patent licenses */
/* granted to You under this License for that Work shall terminate as of */
/* the date such litigation is filed. */
/* */
/* By using, modifying, or distributing the Work you indicate that you */
/* have read and understood the terms and conditions of the */
/* FreeType Project License as well as those provided in this section, */
/* and you accept them fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CF2TYPES_H__
#define __CF2TYPES_H__
 
#include <ft2build.h>
#include FT_FREETYPE_H
 
 
FT_BEGIN_HEADER
 
 
/*
* The data models that we expect to support are as follows:
*
* name char short int long long-long pointer example
* -----------------------------------------------------
* ILP32 8 16 32 32 64* 32 32-bit MacOS, x86
* LLP64 8 16 32 32 64 64 x64
* LP64 8 16 32 64 64 64 64-bit MacOS
*
* *) type may be supported by emulation on a 32-bit architecture
*
*/
 
 
/* integers at least 32 bits wide */
#define CF2_UInt FT_UFast
#define CF2_Int FT_Fast
 
 
/* fixed-float numbers */
typedef FT_Int32 CF2_F16Dot16;
 
 
FT_END_HEADER
 
 
#endif /* __CF2TYPES_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cff.c
0,0 → 1,41
/***************************************************************************/
/* */
/* cff.c */
/* */
/* FreeType OpenType driver component (body only). */
/* */
/* Copyright 1996-2001, 2002, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#define FT_MAKE_OPTION_SINGLE_OBJECT
 
#include <ft2build.h>
 
#include "cffpic.c"
#include "cffdrivr.c"
#include "cffparse.c"
#include "cffload.c"
#include "cffobjs.c"
#include "cffgload.c"
#include "cffcmap.c"
 
#include "cf2arrst.c"
#include "cf2blues.c"
#include "cf2error.c"
#include "cf2font.c"
#include "cf2ft.c"
#include "cf2hints.c"
#include "cf2intrp.c"
#include "cf2read.c"
#include "cf2stack.c"
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffcmap.c
0,0 → 1,210
/***************************************************************************/
/* */
/* cffcmap.c */
/* */
/* CFF character mapping table (cmap) support (body). */
/* */
/* Copyright 2002-2007, 2010, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include "cffcmap.h"
#include "cffload.h"
 
#include "cfferrs.h"
 
 
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CFF STANDARD (AND EXPERT) ENCODING CMAPS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
 
FT_CALLBACK_DEF( FT_Error )
cff_cmap_encoding_init( CFF_CMapStd cmap )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( cmap );
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Encoding encoding = &cff->encoding;
 
 
cmap->gids = encoding->codes;
 
return 0;
}
 
 
FT_CALLBACK_DEF( void )
cff_cmap_encoding_done( CFF_CMapStd cmap )
{
cmap->gids = NULL;
}
 
 
FT_CALLBACK_DEF( FT_UInt )
cff_cmap_encoding_char_index( CFF_CMapStd cmap,
FT_UInt32 char_code )
{
FT_UInt result = 0;
 
 
if ( char_code < 256 )
result = cmap->gids[char_code];
 
return result;
}
 
 
FT_CALLBACK_DEF( FT_UInt32 )
cff_cmap_encoding_char_next( CFF_CMapStd cmap,
FT_UInt32 *pchar_code )
{
FT_UInt result = 0;
FT_UInt32 char_code = *pchar_code;
 
 
*pchar_code = 0;
 
if ( char_code < 255 )
{
FT_UInt code = (FT_UInt)(char_code + 1);
 
 
for (;;)
{
if ( code >= 256 )
break;
 
result = cmap->gids[code];
if ( result != 0 )
{
*pchar_code = code;
break;
}
 
code++;
}
}
return result;
}
 
 
FT_DEFINE_CMAP_CLASS(cff_cmap_encoding_class_rec,
sizeof ( CFF_CMapStdRec ),
 
(FT_CMap_InitFunc) cff_cmap_encoding_init,
(FT_CMap_DoneFunc) cff_cmap_encoding_done,
(FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,
(FT_CMap_CharNextFunc) cff_cmap_encoding_char_next,
 
NULL, NULL, NULL, NULL, NULL
)
 
 
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
 
FT_CALLBACK_DEF( const char* )
cff_sid_to_glyph_name( TT_Face face,
FT_UInt idx )
{
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Charset charset = &cff->charset;
FT_UInt sid = charset->sids[idx];
 
 
return cff_index_get_sid_string( cff, sid );
}
 
 
FT_CALLBACK_DEF( FT_Error )
cff_cmap_unicode_init( PS_Unicodes unicodes )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
FT_Memory memory = FT_FACE_MEMORY( face );
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Charset charset = &cff->charset;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
 
 
/* can't build Unicode map for CID-keyed font */
/* because we don't know glyph names. */
if ( !charset->sids )
return FT_THROW( No_Unicode_Glyph_Name );
 
return psnames->unicodes_init( memory,
unicodes,
cff->num_glyphs,
(PS_GetGlyphNameFunc)&cff_sid_to_glyph_name,
(PS_FreeGlyphNameFunc)NULL,
(FT_Pointer)face );
}
 
 
FT_CALLBACK_DEF( void )
cff_cmap_unicode_done( PS_Unicodes unicodes )
{
FT_Face face = FT_CMAP_FACE( unicodes );
FT_Memory memory = FT_FACE_MEMORY( face );
 
 
FT_FREE( unicodes->maps );
unicodes->num_maps = 0;
}
 
 
FT_CALLBACK_DEF( FT_UInt )
cff_cmap_unicode_char_index( PS_Unicodes unicodes,
FT_UInt32 char_code )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
CFF_Font cff = (CFF_Font)face->extra.data;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
 
 
return psnames->unicodes_char_index( unicodes, char_code );
}
 
 
FT_CALLBACK_DEF( FT_UInt32 )
cff_cmap_unicode_char_next( PS_Unicodes unicodes,
FT_UInt32 *pchar_code )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
CFF_Font cff = (CFF_Font)face->extra.data;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
 
 
return psnames->unicodes_char_next( unicodes, pchar_code );
}
 
 
FT_DEFINE_CMAP_CLASS(cff_cmap_unicode_class_rec,
sizeof ( PS_UnicodesRec ),
 
(FT_CMap_InitFunc) cff_cmap_unicode_init,
(FT_CMap_DoneFunc) cff_cmap_unicode_done,
(FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,
(FT_CMap_CharNextFunc) cff_cmap_unicode_char_next,
 
NULL, NULL, NULL, NULL, NULL
)
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffcmap.h
0,0 → 1,67
/***************************************************************************/
/* */
/* cffcmap.h */
/* */
/* CFF character mapping table (cmap) support (specification). */
/* */
/* Copyright 2002, 2003, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFFCMAP_H__
#define __CFFCMAP_H__
 
#include "cffobjs.h"
 
FT_BEGIN_HEADER
 
 
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
 
/* standard (and expert) encoding cmaps */
typedef struct CFF_CMapStdRec_* CFF_CMapStd;
 
typedef struct CFF_CMapStdRec_
{
FT_CMapRec cmap;
FT_UShort* gids; /* up to 256 elements */
 
} CFF_CMapStdRec;
 
 
FT_DECLARE_CMAP_CLASS(cff_cmap_encoding_class_rec)
 
 
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
 
/* unicode (synthetic) cmaps */
 
FT_DECLARE_CMAP_CLASS(cff_cmap_unicode_class_rec)
 
 
FT_END_HEADER
 
#endif /* __CFFCMAP_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffdrivr.c
0,0 → 1,786
/***************************************************************************/
/* */
/* cffdrivr.c */
/* */
/* OpenType font driver implementation (body). */
/* */
/* Copyright 1996-2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_SERVICE_CID_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
#include FT_SERVICE_POSTSCRIPT_NAME_H
#include FT_SERVICE_TT_CMAP_H
 
#include "cffdrivr.h"
#include "cffgload.h"
#include "cffload.h"
#include "cffcmap.h"
#include "cffparse.h"
 
#include "cfferrs.h"
#include "cffpic.h"
 
#include FT_SERVICE_XFREE86_NAME_H
#include FT_SERVICE_GLYPH_DICT_H
#include FT_SERVICE_PROPERTIES_H
#include FT_CFF_DRIVER_H
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cffdriver
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** F A C E S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
 
#undef PAIR_TAG
#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
(FT_ULong)right )
 
 
/*************************************************************************/
/* */
/* <Function> */
/* cff_get_kerning */
/* */
/* <Description> */
/* A driver method used to return the kerning vector between two */
/* glyphs of the same face. */
/* */
/* <Input> */
/* face :: A handle to the source face object. */
/* */
/* left_glyph :: The index of the left glyph in the kern pair. */
/* */
/* right_glyph :: The index of the right glyph in the kern pair. */
/* */
/* <Output> */
/* kerning :: The kerning vector. This is in font units for */
/* scalable formats, and in pixels for fixed-sizes */
/* formats. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
/* <Note> */
/* Only horizontal layouts (left-to-right & right-to-left) are */
/* supported by this function. Other layouts, or more sophisticated */
/* kernings, are out of scope of this method (the basic driver */
/* interface is meant to be simple). */
/* */
/* They can be implemented by format-specific interfaces. */
/* */
FT_CALLBACK_DEF( FT_Error )
cff_get_kerning( FT_Face ttface, /* TT_Face */
FT_UInt left_glyph,
FT_UInt right_glyph,
FT_Vector* kerning )
{
TT_Face face = (TT_Face)ttface;
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
 
 
kerning->x = 0;
kerning->y = 0;
 
if ( sfnt )
kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
 
return FT_Err_Ok;
}
 
 
#undef PAIR_TAG
 
 
/*************************************************************************/
/* */
/* <Function> */
/* cff_glyph_load */
/* */
/* <Description> */
/* A driver method used to load a glyph within a given glyph slot. */
/* */
/* <Input> */
/* slot :: A handle to the target slot object where the glyph */
/* will be loaded. */
/* */
/* size :: A handle to the source face size at which the glyph */
/* must be scaled, loaded, etc. */
/* */
/* glyph_index :: The index of the glyph in the font file. */
/* */
/* load_flags :: A flag indicating what to load for this glyph. The */
/* FT_LOAD_??? constants can be used to control the */
/* glyph loading process (e.g., whether the outline */
/* should be scaled, whether to load bitmaps or not, */
/* whether to hint the outline, etc). */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_CALLBACK_DEF( FT_Error )
cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */
FT_Size cffsize, /* CFF_Size */
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_Error error;
CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot;
CFF_Size size = (CFF_Size)cffsize;
 
 
if ( !slot )
return FT_THROW( Invalid_Slot_Handle );
 
/* check whether we want a scaled outline or bitmap */
if ( !size )
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
 
/* reset the size object if necessary */
if ( load_flags & FT_LOAD_NO_SCALE )
size = NULL;
 
if ( size )
{
/* these two objects must have the same parent */
if ( cffsize->face != cffslot->face )
return FT_THROW( Invalid_Face_Handle );
}
 
/* now load the glyph outline if necessary */
error = cff_slot_load( slot, size, glyph_index, load_flags );
 
/* force drop-out mode to 2 - irrelevant now */
/* slot->outline.dropout_mode = 2; */
 
return error;
}
 
 
FT_CALLBACK_DEF( FT_Error )
cff_get_advances( FT_Face face,
FT_UInt start,
FT_UInt count,
FT_Int32 flags,
FT_Fixed* advances )
{
FT_UInt nn;
FT_Error error = FT_Err_Ok;
FT_GlyphSlot slot = face->glyph;
 
 
flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
 
for ( nn = 0; nn < count; nn++ )
{
error = cff_glyph_load( slot, face->size, start + nn, flags );
if ( error )
break;
 
advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
? slot->linearVertAdvance
: slot->linearHoriAdvance;
}
 
return error;
}
 
 
/*
* GLYPH DICT SERVICE
*
*/
 
static FT_Error
cff_get_glyph_name( CFF_Face face,
FT_UInt glyph_index,
FT_Pointer buffer,
FT_UInt buffer_max )
{
CFF_Font font = (CFF_Font)face->extra.data;
FT_String* gname;
FT_UShort sid;
FT_Error error;
 
 
if ( !font->psnames )
{
FT_ERROR(( "cff_get_glyph_name:"
" cannot get glyph name from CFF & CEF fonts\n"
" "
" without the `PSNames' module\n" ));
error = FT_THROW( Missing_Module );
goto Exit;
}
 
/* first, locate the sid in the charset table */
sid = font->charset.sids[glyph_index];
 
/* now, lookup the name itself */
gname = cff_index_get_sid_string( font, sid );
 
if ( gname )
FT_STRCPYN( buffer, gname, buffer_max );
 
error = FT_Err_Ok;
 
Exit:
return error;
}
 
 
static FT_UInt
cff_get_name_index( CFF_Face face,
FT_String* glyph_name )
{
CFF_Font cff;
CFF_Charset charset;
FT_Service_PsCMaps psnames;
FT_String* name;
FT_UShort sid;
FT_UInt i;
 
 
cff = (CFF_FontRec *)face->extra.data;
charset = &cff->charset;
 
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
if ( !psnames )
return 0;
 
for ( i = 0; i < cff->num_glyphs; i++ )
{
sid = charset->sids[i];
 
if ( sid > 390 )
name = cff_index_get_string( cff, sid - 391 );
else
name = (FT_String *)psnames->adobe_std_strings( sid );
 
if ( !name )
continue;
 
if ( !ft_strcmp( glyph_name, name ) )
return i;
}
 
return 0;
}
 
 
FT_DEFINE_SERVICE_GLYPHDICTREC(
cff_service_glyph_dict,
(FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
(FT_GlyphDict_NameIndexFunc)cff_get_name_index
)
 
 
/*
* POSTSCRIPT INFO SERVICE
*
*/
 
static FT_Int
cff_ps_has_glyph_names( FT_Face face )
{
return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
}
 
 
static FT_Error
cff_ps_get_font_info( CFF_Face face,
PS_FontInfoRec* afont_info )
{
CFF_Font cff = (CFF_Font)face->extra.data;
FT_Error error = FT_Err_Ok;
 
 
if ( cff && cff->font_info == NULL )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
PS_FontInfoRec *font_info = NULL;
FT_Memory memory = face->root.memory;
 
 
if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
goto Fail;
 
font_info->version = cff_index_get_sid_string( cff,
dict->version );
font_info->notice = cff_index_get_sid_string( cff,
dict->notice );
font_info->full_name = cff_index_get_sid_string( cff,
dict->full_name );
font_info->family_name = cff_index_get_sid_string( cff,
dict->family_name );
font_info->weight = cff_index_get_sid_string( cff,
dict->weight );
font_info->italic_angle = dict->italic_angle;
font_info->is_fixed_pitch = dict->is_fixed_pitch;
font_info->underline_position = (FT_Short)dict->underline_position;
font_info->underline_thickness = (FT_Short)dict->underline_thickness;
 
cff->font_info = font_info;
}
 
if ( cff )
*afont_info = *cff->font_info;
 
Fail:
return error;
}
 
 
FT_DEFINE_SERVICE_PSINFOREC(
cff_service_ps_info,
(PS_GetFontInfoFunc) cff_ps_get_font_info,
(PS_GetFontExtraFunc) NULL,
(PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
(PS_GetFontPrivateFunc)NULL, /* unsupported with CFF fonts */
(PS_GetFontValueFunc) NULL /* not implemented */
)
 
 
/*
* POSTSCRIPT NAME SERVICE
*
*/
 
static const char*
cff_get_ps_name( CFF_Face face )
{
CFF_Font cff = (CFF_Font)face->extra.data;
 
 
return (const char*)cff->font_name;
}
 
 
FT_DEFINE_SERVICE_PSFONTNAMEREC(
cff_service_ps_name,
(FT_PsName_GetFunc)cff_get_ps_name
)
 
 
/*
* TT CMAP INFO
*
* If the charmap is a synthetic Unicode encoding cmap or
* a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
* service defined in SFNT module.
*
* Otherwise call the service function in the sfnt module.
*
*/
static FT_Error
cff_get_cmap_info( FT_CharMap charmap,
TT_CMapInfo *cmap_info )
{
FT_CMap cmap = FT_CMAP( charmap );
FT_Error error = FT_Err_Ok;
 
FT_Face face = FT_CMAP_FACE( cmap );
FT_Library library = FT_FACE_LIBRARY( face );
 
 
cmap_info->language = 0;
cmap_info->format = 0;
 
if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET )
{
FT_Module sfnt = FT_Get_Module( library, "sfnt" );
FT_Service_TTCMaps service =
(FT_Service_TTCMaps)ft_module_get_service( sfnt,
FT_SERVICE_ID_TT_CMAP );
 
 
if ( service && service->get_cmap_info )
error = service->get_cmap_info( charmap, cmap_info );
}
 
return error;
}
 
 
FT_DEFINE_SERVICE_TTCMAPSREC(
cff_service_get_cmap_info,
(TT_CMap_Info_GetFunc)cff_get_cmap_info
)
 
 
/*
* CID INFO SERVICE
*
*/
static FT_Error
cff_get_ros( CFF_Face face,
const char* *registry,
const char* *ordering,
FT_Int *supplement )
{
FT_Error error = FT_Err_Ok;
CFF_Font cff = (CFF_Font)face->extra.data;
 
 
if ( cff )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
 
 
if ( dict->cid_registry == 0xFFFFU )
{
error = FT_THROW( Invalid_Argument );
goto Fail;
}
 
if ( registry )
{
if ( cff->registry == NULL )
cff->registry = cff_index_get_sid_string( cff,
dict->cid_registry );
*registry = cff->registry;
}
 
if ( ordering )
{
if ( cff->ordering == NULL )
cff->ordering = cff_index_get_sid_string( cff,
dict->cid_ordering );
*ordering = cff->ordering;
}
 
/*
* XXX: According to Adobe TechNote #5176, the supplement in CFF
* can be a real number. We truncate it to fit public API
* since freetype-2.3.6.
*/
if ( supplement )
{
if ( dict->cid_supplement < FT_INT_MIN ||
dict->cid_supplement > FT_INT_MAX )
FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
dict->cid_supplement ));
*supplement = (FT_Int)dict->cid_supplement;
}
}
 
Fail:
return error;
}
 
 
static FT_Error
cff_get_is_cid( CFF_Face face,
FT_Bool *is_cid )
{
FT_Error error = FT_Err_Ok;
CFF_Font cff = (CFF_Font)face->extra.data;
 
 
*is_cid = 0;
 
if ( cff )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
 
 
if ( dict->cid_registry != 0xFFFFU )
*is_cid = 1;
}
 
return error;
}
 
 
static FT_Error
cff_get_cid_from_glyph_index( CFF_Face face,
FT_UInt glyph_index,
FT_UInt *cid )
{
FT_Error error = FT_Err_Ok;
CFF_Font cff;
 
 
cff = (CFF_Font)face->extra.data;
 
if ( cff )
{
FT_UInt c;
CFF_FontRecDict dict = &cff->top_font.font_dict;
 
 
if ( dict->cid_registry == 0xFFFFU )
{
error = FT_THROW( Invalid_Argument );
goto Fail;
}
 
if ( glyph_index > cff->num_glyphs )
{
error = FT_THROW( Invalid_Argument );
goto Fail;
}
 
c = cff->charset.sids[glyph_index];
 
if ( cid )
*cid = c;
}
 
Fail:
return error;
}
 
 
FT_DEFINE_SERVICE_CIDREC(
cff_service_cid_info,
(FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
(FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid,
(FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index
)
 
 
/*
* PROPERTY SERVICE
*
*/
static FT_Error
cff_property_set( FT_Module module, /* CFF_Driver */
const char* property_name,
const void* value )
{
FT_Error error = FT_Err_Ok;
CFF_Driver driver = (CFF_Driver)module;
 
 
if ( !ft_strcmp( property_name, "hinting-engine" ) )
{
FT_UInt* hinting_engine = (FT_UInt*)value;
 
 
#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
error = FT_ERR( Unimplemented_Feature );
else
#endif
driver->hinting_engine = *hinting_engine;
 
return error;
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
FT_Bool* no_stem_darkening = (FT_Bool*)value;
 
 
driver->no_stem_darkening = *no_stem_darkening;
 
return error;
}
 
FT_TRACE0(( "cff_property_set: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
 
 
static FT_Error
cff_property_get( FT_Module module, /* CFF_Driver */
const char* property_name,
const void* value )
{
FT_Error error = FT_Err_Ok;
CFF_Driver driver = (CFF_Driver)module;
 
FT_UInt hinting_engine = driver->hinting_engine;
FT_Bool no_stem_darkening = driver->no_stem_darkening;
 
 
if ( !ft_strcmp( property_name, "hinting-engine" ) )
{
FT_UInt* val = (FT_UInt*)value;
 
 
*val = hinting_engine;
 
return error;
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
FT_Bool* val = (FT_Bool*)value;
 
 
*val = no_stem_darkening;
 
return error;
}
 
FT_TRACE0(( "cff_property_get: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
 
 
FT_DEFINE_SERVICE_PROPERTIESREC(
cff_service_properties,
(FT_Properties_SetFunc)cff_property_set,
(FT_Properties_GetFunc)cff_property_get )
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** D R I V E R I N T E R F A C E ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
FT_DEFINE_SERVICEDESCREC7(
cff_services,
FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET,
FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
)
#else
FT_DEFINE_SERVICEDESCREC6(
cff_services,
FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
)
#endif
 
 
FT_CALLBACK_DEF( FT_Module_Interface )
cff_get_interface( FT_Module driver, /* CFF_Driver */
const char* module_interface )
{
FT_Library library;
FT_Module sfnt;
FT_Module_Interface result;
 
 
/* CFF_SERVICES_GET derefers `library' in PIC mode */
#ifdef FT_CONFIG_OPTION_PIC
if ( !driver )
return NULL;
library = driver->library;
if ( !library )
return NULL;
#endif
 
result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
if ( result != NULL )
return result;
 
/* `driver' is not yet evaluated in non-PIC mode */
#ifndef FT_CONFIG_OPTION_PIC
if ( !driver )
return NULL;
library = driver->library;
if ( !library )
return NULL;
#endif
 
/* we pass our request to the `sfnt' module */
sfnt = FT_Get_Module( library, "sfnt" );
 
return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
}
 
 
/* The FT_DriverInterface structure is defined in ftdriver.h. */
 
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
#define CFF_SIZE_SELECT cff_size_select
#else
#define CFF_SIZE_SELECT 0
#endif
 
FT_DEFINE_DRIVER(
cff_driver_class,
 
FT_MODULE_FONT_DRIVER |
FT_MODULE_DRIVER_SCALABLE |
FT_MODULE_DRIVER_HAS_HINTER,
 
sizeof ( CFF_DriverRec ),
"cff",
0x10000L,
0x20000L,
 
0, /* module-specific interface */
 
cff_driver_init,
cff_driver_done,
cff_get_interface,
 
/* now the specific driver fields */
sizeof ( TT_FaceRec ),
sizeof ( CFF_SizeRec ),
sizeof ( CFF_GlyphSlotRec ),
 
cff_face_init,
cff_face_done,
cff_size_init,
cff_size_done,
cff_slot_init,
cff_slot_done,
 
cff_glyph_load,
 
cff_get_kerning,
0, /* FT_Face_AttachFunc */
cff_get_advances,
 
cff_size_request,
 
CFF_SIZE_SELECT
)
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffdrivr.h
0,0 → 1,38
/***************************************************************************/
/* */
/* cffdrivr.h */
/* */
/* High-level OpenType driver interface (specification). */
/* */
/* Copyright 1996-2001, 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFFDRIVER_H__
#define __CFFDRIVER_H__
 
 
#include <ft2build.h>
#include FT_INTERNAL_DRIVER_H
 
 
FT_BEGIN_HEADER
 
 
FT_DECLARE_DRIVER( cff_driver_class )
 
 
FT_END_HEADER
 
#endif /* __CFFDRIVER_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cfferrs.h
0,0 → 1,42
/***************************************************************************/
/* */
/* cfferrs.h */
/* */
/* CFF error codes (specification only). */
/* */
/* Copyright 2001, 2012 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
/*************************************************************************/
/* */
/* This file is used to define the CFF error enumeration constants. */
/* */
/*************************************************************************/
 
#ifndef __CFFERRS_H__
#define __CFFERRS_H__
 
#include FT_MODULE_ERRORS_H
 
#undef __FTERRORS_H__
 
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX CFF_Err_
#define FT_ERR_BASE FT_Mod_Err_CFF
 
 
#include FT_ERRORS_H
 
#endif /* __CFFERRS_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffgload.c
0,0 → 1,3068
/***************************************************************************/
/* */
/* cffgload.c */
/* */
/* OpenType Glyph Loader (body). */
/* */
/* Copyright 1996-2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_OUTLINE_H
#include FT_CFF_DRIVER_H
 
#include "cffobjs.h"
#include "cffload.h"
#include "cffgload.h"
#include "cf2ft.h" /* for cf2_decoder_parse_charstrings */
 
#include "cfferrs.h"
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cffgload
 
 
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
 
typedef enum CFF_Operator_
{
cff_op_unknown = 0,
 
cff_op_rmoveto,
cff_op_hmoveto,
cff_op_vmoveto,
 
cff_op_rlineto,
cff_op_hlineto,
cff_op_vlineto,
 
cff_op_rrcurveto,
cff_op_hhcurveto,
cff_op_hvcurveto,
cff_op_rcurveline,
cff_op_rlinecurve,
cff_op_vhcurveto,
cff_op_vvcurveto,
 
cff_op_flex,
cff_op_hflex,
cff_op_hflex1,
cff_op_flex1,
 
cff_op_endchar,
 
cff_op_hstem,
cff_op_vstem,
cff_op_hstemhm,
cff_op_vstemhm,
 
cff_op_hintmask,
cff_op_cntrmask,
cff_op_dotsection, /* deprecated, acts as no-op */
 
cff_op_abs,
cff_op_add,
cff_op_sub,
cff_op_div,
cff_op_neg,
cff_op_random,
cff_op_mul,
cff_op_sqrt,
 
cff_op_blend,
 
cff_op_drop,
cff_op_exch,
cff_op_index,
cff_op_roll,
cff_op_dup,
 
cff_op_put,
cff_op_get,
cff_op_store,
cff_op_load,
 
cff_op_and,
cff_op_or,
cff_op_not,
cff_op_eq,
cff_op_ifelse,
 
cff_op_callsubr,
cff_op_callgsubr,
cff_op_return,
 
/* Type 1 opcodes: invalid but seen in real life */
cff_op_hsbw,
cff_op_closepath,
cff_op_callothersubr,
cff_op_pop,
cff_op_seac,
cff_op_sbw,
cff_op_setcurrentpoint,
 
/* do not remove */
cff_op_max
 
} CFF_Operator;
 
 
#define CFF_COUNT_CHECK_WIDTH 0x80
#define CFF_COUNT_EXACT 0x40
#define CFF_COUNT_CLEAR_STACK 0x20
 
/* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
/* used for checking the width and requested numbers of arguments */
/* only; they are set to zero afterwards */
 
/* the other two flags are informative only and unused currently */
 
static const FT_Byte cff_argument_counts[] =
{
0, /* unknown */
 
2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
 
0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
 
0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
 
13, /* flex */
7,
9,
11,
 
0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
 
2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
2 | CFF_COUNT_CHECK_WIDTH,
2 | CFF_COUNT_CHECK_WIDTH,
2 | CFF_COUNT_CHECK_WIDTH,
 
0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
0, /* dotsection */
 
1, /* abs */
2,
2,
2,
1,
0,
2,
1,
 
1, /* blend */
 
1, /* drop */
2,
1,
2,
1,
 
2, /* put */
1,
4,
3,
 
2, /* and */
2,
1,
2,
4,
 
1, /* callsubr */
1,
0,
 
2, /* hsbw */
0,
0,
0,
5, /* seac */
4, /* sbw */
2 /* setcurrentpoint */
};
 
#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/********** *********/
/********** *********/
/********** GENERIC CHARSTRING PARSING *********/
/********** *********/
/********** *********/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
 
/*************************************************************************/
/* */
/* <Function> */
/* cff_builder_init */
/* */
/* <Description> */
/* Initializes a given glyph builder. */
/* */
/* <InOut> */
/* builder :: A pointer to the glyph builder to initialize. */
/* */
/* <Input> */
/* face :: The current face object. */
/* */
/* size :: The current size object. */
/* */
/* glyph :: The current glyph object. */
/* */
/* hinting :: Whether hinting is active. */
/* */
static void
cff_builder_init( CFF_Builder* builder,
TT_Face face,
CFF_Size size,
CFF_GlyphSlot glyph,
FT_Bool hinting )
{
builder->path_begun = 0;
builder->load_points = 1;
 
builder->face = face;
builder->glyph = glyph;
builder->memory = face->root.memory;
 
if ( glyph )
{
FT_GlyphLoader loader = glyph->root.internal->loader;
 
 
builder->loader = loader;
builder->base = &loader->base.outline;
builder->current = &loader->current.outline;
FT_GlyphLoader_Rewind( loader );
 
builder->hints_globals = 0;
builder->hints_funcs = 0;
 
if ( hinting && size )
{
CFF_Internal internal = (CFF_Internal)size->root.internal;
 
 
builder->hints_globals = (void *)internal->topfont;
builder->hints_funcs = glyph->root.internal->glyph_hints;
}
}
 
builder->pos_x = 0;
builder->pos_y = 0;
 
builder->left_bearing.x = 0;
builder->left_bearing.y = 0;
builder->advance.x = 0;
builder->advance.y = 0;
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* cff_builder_done */
/* */
/* <Description> */
/* Finalizes a given glyph builder. Its contents can still be used */
/* after the call, but the function saves important information */
/* within the corresponding glyph slot. */
/* */
/* <Input> */
/* builder :: A pointer to the glyph builder to finalize. */
/* */
static void
cff_builder_done( CFF_Builder* builder )
{
CFF_GlyphSlot glyph = builder->glyph;
 
 
if ( glyph )
glyph->root.outline = *builder->base;
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* cff_compute_bias */
/* */
/* <Description> */
/* Computes the bias value in dependence of the number of glyph */
/* subroutines. */
/* */
/* <Input> */
/* in_charstring_type :: The `CharstringType' value of the top DICT */
/* dictionary. */
/* */
/* num_subrs :: The number of glyph subroutines. */
/* */
/* <Return> */
/* The bias value. */
static FT_Int
cff_compute_bias( FT_Int in_charstring_type,
FT_UInt num_subrs )
{
FT_Int result;
 
 
if ( in_charstring_type == 1 )
result = 0;
else if ( num_subrs < 1240 )
result = 107;
else if ( num_subrs < 33900U )
result = 1131;
else
result = 32768U;
 
return result;
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* cff_decoder_init */
/* */
/* <Description> */
/* Initializes a given glyph decoder. */
/* */
/* <InOut> */
/* decoder :: A pointer to the glyph builder to initialize. */
/* */
/* <Input> */
/* face :: The current face object. */
/* */
/* size :: The current size object. */
/* */
/* slot :: The current glyph object. */
/* */
/* hinting :: Whether hinting is active. */
/* */
/* hint_mode :: The hinting mode. */
/* */
FT_LOCAL_DEF( void )
cff_decoder_init( CFF_Decoder* decoder,
TT_Face face,
CFF_Size size,
CFF_GlyphSlot slot,
FT_Bool hinting,
FT_Render_Mode hint_mode )
{
CFF_Font cff = (CFF_Font)face->extra.data;
 
 
/* clear everything */
FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
 
/* initialize builder */
cff_builder_init( &decoder->builder, face, size, slot, hinting );
 
/* initialize Type2 decoder */
decoder->cff = cff;
decoder->num_globals = cff->global_subrs_index.count;
decoder->globals = cff->global_subrs;
decoder->globals_bias = cff_compute_bias(
cff->top_font.font_dict.charstring_type,
decoder->num_globals );
 
decoder->hint_mode = hint_mode;
}
 
 
/* this function is used to select the subfont */
/* and the locals subrs array */
FT_LOCAL_DEF( FT_Error )
cff_decoder_prepare( CFF_Decoder* decoder,
CFF_Size size,
FT_UInt glyph_index )
{
CFF_Builder *builder = &decoder->builder;
CFF_Font cff = (CFF_Font)builder->face->extra.data;
CFF_SubFont sub = &cff->top_font;
FT_Error error = FT_Err_Ok;
 
 
/* manage CID fonts */
if ( cff->num_subfonts )
{
FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
 
 
if ( fd_index >= cff->num_subfonts )
{
FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
 
FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index ));
 
sub = cff->subfonts[fd_index];
 
if ( builder->hints_funcs && size )
{
CFF_Internal internal = (CFF_Internal)size->root.internal;
 
 
/* for CFFs without subfonts, this value has already been set */
builder->hints_globals = (void *)internal->subfonts[fd_index];
}
}
#ifdef FT_DEBUG_LEVEL_TRACE
else
FT_TRACE3(( "glyph index %d:\n", glyph_index ));
#endif
 
decoder->num_locals = sub->local_subrs_index.count;
decoder->locals = sub->local_subrs;
decoder->locals_bias = cff_compute_bias(
decoder->cff->top_font.font_dict.charstring_type,
decoder->num_locals );
 
decoder->glyph_width = sub->private_dict.default_width;
decoder->nominal_width = sub->private_dict.nominal_width;
 
decoder->current_subfont = sub; /* for Adobe's CFF handler */
 
Exit:
return error;
}
 
 
/* check that there is enough space for `count' more points */
FT_LOCAL_DEF( FT_Error )
cff_check_points( CFF_Builder* builder,
FT_Int count )
{
return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
}
 
 
/* add a new point, do not check space */
FT_LOCAL_DEF( void )
cff_builder_add_point( CFF_Builder* builder,
FT_Pos x,
FT_Pos y,
FT_Byte flag )
{
FT_Outline* outline = builder->current;
 
 
if ( builder->load_points )
{
FT_Vector* point = outline->points + outline->n_points;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
 
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face );
 
 
if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
{
point->x = x >> 16;
point->y = y >> 16;
}
else
#endif
{
/* cf2_decoder_parse_charstrings uses 16.16 coordinates */
point->x = x >> 10;
point->y = y >> 10;
}
*control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
}
 
outline->n_points++;
}
 
 
/* check space for a new on-curve point, then add it */
FT_LOCAL_DEF( FT_Error )
cff_builder_add_point1( CFF_Builder* builder,
FT_Pos x,
FT_Pos y )
{
FT_Error error;
 
 
error = cff_check_points( builder, 1 );
if ( !error )
cff_builder_add_point( builder, x, y, 1 );
 
return error;
}
 
 
/* check space for a new contour, then add it */
static FT_Error
cff_builder_add_contour( CFF_Builder* builder )
{
FT_Outline* outline = builder->current;
FT_Error error;
 
 
if ( !builder->load_points )
{
outline->n_contours++;
return FT_Err_Ok;
}
 
error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
if ( !error )
{
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
 
outline->n_contours++;
}
 
return error;
}
 
 
/* if a path was begun, add its first on-curve point */
FT_LOCAL_DEF( FT_Error )
cff_builder_start_point( CFF_Builder* builder,
FT_Pos x,
FT_Pos y )
{
FT_Error error = FT_Err_Ok;
 
 
/* test whether we are building a new contour */
if ( !builder->path_begun )
{
builder->path_begun = 1;
error = cff_builder_add_contour( builder );
if ( !error )
error = cff_builder_add_point1( builder, x, y );
}
 
return error;
}
 
 
/* close the current contour */
FT_LOCAL_DEF( void )
cff_builder_close_contour( CFF_Builder* builder )
{
FT_Outline* outline = builder->current;
FT_Int first;
 
 
if ( !outline )
return;
 
first = outline->n_contours <= 1
? 0 : outline->contours[outline->n_contours - 2] + 1;
 
/* We must not include the last point in the path if it */
/* is located on the first point. */
if ( outline->n_points > 1 )
{
FT_Vector* p1 = outline->points + first;
FT_Vector* p2 = outline->points + outline->n_points - 1;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
 
 
/* `delete' last point only if it coincides with the first */
/* point and if it is not a control point (which can happen). */
if ( p1->x == p2->x && p1->y == p2->y )
if ( *control == FT_CURVE_TAG_ON )
outline->n_points--;
}
 
if ( outline->n_contours > 0 )
{
/* Don't add contours only consisting of one point, i.e., */
/* check whether begin point and last point are the same. */
if ( first == outline->n_points - 1 )
{
outline->n_contours--;
outline->n_points--;
}
else
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
}
}
 
 
FT_LOCAL_DEF( FT_Int )
cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
FT_Int charcode )
{
FT_UInt n;
FT_UShort glyph_sid;
 
 
/* CID-keyed fonts don't have glyph names */
if ( !cff->charset.sids )
return -1;
 
/* check range of standard char code */
if ( charcode < 0 || charcode > 255 )
return -1;
 
/* Get code to SID mapping from `cff_standard_encoding'. */
glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
 
for ( n = 0; n < cff->num_glyphs; n++ )
{
if ( cff->charset.sids[n] == glyph_sid )
return n;
}
 
return -1;
}
 
 
FT_LOCAL_DEF( FT_Error )
cff_get_glyph_data( TT_Face face,
FT_UInt glyph_index,
FT_Byte** pointer,
FT_ULong* length )
{
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* For incremental fonts get the character data using the */
/* callback function. */
if ( face->root.internal->incremental_interface )
{
FT_Data data;
FT_Error error =
face->root.internal->incremental_interface->funcs->get_glyph_data(
face->root.internal->incremental_interface->object,
glyph_index, &data );
 
 
*pointer = (FT_Byte*)data.pointer;
*length = data.length;
 
return error;
}
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
{
CFF_Font cff = (CFF_Font)(face->extra.data);
 
 
return cff_index_access_element( &cff->charstrings_index, glyph_index,
pointer, length );
}
}
 
 
FT_LOCAL_DEF( void )
cff_free_glyph_data( TT_Face face,
FT_Byte** pointer,
FT_ULong length )
{
#ifndef FT_CONFIG_OPTION_INCREMENTAL
FT_UNUSED( length );
#endif
 
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* For incremental fonts get the character data using the */
/* callback function. */
if ( face->root.internal->incremental_interface )
{
FT_Data data;
 
 
data.pointer = *pointer;
data.length = length;
 
face->root.internal->incremental_interface->funcs->free_glyph_data(
face->root.internal->incremental_interface->object, &data );
}
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
{
CFF_Font cff = (CFF_Font)(face->extra.data);
 
 
cff_index_forget_element( &cff->charstrings_index, pointer );
}
}
 
 
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
 
static FT_Error
cff_operator_seac( CFF_Decoder* decoder,
FT_Pos asb,
FT_Pos adx,
FT_Pos ady,
FT_Int bchar,
FT_Int achar )
{
FT_Error error;
CFF_Builder* builder = &decoder->builder;
FT_Int bchar_index, achar_index;
TT_Face face = decoder->builder.face;
FT_Vector left_bearing, advance;
FT_Byte* charstring;
FT_ULong charstring_len;
FT_Pos glyph_width;
 
 
if ( decoder->seac )
{
FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
return FT_THROW( Syntax_Error );
}
 
adx += decoder->builder.left_bearing.x;
ady += decoder->builder.left_bearing.y;
 
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* Incremental fonts don't necessarily have valid charsets. */
/* They use the character code, not the glyph index, in this case. */
if ( face->root.internal->incremental_interface )
{
bchar_index = bchar;
achar_index = achar;
}
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
CFF_Font cff = (CFF_Font)(face->extra.data);
 
 
bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
}
 
if ( bchar_index < 0 || achar_index < 0 )
{
FT_ERROR(( "cff_operator_seac:"
" invalid seac character code arguments\n" ));
return FT_THROW( Syntax_Error );
}
 
/* If we are trying to load a composite glyph, do not load the */
/* accent character and return the array of subglyphs. */
if ( builder->no_recurse )
{
FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
FT_GlyphLoader loader = glyph->internal->loader;
FT_SubGlyph subg;
 
 
/* reallocate subglyph array if necessary */
error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
if ( error )
goto Exit;
 
subg = loader->current.subglyphs;
 
/* subglyph 0 = base character */
subg->index = bchar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
FT_SUBGLYPH_FLAG_USE_MY_METRICS;
subg->arg1 = 0;
subg->arg2 = 0;
subg++;
 
/* subglyph 1 = accent character */
subg->index = achar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
subg->arg1 = (FT_Int)( adx >> 16 );
subg->arg2 = (FT_Int)( ady >> 16 );
 
/* set up remaining glyph fields */
glyph->num_subglyphs = 2;
glyph->subglyphs = loader->base.subglyphs;
glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
 
loader->current.num_subglyphs = 2;
}
 
FT_GlyphLoader_Prepare( builder->loader );
 
/* First load `bchar' in builder */
error = cff_get_glyph_data( face, bchar_index,
&charstring, &charstring_len );
if ( !error )
{
/* the seac operator must not be nested */
decoder->seac = TRUE;
error = cff_decoder_parse_charstrings( decoder, charstring,
charstring_len );
decoder->seac = FALSE;
 
cff_free_glyph_data( face, &charstring, charstring_len );
 
if ( error )
goto Exit;
}
 
/* Save the left bearing, advance and glyph width of the base */
/* character as they will be erased by the next load. */
 
left_bearing = builder->left_bearing;
advance = builder->advance;
glyph_width = decoder->glyph_width;
 
builder->left_bearing.x = 0;
builder->left_bearing.y = 0;
 
builder->pos_x = adx - asb;
builder->pos_y = ady;
 
/* Now load `achar' on top of the base outline. */
error = cff_get_glyph_data( face, achar_index,
&charstring, &charstring_len );
if ( !error )
{
/* the seac operator must not be nested */
decoder->seac = TRUE;
error = cff_decoder_parse_charstrings( decoder, charstring,
charstring_len );
decoder->seac = FALSE;
 
cff_free_glyph_data( face, &charstring, charstring_len );
 
if ( error )
goto Exit;
}
 
/* Restore the left side bearing, advance and glyph width */
/* of the base character. */
builder->left_bearing = left_bearing;
builder->advance = advance;
decoder->glyph_width = glyph_width;
 
builder->pos_x = 0;
builder->pos_y = 0;
 
Exit:
return error;
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* cff_decoder_parse_charstrings */
/* */
/* <Description> */
/* Parses a given Type 2 charstrings program. */
/* */
/* <InOut> */
/* decoder :: The current Type 1 decoder. */
/* */
/* <Input> */
/* charstring_base :: The base of the charstring stream. */
/* */
/* charstring_len :: The length in bytes of the charstring stream. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
cff_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
FT_ULong charstring_len )
{
FT_Error error;
CFF_Decoder_Zone* zone;
FT_Byte* ip;
FT_Byte* limit;
CFF_Builder* builder = &decoder->builder;
FT_Pos x, y;
FT_Fixed seed;
FT_Fixed* stack;
FT_Int charstring_type =
decoder->cff->top_font.font_dict.charstring_type;
 
T2_Hints_Funcs hinter;
 
 
/* set default width */
decoder->num_hints = 0;
decoder->read_width = 1;
 
/* compute random seed from stack address of parameter */
seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^
(FT_PtrDist)(char*)&decoder ^
(FT_PtrDist)(char*)&charstring_base ) &
FT_ULONG_MAX ) ;
seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
if ( seed == 0 )
seed = 0x7384;
 
/* initialize the decoder */
decoder->top = decoder->stack;
decoder->zone = decoder->zones;
zone = decoder->zones;
stack = decoder->top;
 
hinter = (T2_Hints_Funcs)builder->hints_funcs;
 
builder->path_begun = 0;
 
zone->base = charstring_base;
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
 
error = FT_Err_Ok;
 
x = builder->pos_x;
y = builder->pos_y;
 
/* begin hints recording session, if any */
if ( hinter )
hinter->open( hinter->hints );
 
/* now execute loop */
while ( ip < limit )
{
CFF_Operator op;
FT_Byte v;
 
 
/********************************************************************/
/* */
/* Decode operator or operand */
/* */
v = *ip++;
if ( v >= 32 || v == 28 )
{
FT_Int shift = 16;
FT_Int32 val;
 
 
/* this is an operand, push it on the stack */
 
/* if we use shifts, all computations are done with unsigned */
/* values; the conversion to a signed value is the last step */
if ( v == 28 )
{
if ( ip + 1 >= limit )
goto Syntax_Error;
val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] );
ip += 2;
}
else if ( v < 247 )
val = (FT_Int32)v - 139;
else if ( v < 251 )
{
if ( ip >= limit )
goto Syntax_Error;
val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
}
else if ( v < 255 )
{
if ( ip >= limit )
goto Syntax_Error;
val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
}
else
{
if ( ip + 3 >= limit )
goto Syntax_Error;
val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
( (FT_UInt32)ip[1] << 16 ) |
( (FT_UInt32)ip[2] << 8 ) |
(FT_UInt32)ip[3] );
ip += 4;
if ( charstring_type == 2 )
shift = 0;
}
if ( decoder->top - stack >= CFF_MAX_OPERANDS )
goto Stack_Overflow;
 
val = (FT_Int32)( (FT_UInt32)val << shift );
*decoder->top++ = val;
 
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !( val & 0xFFFFL ) )
FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
else
FT_TRACE4(( " %.2f", val / 65536.0 ));
#endif
 
}
else
{
/* The specification says that normally arguments are to be taken */
/* from the bottom of the stack. However, this seems not to be */
/* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
/* arguments similar to a PS interpreter. */
 
FT_Fixed* args = decoder->top;
FT_Int num_args = (FT_Int)( args - decoder->stack );
FT_Int req_args;
 
 
/* find operator */
op = cff_op_unknown;
 
switch ( v )
{
case 1:
op = cff_op_hstem;
break;
case 3:
op = cff_op_vstem;
break;
case 4:
op = cff_op_vmoveto;
break;
case 5:
op = cff_op_rlineto;
break;
case 6:
op = cff_op_hlineto;
break;
case 7:
op = cff_op_vlineto;
break;
case 8:
op = cff_op_rrcurveto;
break;
case 9:
op = cff_op_closepath;
break;
case 10:
op = cff_op_callsubr;
break;
case 11:
op = cff_op_return;
break;
case 12:
{
if ( ip >= limit )
goto Syntax_Error;
v = *ip++;
 
switch ( v )
{
case 0:
op = cff_op_dotsection;
break;
case 1: /* this is actually the Type1 vstem3 operator */
op = cff_op_vstem;
break;
case 2: /* this is actually the Type1 hstem3 operator */
op = cff_op_hstem;
break;
case 3:
op = cff_op_and;
break;
case 4:
op = cff_op_or;
break;
case 5:
op = cff_op_not;
break;
case 6:
op = cff_op_seac;
break;
case 7:
op = cff_op_sbw;
break;
case 8:
op = cff_op_store;
break;
case 9:
op = cff_op_abs;
break;
case 10:
op = cff_op_add;
break;
case 11:
op = cff_op_sub;
break;
case 12:
op = cff_op_div;
break;
case 13:
op = cff_op_load;
break;
case 14:
op = cff_op_neg;
break;
case 15:
op = cff_op_eq;
break;
case 16:
op = cff_op_callothersubr;
break;
case 17:
op = cff_op_pop;
break;
case 18:
op = cff_op_drop;
break;
case 20:
op = cff_op_put;
break;
case 21:
op = cff_op_get;
break;
case 22:
op = cff_op_ifelse;
break;
case 23:
op = cff_op_random;
break;
case 24:
op = cff_op_mul;
break;
case 26:
op = cff_op_sqrt;
break;
case 27:
op = cff_op_dup;
break;
case 28:
op = cff_op_exch;
break;
case 29:
op = cff_op_index;
break;
case 30:
op = cff_op_roll;
break;
case 33:
op = cff_op_setcurrentpoint;
break;
case 34:
op = cff_op_hflex;
break;
case 35:
op = cff_op_flex;
break;
case 36:
op = cff_op_hflex1;
break;
case 37:
op = cff_op_flex1;
break;
default:
FT_TRACE4(( " unknown op (12, %d)\n", v ));
break;
}
}
break;
case 13:
op = cff_op_hsbw;
break;
case 14:
op = cff_op_endchar;
break;
case 16:
op = cff_op_blend;
break;
case 18:
op = cff_op_hstemhm;
break;
case 19:
op = cff_op_hintmask;
break;
case 20:
op = cff_op_cntrmask;
break;
case 21:
op = cff_op_rmoveto;
break;
case 22:
op = cff_op_hmoveto;
break;
case 23:
op = cff_op_vstemhm;
break;
case 24:
op = cff_op_rcurveline;
break;
case 25:
op = cff_op_rlinecurve;
break;
case 26:
op = cff_op_vvcurveto;
break;
case 27:
op = cff_op_hhcurveto;
break;
case 29:
op = cff_op_callgsubr;
break;
case 30:
op = cff_op_vhcurveto;
break;
case 31:
op = cff_op_hvcurveto;
break;
default:
FT_TRACE4(( " unknown op (%d)\n", v ));
break;
}
 
if ( op == cff_op_unknown )
continue;
 
/* check arguments */
req_args = cff_argument_counts[op];
if ( req_args & CFF_COUNT_CHECK_WIDTH )
{
if ( num_args > 0 && decoder->read_width )
{
/* If `nominal_width' is non-zero, the number is really a */
/* difference against `nominal_width'. Else, the number here */
/* is truly a width, not a difference against `nominal_width'. */
/* If the font does not set `nominal_width', then */
/* `nominal_width' defaults to zero, and so we can set */
/* `glyph_width' to `nominal_width' plus number on the stack */
/* -- for either case. */
 
FT_Int set_width_ok;
 
 
switch ( op )
{
case cff_op_hmoveto:
case cff_op_vmoveto:
set_width_ok = num_args & 2;
break;
 
case cff_op_hstem:
case cff_op_vstem:
case cff_op_hstemhm:
case cff_op_vstemhm:
case cff_op_rmoveto:
case cff_op_hintmask:
case cff_op_cntrmask:
set_width_ok = num_args & 1;
break;
 
case cff_op_endchar:
/* If there is a width specified for endchar, we either have */
/* 1 argument or 5 arguments. We like to argue. */
set_width_ok = ( num_args == 5 ) || ( num_args == 1 );
break;
 
default:
set_width_ok = 0;
break;
}
 
if ( set_width_ok )
{
decoder->glyph_width = decoder->nominal_width +
( stack[0] >> 16 );
 
if ( decoder->width_only )
{
/* we only want the advance width; stop here */
break;
}
 
/* Consumed an argument. */
num_args--;
}
}
 
decoder->read_width = 0;
req_args = 0;
}
 
req_args &= 0x000F;
if ( num_args < req_args )
goto Stack_Underflow;
args -= req_args;
num_args -= req_args;
 
/* At this point, `args' points to the first argument of the */
/* operand in case `req_args' isn't zero. Otherwise, we have */
/* to adjust `args' manually. */
 
/* Note that we only pop arguments from the stack which we */
/* really need and can digest so that we can continue in case */
/* of superfluous stack elements. */
 
switch ( op )
{
case cff_op_hstem:
case cff_op_vstem:
case cff_op_hstemhm:
case cff_op_vstemhm:
/* the number of arguments is always even here */
FT_TRACE4((
op == cff_op_hstem ? " hstem\n" :
( op == cff_op_vstem ? " vstem\n" :
( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
 
if ( hinter )
hinter->stems( hinter->hints,
( op == cff_op_hstem || op == cff_op_hstemhm ),
num_args / 2,
args - ( num_args & ~1 ) );
 
decoder->num_hints += num_args / 2;
args = stack;
break;
 
case cff_op_hintmask:
case cff_op_cntrmask:
FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
 
/* implement vstem when needed -- */
/* the specification doesn't say it, but this also works */
/* with the 'cntrmask' operator */
/* */
if ( num_args > 0 )
{
if ( hinter )
hinter->stems( hinter->hints,
0,
num_args / 2,
args - ( num_args & ~1 ) );
 
decoder->num_hints += num_args / 2;
}
 
/* In a valid charstring there must be at least one byte */
/* after `hintmask' or `cntrmask' (e.g., for a `return' */
/* instruction). Additionally, there must be space for */
/* `num_hints' bits. */
 
if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )
goto Syntax_Error;
 
if ( hinter )
{
if ( op == cff_op_hintmask )
hinter->hintmask( hinter->hints,
builder->current->n_points,
decoder->num_hints,
ip );
else
hinter->counter( hinter->hints,
decoder->num_hints,
ip );
}
 
#ifdef FT_DEBUG_LEVEL_TRACE
{
FT_UInt maskbyte;
 
 
FT_TRACE4(( " (maskbytes:" ));
 
for ( maskbyte = 0;
maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );
maskbyte++, ip++ )
FT_TRACE4(( " 0x%02X", *ip ));
 
FT_TRACE4(( ")\n" ));
}
#else
ip += ( decoder->num_hints + 7 ) >> 3;
#endif
args = stack;
break;
 
case cff_op_rmoveto:
FT_TRACE4(( " rmoveto\n" ));
 
cff_builder_close_contour( builder );
builder->path_begun = 0;
x += args[-2];
y += args[-1];
args = stack;
break;
 
case cff_op_vmoveto:
FT_TRACE4(( " vmoveto\n" ));
 
cff_builder_close_contour( builder );
builder->path_begun = 0;
y += args[-1];
args = stack;
break;
 
case cff_op_hmoveto:
FT_TRACE4(( " hmoveto\n" ));
 
cff_builder_close_contour( builder );
builder->path_begun = 0;
x += args[-1];
args = stack;
break;
 
case cff_op_rlineto:
FT_TRACE4(( " rlineto\n" ));
 
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, num_args / 2 ) )
goto Fail;
 
if ( num_args < 2 )
goto Stack_Underflow;
 
args -= num_args & ~1;
while ( args < decoder->top )
{
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y, 1 );
args += 2;
}
args = stack;
break;
 
case cff_op_hlineto:
case cff_op_vlineto:
{
FT_Int phase = ( op == cff_op_hlineto );
 
 
FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
: " vlineto\n" ));
 
if ( num_args < 0 )
goto Stack_Underflow;
 
/* there exist subsetted fonts (found in PDFs) */
/* which call `hlineto' without arguments */
if ( num_args == 0 )
break;
 
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, num_args ) )
goto Fail;
 
args = stack;
while ( args < decoder->top )
{
if ( phase )
x += args[0];
else
y += args[0];
 
if ( cff_builder_add_point1( builder, x, y ) )
goto Fail;
 
args++;
phase ^= 1;
}
args = stack;
}
break;
 
case cff_op_rrcurveto:
{
FT_Int nargs;
 
 
FT_TRACE4(( " rrcurveto\n" ));
 
if ( num_args < 6 )
goto Stack_Underflow;
 
nargs = num_args - num_args % 6;
 
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, nargs / 2 ) )
goto Fail;
 
args -= nargs;
while ( args < decoder->top )
{
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y, 0 );
x += args[2];
y += args[3];
cff_builder_add_point( builder, x, y, 0 );
x += args[4];
y += args[5];
cff_builder_add_point( builder, x, y, 1 );
args += 6;
}
args = stack;
}
break;
 
case cff_op_vvcurveto:
{
FT_Int nargs;
 
 
FT_TRACE4(( " vvcurveto\n" ));
 
if ( num_args < 4 )
goto Stack_Underflow;
 
/* if num_args isn't of the form 4n or 4n+1, */
/* we enforce it by clearing the second bit */
 
nargs = num_args & ~2;
 
if ( cff_builder_start_point( builder, x, y ) )
goto Fail;
 
args -= nargs;
 
if ( nargs & 1 )
{
x += args[0];
args++;
nargs--;
}
 
if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
goto Fail;
 
while ( args < decoder->top )
{
y += args[0];
cff_builder_add_point( builder, x, y, 0 );
x += args[1];
y += args[2];
cff_builder_add_point( builder, x, y, 0 );
y += args[3];
cff_builder_add_point( builder, x, y, 1 );
args += 4;
}
args = stack;
}
break;
 
case cff_op_hhcurveto:
{
FT_Int nargs;
 
 
FT_TRACE4(( " hhcurveto\n" ));
 
if ( num_args < 4 )
goto Stack_Underflow;
 
/* if num_args isn't of the form 4n or 4n+1, */
/* we enforce it by clearing the second bit */
 
nargs = num_args & ~2;
 
if ( cff_builder_start_point( builder, x, y ) )
goto Fail;
 
args -= nargs;
if ( nargs & 1 )
{
y += args[0];
args++;
nargs--;
}
 
if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
goto Fail;
 
while ( args < decoder->top )
{
x += args[0];
cff_builder_add_point( builder, x, y, 0 );
x += args[1];
y += args[2];
cff_builder_add_point( builder, x, y, 0 );
x += args[3];
cff_builder_add_point( builder, x, y, 1 );
args += 4;
}
args = stack;
}
break;
 
case cff_op_vhcurveto:
case cff_op_hvcurveto:
{
FT_Int phase;
FT_Int nargs;
 
 
FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
: " hvcurveto\n" ));
 
if ( cff_builder_start_point( builder, x, y ) )
goto Fail;
 
if ( num_args < 4 )
goto Stack_Underflow;
 
/* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
/* we enforce it by clearing the second bit */
 
nargs = num_args & ~2;
 
args -= nargs;
if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) )
goto Stack_Underflow;
 
phase = ( op == cff_op_hvcurveto );
 
while ( nargs >= 4 )
{
nargs -= 4;
if ( phase )
{
x += args[0];
cff_builder_add_point( builder, x, y, 0 );
x += args[1];
y += args[2];
cff_builder_add_point( builder, x, y, 0 );
y += args[3];
if ( nargs == 1 )
x += args[4];
cff_builder_add_point( builder, x, y, 1 );
}
else
{
y += args[0];
cff_builder_add_point( builder, x, y, 0 );
x += args[1];
y += args[2];
cff_builder_add_point( builder, x, y, 0 );
x += args[3];
if ( nargs == 1 )
y += args[4];
cff_builder_add_point( builder, x, y, 1 );
}
args += 4;
phase ^= 1;
}
args = stack;
}
break;
 
case cff_op_rlinecurve:
{
FT_Int num_lines;
FT_Int nargs;
 
 
FT_TRACE4(( " rlinecurve\n" ));
 
if ( num_args < 8 )
goto Stack_Underflow;
 
nargs = num_args & ~1;
num_lines = ( nargs - 6 ) / 2;
 
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, num_lines + 3 ) )
goto Fail;
 
args -= nargs;
 
/* first, add the line segments */
while ( num_lines > 0 )
{
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y, 1 );
args += 2;
num_lines--;
}
 
/* then the curve */
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y, 0 );
x += args[2];
y += args[3];
cff_builder_add_point( builder, x, y, 0 );
x += args[4];
y += args[5];
cff_builder_add_point( builder, x, y, 1 );
args = stack;
}
break;
 
case cff_op_rcurveline:
{
FT_Int num_curves;
FT_Int nargs;
 
 
FT_TRACE4(( " rcurveline\n" ));
 
if ( num_args < 8 )
goto Stack_Underflow;
 
nargs = num_args - 2;
nargs = nargs - nargs % 6 + 2;
num_curves = ( nargs - 2 ) / 6;
 
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, num_curves * 3 + 2 ) )
goto Fail;
 
args -= nargs;
 
/* first, add the curves */
while ( num_curves > 0 )
{
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y, 0 );
x += args[2];
y += args[3];
cff_builder_add_point( builder, x, y, 0 );
x += args[4];
y += args[5];
cff_builder_add_point( builder, x, y, 1 );
args += 6;
num_curves--;
}
 
/* then the final line */
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y, 1 );
args = stack;
}
break;
 
case cff_op_hflex1:
{
FT_Pos start_y;
 
 
FT_TRACE4(( " hflex1\n" ));
 
/* adding five more points: 4 control points, 1 on-curve point */
/* -- make sure we have enough space for the start point if it */
/* needs to be added */
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, 6 ) )
goto Fail;
 
/* record the starting point's y position for later use */
start_y = y;
 
/* first control point */
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y, 0 );
 
/* second control point */
x += args[2];
y += args[3];
cff_builder_add_point( builder, x, y, 0 );
 
/* join point; on curve, with y-value the same as the last */
/* control point's y-value */
x += args[4];
cff_builder_add_point( builder, x, y, 1 );
 
/* third control point, with y-value the same as the join */
/* point's y-value */
x += args[5];
cff_builder_add_point( builder, x, y, 0 );
 
/* fourth control point */
x += args[6];
y += args[7];
cff_builder_add_point( builder, x, y, 0 );
 
/* ending point, with y-value the same as the start */
x += args[8];
y = start_y;
cff_builder_add_point( builder, x, y, 1 );
 
args = stack;
break;
}
 
case cff_op_hflex:
{
FT_Pos start_y;
 
 
FT_TRACE4(( " hflex\n" ));
 
/* adding six more points; 4 control points, 2 on-curve points */
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, 6 ) )
goto Fail;
 
/* record the starting point's y-position for later use */
start_y = y;
 
/* first control point */
x += args[0];
cff_builder_add_point( builder, x, y, 0 );
 
/* second control point */
x += args[1];
y += args[2];
cff_builder_add_point( builder, x, y, 0 );
 
/* join point; on curve, with y-value the same as the last */
/* control point's y-value */
x += args[3];
cff_builder_add_point( builder, x, y, 1 );
 
/* third control point, with y-value the same as the join */
/* point's y-value */
x += args[4];
cff_builder_add_point( builder, x, y, 0 );
 
/* fourth control point */
x += args[5];
y = start_y;
cff_builder_add_point( builder, x, y, 0 );
 
/* ending point, with y-value the same as the start point's */
/* y-value -- we don't add this point, though */
x += args[6];
cff_builder_add_point( builder, x, y, 1 );
 
args = stack;
break;
}
 
case cff_op_flex1:
{
FT_Pos start_x, start_y; /* record start x, y values for */
/* alter use */
FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */
/* algorithm below */
FT_Int horizontal, count;
FT_Fixed* temp;
 
 
FT_TRACE4(( " flex1\n" ));
 
/* adding six more points; 4 control points, 2 on-curve points */
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, 6 ) )
goto Fail;
 
/* record the starting point's x, y position for later use */
start_x = x;
start_y = y;
 
/* XXX: figure out whether this is supposed to be a horizontal */
/* or vertical flex; the Type 2 specification is vague... */
 
temp = args;
 
/* grab up to the last argument */
for ( count = 5; count > 0; count-- )
{
dx += temp[0];
dy += temp[1];
temp += 2;
}
 
if ( dx < 0 )
dx = -dx;
if ( dy < 0 )
dy = -dy;
 
/* strange test, but here it is... */
horizontal = ( dx > dy );
 
for ( count = 5; count > 0; count-- )
{
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y,
(FT_Bool)( count == 3 ) );
args += 2;
}
 
/* is last operand an x- or y-delta? */
if ( horizontal )
{
x += args[0];
y = start_y;
}
else
{
x = start_x;
y += args[0];
}
 
cff_builder_add_point( builder, x, y, 1 );
 
args = stack;
break;
}
 
case cff_op_flex:
{
FT_UInt count;
 
 
FT_TRACE4(( " flex\n" ));
 
if ( cff_builder_start_point( builder, x, y ) ||
cff_check_points( builder, 6 ) )
goto Fail;
 
for ( count = 6; count > 0; count-- )
{
x += args[0];
y += args[1];
cff_builder_add_point( builder, x, y,
(FT_Bool)( count == 4 || count == 1 ) );
args += 2;
}
 
args = stack;
}
break;
 
case cff_op_seac:
FT_TRACE4(( " seac\n" ));
 
error = cff_operator_seac( decoder,
args[0], args[1], args[2],
(FT_Int)( args[3] >> 16 ),
(FT_Int)( args[4] >> 16 ) );
 
/* add current outline to the glyph slot */
FT_GlyphLoader_Add( builder->loader );
 
/* return now! */
FT_TRACE4(( "\n" ));
return error;
 
case cff_op_endchar:
FT_TRACE4(( " endchar\n" ));
 
/* We are going to emulate the seac operator. */
if ( num_args >= 4 )
{
/* Save glyph width so that the subglyphs don't overwrite it. */
FT_Pos glyph_width = decoder->glyph_width;
 
 
error = cff_operator_seac( decoder,
0L, args[-4], args[-3],
(FT_Int)( args[-2] >> 16 ),
(FT_Int)( args[-1] >> 16 ) );
 
decoder->glyph_width = glyph_width;
}
else
{
if ( !error )
error = FT_Err_Ok;
 
cff_builder_close_contour( builder );
 
/* close hints recording session */
if ( hinter )
{
if ( hinter->close( hinter->hints,
builder->current->n_points ) )
goto Syntax_Error;
 
/* apply hints to the loaded glyph outline now */
hinter->apply( hinter->hints,
builder->current,
(PSH_Globals)builder->hints_globals,
decoder->hint_mode );
}
 
/* add current outline to the glyph slot */
FT_GlyphLoader_Add( builder->loader );
}
 
/* return now! */
FT_TRACE4(( "\n" ));
return error;
 
case cff_op_abs:
FT_TRACE4(( " abs\n" ));
 
if ( args[0] < 0 )
args[0] = -args[0];
args++;
break;
 
case cff_op_add:
FT_TRACE4(( " add\n" ));
 
args[0] += args[1];
args++;
break;
 
case cff_op_sub:
FT_TRACE4(( " sub\n" ));
 
args[0] -= args[1];
args++;
break;
 
case cff_op_div:
FT_TRACE4(( " div\n" ));
 
args[0] = FT_DivFix( args[0], args[1] );
args++;
break;
 
case cff_op_neg:
FT_TRACE4(( " neg\n" ));
 
args[0] = -args[0];
args++;
break;
 
case cff_op_random:
{
FT_Fixed Rand;
 
 
FT_TRACE4(( " rand\n" ));
 
Rand = seed;
if ( Rand >= 0x8000L )
Rand++;
 
args[0] = Rand;
seed = FT_MulFix( seed, 0x10000L - seed );
if ( seed == 0 )
seed += 0x2873;
args++;
}
break;
 
case cff_op_mul:
FT_TRACE4(( " mul\n" ));
 
args[0] = FT_MulFix( args[0], args[1] );
args++;
break;
 
case cff_op_sqrt:
FT_TRACE4(( " sqrt\n" ));
 
if ( args[0] > 0 )
{
FT_Int count = 9;
FT_Fixed root = args[0];
FT_Fixed new_root;
 
 
for (;;)
{
new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
if ( new_root == root || count <= 0 )
break;
root = new_root;
}
args[0] = new_root;
}
else
args[0] = 0;
args++;
break;
 
case cff_op_drop:
/* nothing */
FT_TRACE4(( " drop\n" ));
 
break;
 
case cff_op_exch:
{
FT_Fixed tmp;
 
 
FT_TRACE4(( " exch\n" ));
 
tmp = args[0];
args[0] = args[1];
args[1] = tmp;
args += 2;
}
break;
 
case cff_op_index:
{
FT_Int idx = (FT_Int)( args[0] >> 16 );
 
 
FT_TRACE4(( " index\n" ));
 
if ( idx < 0 )
idx = 0;
else if ( idx > num_args - 2 )
idx = num_args - 2;
args[0] = args[-( idx + 1 )];
args++;
}
break;
 
case cff_op_roll:
{
FT_Int count = (FT_Int)( args[0] >> 16 );
FT_Int idx = (FT_Int)( args[1] >> 16 );
 
 
FT_TRACE4(( " roll\n" ));
 
if ( count <= 0 )
count = 1;
 
args -= count;
if ( args < stack )
goto Stack_Underflow;
 
if ( idx >= 0 )
{
while ( idx > 0 )
{
FT_Fixed tmp = args[count - 1];
FT_Int i;
 
 
for ( i = count - 2; i >= 0; i-- )
args[i + 1] = args[i];
args[0] = tmp;
idx--;
}
}
else
{
while ( idx < 0 )
{
FT_Fixed tmp = args[0];
FT_Int i;
 
 
for ( i = 0; i < count - 1; i++ )
args[i] = args[i + 1];
args[count - 1] = tmp;
idx++;
}
}
args += count;
}
break;
 
case cff_op_dup:
FT_TRACE4(( " dup\n" ));
 
args[1] = args[0];
args += 2;
break;
 
case cff_op_put:
{
FT_Fixed val = args[0];
FT_Int idx = (FT_Int)( args[1] >> 16 );
 
 
FT_TRACE4(( " put\n" ));
 
if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
decoder->buildchar[idx] = val;
}
break;
 
case cff_op_get:
{
FT_Int idx = (FT_Int)( args[0] >> 16 );
FT_Fixed val = 0;
 
 
FT_TRACE4(( " get\n" ));
 
if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
val = decoder->buildchar[idx];
 
args[0] = val;
args++;
}
break;
 
case cff_op_store:
FT_TRACE4(( " store\n"));
 
goto Unimplemented;
 
case cff_op_load:
FT_TRACE4(( " load\n" ));
 
goto Unimplemented;
 
case cff_op_dotsection:
/* this operator is deprecated and ignored by the parser */
FT_TRACE4(( " dotsection\n" ));
break;
 
case cff_op_closepath:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
 
FT_TRACE4(( " closepath (invalid op)\n" ));
 
args = stack;
break;
 
case cff_op_hsbw:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
 
FT_TRACE4(( " hsbw (invalid op)\n" ));
 
decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 );
 
decoder->builder.left_bearing.x = args[0];
decoder->builder.left_bearing.y = 0;
 
x = decoder->builder.pos_x + args[0];
y = decoder->builder.pos_y;
args = stack;
break;
 
case cff_op_sbw:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
 
FT_TRACE4(( " sbw (invalid op)\n" ));
 
decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 );
 
decoder->builder.left_bearing.x = args[0];
decoder->builder.left_bearing.y = args[1];
 
x = decoder->builder.pos_x + args[0];
y = decoder->builder.pos_y + args[1];
args = stack;
break;
 
case cff_op_setcurrentpoint:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
 
FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
 
x = decoder->builder.pos_x + args[0];
y = decoder->builder.pos_y + args[1];
args = stack;
break;
 
case cff_op_callothersubr:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
 
FT_TRACE4(( " callothersubr (invalid op)\n" ));
 
/* subsequent `pop' operands should add the arguments, */
/* this is the implementation described for `unknown' other */
/* subroutines in the Type1 spec. */
/* */
/* XXX Fix return arguments (see discussion below). */
args -= 2 + ( args[-2] >> 16 );
if ( args < stack )
goto Stack_Underflow;
break;
 
case cff_op_pop:
/* this is an invalid Type 2 operator; however, there */
/* exist fonts which are incorrectly converted from probably */
/* Type 1 to CFF, and some parsers seem to accept it */
 
FT_TRACE4(( " pop (invalid op)\n" ));
 
/* XXX Increasing `args' is wrong: After a certain number of */
/* `pop's we get a stack overflow. Reason for doing it is */
/* code like this (actually found in a CFF font): */
/* */
/* 17 1 3 callothersubr */
/* pop */
/* callsubr */
/* */
/* Since we handle `callothersubr' as a no-op, and */
/* `callsubr' needs at least one argument, `pop' can't be a */
/* no-op too as it basically should be. */
/* */
/* The right solution would be to provide real support for */
/* `callothersubr' as done in `t1decode.c', however, given */
/* the fact that CFF fonts with `pop' are invalid, it is */
/* questionable whether it is worth the time. */
args++;
break;
 
case cff_op_and:
{
FT_Fixed cond = args[0] && args[1];
 
 
FT_TRACE4(( " and\n" ));
 
args[0] = cond ? 0x10000L : 0;
args++;
}
break;
 
case cff_op_or:
{
FT_Fixed cond = args[0] || args[1];
 
 
FT_TRACE4(( " or\n" ));
 
args[0] = cond ? 0x10000L : 0;
args++;
}
break;
 
case cff_op_eq:
{
FT_Fixed cond = !args[0];
 
 
FT_TRACE4(( " eq\n" ));
 
args[0] = cond ? 0x10000L : 0;
args++;
}
break;
 
case cff_op_ifelse:
{
FT_Fixed cond = ( args[2] <= args[3] );
 
 
FT_TRACE4(( " ifelse\n" ));
 
if ( !cond )
args[0] = args[1];
args++;
}
break;
 
case cff_op_callsubr:
{
FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
decoder->locals_bias );
 
 
FT_TRACE4(( " callsubr(%d)\n", idx ));
 
if ( idx >= decoder->num_locals )
{
FT_ERROR(( "cff_decoder_parse_charstrings:"
" invalid local subr index\n" ));
goto Syntax_Error;
}
 
if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
{
FT_ERROR(( "cff_decoder_parse_charstrings:"
" too many nested subrs\n" ));
goto Syntax_Error;
}
 
zone->cursor = ip; /* save current instruction pointer */
 
zone++;
zone->base = decoder->locals[idx];
zone->limit = decoder->locals[idx + 1];
zone->cursor = zone->base;
 
if ( !zone->base || zone->limit == zone->base )
{
FT_ERROR(( "cff_decoder_parse_charstrings:"
" invoking empty subrs\n" ));
goto Syntax_Error;
}
 
decoder->zone = zone;
ip = zone->base;
limit = zone->limit;
}
break;
 
case cff_op_callgsubr:
{
FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
decoder->globals_bias );
 
 
FT_TRACE4(( " callgsubr(%d)\n", idx ));
 
if ( idx >= decoder->num_globals )
{
FT_ERROR(( "cff_decoder_parse_charstrings:"
" invalid global subr index\n" ));
goto Syntax_Error;
}
 
if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
{
FT_ERROR(( "cff_decoder_parse_charstrings:"
" too many nested subrs\n" ));
goto Syntax_Error;
}
 
zone->cursor = ip; /* save current instruction pointer */
 
zone++;
zone->base = decoder->globals[idx];
zone->limit = decoder->globals[idx + 1];
zone->cursor = zone->base;
 
if ( !zone->base || zone->limit == zone->base )
{
FT_ERROR(( "cff_decoder_parse_charstrings:"
" invoking empty subrs\n" ));
goto Syntax_Error;
}
 
decoder->zone = zone;
ip = zone->base;
limit = zone->limit;
}
break;
 
case cff_op_return:
FT_TRACE4(( " return\n" ));
 
if ( decoder->zone <= decoder->zones )
{
FT_ERROR(( "cff_decoder_parse_charstrings:"
" unexpected return\n" ));
goto Syntax_Error;
}
 
decoder->zone--;
zone = decoder->zone;
ip = zone->cursor;
limit = zone->limit;
break;
 
default:
Unimplemented:
FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
 
if ( ip[-1] == 12 )
FT_ERROR(( " %d", ip[0] ));
FT_ERROR(( "\n" ));
 
return FT_THROW( Unimplemented_Feature );
}
 
decoder->top = args;
 
if ( decoder->top - stack >= CFF_MAX_OPERANDS )
goto Stack_Overflow;
 
} /* general operator processing */
 
} /* while ip < limit */
 
FT_TRACE4(( "..end..\n\n" ));
 
Fail:
return error;
 
Syntax_Error:
FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
return FT_THROW( Invalid_File_Format );
 
Stack_Underflow:
FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
return FT_THROW( Too_Few_Arguments );
 
Stack_Overflow:
FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
return FT_THROW( Stack_Overflow );
}
 
#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/********** *********/
/********** *********/
/********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
/********** *********/
/********** The following code is in charge of computing *********/
/********** the maximum advance width of the font. It *********/
/********** quickly processes each glyph charstring to *********/
/********** extract the value from either a `sbw' or `seac' *********/
/********** operator. *********/
/********** *********/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
 
#if 0 /* unused until we support pure CFF fonts */
 
 
FT_LOCAL_DEF( FT_Error )
cff_compute_max_advance( TT_Face face,
FT_Int* max_advance )
{
FT_Error error = FT_Err_Ok;
CFF_Decoder decoder;
FT_Int glyph_index;
CFF_Font cff = (CFF_Font)face->other;
 
 
*max_advance = 0;
 
/* Initialize load decoder */
cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
 
decoder.builder.metrics_only = 1;
decoder.builder.load_points = 0;
 
/* For each glyph, parse the glyph charstring and extract */
/* the advance width. */
for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
glyph_index++ )
{
FT_Byte* charstring;
FT_ULong charstring_len;
 
 
/* now get load the unscaled outline */
error = cff_get_glyph_data( face, glyph_index,
&charstring, &charstring_len );
if ( !error )
{
error = cff_decoder_prepare( &decoder, size, glyph_index );
if ( !error )
error = cff_decoder_parse_charstrings( &decoder,
charstring,
charstring_len );
 
cff_free_glyph_data( face, &charstring, &charstring_len );
}
 
/* ignore the error if one has occurred -- skip to next glyph */
error = FT_Err_Ok;
}
 
*max_advance = decoder.builder.advance.x;
 
return FT_Err_Ok;
}
 
 
#endif /* 0 */
 
 
FT_LOCAL_DEF( FT_Error )
cff_slot_load( CFF_GlyphSlot glyph,
CFF_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_Error error;
CFF_Decoder decoder;
TT_Face face = (TT_Face)glyph->root.face;
FT_Bool hinting, scaled, force_scaling;
CFF_Font cff = (CFF_Font)face->extra.data;
 
FT_Matrix font_matrix;
FT_Vector font_offset;
 
 
force_scaling = FALSE;
 
/* in a CID-keyed font, consider `glyph_index' as a CID and map */
/* it immediately to the real glyph_index -- if it isn't a */
/* subsetted font, glyph_indices and CIDs are identical, though */
if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
cff->charset.cids )
{
/* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
if ( glyph_index != 0 )
{
glyph_index = cff_charset_cid_to_gindex( &cff->charset,
glyph_index );
if ( glyph_index == 0 )
return FT_THROW( Invalid_Argument );
}
}
else if ( glyph_index >= cff->num_glyphs )
return FT_THROW( Invalid_Argument );
 
if ( load_flags & FT_LOAD_NO_RECURSE )
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
 
glyph->x_scale = 0x10000L;
glyph->y_scale = 0x10000L;
if ( size )
{
glyph->x_scale = size->root.metrics.x_scale;
glyph->y_scale = size->root.metrics.y_scale;
}
 
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
/* try to load embedded bitmap if any */
/* */
/* XXX: The convention should be emphasized in */
/* the documents because it can be confusing. */
if ( size )
{
CFF_Face cff_face = (CFF_Face)size->root.face;
SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt;
FT_Stream stream = cff_face->root.stream;
 
 
if ( size->strike_index != 0xFFFFFFFFUL &&
sfnt->load_eblc &&
( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
{
TT_SBit_MetricsRec metrics;
 
 
error = sfnt->load_sbit_image( face,
size->strike_index,
glyph_index,
(FT_Int)load_flags,
stream,
&glyph->root.bitmap,
&metrics );
 
if ( !error )
{
FT_Bool has_vertical_info;
FT_UShort advance;
FT_Short dummy;
 
 
glyph->root.outline.n_points = 0;
glyph->root.outline.n_contours = 0;
 
glyph->root.metrics.width = (FT_Pos)metrics.width << 6;
glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
 
glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
 
glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
 
glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
 
if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
{
glyph->root.bitmap_left = metrics.vertBearingX;
glyph->root.bitmap_top = metrics.vertBearingY;
}
else
{
glyph->root.bitmap_left = metrics.horiBearingX;
glyph->root.bitmap_top = metrics.horiBearingY;
}
 
/* compute linear advance widths */
 
( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
glyph_index,
&dummy,
&advance );
glyph->root.linearHoriAdvance = advance;
 
has_vertical_info = FT_BOOL(
face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 );
 
/* get the vertical metrics from the vtmx table if we have one */
if ( has_vertical_info )
{
( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
glyph_index,
&dummy,
&advance );
glyph->root.linearVertAdvance = advance;
}
else
{
/* make up vertical ones */
if ( face->os2.version != 0xFFFFU )
glyph->root.linearVertAdvance = (FT_Pos)
( face->os2.sTypoAscender - face->os2.sTypoDescender );
else
glyph->root.linearVertAdvance = (FT_Pos)
( face->horizontal.Ascender - face->horizontal.Descender );
}
 
return error;
}
}
}
 
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
/* return immediately if we only want the embedded bitmaps */
if ( load_flags & FT_LOAD_SBITS_ONLY )
return FT_THROW( Invalid_Argument );
 
/* if we have a CID subfont, use its matrix (which has already */
/* been multiplied with the root matrix) */
 
/* this scaling is only relevant if the PS hinter isn't active */
if ( cff->num_subfonts )
{
FT_ULong top_upm, sub_upm;
FT_Byte fd_index = cff_fd_select_get( &cff->fd_select,
glyph_index );
 
 
if ( fd_index >= cff->num_subfonts )
fd_index = (FT_Byte)( cff->num_subfonts - 1 );
 
top_upm = cff->top_font.font_dict.units_per_em;
sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;
 
 
font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
font_offset = cff->subfonts[fd_index]->font_dict.font_offset;
 
if ( top_upm != sub_upm )
{
glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );
glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );
 
force_scaling = TRUE;
}
}
else
{
font_matrix = cff->top_font.font_dict.font_matrix;
font_offset = cff->top_font.font_dict.font_offset;
}
 
glyph->root.outline.n_points = 0;
glyph->root.outline.n_contours = 0;
 
/* top-level code ensures that FT_LOAD_NO_HINTING is set */
/* if FT_LOAD_NO_SCALE is active */
hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
 
glyph->hint = hinting;
glyph->scaled = scaled;
glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */
 
{
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face );
#endif
 
 
FT_Byte* charstring;
FT_ULong charstring_len;
 
 
cff_decoder_init( &decoder, face, size, glyph, hinting,
FT_LOAD_TARGET_MODE( load_flags ) );
 
if ( load_flags & FT_LOAD_ADVANCE_ONLY )
decoder.width_only = TRUE;
 
decoder.builder.no_recurse =
(FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
 
/* now load the unscaled outline */
error = cff_get_glyph_data( face, glyph_index,
&charstring, &charstring_len );
if ( error )
goto Glyph_Build_Finished;
 
error = cff_decoder_prepare( &decoder, size, glyph_index );
if ( error )
goto Glyph_Build_Finished;
 
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
/* choose which CFF renderer to use */
if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
error = cff_decoder_parse_charstrings( &decoder,
charstring,
charstring_len );
else
#endif
{
error = cf2_decoder_parse_charstrings( &decoder,
charstring,
charstring_len );
 
/* Adobe's engine uses 16.16 numbers everywhere; */
/* as a consequence, glyphs larger than 2000ppem get rejected */
if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
{
/* this time, we retry unhinted and scale up the glyph later on */
/* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
/* 0x400 for both `x_scale' and `y_scale' in this case) */
hinting = FALSE;
force_scaling = TRUE;
glyph->hint = hinting;
 
error = cf2_decoder_parse_charstrings( &decoder,
charstring,
charstring_len );
}
}
 
cff_free_glyph_data( face, &charstring, charstring_len );
 
if ( error )
goto Glyph_Build_Finished;
 
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* Control data and length may not be available for incremental */
/* fonts. */
if ( face->root.internal->incremental_interface )
{
glyph->root.control_data = 0;
glyph->root.control_len = 0;
}
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
/* We set control_data and control_len if charstrings is loaded. */
/* See how charstring loads at cff_index_access_element() in */
/* cffload.c. */
{
CFF_Index csindex = &cff->charstrings_index;
 
 
if ( csindex->offsets )
{
glyph->root.control_data = csindex->bytes +
csindex->offsets[glyph_index] - 1;
glyph->root.control_len = charstring_len;
}
}
 
Glyph_Build_Finished:
/* save new glyph tables, if no error */
if ( !error )
cff_builder_done( &decoder.builder );
/* XXX: anything to do for broken glyph entry? */
}
 
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
/* Incremental fonts can optionally override the metrics. */
if ( !error &&
face->root.internal->incremental_interface &&
face->root.internal->incremental_interface->funcs->get_glyph_metrics )
{
FT_Incremental_MetricsRec metrics;
 
 
metrics.bearing_x = decoder.builder.left_bearing.x;
metrics.bearing_y = 0;
metrics.advance = decoder.builder.advance.x;
metrics.advance_v = decoder.builder.advance.y;
 
error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
face->root.internal->incremental_interface->object,
glyph_index, FALSE, &metrics );
 
decoder.builder.left_bearing.x = metrics.bearing_x;
decoder.builder.advance.x = metrics.advance;
decoder.builder.advance.y = metrics.advance_v;
}
 
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
if ( !error )
{
/* Now, set the metrics -- this is rather simple, as */
/* the left side bearing is the xMin, and the top side */
/* bearing the yMax. */
 
/* For composite glyphs, return only left side bearing and */
/* advance width. */
if ( load_flags & FT_LOAD_NO_RECURSE )
{
FT_Slot_Internal internal = glyph->root.internal;
 
 
glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
glyph->root.metrics.horiAdvance = decoder.glyph_width;
internal->glyph_matrix = font_matrix;
internal->glyph_delta = font_offset;
internal->glyph_transformed = 1;
}
else
{
FT_BBox cbox;
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
FT_Vector advance;
FT_Bool has_vertical_info;
 
 
/* copy the _unscaled_ advance width */
metrics->horiAdvance = decoder.glyph_width;
glyph->root.linearHoriAdvance = decoder.glyph_width;
glyph->root.internal->glyph_transformed = 0;
 
has_vertical_info = FT_BOOL( face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 );
 
/* get the vertical metrics from the vtmx table if we have one */
if ( has_vertical_info )
{
FT_Short vertBearingY = 0;
FT_UShort vertAdvance = 0;
 
 
( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
glyph_index,
&vertBearingY,
&vertAdvance );
metrics->vertBearingY = vertBearingY;
metrics->vertAdvance = vertAdvance;
}
else
{
/* make up vertical ones */
if ( face->os2.version != 0xFFFFU )
metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
face->os2.sTypoDescender );
else
metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
face->horizontal.Descender );
}
 
glyph->root.linearVertAdvance = metrics->vertAdvance;
 
glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
 
glyph->root.outline.flags = 0;
if ( size && size->root.metrics.y_ppem < 24 )
glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
 
if ( !( font_matrix.xx == 0x10000L &&
font_matrix.yy == 0x10000L &&
font_matrix.xy == 0 &&
font_matrix.yx == 0 ) )
FT_Outline_Transform( &glyph->root.outline, &font_matrix );
 
if ( !( font_offset.x == 0 &&
font_offset.y == 0 ) )
FT_Outline_Translate( &glyph->root.outline,
font_offset.x, font_offset.y );
 
advance.x = metrics->horiAdvance;
advance.y = 0;
FT_Vector_Transform( &advance, &font_matrix );
metrics->horiAdvance = advance.x + font_offset.x;
 
advance.x = 0;
advance.y = metrics->vertAdvance;
FT_Vector_Transform( &advance, &font_matrix );
metrics->vertAdvance = advance.y + font_offset.y;
 
if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
{
/* scale the outline and the metrics */
FT_Int n;
FT_Outline* cur = &glyph->root.outline;
FT_Vector* vec = cur->points;
FT_Fixed x_scale = glyph->x_scale;
FT_Fixed y_scale = glyph->y_scale;
 
 
/* First of all, scale the points */
if ( !hinting || !decoder.builder.hints_funcs )
for ( n = cur->n_points; n > 0; n--, vec++ )
{
vec->x = FT_MulFix( vec->x, x_scale );
vec->y = FT_MulFix( vec->y, y_scale );
}
 
/* Then scale the metrics */
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
}
 
/* compute the other metrics */
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
 
metrics->width = cbox.xMax - cbox.xMin;
metrics->height = cbox.yMax - cbox.yMin;
 
metrics->horiBearingX = cbox.xMin;
metrics->horiBearingY = cbox.yMax;
 
if ( has_vertical_info )
metrics->vertBearingX = metrics->horiBearingX -
metrics->horiAdvance / 2;
else
{
if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
ft_synthesize_vertical_metrics( metrics,
metrics->vertAdvance );
}
}
}
 
return error;
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffgload.h
0,0 → 1,240
/***************************************************************************/
/* */
/* cffgload.h */
/* */
/* OpenType Glyph Loader (specification). */
/* */
/* Copyright 1996-2004, 2006-2009, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFFGLOAD_H__
#define __CFFGLOAD_H__
 
 
#include <ft2build.h>
#include FT_FREETYPE_H
#include "cffobjs.h"
 
 
FT_BEGIN_HEADER
 
 
#define CFF_MAX_OPERANDS 48
#define CFF_MAX_SUBRS_CALLS 32
#define CFF_MAX_TRANS_ELEMENTS 32
 
 
/*************************************************************************/
/* */
/* <Structure> */
/* CFF_Builder */
/* */
/* <Description> */
/* A structure used during glyph loading to store its outline. */
/* */
/* <Fields> */
/* memory :: The current memory object. */
/* */
/* face :: The current face object. */
/* */
/* glyph :: The current glyph slot. */
/* */
/* loader :: The current glyph loader. */
/* */
/* base :: The base glyph outline. */
/* */
/* current :: The current glyph outline. */
/* */
/* pos_x :: The horizontal translation (if composite glyph). */
/* */
/* pos_y :: The vertical translation (if composite glyph). */
/* */
/* left_bearing :: The left side bearing point. */
/* */
/* advance :: The horizontal advance vector. */
/* */
/* bbox :: Unused. */
/* */
/* path_begun :: A flag which indicates that a new path has begun. */
/* */
/* load_points :: If this flag is not set, no points are loaded. */
/* */
/* no_recurse :: Set but not used. */
/* */
/* metrics_only :: A boolean indicating that we only want to compute */
/* the metrics of a given glyph, not load all of its */
/* points. */
/* */
/* hints_funcs :: Auxiliary pointer for hinting. */
/* */
/* hints_globals :: Auxiliary pointer for hinting. */
/* */
typedef struct CFF_Builder_
{
FT_Memory memory;
TT_Face face;
CFF_GlyphSlot glyph;
FT_GlyphLoader loader;
FT_Outline* base;
FT_Outline* current;
 
FT_Pos pos_x;
FT_Pos pos_y;
 
FT_Vector left_bearing;
FT_Vector advance;
 
FT_BBox bbox; /* bounding box */
FT_Bool path_begun;
FT_Bool load_points;
FT_Bool no_recurse;
 
FT_Bool metrics_only;
 
void* hints_funcs; /* hinter-specific */
void* hints_globals; /* hinter-specific */
 
} CFF_Builder;
 
 
FT_LOCAL( FT_Error )
cff_check_points( CFF_Builder* builder,
FT_Int count );
 
FT_LOCAL( void )
cff_builder_add_point( CFF_Builder* builder,
FT_Pos x,
FT_Pos y,
FT_Byte flag );
FT_LOCAL( FT_Error )
cff_builder_add_point1( CFF_Builder* builder,
FT_Pos x,
FT_Pos y );
FT_LOCAL( FT_Error )
cff_builder_start_point( CFF_Builder* builder,
FT_Pos x,
FT_Pos y );
FT_LOCAL( void )
cff_builder_close_contour( CFF_Builder* builder );
 
 
FT_LOCAL( FT_Int )
cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
FT_Int charcode );
FT_LOCAL( FT_Error )
cff_get_glyph_data( TT_Face face,
FT_UInt glyph_index,
FT_Byte** pointer,
FT_ULong* length );
FT_LOCAL( void )
cff_free_glyph_data( TT_Face face,
FT_Byte** pointer,
FT_ULong length );
 
 
/* execution context charstring zone */
 
typedef struct CFF_Decoder_Zone_
{
FT_Byte* base;
FT_Byte* limit;
FT_Byte* cursor;
 
} CFF_Decoder_Zone;
 
 
typedef struct CFF_Decoder_
{
CFF_Builder builder;
CFF_Font cff;
 
FT_Fixed stack[CFF_MAX_OPERANDS + 1];
FT_Fixed* top;
 
CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1];
CFF_Decoder_Zone* zone;
 
FT_Int flex_state;
FT_Int num_flex_vectors;
FT_Vector flex_vectors[7];
 
FT_Pos glyph_width;
FT_Pos nominal_width;
 
FT_Bool read_width;
FT_Bool width_only;
FT_Int num_hints;
FT_Fixed buildchar[CFF_MAX_TRANS_ELEMENTS];
 
FT_UInt num_locals;
FT_UInt num_globals;
 
FT_Int locals_bias;
FT_Int globals_bias;
 
FT_Byte** locals;
FT_Byte** globals;
 
FT_Byte** glyph_names; /* for pure CFF fonts only */
FT_UInt num_glyphs; /* number of glyphs in font */
 
FT_Render_Mode hint_mode;
 
FT_Bool seac;
 
CFF_SubFont current_subfont; /* for current glyph_index */
 
} CFF_Decoder;
 
 
FT_LOCAL( void )
cff_decoder_init( CFF_Decoder* decoder,
TT_Face face,
CFF_Size size,
CFF_GlyphSlot slot,
FT_Bool hinting,
FT_Render_Mode hint_mode );
 
FT_LOCAL( FT_Error )
cff_decoder_prepare( CFF_Decoder* decoder,
CFF_Size size,
FT_UInt glyph_index );
 
#if 0 /* unused until we support pure CFF fonts */
 
/* Compute the maximum advance width of a font through quick parsing */
FT_LOCAL( FT_Error )
cff_compute_max_advance( TT_Face face,
FT_Int* max_advance );
 
#endif /* 0 */
 
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
FT_LOCAL( FT_Error )
cff_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
FT_ULong charstring_len );
#endif
 
FT_LOCAL( FT_Error )
cff_slot_load( CFF_GlyphSlot glyph,
CFF_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags );
 
 
FT_END_HEADER
 
#endif /* __CFFGLOAD_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffload.c
0,0 → 1,1696
/***************************************************************************/
/* */
/* cffload.c */
/* */
/* OpenType and CFF data/program tables loader (body). */
/* */
/* Copyright 1996-2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include FT_TYPE1_TABLES_H
 
#include "cffload.h"
#include "cffparse.h"
 
#include "cfferrs.h"
 
 
#if 1
 
static const FT_UShort cff_isoadobe_charset[229] =
{
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 149, 150, 151,
152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191,
192, 193, 194, 195, 196, 197, 198, 199,
200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215,
216, 217, 218, 219, 220, 221, 222, 223,
224, 225, 226, 227, 228
};
 
static const FT_UShort cff_expert_charset[166] =
{
0, 1, 229, 230, 231, 232, 233, 234,
235, 236, 237, 238, 13, 14, 15, 99,
239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 27, 28, 249, 250, 251, 252,
253, 254, 255, 256, 257, 258, 259, 260,
261, 262, 263, 264, 265, 266, 109, 110,
267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282,
283, 284, 285, 286, 287, 288, 289, 290,
291, 292, 293, 294, 295, 296, 297, 298,
299, 300, 301, 302, 303, 304, 305, 306,
307, 308, 309, 310, 311, 312, 313, 314,
315, 316, 317, 318, 158, 155, 163, 319,
320, 321, 322, 323, 324, 325, 326, 150,
164, 169, 327, 328, 329, 330, 331, 332,
333, 334, 335, 336, 337, 338, 339, 340,
341, 342, 343, 344, 345, 346, 347, 348,
349, 350, 351, 352, 353, 354, 355, 356,
357, 358, 359, 360, 361, 362, 363, 364,
365, 366, 367, 368, 369, 370, 371, 372,
373, 374, 375, 376, 377, 378
};
 
static const FT_UShort cff_expertsubset_charset[87] =
{
0, 1, 231, 232, 235, 236, 237, 238,
13, 14, 15, 99, 239, 240, 241, 242,
243, 244, 245, 246, 247, 248, 27, 28,
249, 250, 251, 253, 254, 255, 256, 257,
258, 259, 260, 261, 262, 263, 264, 265,
266, 109, 110, 267, 268, 269, 270, 272,
300, 301, 302, 305, 314, 315, 158, 155,
163, 320, 321, 322, 323, 324, 325, 326,
150, 164, 169, 327, 328, 329, 330, 331,
332, 333, 334, 335, 336, 337, 338, 339,
340, 341, 342, 343, 344, 345, 346
};
 
static const FT_UShort cff_standard_encoding[256] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72,
73, 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88,
89, 90, 91, 92, 93, 94, 95, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 96, 97, 98, 99, 100, 101, 102,
103, 104, 105, 106, 107, 108, 109, 110,
0, 111, 112, 113, 114, 0, 115, 116,
117, 118, 119, 120, 121, 122, 0, 123,
0, 124, 125, 126, 127, 128, 129, 130,
131, 0, 132, 133, 0, 134, 135, 136,
137, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 138, 0, 139, 0, 0, 0, 0,
140, 141, 142, 143, 0, 0, 0, 0,
0, 144, 0, 0, 0, 145, 0, 0,
146, 147, 148, 149, 0, 0, 0, 0
};
 
static const FT_UShort cff_expert_encoding[256] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 229, 230, 0, 231, 232, 233, 234,
235, 236, 237, 238, 13, 14, 15, 99,
239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 27, 28, 249, 250, 251, 252,
0, 253, 254, 255, 256, 257, 0, 0,
0, 258, 0, 0, 259, 260, 261, 262,
0, 0, 263, 264, 265, 0, 266, 109,
110, 267, 268, 269, 0, 270, 271, 272,
273, 274, 275, 276, 277, 278, 279, 280,
281, 282, 283, 284, 285, 286, 287, 288,
289, 290, 291, 292, 293, 294, 295, 296,
297, 298, 299, 300, 301, 302, 303, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 304, 305, 306, 0, 0, 307, 308,
309, 310, 311, 0, 312, 0, 0, 312,
0, 0, 314, 315, 0, 0, 316, 317,
318, 0, 0, 0, 158, 155, 163, 319,
320, 321, 322, 323, 324, 325, 0, 0,
326, 150, 164, 169, 327, 328, 329, 330,
331, 332, 333, 334, 335, 336, 337, 338,
339, 340, 341, 342, 343, 344, 345, 346,
347, 348, 349, 350, 351, 352, 353, 354,
355, 356, 357, 358, 359, 360, 361, 362,
363, 364, 365, 366, 367, 368, 369, 370,
371, 372, 373, 374, 375, 376, 377, 378
};
 
#endif /* 1 */
 
 
FT_LOCAL_DEF( FT_UShort )
cff_get_standard_encoding( FT_UInt charcode )
{
return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode]
: 0 );
}
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cffload
 
 
/* read an offset from the index's stream current position */
static FT_ULong
cff_index_read_offset( CFF_Index idx,
FT_Error *errorp )
{
FT_Error error;
FT_Stream stream = idx->stream;
FT_Byte tmp[4];
FT_ULong result = 0;
 
 
if ( !FT_STREAM_READ( tmp, idx->off_size ) )
{
FT_Int nn;
 
 
for ( nn = 0; nn < idx->off_size; nn++ )
result = ( result << 8 ) | tmp[nn];
}
 
*errorp = error;
return result;
}
 
 
static FT_Error
cff_index_init( CFF_Index idx,
FT_Stream stream,
FT_Bool load )
{
FT_Error error;
FT_Memory memory = stream->memory;
FT_UShort count;
 
 
FT_MEM_ZERO( idx, sizeof ( *idx ) );
 
idx->stream = stream;
idx->start = FT_STREAM_POS();
if ( !FT_READ_USHORT( count ) &&
count > 0 )
{
FT_Byte offsize;
FT_ULong size;
 
 
/* there is at least one element; read the offset size, */
/* then access the offset table to compute the index's total size */
if ( FT_READ_BYTE( offsize ) )
goto Exit;
 
if ( offsize < 1 || offsize > 4 )
{
error = FT_THROW( Invalid_Table );
goto Exit;
}
 
idx->count = count;
idx->off_size = offsize;
size = (FT_ULong)( count + 1 ) * offsize;
 
idx->data_offset = idx->start + 3 + size;
 
if ( FT_STREAM_SKIP( size - offsize ) )
goto Exit;
 
size = cff_index_read_offset( idx, &error );
if ( error )
goto Exit;
 
if ( size == 0 )
{
error = FT_THROW( Invalid_Table );
goto Exit;
}
 
idx->data_size = --size;
 
if ( load )
{
/* load the data */
if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
goto Exit;
}
else
{
/* skip the data */
if ( FT_STREAM_SKIP( size ) )
goto Exit;
}
}
 
Exit:
if ( error )
FT_FREE( idx->offsets );
 
return error;
}
 
 
static void
cff_index_done( CFF_Index idx )
{
if ( idx->stream )
{
FT_Stream stream = idx->stream;
FT_Memory memory = stream->memory;
 
 
if ( idx->bytes )
FT_FRAME_RELEASE( idx->bytes );
 
FT_FREE( idx->offsets );
FT_MEM_ZERO( idx, sizeof ( *idx ) );
}
}
 
 
static FT_Error
cff_index_load_offsets( CFF_Index idx )
{
FT_Error error = FT_Err_Ok;
FT_Stream stream = idx->stream;
FT_Memory memory = stream->memory;
 
 
if ( idx->count > 0 && idx->offsets == NULL )
{
FT_Byte offsize = idx->off_size;
FT_ULong data_size;
FT_Byte* p;
FT_Byte* p_end;
FT_ULong* poff;
 
 
data_size = (FT_ULong)( idx->count + 1 ) * offsize;
 
if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
FT_STREAM_SEEK( idx->start + 3 ) ||
FT_FRAME_ENTER( data_size ) )
goto Exit;
 
poff = idx->offsets;
p = (FT_Byte*)stream->cursor;
p_end = p + data_size;
 
switch ( offsize )
{
case 1:
for ( ; p < p_end; p++, poff++ )
poff[0] = p[0];
break;
 
case 2:
for ( ; p < p_end; p += 2, poff++ )
poff[0] = FT_PEEK_USHORT( p );
break;
 
case 3:
for ( ; p < p_end; p += 3, poff++ )
poff[0] = FT_PEEK_OFF3( p );
break;
 
default:
for ( ; p < p_end; p += 4, poff++ )
poff[0] = FT_PEEK_ULONG( p );
}
 
FT_FRAME_EXIT();
}
 
Exit:
if ( error )
FT_FREE( idx->offsets );
 
return error;
}
 
 
/* Allocate a table containing pointers to an index's elements. */
/* The `pool' argument makes this function convert the index */
/* entries to C-style strings (this is, NULL-terminated). */
static FT_Error
cff_index_get_pointers( CFF_Index idx,
FT_Byte*** table,
FT_Byte** pool )
{
FT_Error error = FT_Err_Ok;
FT_Memory memory = idx->stream->memory;
 
FT_Byte** t = NULL;
FT_Byte* new_bytes = NULL;
 
 
*table = NULL;
 
if ( idx->offsets == NULL )
{
error = cff_index_load_offsets( idx );
if ( error )
goto Exit;
}
 
if ( idx->count > 0 &&
!FT_NEW_ARRAY( t, idx->count + 1 ) &&
( !pool || !FT_ALLOC( new_bytes,
idx->data_size + idx->count ) ) )
{
FT_ULong n, cur_offset;
FT_ULong extra = 0;
FT_Byte* org_bytes = idx->bytes;
 
 
/* at this point, `idx->offsets' can't be NULL */
cur_offset = idx->offsets[0] - 1;
 
/* sanity check */
if ( cur_offset >= idx->data_size )
{
FT_TRACE0(( "cff_index_get_pointers:"
" invalid first offset value %d set to zero\n",
cur_offset ));
cur_offset = 0;
}
 
if ( !pool )
t[0] = org_bytes + cur_offset;
else
t[0] = new_bytes + cur_offset;
 
for ( n = 1; n <= idx->count; n++ )
{
FT_ULong next_offset = idx->offsets[n] - 1;
 
 
/* empty slot + two sanity checks for invalid offset tables */
if ( next_offset == 0 ||
next_offset < cur_offset ||
( next_offset >= idx->data_size && n < idx->count ) )
next_offset = cur_offset;
 
if ( !pool )
t[n] = org_bytes + next_offset;
else
{
t[n] = new_bytes + next_offset + extra;
 
if ( next_offset != cur_offset )
{
FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
t[n][0] = '\0';
t[n] += 1;
extra++;
}
}
 
cur_offset = next_offset;
}
*table = t;
 
if ( pool )
*pool = new_bytes;
}
 
Exit:
return error;
}
 
 
FT_LOCAL_DEF( FT_Error )
cff_index_access_element( CFF_Index idx,
FT_UInt element,
FT_Byte** pbytes,
FT_ULong* pbyte_len )
{
FT_Error error = FT_Err_Ok;
 
 
if ( idx && idx->count > element )
{
/* compute start and end offsets */
FT_Stream stream = idx->stream;
FT_ULong off1, off2 = 0;
 
 
/* load offsets from file or the offset table */
if ( !idx->offsets )
{
FT_ULong pos = element * idx->off_size;
 
 
if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
goto Exit;
 
off1 = cff_index_read_offset( idx, &error );
if ( error )
goto Exit;
 
if ( off1 != 0 )
{
do
{
element++;
off2 = cff_index_read_offset( idx, &error );
}
while ( off2 == 0 && element < idx->count );
}
}
else /* use offsets table */
{
off1 = idx->offsets[element];
if ( off1 )
{
do
{
element++;
off2 = idx->offsets[element];
 
} while ( off2 == 0 && element < idx->count );
}
}
 
/* XXX: should check off2 does not exceed the end of this entry; */
/* at present, only truncate off2 at the end of this stream */
if ( off2 > stream->size + 1 ||
idx->data_offset > stream->size - off2 + 1 )
{
FT_ERROR(( "cff_index_access_element:"
" offset to next entry (%d)"
" exceeds the end of stream (%d)\n",
off2, stream->size - idx->data_offset + 1 ));
off2 = stream->size - idx->data_offset + 1;
}
 
/* access element */
if ( off1 && off2 > off1 )
{
*pbyte_len = off2 - off1;
 
if ( idx->bytes )
{
/* this index was completely loaded in memory, that's easy */
*pbytes = idx->bytes + off1 - 1;
}
else
{
/* this index is still on disk/file, access it through a frame */
if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
FT_FRAME_EXTRACT( off2 - off1, *pbytes ) )
goto Exit;
}
}
else
{
/* empty index element */
*pbytes = 0;
*pbyte_len = 0;
}
}
else
error = FT_THROW( Invalid_Argument );
 
Exit:
return error;
}
 
 
FT_LOCAL_DEF( void )
cff_index_forget_element( CFF_Index idx,
FT_Byte** pbytes )
{
if ( idx->bytes == 0 )
{
FT_Stream stream = idx->stream;
 
 
FT_FRAME_RELEASE( *pbytes );
}
}
 
 
/* get an entry from Name INDEX */
FT_LOCAL_DEF( FT_String* )
cff_index_get_name( CFF_Font font,
FT_UInt element )
{
CFF_Index idx = &font->name_index;
FT_Memory memory = idx->stream->memory;
FT_Byte* bytes;
FT_ULong byte_len;
FT_Error error;
FT_String* name = 0;
 
 
error = cff_index_access_element( idx, element, &bytes, &byte_len );
if ( error )
goto Exit;
 
if ( !FT_ALLOC( name, byte_len + 1 ) )
{
FT_MEM_COPY( name, bytes, byte_len );
name[byte_len] = 0;
}
cff_index_forget_element( idx, &bytes );
 
Exit:
return name;
}
 
 
/* get an entry from String INDEX */
FT_LOCAL_DEF( FT_String* )
cff_index_get_string( CFF_Font font,
FT_UInt element )
{
return ( element < font->num_strings )
? (FT_String*)font->strings[element]
: NULL;
}
 
 
FT_LOCAL_DEF( FT_String* )
cff_index_get_sid_string( CFF_Font font,
FT_UInt sid )
{
/* value 0xFFFFU indicates a missing dictionary entry */
if ( sid == 0xFFFFU )
return NULL;
 
/* if it is not a standard string, return it */
if ( sid > 390 )
return cff_index_get_string( font, sid - 391 );
 
/* CID-keyed CFF fonts don't have glyph names */
if ( !font->psnames )
return NULL;
 
/* this is a standard string */
return (FT_String *)font->psnames->adobe_std_strings( sid );
}
 
 
/*************************************************************************/
/*************************************************************************/
/*** ***/
/*** FD Select table support ***/
/*** ***/
/*************************************************************************/
/*************************************************************************/
 
 
static void
CFF_Done_FD_Select( CFF_FDSelect fdselect,
FT_Stream stream )
{
if ( fdselect->data )
FT_FRAME_RELEASE( fdselect->data );
 
fdselect->data_size = 0;
fdselect->format = 0;
fdselect->range_count = 0;
}
 
 
static FT_Error
CFF_Load_FD_Select( CFF_FDSelect fdselect,
FT_UInt num_glyphs,
FT_Stream stream,
FT_ULong offset )
{
FT_Error error;
FT_Byte format;
FT_UInt num_ranges;
 
 
/* read format */
if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
goto Exit;
 
fdselect->format = format;
fdselect->cache_count = 0; /* clear cache */
 
switch ( format )
{
case 0: /* format 0, that's simple */
fdselect->data_size = num_glyphs;
goto Load_Data;
 
case 3: /* format 3, a tad more complex */
if ( FT_READ_USHORT( num_ranges ) )
goto Exit;
 
fdselect->data_size = num_ranges * 3 + 2;
 
Load_Data:
if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
goto Exit;
break;
 
default: /* hmm... that's wrong */
error = FT_THROW( Invalid_File_Format );
}
 
Exit:
return error;
}
 
 
FT_LOCAL_DEF( FT_Byte )
cff_fd_select_get( CFF_FDSelect fdselect,
FT_UInt glyph_index )
{
FT_Byte fd = 0;
 
 
switch ( fdselect->format )
{
case 0:
fd = fdselect->data[glyph_index];
break;
 
case 3:
/* first, compare to cache */
if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
fdselect->cache_count )
{
fd = fdselect->cache_fd;
break;
}
 
/* then, lookup the ranges array */
{
FT_Byte* p = fdselect->data;
FT_Byte* p_limit = p + fdselect->data_size;
FT_Byte fd2;
FT_UInt first, limit;
 
 
first = FT_NEXT_USHORT( p );
do
{
if ( glyph_index < first )
break;
 
fd2 = *p++;
limit = FT_NEXT_USHORT( p );
 
if ( glyph_index < limit )
{
fd = fd2;
 
/* update cache */
fdselect->cache_first = first;
fdselect->cache_count = limit-first;
fdselect->cache_fd = fd2;
break;
}
first = limit;
 
} while ( p < p_limit );
}
break;
 
default:
;
}
 
return fd;
}
 
 
/*************************************************************************/
/*************************************************************************/
/*** ***/
/*** CFF font support ***/
/*** ***/
/*************************************************************************/
/*************************************************************************/
 
static FT_Error
cff_charset_compute_cids( CFF_Charset charset,
FT_UInt num_glyphs,
FT_Memory memory )
{
FT_Error error = FT_Err_Ok;
FT_UInt i;
FT_Long j;
FT_UShort max_cid = 0;
 
 
if ( charset->max_cid > 0 )
goto Exit;
 
for ( i = 0; i < num_glyphs; i++ )
{
if ( charset->sids[i] > max_cid )
max_cid = charset->sids[i];
}
 
if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
goto Exit;
 
/* When multiple GIDs map to the same CID, we choose the lowest */
/* GID. This is not described in any spec, but it matches the */
/* behaviour of recent Acroread versions. */
for ( j = num_glyphs - 1; j >= 0 ; j-- )
charset->cids[charset->sids[j]] = (FT_UShort)j;
 
charset->max_cid = max_cid;
charset->num_glyphs = num_glyphs;
 
Exit:
return error;
}
 
 
FT_LOCAL_DEF( FT_UInt )
cff_charset_cid_to_gindex( CFF_Charset charset,
FT_UInt cid )
{
FT_UInt result = 0;
 
 
if ( cid <= charset->max_cid )
result = charset->cids[cid];
 
return result;
}
 
 
static void
cff_charset_free_cids( CFF_Charset charset,
FT_Memory memory )
{
FT_FREE( charset->cids );
charset->max_cid = 0;
}
 
 
static void
cff_charset_done( CFF_Charset charset,
FT_Stream stream )
{
FT_Memory memory = stream->memory;
 
 
cff_charset_free_cids( charset, memory );
 
FT_FREE( charset->sids );
charset->format = 0;
charset->offset = 0;
}
 
 
static FT_Error
cff_charset_load( CFF_Charset charset,
FT_UInt num_glyphs,
FT_Stream stream,
FT_ULong base_offset,
FT_ULong offset,
FT_Bool invert )
{
FT_Memory memory = stream->memory;
FT_Error error = FT_Err_Ok;
FT_UShort glyph_sid;
 
 
/* If the the offset is greater than 2, we have to parse the */
/* charset table. */
if ( offset > 2 )
{
FT_UInt j;
 
 
charset->offset = base_offset + offset;
 
/* Get the format of the table. */
if ( FT_STREAM_SEEK( charset->offset ) ||
FT_READ_BYTE( charset->format ) )
goto Exit;
 
/* Allocate memory for sids. */
if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
goto Exit;
 
/* assign the .notdef glyph */
charset->sids[0] = 0;
 
switch ( charset->format )
{
case 0:
if ( num_glyphs > 0 )
{
if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
goto Exit;
 
for ( j = 1; j < num_glyphs; j++ )
charset->sids[j] = FT_GET_USHORT();
 
FT_FRAME_EXIT();
}
break;
 
case 1:
case 2:
{
FT_UInt nleft;
FT_UInt i;
 
 
j = 1;
 
while ( j < num_glyphs )
{
/* Read the first glyph sid of the range. */
if ( FT_READ_USHORT( glyph_sid ) )
goto Exit;
 
/* Read the number of glyphs in the range. */
if ( charset->format == 2 )
{
if ( FT_READ_USHORT( nleft ) )
goto Exit;
}
else
{
if ( FT_READ_BYTE( nleft ) )
goto Exit;
}
 
/* try to rescue some of the SIDs if `nleft' is too large */
if ( glyph_sid > 0xFFFFL - nleft )
{
FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
" nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
}
 
/* Fill in the range of sids -- `nleft + 1' glyphs. */
for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
charset->sids[j] = glyph_sid;
}
}
break;
 
default:
FT_ERROR(( "cff_charset_load: invalid table format\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
}
else
{
/* Parse default tables corresponding to offset == 0, 1, or 2. */
/* CFF specification intimates the following: */
/* */
/* In order to use a predefined charset, the following must be */
/* true: The charset constructed for the glyphs in the font's */
/* charstrings dictionary must match the predefined charset in */
/* the first num_glyphs. */
 
charset->offset = offset; /* record charset type */
 
switch ( (FT_UInt)offset )
{
case 0:
if ( num_glyphs > 229 )
{
FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
"predefined charset (Adobe ISO-Latin)\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
 
/* Allocate memory for sids. */
if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
goto Exit;
 
/* Copy the predefined charset into the allocated memory. */
FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
 
break;
 
case 1:
if ( num_glyphs > 166 )
{
FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
"predefined charset (Adobe Expert)\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
 
/* Allocate memory for sids. */
if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
goto Exit;
 
/* Copy the predefined charset into the allocated memory. */
FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
 
break;
 
case 2:
if ( num_glyphs > 87 )
{
FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
"predefined charset (Adobe Expert Subset)\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
 
/* Allocate memory for sids. */
if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
goto Exit;
 
/* Copy the predefined charset into the allocated memory. */
FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
 
break;
 
default:
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
}
 
/* we have to invert the `sids' array for subsetted CID-keyed fonts */
if ( invert )
error = cff_charset_compute_cids( charset, num_glyphs, memory );
 
Exit:
/* Clean up if there was an error. */
if ( error )
{
FT_FREE( charset->sids );
FT_FREE( charset->cids );
charset->format = 0;
charset->offset = 0;
charset->sids = 0;
}
 
return error;
}
 
 
static void
cff_encoding_done( CFF_Encoding encoding )
{
encoding->format = 0;
encoding->offset = 0;
encoding->count = 0;
}
 
 
static FT_Error
cff_encoding_load( CFF_Encoding encoding,
CFF_Charset charset,
FT_UInt num_glyphs,
FT_Stream stream,
FT_ULong base_offset,
FT_ULong offset )
{
FT_Error error = FT_Err_Ok;
FT_UInt count;
FT_UInt j;
FT_UShort glyph_sid;
FT_UInt glyph_code;
 
 
/* Check for charset->sids. If we do not have this, we fail. */
if ( !charset->sids )
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
 
/* Zero out the code to gid/sid mappings. */
for ( j = 0; j < 256; j++ )
{
encoding->sids [j] = 0;
encoding->codes[j] = 0;
}
 
/* Note: The encoding table in a CFF font is indexed by glyph index; */
/* the first encoded glyph index is 1. Hence, we read the character */
/* code (`glyph_code') at index j and make the assignment: */
/* */
/* encoding->codes[glyph_code] = j + 1 */
/* */
/* We also make the assignment: */
/* */
/* encoding->sids[glyph_code] = charset->sids[j + 1] */
/* */
/* This gives us both a code to GID and a code to SID mapping. */
 
if ( offset > 1 )
{
encoding->offset = base_offset + offset;
 
/* we need to parse the table to determine its size */
if ( FT_STREAM_SEEK( encoding->offset ) ||
FT_READ_BYTE( encoding->format ) ||
FT_READ_BYTE( count ) )
goto Exit;
 
switch ( encoding->format & 0x7F )
{
case 0:
{
FT_Byte* p;
 
 
/* By convention, GID 0 is always ".notdef" and is never */
/* coded in the font. Hence, the number of codes found */
/* in the table is `count+1'. */
/* */
encoding->count = count + 1;
 
if ( FT_FRAME_ENTER( count ) )
goto Exit;
 
p = (FT_Byte*)stream->cursor;
 
for ( j = 1; j <= count; j++ )
{
glyph_code = *p++;
 
/* Make sure j is not too big. */
if ( j < num_glyphs )
{
/* Assign code to GID mapping. */
encoding->codes[glyph_code] = (FT_UShort)j;
 
/* Assign code to SID mapping. */
encoding->sids[glyph_code] = charset->sids[j];
}
}
 
FT_FRAME_EXIT();
}
break;
 
case 1:
{
FT_UInt nleft;
FT_UInt i = 1;
FT_UInt k;
 
 
encoding->count = 0;
 
/* Parse the Format1 ranges. */
for ( j = 0; j < count; j++, i += nleft )
{
/* Read the first glyph code of the range. */
if ( FT_READ_BYTE( glyph_code ) )
goto Exit;
 
/* Read the number of codes in the range. */
if ( FT_READ_BYTE( nleft ) )
goto Exit;
 
/* Increment nleft, so we read `nleft + 1' codes/sids. */
nleft++;
 
/* compute max number of character codes */
if ( (FT_UInt)nleft > encoding->count )
encoding->count = nleft;
 
/* Fill in the range of codes/sids. */
for ( k = i; k < nleft + i; k++, glyph_code++ )
{
/* Make sure k is not too big. */
if ( k < num_glyphs && glyph_code < 256 )
{
/* Assign code to GID mapping. */
encoding->codes[glyph_code] = (FT_UShort)k;
 
/* Assign code to SID mapping. */
encoding->sids[glyph_code] = charset->sids[k];
}
}
}
 
/* simple check; one never knows what can be found in a font */
if ( encoding->count > 256 )
encoding->count = 256;
}
break;
 
default:
FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
 
/* Parse supplemental encodings, if any. */
if ( encoding->format & 0x80 )
{
FT_UInt gindex;
 
 
/* count supplements */
if ( FT_READ_BYTE( count ) )
goto Exit;
 
for ( j = 0; j < count; j++ )
{
/* Read supplemental glyph code. */
if ( FT_READ_BYTE( glyph_code ) )
goto Exit;
 
/* Read the SID associated with this glyph code. */
if ( FT_READ_USHORT( glyph_sid ) )
goto Exit;
 
/* Assign code to SID mapping. */
encoding->sids[glyph_code] = glyph_sid;
 
/* First, look up GID which has been assigned to */
/* SID glyph_sid. */
for ( gindex = 0; gindex < num_glyphs; gindex++ )
{
if ( charset->sids[gindex] == glyph_sid )
{
encoding->codes[glyph_code] = (FT_UShort)gindex;
break;
}
}
}
}
}
else
{
/* We take into account the fact a CFF font can use a predefined */
/* encoding without containing all of the glyphs encoded by this */
/* encoding (see the note at the end of section 12 in the CFF */
/* specification). */
 
switch ( (FT_UInt)offset )
{
case 0:
/* First, copy the code to SID mapping. */
FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
goto Populate;
 
case 1:
/* First, copy the code to SID mapping. */
FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
 
Populate:
/* Construct code to GID mapping from code to SID mapping */
/* and charset. */
 
encoding->count = 0;
 
error = cff_charset_compute_cids( charset, num_glyphs,
stream->memory );
if ( error )
goto Exit;
 
for ( j = 0; j < 256; j++ )
{
FT_UInt sid = encoding->sids[j];
FT_UInt gid = 0;
 
 
if ( sid )
gid = cff_charset_cid_to_gindex( charset, sid );
 
if ( gid != 0 )
{
encoding->codes[j] = (FT_UShort)gid;
encoding->count = j + 1;
}
else
{
encoding->codes[j] = 0;
encoding->sids [j] = 0;
}
}
break;
 
default:
FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
}
 
Exit:
 
/* Clean up if there was an error. */
return error;
}
 
 
static FT_Error
cff_subfont_load( CFF_SubFont font,
CFF_Index idx,
FT_UInt font_index,
FT_Stream stream,
FT_ULong base_offset,
FT_Library library )
{
FT_Error error;
CFF_ParserRec parser;
FT_Byte* dict = NULL;
FT_ULong dict_len;
CFF_FontRecDict top = &font->font_dict;
CFF_Private priv = &font->private_dict;
 
 
cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
 
/* set defaults */
FT_MEM_ZERO( top, sizeof ( *top ) );
 
top->underline_position = -( 100L << 16 );
top->underline_thickness = 50L << 16;
top->charstring_type = 2;
top->font_matrix.xx = 0x10000L;
top->font_matrix.yy = 0x10000L;
top->cid_count = 8720;
 
/* we use the implementation specific SID value 0xFFFF to indicate */
/* missing entries */
top->version = 0xFFFFU;
top->notice = 0xFFFFU;
top->copyright = 0xFFFFU;
top->full_name = 0xFFFFU;
top->family_name = 0xFFFFU;
top->weight = 0xFFFFU;
top->embedded_postscript = 0xFFFFU;
 
top->cid_registry = 0xFFFFU;
top->cid_ordering = 0xFFFFU;
top->cid_font_name = 0xFFFFU;
 
error = cff_index_access_element( idx, font_index, &dict, &dict_len );
if ( !error )
{
FT_TRACE4(( " top dictionary:\n" ));
error = cff_parser_run( &parser, dict, dict + dict_len );
}
 
cff_index_forget_element( idx, &dict );
 
if ( error )
goto Exit;
 
/* if it is a CID font, we stop there */
if ( top->cid_registry != 0xFFFFU )
goto Exit;
 
/* parse the private dictionary, if any */
if ( top->private_offset && top->private_size )
{
/* set defaults */
FT_MEM_ZERO( priv, sizeof ( *priv ) );
 
priv->blue_shift = 7;
priv->blue_fuzz = 1;
priv->lenIV = -1;
priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
 
cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
 
if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
FT_FRAME_ENTER( font->font_dict.private_size ) )
goto Exit;
 
FT_TRACE4(( " private dictionary:\n" ));
error = cff_parser_run( &parser,
(FT_Byte*)stream->cursor,
(FT_Byte*)stream->limit );
FT_FRAME_EXIT();
if ( error )
goto Exit;
 
/* ensure that `num_blue_values' is even */
priv->num_blue_values &= ~1;
}
 
/* read the local subrs, if any */
if ( priv->local_subrs_offset )
{
if ( FT_STREAM_SEEK( base_offset + top->private_offset +
priv->local_subrs_offset ) )
goto Exit;
 
error = cff_index_init( &font->local_subrs_index, stream, 1 );
if ( error )
goto Exit;
 
error = cff_index_get_pointers( &font->local_subrs_index,
&font->local_subrs, NULL );
if ( error )
goto Exit;
}
 
Exit:
return error;
}
 
 
static void
cff_subfont_done( FT_Memory memory,
CFF_SubFont subfont )
{
if ( subfont )
{
cff_index_done( &subfont->local_subrs_index );
FT_FREE( subfont->local_subrs );
}
}
 
 
FT_LOCAL_DEF( FT_Error )
cff_font_load( FT_Library library,
FT_Stream stream,
FT_Int face_index,
CFF_Font font,
FT_Bool pure_cff )
{
static const FT_Frame_Field cff_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_FontRec
 
FT_FRAME_START( 4 ),
FT_FRAME_BYTE( version_major ),
FT_FRAME_BYTE( version_minor ),
FT_FRAME_BYTE( header_size ),
FT_FRAME_BYTE( absolute_offsize ),
FT_FRAME_END
};
 
FT_Error error;
FT_Memory memory = stream->memory;
FT_ULong base_offset;
CFF_FontRecDict dict;
CFF_IndexRec string_index;
FT_Int subfont_index;
 
 
FT_ZERO( font );
FT_ZERO( &string_index );
 
font->stream = stream;
font->memory = memory;
dict = &font->top_font.font_dict;
base_offset = FT_STREAM_POS();
 
/* read CFF font header */
if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
goto Exit;
 
/* check format */
if ( font->version_major != 1 ||
font->header_size < 4 ||
font->absolute_offsize > 4 )
{
FT_TRACE2(( " not a CFF font header\n" ));
error = FT_THROW( Unknown_File_Format );
goto Exit;
}
 
/* skip the rest of the header */
if ( FT_STREAM_SKIP( font->header_size - 4 ) )
goto Exit;
 
/* read the name, top dict, string and global subrs index */
if ( FT_SET_ERROR( cff_index_init( &font->name_index,
stream, 0 ) ) ||
FT_SET_ERROR( cff_index_init( &font->font_dict_index,
stream, 0 ) ) ||
FT_SET_ERROR( cff_index_init( &string_index,
stream, 1 ) ) ||
FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
stream, 1 ) ) ||
FT_SET_ERROR( cff_index_get_pointers( &string_index,
&font->strings,
&font->string_pool ) ) )
goto Exit;
 
font->num_strings = string_index.count;
 
if ( pure_cff )
{
/* well, we don't really forget the `disabled' fonts... */
subfont_index = face_index;
 
if ( subfont_index >= (FT_Int)font->name_index.count )
{
FT_ERROR(( "cff_font_load:"
" invalid subfont index for pure CFF font (%d)\n",
subfont_index ));
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
font->num_faces = font->name_index.count;
}
else
{
subfont_index = 0;
 
if ( font->name_index.count > 1 )
{
FT_ERROR(( "cff_font_load:"
" invalid CFF font with multiple subfonts\n"
" "
" in SFNT wrapper\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
}
 
/* in case of a font format check, simply exit now */
if ( face_index < 0 )
goto Exit;
 
/* now, parse the top-level font dictionary */
FT_TRACE4(( "parsing top-level\n" ));
error = cff_subfont_load( &font->top_font,
&font->font_dict_index,
subfont_index,
stream,
base_offset,
library );
if ( error )
goto Exit;
 
if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
goto Exit;
 
error = cff_index_init( &font->charstrings_index, stream, 0 );
if ( error )
goto Exit;
 
/* now, check for a CID font */
if ( dict->cid_registry != 0xFFFFU )
{
CFF_IndexRec fd_index;
CFF_SubFont sub = NULL;
FT_UInt idx;
 
 
/* this is a CID-keyed font, we must now allocate a table of */
/* sub-fonts, then load each of them separately */
if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
goto Exit;
 
error = cff_index_init( &fd_index, stream, 0 );
if ( error )
goto Exit;
 
if ( fd_index.count > CFF_MAX_CID_FONTS )
{
FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
goto Fail_CID;
}
 
/* allocate & read each font dict independently */
font->num_subfonts = fd_index.count;
if ( FT_NEW_ARRAY( sub, fd_index.count ) )
goto Fail_CID;
 
/* set up pointer table */
for ( idx = 0; idx < fd_index.count; idx++ )
font->subfonts[idx] = sub + idx;
 
/* now load each subfont independently */
for ( idx = 0; idx < fd_index.count; idx++ )
{
sub = font->subfonts[idx];
FT_TRACE4(( "parsing subfont %u\n", idx ));
error = cff_subfont_load( sub, &fd_index, idx,
stream, base_offset, library );
if ( error )
goto Fail_CID;
}
 
/* now load the FD Select array */
error = CFF_Load_FD_Select( &font->fd_select,
font->charstrings_index.count,
stream,
base_offset + dict->cid_fd_select_offset );
 
Fail_CID:
cff_index_done( &fd_index );
 
if ( error )
goto Exit;
}
else
font->num_subfonts = 0;
 
/* read the charstrings index now */
if ( dict->charstrings_offset == 0 )
{
FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
 
font->num_glyphs = font->charstrings_index.count;
 
error = cff_index_get_pointers( &font->global_subrs_index,
&font->global_subrs, NULL );
 
if ( error )
goto Exit;
 
/* read the Charset and Encoding tables if available */
if ( font->num_glyphs > 0 )
{
FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
 
 
error = cff_charset_load( &font->charset, font->num_glyphs, stream,
base_offset, dict->charset_offset, invert );
if ( error )
goto Exit;
 
/* CID-keyed CFFs don't have an encoding */
if ( dict->cid_registry == 0xFFFFU )
{
error = cff_encoding_load( &font->encoding,
&font->charset,
font->num_glyphs,
stream,
base_offset,
dict->encoding_offset );
if ( error )
goto Exit;
}
}
 
/* get the font name (/CIDFontName for CID-keyed fonts, */
/* /FontName otherwise) */
font->font_name = cff_index_get_name( font, subfont_index );
 
Exit:
cff_index_done( &string_index );
 
return error;
}
 
 
FT_LOCAL_DEF( void )
cff_font_done( CFF_Font font )
{
FT_Memory memory = font->memory;
FT_UInt idx;
 
 
cff_index_done( &font->global_subrs_index );
cff_index_done( &font->font_dict_index );
cff_index_done( &font->name_index );
cff_index_done( &font->charstrings_index );
 
/* release font dictionaries, but only if working with */
/* a CID keyed CFF font */
if ( font->num_subfonts > 0 )
{
for ( idx = 0; idx < font->num_subfonts; idx++ )
cff_subfont_done( memory, font->subfonts[idx] );
 
/* the subfonts array has been allocated as a single block */
FT_FREE( font->subfonts[0] );
}
 
cff_encoding_done( &font->encoding );
cff_charset_done( &font->charset, font->stream );
 
cff_subfont_done( memory, &font->top_font );
 
CFF_Done_FD_Select( &font->fd_select, font->stream );
 
FT_FREE( font->font_info );
 
FT_FREE( font->font_name );
FT_FREE( font->global_subrs );
FT_FREE( font->strings );
FT_FREE( font->string_pool );
 
if ( font->cf2_instance.finalizer )
{
font->cf2_instance.finalizer( font->cf2_instance.data );
FT_FREE( font->cf2_instance.data );
}
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffload.h
0,0 → 1,83
/***************************************************************************/
/* */
/* cffload.h */
/* */
/* OpenType & CFF data/program tables loader (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2007, 2008, 2010 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFFLOAD_H__
#define __CFFLOAD_H__
 
 
#include <ft2build.h>
#include "cfftypes.h"
 
 
FT_BEGIN_HEADER
 
FT_LOCAL( FT_UShort )
cff_get_standard_encoding( FT_UInt charcode );
 
 
FT_LOCAL( FT_String* )
cff_index_get_string( CFF_Font font,
FT_UInt element );
 
FT_LOCAL( FT_String* )
cff_index_get_sid_string( CFF_Font font,
FT_UInt sid );
 
 
FT_LOCAL( FT_Error )
cff_index_access_element( CFF_Index idx,
FT_UInt element,
FT_Byte** pbytes,
FT_ULong* pbyte_len );
 
FT_LOCAL( void )
cff_index_forget_element( CFF_Index idx,
FT_Byte** pbytes );
 
FT_LOCAL( FT_String* )
cff_index_get_name( CFF_Font font,
FT_UInt element );
 
 
FT_LOCAL( FT_UInt )
cff_charset_cid_to_gindex( CFF_Charset charset,
FT_UInt cid );
 
 
FT_LOCAL( FT_Error )
cff_font_load( FT_Library library,
FT_Stream stream,
FT_Int face_index,
CFF_Font font,
FT_Bool pure_cff );
 
FT_LOCAL( void )
cff_font_done( CFF_Font font );
 
 
FT_LOCAL( FT_Byte )
cff_fd_select_get( CFF_FDSelect fdselect,
FT_UInt glyph_index );
 
 
FT_END_HEADER
 
#endif /* __CFFLOAD_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffobjs.c
0,0 → 1,1077
/***************************************************************************/
/* */
/* cffobjs.c */
/* */
/* OpenType objects manager (body). */
/* */
/* Copyright 1996-2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
 
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_STREAM_H
#include FT_ERRORS_H
#include FT_TRUETYPE_IDS_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_SFNT_H
#include FT_CFF_DRIVER_H
 
#include "cffobjs.h"
#include "cffload.h"
#include "cffcmap.h"
#include "cffpic.h"
 
#include "cfferrs.h"
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cffobjs
 
 
/*************************************************************************/
/* */
/* SIZE FUNCTIONS */
/* */
/* Note that we store the global hints in the size's `internal' root */
/* field. */
/* */
/*************************************************************************/
 
 
static PSH_Globals_Funcs
cff_size_get_globals_funcs( CFF_Size size )
{
CFF_Face face = (CFF_Face)size->root.face;
CFF_Font font = (CFF_Font)face->extra.data;
PSHinter_Service pshinter = font->pshinter;
FT_Module module;
 
 
module = FT_Get_Module( size->root.face->driver->root.library,
"pshinter" );
return ( module && pshinter && pshinter->get_globals_funcs )
? pshinter->get_globals_funcs( module )
: 0;
}
 
 
FT_LOCAL_DEF( void )
cff_size_done( FT_Size cffsize ) /* CFF_Size */
{
CFF_Size size = (CFF_Size)cffsize;
CFF_Face face = (CFF_Face)size->root.face;
CFF_Font font = (CFF_Font)face->extra.data;
CFF_Internal internal = (CFF_Internal)cffsize->internal;
 
 
if ( internal )
{
PSH_Globals_Funcs funcs;
 
 
funcs = cff_size_get_globals_funcs( size );
if ( funcs )
{
FT_UInt i;
 
 
funcs->destroy( internal->topfont );
 
for ( i = font->num_subfonts; i > 0; i-- )
funcs->destroy( internal->subfonts[i - 1] );
}
 
/* `internal' is freed by destroy_size (in ftobjs.c) */
}
}
 
 
/* CFF and Type 1 private dictionaries have slightly different */
/* structures; we need to synthesize a Type 1 dictionary on the fly */
 
static void
cff_make_private_dict( CFF_SubFont subfont,
PS_Private priv )
{
CFF_Private cpriv = &subfont->private_dict;
FT_UInt n, count;
 
 
FT_MEM_ZERO( priv, sizeof ( *priv ) );
 
count = priv->num_blue_values = cpriv->num_blue_values;
for ( n = 0; n < count; n++ )
priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
 
count = priv->num_other_blues = cpriv->num_other_blues;
for ( n = 0; n < count; n++ )
priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
 
count = priv->num_family_blues = cpriv->num_family_blues;
for ( n = 0; n < count; n++ )
priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
 
count = priv->num_family_other_blues = cpriv->num_family_other_blues;
for ( n = 0; n < count; n++ )
priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
 
priv->blue_scale = cpriv->blue_scale;
priv->blue_shift = (FT_Int)cpriv->blue_shift;
priv->blue_fuzz = (FT_Int)cpriv->blue_fuzz;
 
priv->standard_width[0] = (FT_UShort)cpriv->standard_width;
priv->standard_height[0] = (FT_UShort)cpriv->standard_height;
 
count = priv->num_snap_widths = cpriv->num_snap_widths;
for ( n = 0; n < count; n++ )
priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n];
 
count = priv->num_snap_heights = cpriv->num_snap_heights;
for ( n = 0; n < count; n++ )
priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n];
 
priv->force_bold = cpriv->force_bold;
priv->language_group = cpriv->language_group;
priv->lenIV = cpriv->lenIV;
}
 
 
FT_LOCAL_DEF( FT_Error )
cff_size_init( FT_Size cffsize ) /* CFF_Size */
{
CFF_Size size = (CFF_Size)cffsize;
FT_Error error = FT_Err_Ok;
PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size );
 
 
if ( funcs )
{
CFF_Face face = (CFF_Face)cffsize->face;
CFF_Font font = (CFF_Font)face->extra.data;
CFF_Internal internal = NULL;
 
PS_PrivateRec priv;
FT_Memory memory = cffsize->face->memory;
 
FT_UInt i;
 
 
if ( FT_NEW( internal ) )
goto Exit;
 
cff_make_private_dict( &font->top_font, &priv );
error = funcs->create( cffsize->face->memory, &priv,
&internal->topfont );
if ( error )
goto Exit;
 
for ( i = font->num_subfonts; i > 0; i-- )
{
CFF_SubFont sub = font->subfonts[i - 1];
 
 
cff_make_private_dict( sub, &priv );
error = funcs->create( cffsize->face->memory, &priv,
&internal->subfonts[i - 1] );
if ( error )
goto Exit;
}
 
cffsize->internal = (FT_Size_Internal)(void*)internal;
}
 
size->strike_index = 0xFFFFFFFFUL;
 
Exit:
return error;
}
 
 
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
FT_LOCAL_DEF( FT_Error )
cff_size_select( FT_Size size,
FT_ULong strike_index )
{
CFF_Size cffsize = (CFF_Size)size;
PSH_Globals_Funcs funcs;
 
 
cffsize->strike_index = strike_index;
 
FT_Select_Metrics( size->face, strike_index );
 
funcs = cff_size_get_globals_funcs( cffsize );
 
if ( funcs )
{
CFF_Face face = (CFF_Face)size->face;
CFF_Font font = (CFF_Font)face->extra.data;
CFF_Internal internal = (CFF_Internal)size->internal;
 
FT_ULong top_upm = font->top_font.font_dict.units_per_em;
FT_UInt i;
 
 
funcs->set_scale( internal->topfont,
size->metrics.x_scale, size->metrics.y_scale,
0, 0 );
 
for ( i = font->num_subfonts; i > 0; i-- )
{
CFF_SubFont sub = font->subfonts[i - 1];
FT_ULong sub_upm = sub->font_dict.units_per_em;
FT_Pos x_scale, y_scale;
 
 
if ( top_upm != sub_upm )
{
x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
}
else
{
x_scale = size->metrics.x_scale;
y_scale = size->metrics.y_scale;
}
 
funcs->set_scale( internal->subfonts[i - 1],
x_scale, y_scale, 0, 0 );
}
}
 
return FT_Err_Ok;
}
 
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
 
FT_LOCAL_DEF( FT_Error )
cff_size_request( FT_Size size,
FT_Size_Request req )
{
CFF_Size cffsize = (CFF_Size)size;
PSH_Globals_Funcs funcs;
 
 
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
if ( FT_HAS_FIXED_SIZES( size->face ) )
{
CFF_Face cffface = (CFF_Face)size->face;
SFNT_Service sfnt = (SFNT_Service)cffface->sfnt;
FT_ULong strike_index;
 
 
if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) )
cffsize->strike_index = 0xFFFFFFFFUL;
else
return cff_size_select( size, strike_index );
}
 
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
FT_Request_Metrics( size->face, req );
 
funcs = cff_size_get_globals_funcs( cffsize );
 
if ( funcs )
{
CFF_Face cffface = (CFF_Face)size->face;
CFF_Font font = (CFF_Font)cffface->extra.data;
CFF_Internal internal = (CFF_Internal)size->internal;
 
FT_ULong top_upm = font->top_font.font_dict.units_per_em;
FT_UInt i;
 
 
funcs->set_scale( internal->topfont,
size->metrics.x_scale, size->metrics.y_scale,
0, 0 );
 
for ( i = font->num_subfonts; i > 0; i-- )
{
CFF_SubFont sub = font->subfonts[i - 1];
FT_ULong sub_upm = sub->font_dict.units_per_em;
FT_Pos x_scale, y_scale;
 
 
if ( top_upm != sub_upm )
{
x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
}
else
{
x_scale = size->metrics.x_scale;
y_scale = size->metrics.y_scale;
}
 
funcs->set_scale( internal->subfonts[i - 1],
x_scale, y_scale, 0, 0 );
}
}
 
return FT_Err_Ok;
}
 
 
/*************************************************************************/
/* */
/* SLOT FUNCTIONS */
/* */
/*************************************************************************/
 
FT_LOCAL_DEF( void )
cff_slot_done( FT_GlyphSlot slot )
{
slot->internal->glyph_hints = 0;
}
 
 
FT_LOCAL_DEF( FT_Error )
cff_slot_init( FT_GlyphSlot slot )
{
CFF_Face face = (CFF_Face)slot->face;
CFF_Font font = (CFF_Font)face->extra.data;
PSHinter_Service pshinter = font->pshinter;
 
 
if ( pshinter )
{
FT_Module module;
 
 
module = FT_Get_Module( slot->face->driver->root.library,
"pshinter" );
if ( module )
{
T2_Hints_Funcs funcs;
 
 
funcs = pshinter->get_t2_funcs( module );
slot->internal->glyph_hints = (void*)funcs;
}
}
 
return FT_Err_Ok;
}
 
 
/*************************************************************************/
/* */
/* FACE FUNCTIONS */
/* */
/*************************************************************************/
 
static FT_String*
cff_strcpy( FT_Memory memory,
const FT_String* source )
{
FT_Error error;
FT_String* result;
 
 
(void)FT_STRDUP( result, source );
 
FT_UNUSED( error );
 
return result;
}
 
 
/* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */
/* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */
/* have been seen in the wild. */
 
static void
remove_subset_prefix( FT_String* name )
{
FT_Int32 idx = 0;
FT_Int32 length = (FT_Int32)strlen( name ) + 1;
FT_Bool continue_search = 1;
 
 
while ( continue_search )
{
if ( length >= 7 && name[6] == '+' )
{
for ( idx = 0; idx < 6; idx++ )
{
/* ASCII uppercase letters */
if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
continue_search = 0;
}
 
if ( continue_search )
{
for ( idx = 7; idx < length; idx++ )
name[idx - 7] = name[idx];
length -= 7;
}
}
else
continue_search = 0;
}
}
 
 
/* Remove the style part from the family name (if present). */
 
static void
remove_style( FT_String* family_name,
const FT_String* style_name )
{
FT_Int32 family_name_length, style_name_length;
 
 
family_name_length = (FT_Int32)strlen( family_name );
style_name_length = (FT_Int32)strlen( style_name );
 
if ( family_name_length > style_name_length )
{
FT_Int idx;
 
 
for ( idx = 1; idx <= style_name_length; ++idx )
{
if ( family_name[family_name_length - idx] !=
style_name[style_name_length - idx] )
break;
}
 
if ( idx > style_name_length )
{
/* family_name ends with style_name; remove it */
idx = family_name_length - style_name_length - 1;
 
/* also remove special characters */
/* between real family name and style */
while ( idx > 0 &&
( family_name[idx] == '-' ||
family_name[idx] == ' ' ||
family_name[idx] == '_' ||
family_name[idx] == '+' ) )
--idx;
 
if ( idx > 0 )
family_name[idx + 1] = '\0';
}
}
}
 
 
FT_LOCAL_DEF( FT_Error )
cff_face_init( FT_Stream stream,
FT_Face cffface, /* CFF_Face */
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params )
{
CFF_Face face = (CFF_Face)cffface;
FT_Error error;
SFNT_Service sfnt;
FT_Service_PsCMaps psnames;
PSHinter_Service pshinter;
FT_Bool pure_cff = 1;
FT_Bool sfnt_format = 0;
FT_Library library = cffface->driver->root.library;
 
 
sfnt = (SFNT_Service)FT_Get_Module_Interface(
library, "sfnt" );
if ( !sfnt )
{
FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" ));
error = FT_THROW( Missing_Module );
goto Exit;
}
 
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
 
pshinter = (PSHinter_Service)FT_Get_Module_Interface(
library, "pshinter" );
 
FT_TRACE2(( "CFF driver\n" ));
 
/* create input stream from resource */
if ( FT_STREAM_SEEK( 0 ) )
goto Exit;
 
/* check whether we have a valid OpenType file */
error = sfnt->init_face( stream, face, face_index, num_params, params );
if ( !error )
{
if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */
{
FT_TRACE2(( " not an OpenType/CFF font\n" ));
error = FT_THROW( Unknown_File_Format );
goto Exit;
}
 
/* if we are performing a simple font format check, exit immediately */
if ( face_index < 0 )
return FT_Err_Ok;
 
sfnt_format = 1;
 
/* now, the font can be either an OpenType/CFF font, or an SVG CEF */
/* font; in the latter case it doesn't have a `head' table */
error = face->goto_table( face, TTAG_head, stream, 0 );
if ( !error )
{
pure_cff = 0;
 
/* load font directory */
error = sfnt->load_face( stream, face, face_index,
num_params, params );
if ( error )
goto Exit;
}
else
{
/* load the `cmap' table explicitly */
error = sfnt->load_cmap( face, stream );
if ( error )
goto Exit;
}
 
/* now load the CFF part of the file */
error = face->goto_table( face, TTAG_CFF, stream, 0 );
if ( error )
goto Exit;
}
else
{
/* rewind to start of file; we are going to load a pure-CFF font */
if ( FT_STREAM_SEEK( 0 ) )
goto Exit;
error = FT_Err_Ok;
}
 
/* now load and parse the CFF table in the file */
{
CFF_Font cff = NULL;
CFF_FontRecDict dict;
FT_Memory memory = cffface->memory;
FT_Int32 flags;
FT_UInt i;
 
 
if ( FT_NEW( cff ) )
goto Exit;
 
face->extra.data = cff;
error = cff_font_load( library, stream, face_index, cff, pure_cff );
if ( error )
goto Exit;
 
cff->pshinter = pshinter;
cff->psnames = psnames;
 
cffface->face_index = face_index;
 
/* Complement the root flags with some interesting information. */
/* Note that this is only necessary for pure CFF and CEF fonts; */
/* SFNT based fonts use the `name' table instead. */
 
cffface->num_glyphs = cff->num_glyphs;
 
dict = &cff->top_font.font_dict;
 
/* we need the `PSNames' module for CFF and CEF formats */
/* which aren't CID-keyed */
if ( dict->cid_registry == 0xFFFFU && !psnames )
{
FT_ERROR(( "cff_face_init:"
" cannot open CFF & CEF fonts\n"
" "
" without the `PSNames' module\n" ));
error = FT_THROW( Missing_Module );
goto Exit;
}
 
#ifdef FT_DEBUG_LEVEL_TRACE
{
FT_UInt idx;
FT_String* s;
 
 
FT_TRACE4(( "SIDs\n" ));
 
/* dump string index, including default strings for convenience */
for ( idx = 0; idx < cff->num_strings + 390; idx++ )
{
s = cff_index_get_sid_string( cff, idx );
if ( s )
FT_TRACE4((" %5d %s\n", idx, s ));
}
}
#endif /* FT_DEBUG_LEVEL_TRACE */
 
if ( !dict->has_font_matrix )
dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
 
/* Normalize the font matrix so that `matrix->xx' is 1; the */
/* scaling is done with `units_per_em' then (at this point, */
/* it already contains the scaling factor, but without */
/* normalization of the matrix). */
/* */
/* Note that the offsets must be expressed in integer font */
/* units. */
 
{
FT_Matrix* matrix = &dict->font_matrix;
FT_Vector* offset = &dict->font_offset;
FT_ULong* upm = &dict->units_per_em;
FT_Fixed temp = FT_ABS( matrix->yy );
 
 
if ( temp != 0x10000L )
{
*upm = FT_DivFix( *upm, temp );
 
matrix->xx = FT_DivFix( matrix->xx, temp );
matrix->yx = FT_DivFix( matrix->yx, temp );
matrix->xy = FT_DivFix( matrix->xy, temp );
matrix->yy = FT_DivFix( matrix->yy, temp );
offset->x = FT_DivFix( offset->x, temp );
offset->y = FT_DivFix( offset->y, temp );
}
 
offset->x >>= 16;
offset->y >>= 16;
}
 
for ( i = cff->num_subfonts; i > 0; i-- )
{
CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict;
CFF_FontRecDict top = &cff->top_font.font_dict;
 
FT_Matrix* matrix;
FT_Vector* offset;
FT_ULong* upm;
FT_Fixed temp;
 
 
if ( sub->has_font_matrix )
{
FT_Long scaling;
 
 
/* if we have a top-level matrix, */
/* concatenate the subfont matrix */
 
if ( top->has_font_matrix )
{
if ( top->units_per_em > 1 && sub->units_per_em > 1 )
scaling = FT_MIN( top->units_per_em, sub->units_per_em );
else
scaling = 1;
 
FT_Matrix_Multiply_Scaled( &top->font_matrix,
&sub->font_matrix,
scaling );
FT_Vector_Transform_Scaled( &sub->font_offset,
&top->font_matrix,
scaling );
 
sub->units_per_em = FT_MulDiv( sub->units_per_em,
top->units_per_em,
scaling );
}
}
else
{
sub->font_matrix = top->font_matrix;
sub->font_offset = top->font_offset;
 
sub->units_per_em = top->units_per_em;
}
 
matrix = &sub->font_matrix;
offset = &sub->font_offset;
upm = &sub->units_per_em;
temp = FT_ABS( matrix->yy );
 
if ( temp != 0x10000L )
{
*upm = FT_DivFix( *upm, temp );
 
matrix->xx = FT_DivFix( matrix->xx, temp );
matrix->yx = FT_DivFix( matrix->yx, temp );
matrix->xy = FT_DivFix( matrix->xy, temp );
matrix->yy = FT_DivFix( matrix->yy, temp );
offset->x = FT_DivFix( offset->x, temp );
offset->y = FT_DivFix( offset->y, temp );
}
 
offset->x >>= 16;
offset->y >>= 16;
}
 
if ( pure_cff )
{
char* style_name = NULL;
 
 
/* set up num_faces */
cffface->num_faces = cff->num_faces;
 
/* compute number of glyphs */
if ( dict->cid_registry != 0xFFFFU )
cffface->num_glyphs = cff->charset.max_cid + 1;
else
cffface->num_glyphs = cff->charstrings_index.count;
 
/* set global bbox, as well as EM size */
cffface->bbox.xMin = dict->font_bbox.xMin >> 16;
cffface->bbox.yMin = dict->font_bbox.yMin >> 16;
/* no `U' suffix here to 0xFFFF! */
cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16;
cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16;
 
cffface->units_per_EM = (FT_UShort)( dict->units_per_em );
 
cffface->ascender = (FT_Short)( cffface->bbox.yMax );
cffface->descender = (FT_Short)( cffface->bbox.yMin );
 
cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
if ( cffface->height < cffface->ascender - cffface->descender )
cffface->height = (FT_Short)( cffface->ascender - cffface->descender );
 
cffface->underline_position =
(FT_Short)( dict->underline_position >> 16 );
cffface->underline_thickness =
(FT_Short)( dict->underline_thickness >> 16 );
 
/* retrieve font family & style name */
cffface->family_name = cff_index_get_name( cff, face_index );
if ( cffface->family_name )
{
char* full = cff_index_get_sid_string( cff,
dict->full_name );
char* fullp = full;
char* family = cffface->family_name;
char* family_name = NULL;
 
 
remove_subset_prefix( cffface->family_name );
 
if ( dict->family_name )
{
family_name = cff_index_get_sid_string( cff,
dict->family_name );
if ( family_name )
family = family_name;
}
 
/* We try to extract the style name from the full name. */
/* We need to ignore spaces and dashes during the search. */
if ( full && family )
{
while ( *fullp )
{
/* skip common characters at the start of both strings */
if ( *fullp == *family )
{
family++;
fullp++;
continue;
}
 
/* ignore spaces and dashes in full name during comparison */
if ( *fullp == ' ' || *fullp == '-' )
{
fullp++;
continue;
}
 
/* ignore spaces and dashes in family name during comparison */
if ( *family == ' ' || *family == '-' )
{
family++;
continue;
}
 
if ( !*family && *fullp )
{
/* The full name begins with the same characters as the */
/* family name, with spaces and dashes removed. In this */
/* case, the remaining string in `fullp' will be used as */
/* the style name. */
style_name = cff_strcpy( memory, fullp );
 
/* remove the style part from the family name (if present) */
remove_style( cffface->family_name, style_name );
}
break;
}
}
}
else
{
char *cid_font_name =
cff_index_get_sid_string( cff,
dict->cid_font_name );
 
 
/* do we have a `/FontName' for a CID-keyed font? */
if ( cid_font_name )
cffface->family_name = cff_strcpy( memory, cid_font_name );
}
 
if ( style_name )
cffface->style_name = style_name;
else
/* assume "Regular" style if we don't know better */
cffface->style_name = cff_strcpy( memory, (char *)"Regular" );
 
/*******************************************************************/
/* */
/* Compute face flags. */
/* */
flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */
FT_FACE_FLAG_HORIZONTAL | /* horizontal data */
FT_FACE_FLAG_HINTER; /* has native hinter */
 
if ( sfnt_format )
flags |= FT_FACE_FLAG_SFNT;
 
/* fixed width font? */
if ( dict->is_fixed_pitch )
flags |= FT_FACE_FLAG_FIXED_WIDTH;
 
/* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
#if 0
/* kerning available? */
if ( face->kern_pairs )
flags |= FT_FACE_FLAG_KERNING;
#endif
 
cffface->face_flags = flags;
 
/*******************************************************************/
/* */
/* Compute style flags. */
/* */
flags = 0;
 
if ( dict->italic_angle )
flags |= FT_STYLE_FLAG_ITALIC;
 
{
char *weight = cff_index_get_sid_string( cff,
dict->weight );
 
 
if ( weight )
if ( !ft_strcmp( weight, "Bold" ) ||
!ft_strcmp( weight, "Black" ) )
flags |= FT_STYLE_FLAG_BOLD;
}
 
/* double check */
if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) ||
!ft_strncmp( cffface->style_name, "Black", 5 ) )
flags |= FT_STYLE_FLAG_BOLD;
 
cffface->style_flags = flags;
}
 
 
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
/* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */
/* has unset this flag because of the 3.0 `post' table. */
if ( dict->cid_registry == 0xFFFFU )
cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
#endif
 
if ( dict->cid_registry != 0xFFFFU && pure_cff )
cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;
 
 
/*******************************************************************/
/* */
/* Compute char maps. */
/* */
 
/* Try to synthesize a Unicode charmap if there is none available */
/* already. If an OpenType font contains a Unicode "cmap", we */
/* will use it, whatever be in the CFF part of the file. */
{
FT_CharMapRec cmaprec;
FT_CharMap cmap;
FT_UInt nn;
CFF_Encoding encoding = &cff->encoding;
 
 
for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )
{
cmap = cffface->charmaps[nn];
 
/* Windows Unicode? */
if ( cmap->platform_id == TT_PLATFORM_MICROSOFT &&
cmap->encoding_id == TT_MS_ID_UNICODE_CS )
goto Skip_Unicode;
 
/* Apple Unicode platform id? */
if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE )
goto Skip_Unicode; /* Apple Unicode */
}
 
/* since CID-keyed fonts don't contain glyph names, we can't */
/* construct a cmap */
if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
goto Exit;
 
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "cff_face_init: no Unicode cmap is found, "
"and too many subtables (%d) to add synthesized cmap\n",
nn ));
goto Exit;
}
#endif
 
/* we didn't find a Unicode charmap -- synthesize one */
cmaprec.face = cffface;
cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
cmaprec.encoding = FT_ENCODING_UNICODE;
 
nn = (FT_UInt)cffface->num_charmaps;
 
error = FT_CMap_New( &CFF_CMAP_UNICODE_CLASS_REC_GET, NULL,
&cmaprec, NULL );
if ( error &&
FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
goto Exit;
error = FT_Err_Ok;
 
/* if no Unicode charmap was previously selected, select this one */
if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )
cffface->charmap = cffface->charmaps[nn];
 
Skip_Unicode:
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( nn > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "cff_face_init: Unicode cmap is found, "
"but too many preceding subtables (%d) to access\n",
nn - 1 ));
goto Exit;
}
#endif
if ( encoding->count > 0 )
{
FT_CMap_Class clazz;
 
 
cmaprec.face = cffface;
cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */
 
if ( encoding->offset == 0 )
{
cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD;
clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET;
}
else if ( encoding->offset == 1 )
{
cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT;
clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET;
}
else
{
cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM;
clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET;
}
 
error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );
}
}
}
 
Exit:
return error;
}
 
 
FT_LOCAL_DEF( void )
cff_face_done( FT_Face cffface ) /* CFF_Face */
{
CFF_Face face = (CFF_Face)cffface;
FT_Memory memory;
SFNT_Service sfnt;
 
 
if ( !face )
return;
 
memory = cffface->memory;
sfnt = (SFNT_Service)face->sfnt;
 
if ( sfnt )
sfnt->done_face( face );
 
{
CFF_Font cff = (CFF_Font)face->extra.data;
 
 
if ( cff )
{
cff_font_done( cff );
FT_FREE( face->extra.data );
}
}
}
 
 
FT_LOCAL_DEF( FT_Error )
cff_driver_init( FT_Module module ) /* CFF_Driver */
{
CFF_Driver driver = (CFF_Driver)module;
 
 
/* set default property values */
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
#else
driver->hinting_engine = FT_CFF_HINTING_ADOBE;
#endif
driver->no_stem_darkening = FALSE;
 
return FT_Err_Ok;
}
 
 
FT_LOCAL_DEF( void )
cff_driver_done( FT_Module module ) /* CFF_Driver */
{
FT_UNUSED( module );
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffobjs.h
0,0 → 1,183
/***************************************************************************/
/* */
/* cffobjs.h */
/* */
/* OpenType objects manager (specification). */
/* */
/* Copyright 1996-2004, 2006-2008, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFFOBJS_H__
#define __CFFOBJS_H__
 
 
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include "cfftypes.h"
#include FT_INTERNAL_TRUETYPE_TYPES_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
 
FT_BEGIN_HEADER
 
 
/*************************************************************************/
/* */
/* <Type> */
/* CFF_Driver */
/* */
/* <Description> */
/* A handle to an OpenType driver object. */
/* */
typedef struct CFF_DriverRec_* CFF_Driver;
 
typedef TT_Face CFF_Face;
 
 
/*************************************************************************/
/* */
/* <Type> */
/* CFF_Size */
/* */
/* <Description> */
/* A handle to an OpenType size object. */
/* */
typedef struct CFF_SizeRec_
{
FT_SizeRec root;
FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */
 
} CFF_SizeRec, *CFF_Size;
 
 
/*************************************************************************/
/* */
/* <Type> */
/* CFF_GlyphSlot */
/* */
/* <Description> */
/* A handle to an OpenType glyph slot object. */
/* */
typedef struct CFF_GlyphSlotRec_
{
FT_GlyphSlotRec root;
 
FT_Bool hint;
FT_Bool scaled;
 
FT_Fixed x_scale;
FT_Fixed y_scale;
 
} CFF_GlyphSlotRec, *CFF_GlyphSlot;
 
 
/*************************************************************************/
/* */
/* <Type> */
/* CFF_Internal */
/* */
/* <Description> */
/* The interface to the `internal' field of `FT_Size'. */
/* */
typedef struct CFF_InternalRec_
{
PSH_Globals topfont;
PSH_Globals subfonts[CFF_MAX_CID_FONTS];
 
} CFF_InternalRec, *CFF_Internal;
 
 
/*************************************************************************/
/* */
/* Subglyph transformation record. */
/* */
typedef struct CFF_Transform_
{
FT_Fixed xx, xy; /* transformation matrix coefficients */
FT_Fixed yx, yy;
FT_F26Dot6 ox, oy; /* offsets */
 
} CFF_Transform;
 
 
/***********************************************************************/
/* */
/* CFF driver class. */
/* */
typedef struct CFF_DriverRec_
{
FT_DriverRec root;
 
FT_UInt hinting_engine;
FT_Bool no_stem_darkening;
 
} CFF_DriverRec;
 
 
FT_LOCAL( FT_Error )
cff_size_init( FT_Size size ); /* CFF_Size */
 
FT_LOCAL( void )
cff_size_done( FT_Size size ); /* CFF_Size */
 
FT_LOCAL( FT_Error )
cff_size_request( FT_Size size,
FT_Size_Request req );
 
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
FT_LOCAL( FT_Error )
cff_size_select( FT_Size size,
FT_ULong strike_index );
 
#endif
 
FT_LOCAL( void )
cff_slot_done( FT_GlyphSlot slot );
 
FT_LOCAL( FT_Error )
cff_slot_init( FT_GlyphSlot slot );
 
 
/*************************************************************************/
/* */
/* Face functions */
/* */
FT_LOCAL( FT_Error )
cff_face_init( FT_Stream stream,
FT_Face face, /* CFF_Face */
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params );
 
FT_LOCAL( void )
cff_face_done( FT_Face face ); /* CFF_Face */
 
 
/*************************************************************************/
/* */
/* Driver functions */
/* */
FT_LOCAL( FT_Error )
cff_driver_init( FT_Module module ); /* CFF_Driver */
 
FT_LOCAL( void )
cff_driver_done( FT_Module module ); /* CFF_Driver */
 
 
FT_END_HEADER
 
#endif /* __CFFOBJS_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffparse.c
0,0 → 1,1177
/***************************************************************************/
/* */
/* cffparse.c */
/* */
/* CFF token stream parser (body) */
/* */
/* Copyright 1996-2004, 2007-2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include "cffparse.h"
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_DEBUG_H
 
#include "cfferrs.h"
#include "cffpic.h"
 
 
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_cffparse
 
 
FT_LOCAL_DEF( void )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
FT_Library library)
{
FT_MEM_ZERO( parser, sizeof ( *parser ) );
 
parser->top = parser->stack;
parser->object_code = code;
parser->object = object;
parser->library = library;
}
 
 
/* read an integer */
static FT_Long
cff_parse_integer( FT_Byte* start,
FT_Byte* limit )
{
FT_Byte* p = start;
FT_Int v = *p++;
FT_Long val = 0;
 
 
if ( v == 28 )
{
if ( p + 2 > limit )
goto Bad;
 
val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] );
p += 2;
}
else if ( v == 29 )
{
if ( p + 4 > limit )
goto Bad;
 
val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) |
( (FT_ULong)p[1] << 16 ) |
( (FT_ULong)p[2] << 8 ) |
(FT_ULong)p[3] );
p += 4;
}
else if ( v < 247 )
{
val = v - 139;
}
else if ( v < 251 )
{
if ( p + 1 > limit )
goto Bad;
 
val = ( v - 247 ) * 256 + p[0] + 108;
p++;
}
else
{
if ( p + 1 > limit )
goto Bad;
 
val = -( v - 251 ) * 256 - p[0] - 108;
p++;
}
 
Exit:
return val;
 
Bad:
val = 0;
FT_TRACE4(( "!!!END OF DATA:!!!" ));
goto Exit;
}
 
 
static const FT_Long power_tens[] =
{
1L,
10L,
100L,
1000L,
10000L,
100000L,
1000000L,
10000000L,
100000000L,
1000000000L
};
 
 
/* read a real */
static FT_Fixed
cff_parse_real( FT_Byte* start,
FT_Byte* limit,
FT_Long power_ten,
FT_Long* scaling )
{
FT_Byte* p = start;
FT_UInt nib;
FT_UInt phase;
 
FT_Long result, number, exponent;
FT_Int sign = 0, exponent_sign = 0, have_overflow = 0;
FT_Long exponent_add, integer_length, fraction_length;
 
 
if ( scaling )
*scaling = 0;
 
result = 0;
 
number = 0;
exponent = 0;
 
exponent_add = 0;
integer_length = 0;
fraction_length = 0;
 
/* First of all, read the integer part. */
phase = 4;
 
for (;;)
{
/* If we entered this iteration with phase == 4, we need to */
/* read a new byte. This also skips past the initial 0x1E. */
if ( phase )
{
p++;
 
/* Make sure we don't read past the end. */
if ( p >= limit )
goto Bad;
}
 
/* Get the nibble. */
nib = ( p[0] >> phase ) & 0xF;
phase = 4 - phase;
 
if ( nib == 0xE )
sign = 1;
else if ( nib > 9 )
break;
else
{
/* Increase exponent if we can't add the digit. */
if ( number >= 0xCCCCCCCL )
exponent_add++;
/* Skip leading zeros. */
else if ( nib || number )
{
integer_length++;
number = number * 10 + nib;
}
}
}
 
/* Read fraction part, if any. */
if ( nib == 0xa )
for (;;)
{
/* If we entered this iteration with phase == 4, we need */
/* to read a new byte. */
if ( phase )
{
p++;
 
/* Make sure we don't read past the end. */
if ( p >= limit )
goto Bad;
}
 
/* Get the nibble. */
nib = ( p[0] >> phase ) & 0xF;
phase = 4 - phase;
if ( nib >= 10 )
break;
 
/* Skip leading zeros if possible. */
if ( !nib && !number )
exponent_add--;
/* Only add digit if we don't overflow. */
else if ( number < 0xCCCCCCCL && fraction_length < 9 )
{
fraction_length++;
number = number * 10 + nib;
}
}
 
/* Read exponent, if any. */
if ( nib == 12 )
{
exponent_sign = 1;
nib = 11;
}
 
if ( nib == 11 )
{
for (;;)
{
/* If we entered this iteration with phase == 4, */
/* we need to read a new byte. */
if ( phase )
{
p++;
 
/* Make sure we don't read past the end. */
if ( p >= limit )
goto Bad;
}
 
/* Get the nibble. */
nib = ( p[0] >> phase ) & 0xF;
phase = 4 - phase;
if ( nib >= 10 )
break;
 
/* Arbitrarily limit exponent. */
if ( exponent > 1000 )
have_overflow = 1;
else
exponent = exponent * 10 + nib;
}
 
if ( exponent_sign )
exponent = -exponent;
}
 
if ( !number )
goto Exit;
 
if ( have_overflow )
{
if ( exponent_sign )
goto Underflow;
else
goto Overflow;
}
 
/* We don't check `power_ten' and `exponent_add'. */
exponent += power_ten + exponent_add;
 
if ( scaling )
{
/* Only use `fraction_length'. */
fraction_length += integer_length;
exponent += integer_length;
 
if ( fraction_length <= 5 )
{
if ( number > 0x7FFFL )
{
result = FT_DivFix( number, 10 );
*scaling = exponent - fraction_length + 1;
}
else
{
if ( exponent > 0 )
{
FT_Long new_fraction_length, shift;
 
 
/* Make `scaling' as small as possible. */
new_fraction_length = FT_MIN( exponent, 5 );
shift = new_fraction_length - fraction_length;
 
if ( shift > 0 )
{
exponent -= new_fraction_length;
number *= power_tens[shift];
if ( number > 0x7FFFL )
{
number /= 10;
exponent += 1;
}
}
else
exponent -= fraction_length;
}
else
exponent -= fraction_length;
 
result = (FT_Long)( (FT_ULong)number << 16 );
*scaling = exponent;
}
}
else
{
if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL )
{
result = FT_DivFix( number, power_tens[fraction_length - 4] );
*scaling = exponent - 4;
}
else
{
result = FT_DivFix( number, power_tens[fraction_length - 5] );
*scaling = exponent - 5;
}
}
}
else
{
integer_length += exponent;
fraction_length -= exponent;
 
if ( integer_length > 5 )
goto Overflow;
if ( integer_length < -5 )
goto Underflow;
 
/* Remove non-significant digits. */
if ( integer_length < 0 )
{
number /= power_tens[-integer_length];
fraction_length += integer_length;
}
 
/* this can only happen if exponent was non-zero */
if ( fraction_length == 10 )
{
number /= 10;
fraction_length -= 1;
}
 
/* Convert into 16.16 format. */
if ( fraction_length > 0 )
{
if ( ( number / power_tens[fraction_length] ) > 0x7FFFL )
goto Exit;
 
result = FT_DivFix( number, power_tens[fraction_length] );
}
else
{
number *= power_tens[-fraction_length];
 
if ( number > 0x7FFFL )
goto Overflow;
 
result = (FT_Long)( (FT_ULong)number << 16 );
}
}
 
Exit:
if ( sign )
result = -result;
 
return result;
 
Overflow:
result = 0x7FFFFFFFL;
FT_TRACE4(( "!!!OVERFLOW:!!!" ));
goto Exit;
 
Underflow:
result = 0;
FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
goto Exit;
 
Bad:
result = 0;
FT_TRACE4(( "!!!END OF DATA:!!!" ));
goto Exit;
}
 
 
/* read a number, either integer or real */
static FT_Long
cff_parse_num( FT_Byte** d )
{
return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 )
: cff_parse_integer( d[0], d[1] );
}
 
 
/* read a floating point number, either integer or real */
static FT_Fixed
do_fixed( FT_Byte** d,
FT_Long scaling )
{
if ( **d == 30 )
return cff_parse_real( d[0], d[1], scaling, NULL );
else
{
FT_Long val = cff_parse_integer( d[0], d[1] );
 
 
if ( scaling )
val *= power_tens[scaling];
 
if ( val > 0x7FFF )
{
val = 0x7FFFFFFFL;
goto Overflow;
}
else if ( val < -0x7FFF )
{
val = -0x7FFFFFFFL;
goto Overflow;
}
 
return (FT_Long)( (FT_ULong)val << 16 );
 
Overflow:
FT_TRACE4(( "!!!OVERFLOW:!!!" ));
return val;
}
}
 
 
/* read a floating point number, either integer or real */
static FT_Fixed
cff_parse_fixed( FT_Byte** d )
{
return do_fixed( d, 0 );
}
 
 
/* read a floating point number, either integer or real, */
/* but return `10^scaling' times the number read in */
static FT_Fixed
cff_parse_fixed_scaled( FT_Byte** d,
FT_Long scaling )
{
return do_fixed( d, scaling );
}
 
 
/* read a floating point number, either integer or real, */
/* and return it as precise as possible -- `scaling' returns */
/* the scaling factor (as a power of 10) */
static FT_Fixed
cff_parse_fixed_dynamic( FT_Byte** d,
FT_Long* scaling )
{
FT_ASSERT( scaling );
 
if ( **d == 30 )
return cff_parse_real( d[0], d[1], 0, scaling );
else
{
FT_Long number;
FT_Int integer_length;
 
 
number = cff_parse_integer( d[0], d[1] );
 
if ( number > 0x7FFFL )
{
for ( integer_length = 5; integer_length < 10; integer_length++ )
if ( number < power_tens[integer_length] )
break;
 
if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL )
{
*scaling = integer_length - 4;
return FT_DivFix( number, power_tens[integer_length - 4] );
}
else
{
*scaling = integer_length - 5;
return FT_DivFix( number, power_tens[integer_length - 5] );
}
}
else
{
*scaling = 0;
return (FT_Long)( (FT_ULong)number << 16 );
}
}
}
 
 
static FT_Error
cff_parse_font_matrix( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_Matrix* matrix = &dict->font_matrix;
FT_Vector* offset = &dict->font_offset;
FT_ULong* upm = &dict->units_per_em;
FT_Byte** data = parser->stack;
FT_Error error = FT_ERR( Stack_Underflow );
 
 
if ( parser->top >= parser->stack + 6 )
{
FT_Long scaling;
 
 
error = FT_Err_Ok;
 
dict->has_font_matrix = TRUE;
 
/* We expect a well-formed font matrix, this is, the matrix elements */
/* `xx' and `yy' are of approximately the same magnitude. To avoid */
/* loss of precision, we use the magnitude of element `xx' to scale */
/* all other elements. The scaling factor is then contained in the */
/* `units_per_em' value. */
 
matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );
 
scaling = -scaling;
 
if ( scaling < 0 || scaling > 9 )
{
/* Return default matrix in case of unlikely values. */
 
FT_TRACE1(( "cff_parse_font_matrix:"
" strange scaling value for xx element (%d),\n"
" "
" using default matrix\n", scaling ));
 
matrix->xx = 0x10000L;
matrix->yx = 0;
matrix->xy = 0;
matrix->yy = 0x10000L;
offset->x = 0;
offset->y = 0;
*upm = 1;
 
goto Exit;
}
 
matrix->yx = cff_parse_fixed_scaled( data++, scaling );
matrix->xy = cff_parse_fixed_scaled( data++, scaling );
matrix->yy = cff_parse_fixed_scaled( data++, scaling );
offset->x = cff_parse_fixed_scaled( data++, scaling );
offset->y = cff_parse_fixed_scaled( data, scaling );
 
*upm = power_tens[scaling];
 
FT_TRACE4(( " [%f %f %f %f %f %f]\n",
(double)matrix->xx / *upm / 65536,
(double)matrix->xy / *upm / 65536,
(double)matrix->yx / *upm / 65536,
(double)matrix->yy / *upm / 65536,
(double)offset->x / *upm / 65536,
(double)offset->y / *upm / 65536 ));
}
 
Exit:
return error;
}
 
 
static FT_Error
cff_parse_font_bbox( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_BBox* bbox = &dict->font_bbox;
FT_Byte** data = parser->stack;
FT_Error error;
 
 
error = FT_ERR( Stack_Underflow );
 
if ( parser->top >= parser->stack + 4 )
{
bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );
error = FT_Err_Ok;
 
FT_TRACE4(( " [%d %d %d %d]\n",
bbox->xMin / 65536,
bbox->yMin / 65536,
bbox->xMax / 65536,
bbox->yMax / 65536 ));
}
 
return error;
}
 
 
static FT_Error
cff_parse_private_dict( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_Byte** data = parser->stack;
FT_Error error;
 
 
error = FT_ERR( Stack_Underflow );
 
if ( parser->top >= parser->stack + 2 )
{
dict->private_size = cff_parse_num( data++ );
dict->private_offset = cff_parse_num( data );
FT_TRACE4(( " %lu %lu\n",
dict->private_size, dict->private_offset ));
 
error = FT_Err_Ok;
}
 
return error;
}
 
 
static FT_Error
cff_parse_cid_ros( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_Byte** data = parser->stack;
FT_Error error;
 
 
error = FT_ERR( Stack_Underflow );
 
if ( parser->top >= parser->stack + 3 )
{
dict->cid_registry = (FT_UInt)cff_parse_num( data++ );
dict->cid_ordering = (FT_UInt)cff_parse_num( data++ );
if ( **data == 30 )
FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
dict->cid_supplement = cff_parse_num( data );
if ( dict->cid_supplement < 0 )
FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
dict->cid_supplement ));
error = FT_Err_Ok;
 
FT_TRACE4(( " %d %d %d\n",
dict->cid_registry,
dict->cid_ordering,
dict->cid_supplement ));
}
 
return error;
}
 
 
#define CFF_FIELD_NUM( code, name, id ) \
CFF_FIELD( code, name, id, cff_kind_num )
#define CFF_FIELD_FIXED( code, name, id ) \
CFF_FIELD( code, name, id, cff_kind_fixed )
#define CFF_FIELD_FIXED_1000( code, name, id ) \
CFF_FIELD( code, name, id, cff_kind_fixed_thousand )
#define CFF_FIELD_STRING( code, name, id ) \
CFF_FIELD( code, name, id, cff_kind_string )
#define CFF_FIELD_BOOL( code, name, id ) \
CFF_FIELD( code, name, id, cff_kind_bool )
 
#define CFFCODE_TOPDICT 0x1000
#define CFFCODE_PRIVATE 0x2000
 
 
#ifndef FT_CONFIG_OPTION_PIC
 
 
#undef CFF_FIELD
#undef CFF_FIELD_DELTA
 
 
#ifndef FT_DEBUG_LEVEL_TRACE
 
 
#define CFF_FIELD_CALLBACK( code, name, id ) \
{ \
cff_kind_callback, \
code | CFFCODE, \
0, 0, \
cff_parse_ ## name, \
0, 0 \
},
 
#define CFF_FIELD( code, name, id, kind ) \
{ \
kind, \
code | CFFCODE, \
FT_FIELD_OFFSET( name ), \
FT_FIELD_SIZE( name ), \
0, 0, 0 \
},
 
#define CFF_FIELD_DELTA( code, name, max, id ) \
{ \
cff_kind_delta, \
code | CFFCODE, \
FT_FIELD_OFFSET( name ), \
FT_FIELD_SIZE_DELTA( name ), \
0, \
max, \
FT_FIELD_OFFSET( num_ ## name ) \
},
 
static const CFF_Field_Handler cff_field_handlers[] =
{
 
#include "cfftoken.h"
 
{ 0, 0, 0, 0, 0, 0, 0 }
};
 
 
#else /* FT_DEBUG_LEVEL_TRACE */
 
 
 
#define CFF_FIELD_CALLBACK( code, name, id ) \
{ \
cff_kind_callback, \
code | CFFCODE, \
0, 0, \
cff_parse_ ## name, \
0, 0, \
id \
},
 
#define CFF_FIELD( code, name, id, kind ) \
{ \
kind, \
code | CFFCODE, \
FT_FIELD_OFFSET( name ), \
FT_FIELD_SIZE( name ), \
0, 0, 0, \
id \
},
 
#define CFF_FIELD_DELTA( code, name, max, id ) \
{ \
cff_kind_delta, \
code | CFFCODE, \
FT_FIELD_OFFSET( name ), \
FT_FIELD_SIZE_DELTA( name ), \
0, \
max, \
FT_FIELD_OFFSET( num_ ## name ), \
id \
},
 
static const CFF_Field_Handler cff_field_handlers[] =
{
 
#include "cfftoken.h"
 
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
 
 
#endif /* FT_DEBUG_LEVEL_TRACE */
 
 
#else /* FT_CONFIG_OPTION_PIC */
 
 
void
FT_Destroy_Class_cff_field_handlers( FT_Library library,
CFF_Field_Handler* clazz )
{
FT_Memory memory = library->memory;
 
 
if ( clazz )
FT_FREE( clazz );
}
 
 
FT_Error
FT_Create_Class_cff_field_handlers( FT_Library library,
CFF_Field_Handler** output_class )
{
CFF_Field_Handler* clazz = NULL;
FT_Error error;
FT_Memory memory = library->memory;
 
int i = 0;
 
 
#undef CFF_FIELD
#define CFF_FIELD( code, name, id, kind ) i++;
#undef CFF_FIELD_DELTA
#define CFF_FIELD_DELTA( code, name, max, id ) i++;
#undef CFF_FIELD_CALLBACK
#define CFF_FIELD_CALLBACK( code, name, id ) i++;
 
#include "cfftoken.h"
 
i++; /* { 0, 0, 0, 0, 0, 0, 0 } */
 
if ( FT_ALLOC( clazz, sizeof ( CFF_Field_Handler ) * i ) )
return error;
 
i = 0;
 
 
#ifndef FT_DEBUG_LEVEL_TRACE
 
 
#undef CFF_FIELD_CALLBACK
#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \
clazz[i].kind = cff_kind_callback; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = 0; \
clazz[i].size = 0; \
clazz[i].reader = cff_parse_ ## name_; \
clazz[i].array_max = 0; \
clazz[i].count_offset = 0; \
i++;
 
#undef CFF_FIELD
#define CFF_FIELD( code_, name_, id_, kind_ ) \
clazz[i].kind = kind_; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
clazz[i].size = FT_FIELD_SIZE( name_ ); \
clazz[i].reader = 0; \
clazz[i].array_max = 0; \
clazz[i].count_offset = 0; \
i++; \
 
#undef CFF_FIELD_DELTA
#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \
clazz[i].kind = cff_kind_delta; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \
clazz[i].reader = 0; \
clazz[i].array_max = max_; \
clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
i++;
 
#include "cfftoken.h"
 
clazz[i].kind = 0;
clazz[i].code = 0;
clazz[i].offset = 0;
clazz[i].size = 0;
clazz[i].reader = 0;
clazz[i].array_max = 0;
clazz[i].count_offset = 0;
 
 
#else /* FT_DEBUG_LEVEL_TRACE */
 
 
#undef CFF_FIELD_CALLBACK
#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \
clazz[i].kind = cff_kind_callback; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = 0; \
clazz[i].size = 0; \
clazz[i].reader = cff_parse_ ## name_; \
clazz[i].array_max = 0; \
clazz[i].count_offset = 0; \
clazz[i].id = id_; \
i++;
 
#undef CFF_FIELD
#define CFF_FIELD( code_, name_, id_, kind_ ) \
clazz[i].kind = kind_; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
clazz[i].size = FT_FIELD_SIZE( name_ ); \
clazz[i].reader = 0; \
clazz[i].array_max = 0; \
clazz[i].count_offset = 0; \
clazz[i].id = id_; \
i++; \
 
#undef CFF_FIELD_DELTA
#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \
clazz[i].kind = cff_kind_delta; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \
clazz[i].reader = 0; \
clazz[i].array_max = max_; \
clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
clazz[i].id = id_; \
i++;
 
#include "cfftoken.h"
 
clazz[i].kind = 0;
clazz[i].code = 0;
clazz[i].offset = 0;
clazz[i].size = 0;
clazz[i].reader = 0;
clazz[i].array_max = 0;
clazz[i].count_offset = 0;
clazz[i].id = 0;
 
 
#endif /* FT_DEBUG_LEVEL_TRACE */
 
 
*output_class = clazz;
 
return FT_Err_Ok;
}
 
 
#endif /* FT_CONFIG_OPTION_PIC */
 
 
FT_LOCAL_DEF( FT_Error )
cff_parser_run( CFF_Parser parser,
FT_Byte* start,
FT_Byte* limit )
{
FT_Byte* p = start;
FT_Error error = FT_Err_Ok;
FT_Library library = parser->library;
FT_UNUSED( library );
 
 
parser->top = parser->stack;
parser->start = start;
parser->limit = limit;
parser->cursor = start;
 
while ( p < limit )
{
FT_UInt v = *p;
 
 
if ( v >= 27 && v != 31 )
{
/* it's a number; we will push its position on the stack */
if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
goto Stack_Overflow;
 
*parser->top ++ = p;
 
/* now, skip it */
if ( v == 30 )
{
/* skip real number */
p++;
for (;;)
{
/* An unterminated floating point number at the */
/* end of a dictionary is invalid but harmless. */
if ( p >= limit )
goto Exit;
v = p[0] >> 4;
if ( v == 15 )
break;
v = p[0] & 0xF;
if ( v == 15 )
break;
p++;
}
}
else if ( v == 28 )
p += 2;
else if ( v == 29 )
p += 4;
else if ( v > 246 )
p += 1;
}
else
{
/* This is not a number, hence it's an operator. Compute its code */
/* and look for it in our current list. */
 
FT_UInt code;
FT_UInt num_args = (FT_UInt)
( parser->top - parser->stack );
const CFF_Field_Handler* field;
 
 
*parser->top = p;
code = v;
if ( v == 12 )
{
/* two byte operator */
p++;
if ( p >= limit )
goto Syntax_Error;
 
code = 0x100 | p[0];
}
code = code | parser->object_code;
 
for ( field = CFF_FIELD_HANDLERS_GET; field->kind; field++ )
{
if ( field->code == (FT_Int)code )
{
/* we found our field's handler; read it */
FT_Long val;
FT_Byte* q = (FT_Byte*)parser->object + field->offset;
 
 
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE4(( " %s", field->id ));
#endif
 
/* check that we have enough arguments -- except for */
/* delta encoded arrays, which can be empty */
if ( field->kind != cff_kind_delta && num_args < 1 )
goto Stack_Underflow;
 
switch ( field->kind )
{
case cff_kind_bool:
case cff_kind_string:
case cff_kind_num:
val = cff_parse_num( parser->stack );
goto Store_Number;
 
case cff_kind_fixed:
val = cff_parse_fixed( parser->stack );
goto Store_Number;
 
case cff_kind_fixed_thousand:
val = cff_parse_fixed_scaled( parser->stack, 3 );
 
Store_Number:
switch ( field->size )
{
case (8 / FT_CHAR_BIT):
*(FT_Byte*)q = (FT_Byte)val;
break;
 
case (16 / FT_CHAR_BIT):
*(FT_Short*)q = (FT_Short)val;
break;
 
case (32 / FT_CHAR_BIT):
*(FT_Int32*)q = (FT_Int)val;
break;
 
default: /* for 64-bit systems */
*(FT_Long*)q = val;
}
 
#ifdef FT_DEBUG_LEVEL_TRACE
switch ( field->kind )
{
case cff_kind_bool:
FT_TRACE4(( " %s\n", val ? "true" : "false" ));
break;
 
case cff_kind_string:
FT_TRACE4(( " %ld (SID)\n", val ));
break;
 
case cff_kind_num:
FT_TRACE4(( " %ld\n", val ));
break;
 
case cff_kind_fixed:
FT_TRACE4(( " %f\n", (double)val / 65536 ));
break;
 
case cff_kind_fixed_thousand:
FT_TRACE4(( " %f\n", (double)val / 65536 / 1000 ));
 
default:
; /* never reached */
}
#endif
 
break;
 
case cff_kind_delta:
{
FT_Byte* qcount = (FT_Byte*)parser->object +
field->count_offset;
 
FT_Byte** data = parser->stack;
 
 
if ( num_args > field->array_max )
num_args = field->array_max;
 
FT_TRACE4(( " [" ));
 
/* store count */
*qcount = (FT_Byte)num_args;
 
val = 0;
while ( num_args > 0 )
{
val += cff_parse_num( data++ );
switch ( field->size )
{
case (8 / FT_CHAR_BIT):
*(FT_Byte*)q = (FT_Byte)val;
break;
 
case (16 / FT_CHAR_BIT):
*(FT_Short*)q = (FT_Short)val;
break;
 
case (32 / FT_CHAR_BIT):
*(FT_Int32*)q = (FT_Int)val;
break;
 
default: /* for 64-bit systems */
*(FT_Long*)q = val;
}
 
FT_TRACE4(( " %ld", val ));
 
q += field->size;
num_args--;
}
 
FT_TRACE4(( "]\n" ));
}
break;
 
default: /* callback */
error = field->reader( parser );
if ( error )
goto Exit;
}
goto Found;
}
}
 
/* this is an unknown operator, or it is unsupported; */
/* we will ignore it for now. */
 
Found:
/* clear stack */
parser->top = parser->stack;
}
p++;
}
 
Exit:
return error;
 
Stack_Overflow:
error = FT_THROW( Invalid_Argument );
goto Exit;
 
Stack_Underflow:
error = FT_THROW( Invalid_Argument );
goto Exit;
 
Syntax_Error:
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffparse.h
0,0 → 1,106
/***************************************************************************/
/* */
/* cffparse.h */
/* */
/* CFF token stream parser (specification) */
/* */
/* Copyright 1996-2003, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFF_PARSE_H__
#define __CFF_PARSE_H__
 
 
#include <ft2build.h>
#include "cfftypes.h"
#include FT_INTERNAL_OBJECTS_H
 
 
FT_BEGIN_HEADER
 
 
#define CFF_MAX_STACK_DEPTH 96
 
#define CFF_CODE_TOPDICT 0x1000
#define CFF_CODE_PRIVATE 0x2000
 
 
typedef struct CFF_ParserRec_
{
FT_Library library;
FT_Byte* start;
FT_Byte* limit;
FT_Byte* cursor;
 
FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1];
FT_Byte** top;
 
FT_UInt object_code;
void* object;
 
} CFF_ParserRec, *CFF_Parser;
 
 
FT_LOCAL( void )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
FT_Library library);
 
FT_LOCAL( FT_Error )
cff_parser_run( CFF_Parser parser,
FT_Byte* start,
FT_Byte* limit );
 
 
enum
{
cff_kind_none = 0,
cff_kind_num,
cff_kind_fixed,
cff_kind_fixed_thousand,
cff_kind_string,
cff_kind_bool,
cff_kind_delta,
cff_kind_callback,
 
cff_kind_max /* do not remove */
};
 
 
/* now generate handlers for the most simple fields */
typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser );
 
typedef struct CFF_Field_Handler_
{
int kind;
int code;
FT_UInt offset;
FT_Byte size;
CFF_Field_Reader reader;
FT_UInt array_max;
FT_UInt count_offset;
 
#ifdef FT_DEBUG_LEVEL_TRACE
const char* id;
#endif
 
} CFF_Field_Handler;
 
 
FT_END_HEADER
 
 
#endif /* __CFF_PARSE_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffpic.c
0,0 → 1,138
/***************************************************************************/
/* */
/* cffpic.c */
/* */
/* The FreeType position independent code services for cff module. */
/* */
/* Copyright 2009, 2010, 2012, 2013 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "cffcmap.h"
#include "cffpic.h"
#include "cfferrs.h"
 
 
#ifdef FT_CONFIG_OPTION_PIC
 
/* forward declaration of PIC init functions from cffdrivr.c */
FT_Error
FT_Create_Class_cff_services( FT_Library library,
FT_ServiceDescRec** output_class );
void
FT_Destroy_Class_cff_services( FT_Library library,
FT_ServiceDescRec* clazz );
void
FT_Init_Class_cff_service_ps_info( FT_Library library,
FT_Service_PsInfoRec* clazz );
void
FT_Init_Class_cff_service_glyph_dict( FT_Library library,
FT_Service_GlyphDictRec* clazz );
void
FT_Init_Class_cff_service_ps_name( FT_Library library,
FT_Service_PsFontNameRec* clazz );
void
FT_Init_Class_cff_service_get_cmap_info( FT_Library library,
FT_Service_TTCMapsRec* clazz );
void
FT_Init_Class_cff_service_cid_info( FT_Library library,
FT_Service_CIDRec* clazz );
 
/* forward declaration of PIC init functions from cffparse.c */
FT_Error
FT_Create_Class_cff_field_handlers( FT_Library library,
CFF_Field_Handler** output_class );
void
FT_Destroy_Class_cff_field_handlers( FT_Library library,
CFF_Field_Handler* clazz );
 
 
void
cff_driver_class_pic_free( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Memory memory = library->memory;
 
 
if ( pic_container->cff )
{
CffModulePIC* container = (CffModulePIC*)pic_container->cff;
 
 
if ( container->cff_services )
FT_Destroy_Class_cff_services( library,
container->cff_services );
container->cff_services = NULL;
if ( container->cff_field_handlers )
FT_Destroy_Class_cff_field_handlers(
library, container->cff_field_handlers );
container->cff_field_handlers = NULL;
FT_FREE( container );
pic_container->cff = NULL;
}
}
 
 
FT_Error
cff_driver_class_pic_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Error error = FT_Err_Ok;
CffModulePIC* container = NULL;
FT_Memory memory = library->memory;
 
 
/* allocate pointer, clear and set global container pointer */
if ( FT_ALLOC ( container, sizeof ( *container ) ) )
return error;
FT_MEM_SET( container, 0, sizeof ( *container ) );
pic_container->cff = container;
 
/* initialize pointer table - */
/* this is how the module usually expects this data */
error = FT_Create_Class_cff_services( library,
&container->cff_services );
if ( error )
goto Exit;
 
error = FT_Create_Class_cff_field_handlers(
library, &container->cff_field_handlers );
if ( error )
goto Exit;
 
FT_Init_Class_cff_service_ps_info(
library, &container->cff_service_ps_info );
FT_Init_Class_cff_service_glyph_dict(
library, &container->cff_service_glyph_dict );
FT_Init_Class_cff_service_ps_name(
library, &container->cff_service_ps_name );
FT_Init_Class_cff_service_get_cmap_info(
library, &container->cff_service_get_cmap_info );
FT_Init_Class_cff_service_cid_info(
library, &container->cff_service_cid_info );
FT_Init_Class_cff_cmap_encoding_class_rec(
library, &container->cff_cmap_encoding_class_rec );
FT_Init_Class_cff_cmap_unicode_class_rec(
library, &container->cff_cmap_unicode_class_rec );
 
Exit:
if ( error )
cff_driver_class_pic_free( library );
return error;
}
 
#endif /* FT_CONFIG_OPTION_PIC */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cffpic.h
0,0 → 1,108
/***************************************************************************/
/* */
/* cffpic.h */
/* */
/* The FreeType position independent code services for cff module. */
/* */
/* Copyright 2009, 2012, 2013 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFFPIC_H__
#define __CFFPIC_H__
 
 
FT_BEGIN_HEADER
 
#include FT_INTERNAL_PIC_H
 
 
#ifndef FT_CONFIG_OPTION_PIC
 
#define CFF_SERVICE_PS_INFO_GET cff_service_ps_info
#define CFF_SERVICE_GLYPH_DICT_GET cff_service_glyph_dict
#define CFF_SERVICE_PS_NAME_GET cff_service_ps_name
#define CFF_SERVICE_GET_CMAP_INFO_GET cff_service_get_cmap_info
#define CFF_SERVICE_CID_INFO_GET cff_service_cid_info
#define CFF_SERVICE_PROPERTIES_GET cff_service_properties
#define CFF_SERVICES_GET cff_services
#define CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec
#define CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec
#define CFF_FIELD_HANDLERS_GET cff_field_handlers
 
#else /* FT_CONFIG_OPTION_PIC */
 
#include FT_SERVICE_GLYPH_DICT_H
#include "cffparse.h"
#include FT_SERVICE_POSTSCRIPT_INFO_H
#include FT_SERVICE_POSTSCRIPT_NAME_H
#include FT_SERVICE_TT_CMAP_H
#include FT_SERVICE_CID_H
#include FT_SERVICE_PROPERTIES_H
 
 
typedef struct CffModulePIC_
{
FT_ServiceDescRec* cff_services;
CFF_Field_Handler* cff_field_handlers;
FT_Service_PsInfoRec cff_service_ps_info;
FT_Service_GlyphDictRec cff_service_glyph_dict;
FT_Service_PsFontNameRec cff_service_ps_name;
FT_Service_TTCMapsRec cff_service_get_cmap_info;
FT_Service_CIDRec cff_service_cid_info;
FT_Service_PropertiesRec cff_service_properties;
FT_CMap_ClassRec cff_cmap_encoding_class_rec;
FT_CMap_ClassRec cff_cmap_unicode_class_rec;
 
} CffModulePIC;
 
 
#define GET_PIC( lib ) \
( (CffModulePIC*)( (lib)->pic_container.cff ) )
 
#define CFF_SERVICE_PS_INFO_GET \
( GET_PIC( library )->cff_service_ps_info )
#define CFF_SERVICE_GLYPH_DICT_GET \
( GET_PIC( library )->cff_service_glyph_dict )
#define CFF_SERVICE_PS_NAME_GET \
( GET_PIC( library )->cff_service_ps_name )
#define CFF_SERVICE_GET_CMAP_INFO_GET \
( GET_PIC( library )->cff_service_get_cmap_info )
#define CFF_SERVICE_CID_INFO_GET \
( GET_PIC( library )->cff_service_cid_info )
#define CFF_SERVICE_PROPERTIES_GET \
( GET_PIC( library )->cff_service_properties )
#define CFF_SERVICES_GET \
( GET_PIC( library )->cff_services )
#define CFF_CMAP_ENCODING_CLASS_REC_GET \
( GET_PIC( library )->cff_cmap_encoding_class_rec )
#define CFF_CMAP_UNICODE_CLASS_REC_GET \
( GET_PIC( library )->cff_cmap_unicode_class_rec )
#define CFF_FIELD_HANDLERS_GET \
( GET_PIC( library )->cff_field_handlers )
 
/* see cffpic.c for the implementation */
void
cff_driver_class_pic_free( FT_Library library );
 
FT_Error
cff_driver_class_pic_init( FT_Library library );
 
#endif /* FT_CONFIG_OPTION_PIC */
 
/* */
 
FT_END_HEADER
 
#endif /* __CFFPIC_H__ */
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cfftoken.h
0,0 → 1,97
/***************************************************************************/
/* */
/* cfftoken.h */
/* */
/* CFF token definitions (specification only). */
/* */
/* Copyright 1996-2003, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_FontRecDictRec
 
#undef CFFCODE
#define CFFCODE CFFCODE_TOPDICT
 
CFF_FIELD_STRING ( 0, version, "Version" )
CFF_FIELD_STRING ( 1, notice, "Notice" )
CFF_FIELD_STRING ( 0x100, copyright, "Copyright" )
CFF_FIELD_STRING ( 2, full_name, "FullName" )
CFF_FIELD_STRING ( 3, family_name, "FamilyName" )
CFF_FIELD_STRING ( 4, weight, "Weight" )
CFF_FIELD_BOOL ( 0x101, is_fixed_pitch, "isFixedPitch" )
CFF_FIELD_FIXED ( 0x102, italic_angle, "ItalicAngle" )
CFF_FIELD_FIXED ( 0x103, underline_position, "UnderlinePosition" )
CFF_FIELD_FIXED ( 0x104, underline_thickness, "UnderlineThickness" )
CFF_FIELD_NUM ( 0x105, paint_type, "PaintType" )
CFF_FIELD_NUM ( 0x106, charstring_type, "CharstringType" )
CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" )
CFF_FIELD_NUM ( 13, unique_id, "UniqueID" )
CFF_FIELD_CALLBACK( 5, font_bbox, "FontBBox" )
CFF_FIELD_NUM ( 0x108, stroke_width, "StrokeWidth" )
CFF_FIELD_NUM ( 15, charset_offset, "charset" )
CFF_FIELD_NUM ( 16, encoding_offset, "Encoding" )
CFF_FIELD_NUM ( 17, charstrings_offset, "CharStrings" )
CFF_FIELD_CALLBACK( 18, private_dict, "Private" )
CFF_FIELD_NUM ( 0x114, synthetic_base, "SyntheticBase" )
CFF_FIELD_STRING ( 0x115, embedded_postscript, "PostScript" )
 
#if 0
CFF_FIELD_STRING ( 0x116, base_font_name, "BaseFontName" )
CFF_FIELD_DELTA ( 0x117, base_font_blend, 16, "BaseFontBlend" )
CFF_FIELD_CALLBACK( 0x118, multiple_master, "MultipleMaster" )
CFF_FIELD_CALLBACK( 0x119, blend_axis_types, "BlendAxisTypes" )
#endif
 
CFF_FIELD_CALLBACK( 0x11E, cid_ros, "ROS" )
CFF_FIELD_NUM ( 0x11F, cid_font_version, "CIDFontVersion" )
CFF_FIELD_NUM ( 0x120, cid_font_revision, "CIDFontRevision" )
CFF_FIELD_NUM ( 0x121, cid_font_type, "CIDFontType" )
CFF_FIELD_NUM ( 0x122, cid_count, "CIDCount" )
CFF_FIELD_NUM ( 0x123, cid_uid_base, "UIDBase" )
CFF_FIELD_NUM ( 0x124, cid_fd_array_offset, "FDArray" )
CFF_FIELD_NUM ( 0x125, cid_fd_select_offset, "FDSelect" )
CFF_FIELD_STRING ( 0x126, cid_font_name, "FontName" )
 
#if 0
CFF_FIELD_NUM ( 0x127, chameleon, "Chameleon" )
#endif
 
 
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_PrivateRec
#undef CFFCODE
#define CFFCODE CFFCODE_PRIVATE
 
CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" )
CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" )
CFF_FIELD_DELTA ( 8, family_blues, 14, "FamilyBlues" )
CFF_FIELD_DELTA ( 9, family_other_blues, 10, "FamilyOtherBlues" )
CFF_FIELD_FIXED_1000( 0x109, blue_scale, "BlueScale" )
CFF_FIELD_NUM ( 0x10A, blue_shift, "BlueShift" )
CFF_FIELD_NUM ( 0x10B, blue_fuzz, "BlueFuzz" )
CFF_FIELD_NUM ( 10, standard_width, "StdHW" )
CFF_FIELD_NUM ( 11, standard_height, "StdVW" )
CFF_FIELD_DELTA ( 0x10C, snap_widths, 13, "StemSnapH" )
CFF_FIELD_DELTA ( 0x10D, snap_heights, 13, "StemSnapV" )
CFF_FIELD_BOOL ( 0x10E, force_bold, "ForceBold" )
CFF_FIELD_FIXED ( 0x10F, force_bold_threshold, "ForceBoldThreshold" )
CFF_FIELD_NUM ( 0x110, lenIV, "lenIV" )
CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" )
CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" )
CFF_FIELD_NUM ( 0x113, initial_random_seed, "initialRandomSeed" )
CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" )
CFF_FIELD_NUM ( 20, default_width, "defaultWidthX" )
CFF_FIELD_NUM ( 21, nominal_width, "nominalWidthX" )
 
 
/* END */
/contrib/sdk/sources/freetype/src/cff/cfftypes.h
0,0 → 1,284
/***************************************************************************/
/* */
/* cfftypes.h */
/* */
/* Basic OpenType/CFF type definitions and interface (specification */
/* only). */
/* */
/* Copyright 1996-2003, 2006-2008, 2010-2011, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#ifndef __CFFTYPES_H__
#define __CFFTYPES_H__
 
 
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_H
#include FT_INTERNAL_SERVICE_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
 
FT_BEGIN_HEADER
 
 
/*************************************************************************/
/* */
/* <Struct> */
/* CFF_IndexRec */
/* */
/* <Description> */
/* A structure used to model a CFF Index table. */
/* */
/* <Fields> */
/* stream :: The source input stream. */
/* */
/* start :: The position of the first index byte in the */
/* input stream. */
/* */
/* count :: The number of elements in the index. */
/* */
/* off_size :: The size in bytes of object offsets in index. */
/* */
/* data_offset :: The position of first data byte in the index's */
/* bytes. */
/* */
/* data_size :: The size of the data table in this index. */
/* */
/* offsets :: A table of element offsets in the index. Must be */
/* loaded explicitly. */
/* */
/* bytes :: If the index is loaded in memory, its bytes. */
/* */
typedef struct CFF_IndexRec_
{
FT_Stream stream;
FT_ULong start;
FT_UInt count;
FT_Byte off_size;
FT_ULong data_offset;
FT_ULong data_size;
 
FT_ULong* offsets;
FT_Byte* bytes;
 
} CFF_IndexRec, *CFF_Index;
 
 
typedef struct CFF_EncodingRec_
{
FT_UInt format;
FT_ULong offset;
 
FT_UInt count;
FT_UShort sids [256]; /* avoid dynamic allocations */
FT_UShort codes[256];
 
} CFF_EncodingRec, *CFF_Encoding;
 
 
typedef struct CFF_CharsetRec_
{
 
FT_UInt format;
FT_ULong offset;
 
FT_UShort* sids;
FT_UShort* cids; /* the inverse mapping of `sids'; only needed */
/* for CID-keyed fonts */
FT_UInt max_cid;
FT_UInt num_glyphs;
 
} CFF_CharsetRec, *CFF_Charset;
 
 
typedef struct CFF_FontRecDictRec_
{
FT_UInt version;
FT_UInt notice;
FT_UInt copyright;
FT_UInt full_name;
FT_UInt family_name;
FT_UInt weight;
FT_Bool is_fixed_pitch;
FT_Fixed italic_angle;
FT_Fixed underline_position;
FT_Fixed underline_thickness;
FT_Int paint_type;
FT_Int charstring_type;
FT_Matrix font_matrix;
FT_Bool has_font_matrix;
FT_ULong units_per_em; /* temporarily used as scaling value also */
FT_Vector font_offset;
FT_ULong unique_id;
FT_BBox font_bbox;
FT_Pos stroke_width;
FT_ULong charset_offset;
FT_ULong encoding_offset;
FT_ULong charstrings_offset;
FT_ULong private_offset;
FT_ULong private_size;
FT_Long synthetic_base;
FT_UInt embedded_postscript;
 
/* these should only be used for the top-level font dictionary */
FT_UInt cid_registry;
FT_UInt cid_ordering;
FT_Long cid_supplement;
 
FT_Long cid_font_version;
FT_Long cid_font_revision;
FT_Long cid_font_type;
FT_ULong cid_count;
FT_ULong cid_uid_base;
FT_ULong cid_fd_array_offset;
FT_ULong cid_fd_select_offset;
FT_UInt cid_font_name;
 
} CFF_FontRecDictRec, *CFF_FontRecDict;
 
 
typedef struct CFF_PrivateRec_
{
FT_Byte num_blue_values;
FT_Byte num_other_blues;
FT_Byte num_family_blues;
FT_Byte num_family_other_blues;
 
FT_Pos blue_values[14];
FT_Pos other_blues[10];
FT_Pos family_blues[14];
FT_Pos family_other_blues[10];
 
FT_Fixed blue_scale;
FT_Pos blue_shift;
FT_Pos blue_fuzz;
FT_Pos standard_width;
FT_Pos standard_height;
 
FT_Byte num_snap_widths;
FT_Byte num_snap_heights;
FT_Pos snap_widths[13];
FT_Pos snap_heights[13];
FT_Bool force_bold;
FT_Fixed force_bold_threshold;
FT_Int lenIV;
FT_Int language_group;
FT_Fixed expansion_factor;
FT_Long initial_random_seed;
FT_ULong local_subrs_offset;
FT_Pos default_width;
FT_Pos nominal_width;
 
} CFF_PrivateRec, *CFF_Private;
 
 
typedef struct CFF_FDSelectRec_
{
FT_Byte format;
FT_UInt range_count;
 
/* that's the table, taken from the file `as is' */
FT_Byte* data;
FT_UInt data_size;
 
/* small cache for format 3 only */
FT_UInt cache_first;
FT_UInt cache_count;
FT_Byte cache_fd;
 
} CFF_FDSelectRec, *CFF_FDSelect;
 
 
/* A SubFont packs a font dict and a private dict together. They are */
/* needed to support CID-keyed CFF fonts. */
typedef struct CFF_SubFontRec_
{
CFF_FontRecDictRec font_dict;
CFF_PrivateRec private_dict;
 
CFF_IndexRec local_subrs_index;
FT_Byte** local_subrs; /* array of pointers into Local Subrs INDEX data */
 
} CFF_SubFontRec, *CFF_SubFont;
 
 
#define CFF_MAX_CID_FONTS 256
 
 
typedef struct CFF_FontRec_
{
FT_Stream stream;
FT_Memory memory;
FT_UInt num_faces;
FT_UInt num_glyphs;
 
FT_Byte version_major;
FT_Byte version_minor;
FT_Byte header_size;
FT_Byte absolute_offsize;
 
 
CFF_IndexRec name_index;
CFF_IndexRec top_dict_index;
CFF_IndexRec global_subrs_index;
 
CFF_EncodingRec encoding;
CFF_CharsetRec charset;
 
CFF_IndexRec charstrings_index;
CFF_IndexRec font_dict_index;
CFF_IndexRec private_index;
CFF_IndexRec local_subrs_index;
 
FT_String* font_name;
 
/* array of pointers into Global Subrs INDEX data */
FT_Byte** global_subrs;
 
/* array of pointers into String INDEX data stored at string_pool */
FT_UInt num_strings;
FT_Byte** strings;
FT_Byte* string_pool;
 
CFF_SubFontRec top_font;
FT_UInt num_subfonts;
CFF_SubFont subfonts[CFF_MAX_CID_FONTS];
 
CFF_FDSelectRec fd_select;
 
/* interface to PostScript hinter */
PSHinter_Service pshinter;
 
/* interface to Postscript Names service */
FT_Service_PsCMaps psnames;
 
/* since version 2.3.0 */
PS_FontInfoRec* font_info; /* font info dictionary */
 
/* since version 2.3.6 */
FT_String* registry;
FT_String* ordering;
 
/* since version 2.4.12 */
FT_Generic cf2_instance;
 
} CFF_FontRec, *CFF_Font;
 
 
FT_END_HEADER
 
#endif /* __CFFTYPES_H__ */
 
 
/* END */