From 953b3682b69b438ce7e6827628909788da25c373 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Tue, 11 Dec 2018 23:22:15 -0500 Subject: [PATCH] Color glyph framework and rendering (3/3). * include/freetype/config/ftmodule.h, src/smooth/module.mk: Register color renderer. * include/freetype/freetype.h (FT_RENDER_MODE_BGRA): Introduce it. * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Handle BGRA mode. * src/smooth/ftsmooth.c (ft_smooth_render_bgra): Implement it. (ft_smooth_bgra_renderer_class): Define it. * src/smooth/ftsmooth.h: Declare it. --- ChangeLog | 12 +++ include/freetype/config/ftmodule.h | 1 + include/freetype/freetype.h | 6 ++ src/base/ftobjs.c | 8 ++ src/smooth/ftsmooth.c | 137 +++++++++++++++++++++++++++++ src/smooth/ftsmooth.h | 2 + src/smooth/module.mk | 2 + 7 files changed, 168 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4242a2179..47bd88705 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2018-12-11 Alexei Podtelezhnikov + + Color glyph framework and rendering (3/3). + + * include/freetype/config/ftmodule.h, src/smooth/module.mk: + Register color renderer. + * include/freetype/freetype.h (FT_RENDER_MODE_BGRA): Introduce it. + * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Handle BGRA mode. + * src/smooth/ftsmooth.c (ft_smooth_render_bgra): Implement it. + (ft_smooth_bgra_renderer_class): Define it. + * src/smooth/ftsmooth.h: Declare it. + 2018-12-11 Alexei Podtelezhnikov Color glyph framework and rendering (2/3). diff --git a/include/freetype/config/ftmodule.h b/include/freetype/config/ftmodule.h index 7c603e532..e3924e658 100644 --- a/include/freetype/config/ftmodule.h +++ b/include/freetype/config/ftmodule.h @@ -27,6 +27,7 @@ FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_bgra_renderer_class ) FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) /* EOF */ diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index 9398f39ee..7e054b0bc 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -3239,6 +3239,11 @@ FT_BEGIN_HEADER * bitmaps that are 3~times the height of the original glyph outline in * pixels and use the @FT_PIXEL_MODE_LCD_V mode. * + * FT_RENDER_MODE_BGRA :: + * This mode is intended for rendering color layered glyphs. It + * produces 32-bit premultiplied color images using @FT_PIXEL_MODE_BGRA + * mode. + * * @note: * Should you define `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` in your * `ftoption.h`, which enables patented ClearType-style rendering, the @@ -3260,6 +3265,7 @@ FT_BEGIN_HEADER FT_RENDER_MODE_MONO, FT_RENDER_MODE_LCD, FT_RENDER_MODE_LCD_V, + FT_RENDER_MODE_BGRA, FT_RENDER_MODE_MAX diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 9022d2536..9358b5f24 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -441,6 +441,10 @@ ft_lcd_padding( &cbox, slot, mode ); goto Adjust; + case FT_RENDER_MODE_BGRA: + pixel_mode = FT_PIXEL_MODE_BGRA; + goto Adjust; + case FT_RENDER_MODE_NORMAL: case FT_RENDER_MODE_LIGHT: default: @@ -469,6 +473,10 @@ pitch = FT_PAD_CEIL( width, 4 ); break; + case FT_PIXEL_MODE_BGRA: + pitch = 4 * width; + break; + case FT_PIXEL_MODE_LCD_V: height *= 3; /* fall through */ diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c index cdae25391..44ceb09ed 100644 --- a/src/smooth/ftsmooth.c +++ b/src/smooth/ftsmooth.c @@ -20,6 +20,7 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_OBJECTS_H #include FT_OUTLINE_H +#include FT_BITMAP_H #include "ftsmooth.h" #include "ftgrays.h" @@ -419,6 +420,115 @@ } + /* convert a slot image into a BGRA bitmap using supplemental color array */ + static FT_Error + ft_smooth_render_bgra( FT_Renderer render, + FT_GlyphSlot slot, + FT_Render_Mode mode, + const FT_Vector* origin ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = render->root.memory; + FT_Outline outline = slot->outline; /* hard copy */ + FT_Bitmap target; + FT_Vector target_offset, offset; + short i, c_done, p_done; + + + /* check glyph image format */ + if ( slot->format != render->glyph_format ) + return FT_THROW( Invalid_Argument ); + + /* check mode */ + if ( mode != FT_RENDER_MODE_BGRA || + slot->color == NULL ) + return FT_THROW( Cannot_Render_Glyph ); + + /* release old bitmap buffer */ + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( slot->bitmap.buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + + if ( ft_glyphslot_preset_bitmap( slot, mode, origin ) ) + return FT_THROW( Raster_Overflow ); + + target = slot->bitmap; + target_offset.x = slot->bitmap_left * 64; + target_offset.y = slot->bitmap_top * 64; + + /* allocate new one */ + if ( FT_ALLOC_MULT( target.buffer, target.rows, target.pitch ) ) + goto Exit; + + c_done = 0; + p_done = 0; + for ( i = 0; i < outline.n_contours; i++ ) + { + /* grow layer */ + slot->outline.n_contours = i - c_done + 1; + slot->outline.n_points = outline.contours[i] - p_done + 1; + slot->outline.contours[i - c_done] = outline.contours[i] - p_done; + + if ( i == outline.n_contours - 1 || + slot->color[i + 1].red != slot->color[c_done].red || + slot->color[i + 1].green != slot->color[c_done].green || + slot->color[i + 1].blue != slot->color[c_done].blue || + slot->color[i + 1].alpha != slot->color[c_done].alpha ) + { + /* render layer */ + error = ft_smooth_render( render, + slot, + FT_RENDER_MODE_NORMAL, + origin ); + if ( error ) + break; + + /* blend layer */ + offset.x = slot->bitmap_left * 64; + offset.y = slot->bitmap_top * 64; + error = FT_Bitmap_Blend( slot->library, + &slot->bitmap, + offset, + &target, + &target_offset, + slot->color[c_done] ); + + if ( error ) + break; + + c_done += slot->outline.n_contours; + p_done += slot->outline.n_points; + + /* start next layer */ + slot->outline.contours = outline.contours + c_done; + slot->outline.points = outline.points + p_done; + slot->outline.tags = outline.tags + p_done; + + slot->format = FT_GLYPH_FORMAT_OUTLINE; + } + } + + /* restore pointers so that they can be freed */ + slot->outline.contours = outline.contours; + slot->outline.points = outline.points; + slot->outline.tags = outline.tags; + + if ( !error ) + { + FT_FREE( slot->bitmap.buffer ); + slot->bitmap = target; + slot->bitmap_left = target_offset.x >> 6; + slot->bitmap_top = target_offset.y >> 6; + slot->format = FT_GLYPH_FORMAT_BITMAP; + } + + Exit: + return error; + } + + FT_DEFINE_RENDERER( ft_smooth_renderer_class, @@ -500,4 +610,31 @@ ) + FT_DEFINE_RENDERER( + ft_smooth_bgra_renderer_class, + + FT_MODULE_RENDERER, + sizeof ( FT_RendererRec ), + + "smooth-bgra", + 0x10000L, + 0x20000L, + + NULL, /* module specific interface */ + + (FT_Module_Constructor)ft_smooth_init, /* module_init */ + (FT_Module_Destructor) NULL, /* module_done */ + (FT_Module_Requester) NULL, /* get_interface */ + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Renderer_RenderFunc) ft_smooth_render_bgra, /* render_glyph */ + (FT_Renderer_TransformFunc)ft_smooth_transform, /* transform_glyph */ + (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, /* get_glyph_cbox */ + (FT_Renderer_SetModeFunc) ft_smooth_set_mode, /* set_mode */ + + (FT_Raster_Funcs*)&ft_grays_raster /* raster_class */ + ) + + /* END */ diff --git a/src/smooth/ftsmooth.h b/src/smooth/ftsmooth.h index 782f11a60..6b67a6a3e 100644 --- a/src/smooth/ftsmooth.h +++ b/src/smooth/ftsmooth.h @@ -33,6 +33,8 @@ FT_BEGIN_HEADER FT_DECLARE_RENDERER( ft_smooth_lcdv_renderer_class ) + FT_DECLARE_RENDERER( ft_smooth_bgra_renderer_class ) + FT_END_HEADER diff --git a/src/smooth/module.mk b/src/smooth/module.mk index 5b8bc3be3..1898f914f 100644 --- a/src/smooth/module.mk +++ b/src/smooth/module.mk @@ -22,6 +22,8 @@ $(OPEN_DRIVER) FT_Renderer_Class, ft_smooth_lcd_renderer_class $(CLOSE_DRIVER) $(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer for LCDs$(ECHO_DRIVER_DONE) $(OPEN_DRIVER) FT_Renderer_Class, ft_smooth_lcdv_renderer_class $(CLOSE_DRIVER) $(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer for vertical LCDs$(ECHO_DRIVER_DONE) +$(OPEN_DRIVER) FT_Renderer_Class, ft_smooth_bgra_renderer_class $(CLOSE_DRIVER) +$(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)color bitmap renderer for layered glyphs$(ECHO_DRIVER_DONE) endef # EOF