commit 6c07136

shrub  ·  2026-02-01 18:24:41 +0000 UTC
parent 8990a83
init
4 files changed,  +142, -37
M font.c
M font.c
+3, -2
 1@@ -172,7 +172,8 @@ font_ensure_glyph(struct font *font, FT_UInt glyph_index)
 2 			if (!glyph)
 3 				return false;
 4 
 5-			FT_Load_Glyph(font->face, glyph_index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO);
 6+			FT_Load_Glyph(font->face, glyph_index,
 7+			              FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL);
 8 
 9 			FT_Bitmap_New(&glyph->bitmap);
10 
11@@ -217,7 +218,7 @@ wld_font_text_extents_n(struct wld_font *font_base,
12 
13 	extents->advance = 0;
14 
15-	while ((ret = FcUtf8ToUcs4((FcChar8 *)text, &c, length) > 0) && c != '\0') {
16+	while ((ret = FcUtf8ToUcs4((FcChar8 *)text, &c, length)) > 0 && c != '\0') {
17 		length -= ret;
18 		text += ret;
19 		glyph_index = FT_Get_Char_Index(font->face, c);
+24, -2
 1@@ -29,6 +29,7 @@
 2 
 3 #include <i915_drm.h>
 4 #include <intel_bufmgr.h>
 5+#include <string.h>
 6 #include <unistd.h>
 7 
 8 struct intel_context {
 9@@ -57,6 +58,20 @@ IMPL(intel_context, wld_context)
10 IMPL(intel_renderer, wld_renderer)
11 IMPL(intel_buffer, wld_buffer)
12 
13+static void
14+pack_gray_row_to_mono(uint8_t *dst, const uint8_t *src, uint32_t width)
15+{
16+	uint32_t x, bytes_per_row;
17+
18+	bytes_per_row = (width + 7) / 8;
19+	memset(dst, 0, bytes_per_row);
20+
21+	for (x = 0; x < width; ++x) {
22+		if (src[x] >= 128)
23+			dst[x / 8] |= 0x80 >> (x & 7);
24+	}
25+}
26+
27 /**** DRM driver ****/
28 bool
29 driver_device_supported(uint32_t vendor_id, uint32_t device_id)
30@@ -315,8 +330,15 @@ renderer_draw_text(struct wld_renderer *base,
31 
32 		/* XY_TEXT_IMMEDIATE requires a pitch with no extra bytes */
33 		for (row = 0; row < glyph->bitmap.rows; ++row) {
34-			memcpy(byte, glyph->bitmap.buffer + (row * glyph->bitmap.pitch),
35-			       (glyph->bitmap.width + 7) / 8);
36+			const uint8_t *src = glyph->bitmap.buffer +
37+			                     (row * glyph->bitmap.pitch);
38+			uint32_t bytes_per_row = (glyph->bitmap.width + 7) / 8;
39+
40+			if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
41+				memcpy(byte, src, bytes_per_row);
42+			} else {
43+				pack_gray_row_to_mono(byte, src, glyph->bitmap.width);
44+			}
45 			byte += (glyph->bitmap.width + 7) / 8;
46 		}
47 
+60, -12
 1@@ -34,6 +34,7 @@
 2 #include "pixman.h"
 3 
 4 #include <nouveau.h>
 5+#include <string.h>
 6 #include <sys/mman.h>
 7 
 8 enum nv_architecture {
 9@@ -75,6 +76,20 @@ IMPL(nouveau_context, wld_context)
10 IMPL(nouveau_renderer, wld_renderer)
11 IMPL(nouveau_buffer, wld_buffer)
12 
13+static void
14+pack_gray_row_to_mono(uint8_t *dst, const uint8_t *src, uint32_t width)
15+{
16+	uint32_t x, bytes_per_row;
17+
18+	bytes_per_row = (width + 7) / 8;
19+	memset(dst, 0, bytes_per_row);
20+
21+	for (x = 0; x < width; ++x) {
22+		if (src[x] >= 128)
23+			dst[x / 8] |= 0x80 >> (x & 7);
24+	}
25+}
26+
27 /**** DRM driver ****/
28 bool
29 driver_device_supported(uint32_t vendor_id, uint32_t device_id)
30@@ -594,22 +609,55 @@ renderer_draw_text(struct wld_renderer *base,
31 		if (glyph->bitmap.width == 0 || glyph->bitmap.rows == 0)
32 			goto advance;
33 
34-		count = (glyph->bitmap.pitch * glyph->bitmap.rows + 3) / 4;
35+		if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
36+			count = (glyph->bitmap.pitch * glyph->bitmap.rows + 3) / 4;
37+		} else {
38+			uint32_t bytes_per_row = (glyph->bitmap.width + 7) / 8;
39+			count = (bytes_per_row * glyph->bitmap.rows + 3) / 4;
40+		}
41 
42 		if (!ensure_space(renderer->pushbuf, 12 + count))
43 			return;
44 
45-		nvc0_2d(renderer->pushbuf, G80_2D_SIFC_WIDTH, 10,
46-		        /* Use the pitch instead of width to ensure the correct
47-			 * alignment is used. */
48-		        glyph->bitmap.pitch * 8, glyph->bitmap.rows,
49-		        0, 1, 0, 1,
50-		        0, origin_x + glyph->x, 0, y + glyph->y);
51-		nv_add_dword(renderer->pushbuf,
52-		             nvc0_command(GF100_COMMAND_TYPE_NON_INCREASING,
53-		                          GF100_SUBCHANNEL_2D,
54-		                          G80_2D_SIFC_DATA, count));
55-		nv_add_data(renderer->pushbuf, glyph->bitmap.buffer, count);
56+		if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
57+			nvc0_2d(renderer->pushbuf, G80_2D_SIFC_WIDTH, 10,
58+			        /* Use the pitch instead of width to ensure the correct
59+				 * alignment is used. */
60+			        glyph->bitmap.pitch * 8, glyph->bitmap.rows,
61+			        0, 1, 0, 1,
62+			        0, origin_x + glyph->x, 0, y + glyph->y);
63+			nv_add_dword(renderer->pushbuf,
64+			             nvc0_command(GF100_COMMAND_TYPE_NON_INCREASING,
65+			                          GF100_SUBCHANNEL_2D,
66+			                          G80_2D_SIFC_DATA, count));
67+			nv_add_data(renderer->pushbuf, glyph->bitmap.buffer, count);
68+		} else {
69+			uint32_t bytes_per_row = (glyph->bitmap.width + 7) / 8;
70+			uint32_t row;
71+			uint8_t *mono = malloc(bytes_per_row * glyph->bitmap.rows);
72+			uint8_t *dst = mono;
73+
74+			if (!mono)
75+				return;
76+
77+			for (row = 0; row < glyph->bitmap.rows; ++row) {
78+				const uint8_t *src = glyph->bitmap.buffer +
79+				                     (row * glyph->bitmap.pitch);
80+				pack_gray_row_to_mono(dst, src, glyph->bitmap.width);
81+				dst += bytes_per_row;
82+			}
83+
84+			nvc0_2d(renderer->pushbuf, G80_2D_SIFC_WIDTH, 10,
85+			        bytes_per_row * 8, glyph->bitmap.rows,
86+			        0, 1, 0, 1,
87+			        0, origin_x + glyph->x, 0, y + glyph->y);
88+			nv_add_dword(renderer->pushbuf,
89+			             nvc0_command(GF100_COMMAND_TYPE_NON_INCREASING,
90+			                          GF100_SUBCHANNEL_2D,
91+			                          G80_2D_SIFC_DATA, count));
92+			nv_add_data(renderer->pushbuf, mono, count);
93+			free(mono);
94+		}
95 
96 	advance:
97 		origin_x += glyph->advance;
+55, -21
  1@@ -24,6 +24,8 @@
  2 #include "pixman.h"
  3 #include "wld-private.h"
  4 
  5+#include <string.h>
  6+
  7 #define PIXMAN_COLOR(c)                              \
  8 	{                                            \
  9 		.alpha = ((c >> 24) & 0xff) * 0x101, \
 10@@ -344,6 +346,58 @@ reverse(uint8_t byte)
 11 	return byte;
 12 }
 13 
 14+static pixman_image_t *
 15+glyph_bitmap_to_pixman_image(struct glyph *glyph)
 16+{
 17+	FT_Bitmap *bitmap = &glyph->bitmap;
 18+	pixman_image_t *image;
 19+	uint8_t *src, *dst;
 20+	uint32_t row, byte_index, bytes_per_row, pitch;
 21+
 22+	switch (bitmap->pixel_mode) {
 23+	case FT_PIXEL_MODE_MONO:
 24+		image = pixman_image_create_bits(PIXMAN_a1, bitmap->width,
 25+		                                 bitmap->rows, NULL, bitmap->pitch);
 26+		if (!image)
 27+			return NULL;
 28+
 29+		pitch = pixman_image_get_stride(image);
 30+		bytes_per_row = (bitmap->width + 7) / 8;
 31+		src = bitmap->buffer;
 32+		dst = (uint8_t *)pixman_image_get_data(image);
 33+
 34+		for (row = 0; row < bitmap->rows; ++row) {
 35+			/* Pixman's A1 format expects the bits in the opposite order
 36+			 * that Freetype gives us. */
 37+			for (byte_index = 0; byte_index < bytes_per_row; ++byte_index)
 38+				dst[byte_index] = reverse(src[byte_index]);
 39+
 40+			dst += pitch;
 41+			src += bitmap->pitch;
 42+		}
 43+		return image;
 44+	case FT_PIXEL_MODE_GRAY:
 45+		image = pixman_image_create_bits(PIXMAN_a8, bitmap->width,
 46+		                                 bitmap->rows, NULL, 0);
 47+		if (!image)
 48+			return NULL;
 49+
 50+		pitch = pixman_image_get_stride(image);
 51+		src = bitmap->buffer;
 52+		dst = (uint8_t *)pixman_image_get_data(image);
 53+
 54+		for (row = 0; row < bitmap->rows; ++row) {
 55+			memset(dst, 0, pitch);
 56+			memcpy(dst, src, bitmap->width);
 57+			dst += pitch;
 58+			src += bitmap->pitch;
 59+		}
 60+		return image;
 61+	default:
 62+		return NULL;
 63+	}
 64+}
 65+
 66 void
 67 renderer_draw_text(struct wld_renderer *base,
 68                    struct font *font, uint32_t color,
 69@@ -385,32 +439,12 @@ renderer_draw_text(struct wld_renderer *base,
 70 		/* If we don't have the glyph in our cache, do some conversions to make
 71 		 * pixman happy, and then insert it. */
 72 		if (!glyphs[index].glyph) {
 73-			uint8_t *src, *dst;
 74-			uint32_t row, byte_index, bytes_per_row, pitch;
 75 			pixman_image_t *image;
 76-			FT_Bitmap *bitmap;
 77-
 78-			bitmap = &glyph->bitmap;
 79-			image = pixman_image_create_bits(PIXMAN_a1, bitmap->width, bitmap->rows, NULL, bitmap->pitch);
 80+			image = glyph_bitmap_to_pixman_image(glyph);
 81 
 82 			if (!image)
 83 				goto advance;
 84 
 85-			pitch = pixman_image_get_stride(image);
 86-			bytes_per_row = (bitmap->width + 7) / 8;
 87-			src = bitmap->buffer;
 88-			dst = (uint8_t *)pixman_image_get_data(image);
 89-
 90-			for (row = 0; row < bitmap->rows; ++row) {
 91-				/* Pixman's A1 format expects the bits in the opposite order
 92-				 * that Freetype gives us. Sigh... */
 93-				for (byte_index = 0; byte_index < bytes_per_row; ++byte_index)
 94-					dst[byte_index] = reverse(src[byte_index]);
 95-
 96-				dst += pitch;
 97-				src += bitmap->pitch;
 98-			}
 99-
100 			/* Insert the glyph into the cache. */
101 			pixman_glyph_cache_freeze(renderer->glyph_cache);
102 			glyphs[index].glyph = pixman_glyph_cache_insert(renderer->glyph_cache, font, glyph,