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 :|
|
||||
|
||||
// we need to collect all the OpenType features and 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
|
||||
// we need to collect all the background blocks and add them all at once
|
||||
// TODO rename this struct to something that isn't exclusively foreach-ing?
|
||||
struct foreachParams {
|
||||
const char *s;
|
||||
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?
|
||||
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;
|
||||
size_t *sb = (size_t *) b;
|
||||
char *s;
|
||||
PangoAttribute *attr;
|
||||
|
||||
return *sa == *sb;
|
||||
}
|
||||
|
||||
static guint featurePosHash(gconstpointer n)
|
||||
{
|
||||
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);
|
||||
s = otfToPangoCSSString(otf);
|
||||
attr = FUTURE_pango_attr_font_features_new(s);
|
||||
g_free(s);
|
||||
return attr;
|
||||
}
|
||||
|
||||
struct closureParams {
|
||||
|
@ -199,8 +167,8 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
|
|||
}
|
||||
break;
|
||||
case uiAttributeFeatures:
|
||||
// TODO ensure the parentheses around spec->Value are provided on Windows (TODO still relevant?)
|
||||
setFeaturesInRange(p, start, end, spec->Features);
|
||||
// TODO handle NULLs properly on all platforms
|
||||
addattr(p, start, end, mkFeaturesAttribute(spec->Features));
|
||||
break;
|
||||
default:
|
||||
// TODO complain
|
||||
|
@ -209,29 +177,6 @@ static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t
|
|||
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)
|
||||
{
|
||||
g_closure_unref((GClosure *) data);
|
||||
|
@ -243,12 +188,8 @@ PangoAttrList *attrstrToPangoAttrList(uiDrawTextLayoutParams *p, GPtrArray **bac
|
|||
|
||||
fep.s = uiAttributedStringString(p->String);
|
||||
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);
|
||||
uiAttributedStringForEachAttribute(p->String, processAttribute, &fep);
|
||||
applyAndFreeFeatureAttributes(&fep);
|
||||
*backgroundClosures = fep.backgroundClosures;
|
||||
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;
|
||||
}
|
||||
|
||||
GString *otfToPangoCSSString(uiOpenTypeFeatures *otf)
|
||||
gchar *otfToPangoCSSString(const uiOpenTypeFeatures *otf)
|
||||
{
|
||||
GString *s;
|
||||
|
||||
|
@ -196,5 +196,5 @@ GString *otfToPangoCSSString(uiOpenTypeFeatures *otf)
|
|||
if (s->len != 0)
|
||||
// and remove the last comma
|
||||
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[];
|
||||
|
||||
// opentype.c
|
||||
extern GString *otfToPangoCSSString(uiOpenTypeFeatures *otf);
|
||||
extern gchar *otfToPangoCSSString(const uiOpenTypeFeatures *otf);
|
||||
|
|
Loading…
Reference in New Issue