diff options
Diffstat (limited to 'skin_generator/generator.cpp')
-rw-r--r-- | skin_generator/generator.cpp | 423 |
1 files changed, 203 insertions, 220 deletions
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 <algorithm> +#include <iterator> +#include <fstream> +#include <functional> +#include <iostream> #include <QtXml/QDomElement> #include <QtXml/QDomDocument> @@ -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<uint32_t>(info.m_size.width())); - m_height = max(max(m_width, m_height), static_cast<uint32_t>(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<uint32_t>(info.m_size.width())); + m_height = std::max(std::max(m_width, m_height), static_cast<uint32_t>(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<unsigned char>( + 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<QSize> const & symbolSizes, - vector<string> const & suffixes) +void SkinGenerator::ProcessSymbols(std::string const & svgDataDir, + std::string const & skinName, + std::vector<QSize> const & symbolSizes, + std::vector<std::string> 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<float>(size.height()) * symbolSize.width() / size.width(); + size.setHeight(static_cast<int>(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<float>(size.width()) * symbolSize.height() / size.height(); + size.setWidth(static_cast<int>(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<uint32_t>(s.m_size.width()), + static_cast<uint32_t>(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<SkinPageInfo>::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<SymbolInfo>::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; +} } |