X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkborderimage.c;h=694db6fe0a86c079643af176c142f6321b52a1aa;hb=b9e189150bfd62c9e956e29324622058672600f0;hp=f5cca50dfe5e3206a224333ac542834820430fdb;hpb=3d1407a01a1e772f8b042801bbbde95ae1e16f9a;p=~andy%2Fgtk diff --git a/gtk/gtkborderimage.c b/gtk/gtkborderimage.c index f5cca50df..694db6fe0 100644 --- a/gtk/gtkborderimage.c +++ b/gtk/gtkborderimage.c @@ -16,9 +16,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include @@ -27,189 +25,31 @@ #include #include "gtkborderimageprivate.h" +#include "gtkcssbordervalueprivate.h" +#include "gtkcssimagevalueprivate.h" +#include "gtkcssnumbervalueprivate.h" +#include "gtkcssrepeatvalueprivate.h" +#include "gtkstylepropertiesprivate.h" +#include "gtkthemingengineprivate.h" + +/* this is in case round() is not provided by the compiler, + * such as in the case of C89 compilers, like MSVC + */ +#include "fallback-c89.c" -G_DEFINE_BOXED_TYPE (GtkBorderImage, _gtk_border_image, - _gtk_border_image_ref, _gtk_border_image_unref) - -enum { - BORDER_LEFT, - BORDER_MIDDLE, - BORDER_RIGHT, - BORDER_LAST, - BORDER_TOP = BORDER_LEFT, - BORDER_BOTTOM = BORDER_RIGHT -}; - -enum { - SIDE_TOP, - SIDE_RIGHT, - SIDE_BOTTOM, - SIDE_LEFT -}; - -struct _GtkBorderImage { - cairo_pattern_t *source; - GtkGradient *source_gradient; - - GtkBorder slice; - GtkBorder *width; - GtkCssBorderImageRepeat repeat; - - gint ref_count; -}; - -GtkBorderImage * -_gtk_border_image_new (cairo_pattern_t *pattern, - GtkBorder *slice, - GtkBorder *width, - GtkCssBorderImageRepeat *repeat) -{ - GtkBorderImage *image; - - image = g_slice_new0 (GtkBorderImage); - image->ref_count = 1; - - if (pattern != NULL) - image->source = cairo_pattern_reference (pattern); - - if (slice != NULL) - image->slice = *slice; - - if (width != NULL) - image->width = gtk_border_copy (width); - - if (repeat != NULL) - image->repeat = *repeat; - - return image; -} - -GtkBorderImage * -_gtk_border_image_new_for_gradient (GtkGradient *gradient, - GtkBorder *slice, - GtkBorder *width, - GtkCssBorderImageRepeat *repeat) -{ - GtkBorderImage *image; - - image = g_slice_new0 (GtkBorderImage); - image->ref_count = 1; - - if (gradient != NULL) - image->source_gradient = gtk_gradient_ref (gradient); - - if (slice != NULL) - image->slice = *slice; - - if (width != NULL) - image->width = gtk_border_copy (width); - - if (repeat != NULL) - image->repeat = *repeat; - - return image; -} - -GtkBorderImage * -_gtk_border_image_ref (GtkBorderImage *image) -{ - g_return_val_if_fail (image != NULL, NULL); - - image->ref_count++; - - return image; -} - -void -_gtk_border_image_unref (GtkBorderImage *image) -{ - g_return_if_fail (image != NULL); - - image->ref_count--; - - if (image->ref_count == 0) - { - if (image->source != NULL) - cairo_pattern_destroy (image->source); - - if (image->source_gradient != NULL) - gtk_gradient_unref (image->source_gradient); - - if (image->width != NULL) - gtk_border_free (image->width); - - g_slice_free (GtkBorderImage, image); - } -} - -GParameter * -_gtk_border_image_unpack (const GValue *value, - guint *n_params) +gboolean +_gtk_border_image_init (GtkBorderImage *image, + GtkThemingEngine *engine) { - GParameter *parameter = g_new0 (GParameter, 4); - GtkBorderImage *image = g_value_get_boxed (value); - - parameter[0].name = "border-image-source"; - g_value_init (¶meter[0].value, CAIRO_GOBJECT_TYPE_PATTERN); + image->source = _gtk_css_image_value_get_image (_gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE)); + if (image->source == NULL) + return FALSE; - parameter[1].name = "border-image-slice"; - g_value_init (¶meter[1].value, GTK_TYPE_BORDER); - - parameter[2].name = "border-image-repeat"; - g_value_init (¶meter[2].value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT); - - parameter[3].name = "border-image-width"; - g_value_init (¶meter[3].value, GTK_TYPE_BORDER); - - if (image != NULL) - { - g_value_set_boxed (¶meter[0].value, image->source); - g_value_set_boxed (¶meter[1].value, &image->slice); - g_value_set_boxed (¶meter[2].value, &image->repeat); - g_value_set_boxed (¶meter[3].value, image->width); - } + image->slice = _gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE); + image->width = _gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH); + image->repeat = _gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT); - *n_params = 4; - return parameter; -} - -void -_gtk_border_image_pack (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state) -{ - GtkBorderImage *image; - cairo_pattern_t *source; - GtkBorder *slice, *width; - GtkCssBorderImageRepeat *repeat; - - gtk_style_properties_get (props, state, - "border-image-source", &source, - "border-image-slice", &slice, - "border-image-repeat", &repeat, - "border-image-width", &width, - NULL); - - if (source == NULL) - { - g_value_take_boxed (value, NULL); - } - else - { - image = _gtk_border_image_new (source, slice, width, repeat); - g_value_take_boxed (value, image); - - cairo_pattern_destroy (source); - } - - if (slice != NULL) - gtk_border_free (slice); - - if (width != NULL) - gtk_border_free (width); - - if (repeat != NULL) - g_free (repeat); + return TRUE; } typedef struct _GtkBorderImageSliceSize GtkBorderImageSliceSize; @@ -219,20 +59,38 @@ struct _GtkBorderImageSliceSize { }; static void -gtk_border_image_compute_border_size (GtkBorderImageSliceSize sizes[3], - double offset, - double area_size, - int start_border, - int end_border) +gtk_border_image_compute_border_size (GtkBorderImageSliceSize sizes[3], + double offset, + double area_size, + double start_border_width, + double end_border_width, + const GtkCssValue *start_border, + const GtkCssValue *end_border) { - /* This code assumes area_size >= start_border + end_border */ + double start, end; + + if (_gtk_css_number_value_get_unit (start_border) == GTK_CSS_NUMBER) + start = start_border_width * _gtk_css_number_value_get (start_border, 100); + else + start = _gtk_css_number_value_get (start_border, area_size); + if (_gtk_css_number_value_get_unit (end_border) == GTK_CSS_NUMBER) + end = end_border_width * _gtk_css_number_value_get (end_border, 100); + else + end = _gtk_css_number_value_get (end_border, area_size); + + /* XXX: reduce vertical and horizontal by the same factor */ + if (start + end > area_size) + { + start = start * area_size / (start + end); + end = end * area_size / (start + end); + } sizes[0].offset = offset; - sizes[0].size = start_border; - sizes[1].offset = offset + start_border; - sizes[1].size = area_size - start_border - end_border; - sizes[2].offset = offset + area_size - end_border; - sizes[2].size = end_border; + sizes[0].size = start; + sizes[1].offset = offset + start; + sizes[1].size = area_size - start - end; + sizes[2].offset = offset + area_size - end; + sizes[2].size = end; } static void @@ -254,7 +112,7 @@ gtk_border_image_render_slice (cairo_t *cr, cairo_pattern_t *pattern; /* We can't draw center tiles yet */ - g_assert (hrepeat == GTK_CSS_REPEAT_STYLE_NONE || vrepeat == GTK_CSS_REPEAT_STYLE_NONE); + g_assert (hrepeat == GTK_CSS_REPEAT_STYLE_STRETCH || vrepeat == GTK_CSS_REPEAT_STYLE_STRETCH); hscale = width / slice_width; vscale = height / slice_height; @@ -282,7 +140,7 @@ gtk_border_image_render_slice (cairo_t *cr, width -= 2 * space; } break; - case GTK_CSS_REPEAT_STYLE_NONE: + case GTK_CSS_REPEAT_STYLE_STRETCH: break; case GTK_CSS_REPEAT_STYLE_ROUND: extend = CAIRO_EXTEND_REPEAT; @@ -314,7 +172,7 @@ gtk_border_image_render_slice (cairo_t *cr, height -= 2 * space; } break; - case GTK_CSS_REPEAT_STYLE_NONE: + case GTK_CSS_REPEAT_STYLE_STRETCH: break; case GTK_CSS_REPEAT_STYLE_ROUND: extend = CAIRO_EXTEND_REPEAT; @@ -377,7 +235,7 @@ gtk_border_image_compute_slice_size (GtkBorderImageSliceSize sizes[3], void _gtk_border_image_render (GtkBorderImage *image, - GtkBorder *border_width, + const double border_width[4], cairo_t *cr, gdouble x, gdouble y, @@ -387,57 +245,42 @@ _gtk_border_image_render (GtkBorderImage *image, cairo_surface_t *surface, *slice; GtkBorderImageSliceSize vertical_slice[3], horizontal_slice[3]; GtkBorderImageSliceSize vertical_border[3], horizontal_border[3]; - int surface_width, surface_height; + double source_width, source_height; int h, v; - if (image->width != NULL) - border_width = image->width; + _gtk_css_image_get_concrete_size (image->source, + 0, 0, + width, height, + &source_width, &source_height); - if (cairo_pattern_get_type (image->source) != CAIRO_PATTERN_TYPE_SURFACE) - { - cairo_matrix_t matrix; - cairo_t *surface_cr; + /* XXX: Optimize for (source_width == width && source_height == height) */ - surface_width = width; - surface_height = height; - - cairo_matrix_init_scale (&matrix, 1 / width, 1 / height); - cairo_pattern_set_matrix (image->source, &matrix); - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - surface_cr = cairo_create (surface); - cairo_set_source (surface_cr, image->source); - cairo_paint (surface_cr); - - cairo_destroy (surface_cr); - } - else - { - cairo_pattern_get_surface (image->source, &surface); - cairo_surface_reference (surface); - - surface_width = cairo_image_surface_get_width (surface); - surface_height = cairo_image_surface_get_height (surface); - } + surface = _gtk_css_image_get_surface (image->source, + cairo_get_target (cr), + source_width, source_height); gtk_border_image_compute_slice_size (horizontal_slice, - surface_width, - image->slice.left, - image->slice.right); + source_width, + _gtk_css_number_value_get (_gtk_css_border_value_get_left (image->slice), source_width), + _gtk_css_number_value_get (_gtk_css_border_value_get_right (image->slice), source_width)); gtk_border_image_compute_slice_size (vertical_slice, - surface_height, - image->slice.top, - image->slice.bottom); + source_height, + _gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height), + _gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height)); gtk_border_image_compute_border_size (horizontal_border, x, width, - border_width->left, - border_width->right); + border_width[GTK_CSS_LEFT], + border_width[GTK_CSS_RIGHT], + _gtk_css_border_value_get_left (image->width), + _gtk_css_border_value_get_right (image->width)); gtk_border_image_compute_border_size (vertical_border, y, height, - border_width->top, - border_width->bottom); + border_width[GTK_CSS_TOP], + border_width[GTK_CSS_BOTTOM], + _gtk_css_border_value_get_top (image->width), + _gtk_css_border_value_get_bottom(image->width)); for (v = 0; v < 3; v++) { @@ -468,10 +311,12 @@ _gtk_border_image_render (GtkBorderImage *image, vertical_border[v].offset, horizontal_border[h].size, vertical_border[v].size, - h == 1 ? image->repeat.hrepeat : GTK_CSS_REPEAT_STYLE_NONE, - v == 1 ? image->repeat.vrepeat : GTK_CSS_REPEAT_STYLE_NONE); + h == 1 ? _gtk_css_border_repeat_value_get_x (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH, + v == 1 ? _gtk_css_border_repeat_value_get_y (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH); cairo_surface_destroy (slice); } } + + cairo_surface_destroy (surface); }