And adding the background attributes. We're done with the Pango one! Now for the Windows one... yay.

This commit is contained in:
Pietro Gagliardi 2017-02-20 22:24:02 -05:00
parent 4ba4e4ba23
commit 75c2c80534
3 changed files with 94 additions and 23 deletions

View File

@ -10,7 +10,8 @@ struct foreachParams {
// keys are pointers to size_t maintained by g_new0()/g_free() // keys are pointers to size_t maintained by g_new0()/g_free()
// values are GStrings // values are GStrings
GHashTable *features; GHashTable *features;
//TODO GArray *backgroundBlocks; // TODO use pango's built-in background attribute?
GPtrArray *backgroundClosures;
}; };
static gboolean featurePosEqual(gconstpointer a, gconstpointer b) 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 */ struct closureParams {
static backgroundBlock mkBackgroundBlock(size_t start, size_t end, double r, double g, double b, double a) size_t start;
{ size_t end;
return Block_copy(^(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y) { double r;
uiDrawBrush brush; double g;
double b;
double a;
};
brush.Type = uiDrawBrushTypeSolid; static void backgroundClosure(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y, gpointer data)
brush.R = r; {
brush.G = g; struct closureParams *p = (struct closureParams *) data;
brush.B = b; uiDrawBrush brush;
brush.A = a;
drawTextBackground(c, x, y, layout, start, end, &brush, 0); 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 otParam {
struct foreachParams *p; 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) static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data)
{ {
struct foreachParams *p = (struct foreachParams *) data; struct foreachParams *p = (struct foreachParams *) data;
//TODO backgroundBlock block; GClosure *closure;
PangoGravity gravity; PangoGravity gravity;
PangoUnderline underline; PangoUnderline underline;
PangoLanguage *lang; PangoLanguage *lang;
@ -145,14 +176,11 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
FUTURE_pango_attr_foreground_alpha_new( FUTURE_pango_attr_foreground_alpha_new(
(guint16) (spec->A * 65535.0))); (guint16) (spec->A * 65535.0)));
break; break;
#if 0 /* TODO */
case uiAttributeBackground: case uiAttributeBackground:
block = mkBackgroundBlock(ostart, oend, closure = mkBackgroundClosure(start, end,
spec->R, spec->G, spec->B, spec->A); spec->R, spec->G, spec->B, spec->A);
[p->backgroundBlocks addObject:block]; g_ptr_array_add(p->backgroundClosures, closure);
Block_release(block);
break; break;
#endif
case uiAttributeVerticalForms: case uiAttributeVerticalForms:
gravity = PANGO_GRAVITY_SOUTH; gravity = PANGO_GRAVITY_SOUTH;
if (spec->Value != 0) if (spec->Value != 0)
@ -249,7 +277,12 @@ static void applyAndFreeFeatureAttributes(struct foreachParams *p)
g_hash_table_destroy(p->features); 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; struct foreachParams fep;
@ -258,7 +291,33 @@ PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p/*TODO, NSArray *
fep.features = g_hash_table_new_full( fep.features = g_hash_table_new_full(
featurePosHash, featurePosEqual, featurePosHash, featurePosEqual,
g_free, freeFeatureString); g_free, freeFeatureString);
fep.backgroundClosures = g_ptr_array_new_with_free_func(unrefClosure);
uiAttributedStringForEachAttribute(p->String, processAttribute, &fep); uiAttributedStringForEachAttribute(p->String, processAttribute, &fep);
applyAndFreeFeatureAttributes(&fep); applyAndFreeFeatureAttributes(&fep);
*backgroundClosures = fep.backgroundClosures;
return fep.attrs; 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);
}

View File

@ -7,6 +7,7 @@
struct uiDrawTextLayout { struct uiDrawTextLayout {
PangoLayout *layout; PangoLayout *layout;
GPtrArray *backgroundClosures;
uiDrawTextLayoutLineMetrics *lineMetrics; uiDrawTextLayoutLineMetrics *lineMetrics;
int nLines; int nLines;
}; };
@ -138,7 +139,7 @@ uiDrawTextLayout *uiDrawNewTextLayout(uiDrawTextLayoutParams *p)
pango_layout_set_alignment(tl->layout, pangoAligns[p->Align]); 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_layout_set_attributes(tl->layout, attrs);
pango_attr_list_unref(attrs); pango_attr_list_unref(attrs);
@ -151,12 +152,22 @@ uiDrawTextLayout *uiDrawNewTextLayout(uiDrawTextLayoutParams *p)
void uiDrawFreeTextLayout(uiDrawTextLayout *tl) void uiDrawFreeTextLayout(uiDrawTextLayout *tl)
{ {
uiFree(tl->lineMetrics); uiFree(tl->lineMetrics);
g_ptr_array_unref(tl->backgroundClosures);
g_object_unref(tl->layout); g_object_unref(tl->layout);
uiFree(tl); uiFree(tl);
} }
void uiDrawText(uiDrawContext *c, uiDrawTextLayout *tl, double x, double y) 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); cairo_move_to(c->cr, x, y);
pango_cairo_show_layout(c->cr, tl->layout); pango_cairo_show_layout(c->cr, tl->layout);
} }

View File

@ -63,7 +63,8 @@ extern gboolean FUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path,
extern void fontdescFromPangoFontDescription(PangoFontDescription *pdesc, uiDrawFontDescriptor *uidesc); extern void fontdescFromPangoFontDescription(PangoFontDescription *pdesc, uiDrawFontDescriptor *uidesc);
// attrstr.c // 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 // drawtext.c
// TODO get rid of these (for attrstr.c) // TODO get rid of these (for attrstr.c)