EStatusCode CFFEmbeddedFontWriter::CreateCFFSubset( FreeTypeFaceWrapper& inFontInfo, const UIntVector& inSubsetGlyphIDs, UShortVector* inCIDMapping, const std::string& inSubsetFontName, bool& outNotEmbedded, MyStringBuf& outFontProgram) { EStatusCode status; do { status = mOpenTypeFile.OpenFile(inFontInfo.GetFontFilePath()); if(status != PDFHummus::eSuccess) { TRACE_LOG1("CFFEmbeddedFontWriter::CreateCFFSubset, cannot open type font file at %s",inFontInfo.GetFontFilePath().c_str()); break; } status = mOpenTypeInput.ReadOpenTypeFile(mOpenTypeFile.GetInputStream(),(unsigned short)inFontInfo.GetFontIndex()); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to read true type file"); break; } if(mOpenTypeInput.GetOpenTypeFontType() != EOpenTypeCFF) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, font file is not CFF, so there is an exceptions here. expecting CFFs only"); break; } // see if font may be embedded if(mOpenTypeInput.mOS2Exists && !FSType(mOpenTypeInput.mOS2.fsType).CanEmbed()) { outNotEmbedded = true; return PDFHummus::eSuccess; } else outNotEmbedded = false; UIntVector subsetGlyphIDs = inSubsetGlyphIDs; if(subsetGlyphIDs.front() != 0) // make sure 0 glyph is in subsetGlyphIDs.insert(subsetGlyphIDs.begin(),0); status = AddDependentGlyphs(subsetGlyphIDs); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to add dependent glyphs"); break; } mIsCID = mOpenTypeInput.mCFF.mTopDictIndex[0].mTopDict.find(scROS) != mOpenTypeInput.mCFF.mTopDictIndex[0].mTopDict.end(); mFontFileStream.Assign(&outFontProgram); mPrimitivesWriter.SetStream(&mFontFileStream); status = WriteCFFHeader(); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write CFF header"); break; } status = WriteName(inSubsetFontName); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write CFF Name"); break; } status = WriteTopIndex(); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write Top Index"); break; } status = WriteStringIndex(); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write String Index"); break; } status = WriteGlobalSubrsIndex(); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write global subrs index"); break; } status = WriteEncodings(inSubsetGlyphIDs); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write encodings"); break; } status = WriteCharsets(inSubsetGlyphIDs,inCIDMapping); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write charstring"); break; } FontDictInfoToByteMap newFDIndexes; if(mIsCID) { DetermineFDArrayIndexes(inSubsetGlyphIDs,newFDIndexes); status = WriteFDSelect(inSubsetGlyphIDs,newFDIndexes); if(status != PDFHummus::eSuccess) break; } status = WriteCharStrings(inSubsetGlyphIDs); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write charstring"); break; } status = WritePrivateDictionary(); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to write private"); break; } if(mIsCID) { status = WriteFDArray(inSubsetGlyphIDs,newFDIndexes); if(status != PDFHummus::eSuccess) break; } status = UpdateIndexesAtTopDict(); if(status != PDFHummus::eSuccess) { TRACE_LOG("CFFEmbeddedFontWriter::CreateCFFSubset, failed to update indexes"); break; } }while(false); mOpenTypeFile.CloseFile(); return status; }
EStatusCode Type1ToCFFEmbeddedFontWriter::CreateCFFSubset( FreeTypeFaceWrapper& inFontInfo, const UIntVector& inSubsetGlyphIDs, const std::string& inSubsetFontName, bool& outNotEmbedded, MyStringBuf& outFontProgram) { EStatusCode status; do { UIntVector subsetGlyphIDs = inSubsetGlyphIDs; StringVector subsetGlyphNames; if(subsetGlyphIDs.front() != 0) // make sure 0 glyph is in subsetGlyphIDs.insert(subsetGlyphIDs.begin(),0); status = mType1File.OpenFile(inFontInfo.GetFontFilePath()); if(status != PDFHummus::eSuccess) { TRACE_LOG1("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, cannot open Type 1 font file at %s",inFontInfo.GetFontFilePath().c_str()); break; } status = mType1Input.ReadType1File(mType1File.GetInputStream()); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to read Type 1 file"); break; } // see if font may be embedded if(mType1Input.mFontDictionary.FSTypeValid || mType1Input.mFontInfoDictionary.FSTypeValid) { if(!FSType( mType1Input.mFontInfoDictionary.FSTypeValid ? mType1Input.mFontInfoDictionary.fsType : mType1Input.mFontDictionary.fsType).CanEmbed()) { outNotEmbedded = true; return PDFHummus::eSuccess; } else outNotEmbedded = false; } else outNotEmbedded = false; // Found big gap between FreeType indexing and the way it's in the Type 1. obvioulsy due to encoding differences. // So i'm replacing the indexes of free type, with names...should be safer (also cleans up invalid glyph ids, in case // direct glyphs placement put them here) TranslateFromFreeTypeToType1(inFontInfo,subsetGlyphIDs,subsetGlyphNames); status = AddDependentGlyphs(subsetGlyphNames); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to add dependent glyphs"); break; } mFontFileStream.Assign(&outFontProgram); mPrimitivesWriter.SetStream(&mFontFileStream); status = WriteCFFHeader(); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write CFF header"); break; } status = WriteName(inSubsetFontName); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write CFF Name"); break; } status = WriteTopIndex(); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write Top Index"); break; } // prepraring charset happens here, so that any added strings to the string index will happen...before // the index is written PrepareCharSetArray(subsetGlyphNames); status = WriteStringIndex(); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write String Index"); break; } status = WriteGlobalSubrsIndex(); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write global subrs index"); break; } status = WriteEncodings(subsetGlyphNames); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write encodings"); break; } status = WriteCharsets(subsetGlyphNames); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write charstring"); break; } status = WriteCharStrings(subsetGlyphNames); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write charstring"); break; } status = WritePrivateDictionary(); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to write private"); break; } status = UpdateIndexesAtTopDict(); if(status != PDFHummus::eSuccess) { TRACE_LOG("Type1ToCFFEmbeddedFontWriter::CreateCFFSubset, failed to update indexes"); break; } }while(false); mType1File.CloseFile(); FreeTemporaryStructs(); return status; }