54#define FT_COMPONENT cf2blues
58 cf2_blues_init( CF2_Blues blues,
62 PS_Decoder* decoder = font->decoder;
65 CF2_Fixed maxZoneHeight = 0;
66 CF2_Fixed csUnitsPerPixel;
70 size_t numFamilyBlues;
71 size_t numFamilyOtherBlues;
75 FT_Fixed* familyBlues;
76 FT_Fixed* familyOtherBlues;
79 CF2_Fixed emBoxBottom, emBoxTop;
82 CF2_Int unitsPerEm = font->unitsPerEm;
85 if ( unitsPerEm == 0 )
90 blues->scale = font->innerTransform.d;
92 cf2_getBlueMetrics( decoder,
97 cf2_getBlueValues( decoder, &numBlueValues, &blueValues );
98 cf2_getOtherBlues( decoder, &numOtherBlues, &otherBlues );
99 cf2_getFamilyBlues( decoder, &numFamilyBlues, &familyBlues );
100 cf2_getFamilyOtherBlues( decoder, &numFamilyOtherBlues, &familyOtherBlues );
116 FCM_getHorizontalLineMetrics( &e,
121 if ( ascender - descender == unitsPerEm )
123 emBoxBottom = cf2_intToFixed( descender );
124 emBoxTop = cf2_intToFixed( ascender );
129 emBoxBottom = CF2_ICF_Bottom;
130 emBoxTop = CF2_ICF_Top;
133 if ( cf2_getLanguageGroup( decoder ) == 1 &&
134 ( numBlueValues == 0 ||
135 ( numBlueValues == 4 &&
136 blueValues[0] < emBoxBottom &&
137 blueValues[1] < emBoxBottom &&
138 blueValues[2] > emBoxTop &&
139 blueValues[3] > emBoxTop ) ) )
152 blues->emBoxBottomEdge.csCoord = emBoxBottom - CF2_FIXED_EPSILON;
153 blues->emBoxBottomEdge.dsCoord = cf2_fixedRound(
155 blues->emBoxBottomEdge.csCoord,
158 blues->emBoxBottomEdge.scale = blues->scale;
159 blues->emBoxBottomEdge.flags = CF2_GhostBottom |
163 blues->emBoxTopEdge.csCoord = emBoxTop + CF2_FIXED_EPSILON +
165 blues->emBoxTopEdge.dsCoord = cf2_fixedRound(
167 blues->emBoxTopEdge.csCoord,
170 blues->emBoxTopEdge.scale = blues->scale;
171 blues->emBoxTopEdge.flags = CF2_GhostTop |
175 blues->doEmBoxHints = TRUE;
182 for ( i = 0; i < numBlueValues; i += 2 )
184 blues->zone[blues->count].csBottomEdge = blueValues[i];
185 blues->zone[blues->count].csTopEdge = blueValues[i + 1];
187 zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
188 blues->zone[blues->count].csBottomEdge );
190 if ( zoneHeight < 0 )
192 FT_TRACE4((
"cf2_blues_init: ignoring negative zone height\n" ));
196 if ( zoneHeight > maxZoneHeight )
200 maxZoneHeight = zoneHeight;
206 blues->zone[blues->count].csTopEdge += 2 * font->darkenY;
207 blues->zone[blues->count].csBottomEdge += 2 * font->darkenY;
213 blues->zone[blues->count].bottomZone =
215 blues->zone[blues->count].csFlatEdge =
216 blues->zone[blues->count].csTopEdge;
220 blues->zone[blues->count].bottomZone =
222 blues->zone[blues->count].csFlatEdge =
223 blues->zone[blues->count].csBottomEdge;
229 for ( i = 0; i < numOtherBlues; i += 2 )
231 blues->zone[blues->count].csBottomEdge = otherBlues[i];
232 blues->zone[blues->count].csTopEdge = otherBlues[i + 1];
234 zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
235 blues->zone[blues->count].csBottomEdge );
237 if ( zoneHeight < 0 )
239 FT_TRACE4((
"cf2_blues_init: ignoring negative zone height\n" ));
243 if ( zoneHeight > maxZoneHeight )
247 maxZoneHeight = zoneHeight;
253 blues->zone[blues->count].bottomZone =
255 blues->zone[blues->count].csFlatEdge =
256 blues->zone[blues->count].csTopEdge;
267 csUnitsPerPixel = FT_DivFix( cf2_intToFixed( 1 ), blues->scale );
270 for ( i = 0; i < blues->count; i++ )
274 CF2_Fixed flatFamilyEdge, diff;
276 CF2_Fixed flatEdge = blues->zone[i].csFlatEdge;
279 if ( blues->zone[i].bottomZone )
285 minDiff = CF2_FIXED_MAX;
287 for ( j = 0; j < numFamilyOtherBlues; j += 2 )
290 flatFamilyEdge = familyOtherBlues[j + 1];
292 diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
294 if ( diff < minDiff && diff < csUnitsPerPixel )
296 blues->zone[i].csFlatEdge = flatFamilyEdge;
305 if ( numFamilyBlues >= 2 )
308 flatFamilyEdge = familyBlues[1];
310 diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
312 if ( diff < minDiff && diff < csUnitsPerPixel )
313 blues->zone[i].csFlatEdge = flatFamilyEdge;
323 minDiff = CF2_FIXED_MAX;
325 for ( j = 2; j < numFamilyBlues; j += 2 )
328 flatFamilyEdge = familyBlues[j];
331 flatFamilyEdge += 2 * font->darkenY;
333 diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
335 if ( diff < minDiff && diff < csUnitsPerPixel )
337 blues->zone[i].csFlatEdge = flatFamilyEdge;
352 if ( maxZoneHeight > 0 )
354 if ( blues->blueScale > FT_DivFix( cf2_intToFixed( 1 ),
358 blues->blueScale = FT_DivFix( cf2_intToFixed( 1 ),
373 if ( blueScale < .4 / maxZoneHeight )
375 tetraphilia_assert( 0 );
377 blueScale = .4 / maxZoneHeight;
391 if ( blues->scale < blues->blueScale )
393 blues->suppressOvershoot = TRUE;
399 blues->boost = cf2_doubleToFixed( .6 ) -
400 FT_MulDiv( cf2_doubleToFixed ( .6 ),
403 if ( blues->boost > 0x7FFF )
406 blues->boost = 0x7FFF;
411 if ( font->stemDarkened )
417 for ( i = 0; i < blues->count; i++ )
419 if ( blues->zone[i].bottomZone )
420 blues->zone[i].dsFlatEdge = cf2_fixedRound(
422 blues->zone[i].csFlatEdge,
426 blues->zone[i].dsFlatEdge = cf2_fixedRound(
428 blues->zone[i].csFlatEdge,
452 FT_LOCAL_DEF( FT_Bool )
453 cf2_blues_capture(
const CF2_Blues blues,
454 CF2_Hint bottomHintEdge,
455 CF2_Hint topHintEdge )
458 CF2_Fixed csFuzz = blues->blueFuzz;
464 CF2_Fixed dsMove = 0;
466 FT_Bool captured = FALSE;
471 FT_ASSERT( !cf2_hint_isTop( bottomHintEdge ) &&
472 !cf2_hint_isBottom( topHintEdge ) );
475 for ( i = 0; i < blues->count; i++ )
477 if ( blues->zone[i].bottomZone &&
478 cf2_hint_isBottom( bottomHintEdge ) )
480 if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
481 bottomHintEdge->csCoord &&
482 bottomHintEdge->csCoord <=
483 ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
487 if ( blues->suppressOvershoot )
488 dsNew = blues->zone[i].dsFlatEdge;
490 else if ( SUB_INT32( blues->zone[i].csTopEdge,
491 bottomHintEdge->csCoord ) >=
496 cf2_fixedRound( bottomHintEdge->dsCoord ),
497 SUB_INT32( blues->zone[i].dsFlatEdge,
498 cf2_intToFixed( 1 ) ) );
504 dsNew = cf2_fixedRound( bottomHintEdge->dsCoord );
507 dsMove = SUB_INT32( dsNew, bottomHintEdge->dsCoord );
514 if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) )
516 if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
517 topHintEdge->csCoord &&
518 topHintEdge->csCoord <=
519 ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
523 if ( blues->suppressOvershoot )
524 dsNew = blues->zone[i].dsFlatEdge;
526 else if ( SUB_INT32( topHintEdge->csCoord,
527 blues->zone[i].csBottomEdge ) >=
532 cf2_fixedRound( topHintEdge->dsCoord ),
533 blues->zone[i].dsFlatEdge + cf2_intToFixed( 1 ) );
539 dsNew = cf2_fixedRound( topHintEdge->dsCoord );
542 dsMove = SUB_INT32( dsNew, topHintEdge->dsCoord );
553 if ( cf2_hint_isValid( bottomHintEdge ) )
555 bottomHintEdge->dsCoord = ADD_INT32( bottomHintEdge->dsCoord,
557 cf2_hint_lock( bottomHintEdge );
560 if ( cf2_hint_isValid( topHintEdge ) )
562 topHintEdge->dsCoord = ADD_INT32( topHintEdge->dsCoord, dsMove );
563 cf2_hint_lock( topHintEdge );