YSTest: ydraw.cpp 源文件

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
31 YSL_BEGIN
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