void CFFANSIFontWriter::WriteCharSet( DictionaryContext* inDescriptorContext, ObjectsContext* inObjectsContext, FreeTypeFaceWrapper* inFontInfo, const UIntAndGlyphEncodingInfoVector& inEncodedGlyphs) { // ChartSet inDescriptorContext->WriteKey(scCharSet); // charset is a rather long string. i'd rather write it down as it goes, than format a string // and submit it. IByteWriterWithPosition* directStream = inObjectsContext->StartFreeContext(); PrimitiveObjectsWriter primitiveWriter(directStream); directStream->Write(scLeftParanthesis,1); UIntAndGlyphEncodingInfoVector::const_iterator it = inEncodedGlyphs.begin()+1; // skip 0 character for(; it != inEncodedGlyphs.end(); ++it) { std::string glyphName = inFontInfo->GetGlyphName(it->first); primitiveWriter.WriteName(glyphName.c_str(),eTokenSepratorNone); } directStream->Write(scRightParanthesis,1); inObjectsContext->EndFreeContext(); inObjectsContext->EndLine(); }
void DescendentFontWriter::WriteCIDSet(const UIntAndGlyphEncodingInfoVector& inEncodedGlyphs) { mObjectsContext->StartNewIndirectObject(mCIDSetObjectID); PDFStream* pdfStream = mObjectsContext->StartPDFStream(); IByteWriter* cidSetWritingContext = pdfStream->GetWriteStream(); Byte buffer; UIntAndGlyphEncodingInfoVector::const_iterator it = inEncodedGlyphs.begin(); unsigned int upperLimit = inEncodedGlyphs.back().first; for(unsigned int i=0; i < upperLimit; i+=8) { buffer = (it->first == i) ? 1:0; if(it->first == i) ++it; for(unsigned int j=1;j<8;++j) { buffer = buffer << 1; if(it != inEncodedGlyphs.end() && (it->first == i + j)) { buffer |= 1; ++it; if(it == inEncodedGlyphs.end()) break; } } cidSetWritingContext->Write(&buffer,1); } mObjectsContext->EndPDFStream(pdfStream); delete pdfStream; }
static UIntVector GetOrderedKeys(const UIntAndGlyphEncodingInfoVector& inMap) { UIntVector result; for(UIntAndGlyphEncodingInfoVector::const_iterator it = inMap.begin(); it != inMap.end(); ++it) result.push_back(it->first); sort(result.begin(),result.end()); return result; }
EStatusCode CFFDescendentFontWriter::WriteFont( ObjectIDType inDecendentObjectID, const std::string& inFontName, FreeTypeFaceWrapper& inFontInfo, const UIntAndGlyphEncodingInfoVector& inEncodedGlyphs, ObjectsContext* inObjectsContext, bool inEmbedFont) { // reset embedded font object ID (and flag...to whether it was actually embedded or not, which may // happen due to font embedding restrictions) mEmbeddedFontFileObjectID = 0; // Logically speaking, i shouldn't be getting to CID writing // if in type 1. at least, this is the current assumption, since // i don't intend to support type 1 CIDs, but just regular type 1s. // as such - fail if got here for type 1 const char* fontType = inFontInfo.GetTypeString(); if(strcmp(scType1,fontType) == 0) { TRACE_LOG1("CFFDescendentFontWriter::WriteFont, Exception. identified type1 font when writing CFF CID font, font name - %s. type 1 CIDs are not supported.",inFontName.substr(0, MAX_TRACE_SIZE - 200).c_str()); return PDFHummus::eFailure; } if (inEmbedFont) { CFFEmbeddedFontWriter embeddedFontWriter; UIntAndGlyphEncodingInfoVector encodedGlyphs = inEncodedGlyphs; UIntVector orderedGlyphs; UShortVector cidMapping; // Gal: the following sort completely ruins everything. // the order of the glyphs should be maintained per the ENCODED characthers // which is how the input is recieved. IMPORTANT - the order is critical // for the success of the embedding, as the order determines the order of the glyphs // in the subset font and so their GID which MUST match the encoded char. //sort(encodedGlyphs.begin(), encodedGlyphs.end(), sEncodedGlypsSort); for (UIntAndGlyphEncodingInfoVector::const_iterator it = encodedGlyphs.begin(); it != encodedGlyphs.end(); ++it) { orderedGlyphs.push_back(it->first); cidMapping.push_back(it->second.mEncodedCharacter); } EStatusCode status = embeddedFontWriter.WriteEmbeddedFont(inFontInfo, orderedGlyphs, scCIDFontType0C, inFontName, inObjectsContext, &cidMapping, mEmbeddedFontFileObjectID); if (status != PDFHummus::eSuccess) return status; } DescendentFontWriter descendentFontWriter; return descendentFontWriter.WriteFont(inDecendentObjectID,inFontName,inFontInfo,inEncodedGlyphs,inObjectsContext,this); }
bool FontDescriptorWriter::IsSymbolic( FreeTypeFaceWrapper* inFontInfo, const UIntAndGlyphEncodingInfoVector& inEncodedGlyphs) { bool hasOnlyAdobeStandard = true; UIntAndGlyphEncodingInfoVector::const_iterator it = inEncodedGlyphs.begin()+1; // skip 0 character for(; it != inEncodedGlyphs.end() && hasOnlyAdobeStandard; ++it) { ULongVector::const_iterator itCharacters = it->second.mUnicodeCharacters.begin(); for(; itCharacters != it->second.mUnicodeCharacters.end() && hasOnlyAdobeStandard;++itCharacters) hasOnlyAdobeStandard = inFontInfo->IsCharachterCodeAdobeStandard(*itCharacters); } return !hasOnlyAdobeStandard; }
void DescendentFontWriter::WriteWidths(const UIntAndGlyphEncodingInfoVector& inEncodedGlyphs, DictionaryContext* inFontContext) { UIntAndGlyphEncodingInfoVector::const_iterator it = inEncodedGlyphs.begin(); // will be the 0 glyph FT_Pos defaultWidth; FTPosList widthsList; bool allWidthsSame = true; FT_Pos currentWidth; unsigned short firstCIDInList = 0; unsigned short previousCIDInList = 0; // DW inFontContext->WriteKey(scDW); FT_Load_Glyph(*mFontInfo,it->first,FT_LOAD_NO_SCALE); defaultWidth = mFontInfo->GetInPDFMeasurements((*mFontInfo)->glyph->metrics.horiAdvance); inFontContext->WriteIntegerValue(defaultWidth); ++it; // find the first which is not default width for(; it != inEncodedGlyphs.end();++it) { FT_Load_Glyph(*mFontInfo,it->first,FT_LOAD_NO_SCALE); currentWidth = mFontInfo->GetInPDFMeasurements((*mFontInfo)->glyph->metrics.horiAdvance); if(currentWidth != defaultWidth) { widthsList.push_back(currentWidth); firstCIDInList = it->second.mEncodedCharacter; previousCIDInList = it->second.mEncodedCharacter; break; } } if(widthsList.size() != 0) { ++it; // promote the iterator, from the already recorded glyph // W inFontContext->WriteKey(scW); mObjectsContext->StartArray(); for(; it != inEncodedGlyphs.end();++it) { FT_Load_Glyph(*mFontInfo,it->first,FT_LOAD_NO_SCALE); currentWidth = mFontInfo->GetInPDFMeasurements((*mFontInfo)->glyph->metrics.horiAdvance); if(currentWidth != defaultWidth) { if(it->second.mEncodedCharacter == previousCIDInList + 1) { ++previousCIDInList; allWidthsSame &= (widthsList.front() == currentWidth); widthsList.push_back(currentWidth); } else { WriteWidthsItem(allWidthsSame,widthsList,firstCIDInList,previousCIDInList); widthsList.clear(); widthsList.push_back(currentWidth); allWidthsSame = true; firstCIDInList = it->second.mEncodedCharacter; previousCIDInList = it->second.mEncodedCharacter; } } } if(widthsList.size() > 0) WriteWidthsItem(allWidthsSame,widthsList,firstCIDInList,previousCIDInList); mObjectsContext->EndArray(eTokenSeparatorEndLine); } }