void oldsetmacro(short n, char *s) /* Set macro number <n> to the value of s */ { unsigned char *p; short num, pos, escape; short len; OSErr memError; if (n<0 || n>9) return; // Restrict the maximum length of macros to MACRO_MAX_LEN bytes len = strlen(s)+1; if (len > (MACRO_MAX_LEN - 1)) { len = MACRO_MAX_LEN; s[MACRO_MAX_LEN - 1] = 0; } // If this is an empty string, remove whatever storage might have been used previously // by this macro. if (len == 1) { if (gMacros[n] != nil) { DisposeHandle(gMacros[n]); gMacros[n] = nil; } return; } // If neccessary, create storage for the macro if (gMacros[n] == nil) { gMacros[n] = myNewHandle(len); if (gMacros[n] == nil) { // Memory error return; } } // Adjust the handle to the proper size (may be making an existing macro longer) memError = mySetHandleSize(gMacros[n], len); if (memError != noErr) { return; } HLock(gMacros[n]); p = (unsigned char *)*gMacros[n]; num = 0; pos = 0; escape = 0; while ( *s) { if (escape) { escape = 0; switch (*s) { case 'i': if ( pos >0) { *p++=num; *p++=*s; pos=0; } *p++=MACRO_IP; break; case '#': if ( pos >0) { *p++=num; *p++=*s; pos=0; } *p++=MACRO_LINES; break; case 'n': if ( pos >0) { *p++=num; *p++=*s; pos=0; } *p++='\012'; break; case 'r': if ( pos >0) { *p++=num; *p++=*s; pos=0; } *p++='\015'; break; case 't': if ( pos >0) { *p++=num; *p++=*s; pos=0; } *p++='\t'; break; case '"': if ( pos >0) { *p++=num; *p++=*s; pos=0; } *p++='\"'; break; case '\\': if ( pos >0) { *p++=num; escape=1; pos=0; num=0; } else *p++='\\'; break; default: if (*s <='9' && *s >='0' && pos <3) { num= num*8+( *s -'0'); pos++; escape=1; } else { if (pos ==0 && num==0) { *p++='\\'; *p++=*s; } else { *p++=num; pos= 0; s--; /* back up the buffer. */ } } break; } } else { if (*s=='\\') { num=0; pos=0; escape=1; } else *p++=*s; } s++; } if (pos >0) *p++=num; *p=0; // The resultant macro may be shorter than the input string due to escaped characters. // So, recalculate the length of the macro and resize than handle if neccessary. len = strlen(*gMacros[n])+1; HUnlock(gMacros[n]); mySetHandleSize(gMacros[n], len); } /* setmacro */
// **************************************************************************** // // Function Name: RTrueTypeFont::GetGlyphOutline( ) // // Description: // // Returns: Nothing // // Exceptions: Memory, Font // // **************************************************************************** // void RTrueTypeFont::GetGlyphOutline( Handle sfnt, long glyphIndex, GlyphOutline* pOutline, Matrix xform ) { short state = GetFontState( sfnt ); short upem, sideBearing, adjustToLsb; short* glyph; sfnt_FontHeader* head; sfnt_HorizontalHeader* hhea; sfnt_HorizontalMetrics* hori; long length; long longMetrics; try { ::HLock( sfnt ); head = (sfnt_FontHeader *)GetSfntTablePtr( sfnt, tag_FontHeader ); hhea = (sfnt_HorizontalHeader *)GetSfntTablePtr( sfnt, tag_HoriHeader ); hori = (sfnt_HorizontalMetrics *)GetSfntTablePtr( sfnt, tag_HorizontalMetrics ); if ( head == NULL || hhea == NULL || hori == NULL ) throw fontNotOutlineErr; upem = head->unitsPerEm; longMetrics = hhea->numberLongMetrics; if ( glyphIndex < longMetrics ) { pOutline->advance.x = ::FixRatio( hori[glyphIndex].advance, upem ); sideBearing = hori[glyphIndex].sideBearing; } else { short *lsb = (short *)&hori[longMetrics]; // first entry after[AW,LSB] array pOutline->advance.x = ::FixRatio( hori[longMetrics-1].advance, upem ); sideBearing = hori[glyphIndex - longMetrics].sideBearing; } pOutline->advance.y = 0; pOutline->origin.x = pOutline->origin.y = 0; if ( (glyph = (short *)GetSfntGlyphPtr(sfnt, glyphIndex, &length)) == 0 ) throw fontNotOutlineErr; if ( length == 0 ) { pOutline->contourCount = pOutline->pointCount = 0; SetFontState( sfnt, state ); return; } pOutline->contourCount = *glyph++; adjustToLsb = *glyph - sideBearing; // xmin - lsb glyph += 4; // skip bounds rect if ( pOutline->contourCount == 0 ) pOutline->pointCount = 0; else if ( pOutline->contourCount == -1 ) { short flags, index, newMatrix; pOutline->contourCount = pOutline->pointCount = 0; mySetHandleSize( (Handle)pOutline->endPoints, 0 ); mySetHandleSize( (Handle)pOutline->onCurve, 0 ); mySetHandleSize( (Handle)pOutline->x, 0 ); mySetHandleSize( (Handle)pOutline->y, 0 ); do { Matrix compXform; short arg1, arg2; flags = *glyph++; index = *glyph++; newMatrix = false; if ( flags & ARG_1_AND_2_ARE_WORDS ) { arg1 = *glyph++; arg2 = *glyph++; } else { char* byteP = (char*)glyph; if ( flags & ARGS_ARE_XY_VALUES ) { // offsets are signed arg1 = *byteP++; arg2 = *byteP; } else { // anchor points are unsigned arg1 = (unsigned char)*byteP++; arg2 = (unsigned char)*byteP; } ++glyph; } #if IMPLEMENT_SCALED_COMPONENTS if ( flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_X_AND_Y_SCALE | WE_HAVE_A_TWO_BY_TWO) ) { Matrix subXform; MakeIdentityMatrix( subXform ); if ( flags & WE_HAVE_A_TWO_BY_TWO ) { compXform[0][0] = (Fixed)*glyph++ << 2; compXform[0][1] = (Fixed)*glyph++ << 2; compXform[1][0] = (Fixed)*glyph++ << 2; compXform[1][1] = (Fixed)*glyph++ << 2; } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) { compXform[0][0] = (Fixed)*glyph++ << 2; compXform[1][1] = (Fixed)*glyph++ << 2; } else compXform[0][0] = compXform[1][1] = (Fixed)*glyph++ << 2; PostMulMatrix (compXform, xform ); newMatrix = true; } #endif { GlyphOutline out; InitGlyphOutline( &out ); GetGlyphOutline( sfnt, index, &out, newMatrix ? compXform : xform ); { Fixed dx, dy; if ( flags & ARGS_ARE_XY_VALUES ) { dx = ::FixRatio(arg1, upem); dy = -::FixRatio(arg2, upem); } else { dx = (*pOutline->x)[arg1] - (*out.x)[arg2]; dy = (*pOutline->y)[arg1] - (*out.y)[arg2]; } MoveGlyphOutline( &out, dx, dy ); } AppendGlyphOutline( pOutline, &out ); KillGlyphOutline( &out ); } } while ( flags & MORE_COMPONENTS ); } else if ( pOutline->contourCount > 0 ) { // Load in the end points. { long size = pOutline->contourCount * sizeof(short); mySetHandleSize( (Handle)pOutline->endPoints, size ); BlockMove( (Ptr)glyph, (Ptr)*pOutline->endPoints, size ); glyph += pOutline->contourCount; } pOutline->pointCount = (*pOutline->endPoints)[pOutline->contourCount - 1] + 1; mySetHandleSize( (Handle)pOutline->onCurve, pOutline->pointCount * sizeof(char) ); mySetHandleSize( (Handle)pOutline->x, pOutline->pointCount * sizeof(Fixed) ); mySetHandleSize( (Handle)pOutline->y, pOutline->pointCount * sizeof(Fixed) ); // Skip the word for instruction count + the instructions. // Then load in the onCurve bytes. { Byte* p = (Byte*)glyph + sizeof(short) + *glyph; Byte* onCurve = *pOutline->onCurve; Byte* stop = onCurve + pOutline->pointCount; Byte flag; while ( onCurve < stop ) { *onCurve++ = flag = GetUnsignedByte( p ); if ( flag & REPEAT_FLAGS ) { short count = GetUnsignedByte( p ); for ( --count; count >= 0; --count ) *onCurve++ = flag; } } // Lets do X { short coord = adjustToLsb; Fixed* x = *pOutline->x; onCurve = *pOutline->onCurve; while ( onCurve < stop ) { if ( (flag = *onCurve++) & XSHORT ) { if ( flag & SHORT_X_IS_POS ) coord += GetUnsignedByte( p ); else coord -= GetUnsignedByte( p ); } else if ( !(flag & NEXT_X_IS_ZERO) ) { coord += (short)(*p++) << 8; coord += (Byte)*p++; } *x = ::FixRatio( coord, upem ); x++; } } // Lets do Y { short coord = 0; Fixed* y = *pOutline->y; onCurve = *pOutline->onCurve; while ( onCurve < stop ) { if ( (flag = *onCurve) & YSHORT ) { if ( flag & SHORT_Y_IS_POS ) coord += GetUnsignedByte( p ); else coord -= GetUnsignedByte( p ); } else if ( !(flag & NEXT_Y_IS_ZERO) ) { coord += (short)(*p++) << 8; coord += (Byte)*p++; } *y = -::FixRatio( coord, upem ); y++; // Filter off the extra bits *onCurve++ = flag & ONCURVE; } } } } else throw fontNotOutlineErr; } catch ( OSErr osErr ) { SetFontState( sfnt, state ); switch ( osErr ) { case memFullErr : // out of memeory SetFontState( sfnt, state ); throw kMemory; break; case fontNotOutlineErr : // bad font SetFontState( sfnt, state ); throw kResource; break; default: TpsAssertAlways( "Bad exception" ); throw; break; } } catch ( ... ) { SetFontState( sfnt, state ); throw; } SetFontState( sfnt, state ); }