[smooth] Use direct rendering mode in Harmony. Instead of rendering 3 bitmaps side by side and reshuffling, we use direct rendering to deliver the bitmaps on each third byte. * src/smooth/ftsmooth.c (ft_smooth_raster_lcd) [!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Set up direct mode with... (ft_smooth_lcd_spans): ... new span function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
diff --git a/ChangeLog b/ChangeLog
index 9af7080..f5045de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2020-07-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+ [smooth] Use direct rendering mode in Harmony.
+
+ Instead of rendering 3 bitmaps side by side and reshuffling, we use
+ direct rendering to deliver the bitmaps on each third byte.
+
+ * src/smooth/ftsmooth.c (ft_smooth_raster_lcd)
+ [!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Set up direct mode with...
+ (ft_smooth_lcd_spans): ... new span function.
+
+2020-07-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
[smooth] Separate LCD paths from gray rendering.
This makes `ft_smooth_render' a lot smaller and easier to follow. It
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 945ff80..1e0d0a3 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -76,6 +76,13 @@
FT_Outline_Get_CBox( &slot->outline, cbox );
}
+ typedef struct TOrigin_
+ {
+ unsigned char* origin; /* pixmap origin at the bottom-left */
+ int pitch; /* pitch to go down one row */
+
+ } TOrigin;
+
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
/* initialize renderer -- init its raster */
@@ -99,24 +106,58 @@
}
+ /* This function writes every third byte in direct rendering mode */
+ static void
+ ft_smooth_lcd_spans( int y,
+ int count,
+ const FT_Span* spans,
+ TOrigin* target )
+ {
+ unsigned char* dst_line = target->origin - y * target->pitch;
+ unsigned char* dst;
+ unsigned short w;
+
+
+ for ( ; count--; spans++ )
+ for ( dst = dst_line + spans->x * 3, w = spans->len; w--; dst += 3 )
+ *dst = spans->coverage;
+ }
+
+
static FT_Error
ft_smooth_raster_lcd( FT_Renderer render,
FT_Outline* outline,
FT_Bitmap* bitmap )
{
FT_Error error = FT_Err_Ok;
- unsigned int width = bitmap->width / 3;
FT_Vector* sub = render->root.library->lcd_geometry;
FT_Pos x, y;
FT_Raster_Params params;
+ TOrigin target;
- params.target = bitmap;
- params.source = outline;
- params.flags = FT_RASTER_FLAG_AA;
-
/* Render 3 separate coverage bitmaps, shifting the outline. */
+ /* Set up direct rendering to record them on each third byte. */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
+ params.gray_spans = (FT_SpanFunc)ft_smooth_lcd_spans;
+ params.user = ⌖
+
+ params.clip_box.xMin = 0;
+ params.clip_box.yMin = 0;
+ params.clip_box.xMax = bitmap->width;
+ params.clip_box.yMax = bitmap->rows;
+
+ if ( bitmap->pitch < 0 )
+ target.origin = bitmap->buffer;
+ else
+ target.origin = bitmap->buffer
+ + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch;
+
+ target.pitch = bitmap->pitch;
+
FT_Outline_Translate( outline,
-sub[0].x,
-sub[0].y );
@@ -126,57 +167,23 @@
if ( error )
goto Exit;
- bitmap->buffer += width;
+ target.origin++;
FT_Outline_Translate( outline,
sub[0].x - sub[1].x,
sub[0].y - sub[1].y );
error = render->raster_render( render->raster, ¶ms );
x = sub[1].x;
y = sub[1].y;
- bitmap->buffer -= width;
if ( error )
goto Exit;
- bitmap->buffer += 2 * width;
+ target.origin++;
FT_Outline_Translate( outline,
sub[1].x - sub[2].x,
sub[1].y - sub[2].y );
error = render->raster_render( render->raster, ¶ms );
x = sub[2].x;
y = sub[2].y;
- bitmap->buffer -= 2 * width;
- if ( error )
- goto Exit;
-
- /* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */
- /* XXX: It is more efficient to render every third byte above. */
- {
- FT_Memory memory = render->root.memory;
- FT_Byte* line;
- FT_Byte* temp = NULL;
- FT_UInt i, j;
-
- unsigned int height = bitmap->rows;
- int pitch = bitmap->pitch;
-
-
- if ( FT_ALLOC( temp, (FT_ULong)pitch ) )
- goto Exit;
-
- for ( i = 0; i < height; i++ )
- {
- line = bitmap->buffer + i * (FT_ULong)pitch;
- for ( j = 0; j < width; j++ )
- {
- temp[3 * j ] = line[j];
- temp[3 * j + 1] = line[j + width];
- temp[3 * j + 2] = line[j + width + width];
- }
- FT_MEM_COPY( line, temp, pitch );
- }
-
- FT_FREE( temp );
- }
Exit:
FT_Outline_Translate( outline, x, y );