//* adfreetype.cpp //* //* Copyright © 2013 CDP Communications Inc. All Rights Reserved //* //* Remarks //* Implements thin C++ wrapper over FreeType //////////////////////////////////////////////////////////////////////////////// #include "adfreetype.h" #include #include #include #include #include FT_FREETYPE_H #include FT_TRUETYPE_IDS_H #include FT_TRUETYPE_TABLES_H #include FT_SFNT_NAMES_H #include FT_TRUETYPE_TAGS_H #include #include namespace { FT_Library InitializeFreeType ( ) { FT_Library library(0); FT_Error ftError = FT_Init_FreeType (&library); if (0 == ftError) { return library; } return 0; } void* CreateFaceFailed ( const unsigned char* buffer, size_t cBuffer, ReleaseTypefaceMemoryCallBackSite_t releaseMemoryCallback ) { releaseMemoryCallback (buffer, cBuffer); return 0; } FT_Face CreateFace ( FT_Library library, const unsigned char* buffer, size_t cBuffer, ReleaseTypefaceMemoryCallBackSite_t releaseMemoryCallback ) { FT_Face ftFace(0); return (0 == FT_New_Memory_Face (library, buffer, cBuffer, 0, &ftFace)) ? ftFace : 0; } const unsigned char hexFormat[] = "0123456789ABCDEF"; size_t DumpSpecifiedNumberOfBytesInHex ( std::string& dest, const unsigned char* src, size_t cBytes) { dest.clear ( ); for (size_t i = 0; i != cBytes; ++i) { unsigned char nibble = ((*(src + i) >> 4) & 0x0f); dest += hexFormat[nibble]; nibble = *(src + i) & 0x0f; dest += hexFormat[nibble]; } return dest.size ( ); } short ReturnTTShortAsShort (const unsigned char* p) { return ((_be16*)(p))->operator TadInt16 ( ); } unsigned short ReturnTTUnsignedShortAsUnsignedShort (const unsigned char* p) { return ((_be16*)(p))->operator TadUInt16 ( ); } long ReturnTTLongAsLong (const unsigned char* p) { return ((_be32*)(p))->operator TadInt32 ( ); } unsigned long ReturnTTUnsignedLongAsUnsignedLong (const unsigned char* p) { return ((_be32*)(p))->operator TadUInt32 ( ); } } AdFreeTypeLibrary::AdFreeTypeLibrary ( ) : ftLibrary_(InitializeFreeType ( )) { } AdFreeTypeLibrary::~AdFreeTypeLibrary ( ) { FT_Done_FreeType (ftLibrary_); } void AdFreeTypeLibrary::VersionReleaseInformation ( int &version, int &release, int &patch ) { FT_Library_Version (ftLibrary_, &version, &release, &patch); } FT_Library AdFreeTypeLibrary::Library ( ) const { return ftLibrary_; } AdFontFace::AdFontFace ( FT_Library ftLibrary, const unsigned char* typefaceMemory, size_t cTypefaceMemory, ReleaseTypefaceMemoryCallBackSite_t releaseMemoryFunction ) : ftFace_(CreateFace (ftLibrary, typefaceMemory, cTypefaceMemory, releaseMemoryFunction)), ftLibrary_(ftLibrary), releaseMemoryFunction_(releaseMemoryFunction), typefaceMemory_(typefaceMemory) { } AdFontFace::~AdFontFace ( ) { if (ftFace_) { FT_Done_Face (ftFace_); releaseMemoryFunction_(typefaceMemory_, cTypefaceMemory_); } } FT_Library AdFontFace::Library ( ) const { return ftLibrary_;} FT_Face AdFontFace::Face ( ) const { return ftFace_; } struct FontTableLoader::Impl { Impl ( ) : table_(), fontFace_(0), tag_(0), cTable_(0) { } ~Impl ( ) { } int Load ( FT_ULong tag, AdFontFace& fontFace ) { unsigned long cTableToLoad = 0; int rc = (0 == FT_Load_Sfnt_Table(fontFace.Face ( ), tag, 0, 0, &cTableToLoad)) ? 0 : 16; if (0 == rc) { if (table_.capacity ( ) < cTableToLoad) { table_.reserve (cTableToLoad); } table_.resize (cTableToLoad); rc = (0 == FT_Load_Sfnt_Table(fontFace.Face ( ), tag, 0, &table_[0], &cTableToLoad)) ? 0 : 16; if (0 == rc) { fontFace_ = &fontFace; tag_ = tag; cTable_ = cTableToLoad; } } return rc; } std::vector table_; // An array of bytes large enough to hold the last table loaded AdFontFace* fontFace_; std::string str_; FT_ULong tag_; // tag identifying table to load FT_ULong cTable_; // the count of actual data stored in the }; FontTableLoader::FontTableLoader ( ) : impl_(new Impl) { } FontTableLoader::~FontTableLoader ( ) { delete impl_; } int FontTableLoader::Load ( unsigned long tag, AdFontFace& face ) { return ((tag == impl_->tag_) && (face.Face( ) == impl_->fontFace_->Face( ))) ? 0 : impl_->Load (tag, face); } const unsigned char* FontTableLoader::Table ( ) const { return &impl_->table_[0]; } size_t FontTableLoader::Size ( ) const { return impl_->cTable_; } const unsigned char* FontTableLoader::HexDumpBytes ( size_t offset, size_t cBytes ) { size_t cDumped = DumpSpecifiedNumberOfBytesInHex (impl_->str_ , Table () + offset, cBytes); assert ((cDumped = 2*cBytes) && "Error in dumping bytes in hex"); return (unsigned char*)impl_->str_.c_str ( ); } OS2Table::OS2Table ( FontTableLoader& fontTable ) : fontTable_(fontTable) { } OS2Table::~OS2Table ( ) { } int OS2Table::Load ( AdFontFace& face ) { return fontTable_.Load (TTAG_OS2, face); } unsigned short OS2Table::Version ( ) const { size_t ct = sizeof(TT_OS2_); size_t cTable = fontTable_.Size ( ); const unsigned char* t = fontTable_.Table ( ); return ReturnTTUnsignedShortAsUnsignedShort (t); //return ReturnTTUnsignedShortAsUnsignedShort (&((TT_OS2*)fontTable_.Table ( ))->version); } const unsigned char* OS2Table::Panose ( ) { static const TT_OS2* p = 0; static size_t cPanose = sizeof(p->panose) / sizeof(p->panose[0]); static size_t oPanose = offsetof(TT_OS2_, panose); return fontTable_.HexDumpBytes(oPanose, cPanose); } unsigned long OS2Table::ulUnicodeRange1 ( ) const { size_t oulRange1 = offsetof(TT_OS2_, TT_OS2_::ulUnicodeRange1); const unsigned char* t = fontTable_.Table ( ) + oulRange1; return ReturnTTUnsignedLongAsUnsignedLong (t); } unsigned long OS2Table::ulUnicodeRange2 ( ) const { size_t oulRange2 = offsetof(TT_OS2_, TT_OS2_::ulUnicodeRange2); const unsigned char* t = fontTable_.Table ( ) + oulRange2; return ReturnTTUnsignedLongAsUnsignedLong (t); } unsigned long OS2Table::ulUnicodeRange3 ( ) const { size_t oulRange3 = offsetof(TT_OS2_, TT_OS2_::ulUnicodeRange3); const unsigned char* t = fontTable_.Table ( ) + oulRange3; return ReturnTTUnsignedLongAsUnsignedLong (t); } unsigned long OS2Table::ulUnicodeRange4 ( ) const { size_t oulRange4 = offsetof(TT_OS2_, TT_OS2_::ulUnicodeRange4); const unsigned char* t = fontTable_.Table ( ) + oulRange4; return ReturnTTUnsignedLongAsUnsignedLong (t); } unsigned long OS2Table::ulCodePageRange1 ( ) const { size_t oulCodePageRange1 = offsetof(TT_OS2_, TT_OS2_::ulCodePageRange1); const unsigned char* t = fontTable_.Table ( ) + oulCodePageRange1; return ReturnTTUnsignedLongAsUnsignedLong (t); } unsigned long OS2Table::ulCodePageRange2 ( ) const { size_t oulCodePageRange2 = offsetof(TT_OS2_, TT_OS2_::ulCodePageRange2); const unsigned char* t = fontTable_.Table ( ) + oulCodePageRange2; return ReturnTTUnsignedLongAsUnsignedLong (t); }