Beispiel #1
0
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);
	}
}