From 60add37b51bf433b48fb18b00bf24822c8462e4f Mon Sep 17 00:00:00 2001 From: Dmitry Karasik Date: Sun, 24 Nov 2024 11:12:33 +0100 Subject: [PATCH] first show at plotting argb glyph outside paint --- class/Image/text.c | 22 ++++++-- img/glyph.c | 127 ++++++++++++++++++++++++++++++++++++++++----- include/apricot.h | 2 +- include/img_conv.h | 4 +- unix/font.c | 7 ++- win32/dwfont.c | 40 +++++++++++--- win32/text.c | 34 +++++++----- 7 files changed, 193 insertions(+), 43 deletions(-) diff --git a/class/Image/text.c b/class/Image/text.c index 098ef24e8..ca3a80d26 100644 --- a/class/Image/text.c +++ b/class/Image/text.c @@ -1,6 +1,6 @@ #include "apricot.h" #include "guts.h" -#include "Image.h" +#include "Icon.h" #include "Drawable_private.h" #include "Image_private.h" #include "img_conv.h" @@ -355,10 +355,21 @@ plot_next_glyph( size.x > 0 && size.y > 0 ) { - Image src_dummy; - img_fill_dummy( &src_dummy, size.x, size.y, - imGrayScale | ((flags & ggoMonochrome) ? 1 : 8), + Icon src_dummy; + img_fill_dummy((PImage) &src_dummy, size.x, size.y, + (( bpp == 32 ) ? 24 : bpp|imGrayScale), arena, NULL); + if ( bpp == 32 ) { + src_dummy.mask = arena + LINE_SIZE(size.x, 24) * size.y; + src_dummy.maskType = 8; + src_dummy.maskLine = LINE_SIZE(size.x, 8); + src_dummy.maskSize = src_dummy.maskLine * size.y; + } else { + src_dummy.mask = NULL; + src_dummy.maskType = 0; + src_dummy.maskLine = 0; + src_dummy.maskSize = 0; + } if ( downgrade_glyph ) { register Byte *s = arena; register unsigned int i = src_dummy.dataSize; @@ -436,6 +447,9 @@ plot_glyphs( Handle self, PGlyphsOutRec t, int x, int y ) } } + if ( var->type == imRGB && !(flags & ggoMonochrome) && !emulate_mono_alpha) + flags |= ggoARGB; + if ( !apc_gp_get_text_out_baseline( self)) { dy = var-> font. descent; y += dy; diff --git a/img/glyph.c b/img/glyph.c index 8717ad78d..01b848862 100644 --- a/img/glyph.c +++ b/img/glyph.c @@ -129,9 +129,9 @@ typedef struct PlotStruct PlotStruct; typedef void PlotFunc( int x, int y, int xFrom, int yFrom, int xLen, int yLen, PlotStruct *p); struct PlotStruct { - PImage src_image, dst_image; - Byte *src, *dst, *mask; - unsigned int src_stride, dst_stride, mask_stride; + PIcon src_image, dst_image; + Byte *src, *src_mask, *dst, *dst_mask; + unsigned int src_stride, src_mask_stride, dst_stride, dst_mask_stride; Byte *color; Rect r; @@ -236,7 +236,7 @@ plot_blend( int x, int y, int xFrom, int yFrom, int xLen, int yLen, PlotStruct * i = 0, s = p->src + yFrom * p->src_stride + xFrom, d = p->dst + y * p->dst_stride + x * p->bytes, - m = p->use_dst_alpha ? &p->dst_alpha : p->mask + y * p->mask_stride + x + m = p->use_dst_alpha ? &p->dst_alpha : p->dst_mask + y * p->dst_mask_stride + x ; i < yLen; i++, s += p->src_stride, d += p->dst_stride @@ -312,7 +312,98 @@ plot_blend( int x, int y, int xFrom, int yFrom, int xLen, int yLen, PlotStruct * #undef BLEND if ( !p->use_dst_alpha ) - m += p->mask_stride; + m += p->dst_mask_stride; + } +} + +static void +plot_argb( int x, int y, int xFrom, int yFrom, int xLen, int yLen, PlotStruct *p) +{ + int i; + Byte *s, *a, *d, *m; + Bool use_mbuf = p->blend2 && p->is_icon; + Byte buf1[768], buf2[768], buf3[256], sa = p->src_alpha; + + for ( + i = 0, + s = p->src + yFrom * p->src_stride + xFrom, + a = p->src_mask + yFrom * p->src_mask_stride + xFrom, + d = p->dst + y * p->dst_stride + x * p->bytes, + m = p->use_dst_alpha ? &p->dst_alpha : p->dst_mask + y * p->dst_mask_stride + x + ; + i < yLen; + i++, + s += p->src_stride, + a += p->src_mask_stride, + d += p->dst_stride + ) { + int pixels = xLen; + Bool curr = 0; + register Byte *ss = s, *dd = d, *mm = m, *aa = a; + while ( pixels > 0 ) { + if ( curr == 0 ) { + /* skip pixels */ + while ( pixels > 0 ) { + if ( *aa > 0 ) + goto FLIP; + dd += 3; + pixels--; + ss += 3; + aa ++; + if ( !p->use_dst_alpha ) mm++; + } + } else { + /* plot pixels */ +#define BLEND \ + if ( px1 > 0 ) { \ + p->blend1( buf1, 1, buf2, 1, dd, mm, 0, px1); \ + if ( use_mbuf ) \ + p->blend2( mmbuf, 1, mmbuf, 1, mm, mm, 0, px2);\ + dd += px1; \ + if ( !p->use_dst_alpha ) mm += px2; \ + } + while ( pixels > 0 ) { + register Byte + *xbuf = buf1, + *abuf = buf2, + *mbuf = use_mbuf ? buf3 : buf2; + Byte + *mmbuf = mbuf; + int + n = (sizeof(buf3) > pixels) ? pixels : (sizeof(buf3)), + px1 = 0, + px2 = 0; + while (n-- > 0) { + if ( *aa != 0 ) { + register Byte aaa = *aa++; + *xbuf++ = *ss++; + *xbuf++ = *ss++; + *xbuf++ = *ss++; + if ( sa < 255 ) + aaa = aaa * sa / 255; + *abuf++ = aaa; + *abuf++ = aaa; + *abuf++ = aaa; + if ( use_mbuf ) *mbuf++ = aaa; + px1 += 3; + px2 ++; + pixels--; + n--; + } else { + BLEND; + goto FLIP; + } + } + BLEND; + } + } + FLIP: + curr = !curr; + } +#undef BLEND + + if ( !p->use_dst_alpha ) + m += p->dst_mask_stride; } } @@ -361,16 +452,17 @@ rop_white( int rop ) Bool -img_plot_glyph( Handle self, PImage glyph, int x, int y, PImgPaintContext ctx) +img_plot_glyph( Handle self, PIcon glyph, int x, int y, PImgPaintContext ctx) { - PImage i = (PImage) self; + PIcon i = (PIcon) self; int w, h, rop = ctx->rop; Bool mono = (glyph->type & imBPP) == 1; + Bool argb = glyph->type == 24; PlotStruct rec = { glyph, i, - glyph->data, i->data, NULL, - glyph->lineSize, i->lineSize, 0, + glyph->data, NULL, i->data, NULL, + glyph->lineSize, 0, i->lineSize, 0, ctx->color, { x, y, x + glyph->w - 1, y + glyph->h - 1 } }; @@ -421,13 +513,24 @@ img_plot_glyph( Handle self, PImage glyph, int x, int y, PImgPaintContext ctx) warn("img_plot_glyph: cannot use antialiased text on 1-bit-mask icons"); return false; } - rec.mask = PIcon(self)->mask; - rec.mask_stride = PIcon(self)->maskLine; + rec.dst_mask = PIcon(self)->mask; + rec.dst_mask_stride = PIcon(self)->maskLine; } else if ( !rec.use_dst_alpha ) { rec.use_dst_alpha = true; rec.dst_alpha = 0xff; } - rec.func = plot_blend; + + if ( argb ) { + if ( i->type != imRGB ) { + warn("img_plot_glyph: cannot plot color glyphs on a non-color target"); + return false; + } + rec.src_mask = glyph->mask; + rec.src_mask_stride = glyph->maskLine; + rec.func = plot_argb; + } else + rec.func = plot_blend; + rec.bpp = i->type & imBPP; rec.bytes = rec.bpp / 8; } else { diff --git a/include/apricot.h b/include/apricot.h index 5395b5809..25e99973e 100644 --- a/include/apricot.h +++ b/include/apricot.h @@ -4328,7 +4328,7 @@ extern PTextShapeFunc apc_font_get_text_shaper( Handle self, int *type); extern Byte* -apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *type); +apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *bpp); extern Bool apc_font_is_colored( Handle self); diff --git a/include/img_conv.h b/include/img_conv.h index d6ab9bd26..f67fc622d 100644 --- a/include/img_conv.h +++ b/include/img_conv.h @@ -1,7 +1,7 @@ #ifndef _IMG_IMG_CONV_H_ #define _IMG_IMG_CONV_H_ #include "guts.h" -#include "Image.h" +#include "Icon.h" #include #include #ifdef HAVE_UNISTD_H @@ -345,7 +345,7 @@ extern Bool img_find_blend_proc( int rop, BlendFunc ** blend1, BlendFunc ** blen extern Bool img_resample_colors( Handle dest, int bpp, PImgPaintContext ctx); extern void img_fill_alpha_buf( Byte * dst, Byte * src, int width, int bpp); extern void img_multiply_alpha( Byte * src, Byte * alpha, int alpha_step, Byte * dst, int bytes); -extern Bool img_plot_glyph( Handle self, PImage glyph, int x, int y, PImgPaintContext ctx); +extern Bool img_plot_glyph( Handle self, PIcon glyph, int x, int y, PImgPaintContext ctx); extern Bool img_aafill( Handle self, NPoint *pts, int n_pts, int rule, PImgPaintContext ctx); typedef struct _NPolyPolyline { diff --git a/unix/font.c b/unix/font.c index 2337aea51..d78278d0c 100644 --- a/unix/font.c +++ b/unix/font.c @@ -803,12 +803,15 @@ apc_gp_get_mapper_ranges(PFont font, int * count, unsigned int * flags) } Byte* -apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *type) +apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *bpp) { + *bpp = (flags & ggoMonochrome) ? 1 : 8; + #ifdef USE_FONTQUERY if ( is_opt(optInFontQuery) ) { - if ( X(self)->font) + if ( X(self)->font) { return prima_fq_get_glyph_bitmap(self, index, flags, offset, size, advance); + } return NULL; } #endif diff --git a/win32/dwfont.c b/win32/dwfont.c index ed439019f..d1b94dd89 100644 --- a/win32/dwfont.c +++ b/win32/dwfont.c @@ -498,20 +498,44 @@ dwrite_draw_bitmap( Handle self, uint16_t index, Point size, Point aperture ) ExtTextOutW(dc, t->baseline.x, t->baseline.y, ETO_GLYPH_INDEX, NULL, (LPCWSTR) t->g.glyphs, 1, NULL); break; } - break; } list_delete_all( l, true ); plist_destroy( l ); - if ( ( ret = malloc( size.x * size.y * 4 )) != NULL ) { - register uint32_t *src = arena, *dst = ret, n = size.x * size.y; - while (n--) { - *(dst++) = (*src == 0xffffff) ? 0 : (*src | 0xff000000); - src++; + { +#define LINE_SIZE(width,type) (((( width ) * (( type ) & imBPP) + 31) / 32) * 4) + int dst_stride = LINE_SIZE( size.x, 24 ), mask_stride = LINE_SIZE( size.x, 8); +#undef LINE_SIZE + if ( ( ret = malloc( (dst_stride + mask_stride) * size.y )) != NULL ) { + int y; + Byte *dst, *mask; + register Byte *src; + + for ( + y = 0, dst = (Byte*) ret, mask = dst + dst_stride * size.y, src = (Byte*) arena; + y < size.y; + y++, dst += dst_stride, mask += mask_stride + ) { + register unsigned int n = size.x; + register Byte *d = dst, *m = mask; + while (n--) { + if (*src == 0xff) { + *(d++) = 0; + *(d++) = 0; + *(d++) = 0; + *(m++) = 0; + src += 4; + } else { + *(d++) = *(src++); + *(d++) = *(src++); + *(d++) = *(src++); + src++; + *(m++) = 0xff; + } + } } - memcpy( ret, arena, size.x * size.y * 4); - } + }} SelectObject(dc, save_bitmap); SelectObject(dc, save_font); diff --git a/win32/text.c b/win32/text.c index 5bc562f79..bc90c9f1f 100644 --- a/win32/text.c +++ b/win32/text.c @@ -2265,7 +2265,7 @@ apc_font_end_query( Handle self ) } Byte* -apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *type) +apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoint offset, PPoint size, int *advance, int *bpp) { int gdi_size; Byte * gdi_buf; @@ -2297,13 +2297,26 @@ apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoi offset-> y =-gm.gmptGlyphOrigin.y; if ( gdi_size == 0 ) size-> x = size-> y = 0; + if ( advance ) { + ABC x; + if (GetCharABCWidthsI( sys ps, index, 1, NULL, &x)) { + *advance = x.abcA + x.abcB + x.abcC; + } else { + *advance = gm.gmCellIncX; + apiErr; + } + } if ( + (gdi_size > 0) && !(flags & ggoMonochrome) && (flags & ggoARGB) && - apc_font_is_colored + apc_font_is_colored(self) ) { - //dwrite_draw_bitmap( self, index, *size, *offset); + if (( gdi_buf = (Byte*) dwrite_draw_bitmap( self, index, *size, *offset)) != NULL) { + *bpp = 32; + return gdi_buf; + } } if (( gdi_buf = malloc(gdi_size)) == NULL ) { @@ -2317,23 +2330,16 @@ apc_font_get_glyph_bitmap( Handle self, uint16_t index, unsigned int flags, PPoi return NULL; } - if ( advance ) { - ABC x; - if (GetCharABCWidthsI( sys ps, index, 1, NULL, &x)) { - *advance = x.abcA + x.abcB + x.abcC; - } else { - *advance = gm.gmCellIncX; - apiErr; - } - } - - if ( !( flags & ggoMonochrome)) { + if ( flags & ggoMonochrome) { + *bpp = 1; + } else { register Byte* buf = gdi_buf; register unsigned int bytes = size->y * (( size->x * 8 + 31) / 32) * 4; while (bytes--) { *buf = *buf * 3.984 + .5; /* 255/64 */ buf++; } + *bpp = 8; } return gdi_buf;