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 
29 #include "YSLib/Service/yblit.h"
30 #include "YSLib/Service/TextLayout.h" // for FetchLastLineBasePosition;
31 
32 using namespace ystdex;
33 
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()
110 {
111  InitializeFont();
112 }
113 
114 void
116 {
117  RenderCharFrom<decltype(RenderCharAlpha), RenderCharAlpha>(c,
120 }
121 
122 void
124 {
126  ResetPen();
127 }
128 
129 void
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
150 {
151  auto& ts(GetTextState());
153 
154  ClearLine(ts.Margin.Top + h * l, h);
155 }
156 
157 void
158 TextRegion::Scroll(ptrdiff_t n)
159 {
161  Scroll(n, GetHeight() - Margin.Bottom);
162 }
163 void
164 TextRegion::Scroll(ptrdiff_t n, SDst h)
165 {
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());
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