From a55d0cada95ed622d27d0fb036362d0beac234a2 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Fri, 6 Apr 2018 19:50:27 +0300 Subject: Added new booking search visualization --- skin_generator/generator.cpp | 423 +++++++++++++++++++++---------------------- skin_generator/generator.hpp | 102 +++++------ skin_generator/main.cpp | 17 +- 3 files changed, 262 insertions(+), 280 deletions(-) (limited to 'skin_generator') diff --git a/skin_generator/generator.cpp b/skin_generator/generator.cpp index 2efc707a6d..f62441ed87 100644 --- a/skin_generator/generator.cpp +++ b/skin_generator/generator.cpp @@ -3,11 +3,11 @@ #include "base/logging.hpp" #include "base/math.hpp" -#include "std/algorithm.hpp" -#include "std/iterator.hpp" -#include "std/fstream.hpp" -#include "std/iostream.hpp" -#include "std/bind.hpp" +#include +#include +#include +#include +#include #include #include @@ -27,276 +27,259 @@ namespace gil = boost::gil; namespace tools { - SkinGenerator::SkinGenerator(bool needColorCorrection) - : m_needColorCorrection(needColorCorrection) - {} - - struct GreaterHeight - { - bool operator() (SkinGenerator::SymbolInfo const & left, - SkinGenerator::SymbolInfo const & right) const - { - return (left.m_size.height() > right.m_size.height()); - } - }; - - struct MaxDimensions +namespace +{ +struct GreaterHeight +{ + bool operator() (SkinGenerator::SymbolInfo const & left, + SkinGenerator::SymbolInfo const & right) const { - uint32_t & m_width; - uint32_t & m_height; + return (left.m_size.height() > right.m_size.height()); + } +}; - MaxDimensions(uint32_t & width, uint32_t & height) : m_width(width), m_height(height) - { - m_width = 0; - m_height = 0; - } +struct MaxDimensions +{ + uint32_t & m_width; + uint32_t & m_height; - void operator()(SkinGenerator::SymbolInfo const & info) - { - m_width = max(max(m_width, m_height), static_cast(info.m_size.width())); - m_height = max(max(m_width, m_height), static_cast(info.m_size.height())); - } - }; + MaxDimensions(uint32_t & width, uint32_t & height) + : m_width(width), m_height(height) + { + m_width = 0; + m_height = 0; + } - int NextPowerOf2(int n) + void operator()(SkinGenerator::SymbolInfo const & info) { - n = n - 1; - n |= (n >> 1); - n |= (n >> 2); - n |= (n >> 4); - n |= (n >> 8); - n |= (n >> 16); - - return n + 1; + m_width = std::max(std::max(m_width, m_height), static_cast(info.m_size.width())); + m_height = std::max(std::max(m_width, m_height), static_cast(info.m_size.height())); } +}; + +uint32_t NextPowerOf2(uint32_t n) +{ + n = n - 1; + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + + return n + 1; +} - void DoPatchSize(QString const & name, string const & skinName, QSize & size) +void correctColors(gil::bgra8_image_t & image) +{ + gil::bgra8_view_t view = gil::view(image); + for (gil::bgra8_view_t::y_coord_t y = 0; y < view.height(); ++y) { - if (name.startsWith("placemark-") || name.startsWith("current-position") || name.startsWith("api_pin")) + for (gil::bgra8_view_t::x_coord_t x = 0; x < view.width(); ++x) { - if (skinName.rfind("-mdpi") != string::npos) - size = QSize(24, 24); - else if (skinName.rfind("-hdpi") != string::npos) - size = QSize(36, 36); - else if (skinName.rfind("-xhdpi") != string::npos) - size = QSize(48, 48); - else if (skinName.rfind("-xxhdpi") != string::npos) - size = QSize(72, 72); + gil::bgra8_pixel_t pixel = view(x, y); + auto color = static_cast( + my::clamp(0.07 * pixel[0] + 0.5 * pixel[1] + 0.22 * pixel[2], 0.0, 255.0)); + + view(x, y)[0] = color; + view(x, y)[1] = color; + view(x, y)[2] = color; } } +} +} + +SkinGenerator::SkinGenerator(bool needColorCorrection) + : m_needColorCorrection(needColorCorrection) +{} - void SkinGenerator::processSymbols(string const & svgDataDir, - string const & skinName, - vector const & symbolSizes, - vector const & suffixes) +void SkinGenerator::ProcessSymbols(std::string const & svgDataDir, + std::string const & skinName, + std::vector const & symbolSizes, + std::vector const & suffixes) +{ + for (size_t j = 0; j < symbolSizes.size(); ++j) { - for (size_t j = 0; j < symbolSizes.size(); ++j) - { - QDir dir(QString(svgDataDir.c_str())); - QStringList fileNames = dir.entryList(QDir::Files); + QDir dir(QString(svgDataDir.c_str())); + QStringList fileNames = dir.entryList(QDir::Files); - QDir pngDir = dir.absolutePath() + "/" + "png"; - fileNames += pngDir.entryList(QDir::Files); + QDir pngDir = dir.absolutePath() + "/png"; + fileNames += pngDir.entryList(QDir::Files); - /// separate page for symbols - m_pages.push_back(SkinPageInfo()); - SkinPageInfo & page = m_pages.back(); + // Separate page for symbols. + m_pages.emplace_back(SkinPageInfo()); + SkinPageInfo & page = m_pages.back(); - page.m_dir = skinName.substr(0, skinName.find_last_of("/") + 1); - page.m_suffix = suffixes[j]; - page.m_fileName = page.m_dir + "symbols" + page.m_suffix; + page.m_dir = skinName.substr(0, skinName.find_last_of("/") + 1); + page.m_suffix = suffixes[j]; + page.m_fileName = page.m_dir + "symbols" + page.m_suffix; - for (int i = 0; i < fileNames.size(); ++i) + for (int i = 0; i < fileNames.size(); ++i) + { + QString const & fileName = fileNames.at(i); + QString symbolID = fileName.left(fileName.lastIndexOf(".")); + if (fileName.endsWith(".svg")) { - QString const & fileName = fileNames.at(i); - QString symbolID = fileName.left(fileName.lastIndexOf(".")); - if (fileName.endsWith(".svg")) + QString fullFileName = QString(dir.absolutePath()) + "/" + fileName; + if (m_svgRenderer.load(fullFileName)) { - QString fullFileName = QString(dir.absolutePath()) + "/" + fileName; - if (m_svgRenderer.load(fullFileName)) - { - QSize defaultSize = m_svgRenderer.defaultSize(); + QSize defaultSize = m_svgRenderer.defaultSize(); - QSize symbolSize = symbolSizes[j]; - DoPatchSize(fileName, skinName, symbolSize); + QSize symbolSize = symbolSizes[j]; + QSize size = defaultSize * (symbolSize.width() / 24.0); - QSize size = defaultSize * (symbolSize.width() / 24.0); - - /// fitting symbol into symbolSize, saving aspect ratio - - if (size.width() > symbolSize.width()) - { - size.setHeight((float)size.height() * symbolSize.width() / (float)size.width()); - size.setWidth(symbolSize.width()); - } - - if (size.height() > symbolSize.height()) - { - size.setWidth((float)size.width() * symbolSize.height() / (float)size.height()); - size.setHeight(symbolSize.height()); - } + // Fitting symbol into symbolSize, saving aspect ratio. + if (size.width() > symbolSize.width()) + { + auto const h = static_cast(size.height()) * symbolSize.width() / size.width(); + size.setHeight(static_cast(h)); + size.setWidth(symbolSize.width()); + } - page.m_symbols.push_back(SymbolInfo(size + QSize(4, 4), fullFileName, symbolID)); + if (size.height() > symbolSize.height()) + { + auto const w = static_cast(size.width()) * symbolSize.height() / size.height(); + size.setWidth(static_cast(w)); + size.setHeight(symbolSize.height()); } - } - else if (fileName.toLower().endsWith(".png")) - { - QString fullFileName = QString(pngDir.absolutePath()) + "/" + fileName; - QPixmap pix(fullFileName); - QSize s = pix.size(); - page.m_symbols.push_back(SymbolInfo(s + QSize(4, 4), fullFileName, symbolID)); + + page.m_symbols.emplace_back(size + QSize(4, 4), fullFileName, symbolID); } } - } - } - - namespace - { - void correctColors(gil::bgra8_image_t & image) - { - gil::bgra8_view_t view = gil::view(image); - for (gil::bgra8_view_t::y_coord_t y = 0; y < view.height(); ++y) + else if (fileName.toLower().endsWith(".png")) { - for (gil::bgra8_view_t::x_coord_t x = 0; x < view.width(); ++x) - { - gil::bgra8_pixel_t pixel = view(x, y); - unsigned char color = - my::clamp(0.07 * pixel[0] + 0.5 * pixel[1] + 0.22 * pixel[2], 0.0, 255.0); - - view(x, y)[0] = color; - view(x, y)[1] = color; - view(x, y)[2] = color; - } + QString fullFileName = QString(pngDir.absolutePath()) + "/" + fileName; + QPixmap pix(fullFileName); + QSize s = pix.size(); + page.m_symbols.emplace_back(s + QSize(4, 4), fullFileName, symbolID); } } } +} - bool SkinGenerator::renderPages(uint32_t maxSize) +bool SkinGenerator::RenderPages(uint32_t maxSize) +{ + for (auto & page : m_pages) { - for (TSkinPages::iterator pageIt = m_pages.begin(); pageIt != m_pages.end(); ++pageIt) - { - SkinPageInfo & page = *pageIt; - sort(page.m_symbols.begin(), page.m_symbols.end(), GreaterHeight()); + std::sort(page.m_symbols.begin(), page.m_symbols.end(), GreaterHeight()); - MaxDimensions dim(page.m_width, page.m_height); - for_each(page.m_symbols.begin(), page.m_symbols.end(), dim); + MaxDimensions dim(page.m_width, page.m_height); + for_each(page.m_symbols.begin(), page.m_symbols.end(), dim); - page.m_width = NextPowerOf2(page.m_width); - page.m_height = NextPowerOf2(page.m_height); + page.m_width = NextPowerOf2(page.m_width); + page.m_height = NextPowerOf2(page.m_height); - /// packing until we find a suitable rect - while (true) - { - page.m_packer = m2::Packer(page.m_width, page.m_height); - page.m_packer.addOverflowFn(bind(&SkinGenerator::markOverflow, this), 10); + // Packing until we find a suitable rect. + while (true) + { + page.m_packer = m2::Packer(page.m_width, page.m_height); + page.m_packer.addOverflowFn(std::bind(&SkinGenerator::MarkOverflow, this), 10); - m_overflowDetected = false; - - for (TSymbols::iterator it = page.m_symbols.begin(); it != page.m_symbols.end(); ++it) - { - it->m_handle = page.m_packer.pack(it->m_size.width(), it->m_size.height()); - if (m_overflowDetected) - break; - } + m_overflowDetected = false; + for (auto & s : page.m_symbols) + { + s.m_handle = page.m_packer.pack(static_cast(s.m_size.width()), + static_cast(s.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 (page.m_width > maxSize) - { - page.m_width = maxSize; - page.m_height *= 2; - if (page.m_height > maxSize) - return false; - } + 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; + if (page.m_width > maxSize) + { + page.m_width = maxSize; + page.m_height *= 2; + if (page.m_height > maxSize) + return false; } - - break; + continue; } + break; + } + LOG(LINFO, ("Texture size =", page.m_width, "x", page.m_height)); - 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); - QPainter painter(&img); - painter.setClipping(true); + 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); + QPainter painter(&img); + painter.setClipping(true); - for (TSymbols::const_iterator it = page.m_symbols.begin(); it != page.m_symbols.end(); ++it) - { - m2::RectU dstRect = page.m_packer.find(it->m_handle).second; - QRect dstRectQt(dstRect.minX(), dstRect.minY(), dstRect.SizeX(), dstRect.SizeY()); + for (auto const & s : page.m_symbols) + { + m2::RectU dstRect = page.m_packer.find(s.m_handle).second; + QRect dstRectQt(dstRect.minX(), dstRect.minY(), dstRect.SizeX(), dstRect.SizeY()); - painter.fillRect(dstRectQt, QColor(0, 0, 0, 0)); + painter.fillRect(dstRectQt, QColor(0, 0, 0, 0)); - painter.setClipRect(dstRect.minX() + 2, dstRect.minY() + 2, dstRect.SizeX() - 4, dstRect.SizeY() - 4); - QRect renderRect(dstRect.minX() + 2, dstRect.minY() + 2, dstRect.SizeX() - 4, dstRect.SizeY() - 4); + painter.setClipRect(dstRect.minX() + 2, dstRect.minY() + 2, dstRect.SizeX() - 4, dstRect.SizeY() - 4); + QRect renderRect(dstRect.minX() + 2, dstRect.minY() + 2, dstRect.SizeX() - 4, dstRect.SizeY() - 4); - QString fullLowerCaseName = it->m_fullFileName.toLower(); - if (fullLowerCaseName.endsWith(".svg")) - { - m_svgRenderer.load(it->m_fullFileName); - m_svgRenderer.render(&painter, renderRect); - } - else if (fullLowerCaseName.endsWith(".png")) - { - QPixmap pix(it->m_fullFileName); - painter.drawPixmap(renderRect, pix); - } + QString fullLowerCaseName = s.m_fullFileName.toLower(); + if (fullLowerCaseName.endsWith(".svg")) + { + m_svgRenderer.load(s.m_fullFileName); + m_svgRenderer.render(&painter, renderRect); + } + else if (fullLowerCaseName.endsWith(".png")) + { + QPixmap pix(s.m_fullFileName); + painter.drawPixmap(renderRect, pix); } - - string s = page.m_fileName + ".png"; - LOG(LINFO, ("saving skin image into: ", s)); - if (m_needColorCorrection) - correctColors(gilImage); - img.save(s.c_str()); } - return true; + string s = page.m_fileName + ".png"; + LOG(LINFO, ("saving skin image into: ", s)); + if (m_needColorCorrection) + correctColors(gilImage); + img.save(s.c_str()); } - void SkinGenerator::markOverflow() - { - m_overflowDetected = true; - } + return true; +} + +void SkinGenerator::MarkOverflow() +{ + m_overflowDetected = true; +} + +bool SkinGenerator::WriteToFileNewStyle(std::string const &skinName) +{ + QDomDocument doc = QDomDocument("skin"); + QDomElement rootElem = doc.createElement("root"); + doc.appendChild(rootElem); - void SkinGenerator::writeToFileNewStyle(const string & skinName) + for (auto const & p : m_pages) { - QDomDocument doc = QDomDocument("skin"); - QDomElement rootElem = doc.createElement("root"); - doc.appendChild(rootElem); + QDomElement fileNode = doc.createElement("file"); + fileNode.setAttribute("width", p.m_width); + fileNode.setAttribute("height", p.m_height); + rootElem.appendChild(fileNode); - for (vector::const_iterator pageIt = m_pages.begin(); pageIt != m_pages.end(); ++pageIt) + for (auto const & s : p.m_symbols) { - QDomElement fileNode = doc.createElement("file"); - fileNode.setAttribute("width", pageIt->m_width); - fileNode.setAttribute("height", pageIt->m_height); - rootElem.appendChild(fileNode); - - for (vector::const_iterator symbolIt = pageIt->m_symbols.begin(); - symbolIt != pageIt->m_symbols.end(); ++symbolIt) - { - m2::RectU r = pageIt->m_packer.find(symbolIt->m_handle).second; - QDomElement symbol = doc.createElement("symbol"); - symbol.setAttribute("minX", r.minX()); - symbol.setAttribute("minY", r.minY()); - symbol.setAttribute("maxX", r.maxX()); - symbol.setAttribute("maxY", r.maxY()); - symbol.setAttribute("name", symbolIt->m_symbolID.toLower()); - fileNode.appendChild(symbol); - } + m2::RectU r = p.m_packer.find(s.m_handle).second; + QDomElement symbol = doc.createElement("symbol"); + symbol.setAttribute("minX", r.minX()); + symbol.setAttribute("minY", r.minY()); + symbol.setAttribute("maxX", r.maxX()); + symbol.setAttribute("maxY", r.maxY()); + symbol.setAttribute("name", s.m_symbolID.toLower()); + fileNode.appendChild(symbol); } - string extName = ".sdf"; - QFile file(QString((skinName + extName).c_str())); - if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) - throw std::exception(); - QTextStream ts(&file); - ts.setCodec("UTF-8"); - ts << doc.toString(); } + QFile file(QString(skinName.c_str())); + if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) + return false; + QTextStream ts(&file); + ts.setCodec("UTF-8"); + ts << doc.toString(); + return true; +} } diff --git a/skin_generator/generator.hpp b/skin_generator/generator.hpp index 15f5d1e397..399c1619f4 100644 --- a/skin_generator/generator.hpp +++ b/skin_generator/generator.hpp @@ -7,11 +7,6 @@ #include "base/base.hpp" -#include "std/vector.hpp" -#include "std/list.hpp" -#include "std/string.hpp" -#include "std/map.hpp" - #include #include #include @@ -20,61 +15,60 @@ #include #include +#include +#include +#include +#include + class QImage; namespace tools { - class SkinGenerator +class SkinGenerator +{ +public: + struct SymbolInfo { - public: - struct SymbolInfo - { - QSize m_size; - QString m_fullFileName; - QString m_symbolID; - - m2::Packer::handle_t m_handle; - - SymbolInfo() {} - SymbolInfo(QSize size, QString const & fullFileName, QString const & symbolID) - : m_size(size), m_fullFileName(fullFileName), m_symbolID(symbolID) {} - }; - - typedef vector TSymbols; + QSize m_size; + QString m_fullFileName; + QString m_symbolID; - struct SkinPageInfo - { - TSymbols m_symbols; - uint32_t m_width; - uint32_t m_height; - string m_fileName; - string m_dir; - string m_suffix; - m2::Packer m_packer; - }; + m2::Packer::handle_t m_handle; - private: + SymbolInfo() {} + SymbolInfo(QSize size, QString const & fullFileName, QString const & symbolID) + : m_size(size), m_fullFileName(fullFileName), m_symbolID(symbolID) + {} + }; - bool m_needColorCorrection; + using TSymbols = std::vector; - QSvgRenderer m_svgRenderer; - - typedef vector TSkinPages; - TSkinPages m_pages; - - bool m_overflowDetected; - void markOverflow(); - - public: - - SkinGenerator(bool needColorCorrection); - //void processFont(string const & fileName, string const & skinName, vector const & fontSizes, int symbolScale); - void processSymbols(string const & symbolsDir, - string const & skinName, - vector const & symbolSizes, - vector const & suffix); - bool renderPages(uint32_t maxSize); - bool writeToFile(string const & skinName); - void writeToFileNewStyle(string const & skinName); - }; -} // namespace tools + struct SkinPageInfo + { + TSymbols m_symbols; + uint32_t m_width = 0; + uint32_t m_height = 0; + std::string m_fileName; + std::string m_dir; + std::string m_suffix; + m2::Packer m_packer; + }; + + explicit SkinGenerator(bool needColorCorrection); + + void ProcessSymbols(std::string const & symbolsDir, std::string const & skinName, + std::vector const & symbolSizes, + std::vector const & suffix); + bool RenderPages(uint32_t maxSize); + bool WriteToFileNewStyle(std::string const & skinName); + +private: + bool m_needColorCorrection; + QSvgRenderer m_svgRenderer; + using TSkinPages = std::vector; + TSkinPages m_pages; + bool m_overflowDetected; + + void MarkOverflow(); +}; +} // namespace tools diff --git a/skin_generator/main.cpp b/skin_generator/main.cpp index eacc9f7a1b..36746252b9 100644 --- a/skin_generator/main.cpp +++ b/skin_generator/main.cpp @@ -44,27 +44,32 @@ int main(int argc, char *argv[]) tools::SkinGenerator gen(FLAGS_colorCorrection); std::vector symbolSizes; - symbolSizes.push_back(QSize(FLAGS_symbolWidth, FLAGS_symbolHeight)); + symbolSizes.emplace_back(QSize(FLAGS_symbolWidth, FLAGS_symbolHeight)); std::vector suffixes; suffixes.push_back(FLAGS_skinSuffix); - gen.processSymbols(FLAGS_symbolsDir, FLAGS_skinName, symbolSizes, suffixes); + gen.ProcessSymbols(FLAGS_symbolsDir, FLAGS_skinName, symbolSizes, suffixes); - if (!gen.renderPages(FLAGS_maxSize)) + if (!gen.RenderPages(FLAGS_maxSize)) { - LOG(LINFO, ("Skin generation finished with error.")); + LOG(LINFO, ("Error: The texture is overflown.")); return 1; } QString newSkin(FLAGS_skinName.c_str()); newSkin.replace("basic", "symbols"); - gen.writeToFileNewStyle(newSkin.toStdString() + FLAGS_skinSuffix); + auto const filename = newSkin.toStdString() + FLAGS_skinSuffix + ".sdf"; + if (!gen.WriteToFileNewStyle(filename)) + { + std::cerr << "Could not write file" << filename << std::endl; + return -1; + } std::cout << "Done" << std::endl; return 0; } - catch (std::exception& e) + catch (std::exception const & e) { std::cerr << "Exception " << e.what() << std::endl; return -1; -- cgit v1.2.3