2017-02-24 11:39:29 -06:00
|
|
|
// uiAttributedString represents a string of UTF-8 text that can
|
|
|
|
// optionally be embellished with formatting attributes. libui
|
|
|
|
// provides the list of formatting attributes, which cover common
|
|
|
|
// formatting traits like boldface and color as well as advanced
|
2017-06-06 12:46:54 -05:00
|
|
|
// typographical features provided by OpenType like superscripts
|
|
|
|
// and small caps. These attributes can be combined in a variety of
|
|
|
|
// ways.
|
2017-02-24 11:39:29 -06:00
|
|
|
//
|
|
|
|
// In addition, uiAttributedString provides facilities for moving
|
|
|
|
// between grapheme clusters, which represent a character
|
|
|
|
// from the point of view of the end user. The cursor of a text editor
|
|
|
|
// is always placed on a grapheme boundary, so you can use these
|
|
|
|
// features to move the cursor left or right by one "character".
|
|
|
|
//
|
|
|
|
// uiAttributedString does not provide enough information to be able
|
|
|
|
// to draw itself onto a uiDrawContext or respond to user actions.
|
|
|
|
// In order to do that, you'll need to use a uiDrawTextLayout, which
|
|
|
|
// is built from the combination of a uiAttributedString and a set of
|
|
|
|
// layout-specific properties.
|
2016-12-12 05:45:49 -06:00
|
|
|
typedef struct uiAttributedString uiAttributedString;
|
|
|
|
|
2017-06-07 23:59:17 -05:00
|
|
|
// TODO just make a separate field in uiAttributeSpec for everything? or make attribute objects opaque instead?
|
2016-12-12 05:45:49 -06:00
|
|
|
_UI_ENUM(uiAttribute) {
|
2017-06-07 23:59:17 -05:00
|
|
|
// uiAttributeFamily changes the font family of the text it is
|
|
|
|
// applied to. Use the Family field of uiAttributeSpec.
|
|
|
|
// TODO case-sensitive?
|
|
|
|
uiAttributeFamily,
|
|
|
|
// uiAttributeSize changes the size of the text it is applied to,
|
|
|
|
// in typographical points. Use the Double field of
|
|
|
|
// uiAttributeSpec.
|
|
|
|
uiAttributeSize,
|
|
|
|
// uiAttributeWeight changes the weight of the text it is applied
|
|
|
|
// to. Use the Value field of uiAttributeSpec and the
|
|
|
|
// uiDrawTextWeight constants.
|
2017-01-02 19:11:15 -06:00
|
|
|
uiAttributeWeight,
|
2017-06-07 23:59:17 -05:00
|
|
|
// uiAttributeItalic changes the italicness of the text it is applied
|
|
|
|
// to. Use the Value field of uiAttributeSpec and the
|
|
|
|
// uiDrawTextItalic constants.
|
2017-02-11 22:19:30 -06:00
|
|
|
uiAttributeItalic,
|
2017-06-07 23:59:17 -05:00
|
|
|
// uiAttributeStretch changes the stretch of the text it is applied
|
|
|
|
// to. Use the Value field of uiAttributeSpec and the
|
|
|
|
// uiDrawTextStretch constants.
|
2017-02-11 22:19:30 -06:00
|
|
|
uiAttributeStretch,
|
2017-06-07 23:59:17 -05:00
|
|
|
// uiAttributeColor changes the color of the text it is applied to.
|
|
|
|
// Use the R, G, B, and A fields of uiAttributeSpec.
|
|
|
|
uiAttributeColor,
|
|
|
|
// uiAttributeBackground changes the color of the text it is
|
|
|
|
// applied to. Use the R, G, B, and A fields of uiAttributeSpec.
|
|
|
|
uiAttributeBackground,
|
2017-02-14 01:26:26 -06:00
|
|
|
|
2017-06-07 23:59:17 -05:00
|
|
|
// uiAttributeUnderline changes the underline style of the text
|
|
|
|
// it is applied to. Use the Value field of uiAttributeSpec and the
|
|
|
|
// uiDrawUnderlineStyle constants.
|
|
|
|
uiAttributeUnderline,
|
|
|
|
// uiAttributeUnderlineColor changes the color of any underline
|
|
|
|
// on the text it is applied to, regardless of the style. Use the
|
|
|
|
// Value field of uiAttributeSpec and the uiDrawUnderlineColor
|
|
|
|
// constants (refer to its documentation for more information).
|
|
|
|
//
|
|
|
|
// If an underline style is applied but no underline color is
|
|
|
|
// specified, the text color is used instead.
|
|
|
|
uiAttributeUnderlineColor,
|
2017-02-14 01:53:21 -06:00
|
|
|
|
2017-06-07 23:59:17 -05:00
|
|
|
// uiAttributeFeatures changes the OpenType features of the
|
|
|
|
// text it is applied to. Use the Features field of uiAttributeSpec.
|
2017-05-27 23:19:49 -05:00
|
|
|
uiAttributeFeatures, // use Features
|
2017-05-07 09:30:08 -05:00
|
|
|
};
|
2016-12-12 05:45:49 -06:00
|
|
|
|
2017-02-14 13:21:58 -06:00
|
|
|
_UI_ENUM(uiDrawUnderlineStyle) {
|
|
|
|
uiDrawUnderlineStyleNone,
|
|
|
|
uiDrawUnderlineStyleSingle,
|
|
|
|
uiDrawUnderlineStyleDouble,
|
|
|
|
uiDrawUnderlineStyleSuggestion, // wavy or dotted underlines used for spelling/grammar checkers
|
|
|
|
};
|
|
|
|
|
|
|
|
_UI_ENUM(uiDrawUnderlineColor) {
|
|
|
|
uiDrawUnderlineColorCustom, // also use R/G/B/A fields
|
|
|
|
uiDrawUnderlineColorSpelling,
|
|
|
|
uiDrawUnderlineColorGrammar,
|
|
|
|
uiDrawUnderlineColorAuxiliary, // for instance, the color used by smart replacements on OS X
|
|
|
|
};
|
|
|
|
|
2017-05-07 09:30:08 -05:00
|
|
|
typedef struct uiOpenTypeFeatures uiOpenTypeFeatures;
|
2017-05-11 09:27:34 -05:00
|
|
|
// TODO pass the feature set?
|
2017-06-06 11:47:07 -05:00
|
|
|
typedef uiForEach (*uiOpenTypeFeaturesForEachFunc)(char a, char b, char c, char d, uint32_t value, void *data);
|
2017-05-07 09:30:08 -05:00
|
|
|
_UI_EXTERN uiOpenTypeFeatures *uiNewOpenTypeFeatures(void);
|
|
|
|
_UI_EXTERN void uiFreeOpenTypeFeatures(uiOpenTypeFeatures *otf);
|
2017-05-11 09:27:34 -05:00
|
|
|
// TODO put above Free?
|
|
|
|
// TODO Copy instead of Clone?
|
2017-05-27 23:19:49 -05:00
|
|
|
_UI_EXTERN uiOpenTypeFeatures *uiOpenTypeFeaturesClone(const uiOpenTypeFeatures *otf);
|
2017-05-07 09:30:08 -05:00
|
|
|
_UI_EXTERN void uiOpenTypeFeaturesAdd(uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value);
|
2017-05-11 09:27:34 -05:00
|
|
|
_UI_EXTERN void uiOpenTypeFeaturesRemove(uiOpenTypeFeatures *otf, char a, char b, char c, char d);
|
|
|
|
_UI_EXTERN int uiOpenTypeFeaturesGet(uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t *value);
|
2017-05-30 13:00:58 -05:00
|
|
|
// TODO make other enumerators const (and in general const-correct everything)
|
|
|
|
_UI_EXTERN void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data);
|
2017-05-27 23:41:40 -05:00
|
|
|
_UI_EXTERN int uiOpenTypeFeaturesEqual(const uiOpenTypeFeatures *a, const uiOpenTypeFeatures *b);
|
2017-05-07 09:30:08 -05:00
|
|
|
|
2017-02-24 11:39:29 -06:00
|
|
|
typedef struct uiAttributeSpec uiAttributeSpec;
|
2017-02-14 01:26:26 -06:00
|
|
|
|
2017-06-07 23:59:17 -05:00
|
|
|
// TODO note that pointers are copied
|
|
|
|
// TODO add a function to uiAttributedString to get an attribute's value at a specific index or in a specific range, so we can edit
|
|
|
|
// (TODO related to above: what about memory consumption during a read-modify-write cycle due to copying?)
|
2017-02-12 13:11:25 -06:00
|
|
|
struct uiAttributeSpec {
|
|
|
|
uiAttribute Type;
|
2017-05-27 23:19:49 -05:00
|
|
|
const char *Family;
|
2017-02-12 13:11:25 -06:00
|
|
|
uintptr_t Value;
|
|
|
|
double Double;
|
2017-02-12 19:27:47 -06:00
|
|
|
double R;
|
|
|
|
double G;
|
|
|
|
double B;
|
|
|
|
double A;
|
2017-06-06 13:14:33 -05:00
|
|
|
const uiOpenTypeFeatures *Features;
|
2017-02-12 13:11:25 -06:00
|
|
|
};
|
|
|
|
|
2017-06-06 13:14:33 -05:00
|
|
|
// TODO how would we make spec const in this case, to prevent fields from being modified?
|
2017-06-06 11:47:07 -05:00
|
|
|
typedef uiForEach (*uiAttributedStringForEachAttributeFunc)(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data);
|
2016-12-23 13:01:09 -06:00
|
|
|
|
2016-12-12 05:45:49 -06:00
|
|
|
// @role uiAttributedString constructor
|
|
|
|
// uiNewAttributedString() creates a new uiAttributedString from
|
|
|
|
// initialString. The string will be entirely unattributed.
|
|
|
|
_UI_EXTERN uiAttributedString *uiNewAttributedString(const char *initialString);
|
|
|
|
|
|
|
|
// @role uiAttributedString destructor
|
|
|
|
// uiFreeAttributedString() destroys the uiAttributedString s.
|
|
|
|
_UI_EXTERN void uiFreeAttributedString(uiAttributedString *s);
|
|
|
|
|
|
|
|
// uiAttributedStringString() returns the textual content of s as a
|
|
|
|
// '\0'-terminated UTF-8 string. The returned pointer is valid until
|
|
|
|
// the next change to the textual content of s.
|
|
|
|
_UI_EXTERN const char *uiAttributedStringString(uiAttributedString *s);
|
|
|
|
|
|
|
|
// uiAttributedStringLength() returns the number of UTF-8 bytes in
|
|
|
|
// the textual content of s, excluding the terminating '\0'.
|
|
|
|
_UI_EXTERN size_t uiAttributedStringLen(uiAttributedString *s);
|
|
|
|
|
|
|
|
_UI_EXTERN void uiAttributedStringAppendUnattributed(uiAttributedString *s, const char *str);
|
|
|
|
_UI_EXTERN void uiAttributedStringInsertAtUnattributed(uiAttributedString *s, const char *str, size_t at);
|
|
|
|
_UI_EXTERN void uiAttributedStringDelete(uiAttributedString *s, size_t start, size_t end);
|
|
|
|
_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);
|
2017-02-12 13:11:25 -06:00
|
|
|
_UI_EXTERN void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end);
|
2016-12-23 13:01:09 -06:00
|
|
|
_UI_EXTERN void uiAttributedStringForEachAttribute(uiAttributedString *s, uiAttributedStringForEachAttributeFunc f, void *data);
|
2016-12-23 11:24:20 -06:00
|
|
|
|
2017-01-02 19:11:15 -06:00
|
|
|
typedef struct uiDrawFontDescriptor uiDrawFontDescriptor;
|
|
|
|
|
|
|
|
// TODO Minimum == 1? IIRC there is at least one font on OS X that actually has a weight of 0
|
|
|
|
// TODO Maximum == 999? IIRC there is at least one font on OS X that actually has a weight of 1000
|
|
|
|
_UI_ENUM(uiDrawTextWeight) {
|
|
|
|
uiDrawTextWeightMinimum = 0,
|
|
|
|
uiDrawTextWeightThin = 100,
|
|
|
|
uiDrawTextWeightUltraLight = 200,
|
|
|
|
uiDrawTextWeightLight = 300,
|
|
|
|
uiDrawTextWeightBook = 350,
|
|
|
|
uiDrawTextWeightNormal = 400,
|
|
|
|
uiDrawTextWeightMedium = 500,
|
|
|
|
uiDrawTextWeightSemiBold = 600,
|
|
|
|
uiDrawTextWeightBold = 700,
|
|
|
|
uiDrawTextWeightUltraBold = 800,
|
|
|
|
uiDrawTextWeightHeavy = 900,
|
|
|
|
uiDrawTextWeightUltraHeavy = 950,
|
|
|
|
uiDrawTextWeightMaximum = 1000,
|
|
|
|
};
|
|
|
|
|
|
|
|
_UI_ENUM(uiDrawTextItalic) {
|
|
|
|
uiDrawTextItalicNormal,
|
|
|
|
uiDrawTextItalicOblique,
|
|
|
|
uiDrawTextItalicItalic,
|
|
|
|
};
|
|
|
|
|
|
|
|
_UI_ENUM(uiDrawTextStretch) {
|
|
|
|
uiDrawTextStretchUltraCondensed,
|
|
|
|
uiDrawTextStretchExtraCondensed,
|
|
|
|
uiDrawTextStretchCondensed,
|
|
|
|
uiDrawTextStretchSemiCondensed,
|
|
|
|
uiDrawTextStretchNormal,
|
|
|
|
uiDrawTextStretchSemiExpanded,
|
|
|
|
uiDrawTextStretchExpanded,
|
|
|
|
uiDrawTextStretchExtraExpanded,
|
|
|
|
uiDrawTextStretchUltraExpanded,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct uiDrawFontDescriptor {
|
|
|
|
char *Family;
|
|
|
|
double Size;
|
|
|
|
uiDrawTextWeight Weight;
|
|
|
|
uiDrawTextItalic Italic;
|
|
|
|
uiDrawTextStretch Stretch;
|
|
|
|
};
|
|
|
|
|
2016-12-23 11:24:20 -06:00
|
|
|
typedef struct uiDrawTextLayout uiDrawTextLayout;
|
2017-02-11 16:10:59 -06:00
|
|
|
typedef struct uiDrawTextLayoutParams uiDrawTextLayoutParams;
|
2016-12-23 11:24:20 -06:00
|
|
|
typedef struct uiDrawTextLayoutLineMetrics uiDrawTextLayoutLineMetrics;
|
|
|
|
|
2017-06-06 13:14:33 -05:00
|
|
|
_UI_ENUM(uiDrawTextAlign) {
|
|
|
|
uiDrawTextAlignLeft,
|
|
|
|
uiDrawTextAlignCenter,
|
|
|
|
uiDrawTextAlignRight,
|
2017-02-11 16:10:59 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
struct uiDrawTextLayoutParams {
|
|
|
|
uiAttributedString *String;
|
|
|
|
uiDrawFontDescriptor *DefaultFont;
|
|
|
|
double Width;
|
2017-06-06 13:14:33 -05:00
|
|
|
uiDrawTextAlign Align;
|
2017-02-11 16:10:59 -06:00
|
|
|
};
|
|
|
|
|
2017-02-24 11:26:04 -06:00
|
|
|
// Height will equal ParagraphSpacingBefore + LineHeightSpace + Ascent + Descent + Leading + LineSpacing + ParagraphSpacing.
|
|
|
|
// The above values are listed in vertical order, from top to bottom.
|
|
|
|
// Ascent + Descent + Leading will give you the typographic bounds
|
|
|
|
// of the text. BaselineY is the boundary between Ascent and Descent.
|
|
|
|
// X, Y, and BaselineY are all in the layout's coordinate system, so the
|
|
|
|
// start point of the baseline will be at (X, BaselineY). All values are
|
|
|
|
// nonnegative.
|
2016-12-23 11:24:20 -06:00
|
|
|
struct uiDrawTextLayoutLineMetrics {
|
2017-01-17 01:17:12 -06:00
|
|
|
// This describes the overall bounding box of the line.
|
2016-12-23 11:24:20 -06:00
|
|
|
double X;
|
2017-01-17 01:17:12 -06:00
|
|
|
double Y;
|
2016-12-23 11:24:20 -06:00
|
|
|
double Width;
|
2017-01-17 01:17:12 -06:00
|
|
|
double Height;
|
|
|
|
|
|
|
|
// This describes the typographic bounds of the line.
|
|
|
|
double BaselineY;
|
2016-12-23 11:24:20 -06:00
|
|
|
double Ascent;
|
|
|
|
double Descent;
|
|
|
|
double Leading;
|
2017-01-17 01:17:12 -06:00
|
|
|
|
|
|
|
// This describes any additional whitespace.
|
|
|
|
// TODO come up with better names for these.
|
|
|
|
double ParagraphSpacingBefore;
|
|
|
|
double LineHeightSpace;
|
|
|
|
double LineSpacing;
|
|
|
|
double ParagraphSpacing;
|
|
|
|
|
2017-01-04 22:50:08 -06:00
|
|
|
// TODO trailing whitespace?
|
2016-12-23 11:24:20 -06:00
|
|
|
};
|
|
|
|
|
2017-01-02 19:11:15 -06:00
|
|
|
// TODO
|
|
|
|
// - allow creating a layout out of a substring
|
|
|
|
// - allow marking compositon strings
|
|
|
|
// - allow marking selections, even after creation
|
2017-01-07 19:09:44 -06:00
|
|
|
// - add the following functions:
|
|
|
|
// - uiDrawTextLayoutHeightForWidth() (returns the height that a layout would need to be to display the entire string at a given width)
|
|
|
|
// - uiDrawTextLayoutRangeForSize() (returns what substring would fit in a given size)
|
|
|
|
// - uiDrawTextLayoutNewWithHeight() (limits amount of string used by the height)
|
2017-02-09 18:20:35 -06:00
|
|
|
// - some function to fix up a range (for text editing)
|
2017-02-11 16:10:59 -06:00
|
|
|
_UI_EXTERN uiDrawTextLayout *uiDrawNewTextLayout(uiDrawTextLayoutParams *params);
|
2016-12-23 11:24:20 -06:00
|
|
|
_UI_EXTERN void uiDrawFreeTextLayout(uiDrawTextLayout *tl);
|
|
|
|
_UI_EXTERN void uiDrawText(uiDrawContext *c, uiDrawTextLayout *tl, double x, double y);
|
|
|
|
_UI_EXTERN void uiDrawTextLayoutExtents(uiDrawTextLayout *tl, double *width, double *height);
|
|
|
|
_UI_EXTERN int uiDrawTextLayoutNumLines(uiDrawTextLayout *tl);
|
|
|
|
_UI_EXTERN void uiDrawTextLayoutLineByteRange(uiDrawTextLayout *tl, int line, size_t *start, size_t *end);
|
|
|
|
_UI_EXTERN void uiDrawTextLayoutLineGetMetrics(uiDrawTextLayout *tl, int line, uiDrawTextLayoutLineMetrics *m);
|
|
|
|
// TODO number of lines visible for clipping rect, range visible for clipping rect?
|
2017-02-08 10:38:52 -06:00
|
|
|
|
2017-02-09 18:20:35 -06:00
|
|
|
// TODO rewrite all this documentation
|
|
|
|
|
|
|
|
// uiDrawTextLayoutHitTest() returns the byte offset and line closest
|
|
|
|
// to the given point. The point is relative to the top-left of the layout.
|
|
|
|
// If the point is outside the layout itself, the closest point is chosen;
|
|
|
|
// this allows the function to be used for cursor positioning with the
|
|
|
|
// mouse. Do keep the returned line in mind if used in this way; the
|
|
|
|
// user might click on the end of a line, at which point the cursor
|
|
|
|
// might be at the trailing edge of the last grapheme on the line
|
|
|
|
// (subject to the operating system's APIs).
|
2017-02-08 10:38:52 -06:00
|
|
|
_UI_EXTERN void uiDrawTextLayoutHitTest(uiDrawTextLayout *tl, double x, double y, size_t *pos, int *line);
|
2017-02-09 18:20:35 -06:00
|
|
|
|
|
|
|
// uiDrawTextLayoutByteLocationInLine() returns the point offset
|
|
|
|
// into the given line that the given byte position stands. This is
|
|
|
|
// relative to the line's X position (as returned by
|
|
|
|
// uiDrawTextLayoutLineGetMetrics()), which in turn is relative to
|
|
|
|
// the top-left of the layout. This function can be used for cursor
|
|
|
|
// positioning: if start and end are the start and end of the line
|
|
|
|
// (as returned by uiDrawTextLayoutLineByteRange()), you will get
|
|
|
|
// the correct offset, even if pos is at the end of the line. If pos is not
|
|
|
|
// in the range [start, end], a negative value will be returned,
|
|
|
|
// indicating you need to move the cursor to another line.
|
2017-02-10 09:54:37 -06:00
|
|
|
// TODO make sure this works right for right-aligned and center-aligned lines and justified lines and RTL text
|
2017-02-08 18:00:14 -06:00
|
|
|
_UI_EXTERN double uiDrawTextLayoutByteLocationInLine(uiDrawTextLayout *tl, size_t pos, int line);
|
2017-02-10 15:29:36 -06:00
|
|
|
|
|
|
|
_UI_EXTERN void uiDrawCaret(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout, size_t pos, int *line);
|
2017-02-10 15:53:08 -06:00
|
|
|
// TODO allow blinking
|
2017-06-06 13:14:33 -05:00
|
|
|
// TODO allow secondary carets
|
2017-02-10 23:25:07 -06:00
|
|
|
|
|
|
|
typedef struct uiFontButton uiFontButton;
|
|
|
|
#define uiFontButton(this) ((uiFontButton *) (this))
|
2017-06-06 13:14:33 -05:00
|
|
|
// TODO have a function that sets an entire font descriptor to a range in a uiAttributedString at once, for SetFont?
|
2017-02-10 23:25:07 -06:00
|
|
|
_UI_EXTERN void uiFontButtonFont(uiFontButton *b, uiDrawFontDescriptor *desc);
|
|
|
|
// TOOD SetFont, mechanics
|
|
|
|
_UI_EXTERN void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data);
|
|
|
|
_UI_EXTERN uiFontButton *uiNewFontButton(void);
|