diff --git a/unix/attrstr.c b/unix/attrstr.c index 88eabef4..7bf556c9 100644 --- a/unix/attrstr.c +++ b/unix/attrstr.c @@ -10,7 +10,7 @@ struct foreachParams { const char *s; PangoAttrList *attrs; // keys are pointers to size_t maintained by g_new0()/g_free() - // values are GStrings + // values are strings GHashTable *features; // TODO use pango's built-in background attribute? GPtrArray *backgroundClosures; @@ -38,24 +38,22 @@ static void freeFeatureString(gpointer s) #define isCodepointStart(b) (((uint8_t) (b)) <= 0x7F || ((uint8_t) (b)) >= 0xC0) -static void ensureFeaturesInRange(struct foreachParams *p, size_t start, size_t end) +static void setFeaturesInRange(struct foreachParams *p, size_t start, size_t end, uiOpenTypeFeatures *otf) { size_t i; size_t *key; GString *new; + new = otfToPangoCSSString(otf); for (i = start; i < end; i++) { // don't create redundant entries; see below if (!isCodepointStart(p->s[i])) continue; - new = (GString *) g_hash_table_lookup(p->features, &i); - if (new != NULL) - continue; - new = g_string_new(""); key = g_new0(size_t, 1); *key = i; - g_hash_table_replace(p->features, key, new); + g_hash_table_replace(p->features, key, g_strdup(new->str)); } + g_string_free(new, TRUE); } struct closureParams { @@ -104,30 +102,6 @@ static GClosure *mkBackgroundClosure(size_t start, size_t end, double r, double return closure; } -struct otParam { - struct foreachParams *p; - size_t start; - size_t end; -}; - -// see https://developer.mozilla.org/en/docs/Web/CSS/font-feature-settings -static void doOpenType(const char *featureTag, uint32_t param, void *data) -{ - struct otParam *p = (struct otParam *) data; - size_t i; - GString *s; - - ensureFeaturesInRange(p->p, p->start, p->end); - for (i = p->start; i < p->end; i++) { - // don't use redundant entries; see below - if (!isCodepointStart(p->p->s[i])) - continue; - s = (GString *) g_hash_table_lookup(p->p->features, &i); - g_string_append_printf(s, "\"%s\" %" PRIu32 ", ", - featureTag, param); - } -} - static void addattr(struct foreachParams *p, size_t start, size_t end, PangoAttribute *attr) { if (attr == NULL) // in case of a future attribute @@ -142,7 +116,6 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t struct foreachParams *p = (struct foreachParams *) data; GClosure *closure; PangoUnderline underline; - struct otParam op; switch (spec->Type) { case uiAttributeFamily: @@ -225,14 +198,13 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t break; } break; - default: - // handle typographic features - op.p = p; - op.start = start; - op.end = end; - // TODO check if unhandled and complain - specToOpenType(spec, doOpenType, &op); + case uiAttributeFeatures: + // TODO ensure the parentheses around spec->Value are provided on Windows + setFeaturesInRange(p, start, end, (uiOpenTypeFeatures *) (spec->Value)); break; + default: + // TODO complain + ; } return 0; } @@ -241,18 +213,16 @@ static gboolean applyFeatures(gpointer key, gpointer value, gpointer data) { struct foreachParams *p = (struct foreachParams *) data; size_t *pos = (size_t *) key; - GString *s = (GString *) value; + char *s = (char *) value; size_t n; - // remove the trailing comma/space - g_string_truncate(s, s->len - 2); // make sure we cover an entire code point // otherwise Pango will break apart multi-byte characters, spitting out U+FFFD characters at the invalid points n = 1; while (!isCodepointStart(p->s[*pos + n])) n++; addattr(p, *pos, *pos + n, - FUTURE_pango_attr_font_features_new(s->str)); + FUTURE_pango_attr_font_features_new(s)); return TRUE; // always delete; we're emptying the map } @@ -275,7 +245,7 @@ PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **bac fep.attrs = pango_attr_list_new(); fep.features = g_hash_table_new_full( featurePosHash, featurePosEqual, - g_free, freeFeatureString); + g_free, g_free); fep.backgroundClosures = g_ptr_array_new_with_free_func(unrefClosure); uiAttributedStringForEachAttribute(p->String, processAttribute, &fep); applyAndFreeFeatureAttributes(&fep); diff --git a/unix/opentype.c b/unix/opentype.c index 12869a6a..6ea317c5 100644 --- a/unix/opentype.c +++ b/unix/opentype.c @@ -1,7 +1,7 @@ // 11 may 2017 -#include "uipriv_windows.hpp" +#include "uipriv_unix.h" -// TODO switch from GINT_FROM_POINTER() and so to a fake GUINT_FROM_POINTER()? +// TODO switch from GINT_TO_POINTER() and so to a fake GUINT_TO_POINTER()? struct uiOpenTypeFeatures { GHashTable *tags; @@ -106,9 +106,9 @@ void uiOpenTypeFeaturesForEach(uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEac g_hash_table_foreach(otf->tags, foreach, &ofe); } -static gint tagcmp(gpointer a, gpointer b) +static gint tagcmp(gconstpointer a, gconstpointer b) { - return GINT_FROM_POINTER(a) - GINT_FROM_POINTER(b); + return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b); } static GList *copySortedKeys(GHashTable *tags) @@ -130,8 +130,8 @@ int uiOpenTypeFeaturesEqual(uiOpenTypeFeatures *a, uiOpenTypeFeatures *b) guint i; int equal = 0; - ak = copySortedKeys(a); - bk = copySortedKeys(b); + ak = copySortedKeys(a->tags); + bk = copySortedKeys(b->tags); na = g_list_length(ak); nb = g_list_length(bk); @@ -140,7 +140,7 @@ int uiOpenTypeFeaturesEqual(uiOpenTypeFeatures *a, uiOpenTypeFeatures *b) goto out; } - // TODO use GINT_FROM_POINTER() in these? + // TODO use GPOINTER_TO_INT() in these? ai = ak; bi = bk; for (i = 0; i < na; i++) { @@ -153,8 +153,8 @@ int uiOpenTypeFeaturesEqual(uiOpenTypeFeatures *a, uiOpenTypeFeatures *b) goto out; } // and compare values - av = g_hash_table_lookup(a, ai->data); - bv = g_hash_table_lookup(b, bi->data); + av = g_hash_table_lookup(a->tags, ai->data); + bv = g_hash_table_lookup(b->tags, bi->data); if (av != bv) { equal = 0; goto out; @@ -172,6 +172,7 @@ out: return equal; } +// see https://developer.mozilla.org/en/docs/Web/CSS/font-feature-settings // TODO make this a g_hash_table_foreach() function (which requires duplicating code)? static int toCSS(char a, char b, char c, char d, uint32_t value, void *data) { diff --git a/unix/uipriv_unix.h b/unix/uipriv_unix.h index bde6502f..cb5bf281 100644 --- a/unix/uipriv_unix.h +++ b/unix/uipriv_unix.h @@ -71,3 +71,6 @@ extern void invokeBackgroundClosure(GClosure *closure, uiDrawContext *c, uiDrawT #define cairoToPango(cairo) (pango_units_from_double(cairo)) extern const PangoStyle pangoItalics[]; extern const PangoStretch pangoStretches[]; + +// opentype.c +extern GString *otfToPangoCSSString(uiOpenTypeFeatures *otf);