logo

etc_portage

Unnamed repository; edit this file 'description' to name the repository. git clone https://hacktivis.me/git/etc_portage.git

1.patch (21699B)


  1. From 7808631e7a9a605d5fe7a1077129c658d9ec47fc Mon Sep 17 00:00:00 2001
  2. From: Maxime Coste <mawww@kakoune.org>
  3. Date: Tue, 22 Oct 2019 22:46:49 +1100
  4. Subject: [PATCH] Add support for BGRA glyphs display and scaling
  5. Display is done using an XRender Picture, as XRender
  6. glyphs are incompatible with BGRA rendering due to
  7. their use of the glyph bitmap as a mask.
  8. Scaling is done by averaging all relevant pixel, which gives
  9. much better result than nearest pixel sampling while staying
  10. simple enough and not too computationally expensive.
  11. This enables color emoji rendering support.
  12. Fixes: #6
  13. Signed-off-by: Maxime Coste <mawww@kakoune.org>
  14. ---
  15. src/xftfreetype.c | 18 ++++-
  16. src/xftglyphs.c | 200 ++++++++++++++++++++++++++++++++++++++++++----
  17. src/xftint.h | 2 +
  18. src/xftrender.c | 168 ++++++++++++++++++++++++--------------
  19. 4 files changed, 307 insertions(+), 81 deletions(-)
  20. diff --git a/src/xftfreetype.c b/src/xftfreetype.c
  21. index a3b8332..a639a03 100644
  22. --- a/src/xftfreetype.c
  23. +++ b/src/xftfreetype.c
  24. @@ -514,7 +514,7 @@ XftFontInfoFill (Display *dpy, _Xconst FcPattern *pattern, XftFontInfo *fi)
  25. /*
  26. * Compute glyph load flags
  27. */
  28. - fi->load_flags = FT_LOAD_DEFAULT;
  29. + fi->load_flags = FT_LOAD_DEFAULT | FT_LOAD_COLOR;
  30. #ifndef XFT_EMBEDDED_BITMAP
  31. #define XFT_EMBEDDED_BITMAP "embeddedbitmap"
  32. @@ -766,6 +766,7 @@ XftFontOpenInfo (Display *dpy,
  33. FcChar32 hash_value;
  34. FcChar32 rehash_value;
  35. FcBool antialias;
  36. + FcBool color;
  37. int max_glyph_memory;
  38. int alloc_size;
  39. int ascent, descent, height;
  40. @@ -822,12 +823,16 @@ XftFontOpenInfo (Display *dpy,
  41. if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
  42. antialias = FcFalse;
  43. + color = FT_HAS_COLOR(face) ? FcTrue : FcFalse;
  44. +
  45. /*
  46. * Find the appropriate picture format
  47. */
  48. if (fi->render)
  49. {
  50. - if (antialias)
  51. + if (color)
  52. + format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
  53. + else if (antialias)
  54. {
  55. switch (fi->rgba) {
  56. case FC_RGBA_RGB:
  57. @@ -842,9 +847,7 @@ XftFontOpenInfo (Display *dpy,
  58. }
  59. }
  60. else
  61. - {
  62. format = XRenderFindStandardFormat (dpy, PictStandardA1);
  63. - }
  64. if (!format)
  65. goto bail2;
  66. @@ -959,6 +962,13 @@ XftFontOpenInfo (Display *dpy,
  67. * which doesn't happen in XftFontInfoFill
  68. */
  69. font->info.antialias = antialias;
  70. +
  71. + /*
  72. + * Set color value, which is only known once the
  73. + * font was loaded
  74. + */
  75. + font->info.color = color;
  76. +
  77. /*
  78. * bump XftFile reference count
  79. */
  80. diff --git a/src/xftglyphs.c b/src/xftglyphs.c
  81. index 4b5fb82..af2e3c1 100644
  82. --- a/src/xftglyphs.c
  83. +++ b/src/xftglyphs.c
  84. @@ -26,6 +26,8 @@
  85. #include FT_SYNTHESIS_H
  86. +#include FT_GLYPH_H
  87. +
  88. /*
  89. * Validate the memory info for a font
  90. */
  91. @@ -78,9 +80,11 @@ _XftFontValidateMemory (Display *dpy, XftFont *public)
  92. static int
  93. _compute_xrender_bitmap_size( FT_Bitmap* target,
  94. FT_GlyphSlot slot,
  95. - FT_Render_Mode mode )
  96. + FT_Render_Mode mode,
  97. + FT_Matrix* matrix )
  98. {
  99. FT_Bitmap* ftbit;
  100. + FT_Vector vector;
  101. int width, height, pitch;
  102. if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
  103. @@ -88,9 +92,18 @@ _compute_xrender_bitmap_size( FT_Bitmap* target,
  104. // compute the size of the final bitmap
  105. ftbit = &slot->bitmap;
  106. -
  107. width = ftbit->width;
  108. height = ftbit->rows;
  109. +
  110. + if ( matrix && mode == FT_RENDER_MODE_NORMAL )
  111. + {
  112. + vector.x = ftbit->width;
  113. + vector.y = ftbit->rows;
  114. + FT_Vector_Transform(&vector, matrix);
  115. +
  116. + width = vector.x;
  117. + height = vector.y;
  118. + }
  119. pitch = (width+3) & ~3;
  120. switch ( ftbit->pixel_mode )
  121. @@ -112,6 +125,10 @@ _compute_xrender_bitmap_size( FT_Bitmap* target,
  122. }
  123. break;
  124. + case FT_PIXEL_MODE_BGRA:
  125. + pitch = width * 4;
  126. + break;
  127. +
  128. case FT_PIXEL_MODE_LCD:
  129. if ( mode != FT_RENDER_MODE_LCD )
  130. return -1;
  131. @@ -142,6 +159,105 @@ _compute_xrender_bitmap_size( FT_Bitmap* target,
  132. return pitch * height;
  133. }
  134. +/* this functions converts the glyph bitmap found in a FT_GlyphSlot
  135. + * into a different format while scaling by applying the given matrix
  136. + * (see _compute_xrender_bitmap_size)
  137. + *
  138. + * you should call this function after _compute_xrender_bitmap_size
  139. + *
  140. + * target :: target bitmap descriptor. Note that its 'buffer' pointer
  141. + * must point to memory allocated by the caller
  142. + *
  143. + * source :: the source bitmap descriptor
  144. + *
  145. + * matrix :: the scaling matrix to apply
  146. + */
  147. +static void
  148. +_scaled_fill_xrender_bitmap( FT_Bitmap* target,
  149. + FT_Bitmap* source,
  150. + const FT_Matrix* matrix )
  151. +{
  152. + unsigned char* src_buf = source->buffer;
  153. + unsigned char* dst_line = target->buffer;
  154. + int src_pitch = source->pitch;
  155. + int width = target->width;
  156. + int height = target->rows;
  157. + int pitch = target->pitch;
  158. + int h;
  159. + FT_Vector vector;
  160. + FT_Matrix inverse = *matrix;
  161. + int sampling_width;
  162. + int sampling_height;
  163. + int sample_count;
  164. +
  165. + if ( src_pitch < 0 )
  166. + src_buf -= src_pitch*(source->rows-1);
  167. +
  168. + FT_Matrix_Invert(&inverse);
  169. +
  170. + /* compute how many source pixels a target pixel spans */
  171. + vector.x = 1;
  172. + vector.y = 1;
  173. + FT_Vector_Transform(&vector, &inverse);
  174. + sampling_width = vector.x / 2;
  175. + sampling_height = vector.y / 2;
  176. + sample_count = (2 * sampling_width + 1) * (2 * sampling_height + 1);
  177. +
  178. + for ( h = height; h > 0; h--, dst_line += pitch )
  179. + {
  180. + int x;
  181. +
  182. + for ( x = 0; x < width; x++ )
  183. + {
  184. + unsigned char* src;
  185. +
  186. +#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
  187. +
  188. + /* compute target pixel location in source space */
  189. + vector.x = (x * 0x10000) + 0x10000 / 2;
  190. + vector.y = ((height - h) * 0x10000) + 0x10000 / 2;
  191. + FT_Vector_Transform(&vector, &inverse);
  192. + vector.x = CLAMP(FT_RoundFix(vector.x) / 0x10000, 0, source->width - 1);
  193. + vector.y = CLAMP(FT_RoundFix(vector.y) / 0x10000, 0, source->rows - 1);
  194. +
  195. + switch ( source->pixel_mode )
  196. + {
  197. + case FT_PIXEL_MODE_MONO: /* convert mono to 8-bit gray, scale using nearest pixel */
  198. + src = src_buf + (vector.y * src_pitch);
  199. + if ( src[(vector.x >> 3)] & (0x80 >> (vector.x & 7)) )
  200. + dst_line[x] = 0xff;
  201. + break;
  202. +
  203. + case FT_PIXEL_MODE_GRAY: /* scale using nearest pixel */
  204. + src = src_buf + (vector.y * src_pitch);
  205. + dst_line[x] = src[vector.x];
  206. + break;
  207. +
  208. + case FT_PIXEL_MODE_BGRA: /* scale by averaging all relevant source pixels, keep BGRA format */
  209. + {
  210. + int sample_x, sample_y;
  211. + int bgra[4] = {};
  212. + for (sample_y = - sampling_height; sample_y < sampling_height + 1; ++sample_y)
  213. + {
  214. + int src_y = CLAMP(vector.y + sample_y, 0, source->rows - 1);
  215. + src = src_buf + (src_y * src_pitch);
  216. + for (sample_x = - sampling_width; sample_x < sampling_width + 1; ++sample_x)
  217. + {
  218. + int src_x = CLAMP(vector.x + sample_x, 0, source->width - 1);
  219. + for (int i = 0; i < 4; ++i)
  220. + bgra[i] += src[src_x * 4 + i];
  221. + }
  222. + }
  223. +
  224. + for (int i = 0; i < 4; ++i)
  225. + dst_line[4 * x + i] = bgra[i] / sample_count;
  226. + break;
  227. + }
  228. + }
  229. + }
  230. + }
  231. +}
  232. +
  233. /* this functions converts the glyph bitmap found in a FT_GlyphSlot
  234. * into a different format (see _compute_xrender_bitmap_size)
  235. *
  236. @@ -244,6 +360,11 @@ _fill_xrender_bitmap( FT_Bitmap* target,
  237. }
  238. break;
  239. + case FT_PIXEL_MODE_BGRA: /* Preserve BGRA format */
  240. + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
  241. + memcpy( dstLine, srcLine, width * 4 );
  242. + break;
  243. +
  244. case FT_PIXEL_MODE_LCD:
  245. if ( !bgr )
  246. {
  247. @@ -365,6 +486,8 @@ XftFontLoadGlyphs (Display *dpy,
  248. FT_Vector vector;
  249. FT_Face face;
  250. FT_Render_Mode mode = FT_RENDER_MODE_MONO;
  251. + FcBool transform;
  252. + FcBool glyph_transform;
  253. if (!info)
  254. return;
  255. @@ -374,6 +497,8 @@ XftFontLoadGlyphs (Display *dpy,
  256. if (!face)
  257. return;
  258. + if (font->info.color)
  259. + mode = FT_RENDER_MODE_NORMAL;
  260. if (font->info.antialias)
  261. {
  262. switch (font->info.rgba) {
  263. @@ -390,6 +515,8 @@ XftFontLoadGlyphs (Display *dpy,
  264. }
  265. }
  266. + transform = font->info.transform && mode != FT_RENDER_MODE_MONO;
  267. +
  268. while (nglyph--)
  269. {
  270. glyphindex = *glyphs++;
  271. @@ -440,7 +567,7 @@ XftFontLoadGlyphs (Display *dpy,
  272. /*
  273. * Compute glyph metrics from FreeType information
  274. */
  275. - if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP)
  276. + if (transform)
  277. {
  278. /*
  279. * calculate the true width by transforming all four corners.
  280. @@ -487,7 +614,7 @@ XftFontLoadGlyphs (Display *dpy,
  281. * Clip charcell glyphs to the bounding box
  282. * XXX transformed?
  283. */
  284. - if (font->info.spacing >= FC_CHARCELL && !font->info.transform)
  285. + if (font->info.spacing >= FC_CHARCELL && !transform)
  286. {
  287. if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
  288. {
  289. @@ -519,18 +646,20 @@ XftFontLoadGlyphs (Display *dpy,
  290. }
  291. }
  292. + glyph_transform = transform;
  293. if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
  294. {
  295. error = FT_Render_Glyph( face->glyph, mode );
  296. if (error)
  297. continue;
  298. + glyph_transform = False;
  299. }
  300. FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
  301. if (font->info.spacing >= FC_MONO)
  302. {
  303. - if (font->info.transform)
  304. + if (transform)
  305. {
  306. if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
  307. {
  308. @@ -613,14 +742,27 @@ XftFontLoadGlyphs (Display *dpy,
  309. }
  310. }
  311. - size = _compute_xrender_bitmap_size( &local, glyphslot, mode );
  312. + size = _compute_xrender_bitmap_size( &local, glyphslot, mode, glyph_transform ? &font->info.matrix : NULL );
  313. if ( size < 0 )
  314. continue;
  315. xftg->metrics.width = local.width;
  316. xftg->metrics.height = local.rows;
  317. - xftg->metrics.x = - glyphslot->bitmap_left;
  318. - xftg->metrics.y = glyphslot->bitmap_top;
  319. + if (transform)
  320. + {
  321. + vector.x = - glyphslot->bitmap_left;
  322. + vector.y = glyphslot->bitmap_top;
  323. +
  324. + FT_Vector_Transform(&vector, &font->info.matrix);
  325. +
  326. + xftg->metrics.x = vector.x;
  327. + xftg->metrics.y = vector.y;
  328. + }
  329. + else
  330. + {
  331. + xftg->metrics.x = - glyphslot->bitmap_left;
  332. + xftg->metrics.y = glyphslot->bitmap_top;
  333. + }
  334. /*
  335. * If the glyph is relatively large (> 1% of server memory),
  336. @@ -645,9 +787,12 @@ XftFontLoadGlyphs (Display *dpy,
  337. local.buffer = bufBitmap;
  338. - _fill_xrender_bitmap( &local, glyphslot, mode,
  339. - (font->info.rgba == FC_RGBA_BGR ||
  340. - font->info.rgba == FC_RGBA_VBGR ) );
  341. + if (mode == FT_RENDER_MODE_NORMAL && glyph_transform)
  342. + _scaled_fill_xrender_bitmap(&local, &glyphslot->bitmap, &font->info.matrix);
  343. + else
  344. + _fill_xrender_bitmap( &local, glyphslot, mode,
  345. + (font->info.rgba == FC_RGBA_BGR ||
  346. + font->info.rgba == FC_RGBA_VBGR ) );
  347. /*
  348. * Copy or convert into local buffer.
  349. @@ -662,6 +807,7 @@ XftFontLoadGlyphs (Display *dpy,
  350. */
  351. glyph = (Glyph) glyphindex;
  352. + xftg->picture = 0;
  353. xftg->glyph_memory = size + sizeof (XftGlyph);
  354. if (font->format)
  355. {
  356. @@ -685,15 +831,35 @@ XftFontLoadGlyphs (Display *dpy,
  357. }
  358. }
  359. }
  360. - else if ( mode != FT_RENDER_MODE_NORMAL )
  361. + else if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA || mode != FT_RENDER_MODE_NORMAL)
  362. {
  363. /* invert ARGB <=> BGRA */
  364. if (ImageByteOrder (dpy) != XftNativeByteOrder ())
  365. XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
  366. }
  367. - XRenderAddGlyphs (dpy, font->glyphset, &glyph,
  368. - &xftg->metrics, 1,
  369. - (char *) bufBitmap, size);
  370. +
  371. + if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
  372. + {
  373. + Pixmap pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), local.width, local.rows, 32);
  374. + GC gc = XCreateGC(dpy, pixmap, 0, NULL);
  375. + XImage image = {
  376. + local.width, local.rows, 0, ZPixmap, (char *)bufBitmap,
  377. + dpy->byte_order, dpy->bitmap_unit, dpy->bitmap_bit_order, 32,
  378. + 32, local.width * 4 - local.pitch, 32,
  379. + 0, 0, 0
  380. + };
  381. +
  382. + XInitImage(&image);
  383. + XPutImage(dpy, pixmap, gc, &image, 0, 0, 0, 0, local.width, local.rows);
  384. + xftg->picture = XRenderCreatePicture(dpy, pixmap, font->format, 0, NULL);
  385. +
  386. + XFreeGC(dpy, gc);
  387. + XFreePixmap(dpy, pixmap);
  388. + }
  389. + else
  390. + XRenderAddGlyphs (dpy, font->glyphset, &glyph,
  391. + &xftg->metrics, 1,
  392. + (char *) bufBitmap, size);
  393. }
  394. else
  395. {
  396. @@ -744,7 +910,9 @@ XftFontUnloadGlyphs (Display *dpy,
  397. {
  398. if (font->format)
  399. {
  400. - if (font->glyphset)
  401. + if (xftg->picture)
  402. + XRenderFreePicture(dpy, xftg->picture);
  403. + else if (font->glyphset)
  404. {
  405. glyphBuf[nused++] = (Glyph) glyphindex;
  406. if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
  407. diff --git a/src/xftint.h b/src/xftint.h
  408. index c06ac3c..b263520 100644
  409. --- a/src/xftint.h
  410. +++ b/src/xftint.h
  411. @@ -85,6 +85,7 @@ typedef struct _XftGlyph {
  412. XGlyphInfo metrics;
  413. void *bitmap;
  414. unsigned long glyph_memory;
  415. + Picture picture;
  416. } XftGlyph;
  417. /*
  418. @@ -134,6 +135,7 @@ struct _XftFontInfo {
  419. FT_F26Dot6 xsize, ysize; /* pixel size */
  420. FcBool antialias; /* doing antialiasing */
  421. FcBool embolden; /* force emboldening */
  422. + FcBool color; /* contains color glyphs */
  423. int rgba; /* subpixel order */
  424. int lcd_filter; /* lcd filter */
  425. FT_Matrix matrix; /* glyph transformation matrix */
  426. diff --git a/src/xftrender.c b/src/xftrender.c
  427. index b280c03..9a789cb 100644
  428. --- a/src/xftrender.c
  429. +++ b/src/xftrender.c
  430. @@ -25,6 +25,35 @@
  431. #define NUM_LOCAL 1024
  432. #define NUM_ELT_LOCAL 128
  433. +/*
  434. + * Dispatch glyph drawing to the correct XRenderCompositeString function
  435. + */
  436. +static void
  437. +_XftCompositeString (Display *dpy, int op, Picture src, Picture dst, XRenderPictFormat* format, GlyphSet glyphset, int srcx, int srcy, int dstx, int dsty, int charwidth, unsigned int* chars, int nchars)
  438. +{
  439. + if (nchars == 0)
  440. + return;
  441. +
  442. + switch (charwidth) {
  443. + case 1:
  444. + default:
  445. + XRenderCompositeString8 (dpy, op,
  446. + src, dst, format, glyphset,
  447. + srcx, srcy, dstx, dsty, (char*)chars, nchars);
  448. + break;
  449. + case 2:
  450. + XRenderCompositeString16(dpy, op,
  451. + src, dst, format, glyphset,
  452. + srcx, srcy, dstx, dsty, (unsigned short*)chars, nchars);
  453. + break;
  454. + case 4:
  455. + XRenderCompositeString32(dpy, op,
  456. + src, dst, format, glyphset,
  457. + srcx, srcy, dstx, dsty, (unsigned int*)chars, nchars);
  458. + break;
  459. + }
  460. +}
  461. +
  462. /*
  463. * Use the Render extension to draw the glyphs
  464. */
  465. @@ -43,12 +72,14 @@ XftGlyphRender (Display *dpy,
  466. int nglyphs)
  467. {
  468. XftFontInt *font = (XftFontInt *) pub;
  469. - int i;
  470. + int i, j;
  471. FT_UInt missing[XFT_NMISSING];
  472. int nmissing;
  473. FT_UInt g, max;
  474. int size, width;
  475. + int dstx, dsty;
  476. Glyph wire;
  477. + XftGlyph* glyph;
  478. char *char8;
  479. unsigned short *char16;
  480. unsigned int *char32;
  481. @@ -100,43 +131,75 @@ XftGlyphRender (Display *dpy,
  482. if (!chars)
  483. goto bail1;
  484. }
  485. + dstx = x;
  486. + dsty = y;
  487. char8 = (char *) chars;
  488. char16 = (unsigned short *) chars;
  489. char32 = (unsigned int *) chars;
  490. - for (i = 0; i < nglyphs; i++)
  491. + for (i = 0, j = 0; i < nglyphs; i++)
  492. {
  493. wire = (Glyph) glyphs[i];
  494. if (wire >= font->num_glyphs || !font->glyphs[wire])
  495. wire = 0;
  496. - switch (width) {
  497. - case 1: char8[i] = (char) wire; break;
  498. - case 2: char16[i] = (unsigned short) wire; break;
  499. - case 4: char32[i] = (unsigned long) wire; break;
  500. + glyph = font->glyphs[wire];
  501. + if (glyph->picture)
  502. + {
  503. + _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset, srcx, srcy, x, y, width, chars, j);
  504. + XRenderComposite(dpy, PictOpOver, glyph->picture, None, dst, 0, 0, 0, 0, dstx, dsty - glyph->metrics.y, glyph->metrics.width, glyph->metrics.height);
  505. + x = dstx = dstx + glyph->metrics.xOff;
  506. + x = dsty = dsty + glyph->metrics.yOff;
  507. + j = 0;
  508. + }
  509. + else
  510. + {
  511. + switch (width) {
  512. + case 1: char8[j] = (char) wire; break;
  513. + case 2: char16[j] = (unsigned short) wire; break;
  514. + case 4: char32[j] = (unsigned long) wire; break;
  515. + }
  516. + dstx += glyph->metrics.xOff;
  517. + dsty += glyph->metrics.yOff;
  518. + ++j;
  519. }
  520. }
  521. - switch (width) {
  522. + _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset, srcx, srcy, x, y, width, chars, j);
  523. + if (chars != char_local)
  524. + free (chars);
  525. +bail1:
  526. + if (glyphs_loaded)
  527. + _XftFontManageMemory (dpy, pub);
  528. +}
  529. +
  530. +/*
  531. + * Dispatch glyph drawing to the correct XRenderCompositeText function
  532. + */
  533. +static void
  534. +_XftCompositeText (Display *dpy, int op, Picture src, Picture dst, XRenderPictFormat* format, int srcx, int srcy, int dstx, int dsty, int eltwidth, XGlyphElt8* elts, int nelt)
  535. +{
  536. + if (nelt == 0)
  537. + return;
  538. +
  539. + switch (eltwidth) {
  540. case 1:
  541. default:
  542. - XRenderCompositeString8 (dpy, op,
  543. - src, dst, font->format, font->glyphset,
  544. - srcx, srcy, x, y, char8, nglyphs);
  545. + XRenderCompositeText8 (dpy, op,
  546. + src, dst, format,
  547. + srcx, srcy, dstx, dsty,
  548. + (XGlyphElt8*)elts, nelt);
  549. break;
  550. case 2:
  551. - XRenderCompositeString16(dpy, op,
  552. - src, dst, font->format, font->glyphset,
  553. - srcx, srcy, x, y, char16, nglyphs);
  554. + XRenderCompositeText16(dpy, op,
  555. + src, dst, format,
  556. + srcx, srcy, dstx, dsty,
  557. + (XGlyphElt16*)elts, nelt);
  558. break;
  559. case 4:
  560. - XRenderCompositeString32(dpy, op,
  561. - src, dst, font->format, font->glyphset,
  562. - srcx, srcy, x, y, char32, nglyphs);
  563. + XRenderCompositeText32(dpy, op,
  564. + src, dst, format,
  565. + srcx, srcy, dstx, dsty,
  566. + (XGlyphElt32*)elts, nelt);
  567. break;
  568. }
  569. - if (chars != char_local)
  570. - free (chars);
  571. -bail1:
  572. - if (glyphs_loaded)
  573. - _XftFontManageMemory (dpy, pub);
  574. }
  575. _X_EXPORT void
  576. @@ -251,9 +314,10 @@ XftGlyphSpecRender (Display *dpy,
  577. g = 0;
  578. /*
  579. * check to see if the glyph is placed where it would
  580. - * fall using the normal spacing
  581. + * fall using the normal spacing and if it would render
  582. + * as a XRender glyph
  583. */
  584. - if ((glyph = font->glyphs[g]))
  585. + if ((glyph = font->glyphs[g]) && !glyph->picture)
  586. {
  587. if (x != glyphs[i].x || y != glyphs[i].y)
  588. {
  589. @@ -267,7 +331,7 @@ XftGlyphSpecRender (Display *dpy,
  590. }
  591. elts = elts_local;
  592. - if (nelt > NUM_ELT_LOCAL)
  593. + if (!font->info.color && nelt > NUM_ELT_LOCAL)
  594. {
  595. elts = malloc (nelt * sizeof (XGlyphElt8));
  596. if (!elts)
  597. @@ -275,7 +339,7 @@ XftGlyphSpecRender (Display *dpy,
  598. }
  599. /*
  600. - * Generate the list of glyph elts
  601. + * Generate the list of glyph elts or render color glyphs
  602. */
  603. nelt = 0;
  604. x = y = 0;
  605. @@ -289,6 +353,11 @@ XftGlyphSpecRender (Display *dpy,
  606. g = 0;
  607. if ((glyph = font->glyphs[g]))
  608. {
  609. + if (glyph->picture)
  610. + {
  611. + XRenderComposite(dpy, PictOpOver, glyph->picture, None, dst, 0, 0, 0, 0, glyphs[i].x, glyphs[i].y - glyph->metrics.y, glyph->metrics.width, glyph->metrics.height);
  612. + continue;
  613. + }
  614. if (!i || x != glyphs[i].x || y != glyphs[i].y)
  615. {
  616. if (n)
  617. @@ -320,23 +389,9 @@ XftGlyphSpecRender (Display *dpy,
  618. elts[nelt].nchars = n;
  619. nelt++;
  620. }
  621. - switch (width) {
  622. - case 1:
  623. - XRenderCompositeText8 (dpy, op, src, dst, font->format,
  624. - srcx, srcy, glyphs[0].x, glyphs[0].y,
  625. - elts, nelt);
  626. - break;
  627. - case 2:
  628. - XRenderCompositeText16 (dpy, op, src, dst, font->format,
  629. - srcx, srcy, glyphs[0].x, glyphs[0].y,
  630. - (XGlyphElt16 *) elts, nelt);
  631. - break;
  632. - case 4:
  633. - XRenderCompositeText32 (dpy, op, src, dst, font->format,
  634. - srcx, srcy, glyphs[0].x, glyphs[0].y,
  635. - (XGlyphElt32 *) elts, nelt);
  636. - break;
  637. - }
  638. + _XftCompositeText(dpy, op, src, dst, font->format,
  639. + srcx, srcy, glyphs[0].x, glyphs[0].y,
  640. + width, elts, nelt);
  641. if (elts != elts_local)
  642. free (elts);
  643. @@ -535,7 +590,7 @@ XftGlyphFontSpecRender (Display *dpy,
  644. * check to see if the glyph is placed where it would
  645. * fall using the normal spacing
  646. */
  647. - if ((glyph = font->glyphs[g]))
  648. + if ((glyph = font->glyphs[g]) && !glyph->picture)
  649. {
  650. if (pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
  651. {
  652. @@ -560,7 +615,7 @@ XftGlyphFontSpecRender (Display *dpy,
  653. }
  654. /*
  655. - * Generate the list of glyph elts
  656. + * Generate the list of glyph elts and render color glyphs
  657. */
  658. nelt = 0;
  659. x = y = 0;
  660. @@ -578,6 +633,11 @@ XftGlyphFontSpecRender (Display *dpy,
  661. g = 0;
  662. if ((glyph = font->glyphs[g]))
  663. {
  664. + if (glyph->picture)
  665. + {
  666. + XRenderComposite(dpy, PictOpOver, glyph->picture, None, dst, 0, 0, 0, 0, glyphs[i].x, glyphs[i].y - glyph->metrics.y, glyph->metrics.width, glyph->metrics.height);
  667. + continue;
  668. + }
  669. if (!i || pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
  670. {
  671. if (n)
  672. @@ -610,23 +670,9 @@ XftGlyphFontSpecRender (Display *dpy,
  673. elts[nelt].nchars = n;
  674. nelt++;
  675. }
  676. - switch (width) {
  677. - case 1:
  678. - XRenderCompositeText8 (dpy, op, src, dst, format,
  679. - srcx, srcy, glyphs[0].x, glyphs[0].y,
  680. - elts, nelt);
  681. - break;
  682. - case 2:
  683. - XRenderCompositeText16 (dpy, op, src, dst, format,
  684. - srcx, srcy, glyphs[0].x, glyphs[0].y,
  685. - (XGlyphElt16 *) elts, nelt);
  686. - break;
  687. - case 4:
  688. - XRenderCompositeText32 (dpy, op, src, dst, format,
  689. - srcx, srcy, glyphs[0].x, glyphs[0].y,
  690. - (XGlyphElt32 *) elts, nelt);
  691. - break;
  692. - }
  693. + _XftCompositeText(dpy, op, src, dst, format,
  694. + srcx, srcy, glyphs[0].x, glyphs[0].y,
  695. + width, elts, nelt);
  696. if (elts != elts_local)
  697. free (elts);
  698. --
  699. 2.24.1