st-glyph-wide-support-boxdraw-20220411-ef05519.diff 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. From 9583955da47177c9557210f70baaaf9511ba106c Mon Sep 17 00:00:00 2001
  2. From: wael <40663@protonmail.com>
  3. Date: Mon, 11 Apr 2022 17:14:06 +0300
  4. Subject: [PATCH] boxdraw support for glyph wide support
  5. ---
  6. st.h | 6 +++
  7. x.c | 139 ++++++++++++++++++++++++++++++-----------------------------
  8. 2 files changed, 76 insertions(+), 69 deletions(-)
  9. diff --git a/st.h b/st.h
  10. index 07a7c66..3b8c97d 100644
  11. --- a/st.h
  12. +++ b/st.h
  13. @@ -37,6 +37,12 @@ enum glyph_attribute {
  14. ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
  15. };
  16. +enum drawing_mode {
  17. + DRAW_NONE = 0,
  18. + DRAW_BG = 1 << 0,
  19. + DRAW_FG = 1 << 1,
  20. +};
  21. +
  22. enum selection_mode {
  23. SEL_IDLE = 0,
  24. SEL_EMPTY = 1,
  25. diff --git a/x.c b/x.c
  26. index bf6bbf9..1311c0d 100644
  27. --- a/x.c
  28. +++ b/x.c
  29. @@ -142,7 +142,7 @@ typedef struct {
  30. static inline ushort sixd_to_16bit(int);
  31. static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
  32. -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
  33. +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
  34. static void xdrawglyph(Glyph, int, int);
  35. static void xclear(int, int, int, int);
  36. static int xgeommasktogravity(int);
  37. @@ -1379,7 +1379,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
  38. }
  39. void
  40. -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
  41. +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
  42. {
  43. int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
  44. int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
  45. @@ -1470,51 +1470,45 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
  46. if (base.mode & ATTR_INVISIBLE)
  47. fg = bg;
  48. - /* Intelligent cleaning up of the borders. */
  49. - if (x == 0) {
  50. - xclear(0, (y == 0)? 0 : winy, borderpx,
  51. - winy + win.ch +
  52. - ((winy + win.ch >= borderpx + win.th)? win.h : 0));
  53. - }
  54. - if (winx + width >= borderpx + win.tw) {
  55. - xclear(winx + width, (y == 0)? 0 : winy, win.w,
  56. - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
  57. - }
  58. - if (y == 0)
  59. - xclear(winx, 0, winx + width, borderpx);
  60. - if (winy + win.ch >= borderpx + win.th)
  61. - xclear(winx, winy + win.ch, winx + width, win.h);
  62. -
  63. - /* Clean up the region we want to draw to. */
  64. - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
  65. -
  66. - /* Set the clip region because Xft is sometimes dirty. */
  67. - r.x = 0;
  68. - r.y = 0;
  69. - r.height = win.ch;
  70. - r.width = width;
  71. - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
  72. -
  73. - if (base.mode & ATTR_BOXDRAW) {
  74. - drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
  75. - } else {
  76. - /* Render the glyphs. */
  77. - XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
  78. - }
  79. + if (dmode & DRAW_BG) {
  80. + /* Intelligent cleaning up of the borders. */
  81. + if (x == 0) {
  82. + xclear(0, (y == 0)? 0 : winy, borderpx,
  83. + winy + win.ch +
  84. + ((winy + win.ch >= borderpx + win.th)? win.h : 0));
  85. + }
  86. + if (winx + width >= borderpx + win.tw) {
  87. + xclear(winx + width, (y == 0)? 0 : winy, win.w,
  88. + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
  89. + }
  90. + if (y == 0)
  91. + xclear(winx, 0, winx + width, borderpx);
  92. + if (winy + win.ch >= borderpx + win.th)
  93. + xclear(winx, winy + win.ch, winx + width, win.h);
  94. + /* Fill the background */
  95. + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
  96. + }
  97. +
  98. +
  99. + if (dmode & DRAW_FG) {
  100. + if (base.mode & ATTR_BOXDRAW) {
  101. + drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
  102. + } else {
  103. + /* Render the glyphs. */
  104. + XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
  105. + }
  106. - /* Render underline and strikethrough. */
  107. - if (base.mode & ATTR_UNDERLINE) {
  108. - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
  109. - width, 1);
  110. - }
  111. + /* Render underline and strikethrough. */
  112. + if (base.mode & ATTR_UNDERLINE) {
  113. + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
  114. + width, 1);
  115. + }
  116. - if (base.mode & ATTR_STRUCK) {
  117. - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
  118. - width, 1);
  119. - }
  120. -
  121. - /* Reset clip to none. */
  122. - XftDrawSetClip(xw.draw, 0);
  123. + if (base.mode & ATTR_STRUCK) {
  124. + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
  125. + width, 1);
  126. + }
  127. + }
  128. }
  129. void
  130. @@ -1524,7 +1518,7 @@ xdrawglyph(Glyph g, int x, int y)
  131. XftGlyphFontSpec spec;
  132. numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
  133. - xdrawglyphfontspecs(&spec, g, numspecs, x, y);
  134. + xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
  135. }
  136. void
  137. @@ -1659,32 +1653,39 @@ xstartdraw(void)
  138. void
  139. xdrawline(Line line, int x1, int y1, int x2)
  140. {
  141. - int i, x, ox, numspecs;
  142. + int i, x, ox, numspecs, numspecs_cached;
  143. Glyph base, new;
  144. - XftGlyphFontSpec *specs = xw.specbuf;
  145. -
  146. - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
  147. - i = ox = 0;
  148. - for (x = x1; x < x2 && i < numspecs; x++) {
  149. - new = line[x];
  150. - if (new.mode == ATTR_WDUMMY)
  151. - continue;
  152. - if (selected(x, y1))
  153. - new.mode ^= ATTR_REVERSE;
  154. - if (i > 0 && ATTRCMP(base, new)) {
  155. - xdrawglyphfontspecs(specs, base, i, ox, y1);
  156. - specs += i;
  157. - numspecs -= i;
  158. - i = 0;
  159. - }
  160. - if (i == 0) {
  161. - ox = x;
  162. - base = new;
  163. + XftGlyphFontSpec *specs;
  164. +
  165. + numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
  166. +
  167. + /* Draw line in 2 passes: background and foreground. This way wide glyphs
  168. + won't get truncated (#223) */
  169. + for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
  170. + specs = xw.specbuf;
  171. + numspecs = numspecs_cached;
  172. + i = ox = 0;
  173. + for (x = x1; x < x2 && i < numspecs; x++) {
  174. + new = line[x];
  175. + if (new.mode == ATTR_WDUMMY)
  176. + continue;
  177. + if (selected(x, y1))
  178. + new.mode ^= ATTR_REVERSE;
  179. + if (i > 0 && ATTRCMP(base, new)) {
  180. + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
  181. + specs += i;
  182. + numspecs -= i;
  183. + i = 0;
  184. + }
  185. + if (i == 0) {
  186. + ox = x;
  187. + base = new;
  188. + }
  189. + i++;
  190. }
  191. - i++;
  192. + if (i > 0)
  193. + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
  194. }
  195. - if (i > 0)
  196. - xdrawglyphfontspecs(specs, base, i, ox, y1);
  197. }
  198. void
  199. --
  200. 2.35.1