diff --git a/test/page8.c b/test/page8.c index e5d565cf..42c72daf 100644 --- a/test/page8.c +++ b/test/page8.c @@ -35,6 +35,78 @@ static uiCheckbox *textHasUnderline; static uiEntry *textUR, *textUG, *textUB, *textUA; static uiButton *textApply; static uiArea *textArea; +static uiAreaHandler textAreaHandler; + +static double entryDouble(uiEntry *e) +{ + char *s; + double d; + + s = uiEntryText(e); + d = atof(s); + uiFreeText(s); + return d; +} + +static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) +{ + uiDrawTextStyle style; + char *s; + char *family; // make compiler happy + + memset(&style, 0, sizeof (uiDrawTextStyle)); + family = uiEntryText(textFont); + style.Family = family; + style.Size = entryDouble(textSize); + style.Weight = uiComboboxSelected(textWeight); + 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); + s = uiEntryText(textString); + uiDrawText(dp->Context, 10, 10, s, &style); + uiFreeText(s); + uiFreeText(family); +} + +static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) +{ + // do nothing +} + +static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) +{ + // do nothing +} + +static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) +{ + // do nothing +} + +static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) +{ + // do nothing + return 0; +} static void onTextApply(uiButton *b, void *data) { @@ -169,7 +241,13 @@ uiBox *makePage8(void) uiButtonOnClicked(textApply, onTextApply, NULL); uiBoxAppend(vbox, uiControl(textApply), 0); - // TODO + textAreaHandler.Draw = handlerDraw; + textAreaHandler.MouseEvent = handlerMouseEvent; + textAreaHandler.MouseCrossed = handlerMouseCrossed; + textAreaHandler.DragBroken = handlerDragBroken; + textAreaHandler.KeyEvent = handlerKeyEvent; + textArea = uiNewArea(&textAreaHandler); + uiBoxAppend(vbox, uiControl(textArea), 1); return page8; } diff --git a/ui.h b/ui.h index 322315a5..b9943160 100644 --- a/ui.h +++ b/ui.h @@ -496,6 +496,7 @@ typedef enum uiDrawTextStretch { } uiDrawTextStretch; struct uiDrawTextStyle { + // TODO Language attribute const char *Family; double Size; uiDrawTextWeight Weight; @@ -506,10 +507,10 @@ struct uiDrawTextStyle { double TextG; double TextB; double TextA; - int HasBackgroundColor; + int HasBackground; double BackgroundR; double BackgroundG; - double BakcgroundB; + double BackgroundB; double BackgroundA; // TODO Pango int HasStrikethrough; double StrikethroughR; @@ -521,13 +522,14 @@ struct uiDrawTextStyle { double UnderlineG; double UnderlineB; double UnderlineA; // TODO Pango + // 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 *context, double x, double y, const char *text, uiDrawTextStyle *style); +_UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, const char *text, uiDrawTextStyle *style); typedef enum uiModifiers { uiModifierCtrl = 1 << 0, diff --git a/unix/draw.c b/unix/draw.c index 83827694..5d2490b2 100644 --- a/unix/draw.c +++ b/unix/draw.c @@ -482,3 +482,91 @@ void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff) g_free(ff->f); uiFree(ff); } + +double uiDrawTextSizeToPoints(double textSize) +{ + gint pangoSize; + + pangoSize = (gint) (textSize * PANGO_SCALE); + return ((double) pangoSize) / PANGO_SCALE; +} + +double uiDrawPointsToTextSize(double points) +{ + // yeah, as far as I can tell the two functions are equivalent + // TODO verify + // TODO make sure they aren't just equivalent + return uiDrawTextSizeToPoints(points); +} + +static const PangoWeight pangoWeights[] = { + [uiDrawTextWeightThin] = PANGO_WEIGHT_THIN, + [uiDrawTextWeightUltraLight] = PANGO_WEIGHT_ULTRALIGHT, + [uiDrawTextWeightLight] = PANGO_WEIGHT_LIGHT, + [uiDrawTextWeightBook] = PANGO_WEIGHT_BOOK, + [uiDrawTextWeightNormal] = PANGO_WEIGHT_NORMAL, + [uiDrawTextWeightMedium] = PANGO_WEIGHT_MEDIUM, + [uiDrawTextWeightSemiBold] = PANGO_WEIGHT_SEMIBOLD, + [uiDrawTextWeightBold] = PANGO_WEIGHT_BOLD, + [uiDrawTextWeightUtraBold] = PANGO_WEIGHT_ULTRABOLD, + [uiDrawTextWeightHeavy] = PANGO_WEIGHT_HEAVY, + [uiDrawTextWeightUltraHeavy] = PANGO_WEIGHT_ULTRAHEAVY, +}; + +static const PangoStyle pangoItalics[] = { + [uiDrawTextItalicNormal] = PANGO_STYLE_NORMAL, + [uiDrawTextItalicOblique] = PANGO_STYLE_OBLIQUE, + [uiDrawTextItalicItalic] = PANGO_STYLE_ITALIC, +}; + +static const PangoStretch pangoStretches[] = { + [uiDrawTextStretchUltraCondensed] = PANGO_STRETCH_ULTRA_CONDENSED, + [uiDrawTextStretchExtraCondensed] = PANGO_STRETCH_EXTRA_CONDENSED, + [uiDrawTextStretchCondensed] = PANGO_STRETCH_CONDENSED, + [uiDrawTextStretchSemiCondensed] = PANGO_STRETCH_SEMI_CONDENSED, + [uiDrawTextStretchNormal] = PANGO_STRETCH_NORMAL, + [uiDrawTextStretchSemiExpanded] = PANGO_STRETCH_SEMI_EXPANDED, + [uiDrawTextStretchExpanded] = PANGO_STRETCH_EXPANDED, + [uiDrawTextStretchExtraExpanded] = PANGO_STRETCH_EXTRA_EXPANDED, + [uiDrawTextStretchUltraExpanded] = PANGO_STRETCH_ULTRA_EXPANDED, +}; + +void uiDrawText(uiDrawContext *c, double x, double y, const char *text, uiDrawTextStyle *style) +{ + PangoAttrList *attrs; + PangoLayout *layout; + + 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 + } + + 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); + + g_object_unref(layout); + pango_attr_list_unref(attrs); +}