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 Henrik Tidefelt
23 #include "afmscanner.h"
24 #include "strrefdup.h"
25 #include "exitcodes.h"
30 #define YY_EXIT_FAILURE Shapes::Interaction::EXIT_INTERNAL_ERROR
32 // These functions must note be called with invalid arguments!
33 const char * strtoname( char * begin, char ** endp, const char * delim = " \t" );
34 const char * strtoname( char * begin, char ** endp, const char * delim, size_t delimSize );
36 /* The rule HorizontalWhiteSpace is not in agreement with the specification, as far as I can see,
37 * but it's the smallest change I can think of which should make this program work
38 * with DOS files as well as ordiary files.
43 HorizontalWhiteSpace [ \t\r]*
46 HexInteger [0-9A-Fa-f]+
48 Boolean "true"|"false"
50 Number [+-]?(([0-9]*[.][0-9]+)|([0-9]+))
59 %option yyclass="AfmScanner"
114 <INITIAL>"StartFontMetrics ".*[\n] {
118 <Global>"EndFontMetrics"{HorizontalWhiteSpace}[\n] {
119 if( fontMetricsDst_->horizontalMetrics_ != NullPtr< FontMetrics::WritingDirectionMetrics >( ) )
121 // I const cast because I'm too tired to think of something better.
122 FontMetrics::CharacterMetrics * defaultChar = const_cast< FontMetrics::CharacterMetrics * >( fontMetricsDst_->horizontalMetrics_->charData_[ 0 ] );
123 defaultChar->xmin_ = fontMetricsDst_->fontBBoxXMin_;
124 defaultChar->ymin_ = fontMetricsDst_->fontBBoxYMin_;
125 defaultChar->xmax_ = fontMetricsDst_->fontBBoxXMax_;
126 defaultChar->ymax_ = fontMetricsDst_->fontBBoxYMax_;
127 if( fontMetricsDst_->horizontalMetrics_->isFixedPitch_ )
129 defaultChar->horizontalCharWidthX_ = fontMetricsDst_->horizontalMetrics_->charWidthX_;
130 defaultChar->horizontalCharWidthY_ = fontMetricsDst_->horizontalMetrics_->charWidthY_;
134 defaultChar->horizontalCharWidthX_ = defaultChar->xmax_;
135 defaultChar->horizontalCharWidthY_ = defaultChar->ymax_;
138 if( fontMetricsDst_->verticalMetrics_ != NullPtr< FontMetrics::WritingDirectionMetrics >( ) )
140 // I const cast because I'm too tired to thing of something better.
141 FontMetrics::CharacterMetrics * defaultChar = const_cast< FontMetrics::CharacterMetrics * >( fontMetricsDst_->verticalMetrics_->charData_[ 0 ] );
142 defaultChar->xmin_ = fontMetricsDst_->fontBBoxXMin_;
143 defaultChar->ymin_ = fontMetricsDst_->fontBBoxYMin_;
144 defaultChar->xmax_ = fontMetricsDst_->fontBBoxXMax_;
145 defaultChar->ymax_ = fontMetricsDst_->fontBBoxYMax_;
146 if( fontMetricsDst_->verticalMetrics_->isFixedPitch_ )
148 defaultChar->verticalCharWidthX_ = fontMetricsDst_->verticalMetrics_->charWidthX_;
149 defaultChar->verticalCharWidthY_ = fontMetricsDst_->verticalMetrics_->charWidthY_;
153 defaultChar->verticalCharWidthX_ = defaultChar->xmax_;
154 defaultChar->verticalCharWidthY_ = defaultChar->ymax_;
160 <FinishGlobalLine>{HorizontalWhiteSpace}[\n] {
161 // Skip to next line.
164 <Global>^{HorizontalWhiteSpace} {
165 // Ignore leading whitespace.
168 <ExpectEOF>{HorizontalWhiteSpace}[\n] {
176 throwError( "Expected EOF." );
179 <Global>"MetricsSets"{HorizontalWhiteSpace} {
180 BEGIN( MetricsSets );
182 <MetricsSets>{Integer} {
184 long int tmp = strtol( yytext, & endp, 10 );
185 if( tmp < 0 || tmp > 2 )
187 throwError( "MetricsSets out of range." );
190 BEGIN( FinishGlobalLine );
193 <Global>"FontName"{HorizontalWhiteSpace} {
197 fontMetricsDst_->fontName_ = strrefdup( yytext );
198 BEGIN( FinishGlobalLine );
201 <Global>"FullName"{HorizontalWhiteSpace} {
205 fontMetricsDst_->fullName_ = strrefdup( yytext );
206 BEGIN( FinishGlobalLine );
209 <Global>"FamilyName"{HorizontalWhiteSpace} {
212 <FamilyName>{String} {
213 fontMetricsDst_->familyName_ = strrefdup( yytext );
214 BEGIN( FinishGlobalLine );
217 <Global>"Weight"{HorizontalWhiteSpace} {
221 fontMetricsDst_->weight_ = strrefdup( yytext );
222 BEGIN( FinishGlobalLine );
225 <Global>"FontBBox"{HorizontalWhiteSpace} {
228 <FontBBox>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number} {
231 fontMetricsDst_->fontBBoxXMin_ = 0.001 * strtod( src, & endp );
233 fontMetricsDst_->fontBBoxYMin_ = 0.001 * strtod( src, & endp );
235 fontMetricsDst_->fontBBoxXMax_ = 0.001 * strtod( src, & endp );
237 fontMetricsDst_->fontBBoxYMax_ = 0.001 * strtod( src, & endp );
238 BEGIN( FinishGlobalLine );
241 <Global>"Version"{HorizontalWhiteSpace} {
245 fontMetricsDst_->version_ = strrefdup( yytext );
246 BEGIN( FinishGlobalLine );
249 <Global>"Notice"{HorizontalWhiteSpace} {
253 fontMetricsDst_->notice_ = strrefdup( yytext );
254 BEGIN( FinishGlobalLine );
257 <Global>"EncodingScheme"{HorizontalWhiteSpace} {
258 BEGIN( EncodingScheme );
260 <EncodingScheme>{String} {
261 fontMetricsDst_->encodingScheme_ = strrefdup( yytext );
262 BEGIN( FinishGlobalLine );
265 <Global>"CharacterSet"{HorizontalWhiteSpace} {
266 BEGIN( CharacterSet );
268 <CharacterSet>{String} {
269 fontMetricsDst_->characterSet_ = strrefdup( yytext );
270 BEGIN( FinishGlobalLine );
273 <Global>"Characters"{HorizontalWhiteSpace} {
276 <Characters>{Integer} {
278 fontMetricsDst_->charCount_ = strtol( yytext, & endp, 10 );
279 BEGIN( FinishGlobalLine );
282 <Global>"IsBaseFont"{HorizontalWhiteSpace} {
285 <IsBaseFont>{Boolean} {
286 if( yytext[ 0 ] != 't' )
288 throwError( "Expected \"IsBaseFont true\"." );
290 BEGIN( FinishGlobalLine );
293 <Global>"VVector"{HorizontalWhiteSpace} {
296 <FontBBox>{Number}{HorizontalWhiteSpace}{Number} {
299 fontMetricsDst_->vVectorX_ = 0.001 * strtod( src, & endp );
301 fontMetricsDst_->vVectorY_ = 0.001 * strtod( src, & endp );
302 fontMetricsDst_->isFixedV_ = true;
303 BEGIN( FinishGlobalLine );
306 <Global>"IsFixedV"{HorizontalWhiteSpace} {
309 <IsFixedV>{Boolean} {
310 fontMetricsDst_->isFixedV_ = yytext[0] == 't';
311 BEGIN( FinishGlobalLine );
314 <Global>"IsCIDFont"{HorizontalWhiteSpace} {
317 <IsCIDFont>{Boolean} {
318 fontMetricsDst_->isCIDFont_ = yytext[0] == 't';
319 BEGIN( FinishGlobalLine );
322 <Global>"CapHeight"{HorizontalWhiteSpace} {
325 <CapHeight>{Number} {
327 fontMetricsDst_->capHeight_ = 0.001 * strtod( yytext, & endp );
328 BEGIN( FinishGlobalLine );
331 <Global>"XHeight"{HorizontalWhiteSpace} {
336 fontMetricsDst_->xHeight_ = 0.001 * strtod( yytext, & endp );
337 BEGIN( FinishGlobalLine );
340 <Global>"Ascender"{HorizontalWhiteSpace} {
345 fontMetricsDst_->ascender_ = 0.001 * strtod( yytext, & endp );
346 BEGIN( FinishGlobalLine );
349 <Global>"Descender"{HorizontalWhiteSpace} {
352 <Descender>{Number} {
354 fontMetricsDst_->descender_ = 0.001 * strtod( yytext, & endp );
355 BEGIN( FinishGlobalLine );
358 <Global>"StdHW"{HorizontalWhiteSpace} {
363 fontMetricsDst_->stdHW_ = 0.001 * strtod( yytext, & endp );
364 BEGIN( FinishGlobalLine );
367 <Global>"StdVW"{HorizontalWhiteSpace} {
372 fontMetricsDst_->stdVW_ = 0.001 * strtod( yytext, & endp );
373 BEGIN( FinishGlobalLine );
377 <Global>"StartDirection"{HorizontalWhiteSpace} {
378 BEGIN( StartDirection );
380 <StartDirection>{Integer} {
382 long int tmp = strtol( yytext, & endp, 10 );
383 if( tmp < 0 || tmp > 2 )
385 throwError( "StartDirection out of range." );
387 activateDirectionID_ = tmp;
388 BEGIN( FinishGlobalLine );
391 <Global>"EndDirection"{HorizontalWhiteSpace} {
392 activateDirectionID_ = 0; // This is probably not necessary.
393 BEGIN( FinishGlobalLine );
396 <Global>"UnderlinePosition"{HorizontalWhiteSpace} {
397 BEGIN( UnderlinePosition );
399 <UnderlinePosition>{Number} {
400 synchWritingDirection( );
402 currentDirectionDst_->underlinePosition_ = 0.001 * strtod( yytext, & endp );
403 BEGIN( FinishGlobalLine );
406 <Global>"UnderlineThickness"{HorizontalWhiteSpace} {
407 BEGIN( UnderlineThickness );
409 <UnderlineThickness>{Number} {
410 synchWritingDirection( );
412 currentDirectionDst_->underlineThickness_ = 0.001 * strtod( yytext, & endp );
413 BEGIN( FinishGlobalLine );
416 <Global>"ItalicAngle"{HorizontalWhiteSpace} {
417 BEGIN( ItalicAngle );
419 <ItalicAngle>{Number} {
420 synchWritingDirection( );
422 currentDirectionDst_->italicAngleRadians_ = strtod( yytext, & endp ) * ( M_PI / 180 ); // Note: Don't scale by 0.001!
423 BEGIN( FinishGlobalLine );
426 <Global>"CharWidth"{HorizontalWhiteSpace} {
429 <CharWidth>{Number}{HorizontalWhiteSpace}{Number} {
430 synchWritingDirection( );
433 currentDirectionDst_->charWidthX_ = 0.001 * strtod( yytext, & endp );
435 currentDirectionDst_->charWidthY_ = 0.001 * strtod( yytext, & endp );
436 BEGIN( FinishGlobalLine );
439 <Global>"IsFixedPitch"{HorizontalWhiteSpace} {
440 BEGIN( IsFixedPitch );
442 <IsFixedPitch>{Boolean} {
443 synchWritingDirection( );
444 currentDirectionDst_->isFixedPitch_ = yytext[0] == 't';
445 BEGIN( FinishGlobalLine );
448 <Global>"StartCharMetrics"{HorizontalWhiteSpace} {
449 BEGIN( StartCharMetrics );
451 <StartCharMetrics>{Integer}{HorizontalWhiteSpace}[\n] {
452 synchWritingDirection( );
453 if( currentDirectionDst_->charData_.size( ) > 1 ) // the first entry is the default values
455 throwError( "Multiply specified character metrics in this writing direction." );
458 long int tmp = strtol( yytext, & endp, 10 );
459 currentDirectionDst_->charData_.reserve( tmp + 1 ); // the first entry is the default values
460 currentCharacter_ = new FontMetrics::CharacterMetrics( currentDirectionDst_->charData_.size( ) );
461 BEGIN( CharMetrics );
464 <CharMetrics>"EndCharMetrics" {
465 delete currentCharacter_;
466 BEGIN( FinishGlobalLine );
473 currentDirectionDst_->charData_.push_back( currentCharacter_ );
474 currentCharacter_ = new FontMetrics::CharacterMetrics( currentDirectionDst_->charData_.size( ) );
477 <CharMetrics>^{HorizontalWhiteSpace}[\n] {
478 // A newline at the end of an empty line does not insert the current character.
480 <CharMetrics>{HorizontalWhiteSpace} {
484 <CharMetrics>"C"{HorizontalWhiteSpace} {
487 <C>{Integer}{HorizontalWhiteSpace}[;] {
489 currentCharacter_->characterCode_ = strtol( yytext, & endp, 10 );
490 if( currentCharacter_->characterCode_ >= 0 )
492 currentDirectionDst_->codeMap_[ currentCharacter_->characterCode_ ] = currentCharacter_->internalPosition_;
494 BEGIN( CharMetrics );
497 <CharMetrics>"CH"{HorizontalWhiteSpace} {
500 <CH>{HexInteger}{HorizontalWhiteSpace}[;] {
502 currentCharacter_->characterCode_ = strtol( yytext, & endp, 16 );
503 if( currentCharacter_->characterCode_ >= 0 )
505 currentDirectionDst_->codeMap_[ currentCharacter_->characterCode_ ] = currentCharacter_->internalPosition_;
507 BEGIN( CharMetrics );
510 <CharMetrics>("WX"|"W0X"){HorizontalWhiteSpace} {
513 <W0X>{Number}{HorizontalWhiteSpace}[;] {
515 currentCharacter_->horizontalCharWidthX_ = 0.001 * strtod( yytext, & endp );
516 BEGIN( CharMetrics );
519 <CharMetrics>("WY"|"W0Y"){HorizontalWhiteSpace} {
522 <W0Y>{Number}{HorizontalWhiteSpace}[;] {
524 currentCharacter_->horizontalCharWidthY_ = 0.001 * strtod( yytext, & endp );
525 BEGIN( CharMetrics );
528 <CharMetrics>"W1X"{HorizontalWhiteSpace} {
531 <W1X>{Number}{HorizontalWhiteSpace}[;] {
533 currentCharacter_->verticalCharWidthX_ = 0.001 * strtod( yytext, & endp );
534 BEGIN( CharMetrics );
537 <CharMetrics>"W1Y"{HorizontalWhiteSpace} {
540 <W1Y>{Number}{HorizontalWhiteSpace}[;] {
542 currentCharacter_->verticalCharWidthY_ = 0.001 * strtod( yytext, & endp );
543 BEGIN( CharMetrics );
546 <CharMetrics>"W0"{HorizontalWhiteSpace} {
549 <W0>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
552 currentCharacter_->horizontalCharWidthX_ = 0.001 * strtod( src, & endp );
554 currentCharacter_->horizontalCharWidthY_ = 0.001 * strtod( src, & endp );
555 BEGIN( CharMetrics );
558 <CharMetrics>"W1"{HorizontalWhiteSpace} {
561 <W1>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
564 currentCharacter_->verticalCharWidthX_ = 0.001 * strtod( src, & endp );
566 currentCharacter_->verticalCharWidthY_ = 0.001 * strtod( src, & endp );
567 BEGIN( CharMetrics );
570 <CharMetrics>"VV"{HorizontalWhiteSpace} {
573 <VV>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
576 currentCharacter_->vX_ = 0.001 * strtod( src, & endp );
578 currentCharacter_->vY_ = 0.001 * strtod( src, & endp );
579 BEGIN( CharMetrics );
582 <CharMetrics>"N"{HorizontalWhiteSpace} {
585 <N>{Name}{HorizontalWhiteSpace}[;] {
587 for( ; *end != ' ' && *end != '\t' && *end != ';'; ++end )
590 currentDirectionDst_->nameMap_[ strrefdup( yytext ) ] = currentCharacter_->internalPosition_;
591 if( currentCharacter_->characterCode_ < 0 )
594 if( encoding_->name_to_position( yytext, & pos ) )
596 currentCharacter_->characterCode_ = pos;
597 currentDirectionDst_->codeMap_[ currentCharacter_->characterCode_ ] = currentCharacter_->internalPosition_;
601 BEGIN( CharMetrics );
604 <CharMetrics>"B"{HorizontalWhiteSpace} {
607 <B>{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[;] {
610 currentCharacter_->xmin_ = 0.001 * strtod( src, & endp );
612 currentCharacter_->ymin_ = 0.001 * strtod( src, & endp );
614 currentCharacter_->xmax_ = 0.001 * strtod( src, & endp );
616 currentCharacter_->ymax_ = 0.001 * strtod( src, & endp );
617 BEGIN( CharMetrics );
620 <CharMetrics>"L"{HorizontalWhiteSpace} {
623 <L>{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}[;] {
625 const char * begin1 = strtoname( yytext, & end1, " \t", 2 );
627 const char * begin2 = strtoname( end1, & end2, " ;\t", 3 );
629 currentCharacter_->addLigature( strrefdup( begin1 ), strrefdup( begin2 ) );
630 BEGIN( CharMetrics );
633 <Global>"StartKernData"{HorizontalWhiteSpace}[\n] {
636 <KernData>"EndKernData"{HorizontalWhiteSpace} {
637 BEGIN( FinishGlobalLine );
639 <KernData>"StartKernPairs"([0]?){HorizontalWhiteSpace} {
640 currentKernPairMapX_ = & fontMetricsDst_->horizontalKernPairsX_;
641 currentKernPairMapY_ = & fontMetricsDst_->horizontalKernPairsY_;
642 if( fontMetricsDst_->horizontalMetrics_ == NullPtr< FontMetrics::WritingDirectionMetrics >( ) )
644 throw "It would be nice if the character metrics appeared before the kern pairs.";
646 currentNameMap_ = & fontMetricsDst_->horizontalMetrics_->nameMap_;
647 BEGIN( StartKernPairs );
649 <KernData>"StartKernPairs1"{HorizontalWhiteSpace} {
650 currentKernPairMapX_ = & fontMetricsDst_->verticalKernPairsX_;
651 currentKernPairMapY_ = & fontMetricsDst_->verticalKernPairsY_;
652 if( fontMetricsDst_->verticalMetrics_ == NullPtr< FontMetrics::WritingDirectionMetrics >( ) )
654 throw "It would be nice if the character metrics appeared before the kern pairs.";
656 currentNameMap_ = & fontMetricsDst_->verticalMetrics_->nameMap_;
657 BEGIN( StartKernPairs );
659 <StartKernPairs>{Integer}{HorizontalWhiteSpace}[\n] {
660 // The number of pairs is not used.
663 <KernPairs>"EndKernPairs"{HorizontalWhiteSpace}[\n] {
666 <KernData>"StartTrackKern"{HorizontalWhiteSpace} {
667 BEGIN( StartTrackKern );
669 <StartTrackKern>{Integer}{HorizontalWhiteSpace}[\n] {
670 // The number of entries is not used.
673 <TrackKern>"EndTrackKern"{HorizontalWhiteSpace}[\n] {
677 <KernPairs>"KP"{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
678 char * src = yytext + 2;
680 const char * name1 = strtoname( src, & end, " \t", 2 );
682 const char * name2 = strtoname( src, & end, " \t", 2 );
684 double x = 0.001 * strtod( src, & end );
686 double y = 0.001 * strtod( src, & end );
687 typedef typeof *currentNameMap_ NameMapType;
688 NameMapType::const_iterator i1 = currentNameMap_->find( strrefdup( name1 ) );
689 if( i1 == currentNameMap_->end( ) )
691 throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
693 NameMapType::const_iterator i2 = currentNameMap_->find( strrefdup( name2 ) );
694 if( i2 == currentNameMap_->end( ) )
696 throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
698 (*currentKernPairMapX_)[ std::pair< size_t, size_t >( i1->second, i2->second ) ] = x;
699 (*currentKernPairMapY_)[ std::pair< size_t, size_t >( i1->second, i2->second ) ] = y;
702 <KernPairs>"KPH"{HorizontalWhiteSpace}"<"{Name}">"{HorizontalWhiteSpace}"<"{Name}">"{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
703 // char * src = yytext + 3;
705 throw "Kern pairs with hexadecimal names are not understood.";
708 <KernPairs>"KPX"{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
709 char * src = yytext + 3;
711 const char * name1 = strtoname( src, & end, " \t", 2 );
713 const char * name2 = strtoname( src, & end, " \t", 2 );
715 double x = 0.001 * strtod( src, & end );
716 typedef typeof *currentNameMap_ NameMapType;
717 NameMapType::const_iterator i1 = currentNameMap_->find( strrefdup( name1 ) );
718 if( i1 == currentNameMap_->end( ) )
720 throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
722 NameMapType::const_iterator i2 = currentNameMap_->find( strrefdup( name2 ) );
723 if( i2 == currentNameMap_->end( ) )
725 throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
727 (*currentKernPairMapX_)[ std::pair< size_t, size_t >( i1->second, i2->second ) ] = x;
730 <KernPairs>"KPY"{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Name}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
731 char * src = yytext + 3;
733 const char * name1 = strtoname( src, & end, " \t", 2 );
735 const char * name2 = strtoname( src, & end, " \t", 2 );
737 double y = 0.001 * strtod( src, & end );
738 typedef typeof *currentNameMap_ NameMapType;
739 NameMapType::const_iterator i1 = currentNameMap_->find( strrefdup( name1 ) );
740 if( i1 == currentNameMap_->end( ) )
742 throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
744 NameMapType::const_iterator i2 = currentNameMap_->find( strrefdup( name2 ) );
745 if( i2 == currentNameMap_->end( ) )
747 throw "Unable to resolve character name in kern pair. Perhaps kern pairs appear before character metrics.";
749 (*currentKernPairMapY_)[ std::pair< size_t, size_t >( i1->second, i2->second ) ] = y;
753 <TrackKern>{HorizontalWhiteSpace}{Integer}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}{Number}{HorizontalWhiteSpace}[\n] {
756 int degree = strtol( src, & endp, 10 );
758 double sizeLow = strtod( src, & endp );
760 double trackLow = 0.001 * strtod( src, & endp );
762 double sizeHigh = strtod( src, & endp );
764 double trackHigh = 0.001 * strtod( src, & endp );
765 typedef typeof fontMetricsDst_->trackKernings_ MapType;
766 fontMetricsDst_->trackKernings_.insert( MapType::value_type( degree, RefCountPtr< FontMetrics::TrackKerning >( new FontMetrics::TrackKerning( sizeLow, trackLow, sizeHigh, trackHigh ) ) ) );
770 <*>^"Comment"{HorizontalWhiteSpace}.*[\n] {
775 // If we match the whole line here, it will be a _very_ good match for anything. Hence we do things in two steps.
778 std::cerr << "The afm parser was unable to understand the key \"" << yytext << "\", with data: " ;
783 // Ignore things we don't understand.
786 std::cerr << yytext << std::endl ;
788 BEGIN( FinishGlobalLine );
791 <*>. { throwError( "Unrecognized token." ); }
794 /* The closing %% above marks the end of the Rules section and the beginning
795 * of the User Subroutines section. All text from here to the end of the
796 * file is copied verbatim to the end of the generated lex.pdf.c file.
797 * This section is where you put definitions of helper functions.
801 strtoname( char * begin, char ** endp, const char * delim )
803 for( ; memchr( " \t", *begin, 2 ) != 0; ++begin )
807 for( ; strchr( delim, *end ) == 0; ++end )
816 strtoname( char * begin, char ** endp, const char * delim, size_t delimSize )
818 for( ; memchr( " \t", *begin, 2 ) != 0; ++begin )
822 for( ; memchr( delim, *end, delimSize ) == 0; ++end )