From 93d0eb1570c9aeb4ca04f06e501e5750f7af1ee7 Mon Sep 17 00:00:00 2001 From: rachytski Date: Wed, 26 Oct 2011 17:37:45 +0300 Subject: [PATCH] introduced CircleElement. fixes #363. --- map/drawer_yg.cpp | 31 +-- yg/agg_traits.hpp | 27 ++ yg/circle_element.cpp | 99 ++++++++ yg/circle_element.hpp | 42 ++++ yg/circle_info.cpp | 6 + yg/circle_info.hpp | 4 + yg/circle_style.cpp | 149 +++++++++++ yg/geometry_batcher.hpp | 1 - yg/glyph_style.cpp | 77 ++++++ yg/line_style.cpp | 194 +++++++++++++++ yg/overlay_renderer.cpp | 15 +- yg/overlay_renderer.hpp | 2 +- yg/resource_style.cpp | 77 +++--- yg/resource_style.hpp | 46 +++- yg/skin_loader.cpp | 59 ----- yg/skin_loader.hpp | 28 +-- yg/skin_page.cpp | 538 ++++------------------------------------ yg/skin_page.hpp | 48 +--- yg/symbol_element.cpp | 1 - yg/symbol_element.hpp | 1 - yg/text_element.cpp | 4 +- yg/text_renderer.cpp | 6 +- yg/text_renderer.hpp | 2 +- yg/yg.pro | 18 +- 24 files changed, 759 insertions(+), 716 deletions(-) create mode 100644 yg/agg_traits.hpp create mode 100644 yg/circle_element.cpp create mode 100644 yg/circle_element.hpp create mode 100644 yg/circle_style.cpp create mode 100644 yg/glyph_style.cpp create mode 100644 yg/line_style.cpp diff --git a/map/drawer_yg.cpp b/map/drawer_yg.cpp index 4b99ec0102..507ac608c9 100644 --- a/map/drawer_yg.cpp +++ b/map/drawer_yg.cpp @@ -102,30 +102,17 @@ void DrawerYG::drawSymbol(m2::PointD const & pt, string const & symbolName, yg:: void DrawerYG::drawCircle(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition pos, int depth) { - uint32_t id = pRule->GetID(m_threadID); - if (id == drule::BaseRule::empty_id) - { - double const radius = min(max(pRule->GetRadius() * m_scale, 3.0), 6.0) * m_visualScale; - unsigned char const alpha = pRule->GetAlpha(); - int const lineC = pRule->GetColor(); + double const radius = min(max(pRule->GetRadius() * m_scale, 3.0), 6.0) * m_visualScale; + unsigned char const alpha = pRule->GetAlpha(); + int const lineC = pRule->GetColor(); - id = m_pSkin->mapCircleInfo(yg::CircleInfo( - radius, - yg::Color::fromXRGB(pRule->GetFillColor(), alpha), - lineC != -1, - (lineC != -1) ? min(max(pRule->GetWidth() * m_scale * m_visualScale, 1.0), 3.0) : 1.0, - yg::Color::fromXRGB(lineC, alpha))); + yg::CircleInfo ci(radius, + yg::Color::fromXRGB(pRule->GetFillColor(), alpha), + lineC != -1, + (lineC != -1) ? min(max(pRule->GetWidth() * m_scale * m_visualScale, 1.0), 3.0) : 1.0, + yg::Color::fromXRGB(lineC, alpha)); - if (id != drule::BaseRule::empty_id) - pRule->SetID(m_threadID, id); - else - { - //ASSERT ( false, ("Can't find symbol by id = ", (name)) ); - return; - } - } - - m_pScreen->drawCircle(pt, id, pos, depth); + m_pScreen->drawCircle(pt, ci, pos, depth); } void DrawerYG::drawSymbol(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition pos, int depth) diff --git a/yg/agg_traits.hpp b/yg/agg_traits.hpp new file mode 100644 index 0000000000..c9aa0945aa --- /dev/null +++ b/yg/agg_traits.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "data_formats.hpp" + +template +struct AggTraits +{ +}; + +template <> +struct AggTraits +{ + typedef agg::pixfmt_rgba32 pixfmt_t; +}; + +template <> +struct AggTraits +{ + typedef agg::pixfmt_rgb4444 pixfmt_t; +}; diff --git a/yg/circle_element.cpp b/yg/circle_element.cpp new file mode 100644 index 0000000000..2c1ddf7702 --- /dev/null +++ b/yg/circle_element.cpp @@ -0,0 +1,99 @@ +#include "circle_element.hpp" + +#include "styles_cache.hpp" +#include "overlay_renderer.hpp" +#include "resource_style.hpp" +#include "skin.hpp" + +namespace yg +{ + CircleElement::CircleElement(Params const & p) + : base_t(p), + m_ci(p.m_ci) + {} + + + CircleElement::CircleElement(CircleElement const & ce, math::Matrix const & m) + : base_t(ce), + m_ci(ce.m_ci) + { + setPivot(ce.pivot() * m); + } + + vector const & CircleElement::boundRects() const + { + if (isDirtyRect()) + { + m_boundRects.clear(); + m_boundRects.push_back(boundRect()); + setIsDirtyRect(false); + } + + return m_boundRects; + } + + m2::AnyRectD const CircleElement::boundRect() const + { + m2::RectI texRect(m2::PointI(0, 0), m2::PointI(m_ci.patternSize())); + texRect.Inflate(-1, -1); + + m2::PointD posPt = tieRect(m2::RectD(texRect), math::Identity()); + + return m2::AnyRectD(m2::RectD(posPt, posPt + m2::PointD(texRect.SizeX(), texRect.SizeY()))); + } + + void CircleElement::draw(gl::OverlayRenderer * r, math::Matrix const & m) const + { + if (!isNeedRedraw()) + return; + + uint32_t styleID = r->skin()->mapCircleInfo(m_ci); + + ResourceStyle const * style = r->skin()->fromID(styleID); + + m2::RectI texRect(style->m_texRect); + texRect.Inflate(-1, -1); + + m2::PointD posPt = tieRect(m2::RectD(texRect), m); + + r->drawTexturedPolygon(m2::PointD(0.0, 0.0), 0.0, + texRect.minX(), texRect.minY(), texRect.maxX(), texRect.maxY(), + posPt.x, posPt.y, posPt.x + texRect.SizeX(), posPt.y + texRect.SizeY(), + yg::maxDepth, + style->m_pipelineID); + } + + int CircleElement::visualRank() const + { + return 500; + } + + void CircleElement::map(StylesCache * stylesCache) const + { + shared_ptr const & skinPage = stylesCache->cachePage(); + + ASSERT(skinPage->hasRoom(m_ci), ()); + + skinPage->mapCircleInfo(m_ci); + } + + bool CircleElement::find(StylesCache * stylesCache) const + { + shared_ptr const & skinPage = stylesCache->cachePage(); + + return skinPage->findCircleInfo(m_ci) != 0x00FFFFFF; + } + + void CircleElement::fillUnpacked(StylesCache * stylesCache, vector & v) const + { + shared_ptr const & skinPage = stylesCache->cachePage(); + + if (skinPage->findCircleInfo(m_ci) == 0x00FFFFFF) + v.push_back(m_ci.patternSize()); + } + + OverlayElement * CircleElement::clone(math::Matrix const & m) const + { + return new CircleElement(*this, m); + } +} diff --git a/yg/circle_element.hpp b/yg/circle_element.hpp new file mode 100644 index 0000000000..f82b4a3c4a --- /dev/null +++ b/yg/circle_element.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "overlay_element.hpp" +#include "circle_info.hpp" + +namespace yg +{ + class CircleElement : public OverlayElement + { + private: + + yg::CircleInfo m_ci; + + mutable vector m_boundRects; + + m2::AnyRectD const boundRect() const; + + public: + + typedef OverlayElement base_t; + + struct Params : public base_t::Params + { + yg::CircleInfo m_ci; + }; + + CircleElement(Params const & p); + CircleElement(CircleElement const & ce, math::Matrix const & m); + + vector const & boundRects() const; + + void draw(gl::OverlayRenderer * s, math::Matrix const & m) const; + + void map(StylesCache * stylesCache) const; + void fillUnpacked(StylesCache * stylesCache, vector & v) const; + bool find(StylesCache * stylesCache) const; + + int visualRank() const; + + OverlayElement * clone(math::Matrix const & m) const; + }; +} diff --git a/yg/circle_info.cpp b/yg/circle_info.cpp index b71fadf4fa..0ab7951e8b 100644 --- a/yg/circle_info.cpp +++ b/yg/circle_info.cpp @@ -34,4 +34,10 @@ namespace yg return l.m_outlineWidth < r.m_outlineWidth; return l.m_outlineColor < r.m_outlineColor; } + + m2::PointU const CircleInfo::patternSize() const + { + unsigned r = m_isOutlined ? m_radius + m_outlineWidth : m_radius; + return m2::PointU(r * 2 + 4, r * 2 + 4); + } } diff --git a/yg/circle_info.hpp b/yg/circle_info.hpp index bb7fef959d..01477e1c8b 100644 --- a/yg/circle_info.hpp +++ b/yg/circle_info.hpp @@ -2,6 +2,8 @@ #include "color.hpp" +#include "../geometry/point2d.hpp" + namespace yg { struct CircleInfo @@ -19,6 +21,8 @@ namespace yg bool isOutlined = false, double outlineWidth = 1, Color const & outlineColor = Color(255, 255, 255, 255)); + + m2::PointU const patternSize() const; }; bool operator< (CircleInfo const & l, CircleInfo const & r); diff --git a/yg/circle_style.cpp b/yg/circle_style.cpp new file mode 100644 index 0000000000..7bb497bddc --- /dev/null +++ b/yg/circle_style.cpp @@ -0,0 +1,149 @@ +#include "resource_style.hpp" + +#include "agg_traits.hpp" +#include "data_formats.hpp" + +namespace yg +{ + CircleStyle::CircleStyle(m2::RectU const & texRect, int pipelineID, yg::CircleInfo const & ci) + : ResourceStyle(ECircleStyle, texRect, pipelineID), + m_ci(ci) + {} + + void CircleStyle::render(void * dst) + { + yg::CircleInfo & circleInfo = m_ci; + m2::RectU const & rect = m_texRect; + + DATA_TRAITS::view_t v = gil::interleaved_view( + rect.SizeX(), rect.SizeY(), + (DATA_TRAITS::pixel_t*)dst, + sizeof(DATA_TRAITS::pixel_t) * rect.SizeX() + ); + + agg::rgba8 aggColor(circleInfo.m_color.r, + circleInfo.m_color.g, + circleInfo.m_color.b, + circleInfo.m_color.a); + + agg::rgba8 aggOutlineColor(circleInfo.m_outlineColor.r, + circleInfo.m_outlineColor.g, + circleInfo.m_outlineColor.b, + circleInfo.m_outlineColor.a); + + circleInfo.m_color /= DATA_TRAITS::channelScaleFactor; + + DATA_TRAITS::pixel_t gilColorTranslucent; + + gil::get_color(gilColorTranslucent, gil::red_t()) = circleInfo.m_color.r; + gil::get_color(gilColorTranslucent, gil::green_t()) = circleInfo.m_color.g; + gil::get_color(gilColorTranslucent, gil::blue_t()) = circleInfo.m_color.b; + gil::get_color(gilColorTranslucent, gil::alpha_t()) = 0; + + circleInfo.m_outlineColor /= DATA_TRAITS::channelScaleFactor; + + DATA_TRAITS::pixel_t gilOutlineColorTranslucent; + + gil::get_color(gilOutlineColorTranslucent, gil::red_t()) = circleInfo.m_outlineColor.r; + gil::get_color(gilOutlineColorTranslucent, gil::green_t()) = circleInfo.m_outlineColor.g; + gil::get_color(gilOutlineColorTranslucent, gil::blue_t()) = circleInfo.m_outlineColor.b; + gil::get_color(gilOutlineColorTranslucent, gil::alpha_t()) = 0; + + DATA_TRAITS::pixel_t gilColor = gilColorTranslucent; + gil::get_color(gilColor, gil::alpha_t()) = circleInfo.m_color.a; + + DATA_TRAITS::pixel_t gilOutlineColor = gilOutlineColorTranslucent; + gil::get_color(gilOutlineColor, gil::alpha_t()) = circleInfo.m_outlineColor.a; + + /// draw circle + agg::rendering_buffer buf( + (unsigned char *)&v(0, 0), + rect.SizeX(), + rect.SizeY(), + rect.SizeX() * sizeof(DATA_TRAITS::pixel_t) + ); + + typedef AggTraits::pixfmt_t agg_pixfmt_t; + + agg_pixfmt_t pixfmt(buf); + agg::renderer_base rbase(pixfmt); + + if (circleInfo.m_isOutlined) + gil::fill_pixels(v, gilOutlineColorTranslucent); + else + gil::fill_pixels(v, gilColorTranslucent); + + m2::PointD center(circleInfo.patternSize()); + center *= 0.5; + + agg::scanline_u8 s; + agg::rasterizer_scanline_aa<> rasterizer; + + agg::ellipse ell; + + ell.init(center.x, + center.y, + circleInfo.m_isOutlined ? circleInfo.m_radius + circleInfo.m_outlineWidth : circleInfo.m_radius, + circleInfo.m_isOutlined ? circleInfo.m_radius + circleInfo.m_outlineWidth : circleInfo.m_radius, + 100); + + rasterizer.add_path(ell); + + agg::render_scanlines_aa_solid(rasterizer, + s, + rbase, + circleInfo.m_isOutlined ? aggOutlineColor : aggColor); + + DATA_TRAITS::pixel_t px = circleInfo.m_isOutlined ? gilOutlineColor : gilColor; + + /// making alpha channel opaque +/* for (size_t x = 2; x < v.width() - 2; ++x) + for (size_t y = 2; y < v.height() - 2; ++y) + { + unsigned char alpha = gil::get_color(v(x, y), gil::alpha_t()); + + float fAlpha = alpha / (float)DATA_TRAITS::maxChannelVal; + + if (alpha != 0) + { + gil::get_color(v(x, y), gil::red_t()) *= fAlpha; + gil::get_color(v(x, y), gil::green_t()) *= fAlpha; + gil::get_color(v(x, y), gil::blue_t()) *= fAlpha; + + gil::get_color(v(x, y), gil::alpha_t()) = DATA_TRAITS::maxChannelVal; + } + } +*/ + if (circleInfo.m_isOutlined) + { + /// drawing inner circle + ell.init(center.x, + center.y, + circleInfo.m_radius, + circleInfo.m_radius, + 100); + + rasterizer.reset(); + rasterizer.add_path(ell); + + agg::render_scanlines_aa_solid(rasterizer, + s, + rbase, + aggColor); +/* for (size_t x = 2; x < v.width() - 2; ++x) + for (size_t y = 2; y < v.height() - 2; ++y) + { + unsigned char alpha = gil::get_color(v(x, y), gil::alpha_t()); + float fAlpha = alpha / (float)DATA_TRAITS::maxChannelVal; +// if (alpha != 0) +// { + gil::get_color(v(x, y), gil::red_t()) *= fAlpha; + gil::get_color(v(x, y), gil::green_t()) *= fAlpha; + gil::get_color(v(x, y), gil::blue_t()) *= fAlpha; + +// gil::get_color(v(x, y), gil::alpha_t()) = DATA_TRAITS::maxChannelVal; +// } + }*/ + } + } +} diff --git a/yg/geometry_batcher.hpp b/yg/geometry_batcher.hpp index 40fd59e6f7..844d9fd921 100644 --- a/yg/geometry_batcher.hpp +++ b/yg/geometry_batcher.hpp @@ -26,7 +26,6 @@ namespace threads namespace yg { class Skin; - struct CharStyle; namespace gl { diff --git a/yg/glyph_style.cpp b/yg/glyph_style.cpp new file mode 100644 index 0000000000..821913ee47 --- /dev/null +++ b/yg/glyph_style.cpp @@ -0,0 +1,77 @@ +#include "resource_style.hpp" + +#include "glyph_cache.hpp" +#include "agg_traits.hpp" +#include "data_formats.hpp" + +namespace yg +{ + GlyphStyle::GlyphStyle(m2::RectU const & texRect, int pipelineID, shared_ptr const & gi) + : ResourceStyle(EGlyphStyle, texRect, pipelineID), m_gi(gi) + {} + + void GlyphStyle::render(void * dst) + { + shared_ptr const & gi = m_gi; + m2::RectU const & rect = m_texRect; + + DATA_TRAITS::view_t v = gil::interleaved_view( + rect.SizeX(), rect.SizeY(), + (DATA_TRAITS::pixel_t*)dst, + sizeof(DATA_TRAITS::pixel_t) * rect.SizeX() + ); + + DATA_TRAITS::pixel_t pxTranslucent; + gil::get_color(pxTranslucent, gil::red_t()) = gi->m_color.r / DATA_TRAITS::channelScaleFactor; + gil::get_color(pxTranslucent, gil::green_t()) = gi->m_color.g / DATA_TRAITS::channelScaleFactor; + gil::get_color(pxTranslucent, gil::blue_t()) = gi->m_color.b / DATA_TRAITS::channelScaleFactor; + gil::get_color(pxTranslucent, gil::alpha_t()) = 0; + + for (size_t y = 0; y < 2; ++y) + for (size_t x = 0; x < rect.SizeX(); ++x) + v(x, y) = pxTranslucent; + + for (size_t y = rect.SizeY() - 2; y < rect.SizeY(); ++y) + for (size_t x = 0; x < rect.SizeX(); ++x) + v(x, y) = pxTranslucent; + + for (size_t y = 2; y < rect.SizeY() - 2; ++y) + { + v(0, y) = pxTranslucent; + v(1, y) = pxTranslucent; + v(rect.SizeX() - 2, y) = pxTranslucent; + v(rect.SizeX() - 1, y) = pxTranslucent; + } + + if ((gi->m_metrics.m_width != 0) && (gi->m_metrics.m_height != 0)) + { + gil::gray8c_view_t srcView = gil::interleaved_view( + gi->m_metrics.m_width, + gi->m_metrics.m_height, + (gil::gray8_pixel_t*)gi->m_bitmapData, + gi->m_bitmapPitch + ); + +/* DATA_TRAITS::const_view_t srcView = gil::interleaved_view( + gi->m_metrics.m_width, + gi->m_metrics.m_height, + (TDynamicTexture::pixel_t*)&gi->m_bitmap[0], + gi->m_metrics.m_width * sizeof(TDynamicTexture::pixel_t) + );*/ + + DATA_TRAITS::pixel_t c; + + gil::get_color(c, gil::red_t()) = gi->m_color.r / DATA_TRAITS::channelScaleFactor; + gil::get_color(c, gil::green_t()) = gi->m_color.g / DATA_TRAITS::channelScaleFactor; + gil::get_color(c, gil::blue_t()) = gi->m_color.b / DATA_TRAITS::channelScaleFactor; + gil::get_color(c, gil::alpha_t()) = gi->m_color.a / DATA_TRAITS::channelScaleFactor; + + for (size_t y = 2; y < rect.SizeY() - 2; ++y) + for (size_t x = 2; x < rect.SizeX() - 2; ++x) + { + gil::get_color(c, gil::alpha_t()) = srcView(x - 2, y - 2) / DATA_TRAITS::channelScaleFactor; + v(x, y) = c; + } + } + } +} diff --git a/yg/line_style.cpp b/yg/line_style.cpp new file mode 100644 index 0000000000..25f114c610 --- /dev/null +++ b/yg/line_style.cpp @@ -0,0 +1,194 @@ +#include "resource_style.hpp" + +#include "agg_traits.hpp" +#include "data_formats.hpp" + +namespace yg +{ + LineStyle::LineStyle(bool isWrapped, m2::RectU const & texRect, int pipelineID, yg::PenInfo const & penInfo) : + ResourceStyle(ELineStyle, texRect, pipelineID), + m_isWrapped(isWrapped), + m_isSolid(penInfo.m_isSolid), + m_penInfo(penInfo) + { + if (m_isSolid) + { + m_borderColorPixel = m_centerColorPixel = m2::PointU(texRect.minX() + 1, texRect.minY() + 1); + } + else + { + double firstDashOffset = penInfo.firstDashOffset(); + m_centerColorPixel = m2::PointU(static_cast(firstDashOffset + texRect.minX() + 3), + static_cast(texRect.minY() + texRect.SizeY() / 2.0)); + m_borderColorPixel = m2::PointU(static_cast(firstDashOffset + texRect.minX() + 3), + static_cast(texRect.minY() + 1)); + } + } + + double LineStyle::geometryTileLen() const + { + return m_texRect.SizeX() - 2; + } + + double LineStyle::geometryTileWidth() const + { + return m_texRect.SizeY() - 2; + } + + double LineStyle::rawTileLen() const + { + return m_texRect.SizeX() - 4; + } + + double LineStyle::rawTileWidth() const + { + return m_texRect.SizeY() - 4; + } + + void LineStyle::render(void * dst) + { + yg::PenInfo const & penInfo = m_penInfo; + m2::RectU const & rect = m_texRect; + + DATA_TRAITS::view_t v = gil::interleaved_view(rect.SizeX(), + rect.SizeY(), + (DATA_TRAITS::pixel_t*)dst, + sizeof(DATA_TRAITS::pixel_t) * rect.SizeX()); + + yg::Color penInfoColor = penInfo.m_color; + + penInfoColor /= DATA_TRAITS::channelScaleFactor; + + DATA_TRAITS::pixel_t penColorTranslucent; + + gil::get_color(penColorTranslucent, gil::red_t()) = penInfoColor.r; + gil::get_color(penColorTranslucent, gil::green_t()) = penInfoColor.g; + gil::get_color(penColorTranslucent, gil::blue_t()) = penInfoColor.b; + gil::get_color(penColorTranslucent, gil::alpha_t()) = 0; + + DATA_TRAITS::pixel_t penColor = penColorTranslucent; + gil::get_color(penColor, gil::alpha_t()) = penInfoColor.a; + + if (penInfo.m_isSolid) + { + /// draw circle + agg::rendering_buffer buf( + (unsigned char *)&v(0, 0), + rect.SizeX(), + rect.SizeY(), + rect.SizeX() * sizeof(DATA_TRAITS::pixel_t) + ); + + typedef AggTraits::pixfmt_t agg_pixfmt_t; + + agg_pixfmt_t pixfmt(buf); + agg::renderer_base rbase(pixfmt); + + gil::fill_pixels(v, penColorTranslucent); + + agg::scanline_u8 s; + agg::rasterizer_scanline_aa<> rasterizer; + if (penInfo.m_w > 2) + { + agg::ellipse ell; + float r = ceil(penInfo.m_w) / 2.0; + ell.init(r + 2, r + 2, r, r, 100); + rasterizer.add_path(ell); + + agg::render_scanlines_aa_solid(rasterizer, + s, + rbase, + agg::rgba8(penInfo.m_color.r, + penInfo.m_color.g, + penInfo.m_color.b, + penInfo.m_color.a)); + + uint32_t ri = static_cast(r); + + /// pixels that are used to texture inner part of the line should be fully opaque + v(2 + ri - 1, 2) = penColor; + v(2 + ri , 2) = penColor; + v(2 + ri - 1, 2 + ri * 2 - 1) = penColor; + v(2 + ri , 2 + ri * 2 - 1) = penColor; + + /// in non-transparent areas - premultiply color value with alpha and make it opaque + for (size_t x = 2; x < v.width() - 2; ++x) + for (size_t y = 2; y < v.height() - 2; ++y) + { + unsigned char alpha = gil::get_color(v(x, y), gil::alpha_t()); + if (alpha != 0) + { + v(x, y) = penColor; +// if (m_fillAlpha) +// gil::get_color(v(x, y), gil::alpha_t()) = alpha; + } + } + } + else + { + gil::fill_pixels( + gil::subimage_view(v, 2, 2, rect.SizeX() - 4, rect.SizeY() - 4), + penColor + ); + } + } + else + { + /// First two and last two rows of a pattern are filled + /// with a penColorTranslucent pixel for the antialiasing. + for (size_t y = 0; y < 2; ++y) + for (size_t x = 0; x < rect.SizeX(); ++x) + v(x, y) = penColorTranslucent; + + for (size_t y = rect.SizeY() - 2; y < rect.SizeY(); ++y) + for (size_t x = 0; x < rect.SizeX(); ++x) + v(x, y) = penColorTranslucent; + + /// first and last two pixels filled with penColorTranslucent + for (size_t y = 2; y < rect.SizeY() - 2; ++y) + { + v(0, y) = penColorTranslucent; + v(1, y) = penColorTranslucent; + v(rect.SizeX() - 2, y) = penColorTranslucent; + v(rect.SizeX() - 1, y) = penColorTranslucent; + } + + /// draw pattern + for (size_t y = 2; y < rect.SizeY() - 2; ++y) + { + double curLen = 0; + + DATA_TRAITS::pixel_t px = penColor; + + /// In general case this code is incorrect. + /// TODO : Make a pattern start and end with a dash. + uint32_t curLenI = static_cast(curLen); + + v(curLenI, y) = px; + v(curLenI + 1, y) = px; + + for (size_t i = 0; i < penInfo.m_pat.size(); ++i) + { + for (size_t j = 0; j < penInfo.m_pat[i]; ++j) + { + uint32_t val = (i + 1) % 2; + + if (val == 0) + gil::get_color(px, gil::alpha_t()) = 0; + else + gil::get_color(px, gil::alpha_t()) = penInfoColor.a; + + v(curLenI + j + 2, y) = px; + } + + v(static_cast(curLen + 2 + penInfo.m_pat[i]), y) = px; + v(static_cast(curLen + 2 + penInfo.m_pat[i] + 1), y) = px; + + curLen += penInfo.m_pat[i]; + + curLenI = static_cast(curLen); + } + } + } + } +} diff --git a/yg/overlay_renderer.cpp b/yg/overlay_renderer.cpp index 42e41143da..7bc0d9026b 100644 --- a/yg/overlay_renderer.cpp +++ b/yg/overlay_renderer.cpp @@ -5,6 +5,7 @@ #include "straight_text_element.hpp" #include "path_text_element.hpp" #include "symbol_element.hpp" +#include "circle_element.hpp" #include "render_state.hpp" #include "info_layer.hpp" #include "resource_manager.hpp" @@ -75,23 +76,25 @@ namespace yg } void OverlayRenderer::drawCircle(m2::PointD const & pt, - uint32_t styleID, + yg::CircleInfo const & ci, EPosition pos, int depth) { - SymbolElement::Params params; + CircleElement::Params params; params.m_depth = depth; params.m_position = pos; params.m_pivot = pt; - params.m_styleID = styleID; - params.m_skin = skin().get(); + params.m_ci = ci; - SymbolElement se(params); + shared_ptr oe(new CircleElement(params)); math::Matrix id = math::Identity(); - se.draw(this, id); + if (!m_infoLayer.get()) + oe->draw(this, id); + else + m_infoLayer->processOverlayElement(oe); } void OverlayRenderer::drawText(FontDesc const & fontDesc, diff --git a/yg/overlay_renderer.hpp b/yg/overlay_renderer.hpp index 4041962102..cc7a88d613 100644 --- a/yg/overlay_renderer.hpp +++ b/yg/overlay_renderer.hpp @@ -36,7 +36,7 @@ namespace yg void drawSymbol(m2::PointD const & pt, string const & symbolName, EPosition pos, int depth); /// Drawing circle - void drawCircle(m2::PointD const & pt, uint32_t styleID, EPosition pos, int depth); + void drawCircle(m2::PointD const & pt, yg::CircleInfo const & ci, EPosition pos, int depth); /// drawing straight text void drawText(FontDesc const & fontDesc, diff --git a/yg/resource_style.cpp b/yg/resource_style.cpp index bfff22e47d..0439b1e912 100644 --- a/yg/resource_style.cpp +++ b/yg/resource_style.cpp @@ -1,6 +1,6 @@ #include "resource_style.hpp" -#include "../base/start_mem_debug.hpp" +#include "data_formats.hpp" namespace yg { @@ -10,7 +10,7 @@ namespace yg ResourceStyle::ResourceStyle( m2::RectU const & texRect, int pipelineID - ) : m_cat(EGenericStyle), + ) : m_cat(EUnknownStyle), m_texRect(texRect), m_pipelineID(pipelineID) {} @@ -24,55 +24,40 @@ namespace yg m_pipelineID(pipelineID) {} - LineStyle::LineStyle(bool isWrapped, m2::RectU const & texRect, int pipelineID, yg::PenInfo const & penInfo) : - ResourceStyle(ELineStyle, texRect, pipelineID), - m_isWrapped(isWrapped), - m_isSolid(penInfo.m_isSolid), - m_penInfo(penInfo) - { - if (m_isSolid) - { - m_borderColorPixel = m_centerColorPixel = m2::PointU(texRect.minX() + 1, texRect.minY() + 1); - } - else - { - double firstDashOffset = penInfo.firstDashOffset(); - m_centerColorPixel = m2::PointU(static_cast(firstDashOffset + texRect.minX() + 3), - static_cast(texRect.minY() + texRect.SizeY() / 2.0)); - m_borderColorPixel = m2::PointU(static_cast(firstDashOffset + texRect.minX() + 3), - static_cast(texRect.minY() + 1)); - } - } - - double LineStyle::geometryTileLen() const - { - return m_texRect.SizeX() - 2; - } - - double LineStyle::geometryTileWidth() const - { - return m_texRect.SizeY() - 2; - } - - double LineStyle::rawTileLen() const - { - return m_texRect.SizeX() - 4; - } - - double LineStyle::rawTileWidth() const - { - return m_texRect.SizeY() - 4; - } - - CharStyle::CharStyle(m2::RectU const & texRect, int pipelineID, int8_t xOffset, int8_t yOffset, int8_t xAdvance) - : ResourceStyle(ECharStyle, texRect, pipelineID), m_xOffset(xOffset), m_yOffset(yOffset), m_xAdvance(xAdvance) + ResourceStyle::~ResourceStyle() {} PointStyle::PointStyle(m2::RectU const & texRect, int pipelineID, string const & styleName) : ResourceStyle(EPointStyle, texRect, pipelineID), m_styleName(styleName) {} - GenericStyle::GenericStyle(m2::RectU const & texRect, int pipelineID) - : ResourceStyle(EGenericStyle, texRect, pipelineID) + void PointStyle::render(void *dst) {} + + ColorStyle::ColorStyle(m2::RectU const & texRect, int pipelineID, yg::Color const & c) + : ResourceStyle(EColorStyle, texRect, pipelineID), m_c(c) + {} + + void ColorStyle::render(void * dst) + { + yg::Color c = m_c; + m2::RectU const & r = m_texRect; + + DATA_TRAITS::pixel_t px; + + gil::get_color(px, gil::red_t()) = c.r / DATA_TRAITS::channelScaleFactor; + gil::get_color(px, gil::green_t()) = c.g / DATA_TRAITS::channelScaleFactor; + gil::get_color(px, gil::blue_t()) = c.b / DATA_TRAITS::channelScaleFactor; + gil::get_color(px, gil::alpha_t()) = c.a / DATA_TRAITS::channelScaleFactor; + + DATA_TRAITS::view_t v = gil::interleaved_view( + r.SizeX(), r.SizeY(), + (DATA_TRAITS::pixel_t*)dst, + sizeof(DATA_TRAITS::pixel_t) * r.SizeX() + ); + + for (size_t y = 0; y < r.SizeY(); ++y) + for (size_t x = 0; x < r.SizeX(); ++x) + v(x, y) = px; + } } diff --git a/yg/resource_style.hpp b/yg/resource_style.hpp index d91e097266..876c6c0208 100644 --- a/yg/resource_style.hpp +++ b/yg/resource_style.hpp @@ -1,18 +1,26 @@ #pragma once -#include "../geometry/rect2d.hpp" #include "pen_info.hpp" +#include "circle_info.hpp" + +#include "../geometry/rect2d.hpp" + +#include "../std/shared_ptr.hpp" namespace yg { + struct GlyphInfo; + struct ResourceStyle { enum Category { - ELineStyle = 1, - ECharStyle, + EColorStyle = 1, + ELineStyle, + EGlyphStyle, EPointStyle, - EGenericStyle + ECircleStyle, + EUnknownStyle }; Category m_cat; @@ -22,6 +30,9 @@ namespace yg ResourceStyle(); ResourceStyle(m2::RectU const & texRect, int pipelineID); + virtual ~ResourceStyle(); + virtual void render(void * dst) = 0; + protected: ResourceStyle(Category cat, m2::RectU const & texRect, int pipelineID); }; @@ -43,25 +54,38 @@ namespace yg double rawTileLen() const; double rawTileWidth() const; + void render(void * dst); }; - struct CharStyle : public ResourceStyle + struct GlyphStyle : public ResourceStyle { - int8_t m_xOffset; - int8_t m_yOffset; - int8_t m_xAdvance; + shared_ptr m_gi; + GlyphStyle(m2::RectU const & texRect, int pipelineID, shared_ptr const & gi); - CharStyle(m2::RectU const & texRect, int pipelineID, int8_t xOffset, int8_t yOffset, int8_t xAdvance); + void render(void * dst); }; struct PointStyle : public ResourceStyle { string m_styleName; PointStyle(m2::RectU const & texRect, int pipelineID, string const & styleName); + + void render(void * dst); }; - struct GenericStyle : public ResourceStyle + struct CircleStyle : public ResourceStyle { - GenericStyle(m2::RectU const & texRect, int pipelineID); + yg::CircleInfo m_ci; + CircleStyle(m2::RectU const & texRect, int pipelineID, yg::CircleInfo const & ci); + + void render(void * dst); + }; + + struct ColorStyle : public ResourceStyle + { + yg::Color m_c; + ColorStyle(m2::RectU const & texRect, int pipelineID, yg::Color const & c); + + void render(void * dst); }; } diff --git a/yg/skin_loader.cpp b/yg/skin_loader.cpp index bbaa6068e8..526e74742b 100644 --- a/yg/skin_loader.cpp +++ b/yg/skin_loader.cpp @@ -35,32 +35,6 @@ namespace yg m_texRect = m2::RectU(m_texX, m_texY, m_texX + m_texWidth, m_texY + m_texHeight); } - void SkinLoader::popCharStyle() - { - m_chars[m_id] = make_pair(m_glyphInfo, m_glyphMaskInfo); - } - - void SkinLoader::popGlyphInfo() - { - m_glyphInfo = shared_ptr(new CharStyle(m_texRect, m_pages.size(), m_xOffset, m_yOffset, m_xAdvance)); - } - - void SkinLoader::popGlyphMaskInfo() - { - m_glyphMaskInfo = shared_ptr(new CharStyle(m_texRect, m_pages.size(), m_xOffset, m_yOffset, m_xAdvance)); - } - - void SkinLoader::pushFontInfo() - { - m_chars.clear(); - m_fontSize = 0; - } - - void SkinLoader::popFontInfo() - { - m_fonts[m_fontSize] = m_chars; - } - void SkinLoader::popPointStyle() { uint32_t id = m_id; @@ -91,16 +65,6 @@ 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() @@ -135,10 +99,6 @@ namespace yg { PUSH_MODE(ESkin, "skin"); PUSH_MODE_EX(EPage, "page", pushPage); - PUSH_MODE(ECharStyle, "charStyle"); - PUSH_MODE(EGlyphInfo, "glyphInfo"); - PUSH_MODE(EGlyphMaskInfo, "glyphMaskInfo"); - PUSH_MODE_EX(EFontInfo, "fontInfo", pushFontInfo); PUSH_MODE(EPointStyle, "symbolStyle"); PUSH_MODE(ELineStyle, "lineStyle"); PUSH_MODE_EX(EResourceStyle, "resourceStyle", pushResourceStyle); @@ -149,10 +109,6 @@ namespace yg { POP_MODE_EX(ESkin, "skin", popSkin); POP_MODE_EX(EPage, "page", popPage); - POP_MODE_EX(ECharStyle, "charStyle", popCharStyle); - POP_MODE_EX(EGlyphInfo, "glyphInfo", popGlyphInfo); - POP_MODE_EX(EGlyphMaskInfo, "glyphMaskInfo", popGlyphMaskInfo); - POP_MODE_EX(EFontInfo, "fontInfo", popFontInfo); POP_MODE_EX(EPointStyle, "symbolStyle", popPointStyle); POP_MODE(ELineStyle, "lineStyle"); POP_MODE_EX(EResourceStyle, "resourceStyle", popResourceStyle); @@ -175,21 +131,6 @@ namespace yg if (attr == "file") m_fileName = value; break; - case ECharStyle: - if (attr == "id") - m_id = StrToInt(value); - case EGlyphInfo: case EGlyphMaskInfo: - if (attr == "xOffset") - m_xOffset = StrToInt(value); - else if (attr == "yOffset") - m_yOffset = StrToInt(value); - else if (attr == "xAdvance") - m_xAdvance = StrToInt(value); - break; - case EFontInfo: - if (attr == "size") - m_fontSize = StrToInt(value); - break; case EPointStyle: if (attr == "id") m_id = StrToInt(value); diff --git a/yg/skin_loader.hpp b/yg/skin_loader.hpp index 832ad600c3..cb6a32693c 100644 --- a/yg/skin_loader.hpp +++ b/yg/skin_loader.hpp @@ -39,7 +39,7 @@ namespace yg class ResourceManager; class SkinPage; struct ResourceStyle; - struct CharStyle; + struct GlyphStyle; class SkinLoader { @@ -53,11 +53,7 @@ namespace yg EFontStyle, EPointStyle, ELineStyle, - EResourceStyle, - ECharStyle, - EGlyphInfo, - EGlyphMaskInfo, - EFontInfo + EResourceStyle }; list m_mode; @@ -70,23 +66,13 @@ namespace yg uint32_t m_texHeight; m2::RectU m_texRect; -/// fontInfo-specific parameters - typedef map, shared_ptr > > TChars; - TChars m_chars; - typedef map TFonts; - TFonts m_fonts; - int8_t m_fontSize; - -/// charStyle-specific parameters - - /// glyphInfo and glyphMaskInfo specific parameters int8_t m_xOffset; int8_t m_yOffset; int8_t m_xAdvance; - shared_ptr m_glyphInfo; - shared_ptr m_glyphMaskInfo; + shared_ptr m_glyphInfo; + shared_ptr m_glyphMaskInfo; /// pointStyle-specific parameters string m_styleID; @@ -118,10 +104,6 @@ namespace yg void AddAttr(string const & attribute, string const & value); void CharData(string const &) {} - void popCharStyle(); - void popGlyphInfo(); - void popGlyphMaskInfo(); - void popFontInfo(); void popPointStyle(); void popSkin(); void pushPage(); @@ -129,9 +111,7 @@ namespace yg void pushResourceStyle(); void popResourceStyle(); - void pushFontInfo(); Skin * skin(); - }; } diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index d008fbbb6f..13401ed9c5 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -1,13 +1,7 @@ -#include -#include -#include -#include -#include -#include +#include "skin_page.hpp" #include "texture.hpp" #include "data_formats.hpp" -#include "skin_page.hpp" #include "resource_style.hpp" #include "resource_manager.hpp" #include "internal/opengl.hpp" @@ -17,51 +11,10 @@ #include "../std/bind.hpp" #include "../std/numeric.hpp" -template -struct AggTraits -{ -}; - -template <> -struct AggTraits -{ - typedef agg::pixfmt_rgba32 pixfmt_t; -}; - -template <> -struct AggTraits -{ - typedef agg::pixfmt_rgb4444 pixfmt_t; -}; - namespace yg { typedef gl::Texture TDynamicTexture; - GlyphUploadCmd::GlyphUploadCmd(){} - GlyphUploadCmd::GlyphUploadCmd(shared_ptr const & glyphInfo, - m2::RectU const & rect) - : m_glyphInfo(glyphInfo), - m_rect(rect){} - - ColorUploadCmd::ColorUploadCmd(){} - ColorUploadCmd::ColorUploadCmd(yg::Color const & color, - m2::RectU const & rect) - : m_color(color), - m_rect(rect){} - - PenUploadCmd::PenUploadCmd(){} - PenUploadCmd::PenUploadCmd(yg::PenInfo const & penInfo, - m2::RectU const & rect) - : m_penInfo(penInfo), - m_rect(rect){} - - CircleUploadCmd::CircleUploadCmd(){} - CircleUploadCmd::CircleUploadCmd(yg::CircleInfo const & circleInfo, - m2::RectU const & rect) - : m_circleInfo(circleInfo), - m_rect(rect){} - ResourceStyle * FontInfo::fromID(uint32_t id, bool isMask) const { TChars::const_iterator it = m_chars.find(id); @@ -130,18 +83,15 @@ namespace yg m_packer.reset(); } - void SkinPage::clearUploadCommands() + void SkinPage::clearUploadQueue() { - m_penUploadCommands.clear(); - m_colorUploadCommands.clear(); - m_glyphUploadCommands.clear(); - m_circleUploadCommands.clear(); + m_uploadQueue.clear(); } void SkinPage::clear() { clearHandles(); - clearUploadCommands(); + clearUploadQueue(); } void SkinPage::clearColorHandles() @@ -194,12 +144,13 @@ namespace yg m2::Packer::handle_t h = m_packer.pack(2, 2); - m2::RectU texRect = m_packer.find(h).second; - - m_colorUploadCommands.push_back(ColorUploadCmd(c, texRect)); m_colorMap[c] = h; - m_styles[h] = shared_ptr(new GenericStyle(texRect, m_pipelineID)); + m2::RectU texRect = m_packer.find(h).second; + shared_ptr colorStyle(new ColorStyle(texRect, m_pipelineID, c)); + + m_styles[h] = colorStyle; + m_uploadQueue.push_back(colorStyle); return h; } @@ -239,15 +190,15 @@ namespace yg gi->m_metrics.m_height + 4); m2::RectU texRect = m_packer.find(handle).second; - m_glyphUploadCommands.push_back(GlyphUploadCmd(gi, texRect)); m_glyphMap[g] = handle; - m_styles[handle] = boost::shared_ptr( - new CharStyle(texRect, + boost::shared_ptr glyphStyle( + new GlyphStyle(texRect, m_pipelineID, - gi->m_metrics.m_xOffset, - gi->m_metrics.m_yOffset, - gi->m_metrics.m_xAdvance)); + gi)); + + m_styles[handle] = glyphStyle; + m_uploadQueue.push_back(glyphStyle); return m_glyphMap[g]; } @@ -279,26 +230,25 @@ namespace yg if (foundHandle != m_packer.invalidHandle()) return foundHandle; - unsigned r = circleInfo.m_isOutlined ? circleInfo.m_radius + circleInfo.m_outlineWidth : circleInfo.m_radius; + m2::PointU sz = circleInfo.patternSize(); + m2::Packer::handle_t handle = m_packer.pack(sz.x, sz.y); - m2::Packer::handle_t handle = m_packer.pack( - r * 2 + 4, - r * 2 + 4); - - m2::RectU texRect = m_packer.find(handle).second; - m_circleUploadCommands.push_back(CircleUploadCmd(circleInfo, texRect)); m_circleInfoMap[circleInfo] = handle; - m_styles[handle] = shared_ptr(new GenericStyle(texRect, m_pipelineID) ); + m2::RectU texRect = m_packer.find(handle).second; + + shared_ptr circleStyle(new CircleStyle(texRect, m_pipelineID, circleInfo)); + + m_styles[handle] = circleStyle; + m_uploadQueue.push_back(circleStyle); return m_circleInfoMap[circleInfo]; } bool SkinPage::hasRoom(CircleInfo const & circleInfo) const { - unsigned r = circleInfo.m_isOutlined ? circleInfo.m_radius + circleInfo.m_outlineWidth : circleInfo.m_radius; - return m_packer.hasRoom(r * 2 + 4, - r * 2 + 4); + m2::PointU sz = circleInfo.patternSize(); + return m_packer.hasRoom(sz.x, sz.y); } uint32_t SkinPage::findPenInfo(PenInfo const & penInfo) const @@ -320,15 +270,19 @@ namespace yg m2::PointU p = penInfo.patternSize(); m2::Packer::handle_t handle = m_packer.pack(p.x, p.y); - m2::RectU texRect = m_packer.find(handle).second; - m_penUploadCommands.push_back(PenUploadCmd(penInfo, texRect)); + m_penInfoMap[penInfo] = handle; - m_styles[handle] = boost::shared_ptr( - new LineStyle(false, - texRect, - m_pipelineID, - penInfo)); + m2::RectU texRect = m_packer.find(handle).second; + + boost::shared_ptr lineStyle( + new LineStyle(false, + texRect, + m_pipelineID, + penInfo)); + + m_styles[handle] = lineStyle; + m_uploadQueue.push_back(lineStyle); return m_penInfoMap[penInfo]; } @@ -344,406 +298,9 @@ namespace yg return m_usage; } - void SkinPage::uploadPenInfo() - { - for (size_t i = 0; i < m_penUploadCommands.size(); ++i) - { - yg::PenInfo const & penInfo = m_penUploadCommands[i].m_penInfo; - m2::RectU const & rect = m_penUploadCommands[i].m_rect; - - TDynamicTexture * dynTexture = static_cast(m_texture.get()); - - TDynamicTexture::view_t v = dynTexture->view(rect.SizeX(), rect.SizeY()); - - yg::Color penInfoColor = penInfo.m_color; - - penInfoColor /= TDynamicTexture::channelScaleFactor; - - TDynamicTexture::pixel_t penColorTranslucent; - - gil::get_color(penColorTranslucent, gil::red_t()) = penInfoColor.r; - gil::get_color(penColorTranslucent, gil::green_t()) = penInfoColor.g; - gil::get_color(penColorTranslucent, gil::blue_t()) = penInfoColor.b; - gil::get_color(penColorTranslucent, gil::alpha_t()) = 0; - - TDynamicTexture::pixel_t penColor = penColorTranslucent; - gil::get_color(penColor, gil::alpha_t()) = penInfoColor.a; - - if (penInfo.m_isSolid) - { - /// draw circle - agg::rendering_buffer buf( - (unsigned char *)&v(0, 0), - rect.SizeX(), - rect.SizeY(), - rect.SizeX() * sizeof(TDynamicTexture::pixel_t) - ); - - typedef AggTraits::pixfmt_t agg_pixfmt_t; - - agg_pixfmt_t pixfmt(buf); - agg::renderer_base rbase(pixfmt); - - gil::fill_pixels(v, penColorTranslucent); - - agg::scanline_u8 s; - agg::rasterizer_scanline_aa<> rasterizer; - if (penInfo.m_w > 2) - { - agg::ellipse ell; - float r = ceil(penInfo.m_w) / 2.0; - ell.init(r + 2, r + 2, r, r, 100); - rasterizer.add_path(ell); - - agg::render_scanlines_aa_solid(rasterizer, - s, - rbase, - agg::rgba8(penInfo.m_color.r, - penInfo.m_color.g, - penInfo.m_color.b, - penInfo.m_color.a)); - - uint32_t ri = static_cast(r); - - /// pixels that are used to texture inner part of the line should be fully opaque - v(2 + ri - 1, 2) = penColor; - v(2 + ri , 2) = penColor; - v(2 + ri - 1, 2 + ri * 2 - 1) = penColor; - v(2 + ri , 2 + ri * 2 - 1) = penColor; - - /// in non-transparent areas - premultiply color value with alpha and make it opaque - for (size_t x = 2; x < v.width() - 2; ++x) - for (size_t y = 2; y < v.height() - 2; ++y) - { - unsigned char alpha = gil::get_color(v(x, y), gil::alpha_t()); - if (alpha != 0) - { - v(x, y) = penColor; -// if (m_fillAlpha) -// gil::get_color(v(x, y), gil::alpha_t()) = alpha; - } - } - } - else - { - gil::fill_pixels( - gil::subimage_view(v, 2, 2, rect.SizeX() - 4, rect.SizeY() - 4), - penColor - ); - } - } - else - { - /// First two and last two rows of a pattern are filled - /// with a penColorTranslucent pixel for the antialiasing. - for (size_t y = 0; y < 2; ++y) - for (size_t x = 0; x < rect.SizeX(); ++x) - v(x, y) = penColorTranslucent; - - for (size_t y = rect.SizeY() - 2; y < rect.SizeY(); ++y) - for (size_t x = 0; x < rect.SizeX(); ++x) - v(x, y) = penColorTranslucent; - - /// first and last two pixels filled with penColorTranslucent - for (size_t y = 2; y < rect.SizeY() - 2; ++y) - { - v(0, y) = penColorTranslucent; - v(1, y) = penColorTranslucent; - v(rect.SizeX() - 2, y) = penColorTranslucent; - v(rect.SizeX() - 1, y) = penColorTranslucent; - } - - /// draw pattern - for (size_t y = 2; y < rect.SizeY() - 2; ++y) - { - double curLen = 0; - - TDynamicTexture::pixel_t px = penColor; - - /// In general case this code is incorrect. - /// TODO : Make a pattern start and end with a dash. - uint32_t curLenI = static_cast(curLen); - - v(curLenI, y) = px; - v(curLenI + 1, y) = px; - - for (size_t i = 0; i < penInfo.m_pat.size(); ++i) - { - for (size_t j = 0; j < penInfo.m_pat[i]; ++j) - { - uint32_t val = (i + 1) % 2; - - if (val == 0) - gil::get_color(px, gil::alpha_t()) = 0; - else - gil::get_color(px, gil::alpha_t()) = penInfoColor.a; - - v(curLenI + j + 2, y) = px; - } - - v(static_cast(curLen + 2 + penInfo.m_pat[i]), y) = px; - v(static_cast(curLen + 2 + penInfo.m_pat[i] + 1), y) = px; - - curLen += penInfo.m_pat[i]; - - curLenI = static_cast(curLen); - } - } - } - - dynTexture->upload(&v(0, 0), rect); - - } - m_penUploadCommands.clear(); - } - - void SkinPage::uploadCircleInfo() - { - for (size_t i = 0; i < m_circleUploadCommands.size(); ++i) - { - yg::CircleInfo & circleInfo = m_circleUploadCommands[i].m_circleInfo; - m2::RectU const & rect = m_circleUploadCommands[i].m_rect; - - TDynamicTexture * dynTexture = static_cast(m_texture.get()); - - TDynamicTexture::view_t v = dynTexture->view(rect.SizeX(), rect.SizeY()); - - agg::rgba8 aggColor(circleInfo.m_color.r, - circleInfo.m_color.g, - circleInfo.m_color.b, - circleInfo.m_color.a); - - agg::rgba8 aggOutlineColor(circleInfo.m_outlineColor.r, - circleInfo.m_outlineColor.g, - circleInfo.m_outlineColor.b, - circleInfo.m_outlineColor.a); - - circleInfo.m_color /= TDynamicTexture::channelScaleFactor; - - TDynamicTexture::pixel_t gilColorTranslucent; - - gil::get_color(gilColorTranslucent, gil::red_t()) = circleInfo.m_color.r; - gil::get_color(gilColorTranslucent, gil::green_t()) = circleInfo.m_color.g; - gil::get_color(gilColorTranslucent, gil::blue_t()) = circleInfo.m_color.b; - gil::get_color(gilColorTranslucent, gil::alpha_t()) = 0; - - circleInfo.m_outlineColor /= TDynamicTexture::channelScaleFactor; - - TDynamicTexture::pixel_t gilOutlineColorTranslucent; - - gil::get_color(gilOutlineColorTranslucent, gil::red_t()) = circleInfo.m_outlineColor.r; - gil::get_color(gilOutlineColorTranslucent, gil::green_t()) = circleInfo.m_outlineColor.g; - gil::get_color(gilOutlineColorTranslucent, gil::blue_t()) = circleInfo.m_outlineColor.b; - gil::get_color(gilOutlineColorTranslucent, gil::alpha_t()) = 0; - - TDynamicTexture::pixel_t gilColor = gilColorTranslucent; - gil::get_color(gilColor, gil::alpha_t()) = circleInfo.m_color.a; - - TDynamicTexture::pixel_t gilOutlineColor = gilOutlineColorTranslucent; - gil::get_color(gilOutlineColor, gil::alpha_t()) = circleInfo.m_outlineColor.a; - - /// draw circle - agg::rendering_buffer buf( - (unsigned char *)&v(0, 0), - rect.SizeX(), - rect.SizeY(), - rect.SizeX() * sizeof(TDynamicTexture::pixel_t) - ); - - typedef AggTraits::pixfmt_t agg_pixfmt_t; - - agg_pixfmt_t pixfmt(buf); - agg::renderer_base rbase(pixfmt); - - if (circleInfo.m_isOutlined) - gil::fill_pixels(v, gilOutlineColorTranslucent); - else - gil::fill_pixels(v, gilColorTranslucent); - - m2::PointD center(circleInfo.m_radius + 2, circleInfo.m_radius + 2); - - if (circleInfo.m_isOutlined) - center += m2::PointD(circleInfo.m_outlineWidth, circleInfo.m_outlineWidth); - - agg::scanline_u8 s; - agg::rasterizer_scanline_aa<> rasterizer; - - agg::ellipse ell; - - ell.init(center.x, - center.y, - circleInfo.m_isOutlined ? circleInfo.m_radius + circleInfo.m_outlineWidth : circleInfo.m_radius, - circleInfo.m_isOutlined ? circleInfo.m_radius + circleInfo.m_outlineWidth : circleInfo.m_radius, - 100); - - rasterizer.add_path(ell); - - agg::render_scanlines_aa_solid(rasterizer, - s, - rbase, - circleInfo.m_isOutlined ? aggOutlineColor : aggColor); - - TDynamicTexture::pixel_t px = circleInfo.m_isOutlined ? gilOutlineColor : gilColor; - - /// making alpha channel opaque -/* for (size_t x = 2; x < v.width() - 2; ++x) - for (size_t y = 2; y < v.height() - 2; ++y) - { - unsigned char alpha = gil::get_color(v(x, y), gil::alpha_t()); - - float fAlpha = alpha / (float)TDynamicTexture::maxChannelVal; - - if (alpha != 0) - { - gil::get_color(v(x, y), gil::red_t()) *= fAlpha; - gil::get_color(v(x, y), gil::green_t()) *= fAlpha; - gil::get_color(v(x, y), gil::blue_t()) *= fAlpha; - - gil::get_color(v(x, y), gil::alpha_t()) = TDynamicTexture::maxChannelVal; - } - } - */ - if (circleInfo.m_isOutlined) - { - /// drawing inner circle - ell.init(center.x, - center.y, - circleInfo.m_radius, - circleInfo.m_radius, - 100); - - rasterizer.reset(); - rasterizer.add_path(ell); - - agg::render_scanlines_aa_solid(rasterizer, - s, - rbase, - aggColor); -/* for (size_t x = 2; x < v.width() - 2; ++x) - for (size_t y = 2; y < v.height() - 2; ++y) - { - unsigned char alpha = gil::get_color(v(x, y), gil::alpha_t()); - float fAlpha = alpha / (float)TDynamicTexture::maxChannelVal; -// if (alpha != 0) -// { - gil::get_color(v(x, y), gil::red_t()) *= fAlpha; - gil::get_color(v(x, y), gil::green_t()) *= fAlpha; - gil::get_color(v(x, y), gil::blue_t()) *= fAlpha; - -// gil::get_color(v(x, y), gil::alpha_t()) = TDynamicTexture::maxChannelVal; -// } - }*/ - } - - dynTexture->upload(&v(0, 0), rect); - } - - m_circleUploadCommands.clear(); - } - - void SkinPage::uploadGlyphs() - { - for (size_t i = 0; i < m_glyphUploadCommands.size(); ++i) - { - shared_ptr const & gi = m_glyphUploadCommands[i].m_glyphInfo; - m2::RectU const & rect = m_glyphUploadCommands[i].m_rect; - - TDynamicTexture * dynTexture = static_cast(m_texture.get()); - - TDynamicTexture::view_t v = dynTexture->view(rect.SizeX(), rect.SizeY()); - - TDynamicTexture::pixel_t pxTranslucent; - gil::get_color(pxTranslucent, gil::red_t()) = gi->m_color.r / TDynamicTexture::channelScaleFactor; - gil::get_color(pxTranslucent, gil::green_t()) = gi->m_color.g / TDynamicTexture::channelScaleFactor; - gil::get_color(pxTranslucent, gil::blue_t()) = gi->m_color.b / TDynamicTexture::channelScaleFactor; - gil::get_color(pxTranslucent, gil::alpha_t()) = 0; - - for (size_t y = 0; y < 2; ++y) - for (size_t x = 0; x < rect.SizeX(); ++x) - v(x, y) = pxTranslucent; - - for (size_t y = rect.SizeY() - 2; y < rect.SizeY(); ++y) - for (size_t x = 0; x < rect.SizeX(); ++x) - v(x, y) = pxTranslucent; - - for (size_t y = 2; y < rect.SizeY() - 2; ++y) - { - v(0, y) = pxTranslucent; - v(1, y) = pxTranslucent; - v(rect.SizeX() - 2, y) = pxTranslucent; - v(rect.SizeX() - 1, y) = pxTranslucent; - } - - if ((gi->m_metrics.m_width != 0) && (gi->m_metrics.m_height != 0)) - { - gil::gray8c_view_t srcView = gil::interleaved_view( - gi->m_metrics.m_width, - gi->m_metrics.m_height, - (gil::gray8_pixel_t*)gi->m_bitmapData, - gi->m_bitmapPitch - ); - -/* TDynamicTexture::const_view_t srcView = gil::interleaved_view( - gi->m_metrics.m_width, - gi->m_metrics.m_height, - (TDynamicTexture::pixel_t*)&gi->m_bitmap[0], - gi->m_metrics.m_width * sizeof(TDynamicTexture::pixel_t) - );*/ - - DATA_TRAITS::pixel_t c; - - gil::get_color(c, gil::red_t()) = gi->m_color.r / DATA_TRAITS::channelScaleFactor; - gil::get_color(c, gil::green_t()) = gi->m_color.g / DATA_TRAITS::channelScaleFactor; - gil::get_color(c, gil::blue_t()) = gi->m_color.b / DATA_TRAITS::channelScaleFactor; - gil::get_color(c, gil::alpha_t()) = gi->m_color.a / DATA_TRAITS::channelScaleFactor; - - for (size_t y = 2; y < rect.SizeY() - 2; ++y) - for (size_t x = 2; x < rect.SizeX() - 2; ++x) - { - gil::get_color(c, gil::alpha_t()) = srcView(x - 2, y - 2) / DATA_TRAITS::channelScaleFactor; - v(x, y) = c; - } - } - - dynTexture->upload(&v(0, 0), rect); - } - - m_glyphUploadCommands.clear(); - } - - void SkinPage::uploadColors() - { - for (size_t i = 0; i < m_colorUploadCommands.size(); ++i) - { - yg::Color c = m_colorUploadCommands[i].m_color; - m2::RectU const & r = m_colorUploadCommands[i].m_rect; - - TDynamicTexture::pixel_t px; - - gil::get_color(px, gil::red_t()) = c.r / TDynamicTexture::channelScaleFactor; - gil::get_color(px, gil::green_t()) = c.g / TDynamicTexture::channelScaleFactor; - gil::get_color(px, gil::blue_t()) = c.b / TDynamicTexture::channelScaleFactor; - gil::get_color(px, gil::alpha_t()) = c.a / TDynamicTexture::channelScaleFactor; - - TDynamicTexture * dynTexture = static_cast(m_texture.get()); - - TDynamicTexture::view_t v = dynTexture->view(r.SizeX(), r.SizeY()); - - for (size_t y = 0; y < r.SizeY(); ++y) - for (size_t x = 0; x < r.SizeX(); ++x) - v(x, y) = px; - - dynTexture->upload(&v(0, 0), r); - } - m_colorUploadCommands.clear(); - } - bool SkinPage::hasData() { - return ((!m_colorUploadCommands.empty()) - || (!m_penUploadCommands.empty()) - || (!m_glyphUploadCommands.empty()) - || (!m_circleUploadCommands.empty())); + return !m_uploadQueue.empty(); } void SkinPage::checkTexture() const @@ -765,10 +322,23 @@ namespace yg { checkTexture(); static_cast(m_texture.get())->lock(); - uploadColors(); - uploadPenInfo(); - uploadGlyphs(); - uploadCircleInfo(); + + TDynamicTexture * dynTexture = static_cast(m_texture.get()); + + for (size_t i = 0; i < m_uploadQueue.size(); ++i) + { + shared_ptr const & style = m_uploadQueue[i]; + + TDynamicTexture::view_t v = dynTexture->view(style->m_texRect.SizeX(), + style->m_texRect.SizeY()); + + style->render(&v(0, 0)); + + dynTexture->upload(&v(0, 0), style->m_texRect); + } + + m_uploadQueue.clear(); + static_cast(m_texture.get())->unlock(); } } diff --git a/yg/skin_page.hpp b/yg/skin_page.hpp index fba0478d42..d93a1a2567 100644 --- a/yg/skin_page.hpp +++ b/yg/skin_page.hpp @@ -17,47 +17,15 @@ namespace yg class BaseTexture; } - struct CharStyle; + struct GlyphStyle; struct ResourceStyle; class ResourceManager; struct GlyphInfo; - struct GlyphUploadCmd - { - shared_ptr m_glyphInfo; - m2::RectU m_rect; - GlyphUploadCmd(shared_ptr const & glyphInfo, m2::RectU const & rect); - GlyphUploadCmd(); - }; - - struct ColorUploadCmd - { - yg::Color m_color; - m2::RectU m_rect; - ColorUploadCmd(yg::Color const & color, m2::RectU const & rect); - ColorUploadCmd(); - }; - - struct PenUploadCmd - { - yg::PenInfo m_penInfo; - m2::RectU m_rect; - PenUploadCmd(yg::PenInfo const & penInfo, m2::RectU const & rect); - PenUploadCmd(); - }; - - struct CircleUploadCmd - { - yg::CircleInfo m_circleInfo; - m2::RectU m_rect; - CircleUploadCmd(yg::CircleInfo const & circleInfo, m2::RectU const & rect); - CircleUploadCmd(); - }; - struct FontInfo { int8_t m_fontSize; - typedef map, shared_ptr > > TChars; + typedef map, shared_ptr > > TChars; TChars m_chars; mutable pair m_invalidChar; @@ -106,17 +74,9 @@ namespace yg mutable shared_ptr m_resourceManager; /// @} - vector m_colorUploadCommands; - vector m_penUploadCommands; - vector m_glyphUploadCommands; - vector m_circleUploadCommands; + vector > m_uploadQueue; - void uploadPenInfo(); - void uploadColors(); - void uploadGlyphs(); - void uploadCircleInfo(); - - void clearUploadCommands(); + void clearUploadQueue(); typedef vector TFonts; TFonts m_fonts; diff --git a/yg/symbol_element.cpp b/yg/symbol_element.cpp index 7781088ab3..5d29366b91 100644 --- a/yg/symbol_element.cpp +++ b/yg/symbol_element.cpp @@ -1,4 +1,3 @@ -#include "../base/SRC_FIRST.hpp" #include "../base/logging.hpp" #include "symbol_element.hpp" diff --git a/yg/symbol_element.hpp b/yg/symbol_element.hpp index cb45cb3f64..aa93b9d77e 100644 --- a/yg/symbol_element.hpp +++ b/yg/symbol_element.hpp @@ -1,7 +1,6 @@ #pragma once #include "overlay_element.hpp" -#include "text_element.hpp" namespace yg { diff --git a/yg/text_element.cpp b/yg/text_element.cpp index f67f4fe467..e17fc5347d 100644 --- a/yg/text_element.cpp +++ b/yg/text_element.cpp @@ -75,7 +75,7 @@ namespace yg fontDesc.m_isMasked, fontDesc.m_isMasked ? fontDesc.m_maskColor : fontDesc.m_color); uint32_t const glyphID = skin->mapGlyph(glyphKey, screen->glyphCache()); - CharStyle const * charStyle = static_cast(skin->fromID(glyphID)); + GlyphStyle const * glyphStyle = static_cast(skin->fromID(glyphID)); m2::PointD glyphPt; ang::AngleD glyphAngle; @@ -91,7 +91,7 @@ namespace yg glyphAngle = ang::AngleD(elem.m_angle.val() + deltaA); } - screen->drawGlyph(glyphPt, m2::PointD(0.0, 0.0), glyphAngle, 0, charStyle, depth); + screen->drawGlyph(glyphPt, m2::PointD(0.0, 0.0), glyphAngle, 0, glyphStyle, depth); } } diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index d885876b1b..46efdf9fc0 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -28,10 +28,10 @@ namespace yg {} - void TextRenderer::drawGlyph(m2::PointD const & ptOrg, m2::PointD const & ptGlyph, ang::AngleD const & angle, float /*blOffset*/, CharStyle const * p, double depth) + void TextRenderer::drawGlyph(m2::PointD const & ptOrg, m2::PointD const & ptGlyph, ang::AngleD const & angle, float /*blOffset*/, GlyphStyle const * p, double depth) { - float x0 = ptGlyph.x + (p->m_xOffset - 1); - float y1 = ptGlyph.y - (p->m_yOffset - 1); + float x0 = ptGlyph.x + (p->m_gi->m_metrics.m_xOffset - 1); + float y1 = ptGlyph.y - (p->m_gi->m_metrics.m_yOffset - 1); float y0 = y1 - (p->m_texRect.SizeY() - 2); float x1 = x0 + (p->m_texRect.SizeX() - 2); diff --git a/yg/text_renderer.hpp b/yg/text_renderer.hpp index fc513446d5..99da201a9c 100644 --- a/yg/text_renderer.hpp +++ b/yg/text_renderer.hpp @@ -38,7 +38,7 @@ namespace yg m2::PointD const & ptGlyph, ang::AngleD const & angle, float blOffset, - CharStyle const * p, + GlyphStyle const * p, double depth); diff --git a/yg/yg.pro b/yg/yg.pro index 13c2ad0ab8..85df6c52af 100644 --- a/yg/yg.pro +++ b/yg/yg.pro @@ -57,7 +57,11 @@ SOURCES += \ composite_overlay_element.cpp \ path_text_element.cpp \ straight_text_element.cpp \ - rendercontext.cpp + rendercontext.cpp \ + line_style.cpp \ + circle_style.cpp \ + glyph_style.cpp \ + circle_element.cpp HEADERS += \ internal/opengl.hpp \ @@ -110,17 +114,11 @@ HEADERS += \ styles_cache.hpp \ composite_overlay_element.hpp \ path_text_element.hpp \ - straight_text_element.hpp + straight_text_element.hpp \ + agg_traits.hpp \ + circle_element.hpp win32 { HEADERS += internal/opengl_win32.hpp SOURCES += internal/opengl_win32.cpp } - - - - - - - -