| st-undercurl-0.8.4-20210822.diff - sites - public wiki contents of suckless.org | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| Refs | |
| --- | |
| st-undercurl-0.8.4-20210822.diff (16126B) | |
| --- | |
| 1 diff --git a/config.def.h b/config.def.h | |
| 2 index 6f05dce..7ae1b92 100644 | |
| 3 --- a/config.def.h | |
| 4 +++ b/config.def.h | |
| 5 @@ -470,3 +470,27 @@ static char ascii_printable[] = | |
| 6 " !\"#$%&'()*+,-./0123456789:;<=>?" | |
| 7 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" | |
| 8 "`abcdefghijklmnopqrstuvwxyz{|}~"; | |
| 9 + | |
| 10 +/** | |
| 11 + * Undercurl style. Set UNDERCURL_STYLE to one of the available styles. | |
| 12 + * | |
| 13 + * Curly: Dunno how to draw it *shrug* | |
| 14 + * _ _ _ _ | |
| 15 + * ( ) ( ) ( ) ( ) | |
| 16 + * (_) (_) (_) (_) | |
| 17 + * | |
| 18 + * Spiky: | |
| 19 + * /\ /\ /\ /\ | |
| 20 + * \/ \/ \/ | |
| 21 + * | |
| 22 + * Capped: | |
| 23 + * _ _ _ | |
| 24 + * / \ / \ / \ | |
| 25 + * \_/ \_/ | |
| 26 + */ | |
| 27 +// Available styles | |
| 28 +#define UNDERCURL_CURLY 0 | |
| 29 +#define UNDERCURL_SPIKY 1 | |
| 30 +#define UNDERCURL_CAPPED 2 | |
| 31 +// Active style | |
| 32 +#define UNDERCURL_STYLE UNDERCURL_SPIKY | |
| 33 diff --git a/st.c b/st.c | |
| 34 index 76b7e0d..542ab3a 100644 | |
| 35 --- a/st.c | |
| 36 +++ b/st.c | |
| 37 @@ -33,6 +33,7 @@ | |
| 38 #define UTF_SIZ 4 | |
| 39 #define ESC_BUF_SIZ (128*UTF_SIZ) | |
| 40 #define ESC_ARG_SIZ 16 | |
| 41 +#define CAR_PER_ARG 4 | |
| 42 #define STR_BUF_SIZ ESC_BUF_SIZ | |
| 43 #define STR_ARG_SIZ ESC_ARG_SIZ | |
| 44 | |
| 45 @@ -139,6 +140,7 @@ typedef struct { | |
| 46 int arg[ESC_ARG_SIZ]; | |
| 47 int narg; /* nb of args */ | |
| 48 char mode[2]; | |
| 49 + int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */ | |
| 50 } CSIEscape; | |
| 51 | |
| 52 /* STR Escape sequence structs */ | |
| 53 @@ -159,6 +161,7 @@ static void ttywriteraw(const char *, size_t); | |
| 54 | |
| 55 static void csidump(void); | |
| 56 static void csihandle(void); | |
| 57 +static void readcolonargs(char **, int, int[][CAR_PER_ARG]); | |
| 58 static void csiparse(void); | |
| 59 static void csireset(void); | |
| 60 static int eschandle(uchar); | |
| 61 @@ -1131,6 +1134,28 @@ tnewline(int first_col) | |
| 62 tmoveto(first_col ? 0 : term.c.x, y); | |
| 63 } | |
| 64 | |
| 65 +void | |
| 66 +readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG]) | |
| 67 +{ | |
| 68 + int i = 0; | |
| 69 + for (; i < CAR_PER_ARG; i++) | |
| 70 + params[cursor][i] = -1; | |
| 71 + | |
| 72 + if (**p != ':') | |
| 73 + return; | |
| 74 + | |
| 75 + char *np = NULL; | |
| 76 + i = 0; | |
| 77 + | |
| 78 + while (**p == ':' && i < CAR_PER_ARG) { | |
| 79 + while (**p == ':') | |
| 80 + (*p)++; | |
| 81 + params[cursor][i] = strtol(*p, &np, 10); | |
| 82 + *p = np; | |
| 83 + i++; | |
| 84 + } | |
| 85 +} | |
| 86 + | |
| 87 void | |
| 88 csiparse(void) | |
| 89 { | |
| 90 @@ -1153,6 +1178,7 @@ csiparse(void) | |
| 91 v = -1; | |
| 92 csiescseq.arg[csiescseq.narg++] = v; | |
| 93 p = np; | |
| 94 + readcolonargs(&p, csiescseq.narg-1, csiescseq.carg); | |
| 95 if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) | |
| 96 break; | |
| 97 p++; | |
| 98 @@ -1369,6 +1395,10 @@ tsetattr(int *attr, int l) | |
| 99 ATTR_STRUCK ); | |
| 100 term.c.attr.fg = defaultfg; | |
| 101 term.c.attr.bg = defaultbg; | |
| 102 + term.c.attr.ustyle = -1; | |
| 103 + term.c.attr.ucolor[0] = -1; | |
| 104 + term.c.attr.ucolor[1] = -1; | |
| 105 + term.c.attr.ucolor[2] = -1; | |
| 106 break; | |
| 107 case 1: | |
| 108 term.c.attr.mode |= ATTR_BOLD; | |
| 109 @@ -1380,7 +1410,14 @@ tsetattr(int *attr, int l) | |
| 110 term.c.attr.mode |= ATTR_ITALIC; | |
| 111 break; | |
| 112 case 4: | |
| 113 - term.c.attr.mode |= ATTR_UNDERLINE; | |
| 114 + term.c.attr.ustyle = csiescseq.carg[i][0]; | |
| 115 + | |
| 116 + if (term.c.attr.ustyle != 0) | |
| 117 + term.c.attr.mode |= ATTR_UNDERLINE; | |
| 118 + else | |
| 119 + term.c.attr.mode &= ~ATTR_UNDERLINE; | |
| 120 + | |
| 121 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; | |
| 122 break; | |
| 123 case 5: /* slow blink */ | |
| 124 /* FALLTHROUGH */ | |
| 125 @@ -1431,6 +1468,18 @@ tsetattr(int *attr, int l) | |
| 126 case 49: | |
| 127 term.c.attr.bg = defaultbg; | |
| 128 break; | |
| 129 + case 58: | |
| 130 + term.c.attr.ucolor[0] = csiescseq.carg[i][1]; | |
| 131 + term.c.attr.ucolor[1] = csiescseq.carg[i][2]; | |
| 132 + term.c.attr.ucolor[2] = csiescseq.carg[i][3]; | |
| 133 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; | |
| 134 + break; | |
| 135 + case 59: | |
| 136 + term.c.attr.ucolor[0] = -1; | |
| 137 + term.c.attr.ucolor[1] = -1; | |
| 138 + term.c.attr.ucolor[2] = -1; | |
| 139 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; | |
| 140 + break; | |
| 141 default: | |
| 142 if (BETWEEN(attr[i], 30, 37)) { | |
| 143 term.c.attr.fg = attr[i] - 30; | |
| 144 diff --git a/st.h b/st.h | |
| 145 index 3d351b6..95bdcbd 100644 | |
| 146 --- a/st.h | |
| 147 +++ b/st.h | |
| 148 @@ -34,6 +34,7 @@ enum glyph_attribute { | |
| 149 ATTR_WIDE = 1 << 9, | |
| 150 ATTR_WDUMMY = 1 << 10, | |
| 151 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, | |
| 152 + ATTR_DIRTYUNDERLINE = 1 << 15, | |
| 153 }; | |
| 154 | |
| 155 enum selection_mode { | |
| 156 @@ -65,6 +66,8 @@ typedef struct { | |
| 157 ushort mode; /* attribute flags */ | |
| 158 uint32_t fg; /* foreground */ | |
| 159 uint32_t bg; /* background */ | |
| 160 + int ustyle; /* underline style */ | |
| 161 + int ucolor[3]; /* underline color */ | |
| 162 } Glyph; | |
| 163 | |
| 164 typedef Glyph *Line; | |
| 165 diff --git a/st.info b/st.info | |
| 166 index 8201ad6..659878c 100644 | |
| 167 --- a/st.info | |
| 168 +++ b/st.info | |
| 169 @@ -1,4 +1,5 @@ | |
| 170 st-mono| simpleterm monocolor, | |
| 171 + Su, | |
| 172 acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{… | |
| 173 am, | |
| 174 bce, | |
| 175 diff --git a/x.c b/x.c | |
| 176 index 210f184..3a0e79e 100644 | |
| 177 --- a/x.c | |
| 178 +++ b/x.c | |
| 179 @@ -45,6 +45,14 @@ typedef struct { | |
| 180 signed char appcursor; /* application cursor */ | |
| 181 } Key; | |
| 182 | |
| 183 +/* Undercurl slope types */ | |
| 184 +enum undercurl_slope_type { | |
| 185 + UNDERCURL_SLOPE_ASCENDING = 0, | |
| 186 + UNDERCURL_SLOPE_TOP_CAP = 1, | |
| 187 + UNDERCURL_SLOPE_DESCENDING = 2, | |
| 188 + UNDERCURL_SLOPE_BOTTOM_CAP = 3 | |
| 189 +}; | |
| 190 + | |
| 191 /* X modifiers */ | |
| 192 #define XK_ANY_MOD UINT_MAX | |
| 193 #define XK_NO_MOD 0 | |
| 194 @@ -1339,6 +1347,51 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, cons… | |
| 195 return numspecs; | |
| 196 } | |
| 197 | |
| 198 +static int isSlopeRising (int x, int iPoint, int waveWidth) | |
| 199 +{ | |
| 200 + // . . . . | |
| 201 + // / \ / \ / \ / \ | |
| 202 + // / \ / \ / \ / \ | |
| 203 + // . . . . . | |
| 204 + | |
| 205 + // Find absolute `x` of point | |
| 206 + x += iPoint * (waveWidth/2); | |
| 207 + | |
| 208 + // Find index of absolute wave | |
| 209 + int absSlope = x / ((float)waveWidth/2); | |
| 210 + | |
| 211 + return (absSlope % 2); | |
| 212 +} | |
| 213 + | |
| 214 +static int getSlope (int x, int iPoint, int waveWidth) | |
| 215 +{ | |
| 216 + // Sizes: Caps are half width of slopes | |
| 217 + // 1_2 1_2 1_2 1_2 | |
| 218 + // / \ / \ / \ / \ | |
| 219 + // / \ / \ / \ / \ | |
| 220 + // 0 3_0 3_0 3_0 3_ | |
| 221 + // <2-> <1> <---6----> | |
| 222 + | |
| 223 + // Find type of first point | |
| 224 + int firstType; | |
| 225 + x -= (x / waveWidth) * waveWidth; | |
| 226 + if (x < (waveWidth * (2.f/6.f))) | |
| 227 + firstType = UNDERCURL_SLOPE_ASCENDING; | |
| 228 + else if (x < (waveWidth * (3.f/6.f))) | |
| 229 + firstType = UNDERCURL_SLOPE_TOP_CAP; | |
| 230 + else if (x < (waveWidth * (5.f/6.f))) | |
| 231 + firstType = UNDERCURL_SLOPE_DESCENDING; | |
| 232 + else | |
| 233 + firstType = UNDERCURL_SLOPE_BOTTOM_CAP; | |
| 234 + | |
| 235 + // Find type of given point | |
| 236 + int pointType = (iPoint % 4); | |
| 237 + pointType += firstType; | |
| 238 + pointType %= 4; | |
| 239 + | |
| 240 + return pointType; | |
| 241 +} | |
| 242 + | |
| 243 void | |
| 244 xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,… | |
| 245 { | |
| 246 @@ -1461,8 +1514,357 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *spec… | |
| 247 | |
| 248 /* Render underline and strikethrough. */ | |
| 249 if (base.mode & ATTR_UNDERLINE) { | |
| 250 - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + … | |
| 251 - width, 1); | |
| 252 + // Underline Color | |
| 253 + const int widthThreshold = 28; // +1 width every width… | |
| 254 + int wlw = (win.ch / widthThreshold) + 1; // Wave Line W… | |
| 255 + int linecolor; | |
| 256 + if ((base.ucolor[0] >= 0) && | |
| 257 + !(base.mode & ATTR_BLINK && win.mode & MODE_BLI… | |
| 258 + !(base.mode & ATTR_INVISIBLE) | |
| 259 + ) { | |
| 260 + // Special color for underline | |
| 261 + // Index | |
| 262 + if (base.ucolor[1] < 0) { | |
| 263 + linecolor = dc.col[base.ucolor[0]].pixe… | |
| 264 + } | |
| 265 + // RGB | |
| 266 + else { | |
| 267 + XColor lcolor; | |
| 268 + lcolor.red = base.ucolor[0] * 257; | |
| 269 + lcolor.green = base.ucolor[1] * 257; | |
| 270 + lcolor.blue = base.ucolor[2] * 257; | |
| 271 + lcolor.flags = DoRed | DoGreen | DoBlue; | |
| 272 + XAllocColor(xw.dpy, xw.cmap, &lcolor); | |
| 273 + linecolor = lcolor.pixel; | |
| 274 + } | |
| 275 + } else { | |
| 276 + // Foreground color for underline | |
| 277 + linecolor = fg->pixel; | |
| 278 + } | |
| 279 + | |
| 280 + XGCValues ugcv = { | |
| 281 + .foreground = linecolor, | |
| 282 + .line_width = wlw, | |
| 283 + .line_style = LineSolid, | |
| 284 + .cap_style = CapNotLast | |
| 285 + }; | |
| 286 + | |
| 287 + GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw), | |
| 288 + GCForeground | GCLineWidth | GCLineStyle | GCCa… | |
| 289 + &ugcv); | |
| 290 + | |
| 291 + // Underline Style | |
| 292 + if (base.ustyle != 3) { | |
| 293 + //XftDrawRect(xw.draw, fg, winx, winy + dc.font… | |
| 294 + XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw)… | |
| 295 + winy + dc.font.ascent + 1, width, wlw); | |
| 296 + } else if (base.ustyle == 3) { | |
| 297 + int ww = win.cw;//width; | |
| 298 + int wh = dc.font.descent - wlw/2 - 1;//r.height… | |
| 299 + int wx = winx; | |
| 300 + int wy = winy + win.ch - dc.font.descent; | |
| 301 + | |
| 302 +#if UNDERCURL_STYLE == UNDERCURL_CURLY | |
| 303 + // Draw waves | |
| 304 + int narcs = charlen * 2 + 1; | |
| 305 + XArc *arcs = xmalloc(sizeof(XArc) * narcs); | |
| 306 + | |
| 307 + int i = 0; | |
| 308 + for (i = 0; i < charlen-1; i++) { | |
| 309 + arcs[i*2] = (XArc) { | |
| 310 + .x = wx + win.cw * i + ww / 4, | |
| 311 + .y = wy, | |
| 312 + .width = win.cw / 2, | |
| 313 + .height = wh, | |
| 314 + .angle1 = 0, | |
| 315 + .angle2 = 180 * 64 | |
| 316 + }; | |
| 317 + arcs[i*2+1] = (XArc) { | |
| 318 + .x = wx + win.cw * i + ww * 0.7… | |
| 319 + .y = wy, | |
| 320 + .width = win.cw/2, | |
| 321 + .height = wh, | |
| 322 + .angle1 = 180 * 64, | |
| 323 + .angle2 = 180 * 64 | |
| 324 + }; | |
| 325 + } | |
| 326 + // Last wave | |
| 327 + arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, w… | |
| 328 + 0, 180 * 64 }; | |
| 329 + // Last wave tail | |
| 330 + arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, … | |
| 331 + wh, 180 * 64, 90 * 64}; | |
| 332 + // First wave tail | |
| 333 + i++; | |
| 334 + arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww … | |
| 335 + 90 * 64 }; | |
| 336 + | |
| 337 + XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc… | |
| 338 + | |
| 339 + free(arcs); | |
| 340 +#elif UNDERCURL_STYLE == UNDERCURL_SPIKY | |
| 341 + // Make the underline corridor larger | |
| 342 + /* | |
| 343 + wy -= wh; | |
| 344 + */ | |
| 345 + wh *= 2; | |
| 346 + | |
| 347 + // Set the angle of the slope to 45° | |
| 348 + ww = wh; | |
| 349 + | |
| 350 + // Position of wave is independent of word, it'… | |
| 351 + wx = (wx / (ww/2)) * (ww/2); | |
| 352 + | |
| 353 + int marginStart = winx - wx; | |
| 354 + | |
| 355 + // Calculate number of points with floating pre… | |
| 356 + float n = width; … | |
| 357 + n = (n / ww) * 2; … | |
| 358 + n += 2; … | |
| 359 + int npoints = n; … | |
| 360 + | |
| 361 + // Total length of underline | |
| 362 + float waveLength = 0; | |
| 363 + | |
| 364 + if (npoints >= 3) { | |
| 365 + // We add an aditional slot in case we … | |
| 366 + XPoint *points = xmalloc(sizeof(XPoint)… | |
| 367 + | |
| 368 + // First point (Starts with the word bo… | |
| 369 + points[0] = (XPoint) { | |
| 370 + .x = wx + marginStart, | |
| 371 + .y = (isSlopeRising(wx, 0, ww)) | |
| 372 + ? (wy - marginStart + w… | |
| 373 + : (wy + marginStart) | |
| 374 + }; | |
| 375 + | |
| 376 + // Second point (Goes back to the absol… | |
| 377 + points[1] = (XPoint) { | |
| 378 + .x = (ww/2.f) - marginStart, | |
| 379 + .y = (isSlopeRising(wx, 1, ww)) | |
| 380 + ? (ww/2.f - marginStart) | |
| 381 + : (-ww/2.f + marginStar… | |
| 382 + }; | |
| 383 + waveLength += (ww/2.f) - marginStart; | |
| 384 + | |
| 385 + // The rest of the points | |
| 386 + for (int i = 2; i < npoints-1; i++) { | |
| 387 + points[i] = (XPoint) { | |
| 388 + .x = ww/2, | |
| 389 + .y = (isSlopeRising(wx,… | |
| 390 + ? wh/2 | |
| 391 + : -wh/2 | |
| 392 + }; | |
| 393 + waveLength += ww/2; | |
| 394 + } | |
| 395 + | |
| 396 + // Last point | |
| 397 + points[npoints-1] = (XPoint) { | |
| 398 + .x = ww/2, | |
| 399 + .y = (isSlopeRising(wx, npoints… | |
| 400 + ? wh/2 | |
| 401 + : -wh/2 | |
| 402 + }; | |
| 403 + waveLength += ww/2; | |
| 404 + | |
| 405 + // End | |
| 406 + if (waveLength < width) { // Add a bonu… | |
| 407 + int marginEnd = width - waveLen… | |
| 408 + points[npoints] = (XPoint) { | |
| 409 + .x = marginEnd, | |
| 410 + .y = (isSlopeRising(wx,… | |
| 411 + ? (marginEnd) | |
| 412 + : (-marginEnd) | |
| 413 + }; | |
| 414 + | |
| 415 + npoints++; | |
| 416 + } else if (waveLength > width) { // Is … | |
| 417 + int marginEnd = waveLength - wi… | |
| 418 + points[npoints-1].x -= marginEn… | |
| 419 + if (isSlopeRising(wx, npoints-1… | |
| 420 + points[npoints-1].y -= … | |
| 421 + else | |
| 422 + points[npoints-1].y += … | |
| 423 + } | |
| 424 + | |
| 425 + // Draw the lines | |
| 426 + XDrawLines(xw.dpy, XftDrawDrawable(xw.d… | |
| 427 + CoordModePrevious); | |
| 428 + | |
| 429 + // Draw a second underline with an offs… | |
| 430 + if ( ((win.ch / (widthThreshold/2)) % 2… | |
| 431 + points[0].x++; | |
| 432 + | |
| 433 + XDrawLines(xw.dpy, XftDrawDrawa… | |
| 434 + npoints, CoordM… | |
| 435 + } | |
| 436 + | |
| 437 + // Free resources | |
| 438 + free(points); | |
| 439 + } | |
| 440 +#else // UNDERCURL_CAPPED | |
| 441 + // Cap is half of wave width | |
| 442 + float capRatio = 0.5f; | |
| 443 + | |
| 444 + // Make the underline corridor larger | |
| 445 + wh *= 2; | |
| 446 + | |
| 447 + // Set the angle of the slope to 45° | |
| 448 + ww = wh; | |
| 449 + ww *= 1 + capRatio; // Add a bit of width for t… | |
| 450 + | |
| 451 + // Position of wave is independent of word, it'… | |
| 452 + wx = (wx / ww) * ww; | |
| 453 + | |
| 454 + float marginStart; | |
| 455 + switch(getSlope(winx, 0, ww)) { | |
| 456 + case UNDERCURL_SLOPE_ASCENDING: | |
| 457 + marginStart = winx - wx; | |
| 458 + break; | |
| 459 + case UNDERCURL_SLOPE_TOP_CAP: | |
| 460 + marginStart = winx - (wx + (ww … | |
| 461 + break; | |
| 462 + case UNDERCURL_SLOPE_DESCENDING: | |
| 463 + marginStart = winx - (wx + (ww … | |
| 464 + break; | |
| 465 + case UNDERCURL_SLOPE_BOTTOM_CAP: | |
| 466 + marginStart = winx - (wx + (ww … | |
| 467 + break; | |
| 468 + } | |
| 469 + | |
| 470 + // Calculate number of points with floating pre… | |
| 471 + float n = width; … | |
| 472 + … | |
| 473 + n = (n / ww) * 4; … | |
| 474 + n += 2; … | |
| 475 + int npoints = n; … | |
| 476 + | |
| 477 + // Position of the pen to draw the lines | |
| 478 + float penX = 0; | |
| 479 + float penY = 0; | |
| 480 + | |
| 481 + if (npoints >= 3) { | |
| 482 + XPoint *points = xmalloc(sizeof(XPoint)… | |
| 483 + | |
| 484 + // First point (Starts with the word bo… | |
| 485 + penX = winx; | |
| 486 + switch (getSlope(winx, 0, ww)) { | |
| 487 + case UNDERCURL_SLOPE_ASCENDING: | |
| 488 + penY = wy + wh/2.f - ma… | |
| 489 + break; | |
| 490 + case UNDERCURL_SLOPE_TOP_CAP: | |
| 491 + penY = wy; | |
| 492 + break; | |
| 493 + case UNDERCURL_SLOPE_DESCENDING: | |
| 494 + penY = wy + marginStart; | |
| 495 + break; | |
| 496 + case UNDERCURL_SLOPE_BOTTOM_CAP: | |
| 497 + penY = wy + wh/2.f; | |
| 498 + break; | |
| 499 + } | |
| 500 + points[0].x = penX; | |
| 501 + points[0].y = penY; | |
| 502 + | |
| 503 + // Second point (Goes back to the absol… | |
| 504 + switch (getSlope(winx, 1, ww)) { | |
| 505 + case UNDERCURL_SLOPE_ASCENDING: | |
| 506 + penX += ww * (1.f/6.f) … | |
| 507 + penY += 0; | |
| 508 + break; | |
| 509 + case UNDERCURL_SLOPE_TOP_CAP: | |
| 510 + penX += ww * (2.f/6.f) … | |
| 511 + penY += -wh/2.f + margi… | |
| 512 + break; | |
| 513 + case UNDERCURL_SLOPE_DESCENDING: | |
| 514 + penX += ww * (1.f/6.f) … | |
| 515 + penY += 0; | |
| 516 + break; | |
| 517 + case UNDERCURL_SLOPE_BOTTOM_CAP: | |
| 518 + penX += ww * (2.f/6.f) … | |
| 519 + penY += -marginStart + … | |
| 520 + break; | |
| 521 + } | |
| 522 + points[1].x = penX; | |
| 523 + points[1].y = penY; | |
| 524 + | |
| 525 + // The rest of the points | |
| 526 + for (int i = 2; i < npoints; i++) { | |
| 527 + switch (getSlope(winx, i, ww)) { | |
| 528 + case UNDERCURL_SLOPE_AS… | |
| 529 + case UNDERCURL_SLOPE_DE… | |
| 530 + penX += ww * (1… | |
| 531 + penY += 0; | |
| 532 + break; | |
| 533 + case UNDERCURL_SLOPE_TO… | |
| 534 + penX += ww * (2… | |
| 535 + penY += -wh / 2… | |
| 536 + break; | |
| 537 + case UNDERCURL_SLOPE_BO… | |
| 538 + penX += ww * (2… | |
| 539 + penY += wh / 2.… | |
| 540 + break; | |
| 541 + } | |
| 542 + points[i].x = penX; | |
| 543 + points[i].y = penY; | |
| 544 + } | |
| 545 + | |
| 546 + // End | |
| 547 + float waveLength = penX - winx; | |
| 548 + if (waveLength < width) { // Add a bonu… | |
| 549 + int marginEnd = width - waveLen… | |
| 550 + penX += marginEnd; | |
| 551 + switch(getSlope(winx, npoints, … | |
| 552 + case UNDERCURL_SLOPE_AS… | |
| 553 + case UNDERCURL_SLOPE_DE… | |
| 554 + //penY += 0; | |
| 555 + break; | |
| 556 + case UNDERCURL_SLOPE_TO… | |
| 557 + penY += -margin… | |
| 558 + break; | |
| 559 + case UNDERCURL_SLOPE_BO… | |
| 560 + penY += marginE… | |
| 561 + break; | |
| 562 + } | |
| 563 + | |
| 564 + points[npoints].x = penX; | |
| 565 + points[npoints].y = penY; | |
| 566 + | |
| 567 + npoints++; | |
| 568 + } else if (waveLength > width) { // Is … | |
| 569 + int marginEnd = waveLength - wi… | |
| 570 + points[npoints-1].x -= marginEn… | |
| 571 + switch(getSlope(winx, npoints-1… | |
| 572 + case UNDERCURL_SLOPE_TO… | |
| 573 + points[npoints-… | |
| 574 + break; | |
| 575 + case UNDERCURL_SLOPE_BO… | |
| 576 + points[npoints-… | |
| 577 + break; | |
| 578 + default: | |
| 579 + break; | |
| 580 + } | |
| 581 + } | |
| 582 + | |
| 583 + // Draw the lines | |
| 584 + XDrawLines(xw.dpy, XftDrawDrawable(xw.d… | |
| 585 + CoordModeOrigin); | |
| 586 + | |
| 587 + // Draw a second underline with an offs… | |
| 588 + if ( ((win.ch / (widthThreshold/2)) % 2… | |
| 589 + for (int i = 0; i < npoints; i+… | |
| 590 + points[i].x++; | |
| 591 + | |
| 592 + XDrawLines(xw.dpy, XftDrawDrawa… | |
| 593 + npoints, CoordM… | |
| 594 + } | |
| 595 + | |
| 596 + // Free resources | |
| 597 + free(points); | |
| 598 + } | |
| 599 +#endif | |
| 600 + } | |
| 601 + | |
| 602 + XFreeGC(xw.dpy, ugc); | |
| 603 } | |
| 604 | |
| 605 if (base.mode & ATTR_STRUCK) { |