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); }
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 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; }
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; }