YSTest  PreAlpha_b500_20140530
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
ydraw.cpp
浏览该文件的文档.
1 /*
2  © 2011-2014 FrankHB.
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/YModules.h"
29 #include YFM_YSLib_Service_YDraw
30 #include YFM_YSLib_Service_YBlit
31 
32 namespace YSLib
33 {
34 
35 namespace Drawing
36 {
37 
38 void
39 PlotHLineSeg(BitmapPtr dst, const Rect& bounds, SDst w, SPos y, SPos x1,
40  SPos x2, Color c)
41 {
42  YAssertNonnull(dst),
43  YAssert(bounds.Width <= w, "Wrong boundary or width found.");
44  if(!bounds.IsUnstrictlyEmpty()
45  && IsInInterval<SPos>(y - bounds.Y, bounds.Height))
46  {
47  const auto bx(bounds.X);
48  const auto bxw(bx + bounds.Width);
49 
50  if(!((x1 < bx && x2 < bx) || (x1 >= bxw && x2 >= bxw)))
51  {
52  RestrictInInterval(x1, bx, bxw),
53  RestrictInInterval(x2, bx, bxw + 1);
54  RestrictLessEqual(x1, x2);
55  FillPixel<PixelType>(&dst[y * w + x1], x2 - x1, c);
56  }
57  }
58 }
59 
60 void
61 PlotVLineSeg(BitmapPtr dst, const Rect& bounds, SDst w, SPos x, SPos y1,
62  SPos y2, Color c)
63 {
64  YAssertNonnull(dst),
65  YAssert(bounds.Width <= w, "Wrong boundary or width found.");
66  if(!bounds.IsUnstrictlyEmpty()
67  && IsInInterval<SPos>(x - bounds.X, bounds.Width))
68  {
69  const auto by(bounds.Y);
70  const auto byh(by + bounds.Height);
71 
72  if(!((y1 < by && y2 < by) || (y1 >= byh && y2 >= byh)))
73  {
74  RestrictInInterval(y1, by, byh),
75  RestrictInInterval(y2, by, byh + 1);
76  RestrictLessEqual(y1, y2);
77  FillVerticalLine<PixelType>(&dst[y1 * w + x], y2 - y1, w, c);
78  }
79  }
80 }
81 
82 void
83 PlotLineSeg(BitmapPtr dst, const Rect& bounds, SDst w, SPos x1, SPos y1,
84  SPos x2, SPos y2, Color c)
85 {
86  if(y1 == y2)
87  PlotHLineSeg(dst, bounds, w, y1, x1, x2 + 1, c);
88  else if(x1 == x2)
89  PlotVLineSeg(dst, bounds, w, x1, y1, y2 + 1, c);
90  else
91  {
92  /*
93  一般 Bresenham 算法:实现自
94  http://cg.sjtu.edu.cn/lecture_site/chap2/mainframe212.htm 伪代码。
95  */
96  //起点 (x1, y1) 和终点 (x2, y2) 不同。
97 
98  const s8 sx(FetchSign(x2 - x1)), sy(FetchSign(y2 - y1));
99  SDst dx(std::abs(x2 - x1)), dy(std::abs(y2 - y1));
100  bool f(dy > dx);
101 
102  if(f)
103  std::swap(dx, dy);
104 
105  //初始化误差项以补偿非零截断。
106  const SDst dx2(dx << 1), dy2(dy << 1);
107  int e(dy2 - dx);
108 
109  //主循环。
110  while(dx-- != 0)
111  {
112  PlotPixel(dst, bounds, w, x1, y1, c);
113  if(e >= 0)
114  {
115  if(f)
116  x1 += sx;
117  else
118  y1 += sy;
119  e -= dx2;
120  }
121  if(f)
122  y1 += sy;
123  else
124  x1 += sx;
125  e += dy2;
126  }
127  }
128 }
129 
130 void
131 DrawRect(const Graphics& g, const Rect& bounds, const Point& pt, const Size& s,
132  Color c)
133 {
134  const SPos x1(pt.X), y1(pt.Y), x2(x1 + s.Width - 1), y2(y1 + s.Height - 1);
135 
136  if(YB_LIKELY(x1 < x2 && y1 < y2))
137  {
138  DrawVLineSeg(g, bounds, x1, y1, y2, c),
139  DrawHLineSeg(g, bounds, y2, x1, x2 + 1, c),
140  DrawVLineSeg(g, bounds, x2, y1, y2, c),
141  DrawHLineSeg(g, bounds, y1, x1, x2, c);
142  }
143 }
144 
145 void
146 FillRect(const Graphics& g, const Rect& r, Color c)
147 {
148  YAssert(bool(g), "Invalid graphics context found.");
149  FillRectRaw<PixelType>(g.GetBufferPtr(), g.GetSize(), r, c);
150 }
151 
152 namespace
153 {
154 
156 void
157 PlotCircle(void(*plotter)(const Graphics&, const Rect&, SPos, SPos, SDst, SDst,
158  Color), const Graphics& g, const Rect& bounds, const Point& pt, SDst r,
159  Color c)
160 {
161  YAssertNonnull(plotter);
162  if(r != 0)
163  // Bresenham circle algorithm implementation.
164  // See http://willperone.net/Code/codecircle.php .
165  for(SPos x(0), y(r), p(3 - 2 * r); y >= x;
166  p += p < 0 ? (4 * x++ + 6) : (4 * (x++ - y--) + 10))
167  plotter(g, bounds, pt.X, pt.Y, x, y, c);
168 }
169 
170 } // unnamed namespace;
171 
172 void
173 DrawCircle(const Graphics& g, const Rect& bounds, const Point& pt, SDst r,
174  Color c)
175 {
176  PlotCircle([](const Graphics& g, const Rect& bounds, SPos x, SPos y,
177  SDst dx, SDst dy, Color c){
178  using namespace std;
179  using namespace placeholders;
180  const auto plot(bind(PlotPixel, g.GetBufferPtr(), cref(bounds),
181  g.GetWidth(), _1, _2, c));
182 
183  plot(x + dx, y + dy),
184  plot(x - dx, y + dy),
185  plot(x - dx, y - dy),
186  plot(x + dx, y - dy),
187  plot(x + dy, y + dx),
188  plot(x - dy, y + dx),
189  plot(x - dy, y - dx),
190  plot(x + dy, y - dx);
191  }, g, bounds, pt, r, c);
192 }
193 
194 void
195 FillCircle(const Graphics& g, const Rect& bounds, const Point& pt, SDst r,
196  Color c)
197 {
198  PlotCircle([](const Graphics& g, const Rect& bounds, SPos x, SPos y,
199  SDst dx, SDst dy, Color c){
200  using namespace std;
201  using namespace placeholders;
202  const auto plot(bind(PlotHLineSeg, g.GetBufferPtr(), cref(bounds),
203  g.GetWidth(), _1, _2, _3, c));
204 
205  plot(y + dy, x - dx, x + dx + 1),
206  plot(y - dy, x - dx, x + dx + 1),
207  plot(y + dx, x - dy, x + dy + 1),
208  plot(y - dx, x - dy, x + dy + 1);
209  }, g, bounds, pt, r, c);
210 }
211 
212 } // namespace Drawing;
213 
214 } // namespace YSLib;
215 
void DrawVLineSeg(const Graphics &g, const Rect &bounds, SPos x, SPos y1, SPos y2, Color c)
描画竖直线段。
Definition: ydraw.h:153
YF_API void FillCircle(const Graphics &, const Rect &, const Point &, SDst, Color c)
填充圆形。
Definition: ydraw.cpp:195
YF_API void FillRect(const Graphics &g, const Rect &, Color c)
填充标准矩形。
Definition: ydraw.cpp:146
YF_API void PlotLineSeg(BitmapPtr dst, const Rect &bounds, SDst w, SPos x1, SPos y1, SPos x2, SPos y2, Color)
绘制线段:在宽 w 的缓冲区内的区域 bounds 绘制端点为 p1(x1, y1) 和 p2(x2, y2) 的线段。 ...
Definition: ydraw.cpp:83
SDst Height
宽和高。
Definition: ygdibase.h:258
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:39
std::int16_t SPos
屏幕坐标度量。
Definition: Video.h:38
void swap(any &x, any &y)
交换对象。
Definition: any.h:729
bounds c YF_API void DrawCircle(const Graphics &, const Rect &, const Point &, SDst, Color c)
描画圆形。
Definition: ydraw.cpp:173
void DrawHLineSeg(const Graphics &g, const Rect &bounds, SPos y, SPos x1, SPos x2, Color c)
描画水平线段。
Definition: ydraw.h:128
yconstfn s8 FetchSign(int a, int b=0) ynothrow
整数类型符号函数。
Definition: ycutil.h:89
屏幕标准矩形:表示屏幕矩形区域。
Definition: ygdibase.h:416
std::int8_t s8
Definition: yadaptor.h:71
void RestrictLessEqual(_type &a, _type &b) ynothrow
约束关系:a ≤ b 。
Definition: ycutil.h:327
#define YAssertNonnull(_expr)
Definition: cassert.h:81
二维图形接口上下文。
Definition: ygdibase.h:721
_tWidget _fCallable && f
Definition: ywgtevt.h:597
void PlotPixel(BitmapPtr dst, const Rect &bounds, SDst w, SPos x, SPos y, Color c)
绘制指定位置的像素:(x, y) 。
Definition: ydraw.h:89
YF_API void PlotVLineSeg(BitmapPtr dst, const Rect &bounds, SDst w, SPos x, SPos y1, SPos y2, Color)
绘制竖直线段:在宽 w 的缓冲区内的区域 bounds 绘制指定竖直水平坐标 x , 竖直坐标 y1 - 1 、 y2 。 ...
Definition: ydraw.cpp:61
void RestrictInInterval(_type &i, int a, int b) ynothrow
约束整数 i 在左闭右开区间 [a, b) 中。
Definition: ycutil.h:283
PixelType * BitmapPtr
Definition: Video.h:295
bounds & r
Definition: ydraw.h:220
c yconstfn g
Definition: ystyle.h:104
#define YB_LIKELY(expr)
Definition: ydef.h:297
颜色。
Definition: Video.h:339
屏幕区域大小。
Definition: ygdibase.h:249
p1 p1 p2 p2 c YF_API void DrawRect(const Graphics &g, const Rect &bounds, const Point &pt, const Size &s, Color c)
描画标准矩形。
Definition: ydraw.cpp:131
#define YAssert(_expr, _msg)
Definition: cassert.h:73
YF_API void PlotHLineSeg(BitmapPtr dst, const Rect &bounds, SDst w, SPos y, SPos x1, SPos x2, Color)
绘制水平线段:在宽 w 的缓冲区内的区域 bounds 绘制指定端点水平坐标 x1 、 x2 - 1 ,竖直坐标 y 。 ...
Definition: ydraw.cpp:39