Fix quadratic rendering

This commit is contained in:
Anurag Thakur 2022-07-17 17:08:14 +05:30
parent 8af62c3469
commit d9c301d35a
1 changed files with 97 additions and 92 deletions

View File

@ -4,11 +4,11 @@
#undef FT_COMPONENT #undef FT_COMPONENT
#define FT_COMPONENT dense #define FT_COMPONENT dense
#include "ftdense.h"
#include <freetype/ftoutln.h> #include <freetype/ftoutln.h>
#include <freetype/internal/ftcalc.h> #include <freetype/internal/ftcalc.h>
#include <freetype/internal/ftdebug.h> #include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h> #include <freetype/internal/ftobjs.h>
#include "ftdense.h"
#include <math.h> #include <math.h>
#include "ftdenseerrs.h" #include "ftdenseerrs.h"
@ -17,20 +17,17 @@
#define PIXEL_BITS 8 #define PIXEL_BITS 8
#define ONE_PIXEL ( 1 << PIXEL_BITS ) #define ONE_PIXEL ( 1 << PIXEL_BITS )
#define TRUNC( x ) ( int )( ( x ) >> PIXEL_BITS ) #define TRUNC( x ) (int)( ( x ) >> PIXEL_BITS )
#define UPSCALE( x ) ( ( x ) * ( ONE_PIXEL >> 6 ) ) #define UPSCALE( x ) ( ( x ) * ( ONE_PIXEL >> 6 ) )
#define DOWNSCALE( x ) ( ( x ) >> ( PIXEL_BITS - 6 ) ) #define DOWNSCALE( x ) ( ( x ) >> ( PIXEL_BITS - 6 ) )
typedef struct dense_TRaster_ typedef struct dense_TRaster_
{ {
void* memory; void* memory;
} dense_TRaster, *dense_PRaster; } dense_TRaster, *dense_PRaster;
static RasterFP_Point static RasterFP_Point
Lerp( float aT, RasterFP_Point aP0, RasterFP_Point aP1 ) Lerp( float aT, RasterFP_Point aP0, RasterFP_Point aP1 )
{ {
@ -49,29 +46,33 @@ dense_move_to( const FT_Vector* to, RasterFP* aRasterFP )
y = UPSCALE( to->y ); y = UPSCALE( to->y );
aRasterFP->prev_x = x; aRasterFP->prev_x = x;
aRasterFP->prev_y = y; aRasterFP->prev_y = y;
//printf( "last point is {%f, %f}", lp.m_x, lp.m_y ); // printf( "last point is {%f, %f}", lp.m_x, lp.m_y );
return 0; return 0;
} }
static int static int
dense_line_to( const FT_Vector* to, RasterFP* aRasterFP ) dense_line_to( const FT_Vector* to, RasterFP* aRasterFP )
{ {
printf("dense_line_to: %d, %d\n", to->x, to->y); printf( "dense_line_to: %d, %d\n", to->x, to->y );
RasterFP_Point tp = {UPSCALE(to->x), UPSCALE(to->y)}; RasterFP_Point tp = { UPSCALE( to->x ), UPSCALE( to->y ) };
RasterFP_DrawLine( aRasterFP, tp.m_x, tp.m_y ); RasterFP_DrawLine( aRasterFP, tp.m_x, tp.m_y );
dense_move_to( to, aRasterFP ); dense_move_to( to, aRasterFP );
return 0; return 0;
} }
void swap(long int *a, long int *b){ void
swap( long int* a, long int* b )
{
long int temp = *a; long int temp = *a;
*a = *b; *a = *b;
*b = temp; *b = temp;
} }
void swapold(unsigned char *a, unsigned char *b){ void
swapold( unsigned char* a, unsigned char* b )
{
unsigned char temp = *a; unsigned char temp = *a;
*a = *b; *a = *b;
*b = temp; *b = temp;
} }
void void
@ -88,19 +89,19 @@ RasterFP_DrawLine( RasterFP* aRasterFP, TPos to_x, TPos to_y )
// aP1.m_x -= aRasterFP->m_origin_x; // aP1.m_x -= aRasterFP->m_origin_x;
// aP1.m_y -= aRasterFP->m_origin_y; // aP1.m_y -= aRasterFP->m_origin_y;
from_x = TRUNC((int)from_x ); from_x = TRUNC( (int)from_x );
from_y = TRUNC((int)from_y ); from_y = TRUNC( (int)from_y );
to_x = TRUNC((int)to_x ); to_x = TRUNC( (int)to_x );
to_y = TRUNC((int)to_y ); to_y = TRUNC( (int)to_y );
float dir; float dir;
if ( from_y < to_y ) if ( from_y < to_y )
dir = 1; dir = 1;
else else
{ {
dir = -1; dir = -1;
swap(&from_x, &to_x); swap( &from_x, &to_x );
swap(&from_y, &to_y); swap( &from_y, &to_y );
} }
// Clip to the height. // Clip to the height.
@ -125,21 +126,21 @@ RasterFP_DrawLine( RasterFP* aRasterFP, TPos to_x, TPos to_y )
by recursive calls. by recursive calls.
*/ */
/* @QUES: This code isn't present in font-rs. It was added later by graham asher /* @QUES: This code isn't present in font-rs. It was added later by graham
I have a very strong feeling that this isn't necessary. asher I have a very strong feeling that this isn't necessary. Since probably
Since probably the outline is already fitted in the bounding box. I tested the outline is already fitted in the bounding box. I tested this code a
this code a little, removing it doesn't seem to make any difference*/ little, removing it doesn't seem to make any difference*/
RasterFP_Point intersect = { 0, 0 }; RasterFP_Point intersect = { 0, 0 };
int recursive = 0; int recursive = 0;
if ( from_x >= aRasterFP->m_w && to_x >= aRasterFP->m_w ) if ( from_x >= aRasterFP->m_w && to_x >= aRasterFP->m_w )
{ {
from_x = to_x = (float)aRasterFP->m_w; from_x = to_x = (float)aRasterFP->m_w;
dxdy = 0; dxdy = 0;
} }
else if ( from_x <= 0 && to_x <= 0 ) else if ( from_x <= 0 && to_x <= 0 )
{ {
from_x = to_x = 0; from_x = to_x = 0;
dxdy = 0; dxdy = 0;
} }
else if ( ( from_x < 0 ) != ( to_x < 0 ) ) else if ( ( from_x < 0 ) != ( to_x < 0 ) )
{ {
@ -180,7 +181,6 @@ RasterFP_DrawLine( RasterFP* aRasterFP, TPos to_x, TPos to_y )
int y_limit = (int)ceil( to_y ); int y_limit = (int)ceil( to_y );
float* m_a = aRasterFP->m_a; float* m_a = aRasterFP->m_a;
for ( int y = y0; y < y_limit; y++ ) for ( int y = y0; y < y_limit; y++ )
{ {
int linestart = y * aRasterFP->m_w; int linestart = y * aRasterFP->m_w;
@ -254,11 +254,10 @@ dense_conic_to( const FT_Vector* control,
} }
void void
RasterFP_DrawQuadratic( RasterFP* aRasterFP, RasterFP_DrawQuadratic( RasterFP* aRasterFP,
const FT_Vector* control, const FT_Vector* control,
const FT_Vector* to ) const FT_Vector* to )
{ {
// assert( aRasterFP ); // assert( aRasterFP );
/* /*
Calculate devsq as the square of four times the Calculate devsq as the square of four times the
@ -272,21 +271,23 @@ RasterFP_DrawQuadratic( RasterFP* aRasterFP,
The division by four is omitted to save time. The division by four is omitted to save time.
*/ */
RasterFP_Point aP0 = {aRasterFP->prev_x, aRasterFP->prev_y}; RasterFP_Point aP0 = { aRasterFP->prev_x, aRasterFP->prev_y };
RasterFP_Point aP1 = {UPSCALE(control->x), UPSCALE(control->y)}; RasterFP_Point aP1 = { UPSCALE( control->x ), UPSCALE( control->y ) };
RasterFP_Point aP2 = {UPSCALE(to->x), UPSCALE(to->y)}; RasterFP_Point aP2 = { UPSCALE( to->x ), UPSCALE( to->y ) };
float devx = aP0.m_x - aP1.m_x - aP1.m_x + aP2.m_x; float devx = aP0.m_x - aP1.m_x - aP1.m_x + aP2.m_x;
float devy = aP0.m_y - aP1.m_y - aP1.m_y + aP2.m_y; float devy = aP0.m_y - aP1.m_y - aP1.m_y + aP2.m_y;
float devsq = devx * devx + devy * devy; float devsq = devx * devx + devy * devy;
if ( devsq < 0.333f ) if ( devsq < 0.333f )
{ {
RasterFP_DrawLine(aRasterFP, aP2.m_x, aP2.m_y ); RasterFP_DrawLine( aRasterFP, aP2.m_x, aP2.m_y );
aRasterFP->prev_x = aP2.m_x;
aRasterFP->prev_y = aP2.m_y;
return; return;
} }
/* /*
According to Raph Levien, the reason for the subdivision by n (instead of According to Raph Levien, the reason for the subdivision by n (instead of
@ -298,20 +299,25 @@ RasterFP_DrawQuadratic( RasterFP* aRasterFP,
expected to be 33% more in the limit". expected to be 33% more in the limit".
*/ */
const float tol = 3.0f; const float tol = 3.0f;
int n = (int)floor( sqrt( sqrt( tol * devsq ) ) ); int n = (int)floor( sqrt( sqrt( tol * devsq ) ) );
// RasterFP_Point p = aP0; RasterFP_Point p = aP0;
float nrecip = 1.0f / ( n + 1.0f ); float nrecip = 1.0f / ( n + 1.0f );
float t = 0.0f; float t = 0.0f;
for ( int i = 0; i < n; i++ ) for ( int i = 0; i < n; i++ )
{ {
t += nrecip; t += nrecip;
RasterFP_Point next = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) ); RasterFP_Point next = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) );
RasterFP_DrawLine(aRasterFP , next.m_x, next.m_y); RasterFP_DrawLine( aRasterFP, next.m_x, next.m_y );
//p = next; aRasterFP->prev_x = next.m_x;
aRasterFP->prev_y = next.m_y;
p = next;
} }
RasterFP_DrawLine( aRasterFP, aP2.m_x, aP2.m_y); RasterFP_DrawLine(aRasterFP,aP2.m_x,aP2.m_y);
aRasterFP->prev_x = aP2.m_x;
aRasterFP->prev_y = aP2.m_y;
} }
static int static int
@ -320,11 +326,11 @@ dense_cubic_to( const FT_Vector* control1,
const FT_Vector* to, const FT_Vector* to,
RasterFP* aRasterFP ) RasterFP* aRasterFP )
{ {
RasterFP_Point ap1 = { UPSCALE(control1->x), UPSCALE(control1->y) }; RasterFP_Point ap1 = { UPSCALE( control1->x ), UPSCALE( control1->y ) };
RasterFP_Point ap2 = { UPSCALE(control2->x), UPSCALE(control2->y) }; RasterFP_Point ap2 = { UPSCALE( control2->x ), UPSCALE( control2->y ) };
RasterFP_Point ap3 = { UPSCALE(to->x), UPSCALE(to->y) }; RasterFP_Point ap3 = { UPSCALE( to->x ), UPSCALE( to->y ) };
RasterFP_Point lP = {aRasterFP->prev_x, aRasterFP->prev_y}; RasterFP_Point lP = { aRasterFP->prev_x, aRasterFP->prev_y };
RasterFP_DrawCubic( aRasterFP, lP, ap1, ap2, ap3 ); RasterFP_DrawCubic( aRasterFP, lP, ap1, ap2, ap3 );
return 0; return 0;
@ -349,7 +355,7 @@ RasterFP_DrawCubic( RasterFP* aRasterFP,
if ( devsq < 0.333f ) if ( devsq < 0.333f )
{ {
RasterFP_DrawLine( aRasterFP, aP3.m_x , aP3.m_y); RasterFP_DrawLine( aRasterFP, aP3.m_x, aP3.m_y );
return; return;
} }
@ -383,7 +389,7 @@ dense_raster_new( FT_Memory memory, dense_PRaster* araster )
raster->memory = memory; raster->memory = memory;
*araster = raster; *araster = raster;
printf("dense_raster_new\n"); printf( "dense_raster_new\n" );
return error; return error;
} }
@ -406,7 +412,7 @@ dense_raster_reset( FT_Raster raster,
FT_UNUSED( raster ); FT_UNUSED( raster );
FT_UNUSED( pool_base ); FT_UNUSED( pool_base );
FT_UNUSED( pool_size ); FT_UNUSED( pool_size );
printf("dense_raster_reset\n"); printf( "dense_raster_reset\n" );
} }
/* @QUES: This methodisnt't called in normal ftlint execution*/ /* @QUES: This methodisnt't called in normal ftlint execution*/
@ -417,7 +423,7 @@ dense_raster_set_mode( FT_Raster raster, unsigned long mode, void* args )
FT_UNUSED( mode ); FT_UNUSED( mode );
FT_UNUSED( args ); FT_UNUSED( args );
printf("dense_raster_set_mode\n"); printf( "dense_raster_set_mode\n" );
return 0; /* nothing to do */ return 0; /* nothing to do */
} }
@ -432,10 +438,9 @@ FT_DEFINE_OUTLINE_FUNCS( dense_decompose_funcs,
0 /* delta */ 0 /* delta */
) )
/* @QUES: So, this calls FT_Outline_Decompose, that calls the move to,
/* @QUES: So, this calls FT_Outline_Decompose, that calls the move to, line to, conic to, cubic to interface methods. The aRasterFP structure stores
line to, conic to, cubic to interface methods. The aRasterFP structure stores the the well, stuff in its m_a and finally renders it to the target->buffer*/
well, stuff in its m_a and finally renders it to the target->buffer*/
static int static int
dense_render_glyph( RasterFP* aRasterFP, const FT_Bitmap* target ) dense_render_glyph( RasterFP* aRasterFP, const FT_Bitmap* target )
{ {
@ -444,37 +449,36 @@ dense_render_glyph( RasterFP* aRasterFP, const FT_Bitmap* target )
// Render into bitmap // Render into bitmap
const float* source = aRasterFP->m_a; const float* source = aRasterFP->m_a;
// printf( "Outputting bitmap\n" );
//printf( "Outputting bitmap\n" ); // for ( int i = 0; i < aRasterFP->m_h; i++ )
// for ( int i = 0; i < aRasterFP->m_h; i++ ) // {
// { // printf( "\n" );
// printf( "\n" ); // for ( int j = 0; j < aRasterFP->m_w; j++ )
// for ( int j = 0; j < aRasterFP->m_w; j++ ) // {
// { // float strength = *( source + ( i * aRasterFP->m_w + j ) );
// float strength = *( source + ( i * aRasterFP->m_w + j ) ); // if ( strength > 0.90 )
// if ( strength > 0.90 ) // {
// { // printf( "@|" );
// printf( "@|" ); // }
// } // else if ( strength > 0.70 )
// else if ( strength > 0.70 ) // {
// { // printf( "#|" );
// printf( "#|" ); // }
// } // else if ( strength > 0.45 )
// else if ( strength > 0.45 ) // {
// { // printf( "+|" );
// printf( "+|" ); // }
// } // else if ( strength > 0.20 )
// else if ( strength > 0.20 ) // {
// { // printf( "*|" );
// printf( "*|" ); // }
// } // else
// else // {
// { // printf( ".|" );
// printf( ".|" ); // }
// } // }
// } // }
// } // printf( "\n" );
// printf( "\n" );
unsigned char* dest = target->buffer; unsigned char* dest = target->buffer;
unsigned char* dest_end = target->buffer + aRasterFP->m_w * aRasterFP->m_h; unsigned char* dest_end = target->buffer + aRasterFP->m_w * aRasterFP->m_h;
@ -494,17 +498,18 @@ dense_render_glyph( RasterFP* aRasterFP, const FT_Bitmap* target )
dest++; dest++;
} }
for ( int col = 0; col < aRasterFP->m_w; col++ )
for (int col = 0; col < aRasterFP->m_w; col++)
{ {
for (int row = 0; row < aRasterFP->m_h/2; row++) for ( int row = 0; row < aRasterFP->m_h / 2; row++ )
{ {
//printf("Swapping position: %d, %d with %d, %d with rows = %d, cols = %d",row,col, aRasterFP->m_h-row, col, aRasterFP->m_h, aRasterFP->m_w); // printf("Swapping position: %d, %d with %d, %d with rows = %d, cols =
swapold(target->buffer + aRasterFP->m_w*row + col, target->buffer + (aRasterFP->m_h-row-1)*aRasterFP->m_w + col); // %d",row,col, aRasterFP->m_h-row, col, aRasterFP->m_h, aRasterFP->m_w);
swapold( target->buffer + aRasterFP->m_w * row + col,
target->buffer + ( aRasterFP->m_h - row - 1 ) * aRasterFP->m_w +
col );
} }
} }
return error; return error;
} }
@ -541,8 +546,8 @@ dense_raster_render( FT_Raster raster, const FT_Raster_Params* params )
aRasterFP->m_origin_x = 0; aRasterFP->m_origin_x = 0;
aRasterFP->m_origin_y = 0; aRasterFP->m_origin_y = 0;
/* @QUES: Why are my bitmaps upsied down 😭*/ /* @QUES: Why are my bitmaps upsied down 😭*/
aRasterFP->m_w = target_map->pitch; aRasterFP->m_w = target_map->pitch;
aRasterFP->m_h = target_map->rows; aRasterFP->m_h = target_map->rows;
int size = aRasterFP->m_w * aRasterFP->m_h + 4; int size = aRasterFP->m_w * aRasterFP->m_h + 4;