And fixed the whole OpenType features nonsense on GTK+, since we now group all OpenType features together. We're now much closer to pushing this back into master!
This commit is contained in:
parent
c61bbfe5c8
commit
2e98219009
|
@ -3,57 +3,25 @@
|
||||||
|
|
||||||
// TODO pango alpha attributes turn 0 into 65535 :|
|
// TODO pango alpha attributes turn 0 into 65535 :|
|
||||||
|
|
||||||
// we need to collect all the OpenType features and background blocks and add them all at once
|
// we need to collect all the background blocks and add them all at once
|
||||||
// TODO this is the wrong approach; it causes Pango to end runs early, meaning attributes like the ligature attributes never get applied properly
|
|
||||||
// TODO rename this struct to something that isn't exclusively foreach-ing?
|
// TODO rename this struct to something that isn't exclusively foreach-ing?
|
||||||
struct foreachParams {
|
struct foreachParams {
|
||||||
const char *s;
|
const char *s;
|
||||||
PangoAttrList *attrs;
|
PangoAttrList *attrs;
|
||||||
// keys are pointers to size_t maintained by g_new0()/g_free()
|
|
||||||
// values are strings
|
|
||||||
GHashTable *features;
|
|
||||||
// TODO use pango's built-in background attribute?
|
// TODO use pango's built-in background attribute?
|
||||||
GPtrArray *backgroundClosures;
|
GPtrArray *backgroundClosures;
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean featurePosEqual(gconstpointer a, gconstpointer b)
|
// TODO merge this into the main function below
|
||||||
|
static PangoAttribute *mkFeaturesAttribute(const uiOpenTypeFeatures *otf)
|
||||||
{
|
{
|
||||||
size_t *sa = (size_t *) a;
|
char *s;
|
||||||
size_t *sb = (size_t *) b;
|
PangoAttribute *attr;
|
||||||
|
|
||||||
return *sa == *sb;
|
s = otfToPangoCSSString(otf);
|
||||||
}
|
attr = FUTURE_pango_attr_font_features_new(s);
|
||||||
|
g_free(s);
|
||||||
static guint featurePosHash(gconstpointer n)
|
return attr;
|
||||||
{
|
|
||||||
size_t *sn = (size_t *) n;
|
|
||||||
|
|
||||||
return (guint) (*sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void freeFeatureString(gpointer s)
|
|
||||||
{
|
|
||||||
g_string_free((GString *) s, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define isCodepointStart(b) (((uint8_t) (b)) <= 0x7F || ((uint8_t) (b)) >= 0xC0)
|
|
||||||
|
|
||||||
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;
|
|
||||||
key = g_new0(size_t, 1);
|
|
||||||
*key = i;
|
|
||||||
g_hash_table_replace(p->features, key, g_strdup(new->str));
|
|
||||||
}
|
|
||||||
g_string_free(new, TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct closureParams {
|
struct closureParams {
|
||||||
|
@ -199,8 +167,8 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case uiAttributeFeatures:
|
case uiAttributeFeatures:
|
||||||
// TODO ensure the parentheses around spec->Value are provided on Windows (TODO still relevant?)
|
// TODO handle NULLs properly on all platforms
|
||||||
setFeaturesInRange(p, start, end, spec->Features);
|
addattr(p, start, end, mkFeaturesAttribute(spec->Features));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// TODO complain
|
// TODO complain
|
||||||
|
@ -209,29 +177,6 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean applyFeatures(gpointer key, gpointer value, gpointer data)
|
|
||||||
{
|
|
||||||
struct foreachParams *p = (struct foreachParams *) data;
|
|
||||||
size_t *pos = (size_t *) key;
|
|
||||||
char *s = (char *) value;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
return TRUE; // always delete; we're emptying the map
|
|
||||||
}
|
|
||||||
|
|
||||||
static void applyAndFreeFeatureAttributes(struct foreachParams *p)
|
|
||||||
{
|
|
||||||
g_hash_table_foreach_remove(p->features, applyFeatures, p);
|
|
||||||
g_hash_table_destroy(p->features);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unrefClosure(gpointer data)
|
static void unrefClosure(gpointer data)
|
||||||
{
|
{
|
||||||
g_closure_unref((GClosure *) data);
|
g_closure_unref((GClosure *) data);
|
||||||
|
@ -243,12 +188,8 @@ PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **bac
|
||||||
|
|
||||||
fep.s = uiAttributedStringString(p->String);
|
fep.s = uiAttributedStringString(p->String);
|
||||||
fep.attrs = pango_attr_list_new();
|
fep.attrs = pango_attr_list_new();
|
||||||
fep.features = g_hash_table_new_full(
|
|
||||||
featurePosHash, featurePosEqual,
|
|
||||||
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);
|
|
||||||
*backgroundClosures = fep.backgroundClosures;
|
*backgroundClosures = fep.backgroundClosures;
|
||||||
return fep.attrs;
|
return fep.attrs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ static int toCSS(char a, char b, char c, char d, uint32_t value, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GString *otfToPangoCSSString(uiOpenTypeFeatures *otf)
|
gchar *otfToPangoCSSString(const uiOpenTypeFeatures *otf)
|
||||||
{
|
{
|
||||||
GString *s;
|
GString *s;
|
||||||
|
|
||||||
|
@ -196,5 +196,5 @@ GString *otfToPangoCSSString(uiOpenTypeFeatures *otf)
|
||||||
if (s->len != 0)
|
if (s->len != 0)
|
||||||
// and remove the last comma
|
// and remove the last comma
|
||||||
g_string_truncate(s, s->len - 2);
|
g_string_truncate(s, s->len - 2);
|
||||||
return s;
|
return g_string_free(s, FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,4 +73,4 @@ extern const PangoStyle pangoItalics[];
|
||||||
extern const PangoStretch pangoStretches[];
|
extern const PangoStretch pangoStretches[];
|
||||||
|
|
||||||
// opentype.c
|
// opentype.c
|
||||||
extern GString *otfToPangoCSSString(uiOpenTypeFeatures *otf);
|
extern gchar *otfToPangoCSSString(const uiOpenTypeFeatures *otf);
|
||||||
|
|
Loading…
Reference in New Issue