From 75c2c805343ebdd0b38dac25c1791a80d053fbf9 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Mon, 20 Feb 2017 22:24:02 -0500 Subject: [PATCH] And adding the background attributes. We're done with the Pango one! Now for the Windows one... yay. --- unix/attrstr.c | 101 +++++++++++++++++++++++++++++++++++---------- unix/drawtext.c | 13 +++++- unix/uipriv_unix.h | 3 +- 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/unix/attrstr.c b/unix/attrstr.c index cdc72da5..115b611e 100644 --- a/unix/attrstr.c +++ b/unix/attrstr.c @@ -10,7 +10,8 @@ struct foreachParams { // keys are pointers to size_t maintained by g_new0()/g_free() // values are GStrings GHashTable *features; -//TODO GArray *backgroundBlocks; + // TODO use pango's built-in background attribute? + GPtrArray *backgroundClosures; }; static gboolean featurePosEqual(gconstpointer a, gconstpointer b) @@ -55,21 +56,51 @@ static void ensureFeaturesInRange(struct foreachParams *p, size_t start, size_t } } -#if 0 /* TODO */ -static backgroundBlock mkBackgroundBlock(size_t start, size_t end, double r, double g, double b, double a) -{ - return Block_copy(^(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y) { - uiDrawBrush brush; +struct closureParams { + size_t start; + size_t end; + double r; + double g; + double b; + double a; +}; - brush.Type = uiDrawBrushTypeSolid; - brush.R = r; - brush.G = g; - brush.B = b; - brush.A = a; - drawTextBackground(c, x, y, layout, start, end, &brush, 0); - }); +static void backgroundClosure(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y, gpointer data) +{ + struct closureParams *p = (struct closureParams *) data; + uiDrawBrush brush; + + brush.Type = uiDrawBrushTypeSolid; + brush.R = p->r; + brush.G = p->g; + brush.B = p->b; + brush.A = p->a; + drawTextBackground(c, x, y, layout, p->start, p->end, &brush, 0); +} + +static void freeClosureParams(gpointer data, GClosure *closure) +{ + uiFree((struct closureParams *) data); +} + +static GClosure *mkBackgroundClosure(size_t start, size_t end, double r, double g, double b, double a) +{ + struct closureParams *p; + GClosure *closure; + + p = uiNew(struct closureParams); + p->start = start; + p->end = end; + p->r = r; + p->g = g; + p->b = b; + p->a = a; + closure = (GClosure *) g_cclosure_new(G_CALLBACK(backgroundClosure), p, freeClosureParams); + // TODO write a specific marshaler + // TODO or drop the closure stuff entirely + g_closure_set_marshal(closure, g_cclosure_marshal_generic); + return closure; } -#endif struct otParam { struct foreachParams *p; @@ -107,7 +138,7 @@ static void addattr(struct foreachParams *p, size_t start, size_t end, PangoAttr static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data) { struct foreachParams *p = (struct foreachParams *) data; -//TODO backgroundBlock block; + GClosure *closure; PangoGravity gravity; PangoUnderline underline; PangoLanguage *lang; @@ -145,14 +176,11 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t FUTURE_pango_attr_foreground_alpha_new( (guint16) (spec->A * 65535.0))); break; -#if 0 /* TODO */ case uiAttributeBackground: - block = mkBackgroundBlock(ostart, oend, + closure = mkBackgroundClosure(start, end, spec->R, spec->G, spec->B, spec->A); - [p->backgroundBlocks addObject:block]; - Block_release(block); + g_ptr_array_add(p->backgroundClosures, closure); break; -#endif case uiAttributeVerticalForms: gravity = PANGO_GRAVITY_SOUTH; if (spec->Value != 0) @@ -249,7 +277,12 @@ static void applyAndFreeFeatureAttributes(struct foreachParams *p) g_hash_table_destroy(p->features); } -PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p/*TODO, NSArray **backgroundBlocks*/) +static void unrefClosure(gpointer data) +{ + g_closure_unref((GClosure *) data); +} + +PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **backgroundClosures) { struct foreachParams fep; @@ -258,7 +291,33 @@ PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p/*TODO, NSArray * fep.features = g_hash_table_new_full( featurePosHash, featurePosEqual, g_free, freeFeatureString); + fep.backgroundClosures = g_ptr_array_new_with_free_func(unrefClosure); uiAttributedStringForEachAttribute(p->String, processAttribute, &fep); applyAndFreeFeatureAttributes(&fep); + *backgroundClosures = fep.backgroundClosures; return fep.attrs; } + +void invokeBackgroundClosure(GClosure *closure, uiDrawContext *c, uiDrawTextLayout *layout, double x, double y) +{ + GValue values[4] = { + // the zero-initialization is needed for g_value_init() to work + G_VALUE_INIT, + G_VALUE_INIT, + G_VALUE_INIT, + G_VALUE_INIT, + }; + + g_value_init(values + 0, G_TYPE_POINTER); + g_value_set_pointer(values + 0, c); + g_value_init(values + 1, G_TYPE_POINTER); + g_value_set_pointer(values + 1, layout); + g_value_init(values + 2, G_TYPE_DOUBLE); + g_value_set_double(values + 2, x); + g_value_init(values + 3, G_TYPE_DOUBLE); + g_value_set_double(values + 3, y); + g_closure_invoke(closure, + NULL, + 4, values, + NULL); +} diff --git a/unix/drawtext.c b/unix/drawtext.c index f0e86b86..8b45530a 100644 --- a/unix/drawtext.c +++ b/unix/drawtext.c @@ -7,6 +7,7 @@ struct uiDrawTextLayout { PangoLayout *layout; + GPtrArray *backgroundClosures; uiDrawTextLayoutLineMetrics *lineMetrics; int nLines; }; @@ -138,7 +139,7 @@ uiDrawTextLayout *uiDrawNewTextLayout(uiDrawTextLayoutParams *p) pango_layout_set_alignment(tl->layout, pangoAligns[p->Align]); - attrs = attrstrToPangoAttrList(p); + attrs = attrstrToPangoAttrList(p, &(tl->backgroundClosures)); pango_layout_set_attributes(tl->layout, attrs); pango_attr_list_unref(attrs); @@ -151,12 +152,22 @@ uiDrawTextLayout *uiDrawNewTextLayout(uiDrawTextLayoutParams *p) void uiDrawFreeTextLayout(uiDrawTextLayout *tl) { uiFree(tl->lineMetrics); + g_ptr_array_unref(tl->backgroundClosures); g_object_unref(tl->layout); uiFree(tl); } void uiDrawText(uiDrawContext *c, uiDrawTextLayout *tl, double x, double y) { + guint i; + GClosure *closure; + + for (i = 0; i < tl->backgroundClosures->len; i++) { + closure = (GClosure *) g_ptr_array_index(tl->backgroundClosures, i); + invokeBackgroundClosure(closure, c, tl, x, y); + } + // TODO have an implicit save/restore on each drawing functions instead? and is this correct? + cairo_set_source_rgb(c->cr, 0.0, 0.0, 0.0); cairo_move_to(c->cr, x, y); pango_cairo_show_layout(c->cr, tl->layout); } diff --git a/unix/uipriv_unix.h b/unix/uipriv_unix.h index 78e94ad8..bde6502f 100644 --- a/unix/uipriv_unix.h +++ b/unix/uipriv_unix.h @@ -63,7 +63,8 @@ extern gboolean FUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path, extern void fontdescFromPangoFontDescription(PangoFontDescription *pdesc, uiDrawFontDescriptor *uidesc); // attrstr.c -extern PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p/*TODO, NSArray **backgroundBlocks*/); +extern PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **backgroundClosures); +extern void invokeBackgroundClosure(GClosure *closure, uiDrawContext *c, uiDrawTextLayout *layout, double x, double y); // drawtext.c // TODO get rid of these (for attrstr.c)