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;
|
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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue