And implemented the new features stuff on the GTK+ side.
This commit is contained in:
parent
ff4ab7110c
commit
39cec570d9
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue