From 6d6d0970698b3741a7d121aea6970dbaf8049018 Mon Sep 17 00:00:00 2001 From: Oleg Korshul Date: Thu, 26 Sep 2019 15:54:55 +0300 Subject: [PATCH] Fix bug 42926 --- DesktopEditor/fontengine/ApplicationFonts.cpp | 12 +- DesktopEditor/fontengine/FontFile.cpp | 4 +- DesktopEditor/fontengine/FontFile.h | 29 ++++ DesktopEditor/fontengine/FontManager.cpp | 9 +- .../fontengine/application_generate_fonts.h | 23 ++- .../freetype-2.5.2/src/sfnt/sfobjs.c | 132 +++++++++++++++++- DesktopEditor/graphics/pro/graphics.pro | 2 + 7 files changed, 179 insertions(+), 32 deletions(-) diff --git a/DesktopEditor/fontengine/ApplicationFonts.cpp b/DesktopEditor/fontengine/ApplicationFonts.cpp index 6f2592f0d9..6b22147b2d 100644 --- a/DesktopEditor/fontengine/ApplicationFonts.cpp +++ b/DesktopEditor/fontengine/ApplicationFonts.cpp @@ -1352,17 +1352,9 @@ void CFontList::LoadFromArrayFiles(std::vector& oArray, int nFlag) continue; } - std::string sFamilyName = ""; - if (NULL != pFace->family_name) - sFamilyName = pFace->family_name; + std::wstring wsFamilyName = GetCorrectSfntName(pFace->family_name); + std::wstring wsStyleName = GetCorrectSfntName(pFace->style_name); - std::string sStyleName = ""; - if (NULL != pFace->style_name) - sStyleName = pFace->style_name; - - std::wstring wsFamilyName = NSFile::CUtf8Converter::GetUnicodeFromCharPtr(sFamilyName); - std::wstring wsStyleName = NSFile::CUtf8Converter::GetUnicodeFromCharPtr(sStyleName); - #ifdef _MAC if (wsFamilyName.find(L".") == 0) { diff --git a/DesktopEditor/fontengine/FontFile.cpp b/DesktopEditor/fontengine/FontFile.cpp index 100f5913f4..8845636e75 100644 --- a/DesktopEditor/fontengine/FontFile.cpp +++ b/DesktopEditor/fontengine/FontFile.cpp @@ -682,9 +682,9 @@ void CFontFile::CheckHintsSupport() return; } - std::string sFamilyName((NULL != m_pFace->family_name) ? m_pFace->family_name : ""); + std::wstring sFamilyName = GetCorrectSfntName(m_pFace->family_name); - if (sFamilyName == "MS Mincho" || sFamilyName == "Castellar") + if (m_sName == L"MS Mincho" || m_sName == L"Castellar") m_bHintsSupport = FALSE; } diff --git a/DesktopEditor/fontengine/FontFile.h b/DesktopEditor/fontengine/FontFile.h index b0c355bb32..f2137ed5cc 100644 --- a/DesktopEditor/fontengine/FontFile.h +++ b/DesktopEditor/fontengine/FontFile.h @@ -44,6 +44,35 @@ #include "FontPath.h" #include "GlyphString.h" +#include "../common/File.h" + +static std::wstring GetCorrectSfntName(const char* name) +{ + if (NULL == name) + return L""; + const char* name_cur = name; + int name_len = 0; + while (*name_cur++) + ++name_len; + + bool isUtf8 = false; + if (6 < name_len) + { + if ('<' == name[0] || 'u' == name[1] || 't' == name[2] || + 'f' == name[3] || '8' == name[4] || '>' == name[5]) + { + name_cur = name + 6; + name_len -= 6; + isUtf8 = true; + } + } + + if (isUtf8) + { + return NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)name_cur, (LONG)name_len); + } + return NSFile::CUtf8Converter::GetUnicodeFromCharPtr(name_cur, (LONG)name_len); +} //------------------------------------------------------------------------------------------------------------------------------- // TODO: RasterHeep diff --git a/DesktopEditor/fontengine/FontManager.cpp b/DesktopEditor/fontengine/FontManager.cpp index 8f4cd295de..ac8efce364 100644 --- a/DesktopEditor/fontengine/FontManager.cpp +++ b/DesktopEditor/fontengine/FontManager.cpp @@ -686,9 +686,9 @@ INT CFontManager::LoadFontFromFile(const std::wstring& sPath, const int& lFaceIn m_pFont->SetSizeAndDpi(dSize, (UINT)dDpiX, (UINT)dDpiY); m_sName = L""; - if (m_pFont->m_pFace && m_pFont->m_pFace->family_name) + if (m_pFont->m_pFace) { - m_pFont->m_sName = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)m_pFont->m_pFace->family_name, strlen(m_pFont->m_pFace->family_name)); + m_pFont->m_sName = GetCorrectSfntName(m_pFont->m_pFace->family_name); m_sName = m_pFont->m_sName; } @@ -710,9 +710,10 @@ INT CFontManager::LoadFontFromFile2(NSFonts::IFontsCache* pCache, const std::wst m_pFont->SetSizeAndDpi(dSize, (UINT)dDpiX, (UINT)dDpiY); m_sName = L""; - if (m_pFont->m_pFace && m_pFont->m_pFace->family_name) + if (m_pFont->m_pFace) { - m_sName = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)m_pFont->m_pFace->family_name, strlen(m_pFont->m_pFace->family_name)); + m_pFont->m_sName = GetCorrectSfntName(m_pFont->m_pFace->family_name); + m_sName = m_pFont->m_sName; } return TRUE; diff --git a/DesktopEditor/fontengine/application_generate_fonts.h b/DesktopEditor/fontengine/application_generate_fonts.h index 88a6f060d4..a439654ff1 100644 --- a/DesktopEditor/fontengine/application_generate_fonts.h +++ b/DesktopEditor/fontengine/application_generate_fonts.h @@ -561,35 +561,28 @@ namespace NSCommon } else if (pFile) { + // у нас режим "без квадратов" + // но есть шрифты, в которых символы есть, но нулевой ширины. + // только из-за таких шрифтов делаем заглушку int nFontNameLen = (int)sFontName.length(); - bool bIsPresentAll = true; + bool bIsExistEmpty = false; for (int nC = 0; nC < nFontNameLen; nC++) { int nCMapIndex = 0; int nGid = pFile->SetCMapForCharCode(sFontName.at(nC), &nCMapIndex); - if (0 >= nGid) + if (0 < nGid && 0.0001 > pFile->GetCharWidth(nGid)) { - bIsPresentAll = false; + bIsExistEmpty = true; break; } - else - { - double offsetG = pFile->GetCharWidth(nGid); - if (offsetG < 0.0001) - { - bIsPresentAll = false; - break; - } - } } - if (!bIsPresentAll) + if (bIsExistEmpty) { NSFonts::CFontSelectFormat oSelectFormat; oSelectFormat.wsName = new std::wstring(L"Arial"); - NSFonts::CFontInfo* pInfoCur = pManager->GetFontInfoByParams(oSelectFormat); - + NSFonts::CFontInfo* pInfoCur = pManager->GetFontInfoByParams(oSelectFormat); if (NULL != pInfoCur) { pManager->LoadFontFromFile(pInfoCur->m_wsFontPath, 0, 14, dDpi, dDpi); diff --git a/DesktopEditor/freetype-2.5.2/src/sfnt/sfobjs.c b/DesktopEditor/freetype-2.5.2/src/sfnt/sfobjs.c index 09fbb4285f..daa5a0f96a 100644 --- a/DesktopEditor/freetype-2.5.2/src/sfnt/sfobjs.c +++ b/DesktopEditor/freetype-2.5.2/src/sfnt/sfobjs.c @@ -44,8 +44,138 @@ #undef FT_COMPONENT #define FT_COMPONENT trace_sfobjs +#ifdef FT_SUPPORT_UTF8_IN_NAMES + // common funcs + static void tt_name_entry_unicode_from_utf16(FT_Byte* string, FT_UShort len, FT_Int** out, FT_UShort* out_len, FT_Memory memory) + { + FT_Int* unicode = NULL; + FT_UShort alloc_len = len / 2; + FT_UShort n = 0; + FT_UShort cur = 0, cur2 = 0; + FT_UShort out_len_cur = 0; + FT_Error error; + *out = NULL; + *out_len = 0; + if ( FT_NEW_ARRAY( unicode, alloc_len ) ) + return; + for ( n = 0; n < alloc_len; n++ ) + { + cur = FT_NEXT_USHORT( string ); + + if ( cur == 0 ) + break; + + if (cur < 0xD800 || cur > 0xDBFF) + { + unicode[out_len_cur++] = cur; + } + else + { + cur2 = FT_NEXT_USHORT( string ); + ++n; + unicode[out_len_cur++] = ((((cur - 0xD800) & 0x03FF) << 10) | ((cur2 - 0xDC00) & 0x03FF)) + 0x10000; + } + } + + *out = unicode; + *out_len = out_len_cur; + } + + static FT_String* tt_name_entry_utf8_from_unicode(FT_Int* unicode, FT_UShort len, FT_Memory memory) + { + FT_String* ret = NULL; + FT_String* retCur = NULL; + FT_UShort index = 0; + FT_UInt alloc_len = 6 * len + 6 + 1; + FT_Int code; + FT_Error error; + + if (0 == len) + return ret; + + if ( FT_NEW_ARRAY( ret, alloc_len ) ) + return ret; + + retCur = ret; + + *retCur++ = '<'; + *retCur++ = 'u'; + *retCur++ = 't'; + *retCur++ = 'f'; + *retCur++ = '8'; + *retCur++ = '>'; + + for ( index = 0; index < len; index++ ) + { + code = unicode[index]; + + if (code < 0x80) + { + *retCur++ = (FT_String)code; + } + else if (code < 0x0800) + { + *retCur++ = (0xC0 | (code >> 6)); + *retCur++ = (0x80 | (code & 0x3F)); + } + else if (code < 0x10000) + { + *retCur++ = (0xE0 | (code >> 12)); + *retCur++ = (0x80 | (code >> 6 & 0x3F)); + *retCur++ = (0x80 | (code & 0x3F)); + } + else if (code < 0x1FFFFF) + { + *retCur++ = (0xF0 | (code >> 18)); + *retCur++ = (0x80 | (code >> 12 & 0x3F)); + *retCur++ = (0x80 | (code >> 6 & 0x3F)); + *retCur++ = (0x80 | (code & 0x3F)); + } + else if (code < 0x3FFFFFF) + { + *retCur++ = (0xF8 | (code >> 24)); + *retCur++ = (0x80 | (code >> 18 & 0x3F)); + *retCur++ = (0x80 | (code >> 12 & 0x3F)); + *retCur++ = (0x80 | (code >> 6 & 0x3F)); + *retCur++ = (0x80 | (code & 0x3F)); + } + else if (code < 0x7FFFFFFF) + { + *retCur++ = (0xFC | (code >> 30)); + *retCur++ = (0x80 | (code >> 24 & 0x3F)); + *retCur++ = (0x80 | (code >> 18 & 0x3F)); + *retCur++ = (0x80 | (code >> 12 & 0x3F)); + *retCur++ = (0x80 | (code >> 6 & 0x3F)); + *retCur++ = (0x80 | (code & 0x3F)); + } + } + + *retCur = 0; + return ret; + } + + // ft interface + static FT_String* tt_name_entry_utf8_from_utf16(TT_NameEntry entry, + FT_Memory memory) + { + FT_Int* unicode = NULL; + FT_UShort unicode_len = 0; + FT_String* retValue = NULL; + tt_name_entry_unicode_from_utf16(entry->string, entry->stringLength, &unicode, &unicode_len, memory); + retValue = tt_name_entry_utf8_from_unicode(unicode, unicode_len, memory); + FT_FREE(unicode); + return retValue; + } + /* convert a UTF-16 name entry to ASCII */ + static FT_String* + tt_name_entry_ascii_from_utf16( TT_NameEntry entry, + FT_Memory memory ) + { + return tt_name_entry_utf8_from_utf16(entry, memory); + } +#else /* convert a UTF-16 name entry to ASCII */ static FT_String* tt_name_entry_ascii_from_utf16( TT_NameEntry entry, @@ -79,7 +209,7 @@ return string; } - +#endif /* convert an Apple Roman or symbol name entry to ASCII */ static FT_String* diff --git a/DesktopEditor/graphics/pro/graphics.pro b/DesktopEditor/graphics/pro/graphics.pro index 1c35c1ca98..dc74041ca2 100644 --- a/DesktopEditor/graphics/pro/graphics.pro +++ b/DesktopEditor/graphics/pro/graphics.pro @@ -32,6 +32,8 @@ DEFINES += \ MNG_STORE_CHUNKS\ MNG_ERROR_TELLTALE +DEFINES += FT_SUPPORT_UTF8_IN_NAMES + core_linux { DEFINES += \ HAVE_UNISTD_H