YSTest: TextRenderer.cpp 源文件

YSTest PreAlpha_b400_20130424 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
TextRenderer.cpp
浏览该文件的文档.
1 ﻿/*
2 Copyright by FrankHB 2009 - 2013.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "YSLib/Service/TextRenderer.h"
29 #include "YSLib/Service/yblit.h"
30 #include "YSLib/Service/TextLayout.h" // for FetchLastLineBasePosition;
31
32 using namespace ystdex;
33
34 YSL_BEGIN
35
36 using namespace Drawing;
37 using namespace Text;
38
39 YSL_BEGIN_NAMESPACE(Drawing)
40
41 namespace
42 {
43
45 PaintContext
46 ClipChar(const Graphics& g, const Point& pen, const CharBitmap& cbmp, Rect r)
47 {
48 YAssert(bool(g), "Invalid graphics context found.");
49
50 const auto pt(ClipBounds(r, Rect(pen.X + cbmp.GetLeft(),
51 pen.Y - cbmp.GetTop(), cbmp.GetWidth(), cbmp.GetHeight())));
52
53 return {g, pt, r};
54 }
55
57 template<typename _tCharRenderer, _tCharRenderer& _fCharRenderer,
58 typename... _tParams>
59 void
60 RenderCharFrom(ucs4_t c, const Graphics& g,
61 TextState& ts, const Rect& clip, _tParams&&... args)
62 {
63 const auto cbmp(ts.Font.GetGlyph(c));
64
65 if(YB_LIKELY(cbmp))
66 {
67 // TODO: Show a special glyph when no bitmap found.
68 // TODO: Use fast glyph advance fetching for non-graph characters
69 // when possible.
70 // TODO: Handle '\t'.
71 if(std::iswgraph(c))
72 if(const auto cbuf = cbmp.GetBuffer())
73 {
74 auto&& pc(ClipChar(g, ts.Pen, cbmp, clip));
75
76 if(!pc.ClipArea.IsUnstrictlyEmpty())
77 _fCharRenderer(std::move(pc), ts.Color, cbuf,
78 {cbmp.GetWidth(), cbmp.GetHeight()}, yforward(args)...);
79 }
80 ts.Pen.X += cbmp.GetXAdvance();
81 }
82 }
83
84 } // unnamed namespace;
85
86 void
87 TextRenderer::operator()(ucs4_t c)
88 {
89 RenderCharFrom<decltype(RenderChar), RenderChar>(c, GetContext(),
90 State, ClipArea);
91 }
92
93 void
94 TextRenderer::ClearLine(u16 l, SDst n)
95 {
96 const auto& g(GetContext());
97 const auto h(g.GetHeight());
98
99 if(YB_LIKELY(bool(g) && l < h))
100 {
101 if(n == 0 || l + n > h)
102 n = h - l;
103 ClearPixel(g[l], g.GetWidth() * n);
104 }
105 }
106
107
108 TextRegion::TextRegion()
109 : GTextRendererBase<TextRegion>(), TextState(), BitmapBufferEx()
110 {
111 InitializeFont();
112 }
113
114 void
115 TextRegion::operator()(ucs4_t c)
116 {
117 RenderCharFrom<decltype(RenderCharAlpha), RenderCharAlpha>(c,
118 TextRegion::GetContext(), GetTextState(), Rect(GetSize())
119 + GetTextState().Margin, GetBufferAlphaPtr());
120 }
121
122 void
123 TextRegion::InitializeFont()
124 {
125 Font.SetSize(Font::DefaultSize);
126 ResetPen();
127 }
128
129 void
130 TextRegion::ClearLine(u16 l, SDst n)
131 {
132 const auto& g(GetContext());
133
134 if(YB_UNLIKELY(l > g.GetHeight()))
135 return;
136 if(!n)
137 --n;
138 if(YB_LIKELY(bool(g) && pBufferAlpha))
139 {
140 const u32 t((l + n > g.GetHeight() ? g.GetHeight() - l : n)
141 * g.GetWidth());
142
143 yunseq(ClearPixel(g[l], t),
144 ClearPixel(&pBufferAlpha[l * g.GetWidth()], t));
145 }
146 }
147
148 void
149 TextRegion::ClearTextLine(u16 l)
150 {
151 auto& ts(GetTextState());
152 SDst h(GetTextLineHeightExOf(ts));
153
154 ClearLine(ts.Margin.Top + h * l, h);
155 }
156
157 void
158 TextRegion::Scroll(ptrdiff_t n)
159 {
160 if(YB_LIKELY(GetHeight() > Margin.Bottom))
161 Scroll(n, GetHeight() - Margin.Bottom);
162 }
163 void
164 TextRegion::Scroll(ptrdiff_t n, SDst h)
165 {
166 if(YB_LIKELY(pBuffer && pBufferAlpha))
167 {
168 const s32 t(((h + Margin.Bottom > GetHeight()
169 ? GetHeight() - Margin.Bottom : h)
170 - Margin.Top - abs(n)) * GetWidth());
171
172 if(YB_LIKELY(n && t > 0))
173 {
174 u32 d(Margin.Top), s(d);
175
176 if(n > 0)
177 d += n;
178 else
179 s -= n;
180 yunseq(s *= GetWidth(), d *= GetWidth());
181 yunseq(ystdex::pod_move_n(&pBuffer[s], t, &pBuffer[d]),
182 ystdex::pod_move_n(&pBufferAlpha[s], t, &pBufferAlpha[d]));
183 }
184 }
185 }
186
187
188 void
189 DrawClippedText(const Graphics& g, const Rect& mask, TextState& ts,
190 const String& str, bool line_wrap)
191 {
192 TextRenderer tr(ts, g, mask);
193
194 if(line_wrap)
195 PutString(tr, str);
196 else
197 PutLine(tr, str);
198 }
199 void
200 DrawClippedText(const Graphics& g, const Rect& mask, const Rect& bounds,
201 const String& str, const Padding& m, Color c, bool line_wrap,
202 const Font& fnt)
203 {
204 TextState ts(fnt);
205 const Rect txt_bounds(bounds + m);
206
207 ts.Margin = FetchMargin(txt_bounds, g.GetSize()),
208 ts.ResetPen(bounds.GetPoint(), m);
209 ts.Color = c;
210 DrawClippedText(g, mask & txt_bounds, ts, str, line_wrap);
211 }
212
213 void
214 DrawText(const Graphics& g, TextState& ts, const String& str, bool line_wrap)
215 {
216 DrawClippedText(g, Rect(g.GetSize()), ts, str, line_wrap);
217 }
218 void
219 DrawText(const Graphics& g, const Rect& bounds, const String& str,
220 const Padding& m, Color c, bool line_wrap, const Font& fnt)
221 {
222 DrawClippedText(g, Rect(g.GetSize()), bounds, str, m, c, line_wrap, fnt);
223 }
224 void
225 DrawText(TextRegion& tr, const Graphics& g, const Point& pt, const Size& s,
226 const String& str, bool line_wrap)
227 {
228 if(line_wrap)
229 PutString(tr, str);
230 else
231 PutLine(tr, str);
232 BlitTo(g.GetBufferPtr(), tr, g.GetSize(), Point(), pt, s);
233 }
234
235 YSL_END_NAMESPACE(Drawing)
236
237 YSL_END
238