summaryrefslogtreecommitdiff
path: root/src/smooth
diff options
context:
space:
mode:
authorAlexei Podtelezhnikov <apodtele@gmail.com>2020-07-03 22:29:34 -0400
committerAlexei Podtelezhnikov <apodtele@gmail.com>2020-07-03 22:29:34 -0400
commit3bb512bc9f621e1329927292d9ee7ba764549cae (patch)
tree573161e8dc324a31a623d7bdecf3042b47ff8779 /src/smooth
parent19d39f43d25b375767b40b26aac7b2061d321ae2 (diff)
downloadfreetype2-3bb512bc9f621e1329927292d9ee7ba764549cae.tar.gz
[smooth] Introduce direct oversampling for overlaps.
This implements oversampling to metigate artifacts in pixels partially covered by overlapping contours. It turns out that the 4x4 oversampling is sufficient but, at least, quadruples the rendering time. The outline has to set FT_OUTLINE_OVERLAP to use this method. * include/freetype/ftimage.h (FT_OUTLINE_OVERLAP): New flag. * src/smooth/ftsmooth.c (ft_smooth_render): Check it to... (ft_smooth_raster_overlap): ... inflate outline and set up direct rendering for oversampling with... (ft_smooth_overlap_spans): ... new span function that integrates them.
Diffstat (limited to 'src/smooth')
-rw-r--r--src/smooth/ftsmooth.c104
1 files changed, 98 insertions, 6 deletions
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 1e0d0a3e3..b32629205 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -333,7 +333,94 @@
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /* convert a slot's glyph image into a bitmap */
+/* Oversampling scale to be used in rendering overlaps */
+#define SCALE ( 1 << 2 )
+
+ /* This function averages inflated spans in direct rendering mode */
+ static void
+ ft_smooth_overlap_spans( int y,
+ int count,
+ const FT_Span* spans,
+ TOrigin* target )
+ {
+ unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch;
+ unsigned short x;
+ unsigned int cover, sum;
+
+
+ /* When accumulating the oversampled spans we need to assure that */
+ /* fully covered pixels are equal to 255 and do not overflow. */
+ /* It is important that the SCALE is a power of 2, each subpixel */
+ /* cover can also reach a power of 2 after rounding, and the total */
+ /* is clamped to 255 when it adds up to 256. */
+ for ( ; count--; spans++ )
+ {
+ cover = ( spans->coverage + SCALE * SCALE / 2 ) / ( SCALE * SCALE );
+ for ( x = 0; x < spans->len; x++ )
+ {
+ sum = dst[ ( spans->x + x ) / SCALE ] + cover;
+ dst[ ( spans->x + x ) / SCALE ] = sum - ( sum >> 8 );
+ }
+ }
+ }
+
+
+ static FT_Error
+ ft_smooth_raster_overlap( FT_Renderer render,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Vector* points = outline->points;
+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
+ FT_Vector* vec;
+
+ FT_Raster_Params params;
+ TOrigin target;
+
+
+ /* Set up direct rendering to average oversampled spans. */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
+ params.gray_spans = (FT_SpanFunc)ft_smooth_overlap_spans;
+ params.user = &target;
+
+ params.clip_box.xMin = 0;
+ params.clip_box.yMin = 0;
+ params.clip_box.xMax = bitmap->width * SCALE;
+ params.clip_box.yMax = bitmap->rows * SCALE;
+
+ if ( bitmap->pitch < 0 )
+ target.origin = bitmap->buffer;
+ else
+ target.origin = bitmap->buffer
+ + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch;
+
+ target.pitch = bitmap->pitch;
+
+ /* inflate outline */
+ for ( vec = points; vec < points_end; vec++ )
+ {
+ vec->x *= SCALE;
+ vec->y *= SCALE;
+ }
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, &params );
+
+ /* deflate outline */
+ for ( vec = points; vec < points_end; vec++ )
+ {
+ vec->x /= SCALE;
+ vec->y /= SCALE;
+ }
+
+ return error;
+ }
+
+#undef SCALE
+
static FT_Error
ft_smooth_render( FT_Renderer render,
FT_GlyphSlot slot,
@@ -407,14 +494,19 @@
if ( mode == FT_RENDER_MODE_NORMAL ||
mode == FT_RENDER_MODE_LIGHT )
{
- FT_Raster_Params params;
+ if ( outline->flags & FT_OUTLINE_OVERLAP )
+ error = ft_smooth_raster_overlap( render, outline, bitmap );
+ else
+ {
+ FT_Raster_Params params;
- params.target = bitmap;
- params.source = outline;
- params.flags = FT_RASTER_FLAG_AA;
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA;
- error = render->raster_render( render->raster, &params );
+ error = render->raster_render( render->raster, &params );
+ }
}
else
{