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; }
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 ComputeMaxPStats( TTFACC_FILEBUFFERINFO * pInputBufferInfo, uint16 * pusMaxContours, uint16 * pusMaxPoints, uint16 * pusMaxCompositeContours, uint16 * pusMaxCompositePoints, uint16 * pusMaxInstructions, uint16 * pusMaxComponentElements, uint16 * pusMaxComponentDepth, uint16 * pausComponents, uint16 usnMaxComponents) { HEAD Head; int16 snContours; uint16 usnPoints; uint16 usnInstructions; uint16 usGlyphIdx; uint16 prepLength; uint16 fpgmLength; uint16 usnCompElements; uint16 usnCompDepth; uint16 usGlyphCount; uint32 ulLocaOffset; uint32 ulGlyfOffset; int16 errCode; BOOL bStatus; *pusMaxContours = 0; *pusMaxPoints = 0; *pusMaxInstructions = 0; *pusMaxCompositeContours = 0; *pusMaxCompositePoints = 0; *pusMaxComponentElements = 0; *pusMaxComponentDepth = 0; /* Build a Loca table that will be used to decide if a glyph has contours or not. There are g_usnGlyphs+1 Loca entries. */ usGlyphCount = GetNumGlyphs(pInputBufferInfo); if (usGlyphCount == 0) return ERR_NO_GLYPHS; ulLocaOffset = TTTableOffset(pInputBufferInfo, LOCA_TAG); if ( ulLocaOffset == 0L ) return ERR_MISSING_LOCA; ulGlyfOffset = TTTableOffset(pInputBufferInfo, GLYF_TAG); if ( ulGlyfOffset == 0L ) return ERR_MISSING_GLYF; if (!GetHead(pInputBufferInfo, &Head)) /* for Head.indexToLocFormat */ return ERR_MISSING_HEAD; for ( usGlyphIdx = 0; usGlyphIdx < usGlyphCount; usGlyphIdx++ ) { /* get statistics on the glyph component */ if ((errCode = GetGlyphStats(pInputBufferInfo, usGlyphIdx, &snContours, &usnPoints, &usnInstructions, Head.indexToLocFormat, ulLocaOffset, ulGlyfOffset, &bStatus)) != NO_ERROR) return errCode; if (bStatus == FALSE) continue; /* remember maxes for simple glyph */ if ( snContours >= 0 ) { *pusMaxContours = max( *pusMaxContours, (uint16) snContours ); *pusMaxPoints = max( *pusMaxPoints, usnPoints ); *pusMaxInstructions = max( *pusMaxInstructions, usnInstructions ); } /* remember maxes for composite glyph */ else if (snContours == -1) { /* start with usnInstructions at 0 for MAX test in fn call... */ usnCompElements = usnCompDepth = usnInstructions = 0; GetCompositeGlyphStats( pInputBufferInfo, usGlyphIdx, &snContours, &usnPoints, &usnInstructions, &usnCompElements, &usnCompDepth, Head.indexToLocFormat, ulLocaOffset, ulGlyfOffset, pausComponents, usnMaxComponents ); *pusMaxCompositeContours = max( *pusMaxCompositeContours, (uint16) snContours ); *pusMaxCompositePoints = max( *pusMaxCompositePoints, usnPoints ); *pusMaxInstructions = max( *pusMaxInstructions, usnInstructions ); *pusMaxComponentElements = max( *pusMaxComponentElements, usnCompElements ); *pusMaxComponentDepth = max( *pusMaxComponentDepth, usnCompDepth ); } else return ERR_INVALID_GLYF; /* what is it? */ } prepLength = (uint16) TTTableLength( pInputBufferInfo, PREP_TAG ); fpgmLength = (uint16) TTTableLength( pInputBufferInfo, FPGM_TAG ); *pusMaxInstructions = max( max( prepLength, fpgmLength), *pusMaxInstructions ); return NO_ERROR; }
int16 ModName( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint16 usLanguage, CONST uint16 usFormat, uint32 *pulNewOutOffset) { PNAMERECORD pNameRecordArray; /* internal representation of NameRecord - from ttftable.h */ uint16 NameRecordCount; int16 errCode = NO_ERROR; uint16 i; uint16 bKeptMSPlatformRecord = FALSE; /* has a MS Platform record been kept? */ uint16 bDeleteStrings = FALSE; /* should we delete strings when writing out table? */ uint32 ulBytesWritten = 0; uint32 ulNameOffset; uint32 ulNameLength; TTFACC_FILEBUFFERINFO NameTableBufferInfo; /* needed by WriteNameRecords */ if (usFormat == TTFDELTA_DELTA) /* only formats for which this is not valid */ { MarkTableForDeletion(pOutputBufferInfo, NAME_TAG); return errCode; } if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, NAME_TAG, pulNewOutOffset))!= NO_ERROR) return errCode; /* required */ ulNameOffset = TTTableOffset( pOutputBufferInfo, NAME_TAG); ulNameLength = TTTableLength( pOutputBufferInfo, NAME_TAG); /* Get info about Name table */ if ((errCode = ReadAllocNameRecords(pOutputBufferInfo, &pNameRecordArray, &NameRecordCount, Mem_Alloc, Mem_Free)) != NO_ERROR) return errCode; if (usLanguage != TTFSUB_LANG_KEEP_ALL) { for (i = 0; i < NameRecordCount; ++i) { if (pNameRecordArray[i].platformID == TTFSUB_MS_PLATFORMID) { if (pNameRecordArray[i].languageID == usLanguage) /* we want to keep this one */ bKeptMSPlatformRecord = TRUE; else /* we don't want it */ { pNameRecordArray[i].bDeleteString = TRUE; /* mark it for deletion */ bDeleteStrings = TRUE; } } } if (bDeleteStrings && !bKeptMSPlatformRecord) /* if we asked to keep a language that wasn't found, don't delete others */ bDeleteStrings = FALSE; } /* now fake up a bufferinfo so that WriteNameRecords will write to the actual file buffer */ InitFileBufferInfo(&NameTableBufferInfo, pOutputBufferInfo->puchBuffer + ulNameOffset, ulNameLength, NULL /*cant reallocate!*/); errCode = WriteNameRecords(&NameTableBufferInfo, pNameRecordArray, NameRecordCount, bDeleteStrings, TRUE, &ulBytesWritten); FreeNameRecords(pNameRecordArray, NameRecordCount, Mem_Free); if (errCode == NO_ERROR) { *pulNewOutOffset = ulNameOffset + ulBytesWritten; UpdateDirEntry(pOutputBufferInfo, NAME_TAG, ulBytesWritten); } else /* ran out of room? restore it */ { *pulNewOutOffset = ulNameOffset; errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, NAME_TAG, pulNewOutOffset); } 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() */