Author: spouliot
Date: 2008-02-07 08:15:52 -0500 (Thu, 07 Feb 2008)
New Revision: 95133
Modified:
trunk/moon/src/ChangeLog
trunk/moon/src/shape.cpp
trunk/moon/src/shape.h
Log:
2008-02-07 Sebastien Pouliot <[EMAIL PROTECTED]>
* shape.cpp|h: Split ComputeBounds to avoid calling functions
bounding_rect_for_transformed_rect and IntersectBoundsWithClipPath
inside each shape. This will enable us to reuse the non-transformed
value elsewhere too. This also fix (for me) the origin point that
caused problems for some brushes. Started implementing methods
ComputeLargestRectangle[Bounds] to optimize drawing.
Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog 2008-02-07 12:50:37 UTC (rev 95132)
+++ trunk/moon/src/ChangeLog 2008-02-07 13:15:52 UTC (rev 95133)
@@ -1,3 +1,12 @@
+2008-02-07 Sebastien Pouliot <[EMAIL PROTECTED]>
+
+ * shape.cpp|h: Split ComputeBounds to avoid calling functions
+ bounding_rect_for_transformed_rect and IntersectBoundsWithClipPath
+ inside each shape. This will enable us to reuse the non-transformed
+ value elsewhere too. This also fix (for me) the origin point that
+ caused problems for some brushes. Started implementing methods
+ ComputeLargestRectangle[Bounds] to optimize drawing.
+
2008-02-06 Chris Toshok <[EMAIL PROTECTED]>
* frameworkelement.cpp (FrameworkElement::GetSizeForBrush): we
Modified: trunk/moon/src/shape.cpp
===================================================================
--- trunk/moon/src/shape.cpp 2008-02-07 12:50:37 UTC (rev 95132)
+++ trunk/moon/src/shape.cpp 2008-02-07 13:15:52 UTC (rev 95133)
@@ -319,47 +319,47 @@
void
Shape::ComputeBounds ()
{
- bounds = Rect (0,0,0,0);
+ Rect shape_bounds = ComputeShapeBounds ();
+ bounds = bounding_rect_for_transformed_rect (&absolute_xform,
+ IntersectBoundsWithClipPath (shape_bounds, false));
+ //printf ("%f,%f,%f,%f\n", bounds.x, bounds.y, bounds.w, bounds.h);
+}
+Rect
+Shape::ComputeShapeBounds ()
+{
if (IsEmpty ())
- return;
+ return Rect ();
double w = framework_element_get_width (this);
double h = framework_element_get_height (this);
-#if FALSE
- Stretch stretch = shape_get_stretch (this);
- switch (stretch) {
- case StretchUniform:
- w = h = (w < h) ? w : h;
- break;
- case StretchUniformToFill:
- w = h = (w > h) ? w : h;
- break;
- case StretchFill:
- /* nothing needed here. the assignment of w/h above
- is correct for this case. */
- break;
- case StretchNone:
- break;
- }
-#endif
+ if ((w == 0.0) && (h == 0.0))
+ return Rect ();
- if (w != 0.0 && h != 0.0) {
- double t = shape_get_stroke_thickness (this) * .5;
+ double t = shape_get_stroke_thickness (this) * .5;
- bounds = bounding_rect_for_transformed_rect (&absolute_xform,
- IntersectBoundsWithClipPath (Rect (-t, -t, w + 2 * t, h
+ 2 * t), false));
+ return Rect (-t, -t, w + 2 * t, h + 2 * t);
+}
- //printf ("%f,%f,%f,%f\n", bounds.x, bounds.y, bounds.w,
bounds.h);
- }
+Rect
+Shape::ComputeLargestRectangleBounds ()
+{
+ Rect largest = ComputeLargestRectangle ();
+ if (largest.IsEmpty ())
+ return largest;
- /* standard "grow the rectangle by enough to cover our
- asses because of cairo's floating point rendering"
- thing */
-// no-op bounds.GrowBy(1);
+ return bounding_rect_for_transformed_rect (&absolute_xform,
+ IntersectBoundsWithClipPath
(largest, false));
}
+Rect
+Shape::ComputeLargestRectangle ()
+{
+ // by default the largest rectangle that fits into a shape is empty
+ return Rect ();
+}
+
void
Shape::GetSizeForBrush (cairo_t *cr, double *width, double *height)
{
@@ -765,6 +765,15 @@
// note: both moon_rounded_rectangle and moon_ellipse close the path
}
+Rect
+Ellipse::ComputeLargestRectangle ()
+{
+ double t = GetValue (Shape::StrokeThicknessProperty)->AsDouble ();
+ double x = (GetValue (FrameworkElement::WidthProperty)->AsDouble () -
t) * cos (M_PI_2);
+ double y = (GetValue (FrameworkElement::HeightProperty)->AsDouble () -
t) * sin (M_PI_2);
+ Rect largest = ComputeShapeBounds ().GrowBy (-x, -y).RoundIn ();
+}
+
void
Ellipse::OnPropertyChanged (DependencyProperty *prop)
{
@@ -1007,10 +1016,22 @@
return ((*rx != 0.0) && (*ry != 0.0));
}
+Rect
+Rectangle::ComputeLargestRectangle ()
+{
+ double x = GetValue (Shape::StrokeThicknessProperty)->AsDouble ();
+ double y = x;
+ if (HasRadii ()) {
+ x += GetValue (Rectangle::RadiusXProperty)->AsDouble ();
+ y += GetValue (Rectangle::RadiusYProperty)->AsDouble ();
+ }
+ return ComputeShapeBounds ().GrowBy (-x, -y).RoundIn ();
+}
+
double
rectangle_get_radius_x (Rectangle *rectangle)
{
- return rectangle->GetValue (Rectangle::RadiusXProperty)->AsDouble();
+ return rectangle->GetValue (Rectangle::RadiusXProperty)->AsDouble ();
}
void
@@ -1182,39 +1203,36 @@
moon_line_to (path, line_get_x2 (this), line_get_y2 (this));
}
-void
-Line::ComputeBounds ()
+Rect
+Line::ComputeShapeBounds ()
{
+ Rect shape_bounds = Rect ();
+
Value *vh, *vw;
- if (Shape::MixedHeightWidth (&vh, &vw)) {
- bounds = Rect (0.0, 0.0, 0.0, 0.0);
- return;
- }
+ if (Shape::MixedHeightWidth (&vh, &vw))
+ return shape_bounds;
double thickness = shape_get_stroke_thickness (this);
- if (thickness <= 0.0) {
- bounds = Rect (0.0, 0.0, 0.0, 0.0);
- return;
- }
+ if (thickness <= 0.0)
+ return shape_bounds;
double x1 = line_get_x1 (this);
double y1 = line_get_y1 (this);
double x2 = line_get_x2 (this);
double y2 = line_get_y2 (this);
- calc_line_bounds (x1, x2, y1, y2, thickness, &bounds);
+ calc_line_bounds (x1, x2, y1, y2, thickness, &shape_bounds);
origin.x = MIN (x1, x2);
origin.y = MIN (y1, y2);
// if Height and Width are specified (they could be both missing)
// then we must clip the line those values
if (vh && vw) {
- bounds.w = MIN (bounds.w, vw->AsDouble ());
- bounds.h = MIN (bounds.h, vh->AsDouble ());
+ shape_bounds.w = MIN (shape_bounds.w, vw->AsDouble ());
+ shape_bounds.h = MIN (shape_bounds.h, vh->AsDouble ());
}
- bounds = bounding_rect_for_transformed_rect (&absolute_xform,
-
IntersectBoundsWithClipPath (bounds, false));
+ return shape_bounds;
}
void
@@ -1450,23 +1468,21 @@
}
}
-void
-Polygon::ComputeBounds ()
+Rect
+Polygon::ComputeShapeBounds ()
{
+ Rect shape_bounds = Rect ();
+
Value *vh, *vw;
- if (Shape::MixedHeightWidth (&vh, &vw)) {
- bounds = Rect (0.0, 0.0, 0.0, 0.0);
- return;
- }
+ if (Shape::MixedHeightWidth (&vh, &vw))
+ return shape_bounds;
int i, count = 0;
Point *points = polygon_get_points (this, &count);
// the first point is a move to, resulting in an empty shape
- if (!points || (count < 2)) {
- bounds = Rect (0.0, 0.0, 0.0, 0.0);
- return;
- }
+ if (!points || (count < 2))
+ return shape_bounds;
double thickness = shape_get_stroke_thickness (this);
if (thickness == 0.0)
@@ -1483,10 +1499,10 @@
origin.y = MIN (origin.y, points[1].y);
polygon_extend_line (&x0, &x1, &y0, &y1, thickness);
- calc_line_bounds (x0, x1, y0, y1, thickness, &bounds);
+ calc_line_bounds (x0, x1, y0, y1, thickness, &shape_bounds);
} else {
- bounds.x = x1 = x0;
- bounds.y = y1 = y0;
+ shape_bounds.x = x1 = x0;
+ shape_bounds.y = y1 = y0;
// FIXME: we're too big for large thickness and/or steep angle
Rect line_bounds;
double x2 = points [1].x;
@@ -1496,7 +1512,7 @@
origin.x = MIN (origin.x, MIN (x2, x3));
origin.y = MIN (origin.y, MIN (y2, y3));
- calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3, thickness,
&bounds);
+ calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3, thickness,
&shape_bounds);
for (i = 3; i < count; i++) {
x1 = x2;
y1 = y2;
@@ -1506,7 +1522,7 @@
y3 = points [i].y;
origin.x = MIN (origin.x, x3);
origin.y = MIN (origin.y, y3);
- calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3,
thickness, &bounds);
+ calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3,
thickness, &shape_bounds);
}
// a polygon is a closed shape (unless it's a line)
x1 = x2;
@@ -1515,7 +1531,7 @@
y2 = y3;
x3 = x0;
y3 = y0;
- calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3, thickness,
&bounds);
+ calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3, thickness,
&shape_bounds);
x1 = points [count-1].x;
y1 = points [count-1].y;
@@ -1523,24 +1539,23 @@
y2 = y0;
x3 = points [1].x;
y3 = points [1].y;
- calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3, thickness,
&bounds);
+ calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3, thickness,
&shape_bounds);
}
if (shape_get_stretch (this) != StretchNone) {
- bounds.x -= x0;
- bounds.y -= y0;
+ shape_bounds.x -= x0;
+ shape_bounds.y -= y0;
}
// if Height and Width are specified (they could be both missing)
// then we must clip the path those values, and this also defines
// *exactly* our bounds (whether we like them or not is another story)
if (vh && vw) {
- bounds.w = vw->AsDouble ();
- bounds.h = vh->AsDouble ();
+ shape_bounds.w = vw->AsDouble ();
+ shape_bounds.h = vh->AsDouble ();
}
- bounds = bounding_rect_for_transformed_rect (&absolute_xform,
-
IntersectBoundsWithClipPath (bounds, false));
+ return shape_bounds;
}
void
@@ -1758,23 +1773,21 @@
return polyline_get_fill_rule (this);
}
-void
-Polyline::ComputeBounds ()
+Rect
+Polyline::ComputeShapeBounds ()
{
+ Rect shape_bounds = Rect ();
+
Value *vh, *vw;
- if (Shape::MixedHeightWidth (&vh, &vw)) {
- bounds = Rect (0.0, 0.0, 0.0, 0.0);
- return;
- }
+ if (Shape::MixedHeightWidth (&vh, &vw))
+ return shape_bounds;
int i, count = 0;
Point *points = polyline_get_points (this, &count);
// the first point is a move to, resulting in an empty shape
- if (!points || (count < 2)) {
- bounds = Rect (0.0, 0.0, 0.0, 0.0);
- return;
- }
+ if (!points || (count < 2))
+ return shape_bounds;
double thickness = shape_get_stroke_thickness (this);
if (thickness == 0.0)
@@ -1789,7 +1802,7 @@
double y2 = points [1].y;
origin.x = MIN (origin.x, x2);
origin.y = MIN (origin.y, y2);
- calc_line_bounds (x1, x2, y1, y2, thickness, &bounds);
+ calc_line_bounds (x1, x2, y1, y2, thickness, &shape_bounds);
} else {
// FIXME: we're too big for large thickness and/or steep angle
Rect line_bounds;
@@ -1797,37 +1810,36 @@
double y2 = points [1].y;
origin.x = MIN (origin.x, x2);
origin.y = MIN (origin.y, y2);
- calc_line_bounds (x1, x2, y1, y2, thickness, &bounds);
+ calc_line_bounds (x1, x2, y1, y2, thickness, &shape_bounds);
for (i = 2; i < count; i++) {
double x3 = points [i].x;
double y3 = points [i].y;
origin.x = MIN (origin.x, x3);
origin.y = MIN (origin.y, y3);
- calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3,
thickness, &bounds);
+ calc_line_bounds_with_joins (x1, y1, x2, y2, x3, y3,
thickness, &shape_bounds);
x1 = x2;
y1 = y2;
x2 = x3;
y2 = y3;
}
calc_line_bounds (x1, x2, y1, y2, thickness, &line_bounds);
- bounds = bounds.Union (line_bounds);
+ shape_bounds = shape_bounds.Union (line_bounds);
}
if (shape_get_stretch (this) != StretchNone) {
- bounds.x -= points [0].x;
- bounds.y -= points [0].y;
+ shape_bounds.x -= points [0].x;
+ shape_bounds.y -= points [0].y;
}
// if Height and Width are specified (they could be both missing)
// then we must clip the path those values, and this also defines
// *exactly* our bounds (whether we like them or not is another story)
if (vh && vw) {
- bounds.w = vw->AsDouble ();
- bounds.h = vh->AsDouble ();
+ shape_bounds.w = vw->AsDouble ();
+ shape_bounds.h = vh->AsDouble ();
}
- bounds = bounding_rect_for_transformed_rect (&absolute_xform,
-
IntersectBoundsWithClipPath (bounds, false));
+ return shape_bounds;
}
void
@@ -1997,20 +2009,20 @@
return geometry ? geometry_get_fill_rule (geometry) :
Shape::GetFillRule ();
}
-void
-Path::ComputeBounds ()
+Rect
+Path::ComputeShapeBounds ()
{
- bounds = Rect (0.0, 0.0, 0.0, 0.0);
+ Rect shape_bounds = Rect ();
cairo_matrix_init_identity (&stretch_transform);
Value *vh, *vw;
if (Shape::MixedHeightWidth (&vh, &vw))
- return;
+ return shape_bounds;
Geometry* geometry = path_get_data (this);
if (!geometry) {
SetShapeFlags (UIElement::SHAPE_EMPTY);
- return;
+ return shape_bounds;
}
double w = vw ? vw->AsDouble () : 0.0;
@@ -2018,30 +2030,30 @@
if ((h < 0.0) || (w < 0.0)) {
SetShapeFlags (UIElement::SHAPE_EMPTY);
- return;
+ return shape_bounds;
}
if (vh && (h <= 0.0) || vw && (w <= 0.0)) {
SetShapeFlags (UIElement::SHAPE_EMPTY);
- return;
+ return shape_bounds;
}
- bounds = geometry->ComputeBounds (this);
+ shape_bounds = geometry->ComputeBounds (this);
- h = (h == 0.0) ? bounds.h : h;
- w = (w == 0.0) ? bounds.w : w;
+ h = (h == 0.0) ? shape_bounds.h : h;
+ w = (w == 0.0) ? shape_bounds.w : w;
if (h <= 0.0 || w <= 0.0) {
SetShapeFlags (UIElement::SHAPE_EMPTY);
- return;
+ return shape_bounds;
}
// Compute the transformation we use for stretching
Stretch stretch = shape_get_stretch (this);
if (stretch != StretchNone) {
- double sh = h / bounds.h;
- double sw = w / bounds.w;
+ double sh = h / shape_bounds.h;
+ double sw = w / shape_bounds.w;
switch (stretch) {
case StretchFill:
break;
@@ -2057,28 +2069,26 @@
}
cairo_matrix_scale (&stretch_transform, sw, sh);
- cairo_matrix_translate (&stretch_transform, -bounds.x,
-bounds.y);
+ cairo_matrix_translate (&stretch_transform, -shape_bounds.x,
-shape_bounds.y);
// Double check our math
cairo_matrix_t test = stretch_transform;
if (cairo_matrix_invert (&test)) {
cairo_matrix_init_identity (&stretch_transform);
- g_warning ("Unable to compute stretch transform %f %f
%f %f \n", sw, sh, bounds.x, bounds.y);
+ g_warning ("Unable to compute stretch transform %f %f
%f %f \n", sw, sh, shape_bounds.x, shape_bounds.y);
}
}
- bounds = bounding_rect_for_transformed_rect (&stretch_transform,
bounds);
+ shape_bounds = bounding_rect_for_transformed_rect (&stretch_transform,
shape_bounds);
if (vh && vw) {
- bounds.w = MIN (bounds.w, vw->AsDouble ());
- bounds.h = MIN (bounds.h, vh->AsDouble ());
+ shape_bounds.w = MIN (shape_bounds.w, vw->AsDouble ());
+ shape_bounds.h = MIN (shape_bounds.h, vh->AsDouble ());
}
- bounds = bounding_rect_for_transformed_rect (&absolute_xform,
-
IntersectBoundsWithClipPath (bounds, false));
//FIXME
- origin = Point (bounds.x, bounds.y);
-
+ origin = Point (shape_bounds.x, shape_bounds.y);
+ return shape_bounds;
}
void
Modified: trunk/moon/src/shape.h
===================================================================
--- trunk/moon/src/shape.h 2008-02-07 12:50:37 UTC (rev 95132)
+++ trunk/moon/src/shape.h 2008-02-07 13:15:52 UTC (rev 95133)
@@ -49,6 +49,9 @@
moon_path *path;
virtual void InvalidatePathCache (bool free = false);
+
+ virtual Rect ComputeShapeBounds ();
+ virtual Rect ComputeLargestRectangle ();
public:
static DependencyProperty* FillProperty;
static DependencyProperty* StretchProperty;
@@ -74,9 +77,9 @@
virtual void ComputeBounds ();
virtual bool InsideObject (cairo_t *cr, double x, double y);
virtual Point GetTransformOrigin ();
- virtual Point GetOriginPoint () {
- return origin;
- }
+ virtual Point GetOriginPoint () { return origin; }
+
+ Rect ComputeLargestRectangleBounds ();
//
// new virtual methods for shapes
@@ -142,6 +145,7 @@
class Ellipse : public Shape {
protected:
virtual bool DrawShape (cairo_t *cr, bool do_op);
+ virtual Rect ComputeLargestRectangle ();
public:
Ellipse ();
virtual Type::Kind GetObjectType () { return Type::ELLIPSE; };
@@ -169,11 +173,12 @@
virtual Type::Kind GetObjectType () { return Type::RECTANGLE; };
virtual void BuildPath ();
+ virtual bool CanFill () { return true; }
virtual void OnPropertyChanged (DependencyProperty *prop);
bool GetRadius (double *rx, double *ry);
- virtual bool CanFill () { return true; }
+ virtual Rect ComputeLargestRectangle ();
};
Rectangle *rectangle_new (void);
@@ -189,6 +194,7 @@
class Line : public Shape {
protected:
virtual bool DrawShape (cairo_t *cr, bool do_op);
+ virtual Rect ComputeShapeBounds ();
public:
static DependencyProperty* X1Property;
static DependencyProperty* Y1Property;
@@ -198,7 +204,6 @@
virtual Type::Kind GetObjectType () { return Type::LINE; };
virtual void BuildPath ();
- virtual void ComputeBounds ();
virtual bool ClipOnHeightAndWidth () { return true; }
virtual void OnPropertyChanged (DependencyProperty *prop);
@@ -224,6 +229,7 @@
class Polygon : public Shape {
protected:
virtual bool DrawShape (cairo_t *cr, bool do_op);
+ virtual Rect ComputeShapeBounds ();
public:
static DependencyProperty* FillRuleProperty;
static DependencyProperty* PointsProperty;
@@ -241,7 +247,6 @@
virtual bool CanFill () { return true; }
virtual void GetSizeForBrush (cairo_t *cr, double *width, double
*height);
- virtual void ComputeBounds ();
virtual bool ClipOnHeightAndWidth () { return true; }
virtual void OnPropertyChanged (DependencyProperty *prop);
@@ -261,6 +266,7 @@
class Polyline : public Shape {
protected:
virtual bool DrawShape (cairo_t *cr, bool do_op);
+ virtual Rect ComputeShapeBounds ();
public:
static DependencyProperty* FillRuleProperty;
static DependencyProperty* PointsProperty;
@@ -275,7 +281,6 @@
virtual bool CanFill () { return true; }
virtual void GetSizeForBrush (cairo_t *cr, double *width, double
*height);
- virtual void ComputeBounds ();
virtual bool ClipOnHeightAndWidth () { return true; }
virtual FillRule GetFillRule ();
@@ -298,6 +303,8 @@
protected:
virtual bool SetupLine (cairo_t* cr);
virtual bool DrawShape (cairo_t *cr, bool do_op);
+ virtual Rect ComputeShapeBounds ();
+
cairo_matrix_t stretch_transform;
public:
static DependencyProperty* DataProperty;
@@ -312,7 +319,6 @@
virtual void Draw (cairo_t *cr);
virtual void GetSizeForBrush (cairo_t *cr, double *width, double
*height);
- virtual void ComputeBounds ();
virtual bool ClipOnHeightAndWidth () { return true; }
virtual bool CanFill () { return true; }
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches