Changed the representation of an attribute type/value pair to allow more type safety and expressability.

This commit is contained in:
Pietro Gagliardi 2017-02-12 14:11:25 -05:00
parent 1c1b16a206
commit 261dd4851a
6 changed files with 61 additions and 47 deletions

View File

@ -12,8 +12,7 @@ The linked list is not a ring; alist->fist->prev == NULL and alist->last->next =
*/
struct attr {
uiAttribute type;
uintptr_t val;
uiAttributeSpec spec;
size_t start;
size_t end;
struct attr *prev;
@ -178,8 +177,7 @@ static struct attr *attrDropRange(struct attrlist *alist, struct attr *a, size_t
// we'll need to split the attribute into two
b = uiNew(struct attr);
b->type = a->type;
b->val = a->val;
b->spec = a->spec;
b->start = end;
b->end = a->end;
*tail = b;
@ -223,8 +221,7 @@ static struct attr *attrSplitAt(struct attrlist *alist, struct attr *a, size_t a
return NULL;
b = uiNew(struct attr);
b->type = a->type;
b->val = a->val;
b->spec = a->spec;
b->start = at;
b->end = a->end;
@ -287,7 +284,24 @@ static struct attr *attrDeleteRange(struct attrlist *alist, struct attr *a, size
return a->next;
}
void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t val, size_t start, size_t end)
static int specsIdentical(struct attr *attr, uiAttributeSpec *spec)
{
if (attr->spec.Type != spec->Type)
return 0;
switch (attr->spec.Type) {
case uiAttributeFamily:
// TODO should we start copying these strings?
return strcmp((char *) (attr->spec.Value), (char *) (spec->Value)) == 0;
case uiAttributeSize:
// TODO use a closest match?
return attr->spec.Double == spec->Double;
// TODO
}
// handles the rest
return attr->spec.Value == spec->Value;
}
void attrlistInsertAttribute(struct attrlist *alist, uiAttributeSpec *spec, size_t start, size_t end)
{
struct attr *a;
struct attr *before;
@ -309,7 +323,7 @@ void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t
goto next;
// should we split this?
if (before->type != type)
if (before->spec.Type != spec->Type)
goto next;
lstart = start;
lend = end;
@ -317,10 +331,8 @@ void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t
goto next;
// okay so this might conflict; if the val is the same as the one we want, we need to expand the existing attribute, not fragment anything
// TODO this might cause problems with system specific attributes, if we support those; maybe also user-specific?
// TODO will this cause problems with fonts?
// TODO will this reduce fragmentation if we first add from 0 to 2 and then from 2 to 4? or do we have to do that separately?
if (before->val == val) {
if (specsIdentical(before, spec)) {
attrGrow(alist, before, start, end);
return;
}
@ -335,8 +347,7 @@ void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t
// if we got here, we know we have to add the attribute before before
a = uiNew(struct attr);
a->type = type;
a->val = val;
a->spec = *spec;
a->start = start;
a->end = end;
attrInsertBefore(alist, a, before);
@ -498,7 +509,7 @@ void attrlistRemoveAttribute(struct attrlist *alist, uiAttribute type, size_t st
// and at this point we're done, so
break;
}
if (a->type != type)
if (a->spec.Type != type)
goto next;
lstart = start;
lend = end;
@ -587,7 +598,7 @@ void attrlistForEach(struct attrlist *alist, uiAttributedString *s, uiAttributed
for (a = alist->first; a != NULL; a = a->next)
// TODO document this
// TODO should this be return 0 to break?
if ((*f)(s, a->type, a->val, a->start, a->end, data))
if ((*f)(s, &(a->spec), a->start, a->end, data))
break;
}

View File

@ -297,9 +297,9 @@ size_t uiAttributedStringGraphemeToByteIndex(uiAttributedString *s, size_t pos)
return pos;
}
void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end)
void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end)
{
attrlistInsertAttribute(s->attrs, type, value, start, end);
attrlistInsertAttribute(s->attrs, spec, start, end);
}
// TODO introduce an iterator?

View File

@ -78,7 +78,7 @@ extern size_t *attrstrCopyUTF16ToUTF8(uiAttributedString *s, size_t *n);
// attrlist.c
struct attrlist;
extern void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t val, size_t start, size_t end);
extern void attrlistInsertAttribute(struct attrlist *alist, uiAttributeSpec *spec, size_t start, size_t end);
extern void attrlistInsertCharactersUnattributed(struct attrlist *alist, size_t start, size_t count);
extern void attrlistInsertCharactersExtendingAttributes(struct attrlist *alist, size_t start, size_t count);
extern void attrlistRemoveAttribute(struct attrlist *alist, uiAttribute type, size_t start, size_t end);

View File

@ -40,41 +40,41 @@ static void adjustFontInRange(struct foreachParams *p, size_t start, size_t end,
}
}
static int processAttribute(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end, void *data)
static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data)
{
struct foreachParams *p = (struct foreachParams *) data;
start = attrstrUTF8ToUTF16(s, start);
end = attrstrUTF8ToUTF16(s, end);
switch (type) {
switch (spec->Type) {
case uiAttributeFamily:
ensureFontInRange(p, start, end);
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
desc->Family = (char *) value;
desc->Family = (char *) (spec->Value);
});
break;
case uiAttributeSize:
ensureFontInRange(p, start, end);
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
desc->Size = *((double *) value);
desc->Size = spec->Double;
});
break;
case uiAttributeWeight:
ensureFontInRange(p, start, end);
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
desc->Weight = (uiDrawTextWeight) value;
desc->Weight = (uiDrawTextWeight) (spec->Value);
});
break;
case uiAttributeItalic:
ensureFontInRange(p, start, end);
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
desc->Italic = (uiDrawTextItalic) value;
desc->Italic = (uiDrawTextItalic) (spec->Value);
});
break;
case uiAttributeStretch:
ensureFontInRange(p, start, end);
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
desc->Stretch = (uiDrawTextStretch) value;
desc->Stretch = (uiDrawTextStretch) (spec->Value);
});
break;
// TODO

View File

@ -5,6 +5,7 @@ static uiAttributedString *attrstr;
static void setupAttributedString(void)
{
uiAttributeSpec spec;
size_t start, end;
const char *next;
@ -14,22 +15,20 @@ static void setupAttributedString(void)
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
uiAttributedStringSetAttribute(attrstr,
uiAttributeFamily,
(uintptr_t) "Courier New",
start, end);
spec.Type = uiAttributeFamily;
spec.Value = (uintptr_t) "Courier New";
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, ", ");
next = "multiple sizes";
static double eighteen = 18;
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
spec.Type = uiAttributeSize;
spec.Double = 18;
uiAttributedStringSetAttribute(attrstr,
uiAttributeSize,
(uintptr_t) (&eighteen),
start, end);
&spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, ", ");
@ -37,10 +36,9 @@ static void setupAttributedString(void)
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
uiAttributedStringSetAttribute(attrstr,
uiAttributeWeight,
(uintptr_t) uiDrawTextWeightBold,
start, end);
spec.Type = uiAttributeWeight;
spec.Value = (uintptr_t) uiDrawTextWeightBold;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, ", ");
@ -48,10 +46,9 @@ static void setupAttributedString(void)
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
uiAttributedStringSetAttribute(attrstr,
uiAttributeItalic,
(uintptr_t) uiDrawTextItalicItalic,
start, end);
spec.Type = uiAttributeItalic;
spec.Value = (uintptr_t) uiDrawTextItalicItalic;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, ", ");
@ -59,10 +56,9 @@ static void setupAttributedString(void)
start = uiAttributedStringLen(attrstr);
end = start + strlen(next);
uiAttributedStringAppendUnattributed(attrstr, next);
uiAttributedStringSetAttribute(attrstr,
uiAttributeStretch,
(uintptr_t) uiDrawTextStretchCondensed,
start, end);
spec.Type = uiAttributeStretch;
spec.Value = (uintptr_t) uiDrawTextStretchCondensed;
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
uiAttributedStringAppendUnattributed(attrstr, ", ");

View File

@ -1,4 +1,5 @@
typedef struct uiAttributedString uiAttributedString;
typedef struct uiAttributeSpec uiAttributeSpec;
_UI_ENUM(uiAttribute) {
// TODO once we allow loading fonts in memory we can't use just one pointer anymore
@ -13,7 +14,13 @@ _UI_ENUM(uiAttribute) {
// TODO uiAttributeCustom,
};
typedef int (*uiAttributedStringForEachAttributeFunc)(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end, void *data);
struct uiAttributeSpec {
uiAttribute Type;
uintptr_t Value;
double Double;
};
typedef int (*uiAttributedStringForEachAttributeFunc)(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data);
// @role uiAttributedString constructor
// uiNewAttributedString() creates a new uiAttributedString from
@ -39,7 +46,7 @@ _UI_EXTERN void uiAttributedStringDelete(uiAttributedString *s, size_t start, si
_UI_EXTERN size_t uiAttributedStringNumGraphemes(uiAttributedString *s);
_UI_EXTERN size_t uiAttributedStringByteIndexToGrapheme(uiAttributedString *s, size_t pos);
_UI_EXTERN size_t uiAttributedStringGraphemeToByteIndex(uiAttributedString *s, size_t pos);
_UI_EXTERN void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end);
_UI_EXTERN void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end);
_UI_EXTERN void uiAttributedStringForEachAttribute(uiAttributedString *s, uiAttributedStringForEachAttributeFunc f, void *data);
typedef struct uiDrawFontDescriptor uiDrawFontDescriptor;