diff --git a/data/basic.skn b/data/basic.skn index e373b53816..ab55e4b85d 100644 --- a/data/basic.skn +++ b/data/basic.skn @@ -1,403 +1,1093 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/data/basic_highres.skn b/data/basic_highres.skn index e5d78f3ff5..53eaf8be3c 100644 --- a/data/basic_highres.skn +++ b/data/basic_highres.skn @@ -1,403 +1,1093 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/data/symbols_24.png b/data/symbols_24.png index a7e1d4aab8..120b66e5a9 100644 Binary files a/data/symbols_24.png and b/data/symbols_24.png differ diff --git a/data/symbols_48.png b/data/symbols_48.png index e7ca9eb1de..60b8c86733 100644 Binary files a/data/symbols_48.png and b/data/symbols_48.png differ diff --git a/map/drawer_yg.cpp b/map/drawer_yg.cpp index ad9b60da38..c3da196298 100644 --- a/map/drawer_yg.cpp +++ b/map/drawer_yg.cpp @@ -244,15 +244,15 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, rule_ptr_t pRule, int depth) void DrawerYG::drawStats(double duration, int scale, double lat, double lng) { -/* ostringstream out; + ostringstream out; out << "SPF: " << duration; if (duration == 0.0) out << " FPS: inf"; else out << " FPS: " << 1.0 / duration; - m_pScreen->drawText(m2::PointD(10, 20), 0, 14, out.str().c_str(), yg::maxDepth); + m_pScreen->drawText(m2::PointD(10, 20), 0, 10, out.str().c_str(), yg::maxDepth, true); out.str(""); out << "(" << lat << ", " << lng << ") Scale: " << scale; - m_pScreen->drawText(m2::PointD(10, 40), 0, 14, out.str().c_str(), yg::maxDepth);*/ + m_pScreen->drawText(m2::PointD(10, 40), 0, 10, out.str().c_str(), yg::maxDepth, true); } diff --git a/skin_generator/main.cpp b/skin_generator/main.cpp index 448a6d487a..add5c9fc55 100644 --- a/skin_generator/main.cpp +++ b/skin_generator/main.cpp @@ -14,8 +14,7 @@ DEFINE_string(symbolsDir, "../../data/styles/symbols", "directory with svg symbo DEFINE_int32(symbolWidth, 24, "width of the rendered symbol"); DEFINE_int32(symbolHeight, 24, "height of the rendered symbol"); DEFINE_double(symbolScale, 1, "scale factor of the symbol"); -DEFINE_int32(smallGlyphSize, 12, "height of the small glyph"); -DEFINE_int32(bigGlyphSize, 16, "height of the big glyph"); +DEFINE_int32(fixedGlyphSize, 16, "height of the fixed font"); DEFINE_string(skinName, "../../data/basic", "prefix for the skin and skinImage file name"); int main(int argc, char *argv[]) @@ -27,17 +26,7 @@ int main(int argc, char *argv[]) std::vector glyphSizes; -// glyphSizes.push_back(6); - glyphSizes.push_back(8); - glyphSizes.push_back(10); - glyphSizes.push_back(12); - glyphSizes.push_back(14); - glyphSizes.push_back(16); - glyphSizes.push_back(20); - glyphSizes.push_back(24); - -// glyphSizes.push_back(FLAGS_smallGlyphSize); -// glyphSizes.push_back(FLAGS_bigGlyphSize); + glyphSizes.push_back(FLAGS_fixedGlyphSize); std::vector symbolSizes; symbolSizes.push_back(QSize(FLAGS_symbolWidth, FLAGS_symbolHeight)); @@ -46,7 +35,8 @@ int main(int argc, char *argv[]) symbolScales.push_back(FLAGS_symbolScale); gen.processSymbols(FLAGS_symbolsDir, FLAGS_skinName, symbolSizes, symbolScales); -// gen.processFont(FLAGS_fontFileName, FLAGS_skinName, FLAGS_symbolsFile, glyphSizes); + gen.processFont(FLAGS_fontFileName, FLAGS_skinName, glyphSizes, FLAGS_symbolScale); + gen.renderPages(); gen.writeToFile(FLAGS_skinName); diff --git a/skin_generator/skin_generator.cpp b/skin_generator/skin_generator.cpp index 89a5d349a3..a84ad71a51 100644 --- a/skin_generator/skin_generator.cpp +++ b/skin_generator/skin_generator.cpp @@ -57,23 +57,9 @@ namespace tools : m_baseLineOffset(0) {} - void SkinGenerator::processFont(string const & fileName, string const & skinName, string const & symFreqFile, vector const & fontSizes) + void SkinGenerator::processFont(string const & fileName, string const & skinName, vector const & fontSizes, int symbolScale) { - FILE * file = fopen(symFreqFile.c_str(), "rb"); - if (!file) - throw std::exception(); - std::vector ucs2Symbols; - - while (true) - { - unsigned short id; - int readBytes = fread(&id, 1, sizeof(unsigned short), file); - if (readBytes < 2) - break; - ucs2Symbols.push_back(id); - } - - fclose(file); + string symbols(" 0123456789abcdefjhigklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ;:'\"/?.,`~!@#$%^&*()-_+="); FT_Library lib; FT_Error error; @@ -84,7 +70,7 @@ namespace tools FT_Stroker stroker; FTCHECK(FT_Stroker_New(lib, &stroker)); - size_t outlineWidth = 3; + size_t outlineWidth = 2; FT_Stroker_Set(stroker, outlineWidth * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); FT_Glyph_Metrics normalGlyphMetrics; @@ -92,7 +78,7 @@ namespace tools for (size_t i = 0; i < fontSizes.size(); ++i) { - m_pages.push_back(SkinPageInfo()); +// m_pages.push_back(SkinPageInfo()); SkinPageInfo & page = m_pages.back(); page.m_fonts.push_back(FontInfo()); @@ -101,10 +87,9 @@ namespace tools fontInfo.m_size = fontSizes[i]; FTCHECK(FT_Set_Pixel_Sizes(face, 0, fontSizes[i])); -// FTCHECK(FT_Set_Pixel_Sizes(face, 0, 100)); - for (size_t j = 0; j < ucs2Symbols.size(); ++j) + for (size_t j = 0; j < symbols.size(); ++j) { - unsigned short symbol = ucs2Symbols[j]; + unsigned short symbol = (unsigned short)symbols[j]; int symbolIdx = FT_Get_Char_Index(face, symbol); @@ -112,7 +97,6 @@ namespace tools continue; FTCHECK(FT_Load_Glyph(face, symbolIdx, FT_LOAD_DEFAULT)); -// FTCHECK(FT_Load_Glyph(face, FT_Get_Char_Index(face, '@'), FT_LOAD_DEFAULT)); normalGlyphMetrics = face->glyph->metrics; @@ -158,10 +142,6 @@ namespace tools gil::copy_pixels(grayview, gil::view(strokedCharInfo.m_image)); -/* gil::lodepng_write_view( - "testchar_outline.png", - gil::view(strokedCharInfo.m_image)); -*/ FT_Done_Glyph(strokedGlyph); FTCHECK(FT_Render_Glyph(glyphSlot, FT_RENDER_MODE_NORMAL)); @@ -181,112 +161,23 @@ namespace tools gil::copy_pixels(grayview, gil::view(normalCharInfo.m_image)); -/* gil::lodepng_write_view( - "testchar.png", - gil::view(normalCharInfo.m_image) - ); - */ FT_Done_Glyph(normalGlyph); } fontInfo.m_chars[symbol] = make_pair(normalCharInfo, strokedCharInfo); } - std::stringstream out; +/* std::stringstream out; out << getBaseFileName(fileName) + "_" << (int)fontSizes[i]; page.m_fileName = out.str().c_str(); - /// repacking symbols as tight as possible - page.m_width = 32; - page.m_height = 32; - - while (true) - { - m_overflowDetected = false; - - page.m_packer = m2::Packer(page.m_width, page.m_height); - page.m_packer.addOverflowFn(bind(&SkinGenerator::markOverflow, this), 10); - - for (TChars::iterator it = fontInfo.m_chars.begin(); it != fontInfo.m_chars.end(); ++it) - { - it->second.first.m_handle = page.m_packer.pack(it->second.first.m_width + 4, it->second.first.m_height + 4); - if (m_overflowDetected) - break; - it->second.second.m_handle = page.m_packer.pack(it->second.second.m_width + 4, it->second.second.m_height + 4); - if (m_overflowDetected) - break; - } - - if (m_overflowDetected) - { - if (page.m_width == page.m_height) - page.m_width *= 2; - else - page.m_height *= 2; - continue; - } - else - break; - } - gil::bgra8_image_t skinImage(page.m_width, page.m_height); gil::fill_pixels(gil::view(skinImage), gil::rgba8_pixel_t(0, 0, 0, 0)); - for (TChars::const_iterator it = fontInfo.m_chars.begin(); it != fontInfo.m_chars.end(); ++it) - { - /// Packing normal char - m2::RectU dstRect(page.m_packer.find(it->second.first.m_handle).second); - - gil::rgba8_pixel_t color(0, 0, 0, 0); - - gil::bgra8_view_t dstView = gil::subimage_view(gil::view(skinImage), dstRect.minX(), dstRect.minY(), dstRect.SizeX(), dstRect.SizeY()); - gil::fill_pixels(dstView, color); - - dstView = gil::subimage_view(gil::view(skinImage), - dstRect.minX() + 2, - dstRect.minY() + 2, - dstRect.SizeX() - 4, - dstRect.SizeY() - 4); - - gil::gray8c_view_t srcView = gil::const_view(it->second.first.m_image); - - for (size_t x = 0; x < dstRect.SizeX() - 4; ++x) - for (size_t y = 0; y < dstRect.SizeY() - 4; ++y) - { - color[3] = srcView(x, y); - dstView(x, y) = color; - } - - /// packing stroked version - - dstRect = m2::RectU(page.m_packer.find(it->second.second.m_handle).second); - - color = gil::rgba8_pixel_t(255, 255, 255, 0); - - dstView = gil::subimage_view(gil::view(skinImage), dstRect.minX(), dstRect.minY(), dstRect.SizeX(), dstRect.SizeY()); - gil::fill_pixels(dstView, color); - - dstView = gil::subimage_view(gil::view(skinImage), - dstRect.minX() + 2, - dstRect.minY() + 2, - dstRect.SizeX() - 4, - dstRect.SizeY() - 4); - - srcView = gil::const_view(it->second.second.m_image); - - for (size_t x = 0; x < dstRect.SizeX() - 4; ++x) - for (size_t y = 0; y < dstRect.SizeY() - 4; ++y) - { - color[3] = srcView(x, y); - dstView(x, y) = color; - } - - } - gil::lodepng_write_view( skinName.substr(0, skinName.find_last_of("/") + 1) + page.m_fileName + ".png", - gil::const_view(skinImage)); + gil::const_view(skinImage));*/ } FT_Done_Face(face); @@ -328,6 +219,8 @@ namespace tools double symbolScale = symbolScales[i]; QSize symbolSize = symbolSizes[i]; + page.m_fileName = skinName.substr(0, skinName.find_last_of("/") + 1) + "symbols_" + QString("%1").arg(symbolSize.width()).toLocal8Bit().constData(); + for (int i = 0; i < fileNames.size(); ++i) { if (fileNames.at(i).endsWith(".svg")) @@ -357,8 +250,14 @@ namespace tools } } } - - /// Trying to repack symbols as tight as possible + } + } + void SkinGenerator::renderPages() + { + for (TSkinPages::iterator pageIt = m_pages.begin(); pageIt != m_pages.end(); ++pageIt) + { + SkinPageInfo & page = *pageIt; + /// Trying to repack all elements as tight as possible page.m_width = 64; page.m_height = 64; @@ -374,24 +273,52 @@ namespace tools { it->m_handle = page.m_packer.pack(it->m_size.width(), it->m_size.height()); if (m_overflowDetected) - { - /// enlarge packing area and try again - if (page.m_width == page.m_height) - page.m_width *= 2; - else - page.m_height *= 2; break; - } } if (m_overflowDetected) + { + /// enlarge packing area and try again + if (page.m_width == page.m_height) + page.m_width *= 2; + else + page.m_height *= 2; continue; + } + + for (TFonts::iterator fontIt = page.m_fonts.begin(); fontIt != page.m_fonts.end(); ++fontIt) + { + for (TChars::iterator charIt = fontIt->m_chars.begin(); charIt != fontIt->m_chars.end(); ++charIt) + { + charIt->second.first.m_handle = page.m_packer.pack( + charIt->second.first.m_width + 4, + charIt->second.first.m_height + 4); + if (m_overflowDetected) + break; + + charIt->second.second.m_handle = page.m_packer.pack( + charIt->second.second.m_width + 4, + charIt->second.second.m_height + 4); + + if (m_overflowDetected) + break; + } + if (m_overflowDetected) + break; + } + + if (m_overflowDetected) + { + if (page.m_width == page.m_height) + page.m_width *= 2; + else + page.m_height *= 2; + continue; + } break; } - /// rendering packed symbols - gil::bgra8_image_t gilImage(page.m_width, page.m_height); gil::fill_pixels(gil::view(gilImage), gil::rgba8_pixel_t(0, 0, 0, 0)); QImage img((uchar*)&gil::view(gilImage)(0, 0), page.m_width, page.m_height, QImage::Format_ARGB32); @@ -411,8 +338,60 @@ namespace tools m_svgRenderer.render(&painter, QRect(dstRect.minX() + 2, dstRect.minY() + 2, dstRect.SizeX() - 4, dstRect.SizeY() - 4)); } - page.m_fileName = skinName.substr(0, skinName.find_last_of("/") + 1) + "symbols_" + QString("%1").arg(symbolSize.width()).toLocal8Bit().constData(); + /// Rendering packed fonts + for (TFonts::const_iterator fontIt = page.m_fonts.begin(); fontIt != page.m_fonts.end(); ++fontIt) + { + for (TChars::const_iterator charIt = fontIt->m_chars.begin(); charIt != fontIt->m_chars.end(); ++charIt) + { + /// Packing normal char + m2::RectU dstRect(page.m_packer.find(charIt->second.first.m_handle).second); + gil::rgba8_pixel_t color(0, 0, 0, 0); + + gil::bgra8_view_t dstView = gil::subimage_view(gil::view(gilImage), dstRect.minX(), dstRect.minY(), dstRect.SizeX(), dstRect.SizeY()); + gil::fill_pixels(dstView, color); + + dstView = gil::subimage_view(gil::view(gilImage), + dstRect.minX() + 2, + dstRect.minY() + 2, + dstRect.SizeX() - 4, + dstRect.SizeY() - 4); + + gil::gray8c_view_t srcView = gil::const_view(charIt->second.first.m_image); + + for (size_t x = 0; x < dstRect.SizeX() - 4; ++x) + for (size_t y = 0; y < dstRect.SizeY() - 4; ++y) + { + color[3] = srcView(x, y); + dstView(x, y) = color; + } + + /// packing stroked version + + dstRect = m2::RectU(page.m_packer.find(charIt->second.second.m_handle).second); + + color = gil::rgba8_pixel_t(255, 255, 255, 0); + + dstView = gil::subimage_view(gil::view(gilImage), dstRect.minX(), dstRect.minY(), dstRect.SizeX(), dstRect.SizeY()); + gil::fill_pixels(dstView, color); + + dstView = gil::subimage_view(gil::view(gilImage), + dstRect.minX() + 2, + dstRect.minY() + 2, + dstRect.SizeX() - 4, + dstRect.SizeY() - 4); + + srcView = gil::const_view(charIt->second.second.m_image); + + for (size_t x = 0; x < dstRect.SizeX() - 4; ++x) + for (size_t y = 0; y < dstRect.SizeY() - 4; ++y) + { + color[3] = srcView(x, y); + dstView(x, y) = color; + } + + } + } img.save((page.m_fileName + ".png").c_str()); } } diff --git a/skin_generator/skin_generator.hpp b/skin_generator/skin_generator.hpp index a82c22a860..54e953bb2d 100644 --- a/skin_generator/skin_generator.hpp +++ b/skin_generator/skin_generator.hpp @@ -84,7 +84,8 @@ namespace tools int m_baseLineOffset; QString m_fontFileName; - vector m_pages; + typedef vector TSkinPages; + TSkinPages m_pages; bool m_overflowDetected; void markOverflow(); @@ -92,8 +93,9 @@ namespace tools public: SkinGenerator(); - void processFont(string const & fileName, string const & skinName, string const & symFreqFile, vector const & fontSizes); + void processFont(string const & fileName, string const & skinName, vector const & fontSizes, int symbolScale); void processSymbols(string const & symbolsDir, string const & skinName, std::vector const & symbolSizes, std::vector const & symbolScales); + void renderPages(); bool writeToFile(string const & skinName); }; } // namespace tools diff --git a/yg/geometry_batcher.cpp b/yg/geometry_batcher.cpp index 21e1b5f0d6..38b3c86f9f 100644 --- a/yg/geometry_batcher.cpp +++ b/yg/geometry_batcher.cpp @@ -544,12 +544,12 @@ namespace yg } template - void GeometryBatcher::ForEachGlyph(uint8_t fontSize, wstring const & text, bool isMask, ToDo toDo) + void GeometryBatcher::ForEachGlyph(uint8_t fontSize, wstring const & text, bool isMask, bool isFixedFont, ToDo toDo) { m2::PointD currPt(0, 0); for (size_t i = 0; i < text.size(); ++i) { - uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, isMask)); + uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, isMask), isFixedFont); CharStyle const * p = static_cast(m_skin->fromID(glyphID)); if (p) { @@ -559,12 +559,12 @@ namespace yg } } - void GeometryBatcher::drawText(m2::PointD const & pt, float angle, uint8_t fontSize, string const & utf8Text, double depth) + void GeometryBatcher::drawText(m2::PointD const & pt, float angle, uint8_t fontSize, string const & utf8Text, double depth, bool isFixedFont) { wstring text = FromUtf8(utf8Text); - ForEachGlyph(fontSize, text, true, bind(&GeometryBatcher::drawGlyph, this, cref(pt), _1, angle, 0, _2, depth)); - ForEachGlyph(fontSize, text, false, bind(&GeometryBatcher::drawGlyph, this, cref(pt), _1, angle, 0, _2, depth)); + ForEachGlyph(fontSize, text, true, isFixedFont, bind(&GeometryBatcher::drawGlyph, this, cref(pt), _1, angle, 0, _2, depth)); + ForEachGlyph(fontSize, text, false, isFixedFont, bind(&GeometryBatcher::drawGlyph, this, cref(pt), _1, angle, 0, _2, depth)); } m2::RectD const GeometryBatcher::textRect(string const & utf8Text, uint8_t fontSize) @@ -646,15 +646,15 @@ namespace yg } void GeometryBatcher::drawPathText(m2::PointD const * path, size_t s, uint8_t fontSize, string const & utf8Text, - double pathLength, TextPos pos, bool isMasked, double depth) + double pathLength, TextPos pos, bool isMasked, double depth, bool isFixedFont) { if (isMasked) - drawPathTextImpl(path, s, fontSize, utf8Text, pathLength, pos, true, depth); - drawPathTextImpl(path, s, fontSize, utf8Text, pathLength, pos, false, depth); + drawPathTextImpl(path, s, fontSize, utf8Text, pathLength, pos, true, depth, isFixedFont); + drawPathTextImpl(path, s, fontSize, utf8Text, pathLength, pos, false, depth, isFixedFont); } void GeometryBatcher::drawPathTextImpl(m2::PointD const * path, size_t s, uint8_t fontSize, string const & utf8Text, - double pathLength, TextPos pos, bool fromMask, double depth) + double pathLength, TextPos pos, bool fromMask, double depth, bool isFixedFont) { pts_array arrPath(path, s); @@ -678,7 +678,7 @@ namespace yg double strLength = 0.0; for (size_t i = 0; i < text.size(); ++i) { - uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, fromMask)); + uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, fromMask), isFixedFont); CharStyle const * p = static_cast(m_skin->fromID(glyphID)); strLength += p->m_xAdvance; } @@ -696,7 +696,7 @@ namespace yg if (!CalcPointAndAngle(arrPath, offset, ind, ptOrg, angle)) break; - uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, fromMask)); + uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, fromMask), isFixedFont); CharStyle const * p = static_cast(m_skin->fromID(glyphID)); drawGlyph(ptOrg, m2::PointD(0.0, 0.0), angle, blOffset, p, depth); diff --git a/yg/geometry_batcher.hpp b/yg/geometry_batcher.hpp index cb1bdd308e..5364ee9e97 100644 --- a/yg/geometry_batcher.hpp +++ b/yg/geometry_batcher.hpp @@ -86,7 +86,8 @@ namespace yg double pathLength, TextPos pos, bool fromMask, - double depth); + double depth, + bool isFixedFont); public: @@ -120,7 +121,7 @@ namespace yg private: template - void ForEachGlyph(uint8_t fontSize, wstring const & text, bool isMask, ToDo toDo); + void ForEachGlyph(uint8_t fontSize, wstring const & text, bool isMask, bool isFixedFont, ToDo toDo); public: /// Drawing text from point rotated by the angle. @@ -128,7 +129,8 @@ namespace yg float angle, uint8_t fontSize, string const & utf8Text, - double depth); + double depth, + bool fixedFont = false); m2::RectD const textRect(string const & utf8Text, uint8_t fontSize); @@ -141,7 +143,8 @@ namespace yg double pathLength, TextPos pos, bool isMasked, - double depth); + double depth, + bool isFixedFont = false); /// This functions hide the base_t functions with the same name and signature /// to flush(-1) upon calling them diff --git a/yg/glyph_cache.cpp b/yg/glyph_cache.cpp index 8da91028cd..a73b6c4a7f 100644 --- a/yg/glyph_cache.cpp +++ b/yg/glyph_cache.cpp @@ -19,6 +19,13 @@ namespace yg : m_id(id), m_fontSize(fontSize), m_isMask(isMask) {} + uint32_t GlyphKey::toUInt32() const + { + return static_cast(m_id) << 16 + | static_cast(m_fontSize) << 8 + | static_cast(m_isMask); + } + bool operator<(GlyphKey const & l, GlyphKey const & r) { if (l.m_id != r.m_id) diff --git a/yg/glyph_cache.hpp b/yg/glyph_cache.hpp index 2f92581372..120d38f2db 100644 --- a/yg/glyph_cache.hpp +++ b/yg/glyph_cache.hpp @@ -29,6 +29,7 @@ namespace yg int m_id; int m_fontSize; bool m_isMask; + uint32_t toUInt32() const; GlyphKey(int id, int fontSize, bool isMask); }; diff --git a/yg/skin.cpp b/yg/skin.cpp index 6bafcdff27..e0488e1312 100644 --- a/yg/skin.cpp +++ b/yg/skin.cpp @@ -115,17 +115,20 @@ namespace yg return packID(m_currentDynamicPage, m_pages[m_currentDynamicPage]->mapPenInfo(penInfo)); } - uint32_t Skin::mapGlyph(GlyphKey const & gk) + uint32_t Skin::mapGlyph(GlyphKey const & gk, bool isFixedFont) { uint32_t res = invalidPageHandle(); for (uint8_t i = 0; i < m_pages.size(); ++i) { - res = m_pages[i]->findGlyph(gk); + res = m_pages[i]->findGlyph(gk, isFixedFont); if (res != invalidPageHandle()) return packID(i, res); } + if (isFixedFont) + return res; + if (!m_pages[m_currentTextPage]->hasRoom(gk)) changeCurrentTextPage(); diff --git a/yg/skin.hpp b/yg/skin.hpp index d6f0f7ee74..3c7e32e328 100644 --- a/yg/skin.hpp +++ b/yg/skin.hpp @@ -117,7 +117,7 @@ namespace yg /// find glyph identified by GlyphKey on texture /// if found - return id /// if not - pack and return id - uint32_t mapGlyph(GlyphKey const & gk); + uint32_t mapGlyph(GlyphKey const & gk, bool isFixedFont); void addClearPageFn(clearPageFn fn, int priority); void addOverflowFn(overflowFn, int priority); diff --git a/yg/skin_loader.cpp b/yg/skin_loader.cpp index d5b3bd5381..9f3a947652 100644 --- a/yg/skin_loader.cpp +++ b/yg/skin_loader.cpp @@ -89,6 +89,16 @@ namespace yg m_stylesList.erase(prevIt); prevIt = it; } + + for (TFonts::const_iterator it = m_fonts.begin(); it != m_fonts.end(); ++it) + { + FontInfo fontInfo; + fontInfo.m_fontSize = it->first; + fontInfo.m_chars = it->second; + m_pages.back()->m_fonts.push_back(fontInfo); + } + + m_fonts.clear(); } void SkinLoader::popSkin() diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index d66ed9995f..6b7270e6ec 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -34,7 +34,7 @@ namespace yg : m_penInfo(penInfo), m_rect(rect){} - ResourceStyle * FontInfo::fromID(uint32_t id, bool primaryGlyph) const + ResourceStyle * FontInfo::fromID(uint32_t id, bool isMask) const { TChars::const_iterator it = m_chars.find(id); if (it == m_chars.end()) @@ -51,16 +51,16 @@ namespace yg m_invalidChar = pair(it->second.first.get(), it->second.second.get()); } - if (primaryGlyph) - return m_invalidChar.first; - else + if (isMask) return m_invalidChar.second; + else + return m_invalidChar.first; } else - if (primaryGlyph) - return it->second.first.get(); - else + if (isMask) return it->second.second.get(); + else + return it->second.first.get(); } SkinPage::SkinPage(shared_ptr const & resourceManager, @@ -161,8 +161,40 @@ namespace yg return it->second; } - uint32_t SkinPage::findGlyph(GlyphKey const & g) const + uint32_t SkinPage::findGlyph(GlyphKey const & g, bool isFixedFont) const { + if (isFixedFont) + { + TStyles::const_iterator styleIt = m_styles.find(g.toUInt32()); + if (styleIt != m_styles.end()) + return g.toUInt32(); + TFonts::const_iterator fontIt = m_fonts.begin(); + int lastFontSize = 0; + if (!m_fonts.empty()) + lastFontSize = m_fonts[0].m_fontSize; + + for (TFonts::const_iterator it = m_fonts.begin(); it != m_fonts.end(); ++it) + if ((lastFontSize < g.m_fontSize) && (g.m_fontSize >= it->m_fontSize)) + fontIt = it; + else + lastFontSize = it->m_fontSize; + + if (fontIt != m_fonts.end()) + { + FontInfo::TChars::const_iterator charIt = fontIt->m_chars.find(g.m_id); + if (charIt != fontIt->m_chars.end()) + { + if (g.m_isMask) + const_cast(m_styles)[g.toUInt32()] = charIt->second.second; + else + const_cast(m_styles)[g.toUInt32()]= charIt->second.first; + return g.toUInt32(); + } + } + + return m_packer.invalidHandle(); + } + TGlyphMap::const_iterator it = m_glyphMap.find(g); if (it == m_glyphMap.end()) return m_packer.invalidHandle(); @@ -172,7 +204,7 @@ namespace yg uint32_t SkinPage::mapGlyph(yg::GlyphKey const & g) { - uint32_t foundHandle = findGlyph(g); + uint32_t foundHandle = findGlyph(g, false); if (foundHandle != m_packer.invalidHandle()) return foundHandle; diff --git a/yg/skin_page.hpp b/yg/skin_page.hpp index 7df7371a55..760a4d0886 100644 --- a/yg/skin_page.hpp +++ b/yg/skin_page.hpp @@ -56,7 +56,7 @@ namespace yg mutable pair m_invalidChar; FontInfo() : m_invalidChar(0, 0){} - ResourceStyle * fromID(uint32_t id, bool primaryGlyph = true) const; + ResourceStyle * fromID(uint32_t id, bool isMask = false) const; }; class SkinPage @@ -96,6 +96,9 @@ namespace yg void uploadColors(); void uploadGlyphs(); + typedef vector TFonts; + TFonts m_fonts; + bool m_isDynamic; uint32_t m_pageID; @@ -137,7 +140,7 @@ namespace yg uint32_t mapPenInfo(PenInfo const & penInfo); bool hasRoom(PenInfo const & penInfo) const; - uint32_t findGlyph(GlyphKey const & g) const; + uint32_t findGlyph(GlyphKey const & g, bool isFixedFont) const; uint32_t mapGlyph(GlyphKey const & g); bool hasRoom(GlyphKey const & g) const; diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index 7b2162776e..2274f1a3f7 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -28,7 +28,7 @@ namespace yg void TextRenderer::TextObj::Draw(GeometryBatcher * pBatcher) const { - pBatcher->drawText(m_pt, 0.0, m_size, m_utf8Text, yg::maxDepth); + pBatcher->drawText(m_pt, 0.0, m_size, m_utf8Text, yg::maxDepth, m_isFixedFont); } m2::RectD const TextRenderer::TextObj::GetLimitRect(GeometryBatcher * pBatcher) const @@ -40,24 +40,30 @@ namespace yg float angle, uint8_t fontSize, string const & utf8Text, - double depth) + double depth, + bool isFixedFont) { - TextObj obj(pt, utf8Text, fontSize, depth); - m2::RectD r = obj.GetLimitRect(this); - /* - m2::PointD pts[5] = + if (isFixedFont) + base_t::drawText(pt, angle, fontSize, utf8Text, depth, isFixedFont); + else { - m2::PointD(r.minX(), r.minY()), - m2::PointD(r.minX(), r.maxY()), - m2::PointD(r.maxX(), r.maxY()), - m2::PointD(r.maxX(), r.minY()), - m2::PointD(r.minX(), r.minY()) - }; + TextObj obj(pt, utf8Text, fontSize, depth, isFixedFont); + m2::RectD r = obj.GetLimitRect(this); + /* + m2::PointD pts[5] = + { + m2::PointD(r.minX(), r.minY()), + m2::PointD(r.minX(), r.maxY()), + m2::PointD(r.maxX(), r.maxY()), + m2::PointD(r.maxX(), r.minY()), + m2::PointD(r.minX(), r.minY()) + }; - drawPath(pts, 5, skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 255), 2, 0, 0, 0)), depth); + drawPath(pts, 5, skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 255), 2, 0, 0, 0)), depth); */ - m_tree.ReplaceIf(obj, r, TextObj::better_depth()); + m_tree.ReplaceIf(obj, r, TextObj::better_depth()); + } } void TextRenderer::endFrame() diff --git a/yg/text_renderer.hpp b/yg/text_renderer.hpp index 721aa4ecd9..cd26436058 100644 --- a/yg/text_renderer.hpp +++ b/yg/text_renderer.hpp @@ -21,10 +21,11 @@ namespace yg uint8_t m_size; string m_utf8Text; double m_depth; + bool m_isFixedFont; public: - TextObj(m2::PointD const & pt, string const & txt, uint8_t sz, double d) - : m_pt(pt), m_size(sz), m_utf8Text(txt), m_depth(d) + TextObj(m2::PointD const & pt, string const & txt, uint8_t sz, double d, bool isFixedFont) + : m_pt(pt), m_size(sz), m_utf8Text(txt), m_depth(d), m_isFixedFont(isFixedFont) { } @@ -59,7 +60,8 @@ namespace yg float angle, uint8_t fontSize, string const & utf8Text, - double depth); + double depth, + bool isFixedFont = false); void endFrame(); }; diff --git a/yg/yg_tests/screengl_test.cpp b/yg/yg_tests/screengl_test.cpp index 5287bb5414..314b6a5d1e 100644 --- a/yg/yg_tests/screengl_test.cpp +++ b/yg/yg_tests/screengl_test.cpp @@ -484,6 +484,14 @@ namespace } }; + struct TestDrawStringWithFixedFont + { + void DoDraw(shared_ptr p) + { + p->drawText(m2::PointD(40, 50), 0/*, math::pi / 18*/, 12, "Simplicity is the ultimate sophistication", 0, true); + } + }; + double calc_length(vector const & v) { double ret = 0.0; @@ -751,27 +759,28 @@ namespace } }; - UNIT_TEST_GL(TestDrawPolyOverflow); - UNIT_TEST_GL(TestDrawText); - UNIT_TEST_GL(TestDrawSingleSymbol); - UNIT_TEST_GL(TestDrawEmptySymbol); - UNIT_TEST_GL(TestDrawSingleSymbolAndSolidPath); - UNIT_TEST_GL(TestDrawString); - UNIT_TEST_GL(TestDrawStringOnString); - UNIT_TEST_GL(TestDrawTextOnPath); - UNIT_TEST_GL(TestDrawTextOnPathWithOffset); - UNIT_TEST_GL(TestDrawTextOverflow); - UNIT_TEST_GL(TestDrawTextFiltering); - UNIT_TEST_GL(TestDrawRandomTextFiltering); - UNIT_TEST_GL(TestDrawSGIConvex); - UNIT_TEST_GL(TestDrawPoly); - UNIT_TEST_GL(TestDrawSolidRect); - UNIT_TEST_GL(TestDrawPathWithSkinPageMiss); - UNIT_TEST_GL(TestDrawPathWithOffset); - UNIT_TEST_GL(TestDrawPathJoin); - UNIT_TEST_GL(TestDrawPathSolid); - UNIT_TEST_GL(TestDrawPathSolidWithZ); - UNIT_TEST_GL(TestDrawPathSolidWithClipRect); - UNIT_TEST_GL(TestDrawUtilsRect); - UNIT_TEST_GL(TestDrawUtilsRectFilledTexture); +// UNIT_TEST_GL(TestDrawPolyOverflow); +// UNIT_TEST_GL(TestDrawText); +// UNIT_TEST_GL(TestDrawSingleSymbol); +// UNIT_TEST_GL(TestDrawEmptySymbol); +// UNIT_TEST_GL(TestDrawSingleSymbolAndSolidPath); +// UNIT_TEST_GL(TestDrawString); + UNIT_TEST_GL(TestDrawStringWithFixedFont); +// UNIT_TEST_GL(TestDrawStringOnString); +// UNIT_TEST_GL(TestDrawTextOnPath); +// UNIT_TEST_GL(TestDrawTextOnPathWithOffset); +// UNIT_TEST_GL(TestDrawTextOverflow); +// UNIT_TEST_GL(TestDrawTextFiltering); +// UNIT_TEST_GL(TestDrawRandomTextFiltering); +// UNIT_TEST_GL(TestDrawSGIConvex); +// UNIT_TEST_GL(TestDrawPoly); +// UNIT_TEST_GL(TestDrawSolidRect); +// UNIT_TEST_GL(TestDrawPathWithSkinPageMiss); +// UNIT_TEST_GL(TestDrawPathWithOffset); +// UNIT_TEST_GL(TestDrawPathJoin); +// UNIT_TEST_GL(TestDrawPathSolid); +// UNIT_TEST_GL(TestDrawPathSolidWithZ); +// UNIT_TEST_GL(TestDrawPathSolidWithClipRect); +// UNIT_TEST_GL(TestDrawUtilsRect); +// UNIT_TEST_GL(TestDrawUtilsRectFilledTexture); }