X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fttf.cpp;h=799f0321ffc288aad01c42836e19b991d961d0c7;hb=0c01fa32c7e0629ae61992e0419f03724fc18487;hp=124468728d8efcdf58d8e94c516484faaf95f3bd;hpb=6d13a5166688e470590692eb91c3915ab332fe36;p=ttedit diff --git a/src/ttf.cpp b/src/ttf.cpp index 1244687..799f032 100755 --- a/src/ttf.cpp +++ b/src/ttf.cpp @@ -1,1212 +1,1212 @@ -// -// TTF.CPP - The TrueType class -// by James L. Hammons -// (C) 2005 Underground Software -// -// This class encapsulates all the complexity of a TrueType Font File -// database. Included are functions to load, save, & initialize the -// TTF database, move, add, & delete points & glyphs, i.e. manipulate -// a TTF file in just about any way imaginable! -// -// JLH = James L. Hammons -// -// Who When What -// --- ---------- ------------------------------------------------------------- -// JLH ??/??/199? Created this file -// -// -// STILL TO BE DONE: -// -// - Eliminate ALL references to BYTE, WORD, SBYTE, SWORD, etc. -// - -#include // For file handling, etc. // -#include -#include -#include "charnames.h" -#include "ttf.h" - -#define TTFDEBUG - -#ifdef TTFDEBUG -#include "debug.h" -#endif - -#define NUMTABS 24 // Number of distinct tables - - -/*void fskip(HANDLE file, uint32 bytesToSkip) -{ - SetFilePointer(file, (LONG)bytesToSkip, NULL, FILE_CURRENT); -}*/ - -// -// Get a BYTE from the current file... -// -uint8 ReadByte(FILE * file) -{ - return (uint8)fgetc(file); -} - -// The following routines get and put WORDs and DWORDs in little endian -// format, so they should work no matter what endianess the platform that -// holds the TTF object. - -// -// Get a WORD from the current file... -// -uint16 ReadWord(FILE * file) -{ - uint16 word = (uint16)fgetc(file) << 8; - word |= (uint16)fgetc(file); - - return word; -} - -// -// Get a double WORD from the current file... -// -uint32 ReadDWord(FILE * file) -{ - uint32 dword = 0; - - for(int i=0; i<4; i++) - { - dword <<= 8; - dword |= (uint8)fgetc(file); - } - - return dword; -} - -// -// Write a WORD to the current file... -// -void WriteWord(FILE * file, uint16 word) -{ - fputc(word >> 8, file); // Hi byte - fputc(word & 0xFF, file); // Lo byte -} - -// -// Write a double WORD to the current file... -// -void WriteDWord(FILE * file, uint32 dword) -{ - for(int i=0; i<4; i++) - { - fputc((char)(dword >> 24), file); - dword <<= 8; - } -} - -///////////////////////////////////////////////////////////////////////////// -// Table extraction helper routines (inline 'em?) -//////////////////////////////////////////////////////////////////////////// - -// -// Return a BYTE from a BYTE based table -// -uint8 GetByte(uint8 * table, uint32 &ptr) -{ - return table[ptr++]; -} - -// -// Return a WORD from a BYTE based table -// -uint16 GetWord(uint8 * table, uint32 &ptr) -{ - uint16 hi = table[ptr++]; - uint16 lo = table[ptr++]; - - return (uint16)((hi<<8) | lo); -} - -// -// Return a double WORD from a BYTE based table -// -uint32 GetDWord(uint8 * table, uint32 &ptr) -{ - uint32 hi1 = table[ptr++]; - uint32 lo1 = table[ptr++]; - uint32 hi2 = table[ptr++]; - uint32 lo2 = table[ptr++]; - - return (uint32)((hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2); -} - -///////////////////////////////////////////////////////////////////////////// -// Table storage helper routines (inline 'em?) -//////////////////////////////////////////////////////////////////////////// - -// -// Store a BYTE in a BYTE based table -// -void SetByte(uint8 * table, uint32 &ptr, uint8 data) -{ - table[ptr++] = data; -} - -// -// Store a WORD in a BYTE based table -// -void SetWord(uint8 * table, uint32 &ptr, uint16 data) -{ - table[ptr++] = data>>8; table[ptr++] = data&0xFF; -} - -// -// Store a DWORD in a BYTE based table -// -void SetDWord(uint8 * table, uint32 &ptr, uint32 data) -{ - table[ptr++] = (uint8)(data >> 24); table[ptr++] = (uint8)(data >> 16); - table[ptr++] = (uint8)(data >> 8); table[ptr++] = (uint8)(data & 0xFF); -} - -///////////////////////////////////////////////////////////////////////////// -// Fixed point to float (& vice versa) conversions -///////////////////////////////////////////////////////////////////////////// -float FixedToFloat(int16 fixed) -{ - return (float)fixed / 16384.0f; -} - -///////////////////////////////////////////////////////////////////////////// -// TTF Constructor -///////////////////////////////////////////////////////////////////////////// -TTF::TTF(void) -{ - loaded = false; // Set font initializer - isDirty = false; // Glyphs are clean - numberOfPolys = 0; // Set reasonable values - isCompositeGlyph = false; // No composite glyph (yet) - - parray[0] = &EBDT; parray[1] = &EBLC; parray[2] = &EBSC; // Init pointer - parray[3] = <SH; parray[4] = &OS_2; parray[5] = &PCLT; // array... - parray[6] = &VDMX; parray[7] = &cmap; parray[8] = &cvt; - parray[9] = &fpgm; parray[10] = &gasp; parray[11] = &glyf; - parray[12] = &hdmx; parray[13] = &head; parray[14] = &hhea; - parray[15] = &hmtx; parray[16] = &kern; parray[17] = &loca; - parray[18] = &maxp; parray[19] = &name; parray[20] = &post; - parray[21] = &prep; parray[22] = &vhea; parray[23] = &vmtx; - - larray[0] = &EBDT_len; larray[1] = &EBLC_len; larray[2] = &EBSC_len; - larray[3] = <SH_len; larray[4] = &OS_2_len; larray[5] = &PCLT_len; - larray[6] = &VDMX_len; larray[7] = &cmap_len; larray[8] = &cvt_len; - larray[9] = &fpgm_len; larray[10] = &gasp_len; larray[11] = &glyf_len; - larray[12] = &hdmx_len; larray[13] = &head_len; larray[14] = &hhea_len; - larray[15] = &hmtx_len; larray[16] = &kern_len; larray[17] = &loca_len; - larray[18] = &maxp_len; larray[19] = &name_len; larray[20] = &post_len; - larray[21] = &prep_len; larray[22] = &vhea_len; larray[23] = &vmtx_len; - - for(uint32 i=0; i 255) || (curx < -255)) // I.e., it's 2 uint8 value - SetWord(xbuf, xp, curx); - else - { - if (curx & 0x100) - { - flag |= 0x02; // I.e., it's negative - curx *= -1; // Flip it so correct value is stored - } - else - flag |= 0x12; - - SetByte(xbuf, xp, curx); // Automagically strips neg bit - } - } - else - flag |= 0x10; // X-coord is same... - - if (cury) - { - if ((cury > 255) || (cury < -255)) // I.e., it's 2 uint8 value - SetWord(ybuf, yp, cury); - else - { - if (cury & 0x100) - { - flag |= 0x04; // I.e., it's negative - cury *= -1; - } - else - flag |= 0x24; - - SetByte(ybuf, yp, cury); - } - } - else - flag |= 0x20; // Y-coord is same... - - fbuf[i] = flag; - lastx = gx[i]; lasty = gy[i]; - } - - // Now crunch flags... ugly, ugly, ugly. -/* - fbuf[numberOfPoints] = 0; // Set sentinel value (ugly way to do this) - for(i=0; i= myMaxp.numGlyphs) - return false; // Invalid char # - - if (!glyphLen[glyphnum]) - { - numberOfPoints = numberOfPolys = 0; - return true; // Zero length IS valid... - } -// else // Get character data... -// { - // Now get the character data... - dp = 0; // Reset data pointer - isCompositeGlyph = false; // Default is no - numberOfPolys = GetWord(glyph[glyphnum], dp); // # of polygons - - llx = (int16)GetWord(glyph[glyphnum], dp); // Lower left X - lly = (int16)GetWord(glyph[glyphnum], dp); // Lower left Y - urx = (int16)GetWord(glyph[glyphnum], dp); // Upper right X - ury = (int16)GetWord(glyph[glyphnum], dp); // Upper right Y - - // Need to handle composite glyphs better here. The ways things - // are set now is a recipe for disaster... - - if (numberOfPolys == 0xFFFF) - { - isCompositeGlyph = true; - numberOfPolys = 0; // Set for no points - - Composite cmpst; - - while (!compositeList.IsEmpty()) // Empty composite list... - compositeList.GetFront(); - - do - { - cmpst.flags = GetWord(glyph[glyphnum], dp); - cmpst.glyphIndex = GetWord(glyph[glyphnum], dp); - cmpst.arg1 = (cmpst.flags & 0x01 ? (int16)GetWord(glyph[glyphnum], dp) : (int8)GetByte(glyph[glyphnum], dp)); - cmpst.arg2 = (cmpst.flags & 0x01 ? (int16)GetWord(glyph[glyphnum], dp) : (int8)GetByte(glyph[glyphnum], dp)); - - if (cmpst.flags & 0x08) - cmpst.xScale = cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)); - else if (cmpst.flags & 0x40) - cmpst.xScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)), - cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)); - else if (cmpst.flags & 0x80) - cmpst.xScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)), - cmpst.scale01 = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)), - cmpst.scale10 = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)), - cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)); - - compositeList.AddAtRear(cmpst); - } - while (cmpst.flags & 0x20); //*/ - - return true; - } - -//do { -// USHORT flags; -// USHORT glyphIndex; -// if ( flags & ARG_1_AND_2_ARE_uint16S) { -// (SHORT or Fuint16) argument1; -// (SHORT or Fuint16) argument2; -// } else { -// USHORT arg1and2; /* (arg1 << 8) | arg2 */ -// } -// if ( flags & WE_HAVE_A_SCALE ) { -// F2Dot14 scale; /* Format 2.14 */ -// } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) { -// F2Dot14 xscale; /* Format 2.14 */ -// F2Dot14 yscale; /* Format 2.14 */ -// } else if ( flags & WE_HAVE_A_TWO_BY_TWO ) { -// F2Dot14 xscale; /* Format 2.14 */ -// F2Dot14 scale01; /* Format 2.14 */ -// F2Dot14 scale10; /* Format 2.14 */ -// F2Dot14 yscale; /* Format 2.14 */ -// } -//} while ( flags & MORE_COMPONENTS ) -//if (flags & WE_HAVE_INSTR){ -// USHORT numInstr -// uint8 instr[numInstr] -// -//Flags Bit Description -//ARG_1_AND_2_ARE_uint16S 0 If this is set, the arguments are uint16s; -// otherwise, they are uint8s. -//ARGS_ARE_XY_VALUES 1 If this is set, the arguments are xy values; -// otherwise, they are points. -//ROUND_XY_TO_GRID 2 For the xy values if the preceding is true. -//WE_HAVE_A_SCALE 3 This indicates that there is a simple scale -// for the component. Otherwise, scale = 1.0. -//RESERVED 4 This bit is reserved. Set it to 0. -//MORE_COMPONENTS 5 Indicates at least one more glyph after this -// one. -//WE_HAVE_AN_X_AND_Y_SCALE 6 The x direction will use a different scale -// from the y direction. -//WE_HAVE_A_TWO_BY_TWO 7 There is a 2 by 2 transformation that will -// be used to scale the component. -//WE_HAVE_INSTRUCTIONS 8 Following the last component are -// instructions for the composite character. -//USE_MY_METRICS 9 If set, this forces the aw and lsb (and rsb) -// for the composite to be equal to those from -// this original glyph. This works for hinted -// and unhinted characters. - - for(i=0; i 1) // Do we need to adjust numTokens? - // this is bad, modifying numTokens while it's used as a compare value - // in the above loop... - // Is it necessary to do so in order to keep from going too far? - numTokens -= (numRep - 1); // Yes, adjust. - } - - // 10 = same x(0uint8s), 00 = 2uint8s, 02&12 = 1uint8 - if ((token & 0x02) == 0x02) - numXs += rpts; - - if ((token & 0x12) == 0x00) - numXs += (rpts*2); - } - - xptr = dp + numTokens; - yptr = dp + numTokens + numXs; - - // & continue decoding X/Y-coords... - - k = 0; // Index to the point array - - for(uint32 i=0; im_myFont.compositeList.Length(); i++) - { - TComposite cmpst = fnt->compositeList.PeekPosition(i); - fnt->SetGlyph(cmpst.glyphIndex); - if (cmpst.flags & 0x0002) - m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2; - ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset); - } - fnt->SetGlyph(pDoc->character_num); -*/ - - GlyphPoints retVal; - - for(int i=1; i<=compositeList.Length(); i++) - { - Composite cmpst = compositeList.PeekPosition(i); - -// SetGlyph(cmpst.glyphIndex); -// if (cmpst.flags & 0x0002) -// m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2; -// ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset); - GlyphPoints gp = GetGlyphPoints(cmpst.glyphIndex); - - if (cmpst.flags & 0x0002) - gp.OffsetPoints(cmpst.arg1, cmpst.arg2); - - retVal = retVal + gp; - // NOTE: May have to adjust scanlines as per 0x0002 above... - } - -// SetGlyph(tmpGlyph); - DecodeGlyph(currentGlyph); // Reset needed here... - - return retVal; -} - -///////////////////////////////////////////////////////////////////////////// -// Member function: void GetCharName(int cNum, uint8 * buf) -// -// This function returns the character name of the glyph number passed in. -///////////////////////////////////////////////////////////////////////////// -void TTF::GetCharName(int cNum, uint8 * buf) -{ - buf[0] = 0; // Set failure as default condition - - if (!post) // PS names are here... - return; - - if (post[1] != 0x02 || post[2] != 0x00) // i.e., it's NOT a V2.0 table - return; - - uint8 * pTab = NULL; - uint32 tabOff = 34, numGlyphs = (uint32)((post[32] << 8) | post[33]); - uint32 index = (uint32)((post[tabOff + cNum * 2] << 8) | post[tabOff + cNum * 2 + 1]); - uint32 nInd2; - - if (index > 257) - { - index -= 258; - nInd2 = tabOff + (2 * numGlyphs); - pTab = post; - } - else - { - nInd2 = 0; - pTab = macStdNames; - } - - for(uint32 i=0; i= MAXPOINTS) - return p; // Fix to make invalid - - p.x = gx[pointno], p.y = gy[pointno], p.onCurve = onCurve[pointno]; - return p; -} - -uint16 TTF::GetNumberOfPolys(void) -{ - return numberOfPolys; -} - -uint16 TTF::GetPolyEnd(uint16 polynum) -{ - if (polynum >= numberOfPolys) - return 0; - - return poly[polynum]; -} - -int TTF::GetPointX(uint16 pointno) -{ - if (pointno >= MAXPOINTS) - return 0; - - return gx[pointno]; -} - -int TTF::GetPointY(uint16 pointno) -{ - if (pointno >= MAXPOINTS) - return 0; - - return gy[pointno]; -} - -bool TTF::GetOnCurve(uint16 pointno) -{ - if (pointno >= MAXPOINTS) - return true; - - return onCurve[pointno]; -} - -bool TTF::SetOnCurve(uint16 pointno, bool state) -{ - if (pointno >= numberOfPoints) - return false; - - onCurve[pointno] = state; - isDirty = true; - - return true; -} - -bool TTF::MovePoint(uint16 pointno, int x, int y) -{ - if (pointno >= numberOfPoints) - return false; - - gx[pointno] = x; gy[pointno] = y; - isDirty = true; - - return true; -} - -bool TTF::MovePoint(uint16 pointno, GlyphPt p) -{ - if (pointno >= numberOfPoints) - return false; - - gx[pointno] = p.x; gy[pointno] = p.y; onCurve[pointno] = p.onCurve; - isDirty = true; - - return true; -} - -bool TTF::IsCompositeGlyph(void) -{ - return isCompositeGlyph; -} - +// +// TTF.CPP - The TrueType class +// by James L. Hammons +// (C) 2005 Underground Software +// +// This class encapsulates all the complexity of a TrueType Font File +// database. Included are functions to load, save, & initialize the +// TTF database, move, add, & delete points & glyphs, i.e. manipulate +// a TTF file in just about any way imaginable! +// +// JLH = James L. Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH ??/??/199? Created this file +// +// +// STILL TO BE DONE: +// +// - Eliminate ALL references to BYTE, WORD, SBYTE, SWORD, etc. +// + +#include // For file handling, etc. +#include +#include +#include "charnames.h" +#include "ttf.h" + +#define TTFDEBUG + +#ifdef TTFDEBUG +#include "debug.h" +#endif + +#define NUMTABS 24 // Number of distinct tables + + +/*void fskip(HANDLE file, uint32_t bytesToSkip) +{ + SetFilePointer(file, (LONG)bytesToSkip, NULL, FILE_CURRENT); +}*/ + +// +// Get a BYTE from the current file... +// +uint8_t ReadByte(FILE * file) +{ + return (uint8_t)fgetc(file); +} + +// The following routines get and put WORDs and DWORDs in little endian +// format, so they should work no matter what endianess the platform that +// holds the TTF object. + +// +// Get a WORD from the current file... +// +uint16_t ReadWord(FILE * file) +{ + uint16_t word = (uint16_t)fgetc(file) << 8; + word |= (uint16_t)fgetc(file); + + return word; +} + +// +// Get a double WORD from the current file... +// +uint32_t ReadDWord(FILE * file) +{ + uint32_t dword = 0; + + for(int i=0; i<4; i++) + { + dword <<= 8; + dword |= (uint8_t)fgetc(file); + } + + return dword; +} + +// +// Write a WORD to the current file... +// +void WriteWord(FILE * file, uint16_t word) +{ + fputc(word >> 8, file); // Hi byte + fputc(word & 0xFF, file); // Lo byte +} + +// +// Write a double WORD to the current file... +// +void WriteDWord(FILE * file, uint32_t dword) +{ + for(int i=0; i<4; i++) + { + fputc((char)(dword >> 24), file); + dword <<= 8; + } +} + +///////////////////////////////////////////////////////////////////////////// +// Table extraction helper routines (inline 'em?) +//////////////////////////////////////////////////////////////////////////// + +// +// Return a BYTE from a BYTE based table +// +uint8_t GetByte(uint8_t * table, uint32_t &ptr) +{ + return table[ptr++]; +} + +// +// Return a WORD from a BYTE based table +// +uint16_t GetWord(uint8_t * table, uint32_t &ptr) +{ + uint16_t hi = table[ptr++]; + uint16_t lo = table[ptr++]; + + return (uint16_t)((hi<<8) | lo); +} + +// +// Return a double WORD from a BYTE based table +// +uint32_t GetDWord(uint8_t * table, uint32_t &ptr) +{ + uint32_t hi1 = table[ptr++]; + uint32_t lo1 = table[ptr++]; + uint32_t hi2 = table[ptr++]; + uint32_t lo2 = table[ptr++]; + + return (uint32_t)((hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2); +} + +///////////////////////////////////////////////////////////////////////////// +// Table storage helper routines (inline 'em?) +//////////////////////////////////////////////////////////////////////////// + +// +// Store a BYTE in a BYTE based table +// +void SetByte(uint8_t * table, uint32_t &ptr, uint8_t data) +{ + table[ptr++] = data; +} + +// +// Store a WORD in a BYTE based table +// +void SetWord(uint8_t * table, uint32_t &ptr, uint16_t data) +{ + table[ptr++] = data>>8; table[ptr++] = data&0xFF; +} + +// +// Store a DWORD in a BYTE based table +// +void SetDWord(uint8_t * table, uint32_t &ptr, uint32_t data) +{ + table[ptr++] = (uint8_t)(data >> 24); table[ptr++] = (uint8_t)(data >> 16); + table[ptr++] = (uint8_t)(data >> 8); table[ptr++] = (uint8_t)(data & 0xFF); +} + +///////////////////////////////////////////////////////////////////////////// +// Fixed point to float (& vice versa) conversions +///////////////////////////////////////////////////////////////////////////// +float FixedToFloat(int16_t fixed) +{ + return (float)fixed / 16384.0f; +} + +///////////////////////////////////////////////////////////////////////////// +// TTF Constructor +///////////////////////////////////////////////////////////////////////////// +TTF::TTF(void) +{ + loaded = false; // Set font initializer + isDirty = false; // Glyphs are clean + numberOfPolys = 0; // Set reasonable values + isCompositeGlyph = false; // No composite glyph (yet) + + parray[0] = &EBDT; parray[1] = &EBLC; parray[2] = &EBSC; // Init pointer + parray[3] = <SH; parray[4] = &OS_2; parray[5] = &PCLT; // array... + parray[6] = &VDMX; parray[7] = &cmap; parray[8] = &cvt; + parray[9] = &fpgm; parray[10] = &gasp; parray[11] = &glyf; + parray[12] = &hdmx; parray[13] = &head; parray[14] = &hhea; + parray[15] = &hmtx; parray[16] = &kern; parray[17] = &loca; + parray[18] = &maxp; parray[19] = &name; parray[20] = &post; + parray[21] = &prep; parray[22] = &vhea; parray[23] = &vmtx; + + larray[0] = &EBDT_len; larray[1] = &EBLC_len; larray[2] = &EBSC_len; + larray[3] = <SH_len; larray[4] = &OS_2_len; larray[5] = &PCLT_len; + larray[6] = &VDMX_len; larray[7] = &cmap_len; larray[8] = &cvt_len; + larray[9] = &fpgm_len; larray[10] = &gasp_len; larray[11] = &glyf_len; + larray[12] = &hdmx_len; larray[13] = &head_len; larray[14] = &hhea_len; + larray[15] = &hmtx_len; larray[16] = &kern_len; larray[17] = &loca_len; + larray[18] = &maxp_len; larray[19] = &name_len; larray[20] = &post_len; + larray[21] = &prep_len; larray[22] = &vhea_len; larray[23] = &vmtx_len; + + for(uint32_t i=0; i 255) || (curx < -255)) // I.e., it's 2 uint8_t value + SetWord(xbuf, xp, curx); + else + { + if (curx & 0x100) + { + flag |= 0x02; // I.e., it's negative + curx *= -1; // Flip it so correct value is stored + } + else + flag |= 0x12; + + SetByte(xbuf, xp, curx); // Automagically strips neg bit + } + } + else + flag |= 0x10; // X-coord is same... + + if (cury) + { + if ((cury > 255) || (cury < -255)) // I.e., it's 2 uint8_t value + SetWord(ybuf, yp, cury); + else + { + if (cury & 0x100) + { + flag |= 0x04; // I.e., it's negative + cury *= -1; + } + else + flag |= 0x24; + + SetByte(ybuf, yp, cury); + } + } + else + flag |= 0x20; // Y-coord is same... + + fbuf[i] = flag; + lastx = gx[i]; lasty = gy[i]; + } + + // Now crunch flags... ugly, ugly, ugly. +/* + fbuf[numberOfPoints] = 0; // Set sentinel value (ugly way to do this) + for(i=0; i= myMaxp.numGlyphs) + return false; // Invalid char # + + if (!glyphLen[glyphnum]) + { + numberOfPoints = numberOfPolys = 0; + return true; // Zero length IS valid... + } +// else // Get character data... +// { + // Now get the character data... + dp = 0; // Reset data pointer + isCompositeGlyph = false; // Default is no + numberOfPolys = GetWord(glyph[glyphnum], dp); // # of polygons + + llx = (int16_t)GetWord(glyph[glyphnum], dp); // Lower left X + lly = (int16_t)GetWord(glyph[glyphnum], dp); // Lower left Y + urx = (int16_t)GetWord(glyph[glyphnum], dp); // Upper right X + ury = (int16_t)GetWord(glyph[glyphnum], dp); // Upper right Y + + // Need to handle composite glyphs better here. The ways things + // are set now is a recipe for disaster... + + if (numberOfPolys == 0xFFFF) + { + isCompositeGlyph = true; + numberOfPolys = 0; // Set for no points + + Composite cmpst; + + while (!compositeList.IsEmpty()) // Empty composite list... + compositeList.GetFront(); + + do + { + cmpst.flags = GetWord(glyph[glyphnum], dp); + cmpst.glyphIndex = GetWord(glyph[glyphnum], dp); + cmpst.arg1 = (cmpst.flags & 0x01 ? (int16_t)GetWord(glyph[glyphnum], dp) : (int8_t)GetByte(glyph[glyphnum], dp)); + cmpst.arg2 = (cmpst.flags & 0x01 ? (int16_t)GetWord(glyph[glyphnum], dp) : (int8_t)GetByte(glyph[glyphnum], dp)); + + if (cmpst.flags & 0x08) + cmpst.xScale = cmpst.yScale = FixedToFloat((int16_t)GetWord(glyph[glyphnum], dp)); + else if (cmpst.flags & 0x40) + cmpst.xScale = FixedToFloat((int16_t)GetWord(glyph[glyphnum], dp)), + cmpst.yScale = FixedToFloat((int16_t)GetWord(glyph[glyphnum], dp)); + else if (cmpst.flags & 0x80) + cmpst.xScale = FixedToFloat((int16_t)GetWord(glyph[glyphnum], dp)), + cmpst.scale01 = FixedToFloat((int16_t)GetWord(glyph[glyphnum], dp)), + cmpst.scale10 = FixedToFloat((int16_t)GetWord(glyph[glyphnum], dp)), + cmpst.yScale = FixedToFloat((int16_t)GetWord(glyph[glyphnum], dp)); + + compositeList.AddAtRear(cmpst); + } + while (cmpst.flags & 0x20); //*/ + + return true; + } + +//do { +// USHORT flags; +// USHORT glyphIndex; +// if ( flags & ARG_1_AND_2_ARE_uint16_tS) { +// (SHORT or Fuint16_t) argument1; +// (SHORT or Fuint16_t) argument2; +// } else { +// USHORT arg1and2; /* (arg1 << 8) | arg2 */ +// } +// if ( flags & WE_HAVE_A_SCALE ) { +// F2Dot14 scale; /* Format 2.14 */ +// } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) { +// F2Dot14 xscale; /* Format 2.14 */ +// F2Dot14 yscale; /* Format 2.14 */ +// } else if ( flags & WE_HAVE_A_TWO_BY_TWO ) { +// F2Dot14 xscale; /* Format 2.14 */ +// F2Dot14 scale01; /* Format 2.14 */ +// F2Dot14 scale10; /* Format 2.14 */ +// F2Dot14 yscale; /* Format 2.14 */ +// } +//} while ( flags & MORE_COMPONENTS ) +//if (flags & WE_HAVE_INSTR){ +// USHORT numInstr +// uint8_t instr[numInstr] +// +//Flags Bit Description +//ARG_1_AND_2_ARE_uint16_tS 0 If this is set, the arguments are uint16_ts; +// otherwise, they are uint8_ts. +//ARGS_ARE_XY_VALUES 1 If this is set, the arguments are xy values; +// otherwise, they are points. +//ROUND_XY_TO_GRID 2 For the xy values if the preceding is true. +//WE_HAVE_A_SCALE 3 This indicates that there is a simple scale +// for the component. Otherwise, scale = 1.0. +//RESERVED 4 This bit is reserved. Set it to 0. +//MORE_COMPONENTS 5 Indicates at least one more glyph after this +// one. +//WE_HAVE_AN_X_AND_Y_SCALE 6 The x direction will use a different scale +// from the y direction. +//WE_HAVE_A_TWO_BY_TWO 7 There is a 2 by 2 transformation that will +// be used to scale the component. +//WE_HAVE_INSTRUCTIONS 8 Following the last component are +// instructions for the composite character. +//USE_MY_METRICS 9 If set, this forces the aw and lsb (and rsb) +// for the composite to be equal to those from +// this original glyph. This works for hinted +// and unhinted characters. + + for(i=0; i 1) // Do we need to adjust numTokens? + // this is bad, modifying numTokens while it's used as a compare value + // in the above loop... + // Is it necessary to do so in order to keep from going too far? + numTokens -= (numRep - 1); // Yes, adjust. + } + + // 10 = same x(0uint8_ts), 00 = 2uint8_ts, 02&12 = 1uint8_t + if ((token & 0x02) == 0x02) + numXs += rpts; + + if ((token & 0x12) == 0x00) + numXs += (rpts*2); + } + + xptr = dp + numTokens; + yptr = dp + numTokens + numXs; + + // & continue decoding X/Y-coords... + + k = 0; // Index to the point array + + for(uint32_t i=0; im_myFont.compositeList.Length(); i++) + { + TComposite cmpst = fnt->compositeList.PeekPosition(i); + fnt->SetGlyph(cmpst.glyphIndex); + if (cmpst.flags & 0x0002) + m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2; + ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset); + } + fnt->SetGlyph(pDoc->character_num); +*/ + + GlyphPoints retVal; + + for(int i=1; i<=compositeList.Length(); i++) + { + Composite cmpst = compositeList.PeekPosition(i); + +// SetGlyph(cmpst.glyphIndex); +// if (cmpst.flags & 0x0002) +// m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2; +// ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset); + GlyphPoints gp = GetGlyphPoints(cmpst.glyphIndex); + + if (cmpst.flags & 0x0002) + gp.OffsetPoints(cmpst.arg1, cmpst.arg2); + + retVal = retVal + gp; + // NOTE: May have to adjust scanlines as per 0x0002 above... + } + +// SetGlyph(tmpGlyph); + DecodeGlyph(currentGlyph); // Reset needed here... + + return retVal; +} + +///////////////////////////////////////////////////////////////////////////// +// Member function: void GetCharName(int cNum, uint8_t * buf) +// +// This function returns the character name of the glyph number passed in. +///////////////////////////////////////////////////////////////////////////// +void TTF::GetCharName(int cNum, uint8_t * buf) +{ + buf[0] = 0; // Set failure as default condition + + if (!post) // PS names are here... + return; + + if (post[1] != 0x02 || post[2] != 0x00) // i.e., it's NOT a V2.0 table + return; + + uint8_t * pTab = NULL; + uint32_t tabOff = 34, numGlyphs = (uint32_t)((post[32] << 8) | post[33]); + uint32_t index = (uint32_t)((post[tabOff + cNum * 2] << 8) | post[tabOff + cNum * 2 + 1]); + uint32_t nInd2; + + if (index > 257) + { + index -= 258; + nInd2 = tabOff + (2 * numGlyphs); + pTab = post; + } + else + { + nInd2 = 0; + pTab = macStdNames; + } + + for(uint32_t i=0; i= MAXPOINTS) + return p; // Fix to make invalid + + p.x = gx[pointno], p.y = gy[pointno], p.onCurve = onCurve[pointno]; + return p; +} + +uint16_t TTF::GetNumberOfPolys(void) +{ + return numberOfPolys; +} + +uint16_t TTF::GetPolyEnd(uint16_t polynum) +{ + if (polynum >= numberOfPolys) + return 0; + + return poly[polynum]; +} + +int TTF::GetPointX(uint16_t pointno) +{ + if (pointno >= MAXPOINTS) + return 0; + + return gx[pointno]; +} + +int TTF::GetPointY(uint16_t pointno) +{ + if (pointno >= MAXPOINTS) + return 0; + + return gy[pointno]; +} + +bool TTF::GetOnCurve(uint16_t pointno) +{ + if (pointno >= MAXPOINTS) + return true; + + return onCurve[pointno]; +} + +bool TTF::SetOnCurve(uint16_t pointno, bool state) +{ + if (pointno >= numberOfPoints) + return false; + + onCurve[pointno] = state; + isDirty = true; + + return true; +} + +bool TTF::MovePoint(uint16_t pointno, int x, int y) +{ + if (pointno >= numberOfPoints) + return false; + + gx[pointno] = x; gy[pointno] = y; + isDirty = true; + + return true; +} + +bool TTF::MovePoint(uint16_t pointno, GlyphPt p) +{ + if (pointno >= numberOfPoints) + return false; + + gx[pointno] = p.x; gy[pointno] = p.y; onCurve[pointno] = p.onCurve; + isDirty = true; + + return true; +} + +bool TTF::IsCompositeGlyph(void) +{ + return isCompositeGlyph; +} +