Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: not all true types can use winansiencoding. need to check cmaps #257

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion PDFWriter/AbstractWrittenFont.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@

using namespace PDFHummus;

AbstractWrittenFont::AbstractWrittenFont(ObjectsContext* inObjectsContext)
AbstractWrittenFont::AbstractWrittenFont(ObjectsContext* inObjectsContext, FreeTypeFaceWrapper* inFontInfo)
{
mObjectsContext = inObjectsContext;
mFontInfo = inFontInfo;
mCIDRepresentation = NULL;
mANSIRepresentation = NULL;
}
Expand Down
3 changes: 2 additions & 1 deletion PDFWriter/AbstractWrittenFont.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class PDFParser;
class AbstractWrittenFont : public IWrittenFont
{
public:
AbstractWrittenFont(ObjectsContext* inObjectsContext);
AbstractWrittenFont(ObjectsContext* inObjectsContext, FreeTypeFaceWrapper* inFontInfo);
virtual ~AbstractWrittenFont(void);

virtual void AppendGlyphs(const GlyphUnicodeMappingList& inGlyphsList,
Expand All @@ -47,6 +47,7 @@ class AbstractWrittenFont : public IWrittenFont
WrittenFontRepresentation* mCIDRepresentation;
WrittenFontRepresentation* mANSIRepresentation;
ObjectsContext* mObjectsContext;
FreeTypeFaceWrapper* mFontInfo;

PDFHummus::EStatusCode WriteStateInDictionary(ObjectsContext* inStateWriter,DictionaryContext* inDerivedObjectDictionary);
PDFHummus::EStatusCode WriteStateAfterDictionary(ObjectsContext* inStateWriter);
Expand Down
4 changes: 2 additions & 2 deletions PDFWriter/FreeTypeFaceWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,11 +655,11 @@ IWrittenFont* FreeTypeFaceWrapper::CreateWrittenFontObject(ObjectsContext* inObj
if(FT_Get_CID_Is_Internally_CID_Keyed(mFace,&isCID) != 0)
isCID = false;

result = new WrittenFontCFF(inObjectsContext,isCID != 0, inFontIsToBeEmbedded); // CFF fonts should know if font is to be embedded, as the embedding code involves re-encoding of glyphs
result = new WrittenFontCFF(inObjectsContext, this,isCID != 0, inFontIsToBeEmbedded); // CFF fonts should know if font is to be embedded, as the embedding code involves re-encoding of glyphs
}
else if(strcmp(fontFormat,scTrueType) == 0)
{
result = new WrittenFontTrueType(inObjectsContext);
result = new WrittenFontTrueType(inObjectsContext, this);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion PDFWriter/IWrittenFont.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class IWrittenFont
/*
Write a font definition using the glyphs appended.
*/
virtual PDFHummus::EStatusCode WriteFontDefinition(FreeTypeFaceWrapper& inFontInfo,bool inEmbedFont) = 0;
virtual PDFHummus::EStatusCode WriteFontDefinition(bool inEmbedFont) = 0;

// state read and write
virtual PDFHummus::EStatusCode WriteState(ObjectsContext* inStateWriter,ObjectIDType inObjectID) = 0;
Expand Down
2 changes: 1 addition & 1 deletion PDFWriter/PDFUsedFont.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ EStatusCode PDFUsedFont::WriteFontDefinition()
if(!mWrittenFont)
return eSuccess;
else
return mWrittenFont->WriteFontDefinition(mFaceWrapper, mEmbedFont);
return mWrittenFont->WriteFontDefinition(mEmbedFont);
}

EStatusCode PDFUsedFont::WriteState(ObjectsContext* inStateWriter,ObjectIDType inObjectID)
Expand Down
8 changes: 4 additions & 4 deletions PDFWriter/WrittenFontCFF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

using namespace PDFHummus;

WrittenFontCFF::WrittenFontCFF(ObjectsContext* inObjectsContext,bool inIsCID, bool inFontWillBeEmbedded):AbstractWrittenFont(inObjectsContext)
WrittenFontCFF::WrittenFontCFF(ObjectsContext* inObjectsContext, FreeTypeFaceWrapper* inFontInfo, bool inIsCID, bool inFontWillBeEmbedded):AbstractWrittenFont(inObjectsContext, inFontInfo)
{
mAvailablePositionsCount = 255;
mFreeList.push_back(UCharAndUChar(1,255));
Expand Down Expand Up @@ -161,7 +161,7 @@ unsigned char WrittenFontCFF::AllocateFromFreeList(unsigned int inGlyph)
return result;
}

EStatusCode WrittenFontCFF::WriteFontDefinition(FreeTypeFaceWrapper& inFontInfo,bool inEmbedFont)
EStatusCode WrittenFontCFF::WriteFontDefinition(bool inEmbedFont)
{
EStatusCode status = PDFHummus::eSuccess;
do
Expand All @@ -170,7 +170,7 @@ EStatusCode WrittenFontCFF::WriteFontDefinition(FreeTypeFaceWrapper& inFontInfo,
{
CFFANSIFontWriter fontWriter;

status = fontWriter.WriteFont(inFontInfo, mANSIRepresentation, mObjectsContext, inEmbedFont);
status = fontWriter.WriteFont(*mFontInfo, mANSIRepresentation, mObjectsContext, inEmbedFont);
if(status != PDFHummus::eSuccess)
{
TRACE_LOG("WrittenFontCFF::WriteFontDefinition, Failed to write Ansi font definition");
Expand All @@ -184,7 +184,7 @@ EStatusCode WrittenFontCFF::WriteFontDefinition(FreeTypeFaceWrapper& inFontInfo,
CIDFontWriter fontWriter;
CFFDescendentFontWriter descendentFontWriter;

status = fontWriter.WriteFont(inFontInfo, mCIDRepresentation, mObjectsContext, &descendentFontWriter, inEmbedFont);
status = fontWriter.WriteFont(*mFontInfo, mCIDRepresentation, mObjectsContext, &descendentFontWriter, inEmbedFont);
if(status != PDFHummus::eSuccess)
{
TRACE_LOG("WrittenFontCFF::WriteFontDefinition, Failed to write CID font definition");
Expand Down
4 changes: 2 additions & 2 deletions PDFWriter/WrittenFontCFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ typedef std::list<UCharAndUChar> UCharAndUCharList;
class WrittenFontCFF : public AbstractWrittenFont
{
public:
WrittenFontCFF(ObjectsContext* inObjectsContext,bool inIsCID, bool inFontWillBeEmbedded);
WrittenFontCFF(ObjectsContext* inObjectsContext, FreeTypeFaceWrapper* inFontInfo, bool inIsCID, bool inFontWillBeEmbedded);
virtual ~WrittenFontCFF(void);


virtual PDFHummus::EStatusCode WriteFontDefinition(FreeTypeFaceWrapper& inFontInfo, bool inEmbedFont);
virtual PDFHummus::EStatusCode WriteFontDefinition(bool inEmbedFont);

virtual PDFHummus::EStatusCode WriteState(ObjectsContext* inStateWriter,ObjectIDType inObjectId);
virtual PDFHummus::EStatusCode ReadState(PDFParser* inStateReader,ObjectIDType inObjectID);
Expand Down
104 changes: 55 additions & 49 deletions PDFWriter/WrittenFontTrueType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,33 @@
#include "PDFObjectCast.h"
#include "PDFParser.h"
#include "PDFDictionary.h"
#include "FreeTypeFaceWrapper.h"

#include <ft2build.h>
#include FT_FREETYPE_H

using namespace PDFHummus;

WrittenFontTrueType::WrittenFontTrueType(ObjectsContext* inObjectsContext):AbstractWrittenFont(inObjectsContext)
bool FontHasCmapsForWinAnsiEncoding(FT_Face font) {
// See PDF Reference 5.5.5 Character Encoding, Encodings for TrueType Fonts. When is mapping from glyph name is possible, and so non CID encoding can be built - only if font contains either of
// two possible cmaps: win unicode bmp or macintosh roman. so check if got either of those.
for(FT_Int i = 0; i < font->num_charmaps; ++i) {
FT_CharMap charmap = font->charmaps[i];

if (charmap->platform_id == 3 && charmap->encoding_id == 1)
return true; // Windows Unicode BMP

if (charmap->platform_id == 1 && charmap->encoding_id == 0)
return true; // Macintosh Roman

}

return false;
}

WrittenFontTrueType::WrittenFontTrueType(ObjectsContext* inObjectsContext, FreeTypeFaceWrapper* inFontInfo):AbstractWrittenFont(inObjectsContext, inFontInfo)
{
fontSupportsWinAnsiEncoding = FontHasCmapsForWinAnsiEncoding(*inFontInfo);
}

WrittenFontTrueType::~WrittenFontTrueType(void)
Expand All @@ -43,18 +65,19 @@ WrittenFontTrueType::~WrittenFontTrueType(void)
/*
here's what i'm deciding on:
1. Can encoding if/f all text codes are available through WinAnsiEncoding.
[maybe should also make sure that the font has the relevant cmaps?! Or maybe I'm just assuming that...]
[maybe should also make sure that the font has the relevant cmaps?! Or maybe I'm just assuming that...] [That's what FontHasCmapsForWinAnsiEncoding and fontSupportsWinAnsiEncoding are for]
2. While encoding use WinAnsiEncoding values, of course. This will necasserily work
3. While writing the font description simply write the WinAnsiEncoding glyph name, and pray.*/

bool WrittenFontTrueType::AddToANSIRepresentation( const GlyphUnicodeMappingList& inGlyphsList,
UShortList& outEncodedCharacters)
{
bool WrittenFontTrueType::AddANSICandidates(const GlyphUnicodeMappingList& inGlyphsList, UShortList& ioCandidates) {
if(!fontSupportsWinAnsiEncoding) {
return false;
}

// i'm totally relying on the text here, which is fine till i'll do ligatures, in which case
// i'll need to make something different out of the text.
// as you can see this has little to do with glyphs (mainly cause i can't use FreeType to map the glyphs
// back to the rleevant unicode values...but no need anyways...that's why i carry the text).
UShortList candidates;
BoolAndByte encodingResult(true,0);
WinAnsiEncoding winAnsiEncoding;
GlyphUnicodeMappingList::const_iterator it = inGlyphsList.begin();
Expand All @@ -81,11 +104,20 @@ bool WrittenFontTrueType::AddToANSIRepresentation( const GlyphUnicodeMappingList
{
encodingResult = winAnsiEncoding.Encode(it->mUnicodeValues.front());
if(encodingResult.first)
candidates.push_back(encodingResult.second);
ioCandidates.push_back(encodingResult.second);
}
}

if(encodingResult.first)
return encodingResult.first;
}

bool WrittenFontTrueType::AddToANSIRepresentation(const GlyphUnicodeMappingList& inGlyphsList, UShortList& outEncodedCharacters)
{
UShortList candidates;

bool result = AddANSICandidates(inGlyphsList, candidates);

if(result)
{
// for the first time, add also 0,0 mapping
if(mANSIRepresentation->mGlyphIDToEncodedChar.size() == 0)
Expand All @@ -104,11 +136,11 @@ bool WrittenFontTrueType::AddToANSIRepresentation( const GlyphUnicodeMappingList
outEncodedCharacters = candidates;
}

return encodingResult.first;
return result;
}


EStatusCode WrittenFontTrueType::WriteFontDefinition(FreeTypeFaceWrapper& inFontInfo,bool inEmbedFont)
EStatusCode WrittenFontTrueType::WriteFontDefinition(bool inEmbedFont)
{
EStatusCode status = PDFHummus::eSuccess;
do
Expand All @@ -117,7 +149,7 @@ EStatusCode WrittenFontTrueType::WriteFontDefinition(FreeTypeFaceWrapper& inFont
{
TrueTypeANSIFontWriter fontWriter;

status = fontWriter.WriteFont(inFontInfo, mANSIRepresentation, mObjectsContext, inEmbedFont);
status = fontWriter.WriteFont(*mFontInfo, mANSIRepresentation, mObjectsContext, inEmbedFont);
if(status != PDFHummus::eSuccess)
{
TRACE_LOG("WrittenFontTrueType::WriteFontDefinition, Failed to write Ansi font definition");
Expand All @@ -131,7 +163,7 @@ EStatusCode WrittenFontTrueType::WriteFontDefinition(FreeTypeFaceWrapper& inFont
CIDFontWriter fontWriter;
TrueTypeDescendentFontWriter descendentFontWriter;

status = fontWriter.WriteFont(inFontInfo, mCIDRepresentation, mObjectsContext, &descendentFontWriter, inEmbedFont);
status = fontWriter.WriteFont(*mFontInfo, mCIDRepresentation, mObjectsContext, &descendentFontWriter, inEmbedFont);
if(status != PDFHummus::eSuccess)
{
TRACE_LOG("WrittenFontTrueType::WriteFontDefinition, Failed to write CID font definition");
Expand All @@ -150,46 +182,20 @@ bool WrittenFontTrueType::AddToANSIRepresentation( const GlyphUnicodeMappingList
UShortListList candidatesList;
UShortList candidates;
BoolAndByte encodingResult(true,0);
WinAnsiEncoding winAnsiEncoding;
GlyphUnicodeMappingListList::const_iterator itList = inGlyphsList.begin();
GlyphUnicodeMappingList::const_iterator it;
bool result = true;

for(; itList != inGlyphsList.end() && encodingResult.first; ++itList)
for(; itList != inGlyphsList.end() && result; ++itList)
{
it = itList->begin();
for(; it != itList->end() && encodingResult.first; ++it)
{
// don't bother with characters of more or less than one unicode
if(it->mUnicodeValues.size() != 1)
{
encodingResult.first = false;
}
else if(0x2022 == it->mUnicodeValues.front())
{
// From the reference:
// In WinAnsiEncoding, all unused codes greater than 40 map to the bullet character.
// However, only code 225 is specifically assigned to the bullet character; other codes are subject to future reassignment.

// now i don't know if it's related or not...but acrobat isn't happy when i'm using winansi with bullet. and text coming after that bullet may be
// corrupted.
// so i'm forcing CID if i hit bullet till i know better.
encodingResult.first = false;
}
else
{
encodingResult = winAnsiEncoding.Encode(it->mUnicodeValues.front());
if(encodingResult.first)
candidates.push_back(encodingResult.second);
}
}
if(encodingResult.first)
result = AddANSICandidates(*itList, candidates);
if(result)
{
candidatesList.push_back(candidates);
candidates.clear();
}
}

if(encodingResult.first)
if(result)
{
// for the first time, add also 0,0 mapping
if(mANSIRepresentation->mGlyphIDToEncodedChar.size() == 0)
Expand All @@ -216,7 +222,7 @@ bool WrittenFontTrueType::AddToANSIRepresentation( const GlyphUnicodeMappingList
outEncodedCharacters = candidatesList;
}

return encodingResult.first;
return result;
}

EStatusCode WrittenFontTrueType::WriteState(ObjectsContext* inStateWriter,ObjectIDType inObjectID)
Expand Down Expand Up @@ -246,9 +252,9 @@ EStatusCode WrittenFontTrueType::ReadState(PDFParser* inStateReader,ObjectIDType
return AbstractWrittenFont::ReadStateFromObject(inStateReader,writtenFontState.GetPtr());
}

unsigned short WrittenFontTrueType::EncodeCIDGlyph(unsigned int inGlyphId) {
// Gal 26/8/2017: Most of the times, the glyph IDs are CIDs. this is to retain a few requirements of True type fonts, and the case of fonts when they are not embedded.
// However, when CFF fonts are embedded, the matching code actually recreates a font from just the subset, and renumbers them based on the order
// of them joining the font. Hence, we need a slight difference for this case, and an override is provided
return (unsigned short)inGlyphId;
unsigned short WrittenFontTrueType::EncodeCIDGlyph(unsigned int inGlyphId) {
// Gal 26/8/2017: Most of the times, the glyph IDs are CIDs. this is to retain a few requirements of True type fonts, and the case of fonts when they are not embedded.
// However, when CFF fonts are embedded, the matching code actually recreates a font from just the subset, and renumbers them based on the order
// of them joining the font. Hence, we need a slight difference for this case, and an override is provided
return (unsigned short)inGlyphId;
}
10 changes: 8 additions & 2 deletions PDFWriter/WrittenFontTrueType.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@
class WrittenFontTrueType : public AbstractWrittenFont
{
public:
WrittenFontTrueType(ObjectsContext* inObjectsContext);
WrittenFontTrueType(ObjectsContext* inObjectsContext, FreeTypeFaceWrapper* inFontInfo);
~WrittenFontTrueType(void);

virtual PDFHummus::EStatusCode WriteFontDefinition(FreeTypeFaceWrapper& inFontInfo,bool inEmbedFont);
virtual PDFHummus::EStatusCode WriteFontDefinition(bool inEmbedFont);

virtual PDFHummus::EStatusCode WriteState(ObjectsContext* inStateWriter,ObjectIDType inObjectId);
virtual PDFHummus::EStatusCode ReadState(PDFParser* inStateReader,ObjectIDType inObjectID);


private:
bool fontSupportsWinAnsiEncoding;

virtual bool AddToANSIRepresentation( const GlyphUnicodeMappingList& inGlyphsList,
UShortList& outEncodedCharacters);

Expand All @@ -44,4 +46,8 @@ class WrittenFontTrueType : public AbstractWrittenFont

virtual unsigned short EncodeCIDGlyph(unsigned int inGlyphId);

bool AddANSICandidates(const GlyphUnicodeMappingList& inGlyphsList, UShortList& ioCandidates);



};
1 change: 1 addition & 0 deletions PDFWriterTesting/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ create_test_sourcelist (Tests
TIFFImageTest.cpp
TiffSpecialsTest.cpp
TimerTest.cpp
TrueTypeAnsiWriteBug.cpp
TrueTypeTest.cpp
TTCTest.cpp
Type1Test.cpp
Expand Down
Binary file not shown.
Loading
Loading