|
Rapicorn - Experimental UI Toolkit - Source Code 10.08.1
|
00001 /* Rapicorn 00002 * Copyright (C) 2005 Tim Janik 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * A copy of the GNU Lesser General Public License should ship along 00015 * with this library; if not, see http://www.gnu.org/copyleft/. 00016 */ 00017 #ifndef __RAPICORN_PRIMITIVES_HH__ 00018 #define __RAPICORN_PRIMITIVES_HH__ 00019 00020 #include <list> 00021 #include <math.h> 00022 #include <values.h> /* MAXDOUBLE, etc. */ 00023 #include <cairo.h> 00024 #include <rapicorn-core.hh> 00025 00026 namespace Rapicorn { 00027 00028 /* --- degree & radians --- */ 00029 #undef PI /* some math packages define PI? */ 00030 static const double PI = 3.141592653589793238462643383279502884197; 00031 static const double LN_INV255 = -5.5412635451584261462455391880218; // ln(1/255) 00032 00033 inline double RAPICORN_CONST degree (double radians) { return radians * (180. / PI); } 00034 inline double RAPICORN_CONST radians (double degree) { return degree * (PI / 180.); } 00035 00036 /* --- forward declarations --- */ 00037 struct FactoryContext; // see factory.cc 00038 00039 /* --- enums --- */ 00040 typedef enum { 00041 COMBINE_NORMAL, /* A OVER B */ 00042 COMBINE_OVER, /* A + (B & ~A) */ 00043 COMBINE_UNDER, /* B + (A & ~B) */ 00044 COMBINE_ADD, /* A + B */ 00045 COMBINE_DEL, /* B - alphaA */ 00046 COMBINE_ATOP, /* (A + B) & B */ 00047 COMBINE_XOR, /* A ^ B */ 00048 COMBINE_BLEND, /* B * (1 - alpha) + A * alpha */ 00049 COMBINE_VALUE, /* B.value = A.value */ 00050 } CombineType; 00051 00052 /* --- Point --- */ 00053 class Point { 00054 public: 00055 double x, y; 00056 Point (double ax, 00057 double ay) : 00058 x (ax), 00059 y (ay) 00060 {} 00061 explicit Point () : 00062 x (0), 00063 y (0) 00064 {} 00065 inline double 00066 dist2 (double px, double py) const 00067 { 00068 double dx = px - x; 00069 double dy = py - y; 00070 return dx * dx + dy * dy; 00071 } 00072 inline double 00073 dist (double px, double py) const 00074 { 00075 // avoid destructive underflow or overflow in (dx^2 + dy^2) ^ .5 00076 double dx = fabs (px - x); 00077 double dy = fabs (py - y); 00078 if (dx == 0.0) 00079 return dy; 00080 else if (dy == 0.0) 00081 return dx; 00082 else if (dx > dy) 00083 { 00084 const double r = dy / dx; 00085 return dx * sqrt (1.0 + r * r); 00086 } 00087 else // dy < dx 00088 { 00089 const double r = dx / dy; 00090 return dy * sqrt (1.0 + r * r); 00091 } 00092 } 00093 inline double dist2 (const Point &p = Point (0, 0)) const { return dist2 (p.x, p.y); } 00094 inline double dist (const Point &p = Point (0, 0)) const { return dist (p.x, p.y); } 00095 Point operator+ (const Point &p) const { return Point (x + p.x, y + p.y); } 00096 Point operator+ (double delta) const { return Point (x + delta, y + delta); } 00097 Point operator- (const Point &p) const { return Point (x - p.x, y - p.y); } 00098 Point operator- (double delta) const { return Point (x - delta, y - delta); } 00099 Point& operator- () { x = -x; y = -y; return *this; } 00100 Point& operator+= (const Point &p) { return *this = *this + p; } 00101 Point& operator+= (double delta) { return *this = *this + delta; } 00102 Point& operator-= (const Point &p) { return *this = *this - p; } 00103 Point& operator-= (double delta) { return *this = *this - delta; } 00104 bool operator== (const Point &p2) const { return x == p2.x && y == p2.y; } 00105 bool operator!= (const Point &p2) const { return x != p2.x || y != p2.y; } 00106 bool equals (const Point &p2, double epsilon = 0.0) const; 00107 }; 00108 inline Point 00109 min (const Point &p1, const Point &p2) 00110 { 00111 return Point (Rapicorn::min (p1.x, p2.x), Rapicorn::min (p1.y, p2.y)); 00112 } 00113 using ::std::min; 00114 inline Point 00115 max (const Point &p1, const Point &p2) 00116 { 00117 return Point (Rapicorn::max (p1.x, p2.x), Rapicorn::max (p1.y, p2.y)); 00118 } 00119 using ::std::max; 00120 inline Point 00121 floor (const Point &s) 00122 { 00123 using ::floor; 00124 return Point (floor (s.x), floor (s.y)); 00125 } 00126 using ::floor; 00127 inline Point 00128 ceil (const Point &s) 00129 { 00130 using ::ceil; 00131 return Point (ceil (s.x), ceil (s.y)); 00132 } 00133 using ::ceil; 00134 inline Point 00135 round (const Point &s) 00136 { 00137 using ::round; 00138 return Point (round (s.x), ::round (s.y)); 00139 } 00140 using ::round; 00141 00142 /* --- Rect --- */ 00143 class IRect; 00144 class Rect { 00145 public: 00146 double x, y; 00147 double width; 00148 double height; 00149 explicit Rect (); 00150 explicit Rect (Point cp0, Point cp1); 00151 explicit Rect (Point p0, double cwidth, double cheight); 00152 explicit Rect (double cx, double cy, double cwidth, double cheight); 00153 Rect& assign (Point p0, Point p1); 00154 Rect& assign (Point p0, double cwidth, double cheight); 00155 Rect& assign (double cx, double cy, double cwidth, double cheight); 00156 double upper_x () const { return x + width; } 00157 double upper_y () const { return y + height; } 00158 Point upper_left () const { return Point (x, y + height); } 00159 Point upper_right () const { return Point (x + width, y + height); } 00160 Point lower_right () const { return Point (x + width, y); } 00161 Point lower_left () const { return Point (x, y); } 00162 Point ul () const { return upper_left(); } 00163 Point ur () const { return upper_right(); } 00164 Point lr () const { return lower_right(); } 00165 Point ll () const { return lower_left(); } 00166 double diagonal () const { return ll().dist (ur()); } 00167 Point ul_tangent () const; 00168 Point ur_tangent () const; 00169 Point lr_tangent () const; 00170 Point ll_tangent () const; 00171 Point center () const { return Point (x + width * 0.5, y + height * 0.5); } 00172 Point north () const { return Point (x + width * 0.5, y); } 00173 Point north_east () const { return upper_right(); } 00174 Point east () const { return Point (x + width, y + height * 0.5); } 00175 Point south_east () const { return lower_right(); } 00176 Point south () const { return Point (x + width * 0.5, y); } 00177 Point south_west () const { return lower_left(); } 00178 Point west () const { return Point (x, y + height * 0.5); } 00179 Point north_west () const { return upper_left(); } 00180 bool contains (const Point &point) const { return x <= point.x && y <= point.y && point.x < x + width && point.y < y + height; } 00181 bool operator== (const Rect &other) const; 00182 bool operator!= (const Rect &other) const { return !operator== (other); } 00183 bool equals (const Rect &other, double epsilon = 0.0) const; 00184 double dist2 (const Point &p) const; 00185 double dist (const Point &p) const; 00186 Rect& rect_union (const Rect &r); 00187 Rect& add (const Point &p); 00188 Rect& add_border (double b); 00189 Rect& intersect (const Rect &r); 00190 bool empty () const; 00191 Point anchor_point (AnchorType anchor); 00192 Rect& translate (double deltax, 00193 double delty); 00194 Rect& operator+ (const Point &p); 00195 Rect& operator- (const Point &p); 00196 String string () const; 00197 static Rect create_anchored (AnchorType anchor, 00198 double width, 00199 double height); 00200 }; 00201 struct IRect { 00202 int64 x, y, width, height; 00203 IRect (const Rect &r) : 00204 x (ifloor (r.x)), y (ifloor (r.y)), 00205 width (iceil (r.width)), height (iceil (r.height)) 00206 {} 00207 IRect& 00208 operator= (const Rect &r) 00209 { 00210 x = ifloor (r.x); 00211 y = ifloor (r.y); 00212 width = iceil (r.width); 00213 height = iceil (r.height); 00214 return *this; 00215 } 00216 }; 00217 00218 /* --- Color --- */ 00219 class Color { 00220 uint32 argb_pixel; 00221 typedef uint32 (Color::*_unspecified_bool_type) () const; // non-numeric operator bool() result 00222 static inline _unspecified_bool_type _unspecified_bool_true () { return &Color::argb; } 00223 public: 00224 static inline uint8 IMUL (uint8 v, uint8 alpha) { return (v * (uint32) 0x010102 * alpha) >> 24; } 00225 static inline uint8 IDIV (uint8 v, uint8 alpha) { return (v * (uint32) 0xff) / alpha; } 00226 static inline uint8 IDIV0 (uint8 v, uint8 alpha) { if (!alpha) return 0xff; return IDIV (v, alpha); } 00227 static inline uint8 IMULDIV (uint8 v, uint8 amul, uint8 adiv) // IMUL (IDIV (v, amul), adiv) 00228 { return (((v * (uint32) 0x010102 * amul / adiv) >> 8) * 0xff) >> 16; } 00229 Color (uint32 c = 0) : 00230 argb_pixel (c) 00231 {} 00232 Color (uint8 red, uint8 green, uint8 blue, uint8 alpha = 0xff) : 00233 argb_pixel ((alpha << 24) | (red << 16) | (green << 8) | blue) 00234 {} 00235 static Color from_name (const String &color_name); 00236 static Color from_premultiplied (uint32 pargb) 00237 { 00238 Color c = (pargb); 00239 if (c.alpha()) 00240 { 00241 c.red (IDIV (c.red(), c.alpha())); 00242 c.green (IDIV (c.green(), c.alpha())); 00243 c.blue (IDIV (c.blue(), c.alpha())); 00244 } 00245 else 00246 { 00247 c.red (0); 00248 c.green (0); 00249 c.blue (0); 00250 } 00251 return c; 00252 } 00253 uint32 premultiplied() const 00254 { 00255 /* extract alpha, red, green ,blue */ 00256 uint32 a = alpha(), r = red(), g = green(), b = blue(); 00257 /* bring into premultiplied form */ 00258 r = IMUL (r, a); 00259 g = IMUL (g, a); 00260 b = IMUL (b, a); 00261 return Color (r, g, b, a).argb(); 00262 } 00263 void 00264 set (uint8 red, uint8 green, uint8 blue) 00265 { 00266 argb_pixel = (alpha() << 24) | (red << 16) | (green << 8) | blue; 00267 } 00268 void 00269 set (uint8 red, uint8 green, uint8 blue, uint8 alpha) 00270 { 00271 argb_pixel = (alpha << 24) | (red << 16) | (green << 8) | blue; 00272 } 00273 uint32 rgb () const { return argb_pixel & 0x00ffffff; } 00274 uint32 argb () const { return argb_pixel; } 00275 uint red () const { return (argb_pixel >> 16) & 0xff; } 00276 uint green () const { return (argb_pixel >> 8) & 0xff; } 00277 uint blue () const { return argb_pixel & 0xff; } 00278 uint alpha () const { return argb_pixel >> 24; } 00279 double red1 () const { return red() / 256.; } 00280 double green1 () const { return green() / 256.; } 00281 double blue1 () const { return blue() / 256.; } 00282 double alpha1 () const { return alpha() / 256.; } 00283 inline operator _unspecified_bool_type () const { return alpha() ? _unspecified_bool_true() : 0; } 00284 Color& alpha (uint8 v) { argb_pixel &= 0x00ffffff; argb_pixel |= v << 24; return *this; } 00285 Color& red (uint8 v) { argb_pixel &= 0xff00ffff; argb_pixel |= v << 16; return *this; } 00286 Color& green (uint8 v) { argb_pixel &= 0xffff00ff; argb_pixel |= v << 8; return *this; } 00287 Color& blue (uint8 v) { argb_pixel &= 0xffffff00; argb_pixel |= v << 0; return *this; } 00288 double get_hsv_value () { return max (max (red(), green()), blue()) / 255.; } 00289 void get_hsv (double *huep, /* 0..360: 0=red, 120=green, 240=blue */ 00290 double *saturationp, /* 0..1 */ 00291 double *valuep); /* 0..1 */ 00292 void set_hsv (double hue, /* 0..360: 0=red, 120=green, 240=blue */ 00293 double saturation, /* 0..1 */ 00294 double value); /* 0..1 */ 00295 void 00296 set_hsv_value (double v) 00297 { 00298 double frac = v / get_hsv_value(); 00299 double r = red() * frac, g = green() * frac, b = blue() * frac; 00300 set (iround (r), iround (g), iround (b)); 00301 } 00302 uint8 channel (uint nth) const 00303 { 00304 switch (nth) 00305 { 00306 case 0: return alpha(); 00307 case 1: return red(); 00308 case 2: return green(); 00309 case 3: return blue(); 00310 } 00311 return 0; 00312 } 00313 void channel (uint nth, uint8 v) 00314 { 00315 switch (nth) 00316 { 00317 case 0: alpha (v); break; 00318 case 1: red (v); break; 00319 case 2: green (v); break; 00320 case 3: blue (v); break; 00321 } 00322 } 00323 Color& shade (uint8 lucent) 00324 { 00325 uint32 a = argb_pixel >> 24; 00326 alpha ((a * lucent + a + lucent) >> 8); 00327 return *this; 00328 } 00329 Color& combine (const Color c2, uint8 lucent) 00330 { 00331 /* extract alpha, red, green ,blue */ 00332 uint32 Aa = c2.alpha(), Ar = c2.red(), Ag = c2.green(), Ab = c2.blue(); 00333 uint32 Ba = alpha(), Br = red(), Bg = green(), Bb = blue(); 00334 /* weight A layer */ 00335 Aa = IMUL (Aa, lucent); 00336 /* bring into premultiplied form */ 00337 Ar = IMUL (Ar, Aa); 00338 Ag = IMUL (Ag, Aa); 00339 Ab = IMUL (Ab, Aa); 00340 Br = IMUL (Br, Ba); 00341 Bg = IMUL (Bg, Ba); 00342 Bb = IMUL (Bb, Ba); 00343 /* A over B = colorA + colorB * (1 - alphaA) */ 00344 uint32 Ai = 255 - Aa; 00345 uint8 Dr = Ar + IMUL (Br, Ai); 00346 uint8 Dg = Ag + IMUL (Bg, Ai); 00347 uint8 Db = Ab + IMUL (Bb, Ai); 00348 uint8 Da = Aa + IMUL (Ba, Ai); 00349 /* un-premultiply */ 00350 if (Da) 00351 { 00352 Dr = IDIV (Dr, Da); 00353 Dg = IDIV (Dg, Da); 00354 Db = IDIV (Db, Da); 00355 } 00356 else 00357 Dr = Dg = Db = 0; 00358 /* assign */ 00359 alpha (Da); 00360 red (Dr); 00361 green (Dg); 00362 blue (Db); 00363 return *this; 00364 } 00365 Color& blend_premultiplied (const Color c2, uint8 lucent) 00366 { 00367 /* extract alpha, red, green ,blue */ 00368 uint32 Aa = c2.alpha(), Ar = c2.red(), Ag = c2.green(), Ab = c2.blue(); 00369 uint32 Ba = alpha(), Br = red(), Bg = green(), Bb = blue(); 00370 /* A over B = colorA * alpha + colorB * (1 - alpha) */ 00371 uint32 ilucent = 255 - lucent; 00372 uint8 Dr = IMUL (Ar, lucent) + IMUL (Br, ilucent); 00373 uint8 Dg = IMUL (Ag, lucent) + IMUL (Bg, ilucent); 00374 uint8 Db = IMUL (Ab, lucent) + IMUL (Bb, ilucent); 00375 uint8 Da = IMUL (Aa, lucent) + IMUL (Ba, ilucent); 00376 /* assign */ 00377 alpha (Da); 00378 red (Dr); 00379 green (Dg); 00380 blue (Db); 00381 return *this; 00382 } 00383 Color& add_premultiplied (const Color c2, uint8 lucent) 00384 { 00385 /* extract alpha, red, green ,blue */ 00386 uint32 Aa = alpha(), Ar = red(), Ag = green(), Ab = blue(); 00387 uint32 Ba = c2.alpha(), Br = c2.red(), Bg = c2.green(), Bb = c2.blue(); 00388 /* A add B = colorA + colorB */ 00389 uint32 Dr = Ar + IMUL (Br, lucent); 00390 uint32 Dg = Ag + IMUL (Bg, lucent); 00391 uint32 Db = Ab + IMUL (Bb, lucent); 00392 uint32 Da = Aa + IMUL (Ba, lucent); 00393 /* assign */ 00394 alpha (MIN (Da, 255)); 00395 red (MIN (Dr, 255)); 00396 green (MIN (Dg, 255)); 00397 blue (MIN (Db, 255)); 00398 return *this; 00399 } 00400 String string() const; 00401 }; 00402 00403 /* --- Affine --- */ 00404 class Affine { 00405 protected: 00406 /* ( xx yx ) 00407 * ( xy yy ) 00408 * ( xz yz ) 00409 */ 00410 double xx, xy, xz, yx, yy, yz; 00411 public: 00412 Affine (double cxx = 1, 00413 double cxy = 0, 00414 double cxz = 0, 00415 double cyx = 0, 00416 double cyy = 1, 00417 double cyz = 0) : 00418 xx (cxx), xy (cxy), xz (cxz), 00419 yx (cyx), yy (cyy), yz (cyz) 00420 {} 00421 Affine& 00422 translate (double tx, double ty) 00423 { 00424 multiply (Affine (1, 0, tx, 0, 1, ty)); 00425 return *this; 00426 } 00427 Affine& 00428 translate (Point p) 00429 { 00430 multiply (Affine (1, 0, p.x, 0, 1, p.y)); 00431 return *this; 00432 } 00433 Affine& 00434 set_translation (double tx, double ty) 00435 { 00436 xz = tx; 00437 yz = ty; 00438 return *this; 00439 } 00440 Affine& 00441 hflip() 00442 { 00443 xx = -xx; 00444 yx = -yx; 00445 xz = -xz; 00446 return *this; 00447 } 00448 Affine& 00449 vflip() 00450 { 00451 xy = -xy; 00452 yy = -yy; 00453 yz = -yz; 00454 return *this; 00455 } 00456 Affine& 00457 rotate (double theta) 00458 { 00459 double s = sin (theta); 00460 double c = cos (theta); 00461 return multiply (Affine (c, -s, 0, s, c, 0)); 00462 } 00463 Affine& 00464 rotate (double theta, Point anchor) 00465 { 00466 translate (anchor.x, anchor.y); 00467 rotate (theta); 00468 return translate (-anchor.x, -anchor.y); 00469 } 00470 Affine& 00471 scale (double sx, double sy) 00472 { 00473 xx *= sx; 00474 xy *= sy; 00475 yx *= sx; 00476 yy *= sy; 00477 return *this; 00478 } 00479 Affine& 00480 shear (double shearx, double sheary) 00481 { 00482 return multiply (Affine (1, shearx, 0, sheary, 1, 0)); 00483 } 00484 Affine& 00485 shear (double theta) 00486 { 00487 return multiply (Affine (1, tan (theta), 0, 0, 1, 0)); 00488 } 00489 Affine& 00490 multiply (const Affine &a2) 00491 { 00492 Affine dst; // dst * point = this * (a2 * point) 00493 dst.xx = a2.xx * xx + a2.yx * xy; 00494 dst.xy = a2.xy * xx + a2.yy * xy; 00495 dst.xz = a2.xz * xx + a2.yz * xy + xz; 00496 dst.yx = a2.xx * yx + a2.yx * yy; 00497 dst.yy = a2.xy * yx + a2.yy * yy; 00498 dst.yz = a2.xz * yx + a2.yz * yy + yz; 00499 return *this = dst; 00500 } 00501 Affine& 00502 multiply_swapped (const Affine &a2) 00503 { 00504 Affine dst; // dst * point = a2 * (this * point) 00505 dst.xx = xx * a2.xx + yx * a2.xy; 00506 dst.xy = xy * a2.xx + yy * a2.xy; 00507 dst.xz = xz * a2.xx + yz * a2.xy + a2.xz; 00508 dst.yx = xx * a2.yx + yx * a2.yy; 00509 dst.yy = xy * a2.yx + yy * a2.yy; 00510 dst.yz = xz * a2.yx + yz * a2.yy + a2.yz; 00511 return *this = dst; 00512 } 00513 Point 00514 point (const Point &s) const 00515 { 00516 Point d; 00517 d.x = xx * s.x + xy * s.y + xz; 00518 d.y = yx * s.x + yy * s.y + yz; 00519 return d; 00520 } 00521 Point point (double x, double y) const { return point (Point (x, y)); } 00522 double 00523 determinant() const 00524 { 00525 /* if this is != 0, the affine is invertible */ 00526 return xx * yy - xy * yx; 00527 } 00528 double 00529 expansion() const 00530 { 00531 return sqrt (fabs (determinant())); 00532 } 00533 double 00534 hexpansion() const 00535 { 00536 Point p0 = point (Point (0, 0)); 00537 Point p1 = point (Point (1, 0)); 00538 return p1.dist (p0); 00539 } 00540 double 00541 vexpansion() const 00542 { 00543 Point p0 = point (Point (0, 0)); 00544 Point p1 = point (Point (0, 1)); 00545 return p1.dist (p0); 00546 } 00547 Affine& 00548 invert() 00549 { 00550 double rec_det = 1.0 / determinant(); 00551 Affine dst (yy, -xy, 0, -yx, xx, 0); 00552 dst.xx *= rec_det; 00553 dst.xy *= rec_det; 00554 dst.yx *= rec_det; 00555 dst.yy *= rec_det; 00556 dst.xz = -(dst.xx * xz + dst.xy * yz); 00557 dst.yz = -(dst.yy * yz + dst.yx * xz); 00558 return *this = dst; 00559 } 00560 Point 00561 ipoint (const Point &s) const 00562 { 00563 double rec_det = 1.0 / determinant(); 00564 Point d; 00565 d.x = yy * s.x - xy * s.y; 00566 d.x *= rec_det; 00567 d.x -= xz; 00568 d.y = xx * s.y - yx * s.x; 00569 d.y *= rec_det; 00570 d.y -= yz; 00571 return d; 00572 } 00573 Point ipoint (double x, double y) const { return ipoint (Point (x, y)); } 00574 Point 00575 operator* (const Point &p) const 00576 { 00577 return point (p); 00578 } 00579 Affine 00580 operator* (const Affine &a2) const 00581 { 00582 return Affine (*this).multiply (a2); 00583 } 00584 Affine& 00585 operator= (const Affine &a2) 00586 { 00587 xx = a2.xx; 00588 xy = a2.xy; 00589 xz = a2.xz; 00590 yx = a2.yx; 00591 yy = a2.yy; 00592 yz = a2.yz; 00593 return *this; 00594 } 00595 bool 00596 is_identity () const 00597 { 00598 return RAPICORN_ISLIKELY (xx == 1 && xy == 0 && xz == 0 && yx == 0 && yy == 1 && yz == 0); 00599 } 00600 Affine 00601 create_inverse () const 00602 { 00603 Affine inv (*this); 00604 return inv.invert(); 00605 } 00606 bool operator== (const Affine &oa) const { return xx == oa.xx && xy == oa.xy && xz == oa.xz && yx == oa.yx && yy == oa.yy && yz == oa.yz; } 00607 bool operator!= (const Affine &oa) const { return !operator== (oa); } 00608 String string() const; 00609 static Affine from_triangles (Point src_a, Point src_b, Point src_c, 00610 Point dst_a, Point dst_b, Point dst_c); 00611 struct VectorReturn { double x, y, z; }; 00612 VectorReturn x() const { VectorReturn v = { xx, xy, xz }; return v; } 00613 VectorReturn y() const { VectorReturn v = { yx, yy, yz }; return v; } 00614 }; 00615 struct AffineIdentity : Affine { 00616 AffineIdentity() : 00617 Affine (1, 0, 0, 0, 1, 0) 00618 {} 00619 }; 00620 struct AffineHFlip : Affine { 00621 AffineHFlip() : 00622 Affine (-1, 0, 0, 0, 1, 0) 00623 {} 00624 }; 00625 struct AffineVFlip : Affine { 00626 AffineVFlip() : 00627 Affine (1, 0, 0, 0, -1, 0) 00628 {} 00629 }; 00630 struct AffineTranslate : Affine { 00631 AffineTranslate (double tx, double ty) 00632 { 00633 xx = 1; 00634 xy = 0; 00635 xz = tx; 00636 yx = 0; 00637 yy = 1; 00638 yz = ty; 00639 } 00640 AffineTranslate (Point p) 00641 { 00642 xx = 1; 00643 xy = 0; 00644 xz = p.x; 00645 yx = 0; 00646 yy = 1; 00647 yz = p.y; 00648 } 00649 }; 00650 struct AffineScale : Affine { 00651 AffineScale (double sx, double sy) 00652 { 00653 xx = sx; 00654 xy = 0; 00655 xz = 0; 00656 yx = 0; 00657 yy = sy; 00658 yz = 0; 00659 } 00660 }; 00661 struct AffineRotate : Affine { 00662 AffineRotate (double theta) 00663 { 00664 double s = sin (theta); 00665 double c = cos (theta); 00666 xx = c; 00667 xy = -s; 00668 xz = 0; 00669 yx = s; 00670 yy = c; 00671 yz = 0; 00672 } 00673 AffineRotate (double theta, Point anchor) 00674 { 00675 rotate (theta, anchor); 00676 } 00677 }; 00678 struct AffineShear : Affine { 00679 AffineShear (double shearx, double sheary) 00680 { 00681 xx = 1; 00682 xy = shearx; 00683 xz = 0; 00684 yx = sheary; 00685 yy = 1; 00686 yz = 0; 00687 } 00688 AffineShear (double theta) 00689 { 00690 xx = 1; 00691 xy = tan (theta); 00692 xz = 0; 00693 yx = 0; 00694 yy = 1; 00695 yz = 0; 00696 } 00697 }; 00698 00699 /* --- Display --- */ 00700 class Display : protected NonCopyable { 00701 std::list<Rect> clip_stack; 00702 cairo_t *m_backing; 00703 public: 00704 explicit Display (); 00705 virtual ~Display (); 00706 void push_clip_rect (int x, int y, uint width, uint height) { push_clip_rect (Rect (Point (x, y), width, height)); } 00707 void push_clip_rect (const Rect &rect); 00708 Rect current_rect (); 00709 cairo_t* create_cairo (Color c = 0x00000000); 00710 void set_backing (cairo_t *cairo); 00711 Rect extents () const; 00712 bool empty () const; 00713 void pop_clip_rect (); 00714 void render_backing (cairo_t *cairo); 00715 }; 00716 00717 /* --- implementations --- */ 00718 inline bool 00719 Point::equals (const Point &p2, 00720 double epsilon) const 00721 { 00722 return fabs (x - p2.x) <= epsilon && fabs (y - p2.y) <= epsilon; 00723 } 00724 00725 inline 00726 Rect::Rect () : 00727 x (0), y (0), width (0), height (0) 00728 {} 00729 00730 inline Rect& 00731 Rect::assign (double cx, double cy, double cwidth, double cheight) 00732 { 00733 x = cx; 00734 y = cy; 00735 width = MAX (cwidth, 0); 00736 height = MAX (cheight, 0); 00737 return *this; 00738 } 00739 00740 inline 00741 Rect::Rect (double cx, double cy, double cwidth, double cheight) 00742 { 00743 assign (cx, cy, cwidth, cheight); 00744 } 00745 00746 inline Rect& 00747 Rect::assign (Point p0, double cwidth, double cheight) 00748 { 00749 return assign (p0.x, p0.y, cwidth, cheight); 00750 } 00751 00752 inline 00753 Rect::Rect (Point p0, double cwidth, double cheight) 00754 { 00755 assign (p0, cwidth, cheight); 00756 } 00757 00758 inline Rect& 00759 Rect::assign (Point p0, Point p1) 00760 { 00761 Point mll (min (p0, p1)); 00762 Point mur (max (p0, p1)); 00763 x = p0.x; 00764 y = p0.y; 00765 width = mur.x - mll.x; 00766 height = mur.y - mll.y; 00767 return *this; 00768 } 00769 00770 inline 00771 Rect::Rect (Point cp0, Point cp1) 00772 { 00773 assign (cp0, cp1); 00774 } 00775 00776 inline bool 00777 Rect::operator== (const Rect &other) const 00778 { 00779 if (empty() && other.empty()) 00780 return true; 00781 return other.x == x && other.y == y && other.width == width && other.height == height; 00782 } 00783 00784 inline bool 00785 Rect::equals (const Rect &other, 00786 double epsilon) const 00787 { 00788 if (empty() && other.empty()) 00789 return true; 00790 return (fabs (other.x - x) <= epsilon && 00791 fabs (other.y - y) <= epsilon && 00792 fabs (other.width - width) <= epsilon && 00793 fabs (other.height - height) <= epsilon); 00794 } 00795 00796 inline Rect& 00797 Rect::add_border (double b) 00798 { 00799 x -= b; 00800 y -= b; 00801 width += 2 * b; 00802 height += 2 * b; 00803 return *this; 00804 } 00805 00806 inline Rect& 00807 Rect::add (const Point &p) 00808 { 00809 if (empty()) 00810 assign (p, 0, 0); 00811 else 00812 assign (min (p, lower_left()), max (p, upper_right())); 00813 return *this; 00814 } 00815 00816 inline Rect& 00817 Rect::rect_union (const Rect &r) 00818 { 00819 if (r.empty()) 00820 return *this; 00821 if (empty()) 00822 return *this = r; 00823 Point mll = min (lower_left(), r.lower_left()); 00824 Point mur = max (upper_right(), r.upper_right()); 00825 assign (mll, mur); 00826 return *this; 00827 } 00828 00829 inline Rect& 00830 Rect::intersect (const Rect &r) 00831 { 00832 Point pll = max (lower_left(), r.lower_left()); 00833 Point pur = min (upper_right(), r.upper_right()); 00834 if (pll.x <= pur.x && pll.y <= pur.y) 00835 assign (pll, pur); 00836 else 00837 *this = Rect(); 00838 return *this; 00839 } 00840 00841 inline bool 00842 Rect::empty () const 00843 { 00844 return width * height == 0; 00845 } 00846 00847 inline Rect& 00848 Rect::translate (double deltax, 00849 double delty) 00850 { 00851 x += deltax; 00852 y += delty; 00853 return *this; 00854 } 00855 00856 } // Rapicorn 00857 00858 #endif /* __RAPICORN_PRIMITIVES_HH__ */
1.7.4