[metacity/cowbell] it renders *something*, anyway
- From: Thomas James Alexander Thurman <tthurman src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [metacity/cowbell] it renders *something*, anyway
- Date: Mon, 19 Oct 2009 14:50:38 +0000 (UTC)
commit 47ffba2e3d94fab15ec2762fde7d382c101f0783
Author: Thomas Thurman <tthurman gnome org>
Date: Sat Oct 17 01:35:26 2009 -0400
it renders *something*, anyway
src/ui/theme.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 326 insertions(+), 0 deletions(-)
---
diff --git a/src/ui/theme.c b/src/ui/theme.c
index e2f693d..0e8d1ae 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -206,6 +206,242 @@ meta_theme_get_title_scale (MetaTheme *theme,
return 1.0;
}
+static gboolean
+get_number_from_style (ccss_style_t *style,
+ char *element,
+ int *dummy,
+ int *original_value)
+{
+ double d = 0.0;
+ gboolean result;
+
+ result = ccss_style_get_double (style, element, &d);
+
+ if (original_value)
+ *original_value = d;
+
+ return result;
+}
+
+static void
+reduce_by_padding_borders_and_margins (ccss_stylesheet_t *stylesheet,
+ CopperClasses style_id,
+ int *x, int *y, int *w, int *h,
+ gboolean honour_margins,
+ gboolean reverse)
+{
+ ccss_style_t *style = ccss_stylesheet_query (stylesheet,
+ (ccss_node_t*) &cowbell_nodes[style_id]);
+ int bt=0, br=0, bb=0, bl=0, pt=0, pr=0, pb=0, pl=0;
+
+ if (!style) return;
+
+ /* FIXME this is silly; libccss should do this for us */
+ /* FIXME maybe it does if we get the property rather than the number */
+ if (get_number_from_style (style, "border-width", NULL, &bl))
+ {
+ bt = br = bb = bl;
+ }
+ else
+ {
+ get_number_from_style (style, "border-top-width", NULL, &bt);
+ get_number_from_style (style, "border-right-width", NULL, &br);
+ get_number_from_style (style, "border-bottom-width", NULL, &bb);
+ get_number_from_style (style, "border-left-width", NULL, &bl);
+ }
+
+ if (get_number_from_style (style, "padding", NULL, &pl))
+ {
+ pt = pr = pb = pl;
+ }
+ else
+ {
+ get_number_from_style (style, "padding-top", NULL, &pt);
+ get_number_from_style (style, "padding-right", NULL, &pr);
+ get_number_from_style (style, "padding-bottom", NULL, &pb);
+ get_number_from_style (style, "padding-left", NULL, &pl);
+ }
+
+ /* FIXME honour honour_margins */
+
+ bt += pt;
+ br += pr;
+ bb += pb;
+ bl += pl;
+
+ if (reverse)
+ {
+ if (x) *x -= bl;
+ if (y) *y -= bt;
+ if (w) *w += (bl+br);
+ if (h) *h += (bt+bb);
+ }
+ else
+ {
+ if (x) *x += bl;
+ if (y) *y += bt;
+ if (w) *w -= (bl+br);
+ if (h) *h -= (bt+bb);
+ }
+
+ ccss_style_destroy (style);
+}
+
+static gint
+draw_rectangle (ccss_stylesheet_t *stylesheet,
+ cairo_t *cr,
+ CopperClasses style_id,
+ int x, int y, int w, int h,
+ gboolean honour_margins,
+ gboolean from_the_right,
+ PangoLayout *layout)
+{
+ ccss_style_t *style = ccss_stylesheet_query (stylesheet,
+ (ccss_node_t*) &cowbell_nodes[style_id]);
+ int full_width;
+ int horizontal_margin = 0;
+
+ if (!style) return 0;
+
+ if (honour_margins)
+ {
+ int mn, mt, mr, mb, ml;
+ /* FIXME: Setting just "margin" doesn't work
+ * because libccss doesn't know about margins.
+ */
+ get_number_from_style (style, "margin", NULL, &mn);
+ if (mn)
+ {
+ /* FIXME this is broken; "margin" may have multiple values */
+ mt = mr = mb = ml = mn;
+ }
+ else
+ {
+ get_number_from_style (style, "margin-top", NULL, &mt);
+ get_number_from_style (style, "margin-right", NULL, &mr);
+ get_number_from_style (style, "margin-bottom", NULL, &mb);
+ get_number_from_style (style, "margin-left", NULL, &ml);
+ }
+
+ x += ml;
+ y += mt;
+ horizontal_margin = ml+mr;
+ h -= (mt+mb);
+ }
+
+ if (w==0)
+ {
+ int height, width;
+
+ get_number_from_style (style, "height", NULL, &height);
+ get_number_from_style (style, "width", NULL, &width);
+
+ if (height!=0 && width!=0)
+ {
+ int min_w, max_w;
+ double scale = ((double)h/(double)height);
+
+ w = (int) ((double)width) * scale;
+
+ get_number_from_style (style, "min-width", NULL, &min_w);
+ get_number_from_style (style, "max-width", NULL, &max_w);
+
+ if (max_w && w>max_w && max_w>min_w) w = max_w;
+ if (w<min_w) w = min_w;
+ }
+ }
+
+ full_width = w+ horizontal_margin;
+
+ if (from_the_right)
+ x -= full_width;
+
+ ccss_cairo_style_draw_rectangle (style, cr, x, y, w, h);
+
+ if (layout)
+ {
+ reduce_by_padding_borders_and_margins (stylesheet, CC_TITLE,
+ &x, &y, &w, &h,
+ TRUE, FALSE);
+ /*
+ * we should maybe undo the translate later, but
+ * we're always the last one to use this context anyway
+ */
+ cairo_translate (cr, x, y);
+
+ pango_cairo_show_layout (cr, layout);
+ }
+
+ ccss_style_destroy (style);
+
+ return full_width;
+}
+
+static PangoLayout*
+cowbell_title_text (ccss_stylesheet_t *stylesheet,
+ cairo_t *cr,
+ char *text)
+{
+ PangoLayout *layout;
+ PangoAttrList *attrs = NULL;
+ ccss_style_t *style = ccss_stylesheet_query (stylesheet,
+ (ccss_node_t*) &cowbell_nodes[CC_TITLE]);
+ char *align;
+ ccss_color_t const *colour;
+
+ layout = pango_cairo_create_layout (cr);
+
+ attrs = pango_attr_list_new ();
+
+ /* We have to handle CSS text properties ourselves here because
+ * libccss doesn't know how to render them yet. We don't try
+ * to do all the funky effects like shadows and so on,
+ * unfortunately.
+ */
+
+ if (ccss_style_get_property (style, "color",
+ (const ccss_property_base_t**) &colour))
+ {
+ pango_attr_list_insert (attrs,
+ pango_attr_foreground_new
+ ((int)65535.0*colour->red,
+ (int)65535.0*colour->green,
+ (int)65535.0*colour->blue));
+ }
+
+ /* Alignment */
+
+ if (ccss_style_get_string (style, "text-align", &align))
+ {
+ if (strcmp (align, "left")==0)
+ {
+ pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
+ }
+ else if (strcmp (align, "center")==0)
+ {
+ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+ }
+ else if (strcmp (align, "right")==0)
+ {
+ pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
+ }
+ else
+ /* FIXME: "align" contains garbage if it's undefined;
+ * is there an easy way of checking?
+ */
+ g_warning ("Unknown alignment: %s", align);
+ }
+
+ pango_layout_set_attributes (layout, attrs);
+
+ /* The actual text */
+ pango_layout_set_text (layout, text, -1);
+
+ ccss_style_destroy (style);
+
+ return layout;
+}
+
void
meta_theme_draw_frame_with_style (MetaTheme *theme,
GtkStyle *style_gtk,
@@ -226,6 +462,96 @@ meta_theme_draw_frame_with_style (MetaTheme *theme,
GdkPixbuf *icon)
{
/* stub */
+
+ cairo_t *cr = gdk_cairo_create (drawable);
+ ccss_stylesheet_t *stylesheet = theme->stylesheet;
+
+ int x = 0;
+ int y = 0;
+ int w = client_width;
+ int h = client_height;
+
+ PangoRectangle text_extents;
+
+ int titlebar_height;
+
+ CopperClasses left_buttons[] = {CC_MENU, CC_LAST};
+ CopperClasses right_buttons[] = {CC_CLOSE, CC_MAXIMIZE, CC_MINIMIZE, CC_LAST};
+ CopperClasses *cursor;
+ int leftpos, rightpos;
+
+ PangoLayout *layout = cowbell_title_text (stylesheet, cr, "Badgers");
+
+ pango_layout_get_pixel_extents (layout, NULL, &text_extents);
+ reduce_by_padding_borders_and_margins (stylesheet, CC_TITLE,
+ &text_extents.x, &text_extents.y,
+ &text_extents.width,
+ &text_extents.height,
+ TRUE, TRUE);
+
+ titlebar_height = text_extents.height;
+
+ reduce_by_padding_borders_and_margins (stylesheet, CC_TITLEBAR,
+ NULL, NULL, NULL,
+ &titlebar_height,
+ TRUE, TRUE);
+
+ draw_rectangle (stylesheet, cr, CC_FRAME, x, y, w, h, FALSE, FALSE, NULL);
+
+ reduce_by_padding_borders_and_margins (stylesheet, CC_FRAME, &x, &y, &w, &h, FALSE, FALSE);
+
+ draw_rectangle (stylesheet, cr, CC_TITLEBAR, x, y, w, titlebar_height, TRUE, FALSE, NULL);
+
+ draw_rectangle (stylesheet, cr, CC_CONTENT, x, y+titlebar_height, w, h-titlebar_height, TRUE, FALSE, NULL);
+
+ h = titlebar_height;
+
+ reduce_by_padding_borders_and_margins (stylesheet, CC_TITLEBAR, &x, &y, &w, &h, TRUE, FALSE);
+
+ cursor = left_buttons;
+ leftpos = x;
+ while (*cursor != CC_LAST)
+ {
+ leftpos += draw_rectangle (stylesheet, cr, *cursor, leftpos, y, 0, h, TRUE, FALSE, NULL);
+ cursor++;
+ }
+
+ cursor = right_buttons;
+ rightpos = x+w;
+ while (*cursor != CC_LAST)
+ {
+ rightpos -= draw_rectangle (stylesheet, cr, *cursor, rightpos, y, 0, h, TRUE, TRUE, NULL);
+ cursor++;
+ }
+
+ switch (pango_layout_get_alignment (layout))
+ {
+ case PANGO_ALIGN_LEFT:
+ x = leftpos;
+ draw_rectangle (stylesheet, cr, CC_FILLER, leftpos+text_extents.width, y,
+ (rightpos-leftpos)-text_extents.width, h, TRUE, FALSE, NULL);
+ break;
+ case PANGO_ALIGN_CENTER:
+ x = leftpos + ((rightpos-leftpos)/2 - text_extents.width);
+ draw_rectangle (stylesheet, cr, CC_FILLER, leftpos, y,
+ x-leftpos, h, TRUE, FALSE, NULL);
+ draw_rectangle (stylesheet, cr, CC_FILLER, x+text_extents.width, y,
+ rightpos-(x+text_extents.width), h, TRUE, FALSE, NULL);
+ break;
+ case PANGO_ALIGN_RIGHT:
+ x = rightpos - text_extents.width;
+ draw_rectangle (stylesheet, cr, CC_FILLER, leftpos, y,
+ rightpos-(leftpos-text_extents.width), h, TRUE, FALSE, NULL);
+ break;
+ default:
+ g_error ("Unknown alignment");
+ }
+
+ draw_rectangle (stylesheet, cr, CC_TITLE, x, y, text_extents.width, h, TRUE, FALSE, layout);
+
+ g_object_unref (G_OBJECT (layout));
+
+ cairo_destroy (cr);
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]