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