From b5b0fae052ca8cf5e1c1a72b3dec7d2f10e85ed6 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Fri, 10 Feb 2017 16:53:08 -0500 Subject: [PATCH] And implemented uiDrawCaret() on GTK+. --- common/drawtext.c | 6 +++--- common/uipriv.h | 3 ++- examples/drawtext/hittest.c | 6 +++++- ui_attrstr.h | 1 + unix/drawtext.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/common/drawtext.c b/common/drawtext.c index 41aadb2e..4c9dd200 100644 --- a/common/drawtext.c +++ b/common/drawtext.c @@ -10,8 +10,6 @@ void uiDrawCaret(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout, uiDrawPath *path; uiDrawBrush brush; - caretDrawParams(c, &cdp); - xoff = uiDrawTextLayoutByteLocationInLine(layout, pos, *line); if (xoff < 0) { size_t start, end; @@ -33,12 +31,14 @@ void uiDrawCaret(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout, } uiDrawTextLayoutLineGetMetrics(layout, *line, &m); + caretDrawParams(c, m.Height, &cdp); + uiDrawSave(c); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathAddRectangle(path, // TODO add m.X? - x + xoff, y + m.Y, + x + xoff - cdp.xoff, y + m.Y, cdp.width, m.Height); uiDrawPathEnd(path); brush.Type = uiDrawBrushTypeSolid; diff --git a/common/uipriv.h b/common/uipriv.h index 64954c38..73c7eeb0 100644 --- a/common/uipriv.h +++ b/common/uipriv.h @@ -95,9 +95,10 @@ struct caretDrawParams { double g; double b; double a; + double xoff; double width; }; -extern void caretDrawParams(uiDrawContext *c, struct caretDrawParams *p); +extern void caretDrawParams(uiDrawContext *c, double height, struct caretDrawParams *p); #ifdef __cplusplus } diff --git a/examples/drawtext/hittest.c b/examples/drawtext/hittest.c index ab0bc5f5..1d836efa 100644 --- a/examples/drawtext/hittest.c +++ b/examples/drawtext/hittest.c @@ -111,9 +111,9 @@ static void draw(uiAreaDrawParams *p) caretLine = uiDrawTextLayoutNumLines(layout) - 1; caretPos = uiAttributedStringLen(attrstr); } +#if 0 caretX = uiDrawTextLayoutByteLocationInLine(layout, caretPos, caretLine); -printf("%g\n", caretX); uiDrawTextLayoutLineGetMetrics(layout, caretLine, &m); path = uiDrawNewPath(uiDrawFillModeWinding); uiDrawPathNewFigure(path, margins + caretX, margins + m.Y); @@ -126,6 +126,10 @@ printf("%g\n", caretX); brush.A = 1.0; uiDrawStroke(p->Context, path, &brush, &strokeParams); uiDrawFreePath(path); +#else + uiDrawCaret(p->Context, margins, margins, + layout, caretPos, &caretLine); +#endif if (uiCheckboxChecked(showLineBounds)) { int i, n; diff --git a/ui_attrstr.h b/ui_attrstr.h index 6254fb02..052f067d 100644 --- a/ui_attrstr.h +++ b/ui_attrstr.h @@ -163,3 +163,4 @@ _UI_EXTERN void uiDrawTextLayoutHitTest(uiDrawTextLayout *tl, double x, double y _UI_EXTERN double uiDrawTextLayoutByteLocationInLine(uiDrawTextLayout *tl, size_t pos, int line); _UI_EXTERN void uiDrawCaret(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout, size_t pos, int *line); +// TODO allow blinking diff --git a/unix/drawtext.c b/unix/drawtext.c index 49165ae3..175403ad 100644 --- a/unix/drawtext.c +++ b/unix/drawtext.c @@ -244,3 +244,39 @@ double uiDrawTextLayoutByteLocationInLine(uiDrawTextLayout *tl, size_t pos, int // TODO unref pll? return pangoToCairo(pangox); } + +// note: we can't use gtk_render_insertion_cursor() because that doesn't take information about what line to render on +// we'll just recreate what it does +void caretDrawParams(uiDrawContext *c, double height, struct caretDrawParams *p) +{ + GdkColor *color; + GdkRGBA rgba; + gfloat aspectRatio; + gint width, xoff; + + gtk_style_context_get_style(c->style, + "cursor-color", &color, + "cursor-aspect-ratio", &aspectRatio, + NULL); + if (color != NULL) { + p->r = ((double) (color->red)) / 65535.0; + p->g = ((double) (color->green)) / 65535.0; + p->b = ((double) (color->blue)) / 65535.0; + p->a = 1.0; + gdk_color_free(color); + } else { + gtk_style_context_get_color(c->style, GTK_STATE_FLAG_NORMAL, &rgba); + p->r = rgba.red; + p->g = rgba.green; + p->b = rgba.blue; + p->a = rgba.alpha; + } + + // GTK+ itself uses integer arithmetic here; let's do the same + width = height * aspectRatio + 1; + // TODO this is for LTR + xoff = width / 2; + + p->xoff = xoff; + p->width = width; +}