And implemented the new features stuff on the GTK+ side.

This commit is contained in:
Pietro Gagliardi 2017-05-17 23:37:16 -04:00
parent ff4ab7110c
commit 39cec570d9
3 changed files with 27 additions and 53 deletions

View File

@ -10,7 +10,7 @@ struct foreachParams {
const char *s; const char *s;
PangoAttrList *attrs; PangoAttrList *attrs;
// 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 strings
GHashTable *features; GHashTable *features;
// TODO use pango's built-in background attribute? // TODO use pango's built-in background attribute?
GPtrArray *backgroundClosures; GPtrArray *backgroundClosures;
@ -38,24 +38,22 @@ static void freeFeatureString(gpointer s)
#define isCodepointStart(b) (((uint8_t) (b)) <= 0x7F || ((uint8_t) (b)) >= 0xC0) #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 i;
size_t *key; size_t *key;
GString *new; GString *new;
new = otfToPangoCSSString(otf);
for (i = start; i < end; i++) { for (i = start; i < end; i++) {
// don't create redundant entries; see below // don't create redundant entries; see below
if (!isCodepointStart(p->s[i])) if (!isCodepointStart(p->s[i]))
continue; 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 = g_new0(size_t, 1);
*key = i; *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 { struct closureParams {
@ -104,30 +102,6 @@ static GClosure *mkBackgroundClosure(size_t start, size_t end, double r, double
return closure; 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) static void addattr(struct foreachParams *p, size_t start, size_t end, PangoAttribute *attr)
{ {
if (attr == NULL) // in case of a future attribute 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; struct foreachParams *p = (struct foreachParams *) data;
GClosure *closure; GClosure *closure;
PangoUnderline underline; PangoUnderline underline;
struct otParam op;
switch (spec->Type) { switch (spec->Type) {
case uiAttributeFamily: case uiAttributeFamily:
@ -225,14 +198,13 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
break; break;
} }
break; break;
default: case uiAttributeFeatures:
// handle typographic features // TODO ensure the parentheses around spec->Value are provided on Windows
op.p = p; setFeaturesInRange(p, start, end, (uiOpenTypeFeatures *) (spec->Value));
op.start = start;
op.end = end;
// TODO check if unhandled and complain
specToOpenType(spec, doOpenType, &op);
break; break;
default:
// TODO complain
;
} }
return 0; return 0;
} }
@ -241,18 +213,16 @@ static gboolean applyFeatures(gpointer key, gpointer value, gpointer data)
{ {
struct foreachParams *p = (struct foreachParams *) data; struct foreachParams *p = (struct foreachParams *) data;
size_t *pos = (size_t *) key; size_t *pos = (size_t *) key;
GString *s = (GString *) value; char *s = (char *) value;
size_t n; size_t n;
// remove the trailing comma/space
g_string_truncate(s, s->len - 2);
// make sure we cover an entire code point // 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 // otherwise Pango will break apart multi-byte characters, spitting out U+FFFD characters at the invalid points
n = 1; n = 1;
while (!isCodepointStart(p->s[*pos + n])) while (!isCodepointStart(p->s[*pos + n]))
n++; n++;
addattr(p, *pos, *pos + 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 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.attrs = pango_attr_list_new();
fep.features = g_hash_table_new_full( fep.features = g_hash_table_new_full(
featurePosHash, featurePosEqual, featurePosHash, featurePosEqual,
g_free, freeFeatureString); g_free, g_free);
fep.backgroundClosures = g_ptr_array_new_with_free_func(unrefClosure); fep.backgroundClosures = g_ptr_array_new_with_free_func(unrefClosure);
uiAttributedStringForEachAttribute(p->String, processAttribute, &fep); uiAttributedStringForEachAttribute(p->String, processAttribute, &fep);
applyAndFreeFeatureAttributes(&fep); applyAndFreeFeatureAttributes(&fep);

View File

@ -1,7 +1,7 @@
// 11 may 2017 // 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 { struct uiOpenTypeFeatures {
GHashTable *tags; GHashTable *tags;
@ -106,9 +106,9 @@ void uiOpenTypeFeaturesForEach(uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEac
g_hash_table_foreach(otf->tags, foreach, &ofe); 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) static GList *copySortedKeys(GHashTable *tags)
@ -130,8 +130,8 @@ int uiOpenTypeFeaturesEqual(uiOpenTypeFeatures *a, uiOpenTypeFeatures *b)
guint i; guint i;
int equal = 0; int equal = 0;
ak = copySortedKeys(a); ak = copySortedKeys(a->tags);
bk = copySortedKeys(b); bk = copySortedKeys(b->tags);
na = g_list_length(ak); na = g_list_length(ak);
nb = g_list_length(bk); nb = g_list_length(bk);
@ -140,7 +140,7 @@ int uiOpenTypeFeaturesEqual(uiOpenTypeFeatures *a, uiOpenTypeFeatures *b)
goto out; goto out;
} }
// TODO use GINT_FROM_POINTER() in these? // TODO use GPOINTER_TO_INT() in these?
ai = ak; ai = ak;
bi = bk; bi = bk;
for (i = 0; i < na; i++) { for (i = 0; i < na; i++) {
@ -153,8 +153,8 @@ int uiOpenTypeFeaturesEqual(uiOpenTypeFeatures *a, uiOpenTypeFeatures *b)
goto out; goto out;
} }
// and compare values // and compare values
av = g_hash_table_lookup(a, ai->data); av = g_hash_table_lookup(a->tags, ai->data);
bv = g_hash_table_lookup(b, bi->data); bv = g_hash_table_lookup(b->tags, bi->data);
if (av != bv) { if (av != bv) {
equal = 0; equal = 0;
goto out; goto out;
@ -172,6 +172,7 @@ out:
return equal; 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)? // 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) static int toCSS(char a, char b, char c, char d, uint32_t value, void *data)
{ {

View File

@ -71,3 +71,6 @@ extern void invokeBackgroundClosure(GClosure *closure, uiDrawContext *c, uiDrawT
#define cairoToPango(cairo) (pango_units_from_double(cairo)) #define cairoToPango(cairo) (pango_units_from_double(cairo))
extern const PangoStyle pangoItalics[]; extern const PangoStyle pangoItalics[];
extern const PangoStretch pangoStretches[]; extern const PangoStretch pangoStretches[];
// opentype.c
extern GString *otfToPangoCSSString(uiOpenTypeFeatures *otf);