YSTest  PreAlpha_b400_20130424
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
ydraw.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/ydraw.h"
29 #include "YSLib/Service/yblit.h"
30 
32 
33 YSL_BEGIN_NAMESPACE(Drawing)
34 
35 bool
36 DrawHLineSeg(const Graphics& g, SPos y, SPos x1, SPos x2, Color c)
37 {
38  YAssert(bool(g), "Invalid graphics context found.");
39 
40  if(IsInInterval<int>(y, g.GetHeight())
41  && !((x1 < 0 && x2 < 0) || (x1 >= g.GetWidth() && x2 >= g.GetWidth())))
42  {
43  RestrictInInterval(x1, 0, g.GetWidth());
44  RestrictInInterval(x2, 0, g.GetWidth());
45  RestrictLessEqual(x1, x2);
46  FillPixel<PixelType>(&g.GetBufferPtr()[y * g.GetWidth() + x1],
47  x2 - x1, c);
48  return true;
49  }
50  return false;
51 }
52 
53 bool
54 DrawVLineSeg(const Graphics& g, SPos x, SPos y1, SPos y2, Color c)
55 {
56  YAssert(bool(g), "Invalid graphics context found.");
57 
58  if(IsInInterval<int>(x, g.GetWidth())
59  && !((y1 < 0 && y2 < 0) || (y1 >= g.GetHeight()
60  && y2 >= g.GetHeight())))
61  {
62  RestrictInInterval(y1, 0, g.GetHeight());
63  RestrictInInterval(y2, 0, g.GetHeight());
64  RestrictLessEqual(y1, y2);
65  FillVerticalLine<PixelType>(&g.GetBufferPtr()[y1 * g.GetWidth() + x],
66  y2 - y1, g.GetWidth(), c);
67  return true;
68  }
69  return false;
70 }
71 
72 namespace
73 {
74 
80 bool
81 DrawObliqueLine(const Graphics& g, SPos x1, SPos y1, SPos x2, SPos y2,
82  Color c)
83 {
84  YAssert(y1 != y2,
85  "Not drawing an oblique line: the line is horizontal.");
86  YAssert(x1 != x2, "Not drawing an oblique line: the line is vertical.");
87 
88  if(Rect(g.GetSize()).Contains(x1, y1)
89  && Rect(g.GetSize()).Contains(x2, y2))
90  {
91  /*
92  一般 Bresenham 算法:实现自
93  http://cg.sjtu.edu.cn/lecture_site/chap2/mainframe212.htm 伪代码。
94  */
95  //起点 (x1, y1) 和终点 (x2, y2) 不同。
96 
97  const s8 sx(FetchSign(x2 - x1)), sy(FetchSign(y2 - y1));
98  SDst dx(abs(x2 - x1)), dy(abs(y2 - y1));
99  bool f(dy > dx);
100 
101  if(f)
102  std::swap(dx, dy);
103 
104  //初始化误差项以补偿非零截断。
105  const SDst dx2(dx << 1), dy2(dy << 1);
106  int e(dy2 - dx);
107 
108  //主循环。
109  while(dx-- != 0)
110  {
111  PutPixel(g, x1, y1, c);
112  if(e >= 0)
113  {
114  if(f)
115  x1 += sx;
116  else
117  y1 += sy;
118  e -= dx2;
119  }
120  if(f)
121  y1 += sy;
122  else
123  x1 += sx;
124  e += dy2;
125  }
126  return true;
127  }
128  return false;
129 }
130 
131 } // unnamed namespace;
132 
133 bool
134 DrawLineSeg(const Graphics& g, SPos x1, SPos y1, SPos x2, SPos y2, Color c)
135 {
136  if(y1 == y2)
137  return DrawHLineSeg(g, y1, x1, x2 + 1, c);
138  else if(x1 == x2)
139  return DrawVLineSeg(g, x1, y1, y2 + 1, c);
140  else
141  return DrawObliqueLine(g, x1, y1, x2, y2, c);
142 }
143 
144 bool
145 DrawRect(const Graphics& g, const Point& pt, const Size& s, Color c)
146 {
147  const SPos x1(pt.X), y1(pt.Y), x2(x1 + s.Width - 1), y2(y1 + s.Height - 1);
148 
149  if(YB_LIKELY(x1 < x2 && y1 < y2))
150  {
151  bool b(DrawVLineSeg(g, x1, y1, y2, c));
152 
153  b |= DrawHLineSeg(g, y2, x1, x2 + 1, c);
154  b |= DrawVLineSeg(g, x2, y1, y2, c);
155  b |= DrawHLineSeg(g, y1, x1, x2, c);
156  return b;
157  }
158  return false;
159 }
160 
161 bool
162 FillRect(const Graphics& g, const Point& pt, const Size& s, Color c)
163 {
164  if(YB_LIKELY(g))
165  {
166  FillRect<PixelType>(g.GetBufferPtr(), g.GetSize(), pt, s, c);
167  return true;
168  }
169  return false;
170 }
171 
172 namespace
173 {
174 
176 void
177 Draw8Points(BitmapPtr dst, const Size& s, SPos x0, SPos y0, SPos x, SPos y,
178  Color c)
179 {
180  PlotPixel(dst, s, x0 + x, y0 + y, c),
181  PlotPixel(dst, s, x0 - x, y0 + y, c),
182  PlotPixel(dst, s, x0 - x, y0 - y, c),
183  PlotPixel(dst, s, x0 + x, y0 - y, c),
184  PlotPixel(dst, s, x0 + y, y0 + x, c),
185  PlotPixel(dst, s, x0 - y, y0 + x, c),
186  PlotPixel(dst, s, x0 - y, y0 - x, c),
187  PlotPixel(dst, s, x0 + y, y0 - x, c);
188 }
189 
190 } // unnamed namespace;
191 
192 bool
193 DrawCircle(const Graphics& g, const Point& pt, SDst r, Color c)
194 {
195  if(r == 0)
196  return false;
197 
198  // Midpoint circle algorithm implementation.
199  // See http://cg.sjtu.edu.cn/lecture_site/chap2/mainframe224.htm .
200  const auto dst(g.GetBufferPtr());
201  const Size& s(g.GetSize());
202  SPos x(0), y(r), d(1 - r);
203 
204  for(SDst dt(2), db(4); x <= y; yunseq(dt += 2, db += 2, ++x))
205  {
206  Draw8Points(dst, s, pt.X, pt.Y, x, y, c);
207  if(d < 0)
208  d += dt;
209  else
210  {
211  d += db;
212  yunseq(db += 2, --y);
213  }
214  }
215  return true;
216 }
217 
218 YSL_END_NAMESPACE(Drawing)
219 
220 YSL_END
221