From ca514d94d1c42cca7b2b27bf58ac469bfe0951b6 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Thu, 7 Jan 2016 18:37:43 -0500 Subject: [PATCH] Set up a proper, formal layout and attirbute system. No attributes right now, but initial font style is in. Implemented it on GTK+. --- test/page9.c | 78 +++++++++---------------------------------- ui.h | 29 ++++++++++++++-- unix/draw.c | 94 +++++++++++++++++++++++++++++++--------------------- 3 files changed, 99 insertions(+), 102 deletions(-) diff --git a/test/page9.c b/test/page9.c index a073788d..8dc79325 100644 --- a/test/page9.c +++ b/test/page9.c @@ -8,13 +8,7 @@ static uiCombobox *textWeight; static uiCombobox *textItalic; static uiCheckbox *textSmallCaps; static uiCombobox *textStretch; -static uiEntry *textR, *textG, *textB, *textA; -static uiCheckbox *textHasBackground; -static uiEntry *textBR, *textBG, *textBB, *textBA; -static uiCheckbox *textHasStrikethrough; -static uiEntry *textSR, *textSG, *textSB, *textSA; -static uiCheckbox *textHasUnderline; -static uiEntry *textUR, *textUG, *textUB, *textUA; +static uiCombobox *textGravity; static uiButton *textApply; static uiArea *textArea; static uiAreaHandler textAreaHandler; @@ -32,11 +26,12 @@ static double entryDouble(uiEntry *e) static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) { - uiDrawTextStyle style; + uiDrawInitialTextStyle style; char *s; char *family; // make compiler happy + uiDrawTextLayout *layout; - memset(&style, 0, sizeof (uiDrawTextStyle)); + memset(&style, 0, sizeof (uiDrawInitialTextStyle)); family = uiEntryText(textFont); style.Family = family; style.Size = entryDouble(textSize); @@ -44,27 +39,11 @@ static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) style.Italic = uiComboboxSelected(textItalic); style.SmallCaps = uiCheckboxChecked(textSmallCaps); style.Stretch = uiComboboxSelected(textStretch); - style.TextR = entryDouble(textR); - style.TextG = entryDouble(textG); - style.TextB = entryDouble(textB); - style.TextA = entryDouble(textA); - style.HasBackground = uiCheckboxChecked(textHasBackground); - style.BackgroundR = entryDouble(textBR); - style.BackgroundG = entryDouble(textBG); - style.BackgroundB = entryDouble(textBB); - style.BackgroundA = entryDouble(textBA); - style.HasStrikethrough = uiCheckboxChecked(textHasStrikethrough); - style.StrikethroughR = entryDouble(textSR); - style.StrikethroughG = entryDouble(textSG); - style.StrikethroughB = entryDouble(textSB); - style.StrikethroughA = entryDouble(textSA); - style.HasUnderline = uiCheckboxChecked(textHasUnderline); - style.UnderlineR = entryDouble(textUR); - style.UnderlineG = entryDouble(textUG); - style.UnderlineB = entryDouble(textUB); - style.UnderlineA = entryDouble(textUA); + style.Gravity = uiComboboxSelected(textGravity); s = uiEntryText(textString); - uiDrawText(dp->Context, 10, 10, s, &style); + layout = uiDrawNewTextLayout(s, &style); + uiDrawText(dp->Context, 10, 10, layout); + uiDrawFreeTextLayout(layout); uiFreeText(s); uiFreeText(family); } @@ -95,35 +74,6 @@ static void onTextApply(uiButton *b, void *data) uiAreaQueueRedrawAll(textArea); } -static void mkRGBA(uiBox *parent, uiCheckbox **has, const char *hasText, uiEntry **r, uiEntry **g, uiEntry **b, uiEntry **a, const char *field) -{ - uiBox *hbox; - - hbox = newHorizontalBox(); - uiBoxAppend(parent, uiControl(hbox), 0); - - if (has != NULL) { - *has = uiNewCheckbox(hasText); - uiBoxAppend(hbox, uiControl(*has), 0); - } - - *r = uiNewEntry(); - uiEntrySetText(*r, field); - uiBoxAppend(hbox, uiControl(*r), 1); - - *g = uiNewEntry(); - uiEntrySetText(*g, field); - uiBoxAppend(hbox, uiControl(*g), 1); - - *b = uiNewEntry(); - uiEntrySetText(*b, field); - uiBoxAppend(hbox, uiControl(*b), 1); - - *a = uiNewEntry(); - uiEntrySetText(*a, "1.0"); - uiBoxAppend(hbox, uiControl(*a), 1); -} - uiBox *makePage9(void) { uiBox *page9; @@ -193,10 +143,14 @@ uiBox *makePage9(void) uiComboboxSetSelected(textStretch, uiDrawTextStretchNormal); uiBoxAppend(hbox, uiControl(textStretch), 1); - mkRGBA(vbox, NULL, NULL, &textR, &textG, &textB, &textA, "0.0"); - mkRGBA(vbox, &textHasBackground, "Background", &textBR, &textBG, &textBB, &textBA, "1.0"); - mkRGBA(vbox, &textHasStrikethrough, "Strikethrough", &textSR, &textSG, &textSB, &textSA, "0.0"); - mkRGBA(vbox, &textHasUnderline, "Underline", &textUR, &textUG, &textUB, &textUA, "0.0"); + textGravity = uiNewCombobox(); + uiComboboxAppend(textGravity, "South"); + uiComboboxAppend(textGravity, "East"); + uiComboboxAppend(textGravity, "North"); + uiComboboxAppend(textGravity, "West"); + uiComboboxAppend(textGravity, "Auto"); + uiComboboxSetSelected(textGravity, uiDrawTextGravitySouth); + uiBoxAppend(hbox, uiControl(textGravity), 1); textApply = uiNewButton("Apply"); uiButtonOnClicked(textApply, onTextApply, NULL); diff --git a/ui.h b/ui.h index af92bb89..da2c28af 100644 --- a/ui.h +++ b/ui.h @@ -449,7 +449,8 @@ _UI_EXTERN uintmax_t uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff); _UI_EXTERN char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, uintmax_t n); _UI_EXTERN void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff); -typedef struct uiDrawTextStyle uiDrawTextStyle; +typedef struct uiDrawTextLayout uiDrawTextLayout; +typedef struct uiDrawInitialTextStyle uiDrawInitialTextStyle; typedef enum uiDrawTextWeight { uiDrawTextWeightThin, @@ -484,6 +485,25 @@ typedef enum uiDrawTextStretch { uiDrawTextStretchUltraExpanded, } uiDrawTextStretch; +typedef enum uiDrawTextGravity { + uiDrawTextGravitySouth, + uiDrawTextGravityEast, + uiDrawTextGravityNorth, + uiDrawTextGravityWest, + uiDrawTextGravityAuto, +} uiDrawTextGravity; + +struct uiDrawInitialTextStyle { + const char *Family; + double Size; + uiDrawTextWeight Weight; + uiDrawTextItalic Italic; + int SmallCaps; + uiDrawTextStretch Stretch; + uiDrawTextGravity Gravity; +}; + +/*TODO struct uiDrawTextStyle { const char *Family; double Size; @@ -513,12 +533,15 @@ struct uiDrawTextStyle { const char *Language; // RFC 3066; NULL for default // TODO other Pango attributes }; +*/ _UI_EXTERN double uiDrawTextSizeToPoints(double textSize); _UI_EXTERN double uiDrawPointsToTextSize(double points); -// TODO make this more robust. -_UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, const char *text, uiDrawTextStyle *style); +_UI_EXTERN uiDrawTextLayout *uiDrawNewTextLayout(const char *text, const uiDrawInitialTextStyle *initialTextStyle); +_UI_EXTERN void uiDrawFreeTextLayout(uiDrawTextLayout *layout); + +_UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout); typedef enum uiModifiers { uiModifierCtrl = 1 << 0, diff --git a/unix/draw.c b/unix/draw.c index 006431b0..464689c4 100644 --- a/unix/draw.c +++ b/unix/draw.c @@ -531,45 +531,65 @@ static const PangoStretch pangoStretches[] = { [uiDrawTextStretchUltraExpanded] = PANGO_STRETCH_ULTRA_EXPANDED, }; -void uiDrawText(uiDrawContext *c, double x, double y, const char *text, uiDrawTextStyle *style) +static const PangoGravity pangoGravities[] = { + [uiDrawTextGravitySouth] = PANGO_GRAVITY_SOUTH, + [uiDrawTextGravityEast] = PANGO_GRAVITY_EAST, + [uiDrawTextGravityNorth] = PANGO_GRAVITY_NORTH, + [uiDrawTextGravityWest] = PANGO_GRAVITY_WEST, + [uiDrawTextGravityAuto] = PANGO_GRAVITY_AUTO, +}; + +// note: PangoCairoLayouts are tied to a given cairo_t, so we can't store one in this device-independent structure +struct uiDrawTextLayout { + char *s; + PangoFontDescription *desc; +}; + +uiDrawTextLayout *uiDrawNewTextLayout(const char *text, const uiDrawInitialTextStyle *initialStyle) { - PangoAttrList *attrs; - PangoLayout *layout; + uiDrawTextLayout *layout; + PangoVariant variant; - attrs = pango_attr_list_new(); - pango_attr_list_insert(attrs, - pango_attr_family_new(style->Family)); - pango_attr_list_insert(attrs, - pango_attr_size_new((gint) (style->Size * PANGO_SCALE))); - pango_attr_list_insert(attrs, - pango_attr_weight_new(pangoWeights[style->Weight])); - pango_attr_list_insert(attrs, - pango_attr_style_new(pangoItalics[style->Italic])); - if (style->SmallCaps) - pango_attr_list_insert(attrs, - pango_attr_variant_new(PANGO_VARIANT_SMALL_CAPS)); - pango_attr_list_insert(attrs, - pango_attr_stretch_new(pangoStretches[style->Stretch])); - cairo_set_source_rgba(c->cr, style->TextR, style->TextG, style->TextB, style->TextA); - if (style->HasBackground) { - // TODO - } - if (style->HasStrikethrough) { - // TODO - } - if (style->HasUnderline) { - // TODO - } - if (style->Language != NULL) - pango_attr_list_insert(attrs, - pango_attr_language_new(pango_language_from_string(style->Language))); + layout = uiNew(uiDrawTextLayout); + layout->s = g_strdup(text); - layout = pango_cairo_create_layout(c->cr); - pango_layout_set_text(layout, text, -1); - pango_layout_set_attributes(layout, attrs); - cairo_move_to(c->cr, x, y); - pango_cairo_show_layout(c->cr, layout); + layout->desc = pango_font_description_new(); + pango_font_description_set_family(layout->desc, + initialStyle->Family); + pango_font_description_set_size(layout->desc, + (gint) (initialStyle->Size * PANGO_SCALE)); + pango_font_description_set_weight(layout->desc, + pangoWeights[initialStyle->Weight]); + pango_font_description_set_style(layout->desc, + pangoItalics[initialStyle->Italic]); + variant = PANGO_VARIANT_NORMAL; + if (initialStyle->SmallCaps) + variant = PANGO_VARIANT_SMALL_CAPS; + pango_font_description_set_variant(layout->desc, variant); + pango_font_description_set_stretch(layout->desc, + pangoStretches[initialStyle->Stretch]); + pango_font_description_set_gravity(layout->desc, + pangoGravities[initialStyle->Gravity]); - g_object_unref(layout); - pango_attr_list_unref(attrs); + return layout; +} + +void uiDrawFreeTextLayout(uiDrawTextLayout *layout) +{ + pango_font_description_free(layout->desc); + g_free(layout->s); + uiFree(layout); +} + +void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout) +{ + PangoLayout *pl; + + pl = pango_cairo_create_layout(c->cr); + pango_layout_set_text(pl, layout->s, -1); + // this is safe; the description is copied + pango_layout_set_font_description(pl, layout->desc); + cairo_move_to(c->cr, x, y); + pango_cairo_show_layout(c->cr, pl); + g_object_unref(pl); }