Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: third_party/freetype/src/cff/cf2hints.c

Issue 815103002: Update freetype to 2.5.4. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Adjust GYP and GN Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/freetype/src/cff/cf2hints.h ('k') | third_party/freetype/src/cff/cf2intrp.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /***************************************************************************/ 1 /***************************************************************************/
2 /* */ 2 /* */
3 /* cf2hints.c */ 3 /* cf2hints.c */
4 /* */ 4 /* */
5 /* Adobe's code for handling CFF hints (body). */ 5 /* Adobe's code for handling CFF hints (body). */
6 /* */ 6 /* */
7 /* Copyright 2007-2013 Adobe Systems Incorporated. */ 7 /* Copyright 2007-2014 Adobe Systems Incorporated. */
8 /* */ 8 /* */
9 /* This software, and all works of authorship, whether in source or */ 9 /* This software, and all works of authorship, whether in source or */
10 /* object code form as indicated by the copyright notice(s) included */ 10 /* object code form as indicated by the copyright notice(s) included */
11 /* herein (collectively, the "Work") is made available, and may only be */ 11 /* herein (collectively, the "Work") is made available, and may only be */
12 /* used, modified, and distributed under the FreeType Project License, */ 12 /* used, modified, and distributed under the FreeType Project License, */
13 /* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ 13 /* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
14 /* FreeType Project License, each contributor to the Work hereby grants */ 14 /* FreeType Project License, each contributor to the Work hereby grants */
15 /* to any individual or legal entity exercising permissions granted by */ 15 /* to any individual or legal entity exercising permissions granted by */
16 /* the FreeType Project License and this section (hereafter, "You" or */ 16 /* the FreeType Project License and this section (hereafter, "You" or */
17 /* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ 17 /* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
(...skipping 12 matching lines...) Expand all
30 /* */ 30 /* */
31 /* By using, modifying, or distributing the Work you indicate that you */ 31 /* By using, modifying, or distributing the Work you indicate that you */
32 /* have read and understood the terms and conditions of the */ 32 /* have read and understood the terms and conditions of the */
33 /* FreeType Project License as well as those provided in this section, */ 33 /* FreeType Project License as well as those provided in this section, */
34 /* and you accept them fully. */ 34 /* and you accept them fully. */
35 /* */ 35 /* */
36 /***************************************************************************/ 36 /***************************************************************************/
37 37
38 38
39 #include "cf2ft.h" 39 #include "cf2ft.h"
40 #include "../../include/freetype/internal/ftdebug.h" 40 #include FT_INTERNAL_DEBUG_H
41 41
42 #include "cf2glue.h" 42 #include "cf2glue.h"
43 #include "cf2font.h" 43 #include "cf2font.h"
44 #include "cf2hints.h" 44 #include "cf2hints.h"
45 #include "cf2intrp.h" 45 #include "cf2intrp.h"
46 46
47 47
48 /*************************************************************************/ 48 /*************************************************************************/
49 /* */ 49 /* */
50 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 50 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 { 297 {
298 return hintmap->isValid; 298 return hintmap->isValid;
299 } 299 }
300 300
301 301
302 /* transform character space coordinate to device space using hint map */ 302 /* transform character space coordinate to device space using hint map */
303 static CF2_Fixed 303 static CF2_Fixed
304 cf2_hintmap_map( CF2_HintMap hintmap, 304 cf2_hintmap_map( CF2_HintMap hintmap,
305 CF2_Fixed csCoord ) 305 CF2_Fixed csCoord )
306 { 306 {
307 FT_ASSERT( hintmap->isValid ); /* must call Build before Map */
308 FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
309
310 if ( hintmap->count == 0 || ! hintmap->hinted ) 307 if ( hintmap->count == 0 || ! hintmap->hinted )
311 { 308 {
312 /* there are no hints; use uniform scale and zero offset */ 309 /* there are no hints; use uniform scale and zero offset */
313 return FT_MulFix( csCoord, hintmap->scale ); 310 return FT_MulFix( csCoord, hintmap->scale );
314 } 311 }
315 else 312 else
316 { 313 {
317 /* start linear search from last hit */ 314 /* start linear search from last hit */
318 CF2_UInt i = hintmap->lastIndex; 315 CF2_UInt i = hintmap->lastIndex;
319 316
317 FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
320 318
321 /* search up */ 319 /* search up */
322 while ( i < hintmap->count - 1 && 320 while ( i < hintmap->count - 1 &&
323 csCoord >= hintmap->edge[i + 1].csCoord ) 321 csCoord >= hintmap->edge[i + 1].csCoord )
324 i += 1; 322 i += 1;
325 323
326 /* search down */ 324 /* search down */
327 while ( i > 0 && csCoord < hintmap->edge[i].csCoord ) 325 while ( i > 0 && csCoord < hintmap->edge[i].csCoord )
328 i -= 1; 326 i -= 1;
329 327
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 } 587 }
590 588
591 /* paired edges must be in proper order */ 589 /* paired edges must be in proper order */
592 FT_ASSERT( !isPair || 590 FT_ASSERT( !isPair ||
593 topHintEdge->csCoord >= bottomHintEdge->csCoord ); 591 topHintEdge->csCoord >= bottomHintEdge->csCoord );
594 592
595 /* linear search to find index value of insertion point */ 593 /* linear search to find index value of insertion point */
596 indexInsert = 0; 594 indexInsert = 0;
597 for ( ; indexInsert < hintmap->count; indexInsert++ ) 595 for ( ; indexInsert < hintmap->count; indexInsert++ )
598 { 596 {
599 if ( hintmap->edge[indexInsert].csCoord > firstHintEdge->csCoord ) 597 if ( hintmap->edge[indexInsert].csCoord >= firstHintEdge->csCoord )
600 break; 598 break;
601 } 599 }
602 600
603 /* 601 /*
604 * Discard any hints that overlap in character space. Most often, 602 * Discard any hints that overlap in character space. Most often, this
605 * this is while building the initial map, but in theory, it can also 603 * is while building the initial map, where captured hints from all
606 * occur because of darkening. 604 * zones are combined. Define overlap to include hints that `touch'
605 * (overlap zero). Hiragino Sans/Gothic fonts have numerous hints that
606 * touch. Some fonts have non-ideographic glyphs that overlap our
607 * synthetic hints.
608 *
609 * Overlap also occurs when darkening stem hints that are close.
607 * 610 *
608 */ 611 */
609 if ( indexInsert < hintmap->count ) 612 if ( indexInsert < hintmap->count )
610 { 613 {
611 /* we are inserting before an existing edge: */ 614 /* we are inserting before an existing edge: */
615 /* verify that an existing edge is not the same */
616 if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord )
617 return; /* ignore overlapping stem hint */
618
612 /* verify that a new pair does not straddle the next edge */ 619 /* verify that a new pair does not straddle the next edge */
613 if ( isPair && 620 if ( isPair &&
614 hintmap->edge[indexInsert].csCoord < secondHintEdge->csCoord ) 621 hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord )
615 return; /* ignore overlapping stem hint */ 622 return; /* ignore overlapping stem hint */
616 623
617 /* verify that we are not inserting between paired edges */ 624 /* verify that we are not inserting between paired edges */
618 if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) ) 625 if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) )
619 return; /* ignore overlapping stem hint */ 626 return; /* ignore overlapping stem hint */
620 } 627 }
621 628
622 /* recompute device space locations using initial hint map */ 629 /* recompute device space locations using initial hint map */
623 if ( cf2_hintmap_isValid( hintmap->initialHintMap ) && 630 if ( cf2_hintmap_isValid( hintmap->initialHintMap ) &&
624 !cf2_hint_isLocked( firstHintEdge ) ) 631 !cf2_hint_isLocked( firstHintEdge ) )
(...skipping 13 matching lines...) Expand all
638 645
639 646
640 firstHintEdge->dsCoord = midpoint - halfWidth; 647 firstHintEdge->dsCoord = midpoint - halfWidth;
641 secondHintEdge->dsCoord = midpoint + halfWidth; 648 secondHintEdge->dsCoord = midpoint + halfWidth;
642 } 649 }
643 else 650 else
644 firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap, 651 firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap,
645 firstHintEdge->csCoord ); 652 firstHintEdge->csCoord );
646 } 653 }
647 654
648 /* discard any hints that overlap in device space; this can occur */ 655 /*
649 /* because locked hints have been moved to align with blue zones */ 656 * Discard any hints that overlap in device space; this can occur
657 * because locked hints have been moved to align with blue zones.
658 *
659 * TODO: Although we might correct this later during adjustment, we
660 * don't currently have a way to delete a conflicting hint once it has
661 * been inserted. See v2.030 MinionPro-Regular, 12 ppem darkened,
662 * initial hint map for second path, glyph 945 (the perispomeni (tilde)
663 * in U+1F6E, Greek omega with psili and perispomeni). Darkening is
664 * 25. Pair 667,747 initially conflicts in design space with top edge
665 * 660. This is because 667 maps to 7.87, and the top edge was
666 * captured by a zone at 8.0. The pair is later successfully inserted
667 * in a zone without the top edge. In this zone it is adjusted to 8.0,
668 * and no longer conflicts with the top edge in design space. This
669 * means it can be included in yet a later zone which does have the top
670 * edge hint. This produces a small mismatch between the first and
671 * last points of this path, even though the hint masks are the same.
672 * The density map difference is tiny (1/256).
673 *
674 */
675
650 if ( indexInsert > 0 ) 676 if ( indexInsert > 0 )
651 { 677 {
652 /* we are inserting after an existing edge */ 678 /* we are inserting after an existing edge */
653 if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord ) 679 if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord )
654 return; 680 return;
655 } 681 }
656 682
657 if ( indexInsert < hintmap->count ) 683 if ( indexInsert < hintmap->count )
658 { 684 {
659 /* we are inserting before an existing edge */ 685 /* we are inserting before an existing edge */
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 */ 744 */
719 FT_LOCAL_DEF( void ) 745 FT_LOCAL_DEF( void )
720 cf2_hintmap_build( CF2_HintMap hintmap, 746 cf2_hintmap_build( CF2_HintMap hintmap,
721 CF2_ArrStack hStemHintArray, 747 CF2_ArrStack hStemHintArray,
722 CF2_ArrStack vStemHintArray, 748 CF2_ArrStack vStemHintArray,
723 CF2_HintMask hintMask, 749 CF2_HintMask hintMask,
724 CF2_Fixed hintOrigin, 750 CF2_Fixed hintOrigin,
725 FT_Bool initialMap ) 751 FT_Bool initialMap )
726 { 752 {
727 FT_Byte* maskPtr; 753 FT_Byte* maskPtr;
728 FT_Byte* maskEndPtr; // add by Xiaochuan_Liu
729 754
730 CF2_Font font = hintmap->font; 755 CF2_Font font = hintmap->font;
731 CF2_HintMaskRec tempHintMask; 756 CF2_HintMaskRec tempHintMask;
732 757
733 size_t bitCount, i; 758 size_t bitCount, i;
734 FT_Byte maskByte; 759 FT_Byte maskByte;
735 760
736 761
737 /* check whether initial map is constructed */ 762 /* check whether initial map is constructed */
738 if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) ) 763 if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) )
739 { 764 {
740 /* make recursive call with initialHintMap and temporary mask; */ 765 /* make recursive call with initialHintMap and temporary mask; */
741 /* temporary mask will get all bits set, below */ 766 /* temporary mask will get all bits set, below */
742 cf2_hintmask_init( &tempHintMask, hintMask->error ); 767 cf2_hintmask_init( &tempHintMask, hintMask->error );
743 cf2_hintmap_build( hintmap->initialHintMap, 768 cf2_hintmap_build( hintmap->initialHintMap,
744 hStemHintArray, 769 hStemHintArray,
745 vStemHintArray, 770 vStemHintArray,
746 &tempHintMask, 771 &tempHintMask,
747 hintOrigin, 772 hintOrigin,
748 TRUE ); 773 TRUE );
749 } 774 }
750 775
751 if ( !cf2_hintmask_isValid( hintMask ) ) 776 if ( !cf2_hintmask_isValid( hintMask ) )
752 { 777 {
753 /* without a hint mask, assume all hints are active */ 778 /* without a hint mask, assume all hints are active */
754 cf2_hintmask_setAll( hintMask, 779 cf2_hintmask_setAll( hintMask,
755 cf2_arrstack_size( hStemHintArray ) + 780 cf2_arrstack_size( hStemHintArray ) +
756 cf2_arrstack_size( vStemHintArray ) ); 781 cf2_arrstack_size( vStemHintArray ) );
782 if ( !cf2_hintmask_isValid( hintMask ) )
783 return; /* too many stem hints */
757 } 784 }
758 785
759 /* begin by clearing the map */ 786 /* begin by clearing the map */
760 hintmap->count = 0; 787 hintmap->count = 0;
761 hintmap->lastIndex = 0; 788 hintmap->lastIndex = 0;
762 789
763 /* make a copy of the hint mask so we can modify it */ 790 /* make a copy of the hint mask so we can modify it */
764 tempHintMask = *hintMask; 791 tempHintMask = *hintMask;
765 maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask ); 792 maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
766 maskEndPtr = maskPtr + ( CF2_MAX_HINTS + 7 ) / 8;
767
768 793
769 /* use the hStem hints only, which are first in the mask */ 794 /* use the hStem hints only, which are first in the mask */
770 /* TODO: compare this to cffhintmaskGetBitCount */
771 bitCount = cf2_arrstack_size( hStemHintArray ); 795 bitCount = cf2_arrstack_size( hStemHintArray );
772 796
797 /* Defense-in-depth. Should never return here. */
798 if ( bitCount > hintMask->bitCount )
799 return;
800
773 /* synthetic embox hints get highest priority */ 801 /* synthetic embox hints get highest priority */
774 if ( font->blues.doEmBoxHints ) 802 if ( font->blues.doEmBoxHints )
775 { 803 {
776 CF2_HintRec dummy; 804 CF2_HintRec dummy;
777 805
778 806
779 cf2_hint_initZero( &dummy ); /* invalid hint map element */ 807 cf2_hint_initZero( &dummy ); /* invalid hint map element */
780 808
781 /* ghost bottom */ 809 /* ghost bottom */
782 cf2_hintmap_insertHint( hintmap, 810 cf2_hintmap_insertHint( hintmap,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge ); 851 cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
824 852
825 *maskPtr &= ~maskByte; /* turn off the bit for this hint */ 853 *maskPtr &= ~maskByte; /* turn off the bit for this hint */
826 } 854 }
827 } 855 }
828 856
829 if ( ( i & 7 ) == 7 ) 857 if ( ( i & 7 ) == 7 )
830 { 858 {
831 /* move to next mask byte */ 859 /* move to next mask byte */
832 maskPtr++; 860 maskPtr++;
833 if (maskPtr >= maskEndPtr)
834 {
835 break;
836 }
837
838 maskByte = 0x80; 861 maskByte = 0x80;
839 } 862 }
840 else 863 else
841 maskByte >>= 1; 864 maskByte >>= 1;
842 } 865 }
843 866
844 /* initial hint map includes only captured hints plus maybe one at 0 */ 867 /* initial hint map includes only captured hints plus maybe one at 0 */
845 868
846 /* 869 /*
847 * TODO: There is a problem here because we are trying to build a 870 * TODO: There is a problem here because we are trying to build a
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 911
889 cf2_hint_initZero( &invalid ); 912 cf2_hint_initZero( &invalid );
890 cf2_hintmap_insertHint( hintmap, &edge, &invalid ); 913 cf2_hintmap_insertHint( hintmap, &edge, &invalid );
891 } 914 }
892 } 915 }
893 else 916 else
894 { 917 {
895 /* insert remaining hints */ 918 /* insert remaining hints */
896 919
897 maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask ); 920 maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
898 maskEndPtr = maskPtr + ( CF2_MAX_HINTS + 7 ) / 8;
899 921
900 for ( i = 0, maskByte = 0x80; i < bitCount; i++ ) 922 for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
901 { 923 {
902 if ( maskByte & *maskPtr ) 924 if ( maskByte & *maskPtr )
903 { 925 {
904 CF2_HintRec bottomHintEdge, topHintEdge; 926 CF2_HintRec bottomHintEdge, topHintEdge;
905 927
906 928
907 cf2_hint_init( &bottomHintEdge, 929 cf2_hint_init( &bottomHintEdge,
908 hStemHintArray, 930 hStemHintArray,
(...skipping 10 matching lines...) Expand all
919 hintmap->scale, 941 hintmap->scale,
920 FALSE /* top */ ); 942 FALSE /* top */ );
921 943
922 cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge ); 944 cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
923 } 945 }
924 946
925 if ( ( i & 7 ) == 7 ) 947 if ( ( i & 7 ) == 7 )
926 { 948 {
927 /* move to next mask byte */ 949 /* move to next mask byte */
928 maskPtr++; 950 maskPtr++;
929 if (maskPtr >= maskEndPtr)
930 {
931 break;
932 }
933 maskByte = 0x80; 951 maskByte = 0x80;
934 } 952 }
935 else 953 else
936 maskByte >>= 1; 954 maskByte >>= 1;
937 } 955 }
938 } 956 }
939 957
940 /* 958 /*
941 * Note: The following line is a convenient place to break when 959 * Note: The following line is a convenient place to break when
942 * debugging hinting. Examine `hintmap->edge' for the list of 960 * debugging hinting. Examine `hintmap->edge' for the list of
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 glyphpath->yOffset = font->darkenY; 1059 glyphpath->yOffset = font->darkenY;
1042 glyphpath->miterLimit = 2 * FT_MAX( 1060 glyphpath->miterLimit = 2 * FT_MAX(
1043 cf2_fixedAbs( glyphpath->xOffset ), 1061 cf2_fixedAbs( glyphpath->xOffset ),
1044 cf2_fixedAbs( glyphpath->yOffset ) ); 1062 cf2_fixedAbs( glyphpath->yOffset ) );
1045 1063
1046 /* .1 character space unit */ 1064 /* .1 character space unit */
1047 glyphpath->snapThreshold = cf2_floatToFixed( 0.1f ); 1065 glyphpath->snapThreshold = cf2_floatToFixed( 0.1f );
1048 1066
1049 glyphpath->moveIsPending = TRUE; 1067 glyphpath->moveIsPending = TRUE;
1050 glyphpath->pathIsOpen = FALSE; 1068 glyphpath->pathIsOpen = FALSE;
1069 glyphpath->pathIsClosing = FALSE;
1051 glyphpath->elemIsQueued = FALSE; 1070 glyphpath->elemIsQueued = FALSE;
1052 } 1071 }
1053 1072
1054 1073
1055 FT_LOCAL_DEF( void ) 1074 FT_LOCAL_DEF( void )
1056 cf2_glyphpath_finalize( CF2_GlyphPath glyphpath ) 1075 cf2_glyphpath_finalize( CF2_GlyphPath glyphpath )
1057 { 1076 {
1058 cf2_arrstack_finalize( &glyphpath->hintMoves ); 1077 cf2_arrstack_finalize( &glyphpath->hintMoves );
1059 } 1078 }
1060 1079
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1181 glyphpath->miterLimit ) 1200 glyphpath->miterLimit )
1182 return FALSE; 1201 return FALSE;
1183 1202
1184 return TRUE; 1203 return TRUE;
1185 } 1204 }
1186 1205
1187 1206
1188 /* 1207 /*
1189 * Push the cached element (glyphpath->prevElem*) to the outline 1208 * Push the cached element (glyphpath->prevElem*) to the outline
1190 * consumer. When a darkening offset is used, the end point of the 1209 * consumer. When a darkening offset is used, the end point of the
1191 * cached element may be adjusted to an intersection point or it may be 1210 * cached element may be adjusted to an intersection point or we may
1192 * connected by a line to the current element. This calculation must 1211 * synthesize a connecting line to the current element. If we are
1193 * use a HintMap that was valid at the time the element was saved. For 1212 * closing a subpath, we may also generate a connecting line to the start
1194 * the first point in a subpath, that is a saved HintMap. For most 1213 * point.
1195 * elements, it just means the caller has delayed building a HintMap 1214 *
1196 * from the current HintMask. 1215 * This is where Character Space (CS) is converted to Device Space (DS)
1216 * using a hint map. This calculation must use a HintMap that was valid
1217 * at the time the element was saved. For the first point in a subpath,
1218 * that is a saved HintMap. For most elements, it just means the caller
1219 * has delayed building a HintMap from the current HintMask.
1197 * 1220 *
1198 * Transform each point with outerTransform and call the outline 1221 * Transform each point with outerTransform and call the outline
1199 * callbacks. This is a general 3x3 transform: 1222 * callbacks. This is a general 3x3 transform:
1200 * 1223 *
1201 * x' = a*x + c*y + tx, y' = b*x + d*y + ty 1224 * x' = a*x + c*y + tx, y' = b*x + d*y + ty
1202 * 1225 *
1203 * but it uses 4 elements from CF2_Font and the translation part 1226 * but it uses 4 elements from CF2_Font and the translation part
1204 * from CF2_GlyphPath. 1227 * from CF2_GlyphPath.
1205 * 1228 *
1206 */ 1229 */
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 } 1279 }
1257 1280
1258 params.pt0 = glyphpath->currentDS; 1281 params.pt0 = glyphpath->currentDS;
1259 1282
1260 switch( glyphpath->prevElemOp ) 1283 switch( glyphpath->prevElemOp )
1261 { 1284 {
1262 case CF2_PathOpLineTo: 1285 case CF2_PathOpLineTo:
1263 params.op = CF2_PathOpLineTo; 1286 params.op = CF2_PathOpLineTo;
1264 1287
1265 /* note: pt2 and pt3 are unused */ 1288 /* note: pt2 and pt3 are unused */
1266 cf2_glyphpath_hintPoint( glyphpath,
1267 hintmap,
1268 &params.pt1,
1269 glyphpath->prevElemP1.x,
1270 glyphpath->prevElemP1.y );
1271 1289
1272 glyphpath->callbacks->lineTo( glyphpath->callbacks, &params ); 1290 if ( close )
1291 {
1292 /* use first hint map if closing */
1293 cf2_glyphpath_hintPoint( glyphpath,
1294 &glyphpath->firstHintMap,
1295 &params.pt1,
1296 glyphpath->prevElemP1.x,
1297 glyphpath->prevElemP1.y );
1298 }
1299 else
1300 {
1301 cf2_glyphpath_hintPoint( glyphpath,
1302 hintmap,
1303 &params.pt1,
1304 glyphpath->prevElemP1.x,
1305 glyphpath->prevElemP1.y );
1306 }
1273 1307
1274 glyphpath->currentDS = params.pt1; 1308 /* output only non-zero length lines */
1309 if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y )
1310 {
1311 glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
1275 1312
1313 glyphpath->currentDS = params.pt1;
1314 }
1276 break; 1315 break;
1277 1316
1278 case CF2_PathOpCubeTo: 1317 case CF2_PathOpCubeTo:
1279 params.op = CF2_PathOpCubeTo; 1318 params.op = CF2_PathOpCubeTo;
1280 1319
1281 /* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */ 1320 /* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */
1282 cf2_glyphpath_hintPoint( glyphpath, 1321 cf2_glyphpath_hintPoint( glyphpath,
1283 hintmap, 1322 hintmap,
1284 &params.pt1, 1323 &params.pt1,
1285 glyphpath->prevElemP1.x, 1324 glyphpath->prevElemP1.x,
(...skipping 16 matching lines...) Expand all
1302 break; 1341 break;
1303 } 1342 }
1304 1343
1305 if ( !useIntersection || close ) 1344 if ( !useIntersection || close )
1306 { 1345 {
1307 /* insert connecting line between end of previous element and start */ 1346 /* insert connecting line between end of previous element and start */
1308 /* of current one */ 1347 /* of current one */
1309 /* note: at the end of a subpath, we might do both, so use `nextP0' */ 1348 /* note: at the end of a subpath, we might do both, so use `nextP0' */
1310 /* before we change it, below */ 1349 /* before we change it, below */
1311 1350
1312 cf2_glyphpath_hintPoint( glyphpath, 1351 if ( close )
1313 hintmap, 1352 {
1314 &params.pt1, 1353 /* if we are closing the subpath, then nextP0 is in the first */
1315 nextP0->x, 1354 /* hint zone */
1316 nextP0->y ); 1355 cf2_glyphpath_hintPoint( glyphpath,
1356 &glyphpath->firstHintMap,
1357 &params.pt1,
1358 nextP0->x,
1359 nextP0->y );
1360 }
1361 else
1362 {
1363 cf2_glyphpath_hintPoint( glyphpath,
1364 hintmap,
1365 &params.pt1,
1366 nextP0->x,
1367 nextP0->y );
1368 }
1317 1369
1318 if ( params.pt1.x != glyphpath->currentDS.x || 1370 if ( params.pt1.x != glyphpath->currentDS.x ||
1319 params.pt1.y != glyphpath->currentDS.y ) 1371 params.pt1.y != glyphpath->currentDS.y )
1320 { 1372 {
1321 /* length is nonzero */ 1373 /* length is nonzero */
1322 params.op = CF2_PathOpLineTo; 1374 params.op = CF2_PathOpLineTo;
1323 params.pt0 = glyphpath->currentDS; 1375 params.pt0 = glyphpath->currentDS;
1324 1376
1325 /* note: pt2 and pt3 are unused */ 1377 /* note: pt2 and pt3 are unused */
1326 glyphpath->callbacks->lineTo( glyphpath->callbacks, &params ); 1378 glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1502 if ( -dx > -2 * dy ) 1554 if ( -dx > -2 * dy )
1503 { 1555 {
1504 /* -x */ 1556 /* -x */
1505 *x = 0; 1557 *x = 0;
1506 *y = 2 * glyphpath->yOffset; 1558 *y = 2 * glyphpath->yOffset;
1507 } 1559 }
1508 else if ( -dy > -2 * dx ) 1560 else if ( -dy > -2 * dx )
1509 { 1561 {
1510 /* -y */ 1562 /* -y */
1511 *x = -glyphpath->xOffset; 1563 *x = -glyphpath->xOffset;
1512 *y = glyphpath->xOffset; 1564 *y = glyphpath->yOffset;
1513 } 1565 }
1514 else 1566 else
1515 { 1567 {
1516 /* -x -y */ 1568 /* -x -y */
1517 *x = FT_MulFix( cf2_floatToFixed( -0.7 ), 1569 *x = FT_MulFix( cf2_floatToFixed( -0.7 ),
1518 glyphpath->xOffset ); 1570 glyphpath->xOffset );
1519 *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ), 1571 *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ),
1520 glyphpath->yOffset ); 1572 glyphpath->yOffset );
1521 } 1573 }
1522 } 1574 }
1523 } 1575 }
1524 } 1576 }
1525 1577
1526 1578
1579 /*
1580 * The functions cf2_glyphpath_{moveTo,lineTo,curveTo,closeOpenPath} are
1581 * called by the interpreter with Character Space (CS) coordinates. Each
1582 * path element is placed into a queue of length one to await the
1583 * calculation of the following element. At that time, the darkening
1584 * offset of the following element is known and joins can be computed,
1585 * including possible modification of this element, before mapping to
1586 * Device Space (DS) and passing it on to the outline consumer.
1587 *
1588 */
1527 FT_LOCAL_DEF( void ) 1589 FT_LOCAL_DEF( void )
1528 cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath, 1590 cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
1529 CF2_Fixed x, 1591 CF2_Fixed x,
1530 CF2_Fixed y ) 1592 CF2_Fixed y )
1531 { 1593 {
1532 cf2_glyphpath_closeOpenPath( glyphpath ); 1594 cf2_glyphpath_closeOpenPath( glyphpath );
1533 1595
1534 /* save the parameters of the move for later, when we'll know how to */ 1596 /* save the parameters of the move for later, when we'll know how to */
1535 /* offset it; */ 1597 /* offset it; */
1536 /* also save last move point */ 1598 /* also save last move point */
(...skipping 17 matching lines...) Expand all
1554 } 1616 }
1555 1617
1556 1618
1557 FT_LOCAL_DEF( void ) 1619 FT_LOCAL_DEF( void )
1558 cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath, 1620 cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath,
1559 CF2_Fixed x, 1621 CF2_Fixed x,
1560 CF2_Fixed y ) 1622 CF2_Fixed y )
1561 { 1623 {
1562 CF2_Fixed xOffset, yOffset; 1624 CF2_Fixed xOffset, yOffset;
1563 FT_Vector P0, P1; 1625 FT_Vector P0, P1;
1626 FT_Bool newHintMap;
1564 1627
1628 /*
1629 * New hints will be applied after cf2_glyphpath_pushPrevElem has run.
1630 * In case this is a synthesized closing line, any new hints should be
1631 * delayed until this path is closed (`cf2_hintmask_isNew' will be
1632 * called again before the next line or curve).
1633 */
1565 1634
1566 /* can't compute offset of zero length line, so ignore them */ 1635 /* true if new hint map not on close */
1567 if ( glyphpath->currentCS.x == x && glyphpath->currentCS.y == y ) 1636 newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) &&
1637 !glyphpath->pathIsClosing;
1638
1639 /*
1640 * Zero-length lines may occur in the charstring. Because we cannot
1641 * compute darkening offsets or intersections from zero-length lines,
1642 * it is best to remove them and avoid artifacts. However, zero-length
1643 * lines in CS at the start of a new hint map can generate non-zero
1644 * lines in DS due to hint substitution. We detect a change in hint
1645 * map here and pass those zero-length lines along.
1646 */
1647
1648 /*
1649 * Note: Find explicitly closed paths here with a conditional
1650 * breakpoint using
1651 *
1652 * !gp->pathIsClosing && gp->start.x == x && gp->start.y == y
1653 *
1654 */
1655
1656 if ( glyphpath->currentCS.x == x &&
1657 glyphpath->currentCS.y == y &&
1658 !newHintMap )
1659 /*
1660 * Ignore zero-length lines in CS where the hint map is the same
1661 * because the line in DS will also be zero length.
1662 *
1663 * Ignore zero-length lines when we synthesize a closing line because
1664 * the close will be handled in cf2_glyphPath_pushPrevElem.
1665 */
1568 return; 1666 return;
1569 1667
1570 cf2_glyphpath_computeOffset( glyphpath, 1668 cf2_glyphpath_computeOffset( glyphpath,
1571 glyphpath->currentCS.x, 1669 glyphpath->currentCS.x,
1572 glyphpath->currentCS.y, 1670 glyphpath->currentCS.y,
1573 x, 1671 x,
1574 y, 1672 y,
1575 &xOffset, 1673 &xOffset,
1576 &yOffset ); 1674 &yOffset );
1577 1675
1578 /* construct offset points */ 1676 /* construct offset points */
1579 P0.x = glyphpath->currentCS.x + xOffset; 1677 P0.x = glyphpath->currentCS.x + xOffset;
1580 P0.y = glyphpath->currentCS.y + yOffset; 1678 P0.y = glyphpath->currentCS.y + yOffset;
1581 P1.x = x + xOffset; 1679 P1.x = x + xOffset;
1582 P1.y = y + yOffset; 1680 P1.y = y + yOffset;
1583 1681
1584 if ( glyphpath->moveIsPending ) 1682 if ( glyphpath->moveIsPending )
1585 { 1683 {
1586 /* emit offset 1st point as MoveTo */ 1684 /* emit offset 1st point as MoveTo */
1587 cf2_glyphpath_pushMove( glyphpath, P0 ); 1685 cf2_glyphpath_pushMove( glyphpath, P0 );
1588 if (glyphpath->callbacks && glyphpath->callbacks->error && *glyphpath- >callbacks->error) return;
1589 1686
1590 glyphpath->moveIsPending = FALSE; /* adjust state machine */ 1687 glyphpath->moveIsPending = FALSE; /* adjust state machine */
1591 glyphpath->pathIsOpen = TRUE; 1688 glyphpath->pathIsOpen = TRUE;
1592 1689
1593 glyphpath->offsetStart1 = P1; /* record second point */ 1690 glyphpath->offsetStart1 = P1; /* record second point */
1594 } 1691 }
1595 1692
1596 if ( glyphpath->elemIsQueued ) 1693 if ( glyphpath->elemIsQueued )
1597 { 1694 {
1598 FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ); 1695 FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
1696 glyphpath->hintMap.count == 0 );
1599 1697
1600 cf2_glyphpath_pushPrevElem( glyphpath, 1698 cf2_glyphpath_pushPrevElem( glyphpath,
1601 &glyphpath->hintMap, 1699 &glyphpath->hintMap,
1602 &P0, 1700 &P0,
1603 P1, 1701 P1,
1604 FALSE ); 1702 FALSE );
1605 if (glyphpath->callbacks && glyphpath->callbacks->error && *glyphpath- >callbacks->error) return;
1606 } 1703 }
1607 1704
1608 /* queue the current element with offset points */ 1705 /* queue the current element with offset points */
1609 glyphpath->elemIsQueued = TRUE; 1706 glyphpath->elemIsQueued = TRUE;
1610 glyphpath->prevElemOp = CF2_PathOpLineTo; 1707 glyphpath->prevElemOp = CF2_PathOpLineTo;
1611 glyphpath->prevElemP0 = P0; 1708 glyphpath->prevElemP0 = P0;
1612 glyphpath->prevElemP1 = P1; 1709 glyphpath->prevElemP1 = P1;
1613 1710
1614 /* update current map */ 1711 /* update current map */
1615 if ( cf2_hintmask_isNew( glyphpath->hintMask ) ) 1712 if ( newHintMap )
1616 cf2_hintmap_build( &glyphpath->hintMap, 1713 cf2_hintmap_build( &glyphpath->hintMap,
1617 glyphpath->hStemHintArray, 1714 glyphpath->hStemHintArray,
1618 glyphpath->vStemHintArray, 1715 glyphpath->vStemHintArray,
1619 glyphpath->hintMask, 1716 glyphpath->hintMask,
1620 glyphpath->hintOriginY, 1717 glyphpath->hintOriginY,
1621 FALSE ); 1718 FALSE );
1622 1719
1623 glyphpath->currentCS.x = x; /* pre-offset current point */ 1720 glyphpath->currentCS.x = x; /* pre-offset current point */
1624 glyphpath->currentCS.y = y; 1721 glyphpath->currentCS.y = y;
1625 } 1722 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1666 /* note: preserve angle of final segment by using offset3 at both ends */ 1763 /* note: preserve angle of final segment by using offset3 at both ends */
1667 P2.x = x2 + xOffset3; 1764 P2.x = x2 + xOffset3;
1668 P2.y = y2 + yOffset3; 1765 P2.y = y2 + yOffset3;
1669 P3.x = x3 + xOffset3; 1766 P3.x = x3 + xOffset3;
1670 P3.y = y3 + yOffset3; 1767 P3.y = y3 + yOffset3;
1671 1768
1672 if ( glyphpath->moveIsPending ) 1769 if ( glyphpath->moveIsPending )
1673 { 1770 {
1674 /* emit offset 1st point as MoveTo */ 1771 /* emit offset 1st point as MoveTo */
1675 cf2_glyphpath_pushMove( glyphpath, P0 ); 1772 cf2_glyphpath_pushMove( glyphpath, P0 );
1676 if (glyphpath->callbacks && glyphpath->callbacks->error && *glyphpath- >callbacks->error) return;
1677 1773
1678 glyphpath->moveIsPending = FALSE; 1774 glyphpath->moveIsPending = FALSE;
1679 glyphpath->pathIsOpen = TRUE; 1775 glyphpath->pathIsOpen = TRUE;
1680 1776
1681 glyphpath->offsetStart1 = P1; /* record second point */ 1777 glyphpath->offsetStart1 = P1; /* record second point */
1682 } 1778 }
1683 1779
1684 if ( glyphpath->elemIsQueued ) 1780 if ( glyphpath->elemIsQueued )
1685 { 1781 {
1686 FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ); 1782 FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
1783 glyphpath->hintMap.count == 0 );
1687 1784
1688 cf2_glyphpath_pushPrevElem( glyphpath, 1785 cf2_glyphpath_pushPrevElem( glyphpath,
1689 &glyphpath->hintMap, 1786 &glyphpath->hintMap,
1690 &P0, 1787 &P0,
1691 P1, 1788 P1,
1692 FALSE ); 1789 FALSE );
1693 if (glyphpath->callbacks && glyphpath->callbacks->error && *glyphpath- >callbacks->error) return;
1694 } 1790 }
1695 1791
1696 /* queue the current element with offset points */ 1792 /* queue the current element with offset points */
1697 glyphpath->elemIsQueued = TRUE; 1793 glyphpath->elemIsQueued = TRUE;
1698 glyphpath->prevElemOp = CF2_PathOpCubeTo; 1794 glyphpath->prevElemOp = CF2_PathOpCubeTo;
1699 glyphpath->prevElemP0 = P0; 1795 glyphpath->prevElemP0 = P0;
1700 glyphpath->prevElemP1 = P1; 1796 glyphpath->prevElemP1 = P1;
1701 glyphpath->prevElemP2 = P2; 1797 glyphpath->prevElemP2 = P2;
1702 glyphpath->prevElemP3 = P3; 1798 glyphpath->prevElemP3 = P3;
1703 1799
1704 /* update current map */ 1800 /* update current map */
1705 if ( cf2_hintmask_isNew( glyphpath->hintMask ) ) 1801 if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
1706 cf2_hintmap_build( &glyphpath->hintMap, 1802 cf2_hintmap_build( &glyphpath->hintMap,
1707 glyphpath->hStemHintArray, 1803 glyphpath->hStemHintArray,
1708 glyphpath->vStemHintArray, 1804 glyphpath->vStemHintArray,
1709 glyphpath->hintMask, 1805 glyphpath->hintMask,
1710 glyphpath->hintOriginY, 1806 glyphpath->hintOriginY,
1711 FALSE ); 1807 FALSE );
1712 1808
1713 glyphpath->currentCS.x = x3; /* pre-offset current point */ 1809 glyphpath->currentCS.x = x3; /* pre-offset current point */
1714 glyphpath->currentCS.y = y3; 1810 glyphpath->currentCS.y = y3;
1715 } 1811 }
1716 1812
1717 1813
1718 FT_LOCAL_DEF( void ) 1814 FT_LOCAL_DEF( void )
1719 cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath ) 1815 cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath )
1720 { 1816 {
1721 if ( glyphpath->pathIsOpen ) 1817 if ( glyphpath->pathIsOpen )
1722 { 1818 {
1723 FT_ASSERT( cf2_hintmap_isValid( &glyphpath->firstHintMap ) ); 1819 /*
1820 * A closing line in Character Space line is always generated below
1821 * with `cf2_glyphPath_lineTo'. It may be ignored later if it turns
1822 * out to be zero length in Device Space.
1823 */
1824 glyphpath->pathIsClosing = TRUE;
1724 1825
1725 /* since we need to apply an offset to the implicit lineto, we make */
1726 /* it explicit here */
1727 cf2_glyphpath_lineTo( glyphpath, 1826 cf2_glyphpath_lineTo( glyphpath,
1728 glyphpath->start.x, 1827 glyphpath->start.x,
1729 glyphpath->start.y ); 1828 glyphpath->start.y );
1730 if (glyphpath->callbacks && glyphpath->callbacks->error && *glyphpath- >callbacks->error) return;
1731 1829
1732 /* Draw previous element (the explicit LineTo we just created, */ 1830 /* empty the final element from the queue and close the path */
1733 /* above) and connect it to the start point, but with the offset we */ 1831 if ( glyphpath->elemIsQueued )
1734 /* saved from the first element. */ 1832 cf2_glyphpath_pushPrevElem( glyphpath,
1735 /* Use the saved HintMap, too. */ 1833 &glyphpath->hintMap,
1736 FT_ASSERT( glyphpath->elemIsQueued ); 1834 &glyphpath->offsetStart0,
1737 1835 glyphpath->offsetStart1,
1738 cf2_glyphpath_pushPrevElem( glyphpath, 1836 TRUE );
1739 &glyphpath->firstHintMap,
1740 &glyphpath->offsetStart0,
1741 glyphpath->offsetStart1,
1742 TRUE );
1743 1837
1744 /* reset state machine */ 1838 /* reset state machine */
1745 glyphpath->moveIsPending = TRUE; 1839 glyphpath->moveIsPending = TRUE;
1746 glyphpath->pathIsOpen = FALSE; 1840 glyphpath->pathIsOpen = FALSE;
1841 glyphpath->pathIsClosing = FALSE;
1747 glyphpath->elemIsQueued = FALSE; 1842 glyphpath->elemIsQueued = FALSE;
1748 } 1843 }
1749 } 1844 }
1750 1845
1751 1846
1752 /* END */ 1847 /* END */
OLDNEW
« no previous file with comments | « third_party/freetype/src/cff/cf2hints.h ('k') | third_party/freetype/src/cff/cf2intrp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698