1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2010 Henrik Tidefelt
23 #include "afmscanner.h"
24 #include "strrefdup.h"
25 #include "exitcodes.h"
29 #include <cstdio> // This is a workaround for a bug in Flex.
31 #define YY_EXIT_FAILURE Shapes::Interaction::EXIT_INTERNAL_ERROR
33 // These functions must note be called with invalid arguments!
34 const char * strtoname( char * begin, char ** endp, const char * delim = " \t" );
35 const char * strtoname( char * begin, char ** endp, const char * delim, size_t delimSize );
37 /* The rule HorizontalWhiteSpace is not in agreement with the specification, as far as I can see,
38 * but it's the smallest change I can think of which should make this program work
39 * with DOS files as well as ordiary files.
44 HorizontalWhiteSpace [ \t\r]*
47 HexInteger [0-9A-Fa-f]+
49 Boolean "true"|"false"
51 Number [+-]?(([0-9]*[.][0-9]+)|([0-9]+))
60 %option yyclass="AfmScanner"
115 <INITIAL>"StartFontMetrics ".*[\n] {
119 <Global>"EndFontMetrics"{HorizontalWhiteSpace}[\n] {
120 if( fontMetricsDst_->horizontalMetrics_ != NullPtr< FontMetrics::WritingDirectionMetrics >( ) )
122 // I const cast because I'm too tired to think of something better.
123 FontMetrics::CharacterMetrics * defaultChar = const_cast< FontMetrics::CharacterMetrics * >( horizontalMetrics_typed_->charData_[ 0 ] );
124 defaultChar->xmin_ = fontMetricsDst_->fontBBoxXMin_;
125 defaultChar->ymin_ = fontMetricsDst_->fontBBoxYMin_;
126 defaultChar->xmax_ = fontMetricsDst_->fontBBoxXMax_;
127 defaultChar->ymax_ = fontMetricsDst_->fontBBoxYMax_;
128 if( horizontalMetrics_typed_->isFixedPitch_ )
130 defaultChar->horizontalCharWidthX_ = horizontalMetrics_typed_->charWidthX_;
131 defaultChar->horizontalCharWidthY_ = horizontalMetrics_typed_->charWidthY_;
135 defaultChar->horizontalCharWidthX_ = defaultChar->xmax_;
136 defaultChar->horizontalCharWidthY_ = defaultChar->ymax_;
139 if( fontMetricsDst_->verticalMetrics_ != NullPtr< FontMetrics::WritingDirectionMetrics >( ) )
141 // I const cast because I'm too tired to thing of something better.
142 FontMetrics::CharacterMetrics * defaultChar = const_cast< FontMetrics::CharacterMetrics * >( verticalMetrics_typed_->charData_[ 0 ] );
143 defaultChar->xmin_ = fontMetricsDst_->fontBBoxXMin_;
144 defaultChar->ymin_ = fontMetricsDst_->fontBBoxYMin_;
145 defaultChar->xmax_ = fontMetricsDst_->fontBBoxXMax_;
146 defaultChar->ymax_ = fontMetricsDst_->fontBBoxYMax_;
147 if( verticalMetrics_typed_->isFixedPitch_ )
149 defaultChar->verticalCharWidthX_ = verticalMetrics_typed_->charWidthX_;
150 defaultChar->verticalCharWidthY_ = verticalMetrics_typed_->charWidthY_;
154 defaultChar->verticalCharWidthX_ = defaultChar->xmax_;
155 defaultChar->verticalCharWidthY_ = defaultChar->ymax_;
161 <FinishGlobalLine>{HorizontalWhiteSpace}[\n] {
162 // Skip to next line.
165 <Global>^{HorizontalWhiteSpace} {
166 // Ignore leading whitespace.
169 <ExpectEOF>{HorizontalWhiteSpace}[\n] {
177 throwError( "Expected EOF." );
180 <Global>"MetricsSets"{HorizontalWhiteSpace} {
181 BEGIN( MetricsSets );
183 <MetricsSets>{Integer} {
185 long int tmp = strtol( yytext, & endp, 10 );
186 if( tmp < 0 || tmp > 2 )
188 throwError( "MetricsSets out of range." );
191 BEGIN( FinishGlobalLine );
194 <Global>"FontName"{HorizontalWhiteSpace} {
198 fontMetricsDst_->fontName_ = strrefdup( yytext );
199 BEGIN( FinishGlobalLine );
202 <Global>"FullName"{HorizontalWhiteSpace} {
206 fontMetricsDst_->fullName_ = strrefdup( yytext );
207 BEGIN( FinishGlobalLine );
210 <Global>"FamilyName"{HorizontalWhiteSpace} {
213 <FamilyName>{String} {
214 fontMetricsDst_->familyName_ = strrefdup( yytext );
215 BEGIN( FinishGlobalLine );
218 <Global>"Weight"{HorizontalWhiteSpace} {
222 fontMetricsDst_->weight_ = strrefdup( yytext );
223 BEGIN( FinishGlobalLine );
226 <Global>"FontBBox"{HorizontalWhiteSpace} {
229 <FontBBox>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number} {
232 fontMetricsDst_->fontBBoxXMin_ = 0.001 * strtod( src, & endp );
234 fontMetricsDst_->fontBBoxYMin_ = 0.001 * strtod( src, & endp );
236 fontMetricsDst_->fontBBoxXMax_ = 0.001 * strtod( src, & endp );
238 fontMetricsDst_->fontBBoxYMax_ = 0.001 * strtod( src, & endp );
239 BEGIN( FinishGlobalLine );
242 <Global>"Version"{HorizontalWhiteSpace} {
246 fontMetricsDst_->version_ = strrefdup( yytext );
247 BEGIN( FinishGlobalLine );
250 <Global>"Notice"{HorizontalWhiteSpace} {
254 fontMetricsDst_->notice_ = strrefdup( yytext );
255 BEGIN( FinishGlobalLine );
258 <Global>"EncodingScheme"{HorizontalWhiteSpace} {
259 BEGIN( EncodingScheme );
261 <EncodingScheme>{String} {
262 fontMetricsDst_->encodingScheme_ = strrefdup( yytext );
263 BEGIN( FinishGlobalLine );
266 <Global>"CharacterSet"{HorizontalWhiteSpace} {
267 BEGIN( CharacterSet );
269 <CharacterSet>{String} {
270 fontMetricsDst_->characterSet_ = strrefdup( yytext );
271 BEGIN( FinishGlobalLine );
274 <Global>"Characters"{HorizontalWhiteSpace} {
277 <Characters>{Integer} {
279 fontMetricsDst_->charCount_ = strtol( yytext, & endp, 10 );
280 BEGIN( FinishGlobalLine );
283 <Global>"IsBaseFont"{HorizontalWhiteSpace} {
286 <IsBaseFont>{Boolean} {
287 if( yytext[ 0 ] != 't' )
289 throwError( "Expected \"IsBaseFont true\"." );
291 BEGIN( FinishGlobalLine );
294 <Global>"VVector"{HorizontalWhiteSpace} {
297 <FontBBox>{Number}{HorizontalWhiteSpace}{Number} {
300 fontMetricsDst_->vVectorX_ = 0.001 * strtod( src, & endp );
302 fontMetricsDst_->vVectorY_ = 0.001 * strtod( src, & endp );
303 fontMetricsDst_->isFixedV_ = true;
304 BEGIN( FinishGlobalLine );
307 <Global>"IsFixedV"{HorizontalWhiteSpace} {
310 <IsFixedV>{Boolean} {
311 fontMetricsDst_->isFixedV_ = yytext[0] == 't';
312 BEGIN( FinishGlobalLine );
315 <Global>"IsCIDFont"{HorizontalWhiteSpace} {
318 <IsCIDFont>{Boolean} {
319 fontMetricsDst_->isCIDFont_ = yytext[0] == 't';
320 BEGIN( FinishGlobalLine );
323 <Global>"CapHeight"{HorizontalWhiteSpace} {
326 <CapHeight>{Number} {
328 fontMetricsDst_->capHeight_ = 0.001 * strtod( yytext, & endp );
329 BEGIN( FinishGlobalLine );
332 <Global>"XHeight"{HorizontalWhiteSpace} {
337 fontMetricsDst_->xHeight_ = 0.001 * strtod( yytext, & endp );
338 BEGIN( FinishGlobalLine );
341 <Global>"Ascender"{HorizontalWhiteSpace} {
346 fontMetricsDst_->ascender_ = 0.001 * strtod( yytext, & endp );
347 BEGIN( FinishGlobalLine );
350 <Global>"Descender"{HorizontalWhiteSpace} {
353 <Descender>{Number} {
355 fontMetricsDst_->descender_ = 0.001 * strtod( yytext, & endp );
356 BEGIN( FinishGlobalLine );
359 <Global>"StdHW"{HorizontalWhiteSpace} {
364 fontMetricsDst_->stdHW_ = 0.001 * strtod( yytext, & endp );
365 BEGIN( FinishGlobalLine );
368 <Global>"StdVW"{HorizontalWhiteSpace} {
373 fontMetricsDst_->stdVW_ = 0.001 * strtod( yytext, & endp );
374 BEGIN( FinishGlobalLine );
378 <Global>"StartDirection"{HorizontalWhiteSpace} {
379 BEGIN( StartDirection );
381 <StartDirection>{Integer} {
383 long int tmp = strtol( yytext, & endp, 10 );
384 if( tmp < 0 || tmp > 2 )
386 throwError( "StartDirection out of range." );
388 activateDirectionID_ = tmp;
389 BEGIN( FinishGlobalLine );
392 <Global>"EndDirection"{HorizontalWhiteSpace} {
393 activateDirectionID_ = 0; // This is probably not necessary.
394 BEGIN( FinishGlobalLine );
397 <Global>"UnderlinePosition"{HorizontalWhiteSpace} {
398 BEGIN( UnderlinePosition );
400 <UnderlinePosition>{Number} {
401 synchWritingDirection( );
403 currentDirectionDst_->underlinePosition_ = 0.001 * strtod( yytext, & endp );
404 BEGIN( FinishGlobalLine );
407 <Global>"UnderlineThickness"{HorizontalWhiteSpace} {
408 BEGIN( UnderlineThickness );
410 <UnderlineThickness>{Number} {
411 synchWritingDirection( );
413 currentDirectionDst_->underlineThickness_ = 0.001 * strtod( yytext, & endp );
414 BEGIN( FinishGlobalLine );
417 <Global>"ItalicAngle"{HorizontalWhiteSpace} {
418 BEGIN( ItalicAngle );
420 <ItalicAngle>{Number} {
421 synchWritingDirection( );
423 currentDirectionDst_->italicAngleRadians_ = strtod( yytext, & endp ) * ( M_PI / 180 ); // Note: Don't scale by 0.001!
424 BEGIN( FinishGlobalLine );
427 <Global>"CharWidth"{HorizontalWhiteSpace} {
430 <CharWidth>{Number}{HorizontalWhiteSpace}{Number} {
431 synchWritingDirection( );
434 currentDirectionDst_->charWidthX_ = 0.001 * strtod( yytext, & endp );
436 currentDirectionDst_->charWidthY_ = 0.001 * strtod( yytext, & endp );
437 BEGIN( FinishGlobalLine );
440 <Global>"IsFixedPitch"{HorizontalWhiteSpace} {
441 BEGIN( IsFixedPitch );
443 <IsFixedPitch>{Boolean} {
444 synchWritingDirection( );
445 currentDirectionDst_->isFixedPitch_ = yytext[0] == 't';
446 BEGIN( FinishGlobalLine );
449 <Global>"StartCharMetrics"{HorizontalWhiteSpace} {
450 BEGIN( StartCharMetrics );
452 <StartCharMetrics>{Integer}{HorizontalWhiteSpace}[\n] {
453 synchWritingDirection( );
454 if( currentDirectionDst_->charData_.size( ) > 1 ) // the first entry is the default values
456 throwError( "Multiply specified character metrics in this writing direction." );
459 long int tmp = strtol( yytext, & endp, 10 );
460 currentDirectionDst_->charData_.reserve( tmp + 1 ); // the first entry is the default values
461 currentCharacter_ = new FontMetrics::CharacterMetrics( currentDirectionDst_->charData_.size( ) );
462 BEGIN( CharMetrics );
465 <CharMetrics>"EndCharMetrics" {
466 delete currentCharacter_;
467 BEGIN( FinishGlobalLine );
474 currentDirectionDst_->charData_.push_back( currentCharacter_ );
475 currentCharacter_ = new FontMetrics::CharacterMetrics( currentDirectionDst_->charData_.size( ) );
478 <CharMetrics>^{HorizontalWhiteSpace}[\n] {
479 // A newline at the end of an empty line does not insert the current character.
481 <CharMetrics>{HorizontalWhiteSpace} {
485 <CharMetrics>"C"{HorizontalWhiteSpace} {
488 <C>{Integer}{HorizontalWhiteSpace}[;] {
490 currentCharacter_->characterCode_ = strtol( yytext, & endp, 10 );
491 if( currentCharacter_->characterCode_ >= 0 )
493 currentDirectionDst_->codeMap_[ currentCharacter_->characterCode_ ] = currentCharacter_->internalPosition_;
495 BEGIN( CharMetrics );
498 <CharMetrics>"CH"{HorizontalWhiteSpace} {
501 <CH>{HexInteger}{HorizontalWhiteSpace}[;] {
503 currentCharacter_->characterCode_ = strtol( yytext, & endp, 16 );
504 if( currentCharacter_->characterCode_ >= 0 )
506 currentDirectionDst_->codeMap_[ currentCharacter_->characterCode_ ] = currentCharacter_->internalPosition_;
508 BEGIN( CharMetrics );
511 <CharMetrics>("WX"|"W0X"){HorizontalWhiteSpace} {
514 <W0X>{Number}{HorizontalWhiteSpace}[;] {
516 currentCharacter_->horizontalCharWidthX_ = 0.001 * strtod( yytext, & endp );
517 BEGIN( CharMetrics );
520 <CharMetrics>("WY"|"W0Y"){HorizontalWhiteSpace} {
523 <W0Y>{Number}{HorizontalWhiteSpace}[;] {
525 currentCharacter_->horizontalCharWidthY_ = 0.001 * strtod( yytext, & endp );
526 BEGIN( CharMetrics );
529 <CharMetrics>"W1X"{HorizontalWhiteSpace} {
532 <W1X>{Number}{HorizontalWhiteSpace}[;] {
534 currentCharacter_->verticalCharWidthX_ = 0.001 * strtod( yytext, & endp );
535 BEGIN( CharMetrics );
538 <CharMetrics>"W1Y"{HorizontalWhiteSpace} {
541 <W1Y>{Number}{HorizontalWhiteSpace}[;] {
543 currentCharacter_->verticalCharWidthY_ = 0.001 * strtod( yytext, & endp );
544 BEGIN( CharMetrics );
547 <CharMetrics>"W0"{HorizontalWhiteSpace} {
550 <W0>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
553 currentCharacter_->horizontalCharWidthX_ = 0.001 * strtod( src, & endp );
555 currentCharacter_->horizontalCharWidthY_ = 0.001 * strtod( src, & endp );
556 BEGIN( CharMetrics );
559 <CharMetrics>"W1"{HorizontalWhiteSpace} {
562 <W1>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
565 currentCharacter_->verticalCharWidthX_ = 0.001 * strtod( src, & endp );
567 currentCharacter_->verticalCharWidthY_ = 0.001 * strtod( src, & endp );
568 BEGIN( CharMetrics );
571 <CharMetrics>"VV"{HorizontalWhiteSpace} {
574 <VV>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
577 currentCharacter_->vX_ = 0.001 * strtod( src, & endp );
579 currentCharacter_->vY_ = 0.001 * strtod( src, & endp );
580 BEGIN( CharMetrics );
583 <CharMetrics>"N"{HorizontalWhiteSpace} {
586 <N>{Name}{HorizontalWhiteSpace}[;] {
588 for( ; *end != ' ' && *end != '\t' && *end != ';'; ++end )
591 currentDirectionDst_->nameMap_[ strrefdup( yytext ) ] = currentCharacter_->internalPosition_;
592 if( currentCharacter_->characterCode_ < 0 )
595 if( encoding_->name_to_position( yytext, & pos ) )
597 currentCharacter_->characterCode_ = pos;
598 currentDirectionDst_->codeMap_[ currentCharacter_->characterCode_ ] = currentCharacter_->internalPosition_;
602 BEGIN( CharMetrics );
605 <CharMetrics>"B"{HorizontalWhiteSpace} {
608 <B>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
611 currentCharacter_->xmin_ = 0.001 * strtod( src, & endp );
613 currentCharacter_->ymin_ = 0.001 * strtod( src, & endp );
615 currentCharacter_->xmax_ = 0.001 * strtod( src, & endp );
617 currentCharacter_->ymax_ = 0.001 * strtod( src, & endp );
618 BEGIN( CharMetrics );
621 <CharMetrics>"L"{HorizontalWhiteSpace} {
624 <L>{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}[;] {
626 const char * begin1 = strtoname( yytext, & end1, " \t", 2 );
628 const char * begin2 = strtoname( end1, & end2, " ;\t", 3 );
630 currentCharacter_->addLigature( strrefdup( begin1 ), strrefdup( begin2 ) );
631 BEGIN( CharMetrics );
634 <Global>"StartKernData"{HorizontalWhiteSpace}[\n] {
637 <KernData>"EndKernData"{HorizontalWhiteSpace} {
638 BEGIN( FinishGlobalLine );
640 <KernData>"StartKernPairs"([0]?){HorizontalWhiteSpace} {
641 currentKernPairMapX_ = & fontMetricsDst_->horizontalKernPairsX_;
642 currentKernPairMapY_ = & fontMetricsDst_->horizontalKernPairsY_;
643 if( horizontalMetrics_typed_ == NullPtr< FontMetrics::SingleByte_WritingDirectionMetrics >( ) )
645 throw "It would be nice if the character metrics appeared before the kern pairs.";
647 currentNameMap_ = & horizontalMetrics_typed_->nameMap_;
648 BEGIN( StartKernPairs );
650 <KernData>"StartKernPairs1"{HorizontalWhiteSpace} {
651 currentKernPairMapX_ = & fontMetricsDst_->verticalKernPairsX_;
652 currentKernPairMapY_ = & fontMetricsDst_->verticalKernPairsY_;
653 if( verticalMetrics_typed_ == NullPtr< FontMetrics::SingleByte_WritingDirectionMetrics >( ) )
655 throw "It would be nice if the character metrics appeared before the kern pairs.";
657 currentNameMap_ = & verticalMetrics_typed_->nameMap_;
658 BEGIN( StartKernPairs );
660 <StartKernPairs>{Integer}{HorizontalWhiteSpace}[\n] {
661 // The number of pairs is not used.
664 <KernPairs>"EndKernPairs"{HorizontalWhiteSpace}[\n] {
667 <KernData>"StartTrackKern"{HorizontalWhiteSpace} {
668 BEGIN( StartTrackKern );
670 <StartTrackKern>{Integer}{HorizontalWhiteSpace}[\n] {
671 // The number of entries is not used.
674 <TrackKern>"EndTrackKern"{HorizontalWhiteSpace}[\n] {
678 <KernPairs>"KP"{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
679 char * src = yytext + 2;
681 const char * name1 = strtoname( src, & end, " \t", 2 );
683 const char * name2 = strtoname( src, & end, " \t", 2 );
685 double x = 0.001 * strtod( src, & end );
687 double y = 0.001 * strtod( src, & end );
688 /* The code commented out below was using a name map local to the writing direction. I cannot see the point of
689 * keeping the name map local to the writing direction, and it makes conversion to a Unicode code point more difficult.
690 * I keep the old code as a reminder of what the code used to look like back in the days when the kern pairs
691 * were indexed using the MacRoman encoding. Now, we use Unicode code points instead.
693 // typedef typeof *currentNameMap_ NameMapType;
694 // NameMapType::const_iterator i1 = currentNameMap_->find( strrefdup( name1 ) );
695 // if( i1 == currentNameMap_->end( ) )
697 // throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
699 // NameMapType::const_iterator i2 = currentNameMap_->find( strrefdup( name2 ) );
700 // if( i2 == currentNameMap_->end( ) )
702 // throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
705 typedef typeof *currentKernPairMapX_ MapType;
706 Shapes::Kernel::UnicodeCodePoint i1u;
707 i1u.decode_glyph_name( name1 );
708 Shapes::Kernel::UnicodeCodePoint i2u;
709 i2u.decode_glyph_name( name2 );
710 (*currentKernPairMapX_)[ MapType::key_type( i1u, i2u ) ] = x;
711 (*currentKernPairMapY_)[ MapType::key_type( i1u, i2u ) ] = y;
715 <KernPairs>"KPH"{HorizontalWhiteSpace}"<"{Name}">"{HorizontalWhiteSpace}"<"{Name}">"{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
716 // char * src = yytext + 3;
718 throw "Kern pairs with hexadecimal names are not understood.";
721 <KernPairs>"KPX"{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
722 char * src = yytext + 3;
724 const char * name1 = strtoname( src, & end, " \t", 2 );
726 const char * name2 = strtoname( src, & end, " \t", 2 );
728 double x = 0.001 * strtod( src, & end );
729 /* See comment for "KP". */
730 // typedef typeof *currentNameMap_ NameMapType;
731 // NameMapType::const_iterator i1 = currentNameMap_->find( strrefdup( name1 ) );
732 // if( i1 == currentNameMap_->end( ) )
734 // throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
736 // NameMapType::const_iterator i2 = currentNameMap_->find( strrefdup( name2 ) );
737 // if( i2 == currentNameMap_->end( ) )
739 // throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
741 // (*currentKernPairMapX_)[ std::pair< size_t, size_t >( i1->second, i2->second ) ] = x;
743 typedef typeof *currentKernPairMapX_ MapType;
744 Shapes::Kernel::UnicodeCodePoint i1u;
745 i1u.decode_glyph_name( name1 );
746 Shapes::Kernel::UnicodeCodePoint i2u;
747 i2u.decode_glyph_name( name2 );
748 (*currentKernPairMapX_)[ MapType::key_type( i1u, i2u ) ] = x;
752 <KernPairs>"KPY"{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
753 char * src = yytext + 3;
755 const char * name1 = strtoname( src, & end, " \t", 2 );
757 const char * name2 = strtoname( src, & end, " \t", 2 );
759 double y = 0.001 * strtod( src, & end );
760 /* See comment for "KP". */
761 // typedef typeof *currentNameMap_ NameMapType;
762 // NameMapType::const_iterator i1 = currentNameMap_->find( strrefdup( name1 ) );
763 // if( i1 == currentNameMap_->end( ) )
765 // throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
767 // NameMapType::const_iterator i2 = currentNameMap_->find( strrefdup( name2 ) );
768 // if( i2 == currentNameMap_->end( ) )
770 // throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
772 // (*currentKernPairMapY_)[ std::pair< size_t, size_t >( i1->second, i2->second ) ] = y;
774 typedef typeof *currentKernPairMapX_ MapType;
775 Shapes::Kernel::UnicodeCodePoint i1u;
776 i1u.decode_glyph_name( name1 );
777 Shapes::Kernel::UnicodeCodePoint i2u;
778 i2u.decode_glyph_name( name2 );
779 (*currentKernPairMapY_)[ MapType::key_type( i1u, i2u ) ] = y;
784 <TrackKern>{HorizontalWhiteSpace}{Integer}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
787 int degree = strtol( src, & endp, 10 );
789 double sizeLow = strtod( src, & endp );
791 double trackLow = 0.001 * strtod( src, & endp );
793 double sizeHigh = strtod( src, & endp );
795 double trackHigh = 0.001 * strtod( src, & endp );
796 typedef typeof fontMetricsDst_->trackKernings_ MapType;
797 fontMetricsDst_->trackKernings_.insert( MapType::value_type( degree, RefCountPtr< FontMetrics::TrackKerning >( new FontMetrics::TrackKerning( sizeLow, trackLow, sizeHigh, trackHigh ) ) ) );
801 <*>^"Comment"{HorizontalWhiteSpace}.*[\n] {
806 // If we match the whole line here, it will be a _very_ good match for anything. Hence we do things in two steps.
809 std::cerr << "The afm parser was unable to understand the key \"" << yytext << "\", with data: " ;
814 // Ignore things we don't understand.
817 std::cerr << yytext << std::endl ;
819 BEGIN( FinishGlobalLine );
822 <*>. { throwError( "Unrecognized token." ); }
825 /* The closing %% above marks the end of the Rules section and the beginning
826 * of the User Subroutines section. All text from here to the end of the
827 * file is copied verbatim to the end of the generated lex.pdf.c file.
828 * This section is where you put definitions of helper functions.
832 strtoname( char * begin, char ** endp, const char * delim )
834 for( ; memchr( " \t", *begin, 2 ) != 0; ++begin )
838 for( ; strchr( delim, *end ) == 0; ++end )
847 strtoname( char * begin, char ** endp, const char * delim, size_t delimSize )
849 for( ; memchr( " \t", *begin, 2 ) != 0; ++begin )
853 for( ; memchr( delim, *end, delimSize ) == 0; ++end )