1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
#pragma once
#include "path_info.hpp"
#include "area_info.hpp"
#include "frame_image.hpp"
#include "text_engine.h"
#include "geometry/point2d.hpp"
#include "graphics/icon.hpp"
#include "graphics/circle.hpp"
#include "graphics/glyph_cache.hpp"
#include "graphics/pen.hpp"
#include "graphics/brush.hpp"
#include "graphics/font_desc.hpp"
#include "base/string_utils.hpp"
#include "3party/agg/agg_rendering_buffer.h"
#include "3party/agg/agg_pixfmt_rgba.h"
#include "3party/agg/agg_renderer_scanline.h"
#include "3party/agg/agg_renderer_primitives.h"
#include "3party/agg/agg_path_storage.h"
#include "std/stdint.hpp"
#include "std/unique_ptr.hpp"
class PathWrapper;
class SoftwareRenderer
{
public:
SoftwareRenderer(graphics::GlyphCache::Params const & glyphCacheParams, graphics::EDensity density);
void BeginFrame(uint32_t width, uint32_t height);
void DrawSymbol(m2::PointD const & pt, graphics::EPosition anchor,
graphics::Icon::Info const & info);
void DrawCircle(m2::PointD const & pt, graphics::EPosition anchor,
graphics::Circle::Info const & info);
void DrawPath(di::PathInfo const & geometry, graphics::Pen::Info const & info);
void DrawPath(PathWrapper & path, math::Matrix<double, 3, 3> const & m);
void DrawArea(di::AreaInfo const & geometry, graphics::Brush::Info const & info);
void DrawText(m2::PointD const & pt, graphics::EPosition anchor,
graphics::FontDesc const & primFont, strings::UniString const & primText);
void DrawText(m2::PointD const & pt, graphics::EPosition anchor,
graphics::FontDesc const & primFont, graphics::FontDesc const & secFont,
strings::UniString const & primText, strings::UniString const & secText);
void DrawPathText(di::PathInfo const & geometry, graphics::FontDesc const & font,
strings::UniString const & text);
void CalculateSymbolMetric(m2::PointD const & pt, graphics::EPosition anchor,
graphics::Icon::Info const & info, m2::RectD & rect);
void CalculateCircleMetric(m2::PointD const & pt, graphics::EPosition anchor,
graphics::Circle::Info const & info, m2::RectD & rect);
void CalculateTextMetric(m2::PointD const & pt, graphics::EPosition anchor,
graphics::FontDesc const & font, strings::UniString const & text,
m2::RectD & result);
/// Result must be bound box contains both texts
void CalculateTextMetric(m2::PointD const & pt, graphics::EPosition anchor,
graphics::FontDesc const & primFont, graphics::FontDesc const & secFont,
strings::UniString const & primText, strings::UniString const & secText,
m2::RectD & result);
/// rects - rect for each glyph
void CalculateTextMetric(di::PathInfo const & geometry, graphics::FontDesc const & font,
strings::UniString const & text,
vector<m2::RectD> & rects);
void EndFrame(FrameImage & image);
m2::RectD FrameRect() const;
graphics::GlyphCache * GetGlyphCache() { return m_glyphCache.get(); }
private:
template <class TColor, class TOrder>
struct TBlendAdaptor
{
using order_type = TOrder;
using color_type = TColor;
using TValueType = typename color_type::value_type;
using TCalcType = typename color_type::calc_type;
enum EBaseScale
{
SCALE_SHIFT = color_type::base_shift,
SCALE_MASK = color_type::base_mask
};
static AGG_INLINE void blend_pix(unsigned op, TValueType * p, unsigned cr, unsigned cg,
unsigned cb, unsigned ca, unsigned cover)
{
using TBlendTable = agg::comp_op_table_rgba<TColor, TOrder>;
if (p[TOrder::A])
{
TBlendTable::g_comp_op_func[op](p, (cr * ca + SCALE_MASK) >> SCALE_SHIFT, (cg * ca + SCALE_MASK) >> SCALE_SHIFT,
(cb * ca + SCALE_MASK) >> SCALE_SHIFT, ca, cover);
}
else
TBlendTable::g_comp_op_func[op](p, cr, cg, cb, ca, cover);
}
};
public:
using TBlender = TBlendAdaptor<agg::rgba8, agg::order_rgba>;
using TPixelFormat = agg::pixfmt_custom_blend_rgba<TBlender, agg::rendering_buffer>;
using TBaseRenderer = agg::renderer_base<TPixelFormat>;
using TPrimitivesRenderer = agg::renderer_primitives<TBaseRenderer>;
using TSolidRenderer = agg::renderer_scanline_aa_solid<TBaseRenderer>;
private:
unique_ptr<graphics::GlyphCache> m_glyphCache;
map<string, m2::RectU> m_symbolsIndex;
vector<uint8_t> m_symbolsSkin;
uint32_t m_skinWidth, m_skinHeight;
std::vector<unsigned char> m_frameBuffer;
uint32_t m_frameWidth, m_frameHeight;
agg::rendering_buffer m_renderBuffer;
TPixelFormat m_pixelFormat;
TBaseRenderer m_baseRenderer;
TSolidRenderer m_solidRenderer;
ml::text_engine m_textEngine;
};
struct PathParams
{
agg::rgba8 m_fillColor;
agg::rgba8 m_strokeColor;
bool m_isFill;
bool m_isStroke;
bool m_isEventOdd;
double m_strokeWidth;
PathParams()
: m_fillColor(agg::rgba(0, 0, 0))
, m_strokeColor(agg::rgba(0, 0, 0))
, m_isFill(false)
, m_isStroke(false)
, m_isEventOdd(false)
, m_strokeWidth(1.0)
{
}
};
class PathWrapper
{
public:
void AddParams(PathParams const & params);
void MoveTo(m2::PointD const & pt);
void LineTo(m2::PointD const & pt);
void CurveTo(m2::PointD const & pt1,
m2::PointD const & pt2,
m2::PointD const & ptTo);
void ClosePath();
void BoundingRect(m2::RectD & rect);
void Render(SoftwareRenderer::TSolidRenderer & renderer,
agg::trans_affine const & mtx,
m2::RectD const & clipBox);
private:
agg::path_storage m_storage;
vector<PathParams> m_params;
};
|