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