commit: 33486ff0313d73442b776ff375067a4409eb3c42
parent: 27c20fe9bdb147649e701da31a18ce49b8c69459
author: Chris Noxz <chris@noxz.tech>
date: Mon, 19 Sep 2022 10:55:08 +0200
add support for wide glyphs
M | st.h | 6 | + |
M | x.c | 718 | ++++++++++---------- |
2 files changed, 365 insertions(+), 359 deletions(-)
diff --git a/st.h b/st.h
@@ -38,6 +38,12 @@ enum glyph_attribute {
ATTR_DIRTYUNDERLINE = 1 << 15,
};
+enum drawing_mode {
+ DRAW_NONE = 0,
+ DRAW_BG = 1 << 0,
+ DRAW_FG = 1 << 1,
+};
+
enum selection_mode {
SEL_IDLE = 0,
SEL_EMPTY = 1,
diff --git a/x.c b/x.c
@@ -166,7 +166,7 @@ typedef struct {
static inline ushort sixd_to_16bit(int);
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
+static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
static void xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int);
static int xgeommasktogravity(int);
@@ -1460,7 +1460,7 @@ static int getSlope (int x, int iPoint, int waveWidth)
}
void
-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
+xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
{
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
@@ -1551,400 +1551,393 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
if (base.mode & ATTR_INVISIBLE)
fg = bg;
- /* Intelligent cleaning up of the borders. */
- if (x == 0) {
- xclear(0, (y == 0)? 0 : winy, borderpx,
- winy + win.ch +
- ((winy + win.ch >= borderpx + win.th)? win.h : 0));
- }
- if (winx + width >= borderpx + win.tw) {
- xclear(winx + width, (y == 0)? 0 : winy, win.w,
- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
- }
- if (y == 0)
- xclear(winx, 0, winx + width, borderpx);
- if (winy + win.ch >= borderpx + win.th)
- xclear(winx, winy + win.ch, winx + width, win.h);
-
- /* Clean up the region we want to draw to. */
- XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
-
- /* Set the clip region because Xft is sometimes dirty. */
- r.x = 0;
- r.y = 0;
- r.height = win.ch;
- r.width = width;
- XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
-
- if (base.mode & ATTR_BOXDRAW) {
- drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
- } else {
- /* Render the glyphs. */
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
+ if (dmode & DRAW_BG) {
+ /* Intelligent cleaning up of the borders. */
+ if (x == 0) {
+ xclear(0, (y == 0)? 0 : winy, borderpx,
+ winy + win.ch +
+ ((winy + win.ch >= borderpx + win.th)? win.h : 0));
+ }
+ if (winx + width >= borderpx + win.tw) {
+ xclear(winx + width, (y == 0)? 0 : winy, win.w,
+ ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
+ }
+ if (y == 0)
+ xclear(winx, 0, winx + width, borderpx);
+ if (winy + win.ch >= borderpx + win.th)
+ xclear(winx, winy + win.ch, winx + width, win.h);
+ /* Fill the background */
+ XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
}
- /* Render underline and strikethrough. */
- if (base.mode & ATTR_UNDERLINE) {
- // Underline Color
- const int widthThreshold = 28; // +1 width every widthThreshold px of font
- int wlw = (win.ch / widthThreshold) + 1; // Wave Line Width
- int linecolor;
- if ((base.ucolor[0] >= 0) &&
- !(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) &&
- !(base.mode & ATTR_INVISIBLE)
- ) {
- // Special color for underline
- // Index
- if (base.ucolor[1] < 0) {
- linecolor = dc.col[base.ucolor[0]].pixel;
- }
- // RGB
- else {
- XColor lcolor;
- lcolor.red = base.ucolor[0] * 257;
- lcolor.green = base.ucolor[1] * 257;
- lcolor.blue = base.ucolor[2] * 257;
- lcolor.flags = DoRed | DoGreen | DoBlue;
- XAllocColor(xw.dpy, xw.cmap, &lcolor);
- linecolor = lcolor.pixel;
- }
+ if (dmode & DRAW_FG) {
+ if (base.mode & ATTR_BOXDRAW) {
+ drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
} else {
- // Foreground color for underline
- linecolor = fg->pixel;
+ /* Render the glyphs. */
+ XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
}
- XGCValues ugcv = {
- .foreground = linecolor,
- .line_width = wlw,
- .line_style = LineSolid,
- .cap_style = CapNotLast
- };
-
- GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw),
- GCForeground | GCLineWidth | GCLineStyle | GCCapStyle,
- &ugcv);
-
- // Underline Style
- if (base.ustyle != 3) {
- //XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1);
- XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx,
- winy + dc.font.ascent + 1, width, wlw);
- } else if (base.ustyle == 3) {
- int ww = win.cw;//width;
- int wh = dc.font.descent - wlw/2 - 1;//r.height/7;
- int wx = winx;
- int wy = winy + win.ch - dc.font.descent;
-
-#if UNDERCURL_STYLE == UNDERCURL_CURLY
- // Draw waves
- int narcs = charlen * 2 + 1;
- XArc *arcs = xmalloc(sizeof(XArc) * narcs);
-
- int i = 0;
- for (i = 0; i < charlen-1; i++) {
- arcs[i*2] = (XArc) {
- .x = wx + win.cw * i + ww / 4,
- .y = wy,
- .width = win.cw / 2,
- .height = wh,
- .angle1 = 0,
- .angle2 = 180 * 64
- };
- arcs[i*2+1] = (XArc) {
- .x = wx + win.cw * i + ww * 0.75,
- .y = wy,
- .width = win.cw/2,
- .height = wh,
- .angle1 = 180 * 64,
- .angle2 = 180 * 64
- };
+ /* Render underline and strikethrough. */
+ if (base.mode & ATTR_UNDERLINE) {
+ // Underline Color
+ const int widthThreshold = 28; // +1 width every widthThreshold px of font
+ int wlw = (win.ch / widthThreshold) + 1; // Wave Line Width
+ int linecolor;
+ if ((base.ucolor[0] >= 0) &&
+ !(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) &&
+ !(base.mode & ATTR_INVISIBLE)
+ ) {
+ // Special color for underline
+ // Index
+ if (base.ucolor[1] < 0) {
+ linecolor = dc.col[base.ucolor[0]].pixel;
+ }
+ // RGB
+ else {
+ XColor lcolor;
+ lcolor.red = base.ucolor[0] * 257;
+ lcolor.green = base.ucolor[1] * 257;
+ lcolor.blue = base.ucolor[2] * 257;
+ lcolor.flags = DoRed | DoGreen | DoBlue;
+ XAllocColor(xw.dpy, xw.cmap, &lcolor);
+ linecolor = lcolor.pixel;
+ }
+ } else {
+ // Foreground color for underline
+ linecolor = fg->pixel;
}
- // Last wave
- arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh,
- 0, 180 * 64 };
- // Last wave tail
- arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.),
- wh, 180 * 64, 90 * 64};
- // First wave tail
- i++;
- arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64,
- 90 * 64 };
- XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs);
+ XGCValues ugcv = {
+ .foreground = linecolor,
+ .line_width = wlw,
+ .line_style = LineSolid,
+ .cap_style = CapNotLast
+ };
+
+ GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw),
+ GCForeground | GCLineWidth | GCLineStyle | GCCapStyle,
+ &ugcv);
+
+ // Underline Style
+ if (base.ustyle != 3) {
+ //XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1);
+ XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx,
+ winy + dc.font.ascent + 1, width, wlw);
+ } else if (base.ustyle == 3) {
+ int ww = win.cw;//width;
+ int wh = dc.font.descent - wlw/2 - 1;//r.height/7;
+ int wx = winx;
+ int wy = winy + win.ch - dc.font.descent;
- free(arcs);
+#if UNDERCURL_STYLE == UNDERCURL_CURLY
+ // Draw waves
+ int narcs = charlen * 2 + 1;
+ XArc *arcs = xmalloc(sizeof(XArc) * narcs);
+
+ int i = 0;
+ for (i = 0; i < charlen-1; i++) {
+ arcs[i*2] = (XArc) {
+ .x = wx + win.cw * i + ww / 4,
+ .y = wy,
+ .width = win.cw / 2,
+ .height = wh,
+ .angle1 = 0,
+ .angle2 = 180 * 64
+ };
+ arcs[i*2+1] = (XArc) {
+ .x = wx + win.cw * i + ww * 0.75,
+ .y = wy,
+ .width = win.cw/2,
+ .height = wh,
+ .angle1 = 180 * 64,
+ .angle2 = 180 * 64
+ };
+ }
+ // Last wave
+ arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh,
+ 0, 180 * 64 };
+ // Last wave tail
+ arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.),
+ wh, 180 * 64, 90 * 64};
+ // First wave tail
+ i++;
+ arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64,
+ 90 * 64 };
+
+ XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs);
+
+ free(arcs);
#elif UNDERCURL_STYLE == UNDERCURL_SPIKY
- // Make the underline corridor larger
- /*
- wy -= wh;
- */
- wh *= 2;
-
- // Set the angle of the slope to 45°
- ww = wh;
-
- // Position of wave is independent of word, it's absolute
- wx = (wx / (ww/2)) * (ww/2);
-
- int marginStart = winx - wx;
-
- // Calculate number of points with floating precision
- float n = width; // Width of word in pixels
- n = (n / ww) * 2; // Number of slopes (/ or \)
- n += 2; // Add two last points
- int npoints = n; // Convert to int
-
- // Total length of underline
- float waveLength = 0;
-
- if (npoints >= 3) {
- // We add an aditional slot in case we use a bonus point
- XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1));
-
- // First point (Starts with the word bounds)
- points[0] = (XPoint) {
- .x = wx + marginStart,
- .y = (isSlopeRising(wx, 0, ww))
- ? (wy - marginStart + ww/2.f)
- : (wy + marginStart)
- };
-
- // Second point (Goes back to the absolute point coordinates)
- points[1] = (XPoint) {
- .x = (ww/2.f) - marginStart,
- .y = (isSlopeRising(wx, 1, ww))
- ? (ww/2.f - marginStart)
- : (-ww/2.f + marginStart)
- };
- waveLength += (ww/2.f) - marginStart;
-
- // The rest of the points
- for (int i = 2; i < npoints-1; i++) {
- points[i] = (XPoint) {
+ // Make the underline corridor larger
+ /*
+ wy -= wh;
+ */
+ wh *= 2;
+
+ // Set the angle of the slope to 45°
+ ww = wh;
+
+ // Position of wave is independent of word, it's absolute
+ wx = (wx / (ww/2)) * (ww/2);
+
+ int marginStart = winx - wx;
+
+ // Calculate number of points with floating precision
+ float n = width; // Width of word in pixels
+ n = (n / ww) * 2; // Number of slopes (/ or \)
+ n += 2; // Add two last points
+ int npoints = n; // Convert to int
+
+ // Total length of underline
+ float waveLength = 0;
+
+ if (npoints >= 3) {
+ // We add an aditional slot in case we use a bonus point
+ XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1));
+
+ // First point (Starts with the word bounds)
+ points[0] = (XPoint) {
+ .x = wx + marginStart,
+ .y = (isSlopeRising(wx, 0, ww))
+ ? (wy - marginStart + ww/2.f)
+ : (wy + marginStart)
+ };
+
+ // Second point (Goes back to the absolute point coordinates)
+ points[1] = (XPoint) {
+ .x = (ww/2.f) - marginStart,
+ .y = (isSlopeRising(wx, 1, ww))
+ ? (ww/2.f - marginStart)
+ : (-ww/2.f + marginStart)
+ };
+ waveLength += (ww/2.f) - marginStart;
+
+ // The rest of the points
+ for (int i = 2; i < npoints-1; i++) {
+ points[i] = (XPoint) {
+ .x = ww/2,
+ .y = (isSlopeRising(wx, i, ww))
+ ? wh/2
+ : -wh/2
+ };
+ waveLength += ww/2;
+ }
+
+ // Last point
+ points[npoints-1] = (XPoint) {
.x = ww/2,
- .y = (isSlopeRising(wx, i, ww))
+ .y = (isSlopeRising(wx, npoints-1, ww))
? wh/2
: -wh/2
};
waveLength += ww/2;
- }
- // Last point
- points[npoints-1] = (XPoint) {
- .x = ww/2,
- .y = (isSlopeRising(wx, npoints-1, ww))
- ? wh/2
- : -wh/2
- };
- waveLength += ww/2;
-
- // End
- if (waveLength < width) { // Add a bonus point?
- int marginEnd = width - waveLength;
- points[npoints] = (XPoint) {
- .x = marginEnd,
- .y = (isSlopeRising(wx, npoints, ww))
- ? (marginEnd)
- : (-marginEnd)
- };
+ // End
+ if (waveLength < width) { // Add a bonus point?
+ int marginEnd = width - waveLength;
+ points[npoints] = (XPoint) {
+ .x = marginEnd,
+ .y = (isSlopeRising(wx, npoints, ww))
+ ? (marginEnd)
+ : (-marginEnd)
+ };
+
+ npoints++;
+ } else if (waveLength > width) { // Is last point too far?
+ int marginEnd = waveLength - width;
+ points[npoints-1].x -= marginEnd;
+ if (isSlopeRising(wx, npoints-1, ww))
+ points[npoints-1].y -= (marginEnd);
+ else
+ points[npoints-1].y += (marginEnd);
+ }
- npoints++;
- } else if (waveLength > width) { // Is last point too far?
- int marginEnd = waveLength - width;
- points[npoints-1].x -= marginEnd;
- if (isSlopeRising(wx, npoints-1, ww))
- points[npoints-1].y -= (marginEnd);
- else
- points[npoints-1].y += (marginEnd);
- }
+ // Draw the lines
+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints,
+ CoordModePrevious);
- // Draw the lines
- XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints,
- CoordModePrevious);
+ // Draw a second underline with an offset of 1 pixel
+ if ( ((win.ch / (widthThreshold/2)) % 2)) {
+ points[0].x++;
- // Draw a second underline with an offset of 1 pixel
- if ( ((win.ch / (widthThreshold/2)) % 2)) {
- points[0].x++;
+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points,
+ npoints, CoordModePrevious);
+ }
- XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points,
- npoints, CoordModePrevious);
+ // Free resources
+ free(points);
}
-
- // Free resources
- free(points);
- }
#else // UNDERCURL_CAPPED
- // Cap is half of wave width
- float capRatio = 0.5f;
-
- // Make the underline corridor larger
- wh *= 2;
-
- // Set the angle of the slope to 45°
- ww = wh;
- ww *= 1 + capRatio; // Add a bit of width for the cap
-
- // Position of wave is independent of word, it's absolute
- wx = (wx / ww) * ww;
-
- float marginStart;
- switch(getSlope(winx, 0, ww)) {
- case UNDERCURL_SLOPE_ASCENDING:
- marginStart = winx - wx;
- break;
- case UNDERCURL_SLOPE_TOP_CAP:
- marginStart = winx - (wx + (ww * (2.f/6.f)));
- break;
- case UNDERCURL_SLOPE_DESCENDING:
- marginStart = winx - (wx + (ww * (3.f/6.f)));
- break;
- case UNDERCURL_SLOPE_BOTTOM_CAP:
- marginStart = winx - (wx + (ww * (5.f/6.f)));
- break;
- }
+ // Cap is half of wave width
+ float capRatio = 0.5f;
- // Calculate number of points with floating precision
- float n = width; // Width of word in pixels
- // ._.
- n = (n / ww) * 4; // Number of points (./ \.)
- n += 2; // Add two last points
- int npoints = n; // Convert to int
+ // Make the underline corridor larger
+ wh *= 2;
- // Position of the pen to draw the lines
- float penX = 0;
- float penY = 0;
+ // Set the angle of the slope to 45°
+ ww = wh;
+ ww *= 1 + capRatio; // Add a bit of width for the cap
- if (npoints >= 3) {
- XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1));
+ // Position of wave is independent of word, it's absolute
+ wx = (wx / ww) * ww;
- // First point (Starts with the word bounds)
- penX = winx;
- switch (getSlope(winx, 0, ww)) {
+ float marginStart;
+ switch(getSlope(winx, 0, ww)) {
case UNDERCURL_SLOPE_ASCENDING:
- penY = wy + wh/2.f - marginStart;
+ marginStart = winx - wx;
break;
case UNDERCURL_SLOPE_TOP_CAP:
- penY = wy;
+ marginStart = winx - (wx + (ww * (2.f/6.f)));
break;
case UNDERCURL_SLOPE_DESCENDING:
- penY = wy + marginStart;
+ marginStart = winx - (wx + (ww * (3.f/6.f)));
break;
case UNDERCURL_SLOPE_BOTTOM_CAP:
- penY = wy + wh/2.f;
+ marginStart = winx - (wx + (ww * (5.f/6.f)));
break;
}
- points[0].x = penX;
- points[0].y = penY;
- // Second point (Goes back to the absolute point coordinates)
- switch (getSlope(winx, 1, ww)) {
- case UNDERCURL_SLOPE_ASCENDING:
- penX += ww * (1.f/6.f) - marginStart;
- penY += 0;
- break;
- case UNDERCURL_SLOPE_TOP_CAP:
- penX += ww * (2.f/6.f) - marginStart;
- penY += -wh/2.f + marginStart;
- break;
- case UNDERCURL_SLOPE_DESCENDING:
- penX += ww * (1.f/6.f) - marginStart;
- penY += 0;
- break;
- case UNDERCURL_SLOPE_BOTTOM_CAP:
- penX += ww * (2.f/6.f) - marginStart;
- penY += -marginStart + wh/2.f;
- break;
- }
- points[1].x = penX;
- points[1].y = penY;
+ // Calculate number of points with floating precision
+ float n = width; // Width of word in pixels
+ // ._.
+ n = (n / ww) * 4; // Number of points (./ \.)
+ n += 2; // Add two last points
+ int npoints = n; // Convert to int
- // The rest of the points
- for (int i = 2; i < npoints; i++) {
- switch (getSlope(winx, i, ww)) {
+ // Position of the pen to draw the lines
+ float penX = 0;
+ float penY = 0;
+
+ if (npoints >= 3) {
+ XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1));
+
+ // First point (Starts with the word bounds)
+ penX = winx;
+ switch (getSlope(winx, 0, ww)) {
case UNDERCURL_SLOPE_ASCENDING:
- case UNDERCURL_SLOPE_DESCENDING:
- penX += ww * (1.f/6.f);
- penY += 0;
+ penY = wy + wh/2.f - marginStart;
break;
case UNDERCURL_SLOPE_TOP_CAP:
- penX += ww * (2.f/6.f);
- penY += -wh / 2.f;
+ penY = wy;
+ break;
+ case UNDERCURL_SLOPE_DESCENDING:
+ penY = wy + marginStart;
break;
case UNDERCURL_SLOPE_BOTTOM_CAP:
- penX += ww * (2.f/6.f);
- penY += wh / 2.f;
+ penY = wy + wh/2.f;
break;
}
- points[i].x = penX;
- points[i].y = penY;
- }
+ points[0].x = penX;
+ points[0].y = penY;
- // End
- float waveLength = penX - winx;
- if (waveLength < width) { // Add a bonus point?
- int marginEnd = width - waveLength;
- penX += marginEnd;
- switch(getSlope(winx, npoints, ww)) {
+ // Second point (Goes back to the absolute point coordinates)
+ switch (getSlope(winx, 1, ww)) {
case UNDERCURL_SLOPE_ASCENDING:
- case UNDERCURL_SLOPE_DESCENDING:
- //penY += 0;
+ penX += ww * (1.f/6.f) - marginStart;
+ penY += 0;
break;
case UNDERCURL_SLOPE_TOP_CAP:
- penY += -marginEnd;
+ penX += ww * (2.f/6.f) - marginStart;
+ penY += -wh/2.f + marginStart;
+ break;
+ case UNDERCURL_SLOPE_DESCENDING:
+ penX += ww * (1.f/6.f) - marginStart;
+ penY += 0;
break;
case UNDERCURL_SLOPE_BOTTOM_CAP:
- penY += marginEnd;
+ penX += ww * (2.f/6.f) - marginStart;
+ penY += -marginStart + wh/2.f;
break;
}
+ points[1].x = penX;
+ points[1].y = penY;
+
+ // The rest of the points
+ for (int i = 2; i < npoints; i++) {
+ switch (getSlope(winx, i, ww)) {
+ case UNDERCURL_SLOPE_ASCENDING:
+ case UNDERCURL_SLOPE_DESCENDING:
+ penX += ww * (1.f/6.f);
+ penY += 0;
+ break;
+ case UNDERCURL_SLOPE_TOP_CAP:
+ penX += ww * (2.f/6.f);
+ penY += -wh / 2.f;
+ break;
+ case UNDERCURL_SLOPE_BOTTOM_CAP:
+ penX += ww * (2.f/6.f);
+ penY += wh / 2.f;
+ break;
+ }
+ points[i].x = penX;
+ points[i].y = penY;
+ }
- points[npoints].x = penX;
- points[npoints].y = penY;
-
- npoints++;
- } else if (waveLength > width) { // Is last point too far?
- int marginEnd = waveLength - width;
- points[npoints-1].x -= marginEnd;
- switch(getSlope(winx, npoints-1, ww)) {
- case UNDERCURL_SLOPE_TOP_CAP:
- points[npoints-1].y += marginEnd;
- break;
- case UNDERCURL_SLOPE_BOTTOM_CAP:
- points[npoints-1].y -= marginEnd;
- break;
- default:
- break;
+ // End
+ float waveLength = penX - winx;
+ if (waveLength < width) { // Add a bonus point?
+ int marginEnd = width - waveLength;
+ penX += marginEnd;
+ switch(getSlope(winx, npoints, ww)) {
+ case UNDERCURL_SLOPE_ASCENDING:
+ case UNDERCURL_SLOPE_DESCENDING:
+ //penY += 0;
+ break;
+ case UNDERCURL_SLOPE_TOP_CAP:
+ penY += -marginEnd;
+ break;
+ case UNDERCURL_SLOPE_BOTTOM_CAP:
+ penY += marginEnd;
+ break;
+ }
+
+ points[npoints].x = penX;
+ points[npoints].y = penY;
+
+ npoints++;
+ } else if (waveLength > width) { // Is last point too far?
+ int marginEnd = waveLength - width;
+ points[npoints-1].x -= marginEnd;
+ switch(getSlope(winx, npoints-1, ww)) {
+ case UNDERCURL_SLOPE_TOP_CAP:
+ points[npoints-1].y += marginEnd;
+ break;
+ case UNDERCURL_SLOPE_BOTTOM_CAP:
+ points[npoints-1].y -= marginEnd;
+ break;
+ default:
+ break;
+ }
}
- }
- // Draw the lines
- XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints,
- CoordModeOrigin);
+ // Draw the lines
+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints,
+ CoordModeOrigin);
- // Draw a second underline with an offset of 1 pixel
- if ( ((win.ch / (widthThreshold/2)) % 2)) {
- for (int i = 0; i < npoints; i++)
- points[i].x++;
+ // Draw a second underline with an offset of 1 pixel
+ if ( ((win.ch / (widthThreshold/2)) % 2)) {
+ for (int i = 0; i < npoints; i++)
+ points[i].x++;
- XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points,
- npoints, CoordModeOrigin);
- }
+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points,
+ npoints, CoordModeOrigin);
+ }
- // Free resources
- free(points);
- }
+ // Free resources
+ free(points);
+ }
#endif
- }
+ }
- XFreeGC(xw.dpy, ugc);
- }
+ XFreeGC(xw.dpy, ugc);
+ }
- if (base.mode & ATTR_STRUCK) {
- XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3,
- width, 1);
+ if (base.mode & ATTR_STRUCK) {
+ XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3,
+ width, 1);
+ }
}
-
- /* Reset clip to none. */
- XftDrawSetClip(xw.draw, 0);
}
void
@@ -1954,7 +1947,7 @@ xdrawglyph(Glyph g, int x, int y)
XftGlyphFontSpec spec;
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
- xdrawglyphfontspecs(&spec, g, numspecs, x, y);
+ xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
}
void
@@ -2074,32 +2067,39 @@ xstartdraw(void)
void
xdrawline(Line line, int x1, int y1, int x2)
{
- int i, x, ox, numspecs;
+ int i, x, ox, numspecs, numspecs_cached;
Glyph base, new;
- XftGlyphFontSpec *specs = xw.specbuf;
-
- numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
- i = ox = 0;
- for (x = x1; x < x2 && i < numspecs; x++) {
- new = line[x];
- if (new.mode == ATTR_WDUMMY)
- continue;
- if (selected(x, y1))
- new.mode ^= ATTR_REVERSE;
- if (i > 0 && ATTRCMP(base, new)) {
- xdrawglyphfontspecs(specs, base, i, ox, y1);
- specs += i;
- numspecs -= i;
- i = 0;
- }
- if (i == 0) {
- ox = x;
- base = new;
+ XftGlyphFontSpec *specs;
+
+ numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
+
+ /* Draw line in 2 passes: background and foreground. This way wide glyphs
+ won't get truncated (#223) */
+ for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
+ specs = xw.specbuf;
+ numspecs = numspecs_cached;
+ i = ox = 0;
+ for (x = x1; x < x2 && i < numspecs; x++) {
+ new = line[x];
+ if (new.mode == ATTR_WDUMMY)
+ continue;
+ if (selected(x, y1))
+ new.mode ^= ATTR_REVERSE;
+ if (i > 0 && ATTRCMP(base, new)) {
+ xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
+ specs += i;
+ numspecs -= i;
+ i = 0;
+ }
+ if (i == 0) {
+ ox = x;
+ base = new;
+ }
+ i++;
}
- i++;
+ if (i > 0)
+ xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
}
- if (i > 0)
- xdrawglyphfontspecs(specs, base, i, ox, y1);
}
void