introduced CircleElement. fixes #363.

This commit is contained in:
rachytski 2011-10-26 17:37:45 +03:00 committed by Alex Zolotarev
parent dcfef49bae
commit 93d0eb1570
24 changed files with 759 additions and 716 deletions

View file

@ -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)

27
yg/agg_traits.hpp Normal file
View file

@ -0,0 +1,27 @@
#pragma once
#include <agg_pixfmt_rgba.h>
#include <agg_pixfmt_rgb_packed.h>
#include <agg_renderer_scanline.h>
#include <agg_rasterizer_scanline_aa.h>
#include <agg_scanline_u.h>
#include <agg_ellipse.h>
#include "data_formats.hpp"
template <typename Traits>
struct AggTraits
{
};
template <>
struct AggTraits<yg::RGBA8Traits>
{
typedef agg::pixfmt_rgba32 pixfmt_t;
};
template <>
struct AggTraits<yg::RGBA4Traits>
{
typedef agg::pixfmt_rgb4444 pixfmt_t;
};

99
yg/circle_element.cpp Normal file
View file

@ -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<double, 3, 3> const & m)
: base_t(ce),
m_ci(ce.m_ci)
{
setPivot(ce.pivot() * m);
}
vector<m2::AnyRectD> 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<double, 3>());
return m2::AnyRectD(m2::RectD(posPt, posPt + m2::PointD(texRect.SizeX(), texRect.SizeY())));
}
void CircleElement::draw(gl::OverlayRenderer * r, math::Matrix<double, 3, 3> 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<SkinPage> const & skinPage = stylesCache->cachePage();
ASSERT(skinPage->hasRoom(m_ci), ());
skinPage->mapCircleInfo(m_ci);
}
bool CircleElement::find(StylesCache * stylesCache) const
{
shared_ptr<SkinPage> const & skinPage = stylesCache->cachePage();
return skinPage->findCircleInfo(m_ci) != 0x00FFFFFF;
}
void CircleElement::fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const
{
shared_ptr<SkinPage> const & skinPage = stylesCache->cachePage();
if (skinPage->findCircleInfo(m_ci) == 0x00FFFFFF)
v.push_back(m_ci.patternSize());
}
OverlayElement * CircleElement::clone(math::Matrix<double, 3, 3> const & m) const
{
return new CircleElement(*this, m);
}
}

42
yg/circle_element.hpp Normal file
View file

@ -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<m2::AnyRectD> 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<double, 3, 3> const & m);
vector<m2::AnyRectD> const & boundRects() const;
void draw(gl::OverlayRenderer * s, math::Matrix<double, 3, 3> const & m) const;
void map(StylesCache * stylesCache) const;
void fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const;
bool find(StylesCache * stylesCache) const;
int visualRank() const;
OverlayElement * clone(math::Matrix<double, 3, 3> const & m) const;
};
}

View file

@ -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);
}
}

View file

@ -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);

149
yg/circle_style.cpp Normal file
View file

@ -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<DATA_TRAITS>::pixfmt_t agg_pixfmt_t;
agg_pixfmt_t pixfmt(buf);
agg::renderer_base<agg_pixfmt_t> 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;
// }
}*/
}
}
}

View file

@ -26,7 +26,6 @@ namespace threads
namespace yg
{
class Skin;
struct CharStyle;
namespace gl
{

77
yg/glyph_style.cpp Normal file
View file

@ -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<GlyphInfo> const & gi)
: ResourceStyle(EGlyphStyle, texRect, pipelineID), m_gi(gi)
{}
void GlyphStyle::render(void * dst)
{
shared_ptr<GlyphInfo> 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;
}
}
}
}

194
yg/line_style.cpp Normal file
View file

@ -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<uint32_t>(firstDashOffset + texRect.minX() + 3),
static_cast<uint32_t>(texRect.minY() + texRect.SizeY() / 2.0));
m_borderColorPixel = m2::PointU(static_cast<uint32_t>(firstDashOffset + texRect.minX() + 3),
static_cast<uint32_t>(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<DATA_TRAITS>::pixfmt_t agg_pixfmt_t;
agg_pixfmt_t pixfmt(buf);
agg::renderer_base<agg_pixfmt_t> 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<uint32_t>(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<uint32_t>(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<uint32_t>(curLen + 2 + penInfo.m_pat[i]), y) = px;
v(static_cast<uint32_t>(curLen + 2 + penInfo.m_pat[i] + 1), y) = px;
curLen += penInfo.m_pat[i];
curLenI = static_cast<uint32_t>(curLen);
}
}
}
}
}

View file

@ -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<OverlayElement> oe(new CircleElement(params));
math::Matrix<double, 3, 3> id = math::Identity<double, 3>();
se.draw(this, id);
if (!m_infoLayer.get())
oe->draw(this, id);
else
m_infoLayer->processOverlayElement(oe);
}
void OverlayRenderer::drawText(FontDesc const & fontDesc,

View file

@ -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,

View file

@ -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<uint32_t>(firstDashOffset + texRect.minX() + 3),
static_cast<uint32_t>(texRect.minY() + texRect.SizeY() / 2.0));
m_borderColorPixel = m2::PointU(static_cast<uint32_t>(firstDashOffset + texRect.minX() + 3),
static_cast<uint32_t>(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;
}
}

View file

@ -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<GlyphInfo> m_gi;
GlyphStyle(m2::RectU const & texRect, int pipelineID, shared_ptr<GlyphInfo> 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);
};
}

View file

@ -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<CharStyle>(new CharStyle(m_texRect, m_pages.size(), m_xOffset, m_yOffset, m_xAdvance));
}
void SkinLoader::popGlyphMaskInfo()
{
m_glyphMaskInfo = shared_ptr<CharStyle>(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);

View file

@ -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<EMode> m_mode;
@ -70,23 +66,13 @@ namespace yg
uint32_t m_texHeight;
m2::RectU m_texRect;
/// fontInfo-specific parameters
typedef map<int32_t, pair<shared_ptr<CharStyle>, shared_ptr<CharStyle> > > TChars;
TChars m_chars;
typedef map<int8_t, TChars> 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<CharStyle> m_glyphInfo;
shared_ptr<CharStyle> m_glyphMaskInfo;
shared_ptr<GlyphStyle> m_glyphInfo;
shared_ptr<GlyphStyle> 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();
};
}

View file

@ -1,13 +1,7 @@
#include <agg_pixfmt_rgba.h>
#include <agg_pixfmt_rgb_packed.h>
#include <agg_renderer_scanline.h>
#include <agg_rasterizer_scanline_aa.h>
#include <agg_scanline_u.h>
#include <agg_ellipse.h>
#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 <typename Traits>
struct AggTraits
{
};
template <>
struct AggTraits<yg::RGBA8Traits>
{
typedef agg::pixfmt_rgba32 pixfmt_t;
};
template <>
struct AggTraits<yg::RGBA4Traits>
{
typedef agg::pixfmt_rgb4444 pixfmt_t;
};
namespace yg
{
typedef gl::Texture<DATA_TRAITS, true> TDynamicTexture;
GlyphUploadCmd::GlyphUploadCmd(){}
GlyphUploadCmd::GlyphUploadCmd(shared_ptr<GlyphInfo> 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<ResourceStyle>(new GenericStyle(texRect, m_pipelineID));
m2::RectU texRect = m_packer.find(h).second;
shared_ptr<ResourceStyle> 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<ResourceStyle>(
new CharStyle(texRect,
boost::shared_ptr<ResourceStyle> 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<ResourceStyle>(new GenericStyle(texRect, m_pipelineID) );
m2::RectU texRect = m_packer.find(handle).second;
shared_ptr<ResourceStyle> 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<ResourceStyle>(
new LineStyle(false,
texRect,
m_pipelineID,
penInfo));
m2::RectU texRect = m_packer.find(handle).second;
boost::shared_ptr<ResourceStyle> 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<TDynamicTexture*>(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<TDynamicTexture::traits_t>::pixfmt_t agg_pixfmt_t;
agg_pixfmt_t pixfmt(buf);
agg::renderer_base<agg_pixfmt_t> 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<uint32_t>(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<uint32_t>(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<uint32_t>(curLen + 2 + penInfo.m_pat[i]), y) = px;
v(static_cast<uint32_t>(curLen + 2 + penInfo.m_pat[i] + 1), y) = px;
curLen += penInfo.m_pat[i];
curLenI = static_cast<uint32_t>(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<TDynamicTexture*>(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<TDynamicTexture::traits_t>::pixfmt_t agg_pixfmt_t;
agg_pixfmt_t pixfmt(buf);
agg::renderer_base<agg_pixfmt_t> 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<GlyphInfo> const & gi = m_glyphUploadCommands[i].m_glyphInfo;
m2::RectU const & rect = m_glyphUploadCommands[i].m_rect;
TDynamicTexture * dynTexture = static_cast<TDynamicTexture*>(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<TDynamicTexture*>(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<gl::ManagedTexture*>(m_texture.get())->lock();
uploadColors();
uploadPenInfo();
uploadGlyphs();
uploadCircleInfo();
TDynamicTexture * dynTexture = static_cast<TDynamicTexture*>(m_texture.get());
for (size_t i = 0; i < m_uploadQueue.size(); ++i)
{
shared_ptr<ResourceStyle> 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<gl::ManagedTexture*>(m_texture.get())->unlock();
}
}

View file

@ -17,47 +17,15 @@ namespace yg
class BaseTexture;
}
struct CharStyle;
struct GlyphStyle;
struct ResourceStyle;
class ResourceManager;
struct GlyphInfo;
struct GlyphUploadCmd
{
shared_ptr<GlyphInfo> m_glyphInfo;
m2::RectU m_rect;
GlyphUploadCmd(shared_ptr<GlyphInfo> 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<int32_t, pair<shared_ptr<CharStyle>, shared_ptr<CharStyle> > > TChars;
typedef map<int32_t, pair<shared_ptr<GlyphStyle>, shared_ptr<GlyphStyle> > > TChars;
TChars m_chars;
mutable pair<ResourceStyle *, ResourceStyle *> m_invalidChar;
@ -106,17 +74,9 @@ namespace yg
mutable shared_ptr<ResourceManager> m_resourceManager;
/// @}
vector<ColorUploadCmd> m_colorUploadCommands;
vector<PenUploadCmd> m_penUploadCommands;
vector<GlyphUploadCmd> m_glyphUploadCommands;
vector<CircleUploadCmd> m_circleUploadCommands;
vector<shared_ptr<ResourceStyle> > m_uploadQueue;
void uploadPenInfo();
void uploadColors();
void uploadGlyphs();
void uploadCircleInfo();
void clearUploadCommands();
void clearUploadQueue();
typedef vector<FontInfo> TFonts;
TFonts m_fonts;

View file

@ -1,4 +1,3 @@
#include "../base/SRC_FIRST.hpp"
#include "../base/logging.hpp"
#include "symbol_element.hpp"

View file

@ -1,7 +1,6 @@
#pragma once
#include "overlay_element.hpp"
#include "text_element.hpp"
namespace yg
{

View file

@ -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<CharStyle const *>(skin->fromID(glyphID));
GlyphStyle const * glyphStyle = static_cast<GlyphStyle const *>(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);
}
}

View file

@ -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);

View file

@ -38,7 +38,7 @@ namespace yg
m2::PointD const & ptGlyph,
ang::AngleD const & angle,
float blOffset,
CharStyle const * p,
GlyphStyle const * p,
double depth);

View file

@ -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
}