From 27f871ac6e898465da85ff20a19c44af5753d6b5 Mon Sep 17 00:00:00 2001 From: Dmitry Karasik Date: Sun, 24 Nov 2024 14:13:34 +0100 Subject: [PATCH] implement RGBA glyphs on X11 --- include/unix/guts.h | 6 ++-- unix/font.c | 11 +++---- unix/fontquery.c | 5 ++-- unix/freetype.c | 73 +++++++++++++++++++++++++++++++++++---------- unix/xft.c | 5 ++-- 5 files changed, 73 insertions(+), 27 deletions(-) diff --git a/include/unix/guts.h b/include/unix/guts.h index 46a5a865..728c9ab8 100644 --- a/include/unix/guts.h +++ b/include/unix/guts.h @@ -1649,7 +1649,7 @@ extern unsigned long * prima_xft_mapper_query_ranges(PFont font, int * count, unsigned int * flags); extern Byte* -prima_xft_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance); +prima_xft_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *bpp); extern Bool prima_xft_is_font_colored(Handle self); @@ -1878,7 +1878,7 @@ extern Bool prima_fq_set_font( Handle self, PCachedFont kf); extern Byte* -prima_fq_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance); +prima_fq_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *bpp); extern int prima_fq_get_glyph_outline( Handle self, unsigned int index, unsigned int flags, int ** buffer); @@ -1941,7 +1941,7 @@ extern int prima_ft_get_glyph_outline( FT_Face face, FT_UInt ft_index, FT_Int32 ft_flags, int ** buffer); extern Byte* -prima_ft_get_glyph_bitmap( FT_Face face, FT_UInt index, FT_Int32 flags, PPoint offset, PPoint size, int *advance); +prima_ft_get_glyph_bitmap( FT_Face face, FT_UInt index, FT_Int32 flags, PPoint offset, PPoint size, int *advance, int *bpp); extern Bool prima_ft_is_font_colored( FT_Face face); diff --git a/unix/font.c b/unix/font.c index d78278d0..8eef7dac 100644 --- a/unix/font.c +++ b/unix/font.c @@ -809,16 +809,15 @@ apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoi #ifdef USE_FONTQUERY if ( is_opt(optInFontQuery) ) { - if ( X(self)->font) { - return prima_fq_get_glyph_bitmap(self, index, flags, offset, size, advance); - } + if ( X(self)->font) + return prima_fq_get_glyph_bitmap(self, index, flags, offset, size, advance, bpp); return NULL; } #endif #ifdef USE_XFT if ( X(self)-> font-> xft) - return prima_xft_get_glyph_bitmap(self, index, flags, offset, size, advance); + return prima_xft_get_glyph_bitmap(self, index, flags, offset, size, advance, bpp); #endif return prima_corefont_get_glyph_bitmap(self, index, flags & ggoMonochrome, offset, size, advance); @@ -840,7 +839,9 @@ apc_font_is_colored( Handle self) #ifdef USE_FONTQUERY if ( is_opt(optInFontQuery) ) { - return false; /* XXX because colored bitmaps are not supported */ + Bool ok = prima_ft_is_font_colored(X(self)->font->ft_face); + f->has_colors = ok ? 1 : -1; + return ok; } #endif diff --git a/unix/fontquery.c b/unix/fontquery.c index 89477cf6..2cde0986 100644 --- a/unix/fontquery.c +++ b/unix/fontquery.c @@ -525,14 +525,15 @@ prima_fq_get_glyph_outline( Handle self, unsigned int index, unsigned int flags, } Byte* -prima_fq_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance) +prima_fq_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *type) { FT_Int32 ft_flags = FT_LOAD_RENDER | + (( flags & ggoARGB ) ? FT_LOAD_COLOR : 0) | (( flags & ggoUseHints ) ? 0 : FT_LOAD_NO_HINTING) | (( flags & ggoMonochrome ) ? FT_LOAD_MONOCHROME : 0) ; - return prima_ft_get_glyph_bitmap(X(self)->font->ft_face, index, ft_flags, offset, size, advance); + return prima_ft_get_glyph_bitmap(X(self)->font->ft_face, index, ft_flags, offset, size, advance, type); } unsigned long * diff --git a/unix/freetype.c b/unix/freetype.c index 8ce953cb..d69bd58c 100644 --- a/unix/freetype.c +++ b/unix/freetype.c @@ -240,17 +240,54 @@ prima_ft_get_glyph_outline( FT_Face face, FT_UInt ft_index, FT_Int32 ft_flags, i } Byte* -prima_ft_get_glyph_bitmap( FT_Face face, FT_UInt index, FT_Int32 flags, PPoint offset, PPoint size, int *advance) +prima_ft_get_glyph_bitmap( FT_Face face, FT_UInt index, FT_Int32 flags, PPoint offset, PPoint size, int *advance, int *bpp) { Byte *ret = NULL; + FT_Bitmap *b; + int src_stride; + Byte *src; - if ( FT_Load_Glyph (face, index, flags) == 0 ) { - FT_Bitmap *b = &face->glyph->bitmap; - int dst_stride = ((b->width * ((flags & FT_LOAD_MONOCHROME) ? 1 : 8) + 31) / 32) * 4; - int src_stride = abs(b->pitch); + if ( FT_Load_Glyph (face, index, flags) != 0 ) + return NULL; + + if ( !( b = &face->glyph->bitmap)) + return NULL; + + src = b->buffer; + src_stride = abs(b->pitch); + +#define LINE_SIZE(width,type) (((( width ) * (( type ) & imBPP) + 31) / 32) * 4) + if ( b-> pixel_mode == FT_PIXEL_MODE_BGRA ) { + int y, dst_stride = LINE_SIZE(b->width, 24 ), mask_stride = LINE_SIZE(b->width, 8); + if ( ( ret = malloc( (dst_stride + mask_stride) * b->rows )) != NULL ) { + Byte *dst = ret, *mask = dst + dst_stride * b->rows; + if ( b->pitch > 0 ) { + dst += dst_stride * (b->rows - 1); + dst_stride = -dst_stride; + mask += mask_stride * (b->rows - 1); + mask_stride = -mask_stride; + } + + for ( + y = 0; + y < b->rows; + y++, dst += dst_stride, mask += mask_stride + ) { + register unsigned int n = b->width; + register Byte *d = dst, *m = mask; + while (n--) { + *(d++) = *(src++); + *(d++) = *(src++); + *(d++) = *(src++); + *(m++) = *(src++); + } + } + } + *bpp = 32; + } else { + int dst_stride = LINE_SIZE(b->width, (flags & FT_LOAD_MONOCHROME) ? 1 : 8); int bytes = (src_stride > dst_stride) ? dst_stride : src_stride; - Byte *src = b->buffer; - if ( b && ( ret = malloc( b->rows * dst_stride ))) { + if (( ret = malloc( b->rows * dst_stride )) != NULL) { int i; Byte *dst = ret; if ( b->pitch > 0 ) { @@ -259,17 +296,22 @@ prima_ft_get_glyph_bitmap( FT_Face face, FT_UInt index, FT_Int32 flags, PPoint o } for ( i = 0; i < b->rows; i++, src += src_stride, dst += dst_stride) memcpy( dst, src, bytes); + } + *bpp = (flags & FT_LOAD_MONOCHROME) ? 1 : 8; + } - offset->x = face->glyph->bitmap_left; - offset->y = face->glyph->bitmap_top - b->rows; - size->x = b->width; - size->y = b->rows; - if ( advance ) { - FT_Fixed a = face->glyph->linearHoriAdvance; - *advance = (a >> 16) + (((a & 0xffff) > 0x7fff) ? 1 : 0); - } + if ( ret ) { + offset->x = face->glyph->bitmap_left; + offset->y = face->glyph->bitmap_top - b->rows; + size->x = b->width; + size->y = b->rows; + if ( advance ) { + FT_Fixed a = face->glyph->linearHoriAdvance; + *advance = (a >> 16) + (((a & 0xffff) > 0x7fff) ? 1 : 0); } } +#undef LINE_SIZE + return ret; } @@ -392,6 +434,7 @@ prima_ft_is_font_colored( FT_Face face) FT_Library_Version(ft_library,&a,&b,&c); if ( a < 2 || ( a == 2 && b < 10 )) /* CPAL/COLR only supported in 2.10 */ return false; + return (FT_Load_Sfnt_Table(face, TTAG_COLR, 0, NULL, &l1) == 0) && (FT_Load_Sfnt_Table(face, TTAG_CPAL, 0, NULL, &l2) == 0) diff --git a/unix/xft.c b/unix/xft.c index 2ad70479..462f8d6e 100644 --- a/unix/xft.c +++ b/unix/xft.c @@ -1410,19 +1410,20 @@ prima_xft_get_glyph_outline( Handle self, unsigned int index, unsigned int flags } Byte* -prima_xft_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance) +prima_xft_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *bpp) { DEFXX; Byte *ret; FT_Face face; FT_Int32 ft_flags = FT_LOAD_RENDER | + (( flags & ggoARGB ) ? FT_LOAD_COLOR : 0) | (( flags & ggoUseHints ) ? 0 : FT_LOAD_NO_HINTING) | (( flags & ggoMonochrome ) ? FT_LOAD_MONOCHROME : 0) ; if ( !( face = XftLockFace( XX->font->xft))) return NULL; - ret = prima_ft_get_glyph_bitmap(face, index, ft_flags, offset, size, advance); + ret = prima_ft_get_glyph_bitmap(face, index, ft_flags, offset, size, advance, bpp); XftUnlockFace(XX->font->xft); return ret; }