static int16 ProcessMinMax(TTFACC_FILEBUFFERINFO * pInputBufferInfo, uint32 ulOffset, uint8 * pabKeepGlyphs, uint16 usnGlyphs, uint16 fKeepFlag) { BASEMINMAX BASEMinMax; BASEFEATMINMAXRECORD BASEFeatMinMaxRecord; uint16 i; uint16 usBytesRead; uint32 ulCurrentOffset; int16 errCode; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEMinMax, SIZEOF_BASEMINMAX, BASEMINMAX_CONTROL, ulOffset, &usBytesRead ) )!= NO_ERROR) return errCode; if (BASEMinMax.MinCoordOffset != 0) if ((errCode = ProcessBaseCoord( pInputBufferInfo, ulOffset + BASEMinMax.MinCoordOffset, pabKeepGlyphs, usnGlyphs, fKeepFlag))!= NO_ERROR) return errCode; if (BASEMinMax.MaxCoordOffset != 0) if ((errCode = ProcessBaseCoord( pInputBufferInfo, ulOffset + BASEMinMax.MaxCoordOffset, pabKeepGlyphs, usnGlyphs, fKeepFlag))!= NO_ERROR) return errCode; ulCurrentOffset = ulOffset + usBytesRead; for (i = 0; i < BASEMinMax.FeatMinMaxCount; ++i) { if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEFeatMinMaxRecord, SIZEOF_BASEFEATMINMAXRECORD, BASEFEATMINMAXRECORD_CONTROL, ulCurrentOffset, &usBytesRead ) )!= NO_ERROR) return errCode; ulCurrentOffset += usBytesRead; if (BASEFeatMinMaxRecord.MinCoordOffset != 0) if ((errCode = ProcessBaseCoord( pInputBufferInfo, ulOffset + BASEFeatMinMaxRecord.MinCoordOffset, pabKeepGlyphs, usnGlyphs, fKeepFlag))!= NO_ERROR) return errCode; if (BASEFeatMinMaxRecord.MaxCoordOffset != 0) if ((errCode = ProcessBaseCoord( pInputBufferInfo, ulOffset + BASEFeatMinMaxRecord.MaxCoordOffset, pabKeepGlyphs, usnGlyphs, fKeepFlag))!= NO_ERROR) return errCode; } return NO_ERROR; }
int16 TTCOffsetTableOffset( /* 0 */ CONST unsigned char * puchSrcBuffer, /* input TTF or TTC buffer */ /* 1 */ CONST unsigned long ulSrcBufferSize, /* size of input TTF or TTC buffer data */ /* 6 */ CONST unsigned short usTTCIndex, /* TTC Index, only used if TTC bit set */ uint32 *pulOffsetTableOffset) { CONST_TTFACC_FILEBUFFERINFO InputBufferInfo; int16 errCode = NO_ERROR; TTC_HEADER TTCHeader; uint16 usBytesRead; uint32 ulOffset; InputBufferInfo.puchBuffer = puchSrcBuffer; InputBufferInfo.ulBufferSize = ulSrcBufferSize; InputBufferInfo.ulOffsetTableOffset = *pulOffsetTableOffset = 0; InputBufferInfo.lpfnReAllocate = NULL; /* can't reallocate input buffer */ if ((errCode = ReadGeneric((TTFACC_FILEBUFFERINFO *) &InputBufferInfo, (uint8 *) &TTCHeader, SIZEOF_TTC_HEADER, TTC_HEADER_CONTROL, 0, &usBytesRead)) != NO_ERROR) return(errCode); ulOffset = usBytesRead; if (TTCHeader.TTCTag != TTC_LONG_TAG) /* this isn't a ttc */ return ERR_NOT_TTC; /* offset set correctly for ttf */ if (usTTCIndex >= TTCHeader.DirectoryCount) return ERR_INVALID_TTC_INDEX; ulOffset += GetGenericSize(LONG_CONTROL) * usTTCIndex; if ((errCode = ReadLong((TTFACC_FILEBUFFERINFO *) &InputBufferInfo, pulOffsetTableOffset, ulOffset)) != NO_ERROR) return(errCode); return errCode; }
PRIVATE int16 CopyForgottenTables( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, uint32 * pulNewOutOffset ) { DIRECTORY *aDirectory; OFFSET_TABLE OffsetTable; uint16 usnTables; uint16 usTableIdx; uint16 usBytesRead; uint32 ulBytesRead; uint32 ulOffset; int16 errCode; char szTag[5]; /* read offset table and determine number of existing tables */ ulOffset = pOutputBufferInfo->ulOffsetTableOffset; if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *) &OffsetTable, SIZEOF_OFFSET_TABLE, OFFSET_TABLE_CONTROL, ulOffset, &usBytesRead)) != NO_ERROR) return(ERR_MEM); ulOffset += usBytesRead; usnTables = OffsetTable.numTables; /* Create a list of valid tables */ aDirectory = (DIRECTORY *) Mem_Alloc((usnTables) * sizeof(DIRECTORY)); if (aDirectory == NULL) return(ERR_MEM); errCode = ReadGenericRepeat( pOutputBufferInfo, (uint8 *) aDirectory, DIRECTORY_CONTROL, ulOffset, &ulBytesRead, usnTables, SIZEOF_DIRECTORY ); if (errCode != NO_ERROR) { Mem_Free(aDirectory); return errCode; } /* sort directories by offset */ SortByOffset( aDirectory, usnTables ); /* will sort all the zero offsets to the beginning */ for ( usTableIdx = 0; usTableIdx < usnTables; usTableIdx++ ) { /* copy the forgotten table from the input file to the output file */ if (aDirectory[ usTableIdx ].length == 0 && aDirectory[ usTableIdx ].offset == DIRECTORY_ERROR) { if (aDirectory[ usTableIdx ].tag != DELETETABLETAG) /* it hasn't been marked for deletion */ { /* Copy the table contents over, and update the directory */ ConvertLongTagToString(aDirectory[ usTableIdx ].tag, szTag); if ((errCode = CopyTableOver( pOutputBufferInfo, pInputBufferInfo, szTag, pulNewOutOffset )) != NO_ERROR) break; } } else break; /* we're done with all the forgotten tables */ } Mem_Free(aDirectory); return(errCode); }
PRIVATE uint16 GetCmapSubtableCount( TTFACC_FILEBUFFERINFO * pInputBufferInfo, uint32 ulCmapOffset) { CMAP_HEADER CmapHdr; uint16 usBytesRead; if (ReadGeneric( pInputBufferInfo, (uint8 *) &CmapHdr, SIZEOF_CMAP_HEADER, CMAP_HEADER_CONTROL, ulCmapOffset, &usBytesRead ) != NO_ERROR) return 0; return(CmapHdr.numTables); } /* GetCmapSubtableCount() */
int16 MortAutoMap(TTFACC_FILEBUFFERINFO * pInputBufferInfo, /* ttfacc info */ uint8 * pabKeepGlyphs, /* binary list of glyphs to keep - to be updated here */ uint16 usnGlyphs, /* number of glyphs in list */ uint16 fKeepFlag) { MORTBINSRCHHEADER MortBinSrchHeader; MORTLOOKUPSINGLE MortLookup; uint16 nEntries; uint16 usBytesRead; uint32 ulOffset; uint32 ulLength; uint32 ulLastOffset; int16 errCode = NO_ERROR; ulOffset = TTTableOffset( pInputBufferInfo, MORT_TAG ); ulLength = TTTableLength( pInputBufferInfo, MORT_TAG ); ulLastOffset = ulOffset+ulLength; if (ulOffset == DIRECTORY_ERROR || ulLength == 0) /* nothing to map, we're done */ return NO_ERROR; ulOffset += GetGenericSize(MORTHEADER_CONTROL); /* skip over mortheader */ if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&MortBinSrchHeader, SIZEOF_MORTBINSRCHHEADER, MORTBINSRCHHEADER_CONTROL, ulOffset, &usBytesRead ) )!= NO_ERROR) return errCode; ulOffset += usBytesRead; for ( nEntries = MortBinSrchHeader.nEntries; nEntries > 0 && ulOffset < ulLastOffset; nEntries--) { if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&MortLookup, SIZEOF_MORTLOOKUPSINGLE, MORTLOOKUPSINGLE_CONTROL, ulOffset, &usBytesRead ) )!= NO_ERROR) return errCode; ulOffset += usBytesRead; if ( MortLookup.glyphid1 < usnGlyphs && pabKeepGlyphs[MortLookup.glyphid1] == fKeepFlag && MortLookup.glyphid2 < usnGlyphs && pabKeepGlyphs[MortLookup.glyphid2] == 0) pabKeepGlyphs[MortLookup.glyphid2] = (uint8)(fKeepFlag + 1); /* set this value too */ } return NO_ERROR; }
static int16 ProcessBaseCoord(TTFACC_FILEBUFFERINFO * pInputBufferInfo, uint32 ulOffset, uint8 * pabKeepGlyphs, uint16 usnGlyphs, uint16 fKeepFlag) { BASECOORDFORMAT2 BASECoordFormat2; uint16 BASECoordFormat; int16 errCode; uint16 usBytesRead; if ((errCode = ReadWord( pInputBufferInfo, &BASECoordFormat, ulOffset ) )!= NO_ERROR) return errCode; if (BASECoordFormat != 2) return NO_ERROR; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *) &BASECoordFormat2, SIZEOF_BASECOORDFORMAT2, BASECOORDFORMAT2_CONTROL, ulOffset, &usBytesRead ) )!= NO_ERROR) return errCode; if (BASECoordFormat2.GlyphID < usnGlyphs && pabKeepGlyphs[BASECoordFormat2.GlyphID] == 0) pabKeepGlyphs[BASECoordFormat2.GlyphID] = (uint8)(fKeepFlag + 1); return NO_ERROR; }
//! This method reads according to the size of rData and performs a swap if needed. bool Read(TOffset Position, u64 &rData) const { return ReadGeneric(Position, rData); }
int16 ModVDMX(CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint16 usFormat, uint32 *pulNewOutOffset) { VDMX Vdmx; uint32 ulSrcOffset; /* offset to Src VDMX table */ uint32 ulSrcLength; /* length of Src VDMX table */ uint32 ulDestOffset; /* offset to Dest VDMX table */ uint32 ulDestLength; /* length of Dest VDMX table */ uint32 ulSrcOffsetRatios; /* absolute offset to Ratios in Src file */ uint32 ulSrcOffsetOffsets; /* absolute offset to Offsets in Src file */ uint32 ulSrcOffsetGroups; /* absolute offset to Groups in Src file */ uint32 ulDestOffsetRatios; /* absolute offset to Ratios in Dest file */ uint32 ulDestOffsetOffsets; /* absolute offset to Offsets in Dest file */ uint32 ulDestOffsetGroups; /* absolute offset to Groups in Dest file */ uint16 usCurrGroupSrcOffset; /* relative offset from beginning of VDMX table */ uint16 usCurrGroupDestOffset; /* relative offset from beginning of VDMX table */ uint32 ulCurrGroupDestOffset=0; /* relative offset from beginning of VDMX table - long value */ uint16 usGroupDestOffset; /* relative offset from beginning of VDMX table, local copy for writing */ uint16 ----cRatioIndex,usDestRatioIndex; uint16 i; uint16 usBytesRead; uint16 usBytesWritten; uint32 ulBytesRead; int16 errCode=NO_ERROR; VDMXRatio *SrcRatioArray=NULL; int8 *KeepSrcRatioArray = NULL; /* parallel array to SrcRatioArray */ VDMXGroup GroupHeader; uint8 * pGroupBuffer=NULL; uint32 ulGroupBufferLength; /* total length of the Group Buffer (from source file) */ uint32 ulGroupLength; /* length of individual group to be read */ uint16 usGroupCount = 0; uint16 usKeepRatioCount = 0; uint16 usRatioSize; uint16 xRatio, yRatio; /* for reducing the ratios */ int16 Found1to1; GROUPOFFSETRECORDKEEPER keeper; TTFACC_FILEBUFFERINFO * pUnCONSTInputBufferInfo; if (usFormat == TTFDELTA_DELTA) /* only formats for which this is not valid */ { MarkTableForDeletion(pOutputBufferInfo, VDMX_TAG); return errCode; } pUnCONSTInputBufferInfo = (TTFACC_FILEBUFFERINFO *) pInputBufferInfo; /* used for Read functions ONLY. Not for Write */ /* get input buffer information */ ulSrcOffset = TTTableOffset( pUnCONSTInputBufferInfo, VDMX_TAG ); if ( ulSrcOffset == 0L ) return NO_ERROR; ulSrcLength = TTTableLength( pUnCONSTInputBufferInfo, VDMX_TAG ); if ( ulSrcLength == 0L ) { MarkTableForDeletion(pOutputBufferInfo, VDMX_TAG); return NO_ERROR; } /* get output buffer information */ if ((errCode = ZeroLongWordAlign(pOutputBufferInfo, *pulNewOutOffset, &ulDestOffset)) != NO_ERROR) return errCode; if ((errCode = ReadGeneric( pUnCONSTInputBufferInfo, (uint8 *) &Vdmx, SIZEOF_VDMX, VDMX_CONTROL, ulSrcOffset, &usBytesRead )) != NO_ERROR) return errCode; if (Vdmx.numRatios == 0) { MarkTableForDeletion(pOutputBufferInfo, VDMX_TAG); return NO_ERROR; } ulSrcOffsetRatios = ulSrcOffset + usBytesRead; ulSrcOffsetOffsets = ulSrcOffsetRatios + GetGenericSize(VDMXRATIO_CONTROL) * Vdmx.numRatios; ulSrcOffsetGroups = ulSrcOffsetOffsets + sizeof(uint16) * Vdmx.numRatios; memset(&keeper, 0, sizeof(keeper)); SrcRatioArray = (VDMXRatio *)Mem_Alloc(Vdmx.numRatios * sizeof(VDMXRatio)); if (SrcRatioArray == NULL) errCode = ERR_MEM; else { KeepSrcRatioArray = (int8 *)Mem_Alloc(Vdmx.numRatios * sizeof(int8)); if (KeepSrcRatioArray == NULL) errCode = ERR_MEM; else errCode = ReadGenericRepeat(pUnCONSTInputBufferInfo, (uint8 *) SrcRatioArray, VDMXRATIO_CONTROL, ulSrcOffsetRatios, &ulBytesRead, Vdmx.numRatios, SIZEOF_VDMXRATIO ); } while (errCode == NO_ERROR) /* while is so we can break out. Only go once through */ { Found1to1 = FALSE; for (i = 0; i < Vdmx.numRatios ; ++i) /* keep all 1:1 aspect ratios */ { KeepSrcRatioArray[i] = 1; /* assume we'll keep it */ xRatio = SrcRatioArray[i].xRatio; yRatio = SrcRatioArray[i].yStartRatio; ReduceRatio(&xRatio,&yRatio); if (xRatio == yRatio) { if (SrcRatioArray[i].xRatio == 0) /* anything after 0:0 is ignored */ { if (!Found1to1) /* need to keep this one */ ++usKeepRatioCount; break; } if (Found1to1) /* already have one */ KeepSrcRatioArray[i] = 0; /* don't keep this one */ else { Found1to1 = TRUE; ++usKeepRatioCount; } } else if (xRatio == EGA_X_RATIO && yRatio == EGA_Y_RATIO) KeepSrcRatioArray[i] = 0; /* don't keep this one */ else ++usKeepRatioCount; } if ((usKeepRatioCount == 0) || (usKeepRatioCount == Vdmx.numRatios)) { /* don't change a thing */ Mem_Free(SrcRatioArray); Mem_Free(KeepSrcRatioArray); return CopyTableOver(pOutputBufferInfo, pInputBufferInfo, VDMX_TAG, pulNewOutOffset); } ulDestOffsetRatios = ulDestOffset + usBytesRead; /* figure out offset for the Offset array */ ulDestOffsetOffsets = ulDestOffsetRatios + GetGenericSize(VDMXRATIO_CONTROL) * usKeepRatioCount; ulDestOffsetGroups = ulDestOffsetOffsets + sizeof(uint16) * usKeepRatioCount; usRatioSize = GetGenericSize(VDMXRATIO_CONTROL); ulCurrGroupDestOffset = ulDestOffsetGroups - ulDestOffset; /* calculate offset from start of VDMX table */ if ((errCode = InitGroupOffsetArray(&keeper,usKeepRatioCount)) != NO_ERROR) /* initialize structure to track offset re-use */ break; ulGroupBufferLength = ulSrcLength - (ulSrcOffsetGroups - ulSrcOffset); /* calculate the length of the group section */ pGroupBuffer = (uint8 *)Mem_Alloc(ulGroupBufferLength); /* allocate buffer the size of the group buffer */ if (pGroupBuffer == NULL) { errCode = ERR_MEM; break; } for (----cRatioIndex = usDestRatioIndex = 0; ----cRatioIndex < Vdmx.numRatios && usDestRatioIndex < usKeepRatioCount; ++----cRatioIndex) /* keep all 1:1 aspect ratios */ { if (KeepSrcRatioArray[----cRatioIndex] == 1) { /* write out the Ratio to the proper location */ if ((errCode = WriteGeneric(pOutputBufferInfo, (uint8 *) &(SrcRatioArray[----cRatioIndex]), SIZEOF_VDMXRATIO, VDMXRATIO_CONTROL, ulDestOffsetRatios + (usDestRatioIndex * usRatioSize), &usBytesWritten)) != NO_ERROR) break; /* now read the offset to the group */ if ((errCode = ReadWord(pUnCONSTInputBufferInfo, &usCurrGroupSrcOffset, ulSrcOffsetOffsets + (----cRatioIndex * sizeof(uint16)) )) != NO_ERROR) break; /* check if offset already used */ if ((usGroupDestOffset = LookupGroupOffset(&keeper, usCurrGroupSrcOffset)) == 0) /* not there already */ { if (ulCurrGroupDestOffset > USHRT_MAX) /* check if will fit in unsigned short */ { errCode = ERR_INVALID_VDMX; break; } usCurrGroupDestOffset = (uint16) ulCurrGroupDestOffset; /* already checked if in range */ /* need to register the old and new group offsets */ if ((errCode = RecordGroupOffset(&keeper, usCurrGroupSrcOffset, usCurrGroupDestOffset)) != NO_ERROR) break; usGroupDestOffset = usCurrGroupDestOffset; /* need to copy the group data over */ if ((errCode = ReadGeneric(pUnCONSTInputBufferInfo, (uint8 *) &GroupHeader, SIZEOF_VDMXGROUP, VDMXGROUP_CONTROL, ulSrcOffset + usCurrGroupSrcOffset, &usBytesRead)) != NO_ERROR) break; ulGroupLength = usBytesRead + (GroupHeader.recs * GetGenericSize(VDMXVTABLE_CONTROL)); /* read the group data into a buffer */ if (ulGroupLength > ulGroupBufferLength) { errCode = ERR_INVALID_VDMX; /* error in data! */ break; } if ((errCode = ReadBytes(pUnCONSTInputBufferInfo, (uint8 *) pGroupBuffer, ulSrcOffset + usCurrGroupSrcOffset, ulGroupLength)) != NO_ERROR) break; /* and write them to the output buffer */ if ((errCode = WriteBytes(pOutputBufferInfo, (uint8 *) pGroupBuffer, ulDestOffset + usCurrGroupDestOffset, ulGroupLength)) != NO_ERROR) break; ++usGroupCount; /* increment our CurrGroupDestOffset value for next time around */ ulCurrGroupDestOffset = usCurrGroupDestOffset + ulGroupLength; } /* now write out that relative offset value */ if ((errCode = WriteWord(pOutputBufferInfo, usGroupDestOffset, ulDestOffsetOffsets + (usDestRatioIndex * sizeof(uint16)))) != NO_ERROR) break; ++usDestRatioIndex; /* increment in dest array */ } } break; /* out of while */ } if (errCode == NO_ERROR) { Vdmx.numRatios = usKeepRatioCount; Vdmx.numRecs = usGroupCount; errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &Vdmx, SIZEOF_VDMX, VDMX_CONTROL, ulDestOffset, &usBytesWritten ); } if (errCode == NO_ERROR) { ulDestLength = ulCurrGroupDestOffset; /* this is the size of the table */ errCode = UpdateDirEntryAll( pOutputBufferInfo, VDMX_TAG, ulDestLength, ulDestOffset ); *pulNewOutOffset = ulDestOffset + ulDestLength; } FreeGroupOffsetArray(&keeper); /* free up structure to track offset re-use */ Mem_Free(pGroupBuffer); Mem_Free(KeepSrcRatioArray); Mem_Free(SrcRatioArray); return errCode; }
int16 ModHdmx( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint8 *puchKeepGlyphList, CONST uint16 usGlyphListCount, CONST uint16 usDttfGlyphIndexCount, uint32 *pulNewOutOffset) { HDMX Hdmx; HDMX_DEVICE_REC DevRecord; uint8 Width; uint8 maxWidth; uint16 i; uint16 j,k; uint32 ulHdmxOffset; uint32 ulOffset; uint32 ulDevOffset; uint32 ulInOffset; uint32 ulOutOffset; uint32 ulInDevOffset; uint32 ulOutDevOffset; int16 errCode; uint16 usBytesRead; uint16 usBytesWritten; uint32 ulOutSizeDeviceRecord; if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, HDMX_TAG, pulNewOutOffset)) != NO_ERROR) { if (errCode == ERR_FORMAT) return NO_ERROR; /* not required */ return errCode; } ulHdmxOffset = GetHdmx(pOutputBufferInfo, &Hdmx); if ( !ulHdmxOffset ) return ERR_GENERIC; ulOffset = ulHdmxOffset + GetGenericSize( HDMX_CONTROL ); if (usDttfGlyphIndexCount) /* we want compact form */ { ulInOffset = ulOutOffset = ulOffset; ulOutSizeDeviceRecord = RoundToLongWord(GetGenericSize(HDMX_DEVICE_REC_CONTROL) + (sizeof(uint8) * usDttfGlyphIndexCount)); for( j = 0; j < Hdmx.numDeviceRecords; j++) { ulInDevOffset = ulInOffset; ulOutDevOffset = ulOutOffset; if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *)&DevRecord, SIZEOF_HDMX_DEVICE_REC, HDMX_DEVICE_REC_CONTROL, ulInDevOffset, &usBytesRead )) != NO_ERROR) return errCode; ulInOffset += usBytesRead; ulOutOffset += usBytesRead; maxWidth = 0; for(i = 0, k= 0; i < usGlyphListCount && k < usDttfGlyphIndexCount; i++) /* process each glyph entry */ { if (puchKeepGlyphList[ i ]) { if ((errCode = ReadByte( pOutputBufferInfo, &Width, ulInOffset)) != NO_ERROR) return errCode; maxWidth = max( maxWidth, Width ); if ((errCode = WriteByte( pOutputBufferInfo, Width, ulOutOffset)) != NO_ERROR) return errCode; ulOutOffset += sizeof(uint8); ++k; } ulInOffset += sizeof(uint8); } if ((errCode = ZeroLongWordAlign(pOutputBufferInfo, ulOutOffset, &ulOutOffset)) != NO_ERROR) return errCode; DevRecord.maxWidth = maxWidth; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&DevRecord, SIZEOF_HDMX_DEVICE_REC, HDMX_DEVICE_REC_CONTROL, ulOutDevOffset, &usBytesWritten )) != NO_ERROR) return errCode; ulInOffset = ulInDevOffset + Hdmx.sizeDeviceRecord; ulOutOffset = ulOutDevOffset + ulOutSizeDeviceRecord; } /* now need to update hdmx record */ Hdmx.sizeDeviceRecord = ulOutSizeDeviceRecord; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&Hdmx, SIZEOF_HDMX, HDMX_CONTROL, ulHdmxOffset, &usBytesWritten )) != NO_ERROR) return errCode; if ((errCode = UpdateDirEntry( pOutputBufferInfo, HDMX_TAG, ulOutOffset - ulHdmxOffset )) != NO_ERROR) return errCode; *pulNewOutOffset = ulOutOffset; } else { /* if (GetHHea(pOutputBufferInfo, &Hhea) == 0L) return ERR_FORMAT; */ for( j = 0; j < Hdmx.numDeviceRecords; j++) { ulDevOffset = ulOffset; if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *)&DevRecord, SIZEOF_HDMX_DEVICE_REC, HDMX_DEVICE_REC_CONTROL, ulDevOffset, &usBytesRead )) != NO_ERROR) return errCode; ulOffset += usBytesRead; maxWidth = 0; for(i = 0; i < usGlyphListCount; i++) /* process each glyph entry */ { if (puchKeepGlyphList[ i ]) { if ((errCode = ReadByte( pOutputBufferInfo, &Width, ulOffset)) != NO_ERROR) return errCode; maxWidth = max( maxWidth, Width ); } else /* if (i != Hhea.numLongMetrics-1) clear the value in the file, so the compressor can do its work, except for any dummy entries in the hmtx table */ { if ((errCode = WriteByte( pOutputBufferInfo, (uint8) 0, ulOffset)) != NO_ERROR) return errCode; } ulOffset += sizeof(uint8); } if (DevRecord.maxWidth != maxWidth) /* it's changed, we need to write it out again */ { DevRecord.maxWidth = maxWidth; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&DevRecord, SIZEOF_HDMX_DEVICE_REC, HDMX_DEVICE_REC_CONTROL, ulDevOffset, &usBytesWritten )) != NO_ERROR) return errCode; } ulOffset = ulDevOffset + Hdmx.sizeDeviceRecord; } *pulNewOutOffset = ulOffset; } return NO_ERROR; }
PRIVATE int16 ModMacTrimmedCmap( TTFACC_FILEBUFFERINFO * pOutputBufferInfo, uint32 ulOffset, uint8 *puchKeepGlyphList, uint16 usGlyphCount ) { uint16 i; uint16 GlyphIndex; CMAP_FORMAT6 CmapFormat6; int16 errCode; uint16 usBytesRead; uint16 usBytesWritten; uint16 usNewFirstCode= 0xFFFF; uint16 usNewLastCode=0; /* saved to calc NewEntryCount */ uint32 ulInGlyphOffset; /* to point to a glyph value to read */ uint32 ulOutGlyphOffset; /* to point to a glyph value to write */ if ((errCode = ReadGeneric(pOutputBufferInfo, (uint8 *)&CmapFormat6, SIZEOF_CMAP_FORMAT6, CMAP_FORMAT6_CONTROL, ulOffset, &usBytesRead)) != NO_ERROR) return errCode; ulInGlyphOffset = ulOutGlyphOffset = ulOffset + usBytesRead; /* first figure out where the start and end are */ for ( i = 0; i < CmapFormat6.entryCount; i++ ) { if ((errCode = ReadWord(pOutputBufferInfo, &GlyphIndex, ulInGlyphOffset)) != NO_ERROR) return errCode; if (GlyphIndex < usGlyphCount && puchKeepGlyphList[GlyphIndex] != 0) /* a glyph to be used */ { if (usNewFirstCode == 0xFFFF) /* default first code, set only if hasn't been set already */ usNewFirstCode = CmapFormat6.firstCode + i; /* may be zero */ usNewLastCode = CmapFormat6.firstCode+i; } ulInGlyphOffset += sizeof(GlyphIndex); } if (usNewFirstCode == 0xFFFF) /* none were found */ { CmapFormat6.firstCode = 0; CmapFormat6.entryCount = 0; } else { /* now calculate the new table */ CmapFormat6.firstCode = usNewFirstCode; CmapFormat6.entryCount = usNewLastCode - usNewFirstCode+1; ulInGlyphOffset = ulOutGlyphOffset + usNewFirstCode * sizeof(GlyphIndex); /* where to read the first code */ for ( i = usNewFirstCode; i <= usNewLastCode; i++ ) { if ((errCode = ReadWord(pOutputBufferInfo, &GlyphIndex, ulInGlyphOffset)) != NO_ERROR) return errCode; if (GlyphIndex >= usGlyphCount || puchKeepGlyphList[GlyphIndex] == 0) /* not a glyph to be used */ { if ((errCode = WriteWord(pOutputBufferInfo, (uint16) 0, ulOutGlyphOffset)) != NO_ERROR) return errCode; } else /* write the glyph Index to the new location */ { if ((errCode = WriteWord(pOutputBufferInfo, GlyphIndex, ulOutGlyphOffset)) != NO_ERROR) return errCode; } ulInGlyphOffset += sizeof(GlyphIndex); ulOutGlyphOffset += sizeof(GlyphIndex); } } CmapFormat6.length = (uint16) (ulOutGlyphOffset - ulOffset); /* write out new cmap subtable header */ if ((errCode = WriteGeneric(pOutputBufferInfo, (uint8 *)&CmapFormat6, SIZEOF_CMAP_FORMAT6, CMAP_FORMAT6_CONTROL, ulOffset, &usBytesWritten)) != NO_ERROR) return errCode; return NO_ERROR; }
int16 ModXmtxXhea( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint8 *puchKeepGlyphList, CONST uint16 usGlyphListCount, CONST uint16 usDttfGlyphIndexCount, CONST uint16 usMaxGlyphIndexUsed, BOOL isHmtx, uint32 *pulNewOutOffset) { XHEA XHea; uint16 i,j; uint32 ulXmtxOffset; uint32 ulXheaOffset; uint32 ulCrntOffset; LONGXMETRIC ZeroLongMetric; LONGXMETRIC CurrLongMetric; LONGXMETRIC *LongMetricsArray; uint16 LongMetricSize; int16 errCode; uint16 usBytesRead; uint16 usBytesWritten; uint16 nNewLongMetrics; uint32 ulBytesWritten; const char * xmtx_tag; const char * xhea_tag; /* determine number of long metrics in hmtx table */ if (isHmtx) { xmtx_tag = HMTX_TAG; xhea_tag = HHEA_TAG; if ((ulXheaOffset = GetHHea( pOutputBufferInfo, (HHEA *) &XHea )) == 0L) { /* hasn't been copied yet */ if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, xhea_tag, pulNewOutOffset)) != NO_ERROR) return ERR_INVALID_HHEA; if ((ulXheaOffset = GetHHea( pOutputBufferInfo, (HHEA *) &XHea )) == 0L) return ERR_MISSING_HHEA; /* required table */ } } else { xmtx_tag = VMTX_TAG; xhea_tag = VHEA_TAG; ulXheaOffset = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, xhea_tag); ulXmtxOffset = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, xmtx_tag); if (ulXheaOffset != DIRECTORY_ERROR && ulXmtxOffset == DIRECTORY_ERROR) /* this is bogus, get rid of the vhea table */ { MarkTableForDeletion(pOutputBufferInfo, xhea_tag); /* there is an entry in the output directory */ return (NO_ERROR); } if ((ulXheaOffset = GetVHea( pOutputBufferInfo, (VHEA *) &XHea )) == 0L) { if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, xhea_tag, pulNewOutOffset)) != NO_ERROR) { if (errCode == ERR_FORMAT) return NO_ERROR; /* not required */ else return errCode; } if ((ulXheaOffset = GetVHea( pOutputBufferInfo, (VHEA *) &XHea )) == 0L) return ERR_MISSING_VHEA; /* */ } } if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, xmtx_tag, pulNewOutOffset)) != NO_ERROR) return errCode; ulXmtxOffset = TTTableOffset( pOutputBufferInfo, xmtx_tag); if ((XHea.numLongMetrics == 0) || (XHea.numLongMetrics > usGlyphListCount)) return ERR_INVALID_HHEA_OR_VHEA; /* invalid values */ if (ulXmtxOffset == DIRECTORY_ERROR ) return ERR_MISSING_HMTX_OR_VMTX; /* required table */ ulCrntOffset = ulXmtxOffset; ZeroLongMetric.xsb = 0; ZeroLongMetric.advanceX = 0; LongMetricSize = GetGenericSize(LONGXMETRIC_CONTROL); if (usDttfGlyphIndexCount == 0) /* not trying to make a compact table, just subsetting */ { /* check to see if we will grow. We will grow with subsetting if our last good glyph index is beyond the current numLongMetrics */ if ((XHea.numLongMetrics != usGlyphListCount) && /* if longmetrics is the same as number of glyphs, table won't be growing */ /* need for zero based to 1 base + 1 for the dummy 0 entry */ (usMaxGlyphIndexUsed + 1 + 1 > XHea.numLongMetrics)) /* check if we may make the table grow */ return (ERR_WOULD_GROW); nNewLongMetrics = min(usGlyphListCount, usMaxGlyphIndexUsed + 1 + 1); /* + 1 again for dummy */ /* process all the Long metrics (and perhaps some short when we won't be modifying the table */ for (i = 0; i < nNewLongMetrics; ++i) { if (puchKeepGlyphList[i] == FALSE)/* else we don't want to keep this one, 0 metrics to write */ { if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&ZeroLongMetric, SIZEOF_LONGXMETRIC, LONGXMETRIC_CONTROL, ulCrntOffset, &usBytesWritten)) != NO_ERROR) return (errCode); } ulCrntOffset += LongMetricSize; } /* write out short metrics of 0 for the rest of them*/ for (i = nNewLongMetrics; i < usGlyphListCount; ++i) { if ((errCode = WriteWord(pOutputBufferInfo, 0, ulCrntOffset)) != NO_ERROR) return errCode; ulCrntOffset += sizeof (uint16); } ulBytesWritten = ulCrntOffset - ulXmtxOffset; } else /* we want to make a compact table */ { /* now collapse the table if we are in Compact form for Subsetting and Delta fonts */ /* we will use an interrum table for simplification */ ulCrntOffset = ulXmtxOffset; LongMetricsArray = (LONGXMETRIC *)Mem_Alloc(sizeof(LONGXMETRIC) * usDttfGlyphIndexCount); if (LongMetricsArray == NULL) return ERR_MEM; nNewLongMetrics = 0; for (i = 0, j= 0; i < XHea.numLongMetrics && j < usDttfGlyphIndexCount && errCode == NO_ERROR; ++i) /* need to read and copy up the values */ { if (puchKeepGlyphList[i]) /* if we want to keep the glyph, or its the last special one */ { if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *)&CurrLongMetric, SIZEOF_LONGXMETRIC, LONGXMETRIC_CONTROL, ulCrntOffset, &usBytesRead)) != NO_ERROR) break; LongMetricsArray[j] = CurrLongMetric; ++j; ++nNewLongMetrics; } else if (i == XHea.numLongMetrics-1) /* its that special dummy "last" one, need AW value */ { if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *)&CurrLongMetric, SIZEOF_LONGXMETRIC, LONGXMETRIC_CONTROL, ulCrntOffset, &usBytesRead)) != NO_ERROR) break; ++nNewLongMetrics; /* we will need an extra one, but guarenteed to be <= XHea.numLongMetrics */ } ulCrntOffset += LongMetricSize; } if (errCode != NO_ERROR) { Mem_Free(LongMetricsArray); return errCode; } for (; i < usGlyphListCount && j < usDttfGlyphIndexCount; ++i) /* copy the xsb from the long metrics */ { if (puchKeepGlyphList[i]) { if ((errCode = ReadWord( pOutputBufferInfo, (uint16 *)&(CurrLongMetric.xsb), ulCrntOffset)) != NO_ERROR) break; LongMetricsArray[j] = CurrLongMetric; ++j; } ulCrntOffset += sizeof(uint16); } if (errCode != NO_ERROR) { Mem_Free(LongMetricsArray); return errCode; } if (j != usDttfGlyphIndexCount) { Mem_Free(LongMetricsArray); return ERR_GENERIC; } /* first write out the long metrics */ errCode = WriteGenericRepeat(pOutputBufferInfo,(uint8 *)LongMetricsArray, LONGXMETRIC_CONTROL, ulXmtxOffset,&ulBytesWritten, nNewLongMetrics, SIZEOF_LONGXMETRIC); /* then write out the short metrics */ if (errCode == NO_ERROR) { ulCrntOffset = ulXmtxOffset + ulBytesWritten; for (i = nNewLongMetrics; i < usDttfGlyphIndexCount; ++i) { if ((errCode = WriteWord( pOutputBufferInfo, LongMetricsArray[i].xsb, ulCrntOffset)) != NO_ERROR) break; ulCrntOffset += sizeof(uint16); } } Mem_Free(LongMetricsArray); if (errCode != NO_ERROR) return errCode; ulBytesWritten = ulCrntOffset - ulXmtxOffset; } /* write out our new, shorter length... cleanup comes later */ errCode = UpdateDirEntry( pOutputBufferInfo, xmtx_tag, ulBytesWritten ); if (errCode == NO_ERROR && nNewLongMetrics != XHea.numLongMetrics) { XHea.numLongMetrics = nNewLongMetrics; /* leave these alone if the hmtx table will remain the same */ if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &XHea, SIZEOF_XHEA, XHEA_CONTROL, ulXheaOffset, &usBytesWritten )) != NO_ERROR) return (errCode); } *pulNewOutOffset = ulCrntOffset; return errCode; }
PRIVATE int16 AdjustKernFormat0(TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint8 *puchKeepGlyphList, CONST uint16 usGlyphListCount, KERN_SUB_HEADER KernSubHeader, uint32 ulOffset, uint16 usSubHeaderSize, /* size in file of usSubHeader */ uint16 * pusNewLength) { uint32 ulSourceOffset; uint32 ulTargetOffset; KERN_FORMAT_0 KernFormat0; KERN_PAIR KernPair; uint16 usKernFormat0Size; uint16 i; uint16 usUsedPairs; uint16 usSearchRange; uint16 usRangeShift; uint16 usBytesRead; uint16 usBytesWritten; int16 errCode; /* determine number of kern pairs */ ulSourceOffset = ulOffset + usSubHeaderSize; if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *)&KernFormat0, SIZEOF_KERN_FORMAT_0, KERN_FORMAT_0_CONTROL, ulSourceOffset, &usBytesRead )) != NO_ERROR) return errCode; usKernFormat0Size = usBytesRead; ulSourceOffset += usKernFormat0Size; ulTargetOffset = ulSourceOffset; /* wade through list of pairs, copying those that do not include a deleted glyph and ignoring those that do */ usUsedPairs = 0; for ( i = 0; i < KernFormat0.nPairs; i++ ) { if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *) &KernPair, SIZEOF_KERN_PAIR, KERN_PAIR_CONTROL, ulSourceOffset, &usBytesRead )) != NO_ERROR) return errCode; if (( KernPair.left < usGlyphListCount && puchKeepGlyphList[KernPair.left] ) && ( KernPair.right < usGlyphListCount && puchKeepGlyphList[KernPair.right] )) { if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &KernPair, SIZEOF_KERN_PAIR, KERN_PAIR_CONTROL, ulTargetOffset, &usBytesWritten)) != NO_ERROR) return errCode; ulTargetOffset += usBytesWritten; usUsedPairs++; } ulSourceOffset += usBytesRead; } /* calc and write out revised subtable header */ if (usUsedPairs > 0) { *pusNewLength = (uint16) (ulTargetOffset - ulOffset); KernSubHeader.length = *pusNewLength ; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &KernSubHeader, SIZEOF_KERN_SUB_HEADER, KERN_SUB_HEADER_CONTROL, ulOffset, &usBytesWritten )) != NO_ERROR) return errCode; /* calc and write out revised format 0 header */ usSearchRange = (0x0001 << log2( usUsedPairs )) * GetGenericSize( KERN_PAIR_CONTROL ); usRangeShift = (usUsedPairs * GetGenericSize( KERN_PAIR_CONTROL )) - usSearchRange; KernFormat0.nPairs = usUsedPairs; KernFormat0.searchRange = usSearchRange; KernFormat0.entrySelector = log2( usUsedPairs ); KernFormat0.rangeShift = usRangeShift; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &KernFormat0, SIZEOF_KERN_FORMAT_0, KERN_FORMAT_0_CONTROL, ulOffset + usBytesWritten, &usBytesWritten )) != NO_ERROR) return errCode; } else *pusNewLength = 0; return NO_ERROR; }
void Control::ReadRC(RCFile &rcFile, bool extended) { switch (rcFile.GetTokenId()) { case Lexer::AUTO3STATE: ReadStandard(rcFile, Button, BS_AUTO3STATE | WS_TABSTOP, extended, 1); break; case Lexer::AUTOCHECKBOX: ReadStandard(rcFile, Button, BS_AUTOCHECKBOX | WS_TABSTOP, extended, 1); break; case Lexer::AUTORADIOBUTTON: ReadStandard(rcFile, Button, BS_AUTORADIOBUTTON, extended, 1); break; case Lexer::CHECKBOX: ReadStandard(rcFile, Button, BS_CHECKBOX | WS_TABSTOP, extended, 1); break; case Lexer::COMBOBOX: ReadStandard(rcFile, Combobox, 0, extended, 0); if (!(style &3)) style |= CBS_SIMPLE; break; case Lexer::CTEXT: ReadStandard(rcFile, Static, SS_CENTER | WS_GROUP, extended, 1); break; case Lexer::DEFPUSHBUTTON: ReadStandard(rcFile, Button, BS_DEFPUSHBUTTON | WS_TABSTOP, extended, 1); break; case Lexer::EDITTEXT: ReadStandard(rcFile, Edit, ES_LEFT | WS_BORDER | WS_TABSTOP, extended, 0); break; case Lexer::GROUPBOX: ReadStandard(rcFile, Button, BS_GROUPBOX, extended, 1); break; case Lexer::ICON: ReadStandard(rcFile, Static, SS_ICON, extended, 1); break; case Lexer::LISTBOX: ReadStandard(rcFile, Listbox, LBS_NOTIFY | WS_BORDER, extended, 0); break; case Lexer::LTEXT: ReadStandard(rcFile, Static, SS_LEFT | WS_GROUP, extended, 1); break; case Lexer::PUSHBUTTON: ReadStandard(rcFile, Button, BS_PUSHBUTTON | WS_TABSTOP, extended, 1); break; case Lexer::RADIOBUTTON: ReadStandard(rcFile, Button, BS_RADIOBUTTON, extended, 1); break; case Lexer::RTEXT: ReadStandard(rcFile, Static, SS_RIGHT | WS_GROUP, extended, 1); break; case Lexer::SCROLLBAR: ReadStandard(rcFile, Scrollbar, SBS_HORZ, extended, 0); break; case Lexer::STATE3: ReadStandard(rcFile, Button, BS_3STATE | WS_TABSTOP, extended, 1); break; case Lexer::CONTROL: ReadGeneric(rcFile, extended); break; default: // shouldn't get here break; } rcFile.NeedEol(); }
PRIVATE int16 CopyOffsetDirectoryTables(CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, uint16 usFormat, uint32 * pulNewOutOffset ) { DIRECTORY *aDirectory; DIRECTORY Directory; OFFSET_TABLE OffsetTable; DTTF_HEADER DttfHeader; uint16 usnTables; uint16 usnNewTables; uint32 ulOffset; uint32 ulDttfOffset; uint16 usTableIdx; uint16 usBytesRead; uint16 usBytesWritten; uint32 ulBytesWritten; int16 errCode; ulDttfOffset = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, DTTF_TAG); /* check to see if one there already */ if (ulDttfOffset != DIRECTORY_ERROR) { if ((errCode = ReadGeneric((TTFACC_FILEBUFFERINFO *) pInputBufferInfo, (uint8 *) &DttfHeader, SIZEOF_DTTF_HEADER, DTTF_HEADER_CONTROL, ulDttfOffset, &usBytesRead)) != NO_ERROR) return(errCode); if (DttfHeader.format != TTFDELTA_MERGE) /* only acceptable delta font at this time */ return(ERR_INVALID_DELTA_FORMAT); } /* read offset table and determine number of existing tables */ ulOffset = pInputBufferInfo->ulOffsetTableOffset; if ((errCode = ReadGeneric((TTFACC_FILEBUFFERINFO *) pInputBufferInfo, (uint8 *) &OffsetTable, SIZEOF_OFFSET_TABLE, OFFSET_TABLE_CONTROL, ulOffset, &usBytesRead)) != NO_ERROR) return(errCode); usnTables = OffsetTable.numTables; ulOffset += usBytesRead; /* Create a list of valid tables */ aDirectory = (DIRECTORY *) Mem_Alloc((usnTables + (ulDttfOffset == 0)) * sizeof(DIRECTORY)); /* one extra for possible private table */ if (aDirectory == NULL) return(ERR_MEM); /* sort directories by offset */ for ( usTableIdx = usnNewTables = 0; usTableIdx < usnTables; usTableIdx++ ) { errCode = ReadGeneric((TTFACC_FILEBUFFERINFO *)pInputBufferInfo, (uint8 *) &Directory, SIZEOF_DIRECTORY, DIRECTORY_CONTROL, ulOffset, &usBytesRead); ulOffset += usBytesRead; if (errCode != NO_ERROR) { Mem_Free(aDirectory); return errCode; } if (usFormat == TTFDELTA_DELTA) /* need to get rid of some of the tables */ { switch(Directory.tag)/* only want to keep these */ { /* tables sent each time */ case HEAD_LONG_TAG: case MAXP_LONG_TAG: case HHEA_LONG_TAG: case VHEA_LONG_TAG: /* tables subsetted */ case CMAP_LONG_TAG: case GLYF_LONG_TAG: case EBLC_LONG_TAG: case EBDT_LONG_TAG: case BLOC_LONG_TAG: case BDAT_LONG_TAG: /* tables compacted */ case LTSH_LONG_TAG: case HMTX_LONG_TAG: case VMTX_LONG_TAG: case HDMX_LONG_TAG: case LOCA_LONG_TAG: /* private table - keep shell */ case DTTF_LONG_TAG: break; default: /* any others, just get rid of */ continue; /* don't copy this over */ } } /* empty out the entries */ aDirectory[ usnNewTables ].length = 0; aDirectory[ usnNewTables ].offset = DIRECTORY_ERROR; aDirectory[ usnNewTables ].tag = Directory.tag; /* don't worry about the checksum */ ++ usnNewTables; } /* add in dttf entry */ if (ulDttfOffset == 0 && usFormat == TTFDELTA_SUBSET1 || usFormat == TTFDELTA_DELTA) { aDirectory[ usnNewTables].length = 0; aDirectory[ usnNewTables].offset = DIRECTORY_ERROR; aDirectory[ usnNewTables].tag = DTTF_LONG_TAG; ++usnNewTables; SortByTag( aDirectory, usnNewTables ); /* to insert the dttf table */ } OffsetTable.numTables = usnNewTables; /* don't worry if other fields not ok, will be updated in compress tables */ ulOffset = pOutputBufferInfo->ulOffsetTableOffset; errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &OffsetTable, SIZEOF_OFFSET_TABLE, OFFSET_TABLE_CONTROL, ulOffset, &usBytesWritten); /* write out the new directory info to the output buffer */ ulOffset += usBytesWritten; if (errCode == NO_ERROR) { errCode = WriteGenericRepeat( pOutputBufferInfo, (uint8 *) aDirectory, DIRECTORY_CONTROL, ulOffset, &ulBytesWritten, usnNewTables, SIZEOF_DIRECTORY ); if (errCode == NO_ERROR) *pulNewOutOffset = ulOffset+ulBytesWritten; /* end of written to data */ } Mem_Free(aDirectory); return(errCode); }
int16 ModCmap(CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, uint8 *puchKeepGlyphList, /* glyphs to keep - boolean */ uint16 usGlyphCount, /* count of puchKeepGlyphList */ uint16 * pOS2MinChr, /* for setting in the OS/2 table */ uint16 * pOS2MaxChr, /* for setting in the OS/2 table */ uint32 *pulNewOutOffset) { FORMAT4_SEGMENTS *NewFormat4Segments = NULL; /* used to create a Segments array for format 4 subtables */ FORMAT12_GROUPS *NewFormat12Groups = NULL; uint16 usnSegment; GLYPH_ID *NewFormat4GlyphIdArray = NULL; /* used to create a GlyphID array for format 4 subtables */ uint16 snFormat4GlyphIdArray; CMAP_FORMAT4 CmapFormat4; CMAP_FORMAT12 CmapFormat12; CMAP_TABLELOC *pCmapTableLoc=NULL; uint16 usSubTableCount; CMAP_SUBHEADER_GEN CmapSubHeader; PCHAR_GLYPH_MAP_LIST pCharGlyphMapList = NULL; /* sorted list of character codes to keep and their glyph indices */ uint16 usnCharGlyphMapListCount= 0; /* length of pCharGlyphMapList array */ PCHAR_GLYPH_MAP_LIST_EX pCharGlyphMapListEx = NULL; /* sorted list of character codes to keep and their glyph indices */ uint32 ulnCharGlyphMapListCount= 0; /* length of pCharGlyphMapListEx array */ CMAPOFFSETRECORDKEEPER CmapSubtableKeeper; uint32 ulCmapOffset; uint32 ulCmapLength; uint32 ulCmapNewLength; uint32 ulCmapSubTableDirOffset; uint32 ulCmapSubtableNewOffset; uint32 ulBytesWritten; uint16 i; int16 errCode= NO_ERROR; uint16 usBytesRead; if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, CMAP_TAG, pulNewOutOffset)) != NO_ERROR) return errCode; ulCmapOffset = TTTableOffset( pOutputBufferInfo, CMAP_TAG ); ulCmapLength = TTTableLength( pOutputBufferInfo, CMAP_TAG); *pOS2MinChr = 0; *pOS2MaxChr = 0; if (ulCmapOffset == 0L || ulCmapLength == 0L) return ERR_INVALID_CMAP; /* huh?*/ usSubTableCount = GetCmapSubtableCount(pOutputBufferInfo, ulCmapOffset); pCmapTableLoc = (CMAP_TABLELOC *)Mem_Alloc(SIZEOF_CMAP_TABLELOC * usSubTableCount); if (pCmapTableLoc == NULL) return ERR_MEM; ulCmapSubTableDirOffset = ulCmapOffset + GetGenericSize( CMAP_HEADER_CONTROL ); if (InitCmapOffsetArray(&CmapSubtableKeeper, usSubTableCount) != NO_ERROR) { return ERR_MEM; } for (i = 0; i < usSubTableCount; ++i) { /* read the cmap directory entry */ if ((errCode = ReadGeneric(pOutputBufferInfo, (uint8 *) &(pCmapTableLoc[i]), SIZEOF_CMAP_TABLELOC, CMAP_TABLELOC_CONTROL, ulCmapSubTableDirOffset, &usBytesRead)) != NO_ERROR) break; ulCmapSubTableDirOffset += usBytesRead; /* for next time around */ /* Check to see if this subtable is shared, and has been modified already */ if ((ulCmapSubtableNewOffset = LookupCmapOffset(&CmapSubtableKeeper, pCmapTableLoc[i].offset)) != 0) { pCmapTableLoc[i].offset = ulCmapSubtableNewOffset; continue; } /* now read the CmapSub Header, to determine the format */ if ((errCode = ReadCmapLength(pOutputBufferInfo, &CmapSubHeader, ulCmapOffset + pCmapTableLoc[i].offset, &usBytesRead)) != NO_ERROR) break; /* Will subset: Format 0, Format 4 ,Format 6 and Format 12 Cmap Subtables */ /* Otherwise, leave them alone */ if (CmapSubHeader.format == FORMAT0_CMAP_FORMAT) { if ((errCode = ModMacStandardCmap(pOutputBufferInfo, ulCmapOffset + pCmapTableLoc[i].offset + usBytesRead, puchKeepGlyphList, usGlyphCount)) != NO_ERROR) break; } else if (CmapSubHeader.format == FORMAT6_CMAP_FORMAT) { if ((errCode = ModMacTrimmedCmap(pOutputBufferInfo, ulCmapOffset + pCmapTableLoc[i].offset, puchKeepGlyphList, usGlyphCount)) != NO_ERROR) break; } else if (CmapSubHeader.format == FORMAT4_CMAP_FORMAT) { /* process Format 4 Cmap Subtable */ /*need to come up with a CharCodeList, from the puchKeepGlyphList */ errCode = ReadAllocFormat4CharGlyphMapList(pOutputBufferInfo, pCmapTableLoc[i].platformID, pCmapTableLoc[i].encodingID, puchKeepGlyphList, usGlyphCount, &pCharGlyphMapList, &usnCharGlyphMapListCount); if (errCode != NO_ERROR) break; NewFormat4Segments = (FORMAT4_SEGMENTS *) Mem_Alloc( (usnCharGlyphMapListCount+1) * SIZEOF_FORMAT4_SEGMENTS ); /* add one for the extra dummy segment */ NewFormat4GlyphIdArray = (GLYPH_ID *) Mem_Alloc( usnCharGlyphMapListCount * sizeof( *NewFormat4GlyphIdArray ) ); if ( NewFormat4Segments == NULL || NewFormat4GlyphIdArray == NULL ) { errCode = ERR_MEM; break; } /* compute new format 4 data */ ComputeFormat4CmapData( &CmapFormat4, NewFormat4Segments, &usnSegment, NewFormat4GlyphIdArray, &snFormat4GlyphIdArray, pCharGlyphMapList, usnCharGlyphMapListCount ); /* Donald, if you don't care if the Cmap subtable grows, you could comment out the next line */ if (CmapFormat4.length <= CmapSubHeader.length) /* if the new length is smaller than the old, we can write it in the old place */ { if (pCmapTableLoc[i].platformID == MS_PLATFORMID) /* only applies to this platform */ { *pOS2MinChr = pCharGlyphMapList[0].usCharCode; *pOS2MaxChr = pCharGlyphMapList[usnCharGlyphMapListCount-1].usCharCode; } errCode = WriteOutFormat4CmapData( pOutputBufferInfo, &CmapFormat4, NewFormat4Segments, NewFormat4GlyphIdArray, usnSegment, snFormat4GlyphIdArray, ulCmapOffset + pCmapTableLoc[i].offset, &ulBytesWritten ); } /* else: leave cmap subtable alone */ /* clean up */ Mem_Free(NewFormat4Segments); Mem_Free(NewFormat4GlyphIdArray ); FreeFormat4CharCodes(pCharGlyphMapList); NewFormat4Segments = NULL; NewFormat4GlyphIdArray = NULL; pCharGlyphMapList = NULL; } else if (CmapSubHeader.format == FORMAT12_CMAP_FORMAT) { uint32 ulnGroups = 0; /*need to come up with a CharCodeList, from the puchKeepGlyphList */ errCode = ReadAllocFormat12CharGlyphMapList(pOutputBufferInfo, ulCmapOffset + pCmapTableLoc[i].offset, puchKeepGlyphList, usGlyphCount, &pCharGlyphMapListEx, &ulnCharGlyphMapListCount); if (errCode != NO_ERROR) break; NewFormat12Groups = (FORMAT12_GROUPS *) Mem_Alloc( (ulnCharGlyphMapListCount) * SIZEOF_FORMAT12_GROUPS ); if ( NewFormat12Groups == NULL) { errCode = ERR_MEM; break; } /* compute new format 12 data */ ComputeFormat12CmapData( &CmapFormat12, NewFormat12Groups, &ulnGroups, pCharGlyphMapListEx, ulnCharGlyphMapListCount ); /* Donald, if you don't care if the Cmap subtable grows, you could comment out the next line */ if (CmapFormat12.length <= CmapSubHeader.length) /* if the new length is smaller than the old, we can write it in the old place */ { if (pCmapTableLoc[i].platformID == MS_PLATFORMID) /* only applies to this platform */ { *pOS2MinChr = (uint16)pCharGlyphMapListEx[0].ulCharCode; *pOS2MaxChr = (uint16)pCharGlyphMapListEx[ulnCharGlyphMapListCount-1].ulCharCode; } errCode = WriteOutFormat12CmapData( pOutputBufferInfo, &CmapFormat12, NewFormat12Groups, ulnGroups, ulCmapOffset + pCmapTableLoc[i].offset, &ulBytesWritten ); } /* else: leave cmap subtable alone */ /* clean up */ Mem_Free(NewFormat12Groups); FreeFormat12CharCodes(pCharGlyphMapListEx); NewFormat12Groups = NULL; pCharGlyphMapListEx = NULL; } RecordCmapOffset(&CmapSubtableKeeper, pCmapTableLoc[i].offset, pCmapTableLoc[i].offset); /* record the new offset (didn't change) */ } /* now need to compress out empty bytes from ends of Cmap Subtables */ if (errCode == NO_ERROR) { errCode = CompressCmapSubTables(pOutputBufferInfo, pCmapTableLoc, usSubTableCount, ulCmapOffset, ulCmapSubTableDirOffset, ulCmapLength, &ulCmapNewLength); *pulNewOutOffset = ulCmapOffset + ulCmapNewLength; /* hand back to caller */ } else /* these weren't taken care of yet (necessarily) */ { Mem_Free(NewFormat4Segments); /* may be non-null */ Mem_Free(NewFormat4GlyphIdArray ); FreeFormat4CharCodes(pCharGlyphMapList); if (errCode == ERR_WOULD_GROW) /* fragmentation has caused a larger cmap table, copy table again */ { *pulNewOutOffset = ulCmapOffset; /* reset */ errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, CMAP_TAG, pulNewOutOffset); } } Mem_Free(pCmapTableLoc); FreeCmapOffsetArray(&CmapSubtableKeeper); return errCode; } /* ModCmap() */
int16 TTOAutoMap( TTFACC_FILEBUFFERINFO * pInputBufferInfo, /* ttfacc info */ uint8 * pabKeepGlyphs, /* binary list of glyphs to keep - to be updated here */ uint16 usnGlyphs, /* number of glyphs in list */ uint16 fKeepFlag) /* flag index (really contains a number) of what to set in the pabKeepGlyph list */ { GSUBHEADER GSUBHeader; GSUBLOOKUPLIST GSUBLookupList, *pGSUBLookupList = NULL; JSTFHEADER JSTFHeader; JSTFSCRIPTRECORD *ScriptRecordArray; JSTFSCRIPT JSTFScript; JSTFEXTENDERGLYPH JSTFExtenderGlyph; uint16 *GlyphIDArray; BASEHEADER BASEHeader; BASEAXIS BASEAxis; BASESCRIPTLIST BASEScriptList; BASESCRIPTRECORD BASEScriptRecord; BASESCRIPT BASEScript; BASEVALUES BASEValues; BASELANGSYSRECORD BASELangSysRecord; uint16 BASECoordOffset; uint16 AxisOffset; uint32 ulHeaderOffset; uint32 ulCurrentOffset; uint32 ulLangSysOffset; uint16 usMaxLookupCount; uint32 ulOffset; uint16 i, j, k; uint16 usBytesRead; uint32 ulBytesRead; int16 errCode = NO_ERROR; /* Process GSUB Table */ while (1) /* so we can break out on null offsets */ { ulHeaderOffset = TTTableOffset( pInputBufferInfo, GSUB_TAG ); if (ulHeaderOffset == 0) break; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBHeader, SIZEOF_GSUBHEADER, GSUBHEADER_CONTROL, ulHeaderOffset, &usBytesRead ) )!= NO_ERROR) return errCode; /* now read the max number of lookups, for allocation of the lookup list */ if (GSUBHeader.LookupListOffset == 0) break; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBLookupList, SIZEOF_GSUBLOOKUPLIST, GSUBLOOKUPLIST_CONTROL, ulHeaderOffset + GSUBHeader.LookupListOffset, &usBytesRead) )!= NO_ERROR) return errCode; usMaxLookupCount = GSUBLookupList.LookupCount; if (usMaxLookupCount == 0) break; while (1) /* so we can break out and clean up on error */ /* Now look at lookup table, and add to list from Context lookups */ { GSUBLOOKUP GSUBLookup; uint16 *SubstTableOffsetArray = NULL; ulOffset = ulHeaderOffset + GSUBHeader.LookupListOffset; pGSUBLookupList = (GSUBLOOKUPLIST *)Mem_Alloc(SIZEOF_GSUBLOOKUPLIST + usMaxLookupCount * sizeof(uint16)); if (pGSUBLookupList == NULL) { errCode = ERR_MEM; break; } /* read the first part */ if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *) pGSUBLookupList, SIZEOF_GSUBLOOKUPLIST, GSUBLOOKUPLIST_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; /* now read the array */ if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *) ((uint8 *)pGSUBLookupList + SIZEOF_GSUBLOOKUPLIST), WORD_CONTROL, ulOffset + usBytesRead, &ulBytesRead, usMaxLookupCount, sizeof(uint16)) )!= NO_ERROR) break; /* now make sure all the referenced glyphs are in the keep table */ for (i = 0; i < usMaxLookupCount; ++i) { uint16 usSubTableCount; if (pGSUBLookupList->LookupTableOffsetArray[i] == 0) continue; ulOffset = ulHeaderOffset + GSUBHeader.LookupListOffset + pGSUBLookupList->LookupTableOffsetArray[i]; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBLookup, SIZEOF_GSUBLOOKUP, GSUBLOOKUP_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; if (GSUBLookup.LookupType == GSUBContextLookupType) /* not looking for context lookups */ continue; usSubTableCount = GSUBLookup.SubTableCount; SubstTableOffsetArray = (uint16 *)Mem_Alloc(sizeof(uint16) * usSubTableCount); if (SubstTableOffsetArray == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *) SubstTableOffsetArray, WORD_CONTROL, ulOffset + usBytesRead, &ulBytesRead, usSubTableCount, sizeof(uint16)) )!= NO_ERROR) break; for (j = 0; j < usSubTableCount; ++j) { uint16 Format; if (SubstTableOffsetArray[j] == 0) continue; ulOffset = ulHeaderOffset + GSUBHeader.LookupListOffset + pGSUBLookupList->LookupTableOffsetArray[i] + SubstTableOffsetArray[j]; if ((errCode = ReadWord( pInputBufferInfo, &Format, ulOffset) )!= NO_ERROR) break; switch(GSUBLookup.LookupType) { case GSUBSingleLookupType: { switch (Format) { case 1: { GSUBSINGLESUBSTFORMAT1 GSUBSubstTable; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBSubstTable, SIZEOF_GSUBSINGLESUBSTFORMAT1, GSUBSINGLESUBSTFORMAT1_CONTROL, ulOffset, &usBytesRead) )== NO_ERROR) errCode = UpdateKeepWithCoverage( pInputBufferInfo, pabKeepGlyphs, usnGlyphs, fKeepFlag, ulOffset, GSUBSubstTable.CoverageOffset , (uint16 *) &(GSUBSubstTable.DeltaGlyphID), GSUBLookup.LookupType, Format); break; } case 2: { GSUBSINGLESUBSTFORMAT2 GSUBSubstTable; uint16 usGlyphCount; uint16 *pGlyphIDArray = NULL; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBSubstTable, SIZEOF_GSUBSINGLESUBSTFORMAT2, GSUBSINGLESUBSTFORMAT2_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; usGlyphCount = GSUBSubstTable.GlyphCount; pGlyphIDArray = (uint16 *)Mem_Alloc(sizeof(uint16) * usGlyphCount); if (pGlyphIDArray == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pGlyphIDArray, WORD_CONTROL, ulOffset + usBytesRead, &ulBytesRead, usGlyphCount, sizeof(uint16)) )== NO_ERROR) errCode = UpdateKeepWithCoverage( pInputBufferInfo, pabKeepGlyphs, usnGlyphs, fKeepFlag, ulOffset, GSUBSubstTable.CoverageOffset , pGlyphIDArray, GSUBLookup.LookupType, Format); Mem_Free(pGlyphIDArray); break; } default: errCode = ERR_INVALID_GSUB; break; } break; } case GSUBMultipleLookupType: { GSUBMULTIPLESUBSTFORMAT1 GSUBSubstTable; uint16 usCount; uint16 *pOffsetArray = NULL; if (Format != 1) break; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBSubstTable, SIZEOF_GSUBMULTIPLESUBSTFORMAT1, GSUBMULTIPLESUBSTFORMAT1_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; usCount = GSUBSubstTable.SequenceCount; pOffsetArray = (uint16 *)Mem_Alloc(sizeof(uint16) * usCount); if (pOffsetArray == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pOffsetArray, WORD_CONTROL, ulOffset + usBytesRead, &ulBytesRead, usCount, sizeof(uint16)) )== NO_ERROR) errCode = UpdateKeepWithCoverage( pInputBufferInfo, pabKeepGlyphs, usnGlyphs, fKeepFlag, ulOffset, GSUBSubstTable.CoverageOffset , pOffsetArray, GSUBLookup.LookupType, Format); Mem_Free(pOffsetArray); break; } case GSUBAlternateLookupType: { GSUBALTERNATESUBSTFORMAT1 GSUBSubstTable; uint16 usCount; uint16 *pOffsetArray = NULL; if (Format != 1) break; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBSubstTable, SIZEOF_GSUBALTERNATESUBSTFORMAT1, GSUBALTERNATESUBSTFORMAT1_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; usCount = GSUBSubstTable.AlternateSetCount; pOffsetArray = (uint16 *)Mem_Alloc(sizeof(uint16) * usCount); if (pOffsetArray == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pOffsetArray, WORD_CONTROL, ulOffset + usBytesRead, &ulBytesRead, usCount, sizeof(uint16)) )== NO_ERROR) errCode = UpdateKeepWithCoverage( pInputBufferInfo, pabKeepGlyphs, usnGlyphs, fKeepFlag, ulOffset, GSUBSubstTable.CoverageOffset , pOffsetArray, GSUBLookup.LookupType, Format); Mem_Free(pOffsetArray); break; } case GSUBLigatureLookupType: { GSUBLIGATURESUBSTFORMAT1 GSUBSubstTable; uint16 usCount; uint16 *pOffsetArray = NULL; if (Format != 1) break; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBSubstTable, SIZEOF_GSUBLIGATURESUBSTFORMAT1, GSUBLIGATURESUBSTFORMAT1_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; usCount = GSUBSubstTable.LigatureSetCount; pOffsetArray = (uint16 *)Mem_Alloc(sizeof(uint16) * usCount); if (pOffsetArray == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pOffsetArray, WORD_CONTROL, ulOffset + usBytesRead, &ulBytesRead, usCount, sizeof(uint16)) )== NO_ERROR) errCode = UpdateKeepWithCoverage( pInputBufferInfo, pabKeepGlyphs, usnGlyphs, fKeepFlag, ulOffset, GSUBSubstTable.CoverageOffset , pOffsetArray, GSUBLookup.LookupType, Format); Mem_Free(pOffsetArray); break; } default: break; } if (errCode != NO_ERROR) break; } Mem_Free(SubstTableOffsetArray); if (errCode != NO_ERROR) break; } break; /* artificial while for error conditions */ } Mem_Free(pGSUBLookupList); break; } if (errCode != NO_ERROR) return errCode; /* Process JSTF Table */ while (1) /* so we can break out on NULL offsets */ { ulHeaderOffset = TTTableOffset( pInputBufferInfo, JSTF_TAG ); if (ulHeaderOffset == 0) break; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&JSTFHeader, SIZEOF_JSTFHEADER, JSTFHEADER_CONTROL, ulHeaderOffset, &usBytesRead ) )!= NO_ERROR) break; ScriptRecordArray = (JSTFSCRIPTRECORD *)Mem_Alloc(SIZEOF_JSTFSCRIPTRECORD * JSTFHeader.ScriptCount); if (ScriptRecordArray == NULL) { errCode = ERR_MEM; break; } ulOffset = ulHeaderOffset; if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)ScriptRecordArray, JSTFSCRIPTRECORD_CONTROL, ulOffset + usBytesRead, & ulBytesRead, JSTFHeader.ScriptCount, SIZEOF_JSTFSCRIPTRECORD ) )!= NO_ERROR) break; for (i = 0 ; i < JSTFHeader.ScriptCount; ++i) { if (ScriptRecordArray[i].JstfScriptOffset == 0) continue; ulOffset = ulHeaderOffset + ScriptRecordArray[i].JstfScriptOffset; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&JSTFScript, SIZEOF_JSTFSCRIPT, JSTFSCRIPT_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; if (JSTFScript.ExtenderGlyphOffset == 0) continue; ulOffset = ulOffset = ulHeaderOffset + ScriptRecordArray[i].JstfScriptOffset + JSTFScript.ExtenderGlyphOffset; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&JSTFExtenderGlyph, SIZEOF_JSTFEXTENDERGLYPH, JSTFEXTENDERGLYPH_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) break; GlyphIDArray = (uint16 *)Mem_Alloc((sizeof(uint16) * JSTFExtenderGlyph.ExtenderGlyphCount)); if (GlyphIDArray == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)GlyphIDArray, WORD_CONTROL, ulOffset + usBytesRead, &ulBytesRead, JSTFExtenderGlyph.ExtenderGlyphCount, sizeof(uint16)) )== NO_ERROR) { for (j = 0; j < JSTFExtenderGlyph.ExtenderGlyphCount; ++j) { if (GlyphIDArray[j] < usnGlyphs && pabKeepGlyphs[GlyphIDArray[j]] == 0) pabKeepGlyphs[GlyphIDArray[j]] = (uint8)(fKeepFlag + 1); } } Mem_Free(GlyphIDArray); if (errCode != NO_ERROR) break; } Mem_Free(ScriptRecordArray); break; } if (errCode != NO_ERROR) return errCode; /* Process BASE Table */ while (1) { ulHeaderOffset = TTTableOffset( pInputBufferInfo, BASE_TAG ); if (ulHeaderOffset == 0) break; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEHeader, SIZEOF_BASEHEADER, BASEHEADER_CONTROL, ulHeaderOffset, &usBytesRead ) )!= NO_ERROR) break; AxisOffset = BASEHeader.HorizAxisOffset; for (i = 0; i < 2; ++i, AxisOffset = BASEHeader.VertAxisOffset) /* process the 2 axis */ { if (AxisOffset == 0) continue; ulOffset = ulHeaderOffset + AxisOffset; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEAxis, SIZEOF_BASEAXIS, BASEAXIS_CONTROL, ulOffset, &usBytesRead ) )!= NO_ERROR) break; if (BASEAxis.BaseScriptListOffset == 0) continue; ulOffset = ulHeaderOffset + AxisOffset + BASEAxis.BaseScriptListOffset; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEScriptList, SIZEOF_BASESCRIPTLIST, BASESCRIPTLIST_CONTROL, ulOffset, &usBytesRead ) )!= NO_ERROR) break; ulCurrentOffset = ulOffset + usBytesRead; for (j = 0; j < BASEScriptList.BaseScriptCount; ++j) { uint32 ulLocalOffset; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEScriptRecord, SIZEOF_BASESCRIPTRECORD, BASESCRIPTRECORD_CONTROL, ulCurrentOffset, &usBytesRead ) )!= NO_ERROR) break; ulCurrentOffset += usBytesRead; if (BASEScriptRecord.BaseScriptOffset == 0) continue; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEScript, SIZEOF_BASESCRIPT, BASESCRIPT_CONTROL, ulOffset + BASEScriptRecord.BaseScriptOffset, &usBytesRead ) )!= NO_ERROR) break; ulLangSysOffset = ulOffset + BASEScriptRecord.BaseScriptOffset + usBytesRead; /* PROCESS BaseValuesOffset */ if (BASEScript.BaseValuesOffset != 0) { ulLocalOffset = ulOffset + BASEScriptRecord.BaseScriptOffset + BASEScript.BaseValuesOffset ; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASEValues, SIZEOF_BASEVALUES, BASEVALUES_CONTROL, ulLocalOffset, &usBytesRead ) )!= NO_ERROR) break; ulLocalOffset += usBytesRead; for (k = 0; k < BASEValues.BaseCoordCount; ++k) { if ((errCode = ReadWord( pInputBufferInfo, &BASECoordOffset, ulLocalOffset ) )!= NO_ERROR) break; ulLocalOffset += sizeof(uint16); if ((errCode = ProcessBaseCoord( pInputBufferInfo, ulOffset + BASEScriptRecord.BaseScriptOffset + BASEScript.BaseValuesOffset + BASECoordOffset, pabKeepGlyphs, usnGlyphs, fKeepFlag))!= NO_ERROR) break; } if (errCode != NO_ERROR) break; } /* Process MinMaxOffset */ if (BASEScript.MinMaxOffset != 0) { ulLocalOffset = ulOffset + BASEScriptRecord.BaseScriptOffset + BASEScript.MinMaxOffset ; if ((errCode = ProcessMinMax( pInputBufferInfo, ulLocalOffset, pabKeepGlyphs, usnGlyphs, fKeepFlag))!= NO_ERROR) break; } /* Process BaseLangSysRecordArray */ for (k = 0; k < BASEScript.BaseLangSysCount; ++k) { if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&BASELangSysRecord, SIZEOF_BASELANGSYSRECORD, BASELANGSYSRECORD_CONTROL, ulLangSysOffset, &usBytesRead ) )!= NO_ERROR) break; ulLangSysOffset += usBytesRead; if (BASELangSysRecord.MinMaxOffset != 0) if ((errCode = ProcessMinMax( pInputBufferInfo, ulOffset + BASEScriptRecord.BaseScriptOffset + BASELangSysRecord.MinMaxOffset, pabKeepGlyphs, usnGlyphs, fKeepFlag))!= NO_ERROR) break; } if (errCode != NO_ERROR) break; } if (errCode != NO_ERROR) break; } break; } return errCode; }
static int16 UpdateKeepWithCoverage(TTFACC_FILEBUFFERINFO * pInputBufferInfo, uint8 * pabKeepGlyphs, uint16 usnGlyphs, uint16 fKeepFlag, uint32 ulBaseOffset, uint32 ulCoverageOffset, uint16 *pArray, uint16 usLookupType, uint16 usSubstFormat) { uint32 ulOffset; uint16 usCoverageFormat; GSUBCOVERAGEFORMAT1 Coverage1; GSUBCOVERAGEFORMAT2 Coverage2; uint16 usCount; /* number of array elements in coverage table */ uint16 usGlyphCount; /* number of glyphs processed in Coverage Table */ uint16 usGlyphID; uint16 *pGlyphIDArray = NULL; GSUBRANGERECORD *pRangeRecordArray = NULL; uint16 i, j, k, l; uint16 usBytesRead; uint32 ulBytesRead; int16 errCode = NO_ERROR; if ((ulCoverageOffset == 0) || (pArray == NULL)) return NO_ERROR; ulOffset = ulBaseOffset + ulCoverageOffset; if ((errCode = ReadWord( pInputBufferInfo, &usCoverageFormat, ulOffset)) != NO_ERROR) return errCode; /* OK, read in the actual Coverage Table */ switch (usCoverageFormat) { case 1: if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&Coverage1, SIZEOF_GSUBCOVERAGEFORMAT1, GSUBCOVERAGEFORMAT1_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) return errCode; ulOffset += usBytesRead; usCount = Coverage1.GlyphCount; pGlyphIDArray = (uint16 *)Mem_Alloc(usCount * sizeof(uint16)); if (pGlyphIDArray == NULL) return ERR_MEM; if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pGlyphIDArray, WORD_CONTROL, ulOffset, &ulBytesRead, usCount, sizeof(uint16)) )!= NO_ERROR) { Mem_Free(pGlyphIDArray); return errCode; } break; case 2: if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&Coverage2, SIZEOF_GSUBCOVERAGEFORMAT2, GSUBCOVERAGEFORMAT2_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) return errCode; ulOffset += usBytesRead; usCount = Coverage2.CoverageRangeCount; pRangeRecordArray = (GSUBRANGERECORD *)Mem_Alloc(usCount * SIZEOF_GSUBRANGERECORD); if (pRangeRecordArray == NULL) return ERR_MEM; if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *) pRangeRecordArray, GSUBRANGERECORD_CONTROL, ulOffset, &ulBytesRead, usCount, SIZEOF_GSUBRANGERECORD) )!= NO_ERROR) { Mem_Free(pRangeRecordArray); return errCode; } break; default: return ERR_INVALID_TTO; } for (i = 0, j = 0, usGlyphCount = 0; i < usCount && errCode == NO_ERROR; ++usGlyphCount) /* while the entire Coverage Table has not been processed */ { /* First, get a glyph Code from coverage table */ if (usCoverageFormat == 1) { usGlyphID = pGlyphIDArray[i]; ++i; } else { usGlyphID = (uint16) (pRangeRecordArray[i].RangeStart + j); if (usGlyphID < pRangeRecordArray[i].RangeEnd) ++j; else /* go to next range */ { ++i; j = 0; } } /* Next, see if it exists, and deal with corresponding Substitute data */ if (usGlyphID >= usnGlyphs || pabKeepGlyphs[usGlyphID] != fKeepFlag) continue; /* now read in the actual Subtitute Glyph Data and process */ switch (usLookupType) { case GSUBSingleLookupType: if (usSubstFormat == 1) { if ((usGlyphID + (int16) *pArray) < usnGlyphs && pabKeepGlyphs[usGlyphID + (int16) *pArray] == 0) pabKeepGlyphs[usGlyphID + (int16) *pArray] = (uint8)(fKeepFlag + 1); } else { if (pArray[usGlyphCount] < usnGlyphs && pabKeepGlyphs[pArray[usGlyphCount]] == 0) pabKeepGlyphs[pArray[usGlyphCount]] = (uint8)(fKeepFlag + 1); } break; case GSUBMultipleLookupType: { uint16 usSequenceGlyphCount; uint16 *pausGlyphID = NULL; if (pArray[usGlyphCount] == 0) break; ulOffset = ulBaseOffset + pArray[usGlyphCount]; if ((errCode = ReadWord( pInputBufferInfo, &usSequenceGlyphCount, ulOffset ) )!= NO_ERROR) break; ulOffset += sizeof(uint16); pausGlyphID = (uint16 *)Mem_Alloc(usSequenceGlyphCount * sizeof(uint16)); if (pausGlyphID == NULL) { errCode = ERR_MEM; break; } errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pausGlyphID, WORD_CONTROL, ulOffset, &ulBytesRead, usSequenceGlyphCount, sizeof(uint16)); if (errCode == NO_ERROR) { for (k = 0; k < usSequenceGlyphCount; ++k) { if (pausGlyphID[k] < usnGlyphs && pabKeepGlyphs[pausGlyphID[k]] == 0) pabKeepGlyphs[pausGlyphID[k]] = (uint8)(fKeepFlag + 1); } } Mem_Free (pausGlyphID); break; } case GSUBAlternateLookupType: { uint16 usAlternateGlyphCount; uint16 *pausGlyphID = NULL; if (pArray[usGlyphCount] == 0) break; ulOffset = ulBaseOffset + pArray[usGlyphCount]; if ((errCode = ReadWord( pInputBufferInfo, &usAlternateGlyphCount, ulOffset ) )!= NO_ERROR) break; ulOffset += sizeof(uint16); pausGlyphID = (uint16 *)Mem_Alloc(usAlternateGlyphCount * sizeof(uint16)); if (pausGlyphID == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pausGlyphID, WORD_CONTROL, ulOffset, &ulBytesRead, usAlternateGlyphCount, sizeof(uint16)) )== NO_ERROR) { for (k = 0; k < usAlternateGlyphCount; ++k) { if (pausGlyphID[k] < usnGlyphs && pabKeepGlyphs[pausGlyphID[k]] == 0) pabKeepGlyphs[pausGlyphID[k]] = (uint8)(fKeepFlag + 1); } } Mem_Free (pausGlyphID); break; } case GSUBLigatureLookupType: { uint16 usLigatureCompCount; uint16 usLigatureCount; uint16 *pausCompGlyphID = NULL; /* glyph IDs components of ligature */ uint16 usLigatureGlyphID; /* actual glyph to substitute for ligatures */ uint16 *pausLigatureOffsetArray = NULL; GSUBLIGATURE GSUBLigature; if (pArray[usGlyphCount] == 0) break; ulOffset = ulBaseOffset + pArray[usGlyphCount]; if ((errCode = ReadWord( pInputBufferInfo, &usLigatureCount, ulOffset ) )!= NO_ERROR) break; ulOffset += sizeof(uint16); pausLigatureOffsetArray = (uint16 *)Mem_Alloc(usLigatureCount * sizeof(uint16)); if (pausLigatureOffsetArray == NULL) { errCode = ERR_MEM; break; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pausLigatureOffsetArray, WORD_CONTROL, ulOffset, &ulBytesRead, usLigatureCount, sizeof(uint16)) ) == NO_ERROR) { for (l = 0; l < usLigatureCount; ++l) { if (pausLigatureOffsetArray[l] == 0) continue; ulOffset = ulBaseOffset + (pArray)[usGlyphCount] + pausLigatureOffsetArray[l]; if ((errCode = ReadGeneric( pInputBufferInfo, (uint8 *)&GSUBLigature, SIZEOF_GSUBLIGATURE, GSUBLIGATURE_CONTROL, ulOffset, &usBytesRead) )!= NO_ERROR) { Mem_Free (pausLigatureOffsetArray); Mem_Free(pGlyphIDArray); Mem_Free(pRangeRecordArray); return errCode; } ulOffset += usBytesRead; usLigatureCompCount = GSUBLigature.LigatureCompCount; usLigatureGlyphID = GSUBLigature.GlyphID; if (usLigatureGlyphID >= usnGlyphs || pabKeepGlyphs[usLigatureGlyphID] != 0) continue; /* already in list, go to next ligature */ pausCompGlyphID = (uint16 *)Mem_Alloc((usLigatureCompCount - 1) * sizeof(uint16)); if (pausCompGlyphID == NULL) { Mem_Free (pausLigatureOffsetArray); Mem_Free(pGlyphIDArray); Mem_Free(pRangeRecordArray); return ERR_MEM; } if ((errCode = ReadGenericRepeat( pInputBufferInfo, (uint8 *)pausCompGlyphID, WORD_CONTROL, ulOffset, &ulBytesRead, (uint16) (usLigatureCompCount - 1) , sizeof(uint16)) )!= NO_ERROR) { Mem_Free (pausCompGlyphID); Mem_Free (pausLigatureOffsetArray); Mem_Free(pGlyphIDArray); Mem_Free(pRangeRecordArray); return errCode; } for (k = 0; k < usLigatureCompCount - 1; ++k) { if (pausCompGlyphID[k] >= usnGlyphs || pabKeepGlyphs[pausCompGlyphID[k]] == 0) break; /* if one of the components is not in list, don't worry about ligature */ } if (k == (usLigatureCompCount - 1) && pabKeepGlyphs[usLigatureGlyphID] == 0) /* got to the end of the component list */ pabKeepGlyphs[usLigatureGlyphID] = (uint8)(fKeepFlag+1); Mem_Free(pausCompGlyphID); } } Mem_Free (pausLigatureOffsetArray); break; } } } Mem_Free(pGlyphIDArray); Mem_Free(pRangeRecordArray); return errCode; }
int16 ModKern( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint8 *puchKeepGlyphList, CONST uint16 usGlyphListCount, CONST uint16 usFormat, uint32 *pulNewOutOffset) { uint32 ulOffset; uint32 ulSourceOffset; uint32 ulTargetOffset; KERN_HEADER KernHeader; KERN_SUB_HEADER KernSubHeader; uint16 i; uint16 usSubtableLength; uint16 usBytesRead; int16 errCode = NO_ERROR; /* read kern table header */ if (usFormat == TTFDELTA_DELTA) /* only formats for which this is valid */ { MarkTableForDeletion(pOutputBufferInfo, KERN_TAG); return NO_ERROR; } if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, KERN_TAG, pulNewOutOffset)) != NO_ERROR) { if (errCode == ERR_FORMAT) return NO_ERROR; /* not required */ return errCode; } if (usFormat == TTFDELTA_SUBSET1) /* need to keep the full kern table as we will send only once */ return NO_ERROR; ulOffset = TTTableOffset( pOutputBufferInfo, KERN_TAG ); if ( ulOffset == 0L ) return ERR_GENERIC; /* should have been copied over */ if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *) &KernHeader, SIZEOF_KERN_HEADER, KERN_HEADER_CONTROL, ulOffset, &usBytesRead )) != NO_ERROR) return errCode; /* read each subtable. If it is a format 0 subtable, remove kern pairs involving deleted glyphs. Otherwise, copy the table down to its new location */ ulSourceOffset = ulOffset + usBytesRead; ulTargetOffset = ulSourceOffset; for ( i = 0; i < KernHeader.nTables; i++ ) { /* read subtable header */ if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *) &KernSubHeader, SIZEOF_KERN_SUB_HEADER, KERN_SUB_HEADER_CONTROL, ulSourceOffset, &usBytesRead )) != NO_ERROR) return errCode; /* copy data to new location to cover any gaps left by shortening the previous format 0 subtable. Nothing happens first time around. */ if ((errCode = CopyBlock( pOutputBufferInfo, ulTargetOffset, ulSourceOffset, KernSubHeader.length )) != NO_ERROR) return errCode; ulSourceOffset += KernSubHeader.length; /* if subtable is format 0, shorten it by deleting kern pairs involving deleted glyphs */ if ( KernSubHeader.format == 0 ) { if ((errCode = AdjustKernFormat0( pOutputBufferInfo, puchKeepGlyphList, usGlyphListCount, KernSubHeader, ulTargetOffset, usBytesRead, &usSubtableLength)) != NO_ERROR) return errCode; ulTargetOffset += usSubtableLength; } else ulTargetOffset += KernSubHeader.length; } /* Write out revised table length */ if (ulTargetOffset == ulOffset + GetGenericSize( KERN_HEADER_CONTROL )) /* no Kern data written */ MarkTableForDeletion(pOutputBufferInfo, KERN_TAG); else errCode = UpdateDirEntry( pOutputBufferInfo, KERN_TAG, ulTargetOffset - ulOffset ); *pulNewOutOffset = ulTargetOffset; return errCode; }