From fba3b6d1979c1d1ad0d56d46fc2d787f111c07fb Mon Sep 17 00:00:00 2001 From: marha Date: Thu, 26 Jun 2014 09:46:14 +0200 Subject: Updated to freetype 2.5.3 --- freetype/src/cff/cf2blues.c | 13 +-- freetype/src/cff/cf2font.c | 182 ++++++++++++++++++++++++++++++---------- freetype/src/cff/cf2font.h | 2 + freetype/src/cff/cf2ft.c | 48 ++++++++--- freetype/src/cff/cf2hints.c | 200 ++++++++++++++++++++++++++++++++++---------- freetype/src/cff/cf2hints.h | 4 +- freetype/src/cff/cffdrivr.c | 61 ++++++++++++-- freetype/src/cff/cffgload.c | 6 +- freetype/src/cff/cffload.c | 25 ++++-- freetype/src/cff/cffobjs.c | 13 ++- freetype/src/cff/cffobjs.h | 2 + freetype/src/cff/cffparse.c | 6 +- 12 files changed, 429 insertions(+), 133 deletions(-) (limited to 'freetype/src/cff') diff --git a/freetype/src/cff/cf2blues.c b/freetype/src/cff/cf2blues.c index 5b348398a..250f89e0d 100644 --- a/freetype/src/cff/cf2blues.c +++ b/freetype/src/cff/cf2blues.c @@ -4,7 +4,7 @@ /* */ /* Adobe's code for handling Blue Zones (body). */ /* */ -/* Copyright 2009-2013 Adobe Systems Incorporated. */ +/* Copyright 2009-2014 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 */ @@ -86,11 +86,13 @@ size_t i; CF2_Fixed emBoxBottom, emBoxTop; +#if 0 CF2_Int unitsPerEm = font->unitsPerEm; if ( unitsPerEm == 0 ) unitsPerEm = 1000; +#endif FT_ZERO( blues ); blues->scale = font->innerTransform.d; @@ -406,11 +408,10 @@ /* 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 ) ) ); + blues->boost = cf2_floatToFixed( .6 ) - + FT_MulDiv( cf2_floatToFixed ( .6 ), + blues->scale, + blues->blueScale ); if ( blues->boost > 0x7FFF ) { /* boost must remain less than 0.5, or baseline could go negative */ diff --git a/freetype/src/cff/cf2font.c b/freetype/src/cff/cf2font.c index 479d9125d..6e99dc2f0 100644 --- a/freetype/src/cff/cf2font.c +++ b/freetype/src/cff/cf2font.c @@ -4,7 +4,7 @@ /* */ /* Adobe's code for font instances (body). */ /* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ +/* Copyright 2007-2014 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 */ @@ -51,10 +51,59 @@ CF2_Fixed stemWidth, CF2_Fixed* darkenAmount, CF2_Fixed boldenAmount, - FT_Bool stemDarkened ) + FT_Bool stemDarkened, + FT_Int* darkenParams ) { + /* + * Total darkening amount is computed in 1000 unit character space + * using the modified 5 part curve as Adobe's Avalon rasterizer. + * The darkening amount is smaller for thicker stems. + * It becomes zero when the stem is thicker than 2.333 pixels. + * + * By default, we use + * + * darkenAmount = 0.4 pixels if scaledStem <= 0.5 pixels, + * darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels, + * darkenAmount = 0 pixel if scaledStem >= 2.333 pixels, + * + * and piecewise linear in-between: + * + * + * darkening + * ^ + * | + * | (x1,y1) + * |--------+ + * | \ + * | \ + * | \ (x3,y3) + * | +----------+ + * | (x2,y2) \ + * | \ + * | \ + * | +----------------- + * | (x4,y4) + * +---------------------------------------------> stem + * thickness + * + * + * This corresponds to the following values for the + * `darkening-parameters' property: + * + * (x1, y1) = (500, 400) + * (x2, y2) = (1000, 275) + * (x3, y3) = (1667, 275) + * (x4, y4) = (2333, 0) + * + */ + /* Internal calculations are done in units per thousand for */ - /* convenience. */ + /* convenience. The x axis is scaled stem width in */ + /* thousandths of a pixel. That is, 1000 is 1 pixel. */ + /* The y axis is darkening amount in thousandths of a pixel.*/ + /* In the code, below, dividing by ppem and */ + /* adjusting for emRatio converts darkenAmount to character */ + /* space (font units). */ CF2_Fixed stemWidthPer1000, scaledStem; @@ -69,6 +118,16 @@ if ( stemDarkened ) { + FT_Int x1 = darkenParams[0]; + FT_Int y1 = darkenParams[1]; + FT_Int x2 = darkenParams[2]; + FT_Int y2 = darkenParams[3]; + FT_Int x3 = darkenParams[4]; + FT_Int y3 = darkenParams[5]; + FT_Int x4 = darkenParams[6]; + FT_Int y4 = darkenParams[7]; + + /* convert from true character space to 1000 unit character space; */ /* add synthetic emboldening effect */ @@ -81,7 +140,7 @@ stemWidthPer1000 <= ( stemWidth + boldenAmount ) ) { stemWidthPer1000 = 0; /* to pacify compiler */ - scaledStem = cf2_intToFixed( 2333 ); + scaledStem = cf2_intToFixed( x4 ); } else { @@ -89,39 +148,70 @@ if ( ppem > CF2_FIXED_ONE && scaledStem <= stemWidthPer1000 ) - scaledStem = cf2_intToFixed( 2333 ); + scaledStem = cf2_intToFixed( x4 ); + } + + /* now apply the darkening parameters */ + + if ( scaledStem < cf2_intToFixed( x1 ) ) + *darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem ); + + else if ( scaledStem < cf2_intToFixed( x2 ) ) + { + FT_Int xdelta = x2 - x1; + FT_Int ydelta = y2 - y1; + FT_Int x = stemWidthPer1000 - + FT_DivFix( cf2_intToFixed( x1 ), ppem ); + + + if ( !xdelta ) + goto Try_x3; + + *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) + + FT_DivFix( cf2_intToFixed( y1 ), ppem ); + } + + else if ( scaledStem < cf2_intToFixed( x3 ) ) + { + Try_x3: + { + FT_Int xdelta = x3 - x2; + FT_Int ydelta = y3 - y2; + FT_Int x = stemWidthPer1000 - + FT_DivFix( cf2_intToFixed( x2 ), ppem ); + + + if ( !xdelta ) + goto Try_x4; + + *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) + + FT_DivFix( cf2_intToFixed( y2 ), ppem ); + } + } + + else if ( scaledStem < cf2_intToFixed( x4 ) ) + { + Try_x4: + { + FT_Int xdelta = x4 - x3; + FT_Int ydelta = y4 - y3; + FT_Int x = stemWidthPer1000 - + FT_DivFix( cf2_intToFixed( x3 ), ppem ); + + + if ( !xdelta ) + goto Use_y4; + + *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) + + FT_DivFix( cf2_intToFixed( y3 ), ppem ); + } } - /* - * 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 ) ); + else + { + Use_y4: + *darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem ); + } /* use half the amount on each side and convert back to true */ /* character space */ @@ -143,13 +233,14 @@ /* pointer to parsed font object */ CFF_Decoder* decoder = font->decoder; - FT_Bool needExtraSetup; + FT_Bool needExtraSetup = FALSE; /* character space units */ CF2_Fixed boldenX = font->syntheticEmboldeningAmountX; CF2_Fixed boldenY = font->syntheticEmboldeningAmountY; - CF2_Fixed ppem; + CFF_SubFont subFont; + CF2_Fixed ppem; /* clear previous error */ @@ -157,8 +248,12 @@ /* if a CID fontDict has changed, we need to recompute some cached */ /* data */ - needExtraSetup = - (FT_Bool)( font->lastSubfont != cf2_getSubfont( decoder ) ); + subFont = cf2_getSubfont( decoder ); + if ( font->lastSubfont != subFont ) + { + font->lastSubfont = subFont; + needExtraSetup = TRUE; + } /* if ppem has changed, we need to recompute some cached data */ /* note: because of CID font matrix concatenation, ppem and transform */ @@ -268,7 +363,8 @@ font->stdVW, &font->darkenX, boldenX, - FALSE ); + FALSE, + font->darkenParams ); } else cf2_computeDarkening( emRatio, @@ -276,7 +372,8 @@ font->stdVW, &font->darkenX, 0, - font->stemDarkened ); + font->stemDarkened, + font->darkenParams ); #if 0 /* since hstem is measured in the y-direction, we use the `d' member */ @@ -303,7 +400,8 @@ font->stdHW, &font->darkenY, boldenY, - font->stemDarkened ); + font->stemDarkened, + font->darkenParams ); if ( font->darkenX != 0 || font->darkenY != 0 ) font->darkened = TRUE; diff --git a/freetype/src/cff/cf2font.h b/freetype/src/cff/cf2font.h index f9dd1bbd4..d8860ce8e 100644 --- a/freetype/src/cff/cf2font.h +++ b/freetype/src/cff/cf2font.h @@ -85,6 +85,8 @@ FT_BEGIN_HEADER /* i.e. darkenX != 0 || darkenY != 0 */ FT_Bool stemDarkened; + FT_Int darkenParams[8]; /* 1000 unit character space */ + /* 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 */ diff --git a/freetype/src/cff/cf2ft.c b/freetype/src/cff/cf2ft.c index c09a0244a..cb8d31c53 100644 --- a/freetype/src/cff/cf2ft.c +++ b/freetype/src/cff/cf2ft.c @@ -4,7 +4,7 @@ /* */ /* FreeType Glue Component to Adobe's Interpreter (body). */ /* */ -/* Copyright 2013 Adobe Systems Incorporated. */ +/* Copyright 2013-2014 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 */ @@ -61,7 +61,9 @@ FT_ASSERT( unitsPerEm > 0 ); - FT_ASSERT( transform->a > 0 && transform->d > 0 ); + if ( transform->a <= 0 || transform->d <= 0 ) + return FT_THROW( Invalid_Size_Handle ); + FT_ASSERT( transform->b == 0 && transform->c == 0 ); FT_ASSERT( transform->tx == 0 && transform->ty == 0 ); @@ -236,10 +238,8 @@ 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 ) ); + *x_scale = ( decoder->builder.glyph->x_scale + 32 ) / 64; + *y_scale = ( decoder->builder.glyph->y_scale + 32 ) / 64; } else { @@ -344,13 +344,25 @@ if ( scaled && !driver->no_stem_darkening ) font->renderingFlags |= CF2_FlagsDarkened; + font->darkenParams[0] = driver->darken_params[0]; + font->darkenParams[1] = driver->darken_params[1]; + font->darkenParams[2] = driver->darken_params[2]; + font->darkenParams[3] = driver->darken_params[3]; + font->darkenParams[4] = driver->darken_params[4]; + font->darkenParams[5] = driver->darken_params[5]; + font->darkenParams[6] = driver->darken_params[6]; + font->darkenParams[7] = driver->darken_params[7]; + /* 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; + if ( scaled ) + { + error2 = cf2_checkTransform( &transform, font->unitsPerEm ); + if ( error2 ) + return error2; + } error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth ); if ( error2 ) @@ -380,8 +392,16 @@ FT_ASSERT( decoder && decoder->builder.face && decoder->builder.face->root.size ); - FT_ASSERT( decoder->builder.face->root.size->metrics.y_ppem ); + /* + * Note that `y_ppem' can be zero if there wasn't a call to + * `FT_Set_Char_Size' or something similar. However, this isn't a + * problem since we come to this place in the code only if + * FT_LOAD_NO_SCALE is set (the other case gets caught by + * `cf2_checkTransform'). The ppem value is needed to compute the stem + * darkening, which is disabled for getting the unscaled outline. + * + */ return cf2_intToFixed( decoder->builder.face->root.size->metrics.y_ppem ); } @@ -499,7 +519,7 @@ CF2_UInt idx, CF2_Buffer buf ) { - FT_ASSERT( decoder && decoder->globals ); + FT_ASSERT( decoder ); FT_ZERO( buf ); @@ -507,6 +527,8 @@ if ( idx >= decoder->num_globals ) return TRUE; /* error */ + FT_ASSERT( decoder->globals ); + buf->start = buf->ptr = decoder->globals[idx]; buf->end = decoder->globals[idx + 1]; @@ -572,7 +594,7 @@ CF2_UInt idx, CF2_Buffer buf ) { - FT_ASSERT( decoder && decoder->locals ); + FT_ASSERT( decoder ); FT_ZERO( buf ); @@ -580,6 +602,8 @@ if ( idx >= decoder->num_locals ) return TRUE; /* error */ + FT_ASSERT( decoder->locals ); + buf->start = buf->ptr = decoder->locals[idx]; buf->end = decoder->locals[idx + 1]; diff --git a/freetype/src/cff/cf2hints.c b/freetype/src/cff/cf2hints.c index 96bd49f18..5853d7758 100644 --- a/freetype/src/cff/cf2hints.c +++ b/freetype/src/cff/cf2hints.c @@ -4,7 +4,7 @@ /* */ /* Adobe's code for handling CFF hints (body). */ /* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ +/* Copyright 2007-2014 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 */ @@ -596,22 +596,31 @@ indexInsert = 0; for ( ; indexInsert < hintmap->count; indexInsert++ ) { - if ( hintmap->edge[indexInsert].csCoord > firstHintEdge->csCoord ) + 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. + * Discard any hints that overlap in character space. Most often, this + * is while building the initial map, where captured hints from all + * zones are combined. Define overlap to include hints that `touch' + * (overlap zero). Hiragino Sans/Gothic fonts have numerous hints that + * touch. Some fonts have non-ideographic glyphs that overlap our + * synthetic hints. + * + * Overlap also occurs when darkening stem hints that are close. * */ if ( indexInsert < hintmap->count ) { - /* we are inserting before an existing edge: */ + /* we are inserting before an existing edge: */ + /* verify that an existing edge is not the same */ + if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord ) + return; /* ignore overlapping stem hint */ + /* verify that a new pair does not straddle the next edge */ - if ( isPair && - hintmap->edge[indexInsert].csCoord < secondHintEdge->csCoord ) + if ( isPair && + hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord ) return; /* ignore overlapping stem hint */ /* verify that we are not inserting between paired edges */ @@ -645,8 +654,27 @@ firstHintEdge->csCoord ); } - /* discard any hints that overlap in device space; this can occur */ - /* because locked hints have been moved to align with blue zones */ + /* + * Discard any hints that overlap in device space; this can occur + * because locked hints have been moved to align with blue zones. + * + * TODO: Although we might correct this later during adjustment, we + * don't currently have a way to delete a conflicting hint once it has + * been inserted. See v2.030 MinionPro-Regular, 12 ppem darkened, + * initial hint map for second path, glyph 945 (the perispomeni (tilde) + * in U+1F6E, Greek omega with psili and perispomeni). Darkening is + * 25. Pair 667,747 initially conflicts in design space with top edge + * 660. This is because 667 maps to 7.87, and the top edge was + * captured by a zone at 8.0. The pair is later successfully inserted + * in a zone without the top edge. In this zone it is adjusted to 8.0, + * and no longer conflicts with the top edge in design space. This + * means it can be included in yet a later zone which does have the top + * edge hint. This produces a small mismatch between the first and + * last points of this path, even though the hint masks are the same. + * The density map difference is tiny (1/256). + * + */ + if ( indexInsert > 0 ) { /* we are inserting after an existing edge */ @@ -753,6 +781,8 @@ cf2_hintmask_setAll( hintMask, cf2_arrstack_size( hStemHintArray ) + cf2_arrstack_size( vStemHintArray ) ); + if ( !cf2_hintmask_isValid( hintMask ) ) + return; /* too many stem hints */ } /* begin by clearing the map */ @@ -1035,6 +1065,7 @@ glyphpath->moveIsPending = TRUE; glyphpath->pathIsOpen = FALSE; + glyphpath->pathIsClosing = FALSE; glyphpath->elemIsQueued = FALSE; } @@ -1175,12 +1206,16 @@ /* * 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. + * cached element may be adjusted to an intersection point or we may + * synthesize a connecting line to the current element. If we are + * closing a subpath, we may also generate a connecting line to the start + * point. + * + * This is where Character Space (CS) is converted to Device Space (DS) + * using a hint map. 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: @@ -1250,16 +1285,32 @@ params.op = CF2_PathOpLineTo; /* note: pt2 and pt3 are unused */ - cf2_glyphpath_hintPoint( glyphpath, - hintmap, - ¶ms.pt1, - glyphpath->prevElemP1.x, - glyphpath->prevElemP1.y ); - glyphpath->callbacks->lineTo( glyphpath->callbacks, ¶ms ); + if ( close ) + { + /* use first hint map if closing */ + cf2_glyphpath_hintPoint( glyphpath, + &glyphpath->firstHintMap, + ¶ms.pt1, + glyphpath->prevElemP1.x, + glyphpath->prevElemP1.y ); + } + else + { + cf2_glyphpath_hintPoint( glyphpath, + hintmap, + ¶ms.pt1, + glyphpath->prevElemP1.x, + glyphpath->prevElemP1.y ); + } - glyphpath->currentDS = params.pt1; + /* output only non-zero length lines */ + if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y ) + { + glyphpath->callbacks->lineTo( glyphpath->callbacks, ¶ms ); + glyphpath->currentDS = params.pt1; + } break; case CF2_PathOpCubeTo: @@ -1296,11 +1347,24 @@ /* note: at the end of a subpath, we might do both, so use `nextP0' */ /* before we change it, below */ - cf2_glyphpath_hintPoint( glyphpath, - hintmap, - ¶ms.pt1, - nextP0->x, - nextP0->y ); + if ( close ) + { + /* if we are closing the subpath, then nextP0 is in the first */ + /* hint zone */ + cf2_glyphpath_hintPoint( glyphpath, + &glyphpath->firstHintMap, + ¶ms.pt1, + nextP0->x, + nextP0->y ); + } + else + { + cf2_glyphpath_hintPoint( glyphpath, + hintmap, + ¶ms.pt1, + nextP0->x, + nextP0->y ); + } if ( params.pt1.x != glyphpath->currentDS.x || params.pt1.y != glyphpath->currentDS.y ) @@ -1511,6 +1575,16 @@ } + /* + * The functions cf2_glyphpath_{moveTo,lineTo,curveTo,closeOpenPath} are + * called by the interpreter with Character Space (CS) coordinates. Each + * path element is placed into a queue of length one to await the + * calculation of the following element. At that time, the darkening + * offset of the following element is known and joins can be computed, + * including possible modification of this element, before mapping to + * Device Space (DS) and passing it on to the outline consumer. + * + */ FT_LOCAL_DEF( void ) cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath, CF2_Fixed x, @@ -1548,10 +1622,46 @@ { CF2_Fixed xOffset, yOffset; FT_Vector P0, P1; + FT_Bool newHintMap; + + /* + * New hints will be applied after cf2_glyphpath_pushPrevElem has run. + * In case this is a synthesized closing line, any new hints should be + * delayed until this path is closed (`cf2_hintmask_isNew' will be + * called again before the next line or curve). + */ + + /* true if new hint map not on close */ + newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) && + !glyphpath->pathIsClosing; + + /* + * Zero-length lines may occur in the charstring. Because we cannot + * compute darkening offsets or intersections from zero-length lines, + * it is best to remove them and avoid artifacts. However, zero-length + * lines in CS at the start of a new hint map can generate non-zero + * lines in DS due to hint substitution. We detect a change in hint + * map here and pass those zero-length lines along. + */ + /* + * Note: Find explicitly closed paths here with a conditional + * breakpoint using + * + * !gp->pathIsClosing && gp->start.x == x && gp->start.y == y + * + */ - /* can't compute offset of zero length line, so ignore them */ - if ( glyphpath->currentCS.x == x && glyphpath->currentCS.y == y ) + if ( glyphpath->currentCS.x == x && + glyphpath->currentCS.y == y && + !newHintMap ) + /* + * Ignore zero-length lines in CS where the hint map is the same + * because the line in DS will also be zero length. + * + * Ignore zero-length lines when we synthesize a closing line because + * the close will be handled in cf2_glyphPath_pushPrevElem. + */ return; cf2_glyphpath_computeOffset( glyphpath, @@ -1597,7 +1707,7 @@ glyphpath->prevElemP1 = P1; /* update current map */ - if ( cf2_hintmask_isNew( glyphpath->hintMask ) ) + if ( newHintMap ) cf2_hintmap_build( &glyphpath->hintMap, glyphpath->hStemHintArray, glyphpath->vStemHintArray, @@ -1703,29 +1813,29 @@ { if ( glyphpath->pathIsOpen ) { - FT_ASSERT( cf2_hintmap_isValid( &glyphpath->firstHintMap ) ); + /* + * A closing line in Character Space line is always generated below + * with `cf2_glyphPath_lineTo'. It may be ignored later if it turns + * out to be zero length in Device Space. + */ + glyphpath->pathIsClosing = TRUE; - /* 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 ); + /* empty the final element from the queue and close the path */ + if ( glyphpath->elemIsQueued ) + cf2_glyphpath_pushPrevElem( glyphpath, + &glyphpath->hintMap, + &glyphpath->offsetStart0, + glyphpath->offsetStart1, + TRUE ); /* reset state machine */ glyphpath->moveIsPending = TRUE; glyphpath->pathIsOpen = FALSE; + glyphpath->pathIsClosing = FALSE; glyphpath->elemIsQueued = FALSE; } } diff --git a/freetype/src/cff/cf2hints.h b/freetype/src/cff/cf2hints.h index c4fa922a3..f25d91bf8 100644 --- a/freetype/src/cff/cf2hints.h +++ b/freetype/src/cff/cf2hints.h @@ -204,6 +204,7 @@ FT_BEGIN_HEADER #endif FT_Bool pathIsOpen; /* true after MoveTo */ + FT_Bool pathIsClosing; /* true when synthesizing closepath line */ FT_Bool darken; /* true if stem darkening */ FT_Bool moveIsPending; /* true between MoveTo and offset MoveTo */ @@ -229,7 +230,8 @@ FT_BEGIN_HEADER FT_Vector currentCS; /* current point, device space */ FT_Vector currentDS; - FT_Vector start; /* start point of subpath */ + /* start point of subpath, character space */ + FT_Vector start; /* the following members constitute the `queue' of one element */ FT_Bool elemIsQueued; diff --git a/freetype/src/cff/cffdrivr.c b/freetype/src/cff/cffdrivr.c index c8ca96ba4..dde7d4488 100644 --- a/freetype/src/cff/cffdrivr.c +++ b/freetype/src/cff/cffdrivr.c @@ -164,6 +164,8 @@ if ( !slot ) return FT_THROW( Invalid_Slot_Handle ); + FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); + /* check whether we want a scaled outline or bitmap */ if ( !size ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; @@ -586,7 +588,38 @@ CFF_Driver driver = (CFF_Driver)module; - if ( !ft_strcmp( property_name, "hinting-engine" ) ) + if ( !ft_strcmp( property_name, "darkening-parameters" ) ) + { + FT_Int* darken_params = (FT_Int*)value; + + FT_Int x1 = darken_params[0]; + FT_Int y1 = darken_params[1]; + FT_Int x2 = darken_params[2]; + FT_Int y2 = darken_params[3]; + FT_Int x3 = darken_params[4]; + FT_Int y3 = darken_params[5]; + FT_Int x4 = darken_params[6]; + FT_Int y4 = darken_params[7]; + + + if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 || + y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 || + x1 > x2 || x2 > x3 || x3 > x4 || + y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 ) + return FT_THROW( Invalid_Argument ); + + driver->darken_params[0] = x1; + driver->darken_params[1] = y1; + driver->darken_params[2] = x2; + driver->darken_params[3] = y2; + driver->darken_params[4] = x3; + driver->darken_params[5] = y3; + driver->darken_params[6] = x4; + driver->darken_params[7] = y4; + + return error; + } + else if ( !ft_strcmp( property_name, "hinting-engine" ) ) { FT_UInt* hinting_engine = (FT_UInt*)value; @@ -624,13 +657,28 @@ 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, "darkening-parameters" ) ) + { + FT_Int* darken_params = driver->darken_params; + FT_Int* val = (FT_Int*)value; + + + val[0] = darken_params[0]; + val[1] = darken_params[1]; + val[2] = darken_params[2]; + val[3] = darken_params[3]; + val[4] = darken_params[4]; + val[5] = darken_params[5]; + val[6] = darken_params[6]; + val[7] = darken_params[7]; - if ( !ft_strcmp( property_name, "hinting-engine" ) ) + return error; + } + else if ( !ft_strcmp( property_name, "hinting-engine" ) ) { - FT_UInt* val = (FT_UInt*)value; + FT_UInt hinting_engine = driver->hinting_engine; + FT_UInt* val = (FT_UInt*)value; *val = hinting_engine; @@ -639,7 +687,8 @@ } else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) { - FT_Bool* val = (FT_Bool*)value; + FT_Bool no_stem_darkening = driver->no_stem_darkening; + FT_Bool* val = (FT_Bool*)value; *val = no_stem_darkening; diff --git a/freetype/src/cff/cffgload.c b/freetype/src/cff/cffgload.c index 6a8494fa9..c8e9f9124 100644 --- a/freetype/src/cff/cffgload.c +++ b/freetype/src/cff/cffgload.c @@ -434,7 +434,7 @@ goto Exit; } - FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); + FT_TRACE3(( " in subfont %d:\n", fd_index )); sub = cff->subfonts[fd_index]; @@ -447,10 +447,6 @@ 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; diff --git a/freetype/src/cff/cffload.c b/freetype/src/cff/cffload.c index 64b497168..d9bec5966 100644 --- a/freetype/src/cff/cffload.c +++ b/freetype/src/cff/cffload.c @@ -4,7 +4,7 @@ /* */ /* OpenType and CFF data/program tables loader (body). */ /* */ -/* Copyright 1996-2013 by */ +/* Copyright 1996-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -414,7 +414,7 @@ cur_offset = idx->offsets[0] - 1; /* sanity check */ - if ( cur_offset >= idx->data_size ) + if ( cur_offset != 0 ) { FT_TRACE0(( "cff_index_get_pointers:" " invalid first offset value %d set to zero\n", @@ -432,11 +432,11 @@ 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 ) ) + /* two sanity checks for invalid offset tables */ + if ( next_offset < cur_offset ) next_offset = cur_offset; + else if ( next_offset > idx->data_size ) + next_offset = idx->data_size; if ( !pool ) t[n] = org_bytes + next_offset; @@ -689,6 +689,13 @@ if ( FT_READ_USHORT( num_ranges ) ) goto Exit; + if ( !num_ranges ) + { + FT_TRACE0(( "CFF_Load_FD_Select: empty FDSelect array\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } + fdselect->data_size = num_ranges * 3 + 2; Load_Data: @@ -719,7 +726,7 @@ break; case 3: - /* first, compare to cache */ + /* first, compare to the cache */ if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < fdselect->cache_count ) { @@ -727,7 +734,7 @@ break; } - /* then, lookup the ranges array */ + /* then, look up the ranges array */ { FT_Byte* p = fdselect->data; FT_Byte* p_limit = p + fdselect->data_size; @@ -750,7 +757,7 @@ /* update cache */ fdselect->cache_first = first; - fdselect->cache_count = limit-first; + fdselect->cache_count = limit - first; fdselect->cache_fd = fd2; break; } diff --git a/freetype/src/cff/cffobjs.c b/freetype/src/cff/cffobjs.c index dd750d104..cac4ac2bd 100644 --- a/freetype/src/cff/cffobjs.c +++ b/freetype/src/cff/cffobjs.c @@ -866,7 +866,7 @@ flags |= FT_FACE_FLAG_KERNING; #endif - cffface->face_flags = flags; + cffface->face_flags |= flags; /*******************************************************************/ /* */ @@ -1055,7 +1055,7 @@ CFF_Driver driver = (CFF_Driver)module; - /* set default property values */ + /* set default property values, cf `ftcffdrv.h' */ #ifdef CFF_CONFIG_OPTION_OLD_ENGINE driver->hinting_engine = FT_CFF_HINTING_FREETYPE; #else @@ -1063,6 +1063,15 @@ #endif driver->no_stem_darkening = FALSE; + driver->darken_params[0] = 500; + driver->darken_params[1] = 400; + driver->darken_params[2] = 1000; + driver->darken_params[3] = 275; + driver->darken_params[4] = 1667; + driver->darken_params[5] = 275; + driver->darken_params[6] = 2333; + driver->darken_params[7] = 0; + return FT_Err_Ok; } diff --git a/freetype/src/cff/cffobjs.h b/freetype/src/cff/cffobjs.h index b375c20c7..dfbf9a96b 100644 --- a/freetype/src/cff/cffobjs.h +++ b/freetype/src/cff/cffobjs.h @@ -121,6 +121,8 @@ FT_BEGIN_HEADER FT_UInt hinting_engine; FT_Bool no_stem_darkening; + FT_Int darken_params[8]; + } CFF_DriverRec; diff --git a/freetype/src/cff/cffparse.c b/freetype/src/cff/cffparse.c index 96222120b..91bd5326c 100644 --- a/freetype/src/cff/cffparse.c +++ b/freetype/src/cff/cffparse.c @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (body) */ /* */ -/* Copyright 1996-2004, 2007-2013 by */ +/* Copyright 1996-2004, 2007-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -66,7 +66,6 @@ goto Bad; val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] ); - p += 2; } else if ( v == 29 ) { @@ -77,7 +76,6 @@ ( (FT_ULong)p[1] << 16 ) | ( (FT_ULong)p[2] << 8 ) | (FT_ULong)p[3] ); - p += 4; } else if ( v < 247 ) { @@ -89,7 +87,6 @@ goto Bad; val = ( v - 247 ) * 256 + p[0] + 108; - p++; } else { @@ -97,7 +94,6 @@ goto Bad; val = -( v - 251 ) * 256 - p[0] - 108; - p++; } Exit: -- cgit v1.2.3