diff --git a/data/mangal.ttf b/data/mangal.ttf new file mode 100644 index 0000000000..bce3e5c38d Binary files /dev/null and b/data/mangal.ttf differ diff --git a/data/unicode_blocks.txt b/data/unicode_blocks.txt new file mode 100644 index 0000000000..7c9e5dff8f --- /dev/null +++ b/data/unicode_blocks.txt @@ -0,0 +1,152 @@ +Basic_Latin 0x0000 0x007F +Latin-1_Supplement 0x0080 0x00FF +Latin_Extended-A 0x0100 0x017F +Latin_Extended-B 0x0180 0x024F +IPA_Extensions 0x0250 0x02AF +Spacing_Modifier_Letters 0x02B0 0x02FF +Combining_Diacritical_Marks 0x0300 0x036F +Greek_and_Coptic 0x0370 0x03FF +Cyrillic 0x0400 0x04FF +Cyrillic_Supplement 0x0500 0x052F +Armenian 0x0530 0x058F +Hebrew 0x0590 0x05FF +Arabic 0x0600 0x06FF +Syriac 0x0700 0x074F +Arabic_Supplement 0x0750 0x077F +Thaana 0x0780 0x07BF +NKo 0x07C0 0x07FF +Samaritan 0x0800 0x083F +Mandaic 0x0840 0x085F +Devanagari 0x0900 0x097F +Bengali 0x0980 0x09FF +Gurmukhi 0x0A00 0x0A7F +Gujarati 0x0A80 0x0AFF +Oriya 0x0B00 0x0B7F +Tamil 0x0B80 0x0BFF +Telugu 0x0C00 0x0C7F +Kannada 0x0C80 0x0CFF +Malayalam 0x0D00 0x0D7F +Sinhala 0x0D80 0x0DFF +Thai 0x0E00 0x0E7F +Lao 0x0E80 0x0EFF +Tibetan 0x0F00 0x0FFF +Myanmar 0x1000 0x109F +Georgian 0x10A0 0x10FF +Hangul_Jamo 0x1100 0x11FF +Ethiopic 0x1200 0x137F +Ethiopic_Supplement 0x1380 0x139F +Cherokee 0x13A0 0x13FF +Unified_Canadian_Aboriginal_Syllabics 0x1400 0x167F +Ogham 0x1680 0x169F +Runic 0x16A0 0x16FF +Tagalog 0x1700 0x171F +Hanunoo 0x1720 0x173F +Buhid 0x1740 0x175F +Tagbanwa 0x1760 0x177F +Khmer 0x1780 0x17FF +Mongolian 0x1800 0x18AF +Unified_Canadian_Aboriginal_Syllabics_Extended 0x18B0 0x18FF +Limbu 0x1900 0x194F +Tai_Le 0x1950 0x197F +New_Tai_Lue 0x1980 0x19DF +Khmer_Symbols 0x19E0 0x19FF +Buginese 0x1A00 0x1A1F +Tai_Tham 0x1A20 0x1AAF +Balinese 0x1B00 0x1B7F +Sundanese 0x1B80 0x1BBF +Batak 0x1BC0 0x1BFF +Lepcha 0x1C00 0x1C4F +Ol_Chiki 0x1C50 0x1C7F +Vedic_Extensions 0x1CD0 0x1CFF +Phonetic_Extensions 0x1D00 0x1D7F +Phonetic_Extensions_Supplement 0x1D80 0x1DBF +Combining_Diacritical_Marks_Supplement 0x1DC0 0x1DFF +Latin_Extended_Additional 0x1E00 0x1EFF +Greek_Extended 0x1F00 0x1FFF +General_Punctuation 0x2000 0x206F +Superscripts_and_Subscripts 0x2070 0x209F +Currency_Symbols 0x20A0 0x20CF +Combining_Diacritical_Marks_for_Symbols 0x20D0 0x20FF +Letterlike_Symbols 0x2100 0x214F +Number_Forms 0x2150 0x218F +Arrows 0x2190 0x21FF +Mathematical_Operators 0x2200 0x22FF +Miscellaneous_Technical 0x2300 0x23FF +Control_Pictures 0x2400 0x243F +Optical_Character_Recognition 0x2440 0x245F +Enclosed_Alphanumerics 0x2460 0x24FF +Box_Drawing 0x2500 0x257F +Block_Elements 0x2580 0x259F +Geometric_Shapes 0x25A0 0x25FF +Miscellaneous_Symbols 0x2600 0x26FF +Dingbats 0x2700 0x27BF +Miscellaneous_Mathematical_Symbols-A 0x27C0 0x27EF +Supplemental_Arrows-A 0x27F0 0x27FF +Braille_Patterns 0x2800 0x28FF +Supplemental_Arrows-B 0x2900 0x297F +Miscellaneous_Mathematical_Symbols-B 0x2980 0x29FF +Supplemental_Mathematical_Operators 0x2A00 0x2AFF +Miscellaneous_Symbols_and_Arrows 0x2B00 0x2BFF +Glagolitic 0x2C00 0x2C5F +Latin_Extended-C 0x2C60 0x2C7F +Coptic 0x2C80 0x2CFF +Georgian_Supplement 0x2D00 0x2D2F +Tifinagh 0x2D30 0x2D7F +Ethiopic_Extended 0x2D80 0x2DDF +Cyrillic_Extended-A 0x2DE0 0x2DFF +Supplemental_Punctuation 0x2E00 0x2E7F +CJK_Radicals_Supplement 0x2E80 0x2EFF +Kangxi_Radicals 0x2F00 0x2FDF +Ideographic_Description_Characters 0x2FF0 0x2FFF +CJK_Symbols_and_Punctuation 0x3000 0x303F +Hiragana 0x3040 0x309F +Katakana 0x30A0 0x30FF +Bopomofo 0x3100 0x312F +Hangul_Compatibility_Jamo 0x3130 0x318F +Kanbun 0x3190 0x319F +Bopomofo_Extended 0x31A0 0x31BF +CJK_Strokes 0x31C0 0x31EF +Katakana_Phonetic_Extensions 0x31F0 0x31FF +Enclosed_CJK_Letters_and_Months 0x3200 0x32FF +CJK_Compatibility 0x3300 0x33FF +CJK_Unified_Ideographs_Extension_A 0x3400 0x4DBF +Yijing_Hexagram_Symbols 0x4DC0 0x4DFF +CJK_Unified_Ideographs 0x4E00 0x9FFF +Yi_Syllables 0xA000 0xA48F +Yi_Radicals 0xA490 0xA4CF +Lisu 0xA4D0 0xA4FF +Vai 0xA500 0xA63F +Cyrillic_Extended-B 0xA640 0xA69F +Bamum 0xA6A0 0xA6FF +Modifier_Tone_Letters 0xA700 0xA71F +Latin_Extended-D 0xA720 0xA7FF +Syloti_Nagri 0xA800 0xA82F +Common_Indic_Number_Forms 0xA830 0xA83F +Phags-pa 0xA840 0xA87F +Saurashtra 0xA880 0xA8DF +Devanagari_Extended 0xA8E0 0xA8FF +Kayah_Li 0xA900 0xA92F +Rejang 0xA930 0xA95F +Hangul_Jamo_Extended-A 0xA960 0xA97F +Javanese 0xA980 0xA9DF +Cham 0xAA00 0xAA5F +Myanmar_Extended-A 0xAA60 0xAA7F +Tai_Viet 0xAA80 0xAADF +Ethiopic_Extended-A 0xAB00 0xAB2F +Meetei_Mayek 0xABC0 0xABFF +Hangul_Syllables 0xAC00 0xD7AF +Hangul_Jamo_Extended-B 0xD7B0 0xD7FF +High_Surrogates 0xD800 0xDB7F +High_Private_Use_Surrogates 0xDB80 0xDBFF +Low_Surrogates 0xDC00 0xDFFF +Private_Use_Area 0xE000 0xF8FF +CJK_Compatibility_Ideographs 0xF900 0xFAFF +Alphabetic_Presentation_Forms 0xFB00 0xFB4F +Arabic_Presentation_Forms-A 0xFB50 0xFDFF +Variation_Selectors 0xFE00 0xFE0F +Vertical_Forms 0xFE10 0xFE1F +Combining_Half_Marks 0xFE20 0xFE2F +CJK_Compatibility_Forms 0xFE30 0xFE4F +Small_Form_Variants 0xFE50 0xFE6F +Arabic_Presentation_Forms-B 0xFE70 0xFEFF +Halfwidth_and_Fullwidth_Forms 0xFF00 0xFFEF diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm index 53820fc9fb..80019d7fd4 100644 --- a/iphone/Maps/Classes/EAGLView.mm +++ b/iphone/Maps/Classes/EAGLView.mm @@ -91,10 +91,10 @@ smallVBSize, smallIBSize, 30, blitVBSize, blitIBSize, 20, 512, 256, 10, - 2000000)); + GetPlatform().ReadPathForFile("unicode_blocks.txt").c_str(), 2000000)); -// resourceManager->addFont(GetPlatform().ReadPathForFile("dejavusans.ttf").c_str()); - resourceManager->addFont(GetPlatform().ReadPathForFile("wqy-microhei.ttf").c_str()); + + resourceManager->addFonts(GetPlatform().GetFontNames()); DrawerYG::params_t p; p.m_resourceManager = resourceManager; diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 949c5939c1..5d387df6c2 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ EE12021011CD464100ABDD5D /* libmap.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE12020611CD464100ABDD5D /* libmap.a */; }; EE12021211CD464100ABDD5D /* libyg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE12020811CD464100ABDD5D /* libyg.a */; }; EE12092C12BD67C900068DC3 /* wqy-microhei.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EE12092B12BD67C900068DC3 /* wqy-microhei.ttf */; }; + EE583CBB12F773F00042CBE3 /* unicode_blocks.txt in Resources */ = {isa = PBXBuildFile; fileRef = EE583CBA12F773F00042CBE3 /* unicode_blocks.txt */; }; EE7F29811219ECA300EB67A9 /* RenderBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */; }; EE7F29821219ECA300EB67A9 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F297E1219ECA300EB67A9 /* RenderContext.mm */; }; EE7F29831219ECA300EB67A9 /* WindowHandle.mm in Sources */ = {isa = PBXBuildFile; fileRef = EE7F29801219ECA300EB67A9 /* WindowHandle.mm */; }; @@ -39,6 +40,7 @@ EEF5745512DE1AD50082F472 /* libfribidi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EEF5745412DE1AD50082F472 /* libfribidi.a */; }; EEFC0A9612B561B7002914FF /* dejavusans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EEFC0A9512B561B7002914FF /* dejavusans.ttf */; }; EEFC0BBF12B5656A002914FF /* libfreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EE12020311CD464100ABDD5D /* libfreetype.a */; }; + EEFE7BBA12F78091006AF8C3 /* mangal.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EEFE7BB912F78091006AF8C3 /* mangal.ttf */; }; FA04373212CAB83F00017494 /* libstorage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA04373112CAB83F00017494 /* libstorage.a */; }; FA065FED128614C400FEA989 /* MainWindow-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA065FEC128614C400FEA989 /* MainWindow-iPad.xib */; }; FA065FFF1286167A00FEA989 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FA065FFD1286167A00FEA989 /* Default@2x.png */; }; @@ -93,6 +95,7 @@ EE12020811CD464100ABDD5D /* libyg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libyg.a; sourceTree = SOURCE_ROOT; }; EE12092B12BD67C900068DC3 /* wqy-microhei.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "wqy-microhei.ttf"; path = "../../data/wqy-microhei.ttf"; sourceTree = ""; }; EE16192B126E374500622BD0 /* RenderContext.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RenderContext.hpp; path = Classes/RenderContext.hpp; sourceTree = SOURCE_ROOT; }; + EE583CBA12F773F00042CBE3 /* unicode_blocks.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = unicode_blocks.txt; path = ../../data/unicode_blocks.txt; sourceTree = ""; }; EE7F297C1219ECA300EB67A9 /* RenderBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RenderBuffer.hpp; path = Classes/RenderBuffer.hpp; sourceTree = SOURCE_ROOT; }; EE7F297D1219ECA300EB67A9 /* RenderBuffer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RenderBuffer.mm; path = Classes/RenderBuffer.mm; sourceTree = SOURCE_ROOT; }; EE7F297E1219ECA300EB67A9 /* RenderContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RenderContext.mm; path = Classes/RenderContext.mm; sourceTree = SOURCE_ROOT; }; @@ -107,6 +110,7 @@ EEE4C9411298A31B007231A9 /* basic_highres.skn */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = basic_highres.skn; path = ../../data/basic_highres.skn; sourceTree = SOURCE_ROOT; }; EEF5745412DE1AD50082F472 /* libfribidi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libfribidi.a; sourceTree = SOURCE_ROOT; }; EEFC0A9512B561B7002914FF /* dejavusans.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = dejavusans.ttf; path = ../../data/dejavusans.ttf; sourceTree = ""; }; + EEFE7BB912F78091006AF8C3 /* mangal.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = mangal.ttf; path = ../../data/mangal.ttf; sourceTree = ""; }; FA04373112CAB83F00017494 /* libstorage.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libstorage.a; sourceTree = SOURCE_ROOT; }; FA065FEC128614C400FEA989 /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "MainWindow-iPad.xib"; path = "Resources-iPad/MainWindow-iPad.xib"; sourceTree = SOURCE_ROOT; }; FA065FFD1286167A00FEA989 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = SOURCE_ROOT; }; @@ -252,6 +256,8 @@ FA065FC61286143F00FEA989 /* External Resources */ = { isa = PBXGroup; children = ( + EEFE7BB912F78091006AF8C3 /* mangal.ttf */, + EE583CBA12F773F00042CBE3 /* unicode_blocks.txt */, FA57ADF312F338FB002BFB9D /* countries_poly.txt */, FA46DA2B12D4166E00968C36 /* countries.txt */, FA46DA0412D414D200968C36 /* maps.update */, @@ -395,6 +401,8 @@ FA46DA0512D414D200968C36 /* maps.update in Resources */, FA46DA2C12D4166E00968C36 /* countries.txt in Resources */, FA57ADF412F338FB002BFB9D /* countries_poly.txt in Resources */, + EE583CBB12F773F00042CBE3 /* unicode_blocks.txt in Resources */, + EEFE7BBA12F78091006AF8C3 /* mangal.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/iphone/Maps/Platform/IPhonePlatform.hpp b/iphone/Maps/Platform/IPhonePlatform.hpp index 0e94b121b3..066de0f389 100644 --- a/iphone/Maps/Platform/IPhonePlatform.hpp +++ b/iphone/Maps/Platform/IPhonePlatform.hpp @@ -19,6 +19,7 @@ public: virtual string const SkinName() const; virtual bool IsMultiSampled() const; virtual bool DoPeriodicalUpdate() const; + virtual vector GetFontNames() const; private: string m_skinName; diff --git a/iphone/Maps/Platform/IPhonePlatform.mm b/iphone/Maps/Platform/IPhonePlatform.mm index 06db42e6c4..8a6c9fb694 100644 --- a/iphone/Maps/Platform/IPhonePlatform.mm +++ b/iphone/Maps/Platform/IPhonePlatform.mm @@ -31,7 +31,7 @@ IPhonePlatform::IPhonePlatform() m_visualScale = 1.0; m_skinName = "basic.skn"; m_isMultiSampled = true; - m_doPeriodicalUpdate = false; + m_doPeriodicalUpdate = true; /// Calculating resolution UIDevice * device = [UIDevice currentDevice]; @@ -168,6 +168,23 @@ bool IPhonePlatform::DoPeriodicalUpdate() const return m_doPeriodicalUpdate; } +vector IPhonePlatform::GetFontNames() const +{ + vector res; +/* string fontFolder("/System/Library/Fonts/"); + + GetFilesInDir(fontFolder, ".ttf", res); + for (int i = 0; i < res.size(); ++i) + res[i] = fontFolder + res[i]; +*/ + + res.push_back(ReadPathForFile("wqy-microhei.ttf")); + res.push_back(ReadPathForFile("dejavusans.ttf")); + res.push_back(ReadPathForFile("mangal.ttf")); + + return res; +} + Platform & GetPlatform() { static IPhonePlatform platform; diff --git a/platform/platform.hpp b/platform/platform.hpp index 1c2fe3b4fc..eb27f61284 100644 --- a/platform/platform.hpp +++ b/platform/platform.hpp @@ -66,6 +66,8 @@ public: virtual bool IsMultiSampled() const = 0; virtual bool DoPeriodicalUpdate() const = 0; + + virtual vector GetFontNames() const = 0; }; extern "C" Platform & GetPlatform(); diff --git a/platform/qtplatform.cpp b/platform/qtplatform.cpp index 7e81e9b41b..1125c6489a 100644 --- a/platform/qtplatform.cpp +++ b/platform/qtplatform.cpp @@ -357,6 +357,28 @@ public: { return false; } + + vector GetFontNames() const + { + vector res; + +/*#if defined(OMIM_OS_WINDOWS) + string fontFolder = "C:\\Windows\\Fonts\\" +#elif defined(OMIM_OS_MAC) + string fontFolder = "/System/Library/Fonts/"; +#endif + + GetFilesInDir(fontFolder, "*.ttf", res); + + for (int i = 0; i < res.size(); ++i) + res[i] = fontFolder + res[i]; +*/ + res.push_back(ReadPathForFile("wqy-microhei.ttf")); + res.push_back(ReadPathForFile("dejavusans.ttf")); + res.push_back(ReadPathForFile("mangal.ttf")); + + return res; + } }; extern "C" Platform & GetPlatform() diff --git a/qt/widgets.cpp b/qt/widgets.cpp index 4794bfe086..93d651796b 100644 --- a/qt/widgets.cpp +++ b/qt/widgets.cpp @@ -45,10 +45,9 @@ namespace qt 50, 512, 256, 15, - 2000000)); + GetPlatform().ReadPathForFile("unicode_blocks.txt").c_str(), 2000000)); -// m_resourceManager->addFont(GetPlatform().ReadPathForFile("dejavusans.ttf").c_str()); - m_resourceManager->addFont(GetPlatform().ReadPathForFile("wqy-microhei.ttf").c_str()); + m_resourceManager->addFonts(GetPlatform().GetFontNames()); DrawerYG::params_t p; diff --git a/qt_tstfrm/tstwidgets.cpp b/qt_tstfrm/tstwidgets.cpp index a4d0a1ee83..ad56b5484e 100644 --- a/qt_tstfrm/tstwidgets.cpp +++ b/qt_tstfrm/tstwidgets.cpp @@ -50,10 +50,9 @@ void GLDrawWidget::initializeGL() 10 * sizeof(unsigned short), 30, 512, 256, 15, - 2000000)); + GetPlatform().ReadPathForFile("unicode_blocks.txt").c_str(), 2000000)); -// m_resourceManager->addFont(GetPlatform().ReadPathForFile("dejavusans.ttf").c_str()); - m_resourceManager->addFont(GetPlatform().ReadPathForFile("wqy-microhei.ttf").c_str()); + m_resourceManager->addFonts(GetPlatform().GetFontNames()); m_frameBuffer = make_shared_ptr(new yg::gl::FrameBuffer()); diff --git a/yg/glyph_cache.cpp b/yg/glyph_cache.cpp index e37a1252f5..86e59c82d1 100644 --- a/yg/glyph_cache.cpp +++ b/yg/glyph_cache.cpp @@ -35,20 +35,25 @@ namespace yg return l.m_isMask < r.m_isMask; } - GlyphCache::GlyphCache(size_t maxSize) : m_impl(new GlyphCacheImpl(maxSize)) + GlyphCache::GlyphCache(string const & blocksFileName, size_t maxSize) : m_impl(new GlyphCacheImpl(blocksFileName, maxSize)) { } - void GlyphCache::addFont(char const * fileName) + void GlyphCache::addFont(const char *fileName) { - m_impl->m_fonts.push_back(make_shared_ptr(new Font(fileName))); + m_impl->addFont(fileName); + } + + void GlyphCache::addFonts(vector const & fontNames) + { + m_impl->addFonts(fontNames); } int GlyphCache::getCharIDX(GlyphKey const & key) { - Font * font = m_impl->m_fonts.back().get(); + vector > & fonts = m_impl->getFonts(key.m_id); - FTC_FaceID faceID = reinterpret_cast(font); + FTC_FaceID faceID = reinterpret_cast(fonts.front().get()); int charIDX = FTC_CMapCache_Lookup( m_impl->m_charMapCache, @@ -79,9 +84,9 @@ namespace yg GlyphMetrics const GlyphCache::getGlyphMetrics(GlyphKey const & key) { - Font * font = m_impl->m_fonts.back().get(); + vector > & fonts = m_impl->getFonts(key.m_id); - FTC_FaceID faceID = reinterpret_cast(font); + FTC_FaceID faceID = reinterpret_cast(fonts.front().get()); FTC_ScalerRec fontScaler = { @@ -121,8 +126,8 @@ namespace yg shared_ptr const GlyphCache::getGlyph(GlyphKey const & key) { - Font * font = m_impl->m_fonts.back().get(); - FTC_FaceID faceID = reinterpret_cast(font); + vector > & fonts = m_impl->getFonts(key.m_id); + FTC_FaceID faceID = reinterpret_cast(fonts.front().get()); FTC_ScalerRec fontScaler = { faceID, diff --git a/yg/glyph_cache.hpp b/yg/glyph_cache.hpp index 120d38f2db..582016340f 100644 --- a/yg/glyph_cache.hpp +++ b/yg/glyph_cache.hpp @@ -1,6 +1,8 @@ #pragma once #include "../std/shared_ptr.hpp" +#include "../std/vector.hpp" +#include "../std/string.hpp" #include "color.hpp" namespace yg @@ -45,10 +47,11 @@ namespace yg public: - GlyphCache(size_t maxSize); + GlyphCache(string const & blocksFileName, size_t maxSize); void reset(); void addFont(char const * fileName); + void addFonts(vector const & fontNames); int getCharIDX(GlyphKey const & key); diff --git a/yg/glyph_cache_impl.cpp b/yg/glyph_cache_impl.cpp index f3fdb9e5c6..663626ca56 100644 --- a/yg/glyph_cache_impl.cpp +++ b/yg/glyph_cache_impl.cpp @@ -7,9 +7,21 @@ #include <../cache/ftccback.h> #include <../cache/ftccache.h> +#include "../std/fstream.hpp" +#include "../base/ptr_utils.hpp" + namespace yg { + UnicodeBlock::UnicodeBlock(string const & name, uint32_t start, uint32_t end) + : m_start(start), m_end(end), m_name(name) + {} + + bool UnicodeBlock::hasSymbol(uint16_t sym) const + { + return (m_start <= sym) && (m_end >= sym); + } + Font::Font(char const * name) : m_name(name), m_fontData(name, true) { } @@ -19,8 +31,152 @@ namespace yg return FT_New_Memory_Face(library, (unsigned char*)m_fontData.data(), m_fontData.size(), 0, face); } - GlyphCacheImpl::GlyphCacheImpl(size_t maxSize) + void GlyphCacheImpl::initBlocks(string const & fileName) { + ifstream fin(fileName.c_str()); + while (true) + { + string name; + uint16_t start; + uint16_t end; + fin >> name >> std::hex >> start >> std::hex >> end; + if (!fin) + break; + + m_unicodeBlocks.push_back(UnicodeBlock(name, start, end)); + } + + m_lastUsedBlock = m_unicodeBlocks.end(); + } + + bool sym_in_block(UnicodeBlock & b, uint16_t sym) + { + return (b.m_start <= sym); + } + + bool greater_coverage(pair > const & l, pair > const & r) + { + return l.first > r.first; + } + + void GlyphCacheImpl::addFonts(vector const & fontNames) + { + for (int i = 0; i < fontNames.size(); ++i) + addFont(fontNames[i].c_str()); + + for (unicode_blocks_t::const_iterator it = m_unicodeBlocks.begin(); it != m_unicodeBlocks.end(); ++it) + { + if (it->m_fonts.empty()) + LOG(LINFO, (it->m_name, " unicode block is empty")); + } + } + + void GlyphCacheImpl::addFont(char const * fileName) + { + m_fonts.push_back(make_shared_ptr(new Font(fileName))); + + /// obtaining all glyphs, supported by this font + FT_Face face; + m_fonts.back()->CreateFaceID(m_lib, &face); + + vector charcodes; + + FT_UInt gindex; + charcodes.push_back(FT_Get_First_Char(face, &gindex)); + while (gindex) + charcodes.push_back(FT_Get_Next_Char(face, charcodes.back(), &gindex)); + + sort(charcodes.begin(), charcodes.end()); + unique(charcodes.begin(), charcodes.end()); + + FT_Done_Face(face); + + /// modifying the m_unicodeBlocks + + int lastUBEnd = 0; + + unicode_blocks_t::iterator ubIt = m_unicodeBlocks.begin(); + vector::iterator ccIt = charcodes.begin(); + + while (true) + { + while (ubIt != m_unicodeBlocks.end()) + { + if ((*ccIt > lastUBEnd) && (*ccIt < ubIt->m_start)) + LOG(LINFO, ("Symbol with code ", (uint16_t)*ccIt, "lies between two unicode blocks!")); + if (ubIt->hasSymbol(*ccIt)) + break; + lastUBEnd = ubIt->m_end; + ++ubIt; + } + + if (ubIt == m_unicodeBlocks.end()) + break; + + /// here we have unicode block, which contains the specified symbol. + if (ubIt->m_fonts.empty() || (ubIt->m_fonts.back() != m_fonts.back())) + { + ubIt->m_fonts.push_back(m_fonts.back()); + ubIt->m_coverage.push_back(0); + } + + ++ubIt->m_coverage.back(); + ++ccIt; + } + + /// rearrange fonts in all unicode blocks according to it's coverage + for (ubIt = m_unicodeBlocks.begin(); ubIt != m_unicodeBlocks.end(); ++ubIt) + { + vector > > sortData; + + for (unsigned i = 0; i < ubIt->m_fonts.size(); ++i) + sortData.push_back(make_pair >(ubIt->m_coverage[i], ubIt->m_fonts[i])); + + sort(sortData.begin(), sortData.end(), &greater_coverage); + + for (unsigned i = 0; i < ubIt->m_fonts.size(); ++i) + { + ubIt->m_coverage[i] = sortData[i].first; + ubIt->m_fonts[i] = sortData[i].second; + } + } + + } + + vector > & GlyphCacheImpl::getFonts(uint16_t sym) + { + if ((m_lastUsedBlock != m_unicodeBlocks.end()) && (m_lastUsedBlock->hasSymbol(sym))) + return m_lastUsedBlock->m_fonts; + + unicode_blocks_t::iterator it = lower_bound(m_unicodeBlocks.begin(), + m_unicodeBlocks.end(), + sym, + &sym_in_block); + + if (it == m_unicodeBlocks.end()) + it = (--m_unicodeBlocks.rbegin()).base(); + else + if (it != m_unicodeBlocks.begin()) + it = --it; + + m_lastUsedBlock = it; + + if ((it != m_unicodeBlocks.end()) && (it->hasSymbol(sym))) + { + if (it->m_fonts.empty()) + it->m_fonts.push_back(m_fonts.front()); + + return it->m_fonts; + } + else + return m_fonts; + } + + + GlyphCacheImpl::GlyphCacheImpl(std::string const & blocksFileName, size_t maxSize) + { + initBlocks(blocksFileName); + FTCHECK(FT_Init_FreeType(&m_lib)); /// Initializing caches @@ -36,7 +192,6 @@ namespace yg FTCHECK(FTC_StrokedImageCache_New(m_manager, &m_strokedGlyphCache, m_stroker)); FTCHECK(FTC_CMapCache_New(m_manager, &m_charMapCache)); - } GlyphCacheImpl::~GlyphCacheImpl() diff --git a/yg/glyph_cache_impl.hpp b/yg/glyph_cache_impl.hpp index e9a63b2bc8..b5e5d19e44 100644 --- a/yg/glyph_cache_impl.hpp +++ b/yg/glyph_cache_impl.hpp @@ -22,6 +22,21 @@ namespace yg FT_Error CreateFaceID(FT_Library library, FT_Face * face); }; + /// Information about single unicode block. + struct UnicodeBlock + { + string m_name; + uint32_t m_start; + uint32_t m_end; + /// sorted indices in m_fonts, from the best to the worst + vector > m_fonts; + /// coverage of each font, in symbols + vector m_coverage; + + UnicodeBlock(string const & name, uint32_t start, uint32_t end); + bool hasSymbol(uint16_t sym) const; + }; + struct GlyphCacheImpl { FT_Library m_lib; @@ -35,12 +50,22 @@ namespace yg FTC_CMapCache m_charMapCache; + typedef vector unicode_blocks_t; + unicode_blocks_t m_unicodeBlocks; + unicode_blocks_t::iterator m_lastUsedBlock; + typedef vector > TFonts; TFonts m_fonts; static FT_Error RequestFace(FTC_FaceID faceID, FT_Library library, FT_Pointer requestData, FT_Face * face); - GlyphCacheImpl(size_t maxSize); + void initBlocks(string const & fileName); + + vector > & getFonts(uint16_t sym); + void addFont(char const * fileName); + void addFonts(vector const & fontNames); + + GlyphCacheImpl(string const & blocksFileName, size_t maxSize); ~GlyphCacheImpl(); }; } diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index 27e94c9396..bee45e3084 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -20,7 +20,7 @@ namespace yg size_t smallVBSize, size_t smallIBSize, size_t smallStoragesCount, size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, size_t texWidth, size_t texHeight, size_t texCount, - size_t maxGlyphCacheSize) : m_glyphCache(maxGlyphCacheSize) + char const * blocksFileName, size_t maxGlyphCacheSize) : m_glyphCache(blocksFileName, maxGlyphCacheSize) { for (size_t i = 0; i < storagesCount; ++i) m_storages.push_back(gl::Storage(vbSize, ibSize)); @@ -170,8 +170,8 @@ namespace yg return m_glyphCache.getGlyphMetrics(key); } - void ResourceManager::addFont(char const * fileName) + void ResourceManager::addFonts(vector const & fontNames) { - m_glyphCache.addFont(fileName); + m_glyphCache.addFonts(fontNames); } } diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index 098c6cb7c7..9fbef9b69e 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -49,7 +49,7 @@ namespace yg size_t smallVBSize, size_t smallIBSize, size_t smallStoragesCount, size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, size_t texWidth, size_t texHeight, size_t texCount, - size_t maxGlyphCacheSize); + char const * blocksFileName, size_t maxGlyphCacheSize); shared_ptr const & getTexture(string const & fileName); @@ -67,7 +67,8 @@ namespace yg shared_ptr const getGlyph(GlyphKey const & key); GlyphMetrics const getGlyphMetrics(GlyphKey const & key); - void addFont(char const * fileName); + + void addFonts(vector const & fontNames); }; Skin * loadSkin(shared_ptr const & resourceManager, diff --git a/yg/yg_tests/glyph_cache_test.cpp b/yg/yg_tests/glyph_cache_test.cpp index 5872a87ae9..9e091518a4 100644 --- a/yg/yg_tests/glyph_cache_test.cpp +++ b/yg/yg_tests/glyph_cache_test.cpp @@ -5,7 +5,7 @@ UNIT_TEST(GlyphCacheTest_Main) { - yg::GlyphCache cache(200000); + yg::GlyphCache cache("", 200000); cache.addFont(GetPlatform().ReadPathForFile("dejavusans.ttf").c_str()); shared_ptr g1 = cache.getGlyph(yg::GlyphKey('#', 40, true)); // g1->dump(GetPlatform().WritablePathForFile("#_mask.png").c_str()); diff --git a/yg/yg_tests/screengl_test.cpp b/yg/yg_tests/screengl_test.cpp index 774ae9c101..573984dc33 100644 --- a/yg/yg_tests/screengl_test.cpp +++ b/yg/yg_tests/screengl_test.cpp @@ -592,6 +592,15 @@ namespace } }; + struct TestDrawUnicodeSymbols + { + void DoDraw(shared_ptr p) + { + p->drawText(m2::PointD(40, 50), 0, 12, "Latin Symbol : A", 0); + p->drawText(m2::PointD(40, 80), 0, 12, "Cyrillic Symbol : Ы", 0); + } + }; + struct TestDrawTextRectWithFixedFont : TestDrawStringWithFixedFont { typedef TestDrawStringWithFixedFont base_t; @@ -901,6 +910,7 @@ namespace // UNIT_TEST_GL(TestDrawSingleSymbolAndSolidPath); // UNIT_TEST_GL(TestDrawString); // UNIT_TEST_GL(TestDrawStringWithFixedFont); + UNIT_TEST_GL(TestDrawUnicodeSymbols); UNIT_TEST_GL(TestDrawTextRectWithFixedFont); // UNIT_TEST_GL(TestDrawStringOnString); // UNIT_TEST_GL(TestDrawTextOnPath); diff --git a/yg/yg_tests/skin_loader_test.cpp b/yg/yg_tests/skin_loader_test.cpp index 166750750f..a5aace72df 100644 --- a/yg/yg_tests/skin_loader_test.cpp +++ b/yg/yg_tests/skin_loader_test.cpp @@ -8,6 +8,6 @@ UNIT_TEST(SkinLoaderTest_Main) { GL_TEST_START; - shared_ptr rm(new yg::ResourceManager(1000, 1000, 2, 1000, 1000, 2, 1000, 1000, 2, 128, 128, 15, 2000000)); + shared_ptr rm(new yg::ResourceManager(1000, 1000, 2, 1000, 1000, 2, 1000, 1000, 2, 128, 128, 15, "", 2000000)); /*yg::Skin * skin = */loadSkin(rm, "basic.skn", 2, 2); }; diff --git a/yg/yg_tests/skin_test.cpp b/yg/yg_tests/skin_test.cpp index f00b642c26..3c80dded6c 100644 --- a/yg/yg_tests/skin_test.cpp +++ b/yg/yg_tests/skin_test.cpp @@ -9,7 +9,7 @@ UNIT_TEST(SkinTest_Main) { GL_TEST_START; - shared_ptr rm(new yg::ResourceManager(100, 100, 1, 100, 100, 1, 100, 100, 1, 128, 128, 15, 2000000)); + shared_ptr rm(new yg::ResourceManager(100, 100, 1, 100, 100, 1, 100, 100, 1, 128, 128, 15, "", 2000000)); yg::Skin * skin = loadSkin(rm, "test.skn", 2, 2); double p0 [] = {1, 1};