diff --git a/darwin/attrstr.m b/darwin/attrstr.m index 530e6a22..180bf272 100644 --- a/darwin/attrstr.m +++ b/darwin/attrstr.m @@ -454,7 +454,7 @@ static CTParagraphStyleRef mkParagraphStyle(uiDrawTextLayoutParams *p) return ps; } -// TODO either rename this to uiprivDrawTextLayoutParams... or rename this file or both or split the struct or something else... +// TODO either rename this (on all platforms) to uiprivDrawTextLayoutParams... or rename this file or both or split the struct or something else... CFAttributedStringRef uiprivAttributedStringToCFAttributedString(uiDrawTextLayoutParams *p, NSArray **backgroundParams) { CFStringRef cfstr; diff --git a/unix/OLD_attrstr.c b/unix/OLD_attrstr.c deleted file mode 100644 index 36141b7c..00000000 --- a/unix/OLD_attrstr.c +++ /dev/null @@ -1,211 +0,0 @@ -// 12 february 2017 -#include "uipriv_unix.h" - -// TODO pango alpha attributes turn 0 into 65535 :| - -// TODO make this name less generic? -struct foreachParams { - PangoAttrList *attrs; - // TODO use pango's built-in background attribute? - GPtrArray *backgroundClosures; -}; - -struct closureParams { - size_t start; - size_t end; - double r; - double g; - double b; - double a; -}; - -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 = 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; -} - -static void addattr(struct foreachParams *p, size_t start, size_t end, PangoAttribute *attr) -{ - if (attr == NULL) // in case of a future attribute - return; - attr->start_index = start; - attr->end_index = end; - pango_attr_list_insert(p->attrs, attr); -} - -static uiForEach processAttribute(const uiAttributedString *s, const uiAttributeSpec *spec, size_t start, size_t end, void *data) -{ - struct foreachParams *p = (struct foreachParams *) data; - GClosure *closure; - PangoUnderline underline; - char *featurestr; - - switch (spec->Type) { - case uiAttributeFamily: - addattr(p, start, end, - pango_attr_family_new(spec->Family)); - break; - case uiAttributeSize: - addattr(p, start, end, - pango_attr_size_new(cairoToPango(spec->Double))); - break; - case uiAttributeWeight: - // TODO reverse the misalignment from drawtext.c if it is corrected - addattr(p, start, end, - pango_attr_weight_new((PangoWeight) (spec->Value))); - break; - case uiAttributeItalic: - addattr(p, start, end, - pango_attr_style_new(pangoItalics[(uiDrawTextItalic) (spec->Value)])); - break; - case uiAttributeStretch: - addattr(p, start, end, - pango_attr_stretch_new(pangoStretches[(uiDrawTextStretch) (spec->Value)])); - break; - case uiAttributeColor: - addattr(p, start, end, - pango_attr_foreground_new( - (guint16) (spec->R * 65535.0), - (guint16) (spec->G * 65535.0), - (guint16) (spec->B * 65535.0))); - addattr(p, start, end, - FUTURE_pango_attr_foreground_alpha_new( - (guint16) (spec->A * 65535.0))); - break; - case uiAttributeBackground: - closure = mkBackgroundClosure(start, end, - spec->R, spec->G, spec->B, spec->A); - g_ptr_array_add(p->backgroundClosures, closure); - break; - case uiAttributeUnderline: - switch (spec->Value) { - case uiDrawUnderlineStyleNone: - underline = PANGO_UNDERLINE_NONE; - break; - case uiDrawUnderlineStyleSingle: - underline = PANGO_UNDERLINE_SINGLE; - break; - case uiDrawUnderlineStyleDouble: - underline = PANGO_UNDERLINE_DOUBLE; - break; - case uiDrawUnderlineStyleSuggestion: - underline = PANGO_UNDERLINE_ERROR; - break; - } - addattr(p, start, end, - pango_attr_underline_new(underline)); - break; - case uiAttributeUnderlineColor: - switch (spec->Value) { - case uiDrawUnderlineColorCustom: - addattr(p, start, end, - pango_attr_underline_color_new( - (guint16) (spec->R * 65535.0), - (guint16) (spec->G * 65535.0), - (guint16) (spec->B * 65535.0))); - break; - case uiDrawUnderlineColorSpelling: - // TODO GtkTextView style property error-underline-color - addattr(p, start, end, - pango_attr_underline_color_new(65535, 0, 0)); - break; - case uiDrawUnderlineColorGrammar: - // TODO find a more appropriate color - addattr(p, start, end, - pango_attr_underline_color_new(0, 65535, 0)); - break; - case uiDrawUnderlineColorAuxiliary: - // TODO find a more appropriate color - addattr(p, start, end, - pango_attr_underline_color_new(0, 0, 65535)); - break; - } - break; - case uiAttributeFeatures: - // only generate an attribute if spec->Features is not NULL - // TODO state that this is allowed - if (spec->Features == NULL) - break; - featurestr = otfToPangoCSSString(spec->Features); - addattr(p, start, end, - FUTURE_pango_attr_font_features_new(featurestr)); - g_free(featurestr); - break; - default: - // TODO complain - ; - } - return uiForEachContinue; -} - -static void unrefClosure(gpointer data) -{ - g_closure_unref((GClosure *) data); -} - -PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **backgroundClosures) -{ - struct foreachParams fep; - - fep.attrs = pango_attr_list_new(); - fep.backgroundClosures = g_ptr_array_new_with_free_func(unrefClosure); - uiAttributedStringForEachAttribute(p->String, processAttribute, &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/attrstr.c b/unix/attrstr.c new file mode 100644 index 00000000..0ffb0b56 --- /dev/null +++ b/unix/attrstr.c @@ -0,0 +1,173 @@ +// 12 february 2017 +#include "uipriv_unix.h" +#include "attrstr.h" + +// TODO pango alpha attributes turn 0 into 65535 :| + +// TODO make this name less generic? +struct foreachParams { + PangoAttrList *attrs; + // TODO use pango's built-in background attribute + GPtrArray *backgroundParams; +}; + +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; +//TODO drawTextBackground(c, x, y, layout, p->start, p->end, &brush, 0); +} + +static void addBackgroundAttribute(struct foreachParams *p, size_t start, size_t end, double r, double g, double b, double a) +{ + uiprivDrawTextBackgroundParams *dtb; + + dtb = uiprivNew(uiprivDrawTextBackgroundParams); + dtb->start = start; + dtb->end = end; + dtb->r = r; + dtb->g = g; + dtb->b = b; + dtb->a = a; + g_ptr_array_add(p->backgroundParams, dtb); +} + +static void addattr(struct foreachParams *p, size_t start, size_t end, PangoAttribute *attr) +{ + if (attr == NULL) // in case of a future attribute + return; + attr->start_index = start; + attr->end_index = end; + pango_attr_list_insert(p->attrs, attr); +} + +static uiForEach processAttribute(const uiAttributedString *s, const uiAttribute *attr, size_t start, size_t end, void *data) +{ + struct foreachParams *p = (struct foreachParams *) data; + double r, g, b, a; + PangoUnderline underline; + uiUnderlineColor colorType; + const uiOpenTypeFeatures *features; + GString *featurestr; + + switch (uiAttributeGetType(attr)) { + case uiAttributeTypeFamily: + addattr(p, start, end, + pango_attr_family_new(uiAttributeFamily(attr))); + break; + case uiAttributeTypeSize: + addattr(p, start, end, + pango_attr_size_new(cairoToPango(uiAttributeSize(attr)))); + break; + case uiAttributeTypeWeight: + // TODO reverse the misalignment from drawtext.c if it is corrected + addattr(p, start, end, + pango_attr_weight_new((PangoWeight) uiAttributeWeight(attr))); + break; + case uiAttributeTypeItalic: + addattr(p, start, end, + pango_attr_style_new(pangoItalics[uiAttributeItalic(attr)])); + break; + case uiAttributeTypeStretch: + addattr(p, start, end, + pango_attr_stretch_new(pangoStretches[uiAttributeStretch(attr)])); + break; + case uiAttributeTypeColor: + uiAttributeColor(attr, &r, &g, &b, &a); + addattr(p, start, end, + pango_attr_foreground_new( + (guint16) (r * 65535.0), + (guint16) (g * 65535.0), + (guint16) (b * 65535.0))); + addattr(p, start, end, + FUTURE_pango_attr_foreground_alpha_new( + (guint16) (a * 65535.0))); + break; + case uiAttributeTypeBackground: + uiAttributeColor(attr, &r, &g, &b, &a); + addBackgroundAttribute(p, start, end, r, g, b, a); + break; + case uiAttributeTypeUnderline: + switch (uiAttributeUnderline(attr)) { + case uiUnderlineNone: + underline = PANGO_UNDERLINE_NONE; + break; + case uiUnderlineSingle: + underline = PANGO_UNDERLINE_SINGLE; + break; + case uiUnderlineDouble: + underline = PANGO_UNDERLINE_DOUBLE; + break; + case uiUnderlineSuggestion: + underline = PANGO_UNDERLINE_ERROR; + break; + } + addattr(p, start, end, + pango_attr_underline_new(underline)); + break; + case uiAttributeTypeUnderlineColor: + uiAttributeUnderlineColor(attr, &colorType, &r, &g, &b, &a); + switch (colorType) { + case uiUnderlineColorCustom: + addattr(p, start, end, + pango_attr_underline_color_new( + (guint16) (r * 65535.0), + (guint16) (g * 65535.0), + (guint16) (b * 65535.0))); + break; + case uiUnderlineColorSpelling: + // TODO GtkTextView style property error-underline-color + addattr(p, start, end, + pango_attr_underline_color_new(65535, 0, 0)); + break; + case uiUnderlineColorGrammar: + // TODO find a more appropriate color + addattr(p, start, end, + pango_attr_underline_color_new(0, 65535, 0)); + break; + case uiUnderlineColorAuxiliary: + // TODO find a more appropriate color + addattr(p, start, end, + pango_attr_underline_color_new(0, 0, 65535)); + break; + } + break; + case uiAttributeTypeFeatures: + // only generate an attribute if the features object is not NULL + // TODO state that this is allowed + features = uiAttributeFeatures(attr); + if (features == NULL) + break; + featurestr = uiprivOpenTypeFeaturesToPangoCSSFeaturesString(features); + addattr(p, start, end, + FUTURE_pango_attr_font_features_new(featurestr->str)); + g_string_free(featurestr, TRUE); + break; + default: + // TODO complain + ; + } + return uiForEachContinue; +} + +static void freeBackgroundParams(gpointer data) +{ + uiprivFree((uiprivDrawTextBackgroundParams *) data); +} + +PangoAttrList *uiprivAttributedStringToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **backgroundParams) +{ + struct foreachParams fep; + + fep.attrs = pango_attr_list_new(); + fep.backgroundParams = g_ptr_array_new_with_free_func(freeBackgroundParams); + uiAttributedStringForEachAttribute(p->String, processAttribute, &fep); + *backgroundParams = fep.backgroundParams; + return fep.attrs; +} diff --git a/unix/attrstr.h b/unix/attrstr.h index 3c3e49b3..c2632786 100644 --- a/unix/attrstr.h +++ b/unix/attrstr.h @@ -1,4 +1,20 @@ // 11 march 2018 +#import "../common/attrstr.h" // opentype.c extern GString *uiprivOpenTypeFeaturesToPangoCSSFeaturesString(const uiOpenTypeFeatures *otf); + +// attrstr.c +extern PangoAttrList *uiprivAttributedStringToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **backgroundParams); + +// drawtext.c +// TODO figure out where this type should *really* go in all the headers... +typedef struct uiprivDrawTextBackgroundParams uiprivDrawTextBackgroundParams; +struct uiprivDrawTextBackgroundParams { + size_t start; + size_t end; + double r; + double g; + double b; + double a; +};