Rapicorn - Experimental UI Toolkit - Source Code  13.07.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
primitives.hh
Go to the documentation of this file.
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__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines