Author: mdk
Date: 2008-02-14 10:25:50 -0500 (Thu, 14 Feb 2008)
New Revision: 95638

Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/shape.cpp
   trunk/moon/src/shape.h
Log:
2008-02-14  Michael Dominic K.  <[EMAIL PROTECTED]>

        * src/shape.cpp:
        * src/shape.h: Adding surface caching for shapes. The strategy
        is to cache big surfaces that have little transformations (such as
        ie. backgrounds, fade overlays, etc.). Improves performance greatly
        for many sites (ie. Showcase).


Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2008-02-14 15:23:13 UTC (rev 95637)
+++ trunk/moon/src/ChangeLog    2008-02-14 15:25:50 UTC (rev 95638)
@@ -1,5 +1,13 @@
 2008-02-14  Michael Dominic K.  <[EMAIL PROTECTED]>
 
+       * src/shape.cpp:
+       * src/shape.h: Adding surface caching for shapes. The strategy
+       is to cache big surfaces that have little transformations (such as
+       ie. backgrounds, fade overlays, etc.). Improves performance greatly
+       for many sites (ie. Showcase).
+
+2008-02-14  Michael Dominic K.  <[EMAIL PROTECTED]> 
+
        * src/uielement.cpp: Commenting out the timer in post-pre render as it's
        broken and blocks the compilation with timers on.
 

Modified: trunk/moon/src/shape.cpp
===================================================================
--- trunk/moon/src/shape.cpp    2008-02-14 15:23:13 UTC (rev 95637)
+++ trunk/moon/src/shape.cpp    2008-02-14 15:25:50 UTC (rev 95638)
@@ -5,6 +5,7 @@
  *   Miguel de Icaza ([EMAIL PROTECTED])
  *   Sebastien Pouliot  <[EMAIL PROTECTED]>
  *   Stephane Delcroix  <[EMAIL PROTECTED]>
+ *   Michael Dominic K. <[EMAIL PROTECTED]>
  *
  * Copyright 2007-2008 Novell, Inc. (http://www.novell.com)
  *
@@ -107,6 +108,7 @@
        fill = NULL;
        path = NULL;
        origin = Point (0, 0);
+       cached_surface = NULL;
        SetShapeFlags (UIElement::SHAPE_NORMAL);
 }
 
@@ -121,6 +123,8 @@
                fill->Detach (NULL, this);
                fill->unref ();
        }
+
+       // That also destroys the cached surface
        InvalidatePathCache (true);
 }
 
@@ -270,37 +274,79 @@
        }
 }
 
+int number = 0;
+
 //
+// Returns TRUE if surface is a good candidate for caching.
+// Our current strategy is to cache big surfaces (likely backgrounds)
+// that don't scale tranformations. We accept a little bit of scaling though.
+//
+bool
+Shape::IsCandidateForCaching (void)
+{
+       if (bounds.w + bounds.h < 300)
+               return FALSE;
+
+       int diffw = fabs (bounds.w - extents.w);
+       int diffh = fabs (bounds.h - extents.h);
+
+       if (diffw > 5 || diffh > 5)
+               return FALSE;
+
+       return TRUE;
+}
+
+//
 // This routine is useful for Shape derivatives: it can be used
 // to either get the bounding box from cairo, or to paint it
 //
 void
 Shape::DoDraw (cairo_t *cr, bool do_op)
 {
+       int w;
+       int h;
+       cairo_t *cached_cr = NULL;
+       cairo_pattern_t *cached_pattern = NULL;
+       bool ret = FALSE;
+       gchar *fname;
+
        // quick out if, when building the path, we detected a empty shape
        if (IsEmpty ())
                goto cleanpath;
 
-       cairo_set_matrix (cr, &absolute_xform);
+       if (!do_op) {
+               cairo_set_matrix (cr, &absolute_xform);
+               Clip (cr);
 
-//     printf ("Draw, xform: %g %g %g %g %g %g\n", 
-//             absolute_xform.xy,
-//             absolute_xform.xx,
-//             absolute_xform.yx,
-//             absolute_xform.yy,
-//             absolute_xform.x0,
-//             absolute_xform.y0);
-
-       Clip (cr);
-
-       // if building the path detected a degenerate case
-       if (IsDegenerate ()) {
-               // FIXME: needs a DrawDegenerateShape to get more control over 
output
                if (DrawShape (cr, do_op))
                        return;
        } else {
-               if (DrawShape (cr, do_op))
-                       return;
+               if (cached_surface == NULL && IsCandidateForCaching ()) {
+                       w = extents.w + extents.x;
+                       h = extents.h + extents.y;
+                       w = MAX (w, 1);
+                       h = MAX (h, 1);
+
+                       cached_surface = image_brush_create_similar (cr, w, h);
+                       cached_cr = cairo_create (cached_surface);
+                       ret = DrawShape (cached_cr, do_op);
+                       cairo_destroy (cached_cr);
+               }
+
+               cairo_set_matrix (cr, &absolute_xform);
+               Clip (cr);
+
+               if (cached_surface) {
+                       cached_pattern = cairo_pattern_create_for_surface 
(cached_surface);
+                       cairo_set_source (cr, cached_pattern);
+                       cairo_paint (cr);
+                       cairo_pattern_destroy (cached_pattern);
+                       if (ret)
+                               return;
+               } else {
+                       if (DrawShape (cr, do_op))
+                               return;
+               }
        }
 
 cleanpath:
@@ -397,6 +443,7 @@
 void
 Shape::OnPropertyChanged (DependencyProperty *prop)
 {
+
        if (prop->type != Type::SHAPE) {
                if ((prop == FrameworkElement::HeightProperty) || (prop == 
FrameworkElement::WidthProperty))
                        InvalidatePathCache ();
@@ -420,6 +467,7 @@
                        stroke->ref ();
                }
 
+               InvalidateSurfaceCache ();
                UpdateBounds ();
        } else if (prop == Shape::FillProperty) {
                if (fill != NULL) {
@@ -432,6 +480,7 @@
                        fill->ref ();
                }
 
+               InvalidateSurfaceCache ();
                UpdateBounds ();
        } else if (prop == Shape::StrokeThicknessProperty) {
                InvalidatePathCache ();
@@ -442,6 +491,7 @@
                   || prop == Shape::StrokeMiterLimitProperty
                   || prop == Shape::StrokeStartLineCapProperty) {
                UpdateBounds ();
+               InvalidateSurfaceCache ();
        }
        
        Invalidate ();
@@ -454,6 +504,7 @@
 {
        if (prop == Shape::FillProperty || prop == Shape::StrokeProperty) {
                Invalidate ();
+               InvalidateSurfaceCache ();
        }
        else
                FrameworkElement::OnSubPropertyChanged (prop, obj, subprop);
@@ -468,7 +519,6 @@
                framework_element_get_height (this) * user_xform_origin.y);
 }
 
-
 void
 Shape::InvalidatePathCache (bool free)
 {
@@ -481,8 +531,19 @@
                        moon_path_clear (path);
                }
        }
+
+       InvalidateSurfaceCache ();
 }
 
+void
+Shape::InvalidateSurfaceCache (void)
+{
+       if (cached_surface) {
+               cairo_surface_destroy (cached_surface);
+               cached_surface = NULL;
+       }
+}
+
 Brush *
 shape_get_fill (Shape *shape)
 {
@@ -762,6 +823,7 @@
        if ((prop == Shape::StrokeThicknessProperty) || (prop == 
Shape::StretchProperty) ||
                (prop == FrameworkElement::WidthProperty) || (prop == 
FrameworkElement::HeightProperty)) {
                BuildPath ();
+               InvalidateSurfaceCache ();
        }
 
        // Ellipse has no property of it's own

Modified: trunk/moon/src/shape.h
===================================================================
--- trunk/moon/src/shape.h      2008-02-14 15:23:13 UTC (rev 95637)
+++ trunk/moon/src/shape.h      2008-02-14 15:25:50 UTC (rev 95638)
@@ -4,6 +4,7 @@
  * Author:
  *   Miguel de Icaza ([EMAIL PROTECTED])
  *   Sebastien Pouliot  <[EMAIL PROTECTED]>
+ *   Michael Dominic K. <[EMAIL PROTECTED]>
  *
  * Copyright 2007-2008 Novell, Inc. (http://www.novell.com)
  *
@@ -36,6 +37,8 @@
  protected:
        Brush *stroke, *fill;
        Point origin;
+       cairo_surface_t *cached_surface;
+
        void DoDraw (cairo_t *cr, bool do_op);
 
        void SetupLineCaps (cairo_t *cr);
@@ -49,6 +52,8 @@
 
        moon_path *path;
        virtual void InvalidatePathCache (bool free = false);
+       void InvalidateSurfaceCache (void);
+       bool IsCandidateForCaching (void);
 
        virtual Rect ComputeShapeBounds ();
        virtual Rect ComputeLargestRectangle ();

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to