int16 ModOS2( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, uint16 usMinChr, uint16 usMaxChr, CONST uint16 usFormat, uint32 *pulNewOutOffset) { /* read OS2 table, modify the max,min char field, and write out the new table */ NEWOS2 Os2; uint32 ulOffset; BOOL bNewOS2 = FALSE; uint16 usBytesWritten; int16 errCode = NO_ERROR; if (usFormat == TTFDELTA_DELTA) /* only formats for which this is not valid */ { MarkTableForDeletion(pOutputBufferInfo, OS2_TAG); return errCode; } if ((ulOffset = GetSmartOS2(pOutputBufferInfo,&Os2,&bNewOS2)) == 0L) { if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, OS2_TAG, pulNewOutOffset)) != NO_ERROR) { if (errCode == ERR_FORMAT) return NO_ERROR; /* not required */ return errCode; } if ((ulOffset = GetSmartOS2(pOutputBufferInfo,&Os2,&bNewOS2)) == 0L) return ERR_GENERIC; } if (usMinChr != 0 || usMaxChr != 0) /* couldn't set in modcmap because of growth */ { if (Os2.usFirstCharIndex < 0xF000) /* lcp 5/26/97 don't want to change this if it is a Symbol font */ Os2.usFirstCharIndex = usMinChr; Os2.usLastCharIndex = usMaxChr; if( bNewOS2 ) /* write out the new one */ { if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &Os2, SIZEOF_NEWOS2, NEWOS2_CONTROL, ulOffset, &usBytesWritten)) != NO_ERROR) return errCode; } else /* write out the old one */ { if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &Os2, SIZEOF_OS2, OS2_CONTROL, ulOffset, &usBytesWritten )) != NO_ERROR) return errCode; } } return errCode; }
int16 ModPost( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint16 usFormat, uint32 *pulNewOutOffset) { POST Post; int16 errCode = NO_ERROR; uint16 usBytesWritten; uint32 ulOffset; /* verify table needs to be modified */ if (usFormat == TTFDELTA_DELTA) /* only formats for which this is not valid */ { MarkTableForDeletion(pOutputBufferInfo, POST_TAG); return errCode; } if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, POST_TAG, pulNewOutOffset)) != NO_ERROR) { if (errCode == ERR_FORMAT) return NO_ERROR; /* not required */ return errCode; } if ((ulOffset = GetPost( pOutputBufferInfo, &Post )) == 0L) return ERR_GENERIC; if ( Post.formatType != POST_FORMAT_3 ) { /* Not POST format 3.0, so change it to 3.0 */ Post.formatType = POST_FORMAT_3; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &Post,SIZEOF_POST, POST_CONTROL, ulOffset, &usBytesWritten )) != NO_ERROR) return errCode; /* update the directory entry with new length */ errCode = UpdateDirEntry( pOutputBufferInfo, POST_TAG, (uint32) usBytesWritten ); *pulNewOutOffset = ulOffset + usBytesWritten; } return errCode; }
int16 ModMaxP( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, uint32 *pulNewOutOffset) { MAXP MaxP; uint32 ulOffset; uint16 usnMaxComponents; uint16 *pausComponents; int16 errCode; uint16 usBytesWritten; /* get old maxp record */ if ((ulOffset = GetMaxp( pOutputBufferInfo, &MaxP)) == 0L) { /* not copied over yet */ if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, MAXP_TAG, pulNewOutOffset)) != NO_ERROR) return ERR_MISSING_MAXP; /* required */ if ((ulOffset = GetMaxp( pOutputBufferInfo, &MaxP)) == 0L) return ERR_GENERIC; } /* recompute maxp info */ /* figure a conservative maximum total possible. 3x3 at minimum */ usnMaxComponents = max(3,MaxP.maxComponentElements) * max(3,MaxP.maxComponentDepth); pausComponents = (uint16 *) Mem_Alloc(usnMaxComponents * sizeof(uint16)); if (pausComponents == NULL) return ERR_MEM; errCode = ComputeMaxPStats( pOutputBufferInfo, &(MaxP.maxContours), &(MaxP.maxPoints), &(MaxP.maxCompositeContours), &(MaxP.maxCompositePoints), &(MaxP.maxSizeOfInstructions), &(MaxP.maxComponentElements), &(MaxP.maxComponentDepth), pausComponents, usnMaxComponents ); /* write out new maxp record with new maxp info */ Mem_Free(pausComponents); if (errCode == NO_ERROR) errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &MaxP, SIZEOF_MAXP, MAXP_CONTROL, ulOffset, &usBytesWritten ); return errCode; }
bool Write(TOffset Position, u64 const& rData) { return WriteGeneric(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 ModLTSH( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, CONST uint8 *puchKeepGlyphList, CONST uint16 usGlyphListCount, CONST uint16 usDttfGlyphIndexCount, uint32 *pulNewOutOffset) { LTSH Ltsh; uint32 ulLtshOffset; uint32 ulInOffset; uint32 ulOutOffset; uint16 i,j; int16 errCode; uint16 GlyphCount; uint8 uchValue; uint16 usBytesWritten; /* read ltsh table header */ if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, LTSH_TAG, pulNewOutOffset)) != NO_ERROR) { if (errCode == ERR_FORMAT) return NO_ERROR; /* not required */ return errCode; } ulLtshOffset = GetLTSH( pOutputBufferInfo, &Ltsh ); if ( ulLtshOffset == 0 ) return ERR_GENERIC; if (usDttfGlyphIndexCount) { ulOutOffset = ulLtshOffset + GetGenericSize( LTSH_CONTROL ); ulInOffset = ulLtshOffset + GetGenericSize( LTSH_CONTROL ); GlyphCount = min(Ltsh.numGlyphs, usGlyphListCount); /* don't want to process too many if file is buggy */ for( i=0, j= 0; i < GlyphCount && j < usDttfGlyphIndexCount; i++) { if (puchKeepGlyphList[ i ]) /* need keep this one out */ { if ((errCode = ReadByte( pOutputBufferInfo, (uint8 *) &uchValue, ulInOffset)) != NO_ERROR) return errCode; if ((errCode = WriteByte( pOutputBufferInfo, (uint8) uchValue, ulOutOffset)) != NO_ERROR) return errCode; ulOutOffset += sizeof(uint8); ++j; } ulInOffset += sizeof(uint8); } /* now we need to update the count for the LTSH table */ Ltsh.numGlyphs = usDttfGlyphIndexCount; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&Ltsh, SIZEOF_LTSH, LTSH_CONTROL, ulLtshOffset, &usBytesWritten )) != NO_ERROR) return errCode; if ((errCode = UpdateDirEntry( pOutputBufferInfo, LTSH_TAG, ulOutOffset - ulLtshOffset )) != NO_ERROR) return errCode; } else { ulOutOffset = ulLtshOffset + GetGenericSize( LTSH_CONTROL ); GlyphCount = min(Ltsh.numGlyphs, usGlyphListCount); /* don't want to process too many if file is buggy */ for( i=0; i < GlyphCount; i++) { if (!puchKeepGlyphList[ i ]) /* need to zero out */ { if ((errCode = WriteByte( pOutputBufferInfo, (uint8) 0, ulOutOffset)) != NO_ERROR) return errCode; } ulOutOffset += sizeof(uint8); } } *pulNewOutOffset = ulOutOffset; return NO_ERROR; }
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; }
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 MD32spr::Write() { size_t i = 0; csString vfspath; char* fileName = 0; char* mdlName = 0; if (outZipName) { if (outZipName.Length() > 0) { csArchive* zipFile = new csArchive (outZipName.GetData()); if(!zipFile) { ReportError("Error creating output zip file.\n"); return; } delete zipFile; fileName = new char[outZipName.Length() + 1]; basename(outZipName.GetData(), fileName); vfspath.Format ("/tmp/%s_out/", fileName); if (!out->Mount(vfspath, outZipName.GetData())) { ReportError("Error mounting output zip file.\n"); return; } } } if (!player && !weaponDir) { if (generic.GetSize ()) { for (i = 0; i < generic.GetSize (); i++) { md3Model *mdl = generic.Get(i); mdlName = new char[strlen(mdl->GetFileName()) + 1]; basename(mdl->GetFileName(), mdlName); csRef<iDocumentSystem> xml(csPtr <iDocumentSystem> (new csTinyDocumentSystem())); csRef <iDocument> doc = xml->CreateDocument(); csRef <iDocumentNode> root = doc->CreateRoot(); csRef <iDocumentNode> parent = root->CreateNodeBefore(CS_NODE_ELEMENT, 0); parent->SetValue("library"); WriteGeneric(mdl, parent); csString outFile(vfspath); outFile += mdlName; doc->Write(out, outFile.GetData()); } } } if (player) { if (headModel) { char *headName = new char[strlen(headModel->GetFileName()) + 1]; csString tagFileName; basename(headModel->GetFileName(), headName); tagFileName.Format ("%s%s.tag", vfspath.GetData(), headName); WriteXMLTags(headModel, tagFileName); csRef < iDocumentSystem > xml(csPtr < iDocumentSystem > (new csTinyDocumentSystem())); csRef < iDocument > doc = xml->CreateDocument(); csRef < iDocumentNode > root = doc->CreateRoot(); csRef < iDocumentNode > parent = root->CreateNodeBefore(CS_NODE_ELEMENT, 0); parent->SetValue("library"); WriteGeneric(headModel, parent); csString outFile(vfspath); outFile += headName; doc->Write(out, outFile.GetData()); } if (upperModel) { char *upperName = new char[strlen(headModel->GetFileName()) + 1]; csString tagFileName; basename(upperModel->GetFileName(), upperName); tagFileName.Format ("%s%s.tag", vfspath.GetData(), upperName); WriteXMLTags(upperModel, tagFileName); csRef < iDocumentSystem > xml(csPtr < iDocumentSystem > (new csTinyDocumentSystem())); csRef < iDocument > doc = xml->CreateDocument(); csRef < iDocumentNode > root = doc->CreateRoot(); csRef < iDocumentNode > parent = root->CreateNodeBefore(CS_NODE_ELEMENT, 0); parent->SetValue("library"); WriteGeneric(upperModel, parent); csString outFile(vfspath); outFile += upperName; doc->Write(out, outFile.GetData()); } if (lowerModel) { char *lowerName = new char[strlen(headModel->GetFileName()) + 1]; csString tagFileName; basename(lowerModel->GetFileName(), lowerName); tagFileName.Format ("%s%s.tag", vfspath.GetData(), lowerName); WriteXMLTags(lowerModel, tagFileName); csRef < iDocumentSystem > xml(csPtr < iDocumentSystem > (new csTinyDocumentSystem())); csRef < iDocument > doc = xml->CreateDocument(); csRef < iDocumentNode > root = doc->CreateRoot(); csRef < iDocumentNode > parent = root->CreateNodeBefore(CS_NODE_ELEMENT, 0); parent->SetValue("library"); WriteGeneric(lowerModel, parent); csString outFile(vfspath); outFile += lowerName; doc->Write(out, outFile.GetData()); } if (weaponDir) { for (i = 0; i < generic.GetSize (); i++) { md3Model *mdl = generic.Get(i); csRef < iDocumentSystem > xml(csPtr < iDocumentSystem > (new csTinyDocumentSystem())); csRef < iDocument > doc = xml->CreateDocument(); csRef < iDocumentNode > root = doc->CreateRoot(); csRef < iDocumentNode > parent = root->CreateNodeBefore(CS_NODE_ELEMENT, 0); parent->SetValue("library"); WriteGeneric(mdl, parent); char *fileName = new char[mdl->fileName.Length() + 1]; csString tagFileName; basename(mdl->fileName.GetData(), fileName); csString outFile(vfspath); outFile += weaponDir; outFile += "/"; outFile += fileName; doc->Write(out, outFile.GetData()); tagFileName.Format ("%s%s/%s.tag", vfspath.GetData(), weaponDir.GetData(), fileName); WriteXMLTags(mdl, tagFileName); } } } WriteTextures(mountPath.GetData(),vfspath); if(weaponDir) { csString weaponInPath(mountPath.GetData()); csString weaponOutPath(vfspath); weaponInPath += weaponDir; weaponInPath += "/"; weaponOutPath += weaponDir; weaponOutPath += "/"; WriteTextures(weaponInPath.GetData(), weaponOutPath.GetData()); } }
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); }
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; }
PRIVATE int16 CompressCmapSubTables(TTFACC_FILEBUFFERINFO * pOutputBufferInfo, /* ttfacc info */ CMAP_TABLELOC *pCmapTableLoc, /* array of CmapSubTable locators */ uint16 usSubTableCount, /* count of that array */ uint32 ulCmapOffset, /* offset to cmap table */ uint32 ulSubTableOffset, /* offset to beginning of Subtables */ uint32 ulCmapOldLength, /* length of old cmap table - not to be exceeded */ uint32 *pulCmapNewLength) { IndexOffset *pIndexArray; /* local array of structures to keep track of new offsets of sorted subtables */ CMAP_SUBHEADER_GEN CmapSubHeader; int16 errCode = NO_ERROR; uint32 ulCurrentOffset; uint32 ulLastOffset; uint16 usIndex; uint32 ulCmapTableLength = 0; uint32 ulCmapSubTableDirOffset; uint32 ulPadOffset; uint16 i,j; uint16 usBytesRead; uint16 usPadBytes; pIndexArray = (IndexOffset *) Mem_Alloc(usSubTableCount * sizeof(*pIndexArray)); if (pIndexArray == NULL) return ERR_MEM; /* sort them by old offsets, so we can move the blocks in order */ SortCmapSubByOffset(pCmapTableLoc, usSubTableCount, pIndexArray); ulCurrentOffset = ulSubTableOffset; /* end of the Cmap Directories */ ulLastOffset = 0; for (i = 0; i < usSubTableCount; ++i) /* process each subtable */ { usIndex = pIndexArray[i].usIndex; /* check to see if this offset is the same as the last one copied. If so, ignore, as it has already been copied */ if (i > 0 && pCmapTableLoc[usIndex].offset == ulLastOffset) /* we're pointing to some already copied data */ { pIndexArray[i].ulNewOffset = pIndexArray[i-1].ulNewOffset; continue; } /* read the CmapSub Header */ if ((errCode = ReadCmapLength(pOutputBufferInfo, &CmapSubHeader, ulCmapOffset + pCmapTableLoc[usIndex].offset, &usBytesRead)) != NO_ERROR) break; /* do we need to pad? */ ulPadOffset = ulCurrentOffset; ulCurrentOffset = (ulPadOffset + 1) & ~1; /* we may need to pad, but do it after we move data in case we would overwrite data */ usPadBytes = (uint16) (ulCurrentOffset - ulPadOffset); if (ulCmapTableLength + usPadBytes + CmapSubHeader.length > ulCmapOldLength) /* if we are about to exceed the bounds */ { errCode = ERR_WOULD_GROW; /* can't do it. Bail and restore the old cmap table */ break; } pIndexArray[i].ulNewOffset = ulCurrentOffset-ulCmapOffset; /* calculate the new offset of the cmap subtable, and store in local structure */ ulLastOffset = pCmapTableLoc[usIndex].offset; /* now copy the subtable to it's new locations */ if ((errCode = CopyBlock(pOutputBufferInfo, ulCurrentOffset, ulCmapOffset + pCmapTableLoc[usIndex].offset,CmapSubHeader.length)) != NO_ERROR) break; for (j = 0; j < usPadBytes; ++j) WriteByte(pOutputBufferInfo,(uint8) 0, ulPadOffset+j); /* now clear out those pad bytes */ ulCurrentOffset += CmapSubHeader.length; ulCmapTableLength = ulCurrentOffset - ulCmapOffset; /* to update the Font Directory values */ } if (errCode == NO_ERROR) { for (i = 0; i < usSubTableCount; ++i) /* now set the new offsets - retrieved from the local structure array */ pCmapTableLoc[pIndexArray[i].usIndex].offset = pIndexArray[i].ulNewOffset; ulCmapSubTableDirOffset = ulCmapOffset + GetGenericSize( CMAP_HEADER_CONTROL ); for (i = 0; i < usSubTableCount; ++i) /* now write the new offsets in their original order (Plat/encoding order) */ { if ((errCode = WriteGeneric(pOutputBufferInfo, (uint8 *) &(pCmapTableLoc[i]), SIZEOF_CMAP_TABLELOC, CMAP_TABLELOC_CONTROL, ulCmapSubTableDirOffset, &usBytesRead)) != NO_ERROR) break; ulCmapSubTableDirOffset += usBytesRead; /* for next time around */ } } Mem_Free(pIndexArray); if (errCode == NO_ERROR) /* now update the Directory Entry for the file */ errCode = UpdateDirEntry(pOutputBufferInfo, CMAP_TAG, ulCmapTableLength); *pulCmapNewLength = ulCmapTableLength; return errCode; }
int16 ModGlyfLocaAndHead( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, TTFACC_FILEBUFFERINFO * pOutputBufferInfo, uint8 *puchKeepGlyphList, uint16 usGlyphCount, uint32 *pCheckSumAdjustment, /* this is returned to be saved with a subset1 or delta format font */ uint32 *pulNewOutOffset) { uint16 i; uint16 usOffset; uint16 usIdxToLocFmt; uint16 usBytesWritten; uint32 ulBytesWritten; int16 errCode = NO_ERROR; uint32 * aulLoca; uint32 ulGlyphLength; uint32 ulOutLoca; uint32 ulGlyfOffset; uint32 ulOutGlyfOffset; uint32 ulOutGlyfDirectoryOffset; uint32 ulHeadOffset; uint32 ulOutLocaOffset; uint32 ulOutLocaDirectoryOffset; DIRECTORY LocaDirectory, GlyfDirectory; HEAD Head; /* allocate memory for and read loca table */ aulLoca = (uint32 *)Mem_Alloc( (usGlyphCount + 1) * sizeof( uint32 )); if ( aulLoca == NULL ) return ERR_MEM; if (GetLoca((TTFACC_FILEBUFFERINFO *)pInputBufferInfo, aulLoca, usGlyphCount + 1) == 0L) { Mem_Free(aulLoca); return ERR_INVALID_LOCA; } if ((ulHeadOffset = GetHead(pOutputBufferInfo, &Head)) == 0L) { /* copy over head table. will update below */ if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, HEAD_TAG, pulNewOutOffset))!=NO_ERROR) { Mem_Free(aulLoca); return errCode; } ulHeadOffset = GetHead(pOutputBufferInfo, &Head); } ulOutLoca = 0L; ulGlyfOffset = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, GLYF_TAG ); if (ulGlyfOffset == DIRECTORY_ERROR) /* this should have been setup */ { Mem_Free(aulLoca); return ERR_MISSING_GLYF; } ulOutGlyfDirectoryOffset = GetTTDirectory( pOutputBufferInfo, GLYF_TAG, &GlyfDirectory); /* make sure there is a directory entry */ if (ulOutGlyfDirectoryOffset == DIRECTORY_ERROR) /* this should have been setup */ { Mem_Free(aulLoca); return ERR_MISSING_GLYF; } if (GlyfDirectory.offset == DIRECTORY_ERROR) { if ((errCode = ZeroLongWordAlign(pOutputBufferInfo, *pulNewOutOffset, pulNewOutOffset)) != NO_ERROR) { Mem_Free(aulLoca); return errCode; } GlyfDirectory.offset = *pulNewOutOffset; } ulOutGlyfOffset = GlyfDirectory.offset; /* go thru the glyf table, copying up the glyphs to be saved */ for ( i = 0; i < usGlyphCount; i++ ) { ulGlyphLength = 0L; if (puchKeepGlyphList[i]) /* we want to keep this one */ { /* copy existing glyph data to new location */ if ( aulLoca[ i ] < aulLoca[ i+1 ] ) ulGlyphLength = aulLoca[ i+1 ] - aulLoca[ i ]; if ( ulGlyphLength ) { if ((errCode = CopyBlockOver( pOutputBufferInfo, pInputBufferInfo, ulOutGlyfOffset + ulOutLoca, ulGlyfOffset + aulLoca[ i ], ulGlyphLength )) != NO_ERROR) break; } } assert((ulOutLoca & 1) != 1); aulLoca[ i ] = ulOutLoca; ulOutLoca += ulGlyphLength; if (ulOutLoca & 1) { /* the glyph offset is on an odd-byte boundry. get ready for next time */ if ((errCode = WriteByte( pOutputBufferInfo, 0, ulOutGlyfOffset + ulOutLoca)) != NO_ERROR) break; ++ulOutLoca; } } if (errCode == NO_ERROR) { /* The last loca entry is the end of the last glyph! */ *pulNewOutOffset += ulOutLoca; aulLoca[ usGlyphCount ] = ulOutLoca; GlyfDirectory.length = ulOutLoca; errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&GlyfDirectory, SIZEOF_DIRECTORY, DIRECTORY_CONTROL, ulOutGlyfDirectoryOffset, &usBytesWritten ); } if (errCode != NO_ERROR) { Mem_Free(aulLoca); return errCode; } /* write out the modified 'loca' table */ ulOutLocaDirectoryOffset = GetTTDirectory( pOutputBufferInfo, LOCA_TAG, &LocaDirectory); /* make sure there is a directory entry */ if (ulOutLocaDirectoryOffset == DIRECTORY_ERROR) /* this should have been setup */ { Mem_Free(aulLoca); return ERR_MISSING_LOCA; } if ((errCode = ZeroLongWordAlign(pOutputBufferInfo, *pulNewOutOffset, pulNewOutOffset)) != NO_ERROR) { Mem_Free(aulLoca); return errCode; } ulOutLocaOffset = LocaDirectory.offset = *pulNewOutOffset; /* where to write the loca */ /* Check to see what format to use */ if (ulOutLoca <= 0x1FFFC) /* maximum number stored here (0xFFFE * 2) Chosen as conservative value over 0xFFFF * 2 */ { usIdxToLocFmt = SHORT_OFFSETS; for ( i = 0; i <= usGlyphCount; i++ ) { assert((aulLoca[i] & 1) != 1); /* can't have this, would be truncated */ usOffset = (uint16) (aulLoca[ i ] / 2L); if ((errCode = WriteWord( pOutputBufferInfo, usOffset, ulOutLocaOffset + i*sizeof(uint16) )) != NO_ERROR) break; } ulOutLoca = (uint32) (usGlyphCount+1) * sizeof(uint16); } else { usIdxToLocFmt = LONG_OFFSETS; errCode = WriteGenericRepeat(pOutputBufferInfo, (uint8 *) aulLoca, LONG_CONTROL,ulOutLocaOffset,&ulBytesWritten,(uint16) (usGlyphCount+1), sizeof(uint32)); ulOutLoca = ulBytesWritten; } if (errCode == NO_ERROR) { /* update the length, etc. for the loca table as well */ LocaDirectory.length = ulOutLoca; *pulNewOutOffset += ulOutLoca; if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &LocaDirectory, SIZEOF_DIRECTORY, DIRECTORY_CONTROL, ulOutLocaDirectoryOffset, &usBytesWritten )) == NO_ERROR) { *pCheckSumAdjustment = Head.checkSumAdjustment;/* for use by dttf table */ Head.checkSumAdjustment = 0L; /* needs to be 0 when setting the file checksum value */ Head.indexToLocFormat = usIdxToLocFmt; errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &Head, SIZEOF_HEAD, HEAD_CONTROL, ulHeadOffset, &usBytesWritten); } } /* clean up */ Mem_Free( aulLoca ); return errCode; }