00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <background_wnd/painters/gradient_painter.hpp>
00016 #include <math.h>
00017
00018
00019 namespace win32 { namespace gui {
00020
00021 namespace detail {
00022
00024
00025
00026 const double PI = 3.141592654;
00027
00028 double degree_to_rad(double n)
00029 {
00030 return PI / 180.0 * n;
00031 }
00032
00033 double rad_to_degree(double n)
00034 {
00035 return (180.0 / PI) * n;
00036 }
00037
00038 class triangle
00039 {
00040 public:
00041 triangle() : alpha_(0), beta_(0), a_(0), b_(0), c_(0)
00042 {}
00043
00044 void set_a(double a)
00045 {
00046 a_ = a;
00047 }
00048
00049 void set_b(double b)
00050 {
00051 b_ = b;
00052 }
00053
00054 void set_hypotenuse(double c)
00055 {
00056 c_ = c;
00057 }
00058
00059 void set_alpha(double alpha)
00060 {
00061 alpha_ = alpha;
00062 }
00063
00064 void set_beta(double beta)
00065 {
00066 beta_ = beta;
00067 }
00068
00069 double get_a() const
00070 {
00071 if (a_)
00072 return a_;
00073 else if (b_)
00074 return leg_from_pythagoras(b_, get_hypotenuse());
00075 else if (c_ && alpha_)
00076 return cos(degree_to_rad(alpha_)) / c_;
00077 else if (c_ && beta_)
00078 return sin(degree_to_rad(beta_)) / c_;
00079 return 0;
00080 }
00081
00082 double get_b() const
00083 {
00084 if (b_)
00085 return b_;
00086 else if (a_)
00087 return leg_from_pythagoras(a_, get_hypotenuse());
00088 else if (c_ && alpha_)
00089 return sin(degree_to_rad(alpha_)) / c_;
00090 else if (c_ && beta_)
00091 return cos(degree_to_rad(beta_)) / c_;
00092 return 0;
00093 }
00094
00095 double get_hypotenuse() const
00096 {
00097 if (c_)
00098 return c_;
00099 else if (a_ && b_)
00100 return hypotenuse_from_pythagoras(a_, b_);
00101 else if (a_ && alpha_)
00102 return a_ / cos(degree_to_rad(alpha_));
00103 else if (a_ && beta_)
00104 return a_ / sin(degree_to_rad(beta_));
00105 else if (b_ && alpha_)
00106 return b_ / sin(degree_to_rad(alpha_));
00107 else if (b_ && beta_)
00108 return b_ / cos(degree_to_rad(beta_));
00109 return 0;
00110 }
00111
00112 double get_alpha() const
00113 {
00114 if (alpha_)
00115 return alpha_;
00116 if (beta_)
00117 return 90 - beta_;
00118 double hypo = get_hypotenuse();
00119 if (a_ && hypo)
00120 return rad_to_degree(acos(a_ / hypo));
00121 else if (b_ && hypo)
00122 return rad_to_degree(asin(b_ / hypo));
00123 return 0;
00124 }
00125
00126 double get_beta() const
00127 {
00128 if (beta_)
00129 return beta_;
00130 if (alpha_)
00131 return 90 - alpha_;
00132 double hypo = get_hypotenuse();
00133 if (a_ && hypo)
00134 return rad_to_degree(asin(a_ / hypo));
00135 else if (b_ && hypo)
00136 return rad_to_degree(acos(b_ / hypo));
00137 return 0;
00138 }
00139
00140
00141
00142 private:
00143 static double leg_from_pythagoras(double leg, double hypotenuse)
00144 {
00145 double leg_square = hypotenuse * hypotenuse - leg * leg;
00146 return sqrt(leg_square);
00147 }
00148
00149 static double hypotenuse_from_pythagoras(double adj_leg, double opp_leg)
00150 {
00151 double hyp_square = adj_leg * adj_leg + opp_leg * opp_leg;
00152 return sqrt(hyp_square);
00153 }
00154
00155 double alpha_;
00156 double beta_;
00157
00158 double a_;
00159 double b_;
00160 double c_;
00161 };
00162
00163 }
00164
00165
00166
00167
00168
00175 gradient_painter::gradient_painter(param0 colors, param1 angle) : colors_(colors), angle_(angle)
00176 {}
00177
00178 gradient_painter* gradient_painter::clone() const
00179 {
00180 return new gradient_painter(*this);
00181 }
00182
00183 void gradient_painter::draw(HDC hDC, int cx, int cy)
00184 {
00185 if (cx == 0 || cy == 0)
00186 return;
00187
00188 int r1 = GetRValue(colors_.first);
00189 int g1 = GetGValue(colors_.first);
00190 int b1 = GetBValue(colors_.first);
00191 int r2 = GetRValue(colors_.second);
00192 int g2 = GetGValue(colors_.second);
00193 int b2 = GetBValue(colors_.second);
00194
00195 draw_linear (hDC, cx, cy, r1, g1, b1, r2, g2, b2);
00196 }
00197
00198
00199 void gradient_painter::draw_linear(HDC hDC, int cx, int cy, int r1, int g1, int b1, int r2, int g2, int b2)
00200 {
00201 double r, g, b;
00202 unsigned angle = angle_ % 360;
00203 HPEN hOldPen = (HPEN) GetCurrentObject(hDC, OBJ_PEN);
00204
00205
00206 if (angle % 180 == 0) {
00207 for (int x = 0; x < cx; ++x) {
00208
00209 if (angle == 0) {
00210 r = r1 + (x * (r2 - r1)) / cx;
00211 g = g1 + (x * (g2 - g1)) / cx;
00212 b = b1 + (x * (b2 - b1)) / cx;
00213 }
00214
00215 else {
00216 r = r2 + (x * (r1 - r2)) / cx;
00217 g = g2 + (x * (g1 - g2)) / cx;
00218 b = b2 + (x * (b1 - b2)) / cx;
00219 }
00220
00221 SelectObject( hDC, CreatePen(PS_SOLID, 1, RGB(r, g, b)) );
00222 MoveToEx(hDC, x, 0, NULL);
00223 LineTo(hDC, x, cy);
00224 DeleteObject( SelectObject(hDC, hOldPen) );
00225 }
00226 }
00227
00228 else {
00229 detail::triangle triangle;
00230 triangle.set_a(cx);
00231 triangle.set_beta(angle);
00232 double y_diff = triangle.get_b();
00233 double whole_cy = cy + y_diff;
00234
00235 for (int y = 0; y <= whole_cy; ++y) {
00236
00237 if (angle < 180) {
00238 r = r1 + ( (whole_cy - y) * (r2 - r1) ) / whole_cy;
00239 g = g1 + ( (whole_cy - y) * (g2 - g1) ) / whole_cy;
00240 b = b1 + ( (whole_cy - y) * (b2 - b1) ) / whole_cy;
00241 }
00242
00243 else {
00244 r = r2 + ( (whole_cy - y) * (r1 - r2) ) / whole_cy;
00245 g = g2 + ( (whole_cy - y) * (g1 - g2) ) / whole_cy;
00246 b = b2 + ( (whole_cy - y) * (b1 - b2) ) / whole_cy;
00247 }
00248
00249 int y_from = (int) (y - y_diff);
00250 int y_to = y;
00251
00252
00253 if ( (angle / 90) % 2 == 1 )
00254 std::swap(y_from, y_to);
00255
00256 SelectObject( hDC, CreatePen(PS_SOLID, 1, RGB(r, g, b)) );
00257 MoveToEx(hDC, 0, y_from, NULL);
00258 LineTo(hDC, cx, y_to);
00259 DeleteObject( SelectObject(hDC, hOldPen) );
00260 }
00261 }
00262 }
00263
00264
00265 bool gradient_painter::is_opaque(int, int) const
00266 {
00267 return true;
00268 }
00269
00271 void gradient_painter::gradient_colors(const GradientColors& colors)
00272 {
00273 colors_ = colors;
00274 }
00275
00277 gradient_painter::GradientColors gradient_painter::gradient_colors() const
00278 {
00279 return colors_;
00280 }
00281
00283 void gradient_painter::angle(unsigned angle)
00284 {
00285 angle_ = angle;
00286 }
00287
00289 unsigned gradient_painter::angle() const
00290 {
00291 return angle_;
00292 }
00293
00295 gradient_painter::GradientColors gradient_painter::make_gradient_colors(COLORREF crStart, COLORREF crEnd)
00296 {
00297 return std::make_pair(crStart, crEnd);
00298 }
00299
00300 } }