ui: add cairo-text widget

This commit is contained in:
DanyLE 2024-04-29 21:41:51 +02:00
parent 1219ec1563
commit 98885e34a3
8 changed files with 501 additions and 24 deletions

View File

@ -60,6 +60,7 @@ src = [
'src/widgets/cairo-box.c',
'src/widgets/cairo-window.c',
'src/widgets/cairo-image.c',
'src/widgets/cairo-text.c',
'src/main.c',
wayland_targets]

View File

@ -13,10 +13,19 @@
#include "widgets/cairo-window.h"
#include "widgets/cairo-box.h"
#include "widgets/cairo-image.h"
#include "widgets/cairo-text.h"
#define DEF_SURF_W 600
#define DEF_SURF_H 400
#define LOREM "Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n" \
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n" \
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \n" \
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in \n" \
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n" \
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia \n" \
"deserunt mollit anim id est laborum."
struct _DiyaLockSession
{
DiyaObject parent;
@ -314,13 +323,13 @@ static void diya_lock_session_ui(DiyaCairoWindow * window)
NULL);
diya_cairo_container_add(box, hbox);
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
"vspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
"hspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
"stroke", &stroke,
"padding", &padding,
"corner-radius", 10.0,
NULL);
diya_cairo_container_add(box, hbox);
@ -328,7 +337,26 @@ static void diya_lock_session_ui(DiyaCairoWindow * window)
2.0,
{ 0.0, 0.0, 1.0, 1.0 }
};
DiyaCairoImage * image = g_object_new(DIYA_TYPE_CAIRO_IMAGE,
diya_color_t fill = { 1.0,1.0,1.0,1.0 };
diya_color_t color = { 0.0,0.0,0.0,1.0 };
DiyaCairoText *text = g_object_new(DIYA_TYPE_CAIRO_TEXT,
"vspace", DIYA_CAIRO_WIDGET_FILL_NONE,
"hspace", DIYA_CAIRO_WIDGET_FILL_NONE,
"stroke", &stroke,
"padding", &padding,
"corner-radius", 5.0,
"fill", &fill,
"color", &color,
"font-size", 11,
"font-family", "Monospace",
"halign", DIYA_CAIRO_WIDGET_ALIGN_START,
"valign", DIYA_CAIRO_WIDGET_ALIGN_START,
NULL);
diya_cairo_text_set_text(text, LOREM);
diya_cairo_widget_set_size(text, 600, 400);
diya_cairo_container_add(hbox, text);
/*DiyaCairoImage * image = g_object_new(DIYA_TYPE_CAIRO_IMAGE,
"file",
"/home/diya/test.jpg",
"stroke",
@ -336,7 +364,7 @@ static void diya_lock_session_ui(DiyaCairoWindow * window)
"vspace", DIYA_CAIRO_WIDGET_FILL_NONE,
"hspace", DIYA_CAIRO_WIDGET_FILL_NONE,
NULL);
diya_cairo_container_add(hbox, image);
diya_cairo_container_add(hbox, image);*/
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,

View File

@ -92,6 +92,7 @@ static void cairo_box_update(gpointer object)
diya_rect_t space = diya_cairo_widget_get_extent(object);
diya_offset_t * padding;
diya_stroke_t * stroke;
diya_rect_t * default_extent;
g_object_get(object,"padding", &padding, "stroke", &stroke, NULL);
gint stroke_size = ceil(stroke->size);
gpointer item;
@ -110,7 +111,7 @@ static void cairo_box_update(gpointer object)
}
G_LIST_FOREACH(item, children)
{
g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL);
g_object_get(item, "vspace", &vspace, "hspace", &hspace, "default-extent", &default_extent, NULL);
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL)
{
@ -120,9 +121,11 @@ static void cairo_box_update(gpointer object)
n_extended++;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
case DIYA_CAIRO_WIDGET_FILL_NONE:
occupied_space += cwidth;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
occupied_space += default_extent->width;
break;
default:
break;
}
@ -135,9 +138,11 @@ static void cairo_box_update(gpointer object)
n_extended++;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
case DIYA_CAIRO_WIDGET_FILL_NONE:
occupied_space += cheight;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
occupied_space += default_extent->height;
break;
default:
break;
}
@ -149,7 +154,7 @@ static void cairo_box_update(gpointer object)
G_LIST_FOREACH(item, children)
{
g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL);
g_object_get(item, "vspace", &vspace, "hspace", &hspace, "default-extent", &default_extent, NULL);
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
diya_rect_t rect = {0};
@ -166,7 +171,6 @@ static void cairo_box_update(gpointer object)
off_x += rect.width;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
case DIYA_CAIRO_WIDGET_FILL_NONE:
rect.width = cwidth;
if(!DIYA_IS_CAIRO_BOX(item))
{
@ -174,6 +178,14 @@ static void cairo_box_update(gpointer object)
}
off_x += cwidth;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
rect.width = default_extent->width;
if(!DIYA_IS_CAIRO_BOX(item))
{
rect.height = default_extent->height;
}
off_x += default_extent->width;
break;
default:
break;
}
@ -188,7 +200,6 @@ static void cairo_box_update(gpointer object)
off_y += rect.height;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
case DIYA_CAIRO_WIDGET_FILL_NONE:
rect.height = cheight;
if(!DIYA_IS_CAIRO_BOX(item))
{
@ -196,6 +207,14 @@ static void cairo_box_update(gpointer object)
}
off_y += cheight;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
rect.height = default_extent->height;
if(!DIYA_IS_CAIRO_BOX(item))
{
rect.width = default_extent->width;
}
off_y += default_extent->height;
break;
default:
break;
}

View File

@ -208,7 +208,7 @@ static gboolean diya_cairo_image_draw(gpointer object, cairo_t * context)
break;
}
g_warning("Global position %d %d offset %d %d", gpos.x, gpos.y, off_x, off_y);
//g_warning("Global position %d %d offset %d %d", gpos.x, gpos.y, off_x, off_y);
if(color->a > 0)
{

367
src/widgets/cairo-text.c Normal file
View File

@ -0,0 +1,367 @@
#include <assert.h>
#include <pango/pangocairo.h>
#include <math.h>
#include "cairo-text.h"
#define FONT "Sans Bold 10"
enum
{
NO_PROP,
C_TEXT,
C_FONT_FAMILY,
C_FONT_SIZE,
C_FONT_STYLE,
C_FONT_WEIGHT,
C_COLOR,
C_WRAP,
N_PROPERTIES
};
static GParamSpec *g_prop[N_PROPERTIES] = {0};
typedef struct _DiyaCairoTextPrivate
{
DiyaCairoWidget parent_object;
gchar *text;
gchar *family;
int size;
guint style;
guint wrap;
guint weight;
diya_color_t color;
} DiyaCairoTextPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoText, diya_cairo_text, DIYA_TYPE_CAIRO_WIDGET)
static void diya_cairo_text_dispose(GObject *object)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
g_debug("diya_cairo_text_dispose: %s", diya_object_to_string(object));
if (priv->text)
{
g_free(priv->text);
}
if (priv->family)
{
g_free(priv->family);
}
G_OBJECT_CLASS(diya_cairo_text_parent_class)->dispose(object);
}
static void diya_cairo_text_init(DiyaCairoText *self)
{
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
priv->text = NULL;
priv->family = NULL;
priv->size = 10;
priv->style = DIYA_CAIRO_FONT_STYLE_NORMAL;
priv->weight = DIYA_CAIRO_FONT_WEIGHT_NORMAL;
priv->wrap = DIYA_CAIRO_TEXT_WRAP_WORD;
}
static void diya_cairo_text_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
switch (property_id)
{
case C_TEXT:
if (priv->text)
{
g_free(priv->text);
}
priv->text = g_strdup(g_value_get_pointer(value));
break;
case C_FONT_FAMILY:
if (priv->family)
{
g_free(priv->family);
}
priv->family = g_strdup(g_value_get_pointer(value));
break;
case C_FONT_SIZE:
priv->size = g_value_get_int(value);
break;
case C_FONT_STYLE:
priv->style = g_value_get_uint(value);
break;
case C_WRAP:
priv->wrap = g_value_get_uint(value);
break;
case C_FONT_WEIGHT:
priv->weight = g_value_get_uint(value);
break;
case C_COLOR:
memcpy(&priv->color,g_value_get_pointer(value), sizeof(priv->color));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void diya_cairo_text_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
switch (property_id)
{
case C_TEXT:
g_value_set_pointer(value, priv->text);
break;
case C_FONT_FAMILY:
g_value_set_pointer(value, priv->family);
break;
case C_FONT_SIZE:
g_value_set_int(value, priv->size);
break;
case C_FONT_STYLE:
g_value_set_uint(value, priv->style);
break;
case C_WRAP:
g_value_set_uint(value, priv->wrap);
break;
case C_FONT_WEIGHT:
g_value_set_uint(value, priv->weight);
break;
case C_COLOR:
g_value_set_pointer(value, &priv->color);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static PangoFontDescription *diya_cairo_text_get_pango_font_desc(DiyaCairoText *self)
{
PangoFontDescription *desc = pango_font_description_new();
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
if (priv->family)
{
pango_font_description_set_family(desc, priv->family);
}
pango_font_description_set_size(desc, priv->size * PANGO_SCALE);
pango_font_description_set_style(desc, priv->style);
pango_font_description_set_weight(desc, priv->weight);
return desc;
}
static gboolean diya_cairo_text_draw(gpointer object, cairo_t *context)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
if(!diya_cairo_widget_is_damaged(object) || !diya_cairo_widget_is_visible(object))
{
return FALSE;
}
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_text_parent_class)->draw(object, context);
diya_rect_t view_port = diya_cairo_widget_get_view_port(object);
diya_rect_dump("diya_cairo_text_draw: ", &view_port);
if(diya_rect_is_empty(&view_port))
{
return FALSE;
}
cairo_save(context);
cairo_rectangle(context, view_port.x, view_port.y, view_port.width, view_port.height);
cairo_clip(context);
diya_rect_t extent = diya_cairo_widget_get_extent(object);
g_warning("diya_cairo_widget_get_extent: width %d, %d", extent.width, extent.height);
diya_offset_t * padding, *margin;
diya_stroke_t *stroke;
diya_color_t *color;
guint halign, valign;
g_object_get(object,
"stroke", &stroke,
"halign", &halign,
"valign", &valign,
"margin", &margin,
"padding", &padding,
"color", &color,
NULL);
gint stroke_size = ceil(stroke->size);
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
PangoFontDescription *desc = diya_cairo_text_get_pango_font_desc(object);
cairo_set_source_rgba(context, color->r, color->g, color->b, color->a);
int display_w = extent.width - padding->left - padding->right - margin->left - margin->right - 2*stroke_size;
int display_h = extent.height - padding->top - padding->bottom - margin->top - margin->bottom - 2*stroke_size;
int off_x = padding->left + margin->left + stroke_size;
int off_y = padding->top + margin->top + stroke_size;
PangoLayout *layout = pango_cairo_create_layout(context);
// take into account my padding setting
pango_layout_set_text(layout, priv->text, -1);
pango_layout_set_font_description(layout, desc);
pango_layout_set_width(layout,display_w*PANGO_SCALE);
pango_layout_set_height(layout, display_h*PANGO_SCALE);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
pango_layout_set_wrap(layout, priv->wrap);
switch(halign)
{
case DIYA_CAIRO_WIDGET_ALIGN_START:
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
break;
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
break;
case DIYA_CAIRO_WIDGET_ALIGN_END:
pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
break;
}
PangoRectangle text_rect = {0};
pango_layout_get_extents(layout, NULL, &text_rect);
pango_extents_to_pixels(&text_rect, NULL);
// draw text
switch (valign)
{
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
off_y += (display_h - text_rect.height)/ 2;
break;
case DIYA_CAIRO_WIDGET_ALIGN_END:
off_y += display_h - text_rect.height;
break;
default:
break;
}
cairo_move_to(context, gpos.x + off_x, gpos.y + off_y);
pango_cairo_update_layout(context, layout);
pango_cairo_show_layout(context, layout);
cairo_restore(context);
pango_font_description_free(desc);
g_object_unref(layout);
return TRUE;
}
static void diya_cairo_text_content_size(gpointer object, int *width, int *height)
{
diya_offset_t* padding, *margin;
diya_stroke_t * stroke;
diya_rect_t * def_xtent;
guint hspace,vspace;
g_object_get(object,
"padding", &padding,
"margin", &margin,
"stroke", &stroke,
"hspace", &hspace,
"vspace", &vspace,
"default-extent", &def_xtent,
NULL);
gint stroke_size = ceil(stroke->size) * 2;
*width = padding->left + padding->right + margin->left + margin->right + stroke_size;
*height = padding->top + padding->bottom + margin->top + margin->bottom + stroke_size;
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
// diya_rect_t default_extent = DIYA_CAIRO_WIDGET_GET_CLASS(object)->default_extent(object);
int text_width = 0;
int text_height = 0;
if (priv->text)
{
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
cairo_t *context = cairo_create(surface);
PangoLayout *layout = pango_cairo_create_layout(context);
PangoFontDescription *desc = diya_cairo_text_get_pango_font_desc(object);
pango_layout_set_font_description(layout, desc);
pango_layout_set_text(layout, priv->text, -1);
pango_layout_set_width(layout, -1);
pango_layout_set_height(layout, -1);
pango_layout_set_single_paragraph_mode(layout, FALSE);
//pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_MIDDLE);
PangoRectangle rect = {0};
pango_layout_get_extents(layout, NULL, &rect);
pango_extents_to_pixels(&rect, NULL);
//rect.width += 4;
text_width = rect.width;
text_height = rect.height;
cairo_destroy(context);
cairo_surface_destroy(surface);
pango_font_description_free(desc);
g_object_unref(layout);
}
switch (hspace)
{
case DIYA_CAIRO_WIDGET_FILL_NONE:
*width = def_xtent->width;
break;
default:
*width += text_width;
break;
}
switch (vspace)
{
case DIYA_CAIRO_WIDGET_FILL_NONE:
*height = def_xtent->height;
break;
default:
*height += text_height;
break;
}
}
static void diya_cairo_text_class_init(DiyaCairoTextClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
class->set_text = diya_cairo_text_set_text;
class->get_text = diya_cairo_text_get_text;
wclass->draw = diya_cairo_text_draw;
wclass->content_size = diya_cairo_text_content_size;
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoText");
gobject_class->dispose = diya_cairo_text_dispose;
gobject_class->set_property = diya_cairo_text_set_property;
gobject_class->get_property = diya_cairo_text_get_property;
g_prop[C_TEXT] = g_param_spec_pointer("text", NULL, "text content", G_PARAM_READWRITE);
g_prop[C_FONT_FAMILY] = g_param_spec_pointer("font-family", NULL, "text font face", G_PARAM_READWRITE);
g_prop[C_COLOR] = g_param_spec_pointer("color", NULL, "text color", G_PARAM_READWRITE);
g_prop[C_FONT_STYLE] = g_param_spec_uint(
"font-style", NULL, "text font style",
DIYA_CAIRO_FONT_STYLE_NORMAL,
DIYA_CAIRO_FONT_STYLE_ITALIC,
DIYA_CAIRO_FONT_STYLE_NORMAL,
G_PARAM_READWRITE);
g_prop[C_FONT_WEIGHT] = g_param_spec_uint(
"font-weight", NULL, "text font weight",
PANGO_WEIGHT_THIN,
PANGO_WEIGHT_ULTRAHEAVY,
DIYA_CAIRO_FONT_WEIGHT_NORMAL,
G_PARAM_READWRITE);
g_prop[C_FONT_SIZE] = g_param_spec_int(
"font-size", NULL, "text font size",
0,
G_MAXINT,
10,
G_PARAM_READWRITE);
g_prop[C_WRAP] = g_param_spec_uint(
"wrap", NULL, "text wrap mode",
DIYA_CAIRO_TEXT_WRAP_WORD,
DIYA_CAIRO_TEXT_WRAP_WORD_CHAR,
DIYA_CAIRO_TEXT_WRAP_WORD,
G_PARAM_READWRITE);
g_object_class_install_properties(gobject_class, N_PROPERTIES, g_prop);
}
void diya_cairo_text_set_text(gpointer object, const gchar *text)
{
assert(DIYA_IS_CAIRO_TEXT(object));
g_object_set(object, "text", text, NULL);
}
const gchar *diya_cairo_text_get_text(gpointer object)
{
assert(DIYA_IS_CAIRO_TEXT(object));
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
return priv->text;
}

31
src/widgets/cairo-text.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef CAIRO_TEXT_H
#define CAIRO_TEXT_H
#include <pango/pangocairo.h>
#include "cairo-widget.h"
#define DIYA_CAIRO_FONT_STYLE_NORMAL PANGO_STYLE_NORMAL
#define DIYA_CAIRO_FONT_STYLE_ITALIC PANGO_STYLE_ITALIC
#define DIYA_CAIRO_FONT_STYLE_OBLIQUE PANGO_STYLE_OBLIQUE
#define DIYA_CAIRO_FONT_WEIGHT_NORMAL PANGO_WEIGHT_NORMAL
#define DIYA_CAIRO_FONT_WEIGHT_BOLD PANGO_WEIGHT_BOLD
#define DIYA_CAIRO_TEXT_WRAP_WORD PANGO_WRAP_WORD
#define DIYA_CAIRO_TEXT_WRAP_CHAR PANGO_WRAP_CHAR
#define DIYA_CAIRO_TEXT_WRAP_WORD_CHAR PANGO_WRAP_WORD_CHAR
#define DIYA_TYPE_CAIRO_TEXT (diya_cairo_text_get_type ())
G_DECLARE_DERIVABLE_TYPE (DiyaCairoText, diya_cairo_text, DIYA, CAIRO_TEXT, DiyaCairoWidget)
struct _DiyaCairoTextClass
{
DiyaCairoWidgetClass parent_class;
void (*set_text)(gpointer object, const gchar* text);
const gchar* (*get_text)(gpointer object);
};
void diya_cairo_text_set_text(gpointer object, const gchar* text);
const gchar* diya_cairo_text_get_text(gpointer object);
#endif

View File

@ -51,6 +51,7 @@ enum
CW_MARGIN,
CW_FILL,
CW_STROKE,
CW_CORNER_RADIUS,
CW_N_PROPERTIES
};
static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0};
@ -70,6 +71,8 @@ typedef struct _DiyaCairoWidgetPrivate
guint16 hspace;
guint16 vspace;
gdouble corner_radius;
diya_offset_t margin;
diya_offset_t padding;
@ -166,6 +169,9 @@ static void diya_cairo_widget_set_property(GObject *object, guint property_id, c
assert(ptr);
priv->stroke = *(diya_stroke_t*) ptr;
break;
case CW_CORNER_RADIUS:
priv->corner_radius = g_value_get_double(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -214,6 +220,9 @@ static void diya_cairo_widget_get_property(GObject *object, guint property_id, G
case CW_STROKE:
g_value_set_pointer(value, &priv->stroke);
break;
case CW_CORNER_RADIUS:
g_value_set_double(value, priv->corner_radius);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -241,6 +250,7 @@ static void diya_cairo_widget_init(DiyaCairoWidget *self)
memset(&priv->fill, 0, sizeof(priv->fill));
priv->damaged = TRUE;
priv->corner_radius = 0;
}
static const gchar *diya_cairo_widget_to_string(DiyaObject *object)
@ -277,6 +287,12 @@ diya_rect_t diya_cairo_widget_get_view_port(gpointer object)
if(priv->parent_widget)
{
diya_rect_t parent_view = diya_cairo_widget_get_view_port(priv->parent_widget);
diya_offset_t* padding;
g_object_get(priv->parent_widget,"padding", &padding, NULL);
parent_view.x += padding->left;
parent_view.y += padding->top;
parent_view.width -= (padding->left + padding->right);
parent_view.height -= (padding->top + padding->bottom);
if(!diya_rect_overlap(&view, &parent_view))
{
view.x = view.y = view.width = view.height = 0;
@ -298,8 +314,6 @@ diya_rect_t diya_cairo_widget_get_view_port(gpointer object)
static gboolean diya_cairo_widget_draw(gpointer object, cairo_t* context)
{
(void) context;
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
if(!priv->damaged)
@ -325,11 +339,25 @@ static gboolean diya_cairo_widget_draw(gpointer object, cairo_t* context)
//cairo_move_to(context, (double)gpos.x +, (double)gpos.y);
guint stroke_size = ceil(priv->stroke.size);
guint half_stroke_size = ceil(priv->stroke.size / 2.0);
cairo_rectangle(context,
gpos.x + priv->margin.left + half_stroke_size,
gpos.y + priv->margin.top + half_stroke_size,
priv->extent.width - priv->margin.left - priv->margin.right - stroke_size,
priv->extent.height - priv->margin.bottom - priv->margin.top - stroke_size);
double width = (double)(priv->extent.width - priv->margin.left - priv->margin.right - stroke_size);
int height = (double)(priv->extent.height - priv->margin.bottom - priv->margin.top - stroke_size);
int x = (double)(gpos.x + priv->margin.left + half_stroke_size);
int y = (double)(gpos.y + priv->margin.top + half_stroke_size);
if(priv->corner_radius > 0)
{
double degrees = M_PI / 180.0;
cairo_new_sub_path(context);
cairo_arc (context, x + width - priv->corner_radius, y + priv->corner_radius, priv->corner_radius, -90 * degrees, 0);
cairo_arc (context, x + width - priv->corner_radius, y + height - priv->corner_radius, priv->corner_radius, 0, 90 * degrees);
cairo_arc (context, x + priv->corner_radius, y + height - priv->corner_radius, priv->corner_radius, 90 * degrees, 180 * degrees);
cairo_arc (context, x + priv->corner_radius, y + priv->corner_radius, priv->corner_radius, 180 * degrees, 270 * degrees);
cairo_close_path (context);
}
else
{
cairo_rectangle(context,x,y,width,height);
}
if(priv->fill.a > 0)
{
cairo_set_source_rgba(context, priv->fill.r, priv->fill.g, priv->fill.b, priv->fill.a);
@ -361,7 +389,7 @@ static void diya_cairo_widget_update(gpointer object)
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
gint stroke_size = ceil(priv->stroke.size) *2;
if(priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN)
{
/**
@ -394,11 +422,10 @@ static void diya_cairo_widget_update(gpointer object)
width = space.width;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
case DIYA_CAIRO_WIDGET_FILL_NONE:
width = cwidth;
break;
default:
width = priv->default_extent.width + priv->margin.left + priv->margin.right;
width = priv->default_extent.width + priv->margin.left + priv->margin.right + stroke_size;
break;
}
@ -408,11 +435,10 @@ static void diya_cairo_widget_update(gpointer object)
height = space.height;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
case DIYA_CAIRO_WIDGET_FILL_NONE:
height = cheight;
break;
default:
height = priv->default_extent.height + priv->margin.top + priv->margin.bottom;
height = priv->default_extent.height + priv->margin.top + priv->margin.bottom + stroke_size;
break;
}
@ -576,6 +602,12 @@ static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class)
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_CORNER_RADIUS] = g_param_spec_double(
"corner-radius", NULL, "Corner radius",
0,
DBL_MAX,
0,
G_PARAM_READWRITE);
base_class->to_string = diya_cairo_widget_to_string;
@ -717,7 +749,7 @@ static void diya_cairo_container_dispose(GObject* object)
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self);
g_debug("diya_cairo_container_dispose: %s", diya_object_to_string(object));
g_list_free_full(priv->children, g_object_unref);
G_OBJECT_CLASS(diya_cairo_widget_parent_class)->dispose(object);
G_OBJECT_CLASS(diya_cairo_container_parent_class)->dispose(object);
}
static void diya_cairo_container_init(DiyaCairoContainer *self)

View File

@ -102,7 +102,6 @@ struct _DiyaCairoWidgetClass
diya_rect_t (*default_extent)(gpointer);
diya_rect_t (*view_port)(gpointer);
gboolean (*damaged)(gpointer);
const gchar* name;
};