freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Git][freetype/freetype][gsoc-anurag-2022-final] [dense] Add drawing fun


From: Anurag Thakur (@AdbhutDev)
Subject: [Git][freetype/freetype][gsoc-anurag-2022-final] [dense] Add drawing functions to rasterizer
Date: Sat, 19 Nov 2022 05:16:11 +0000

Anurag Thakur pushed to branch gsoc-anurag-2022-final at FreeType / FreeType

Commits:

  • 4b77d947
    by Anurag Thakur at 2022-11-19T10:45:39+05:30
    [dense] Add drawing functions to rasterizer
    
    * src/dense/ftdense.c: (dense_render_line, dense_render_quadratic,
    dense_render_cubic, dense_render_glyph, dense_raster_render, Lerp):
    New Functions
    

1 changed file:

Changes:

  • src/dense/ftdense.c
    ... ... @@ -32,6 +32,15 @@ typedef struct dense_TRaster_
    32 32
     
    
    33 33
     } dense_TRaster, *dense_PRaster;
    
    34 34
     
    
    35
    +/* Linear interpolation between P0 and P1 */
    
    36
    +static FT_Vector
    
    37
    +Lerp( float T, FT_Vector P0, FT_Vector P1 )
    
    38
    +{
    
    39
    +  FT_Vector p;
    
    40
    +  p.x = P0.x + T * ( P1.x - P0.x );
    
    41
    +  p.y = P0.y + T * ( P1.y - P0.y );
    
    42
    +  return p;
    
    43
    +}
    
    35 44
     
    
    36 45
     static int
    
    37 46
     dense_move_to( const FT_Vector* to, dense_worker* worker )
    
    ... ... @@ -54,11 +63,112 @@ dense_line_to( const FT_Vector* to, dense_worker* worker )
    54 63
     }
    
    55 64
     
    
    56 65
     void
    
    57
    -dense_render_line( dense_worker* worker, TPos tox, TPos toy )
    
    66
    +dense_render_line( dense_worker* worker, FT_Pos tox, FT_Pos toy )
    
    58 67
     {
    
    59
    -  return;
    
    68
    +  float from_x = worker->prev_x;
    
    69
    +  float from_y = worker->prev_y;
    
    70
    +  if ( from_y == toy )
    
    71
    +    return;
    
    72
    +
    
    73
    +
    
    74
    +  from_x /= 256.0;
    
    75
    +  from_y /= 256.0;
    
    76
    +  float to_x = tox / 256.0;
    
    77
    +  float to_y = toy / 256.0;
    
    78
    +
    
    79
    +
    
    80
    +  float dir;
    
    81
    +  if ( from_y < to_y )
    
    82
    +    dir = 1;
    
    83
    +  else
    
    84
    +  {
    
    85
    +    dir = -1;
    
    86
    +    FT_SWAP(from_x, to_x );
    
    87
    +    FT_SWAP(from_y, to_y );
    
    88
    +  }
    
    89
    +
    
    90
    +  // Clip to the height.
    
    91
    +  if ( from_y >= worker->m_h || to_y <= 0 )
    
    92
    +    return;
    
    93
    +
    
    94
    +  float dxdy = ( to_x - from_x ) / (float)( to_y - from_y );
    
    95
    +  if ( from_y < 0 )
    
    96
    +  {
    
    97
    +    from_x -= from_y * dxdy;
    
    98
    +    from_y = 0;
    
    99
    +  }
    
    100
    +  if ( to_y > worker->m_h )
    
    101
    +  {
    
    102
    +    to_x -= ( to_y - worker->m_h ) * dxdy;
    
    103
    +    to_y = (float)worker->m_h;
    
    104
    +  }
    
    105
    +
    
    106
    +  float  x       = from_x;
    
    107
    +  int    y0      = (int)from_y;
    
    108
    +  int    y_limit = (int)ceil( to_y );
    
    109
    +  float* m_a     = worker->m_a;
    
    110
    +
    
    111
    +  for ( int y = y0; y < y_limit; y++ )
    
    112
    +  {
    
    113
    +    int   linestart = y * worker->m_w;
    
    114
    +    float dy        = fmin( y + 1.0f, to_y ) - fmax( (float)y, from_y );
    
    115
    +    float xnext     = x + dxdy * dy;
    
    116
    +    float d         = dy * dir;
    
    117
    +
    
    118
    +    float x0, x1;
    
    119
    +    if ( x < xnext )
    
    120
    +    {
    
    121
    +      x0 = x;
    
    122
    +      x1 = xnext;
    
    123
    +    }
    
    124
    +    else
    
    125
    +    {
    
    126
    +      x0 = xnext;
    
    127
    +      x1 = x;
    
    128
    +    }
    
    129
    +
    
    130
    +    /*
    
    131
    +    It's possible for x0 to be negative on the last scanline because of
    
    132
    +    floating-point inaccuracy That would cause an out-of-bounds array access at
    
    133
    +    index -1.
    
    134
    +    */
    
    135
    +    float x0floor = x0 <= 0.0f ? 0.0f : (float)floor( x0 );
    
    136
    +
    
    137
    +    int   x0i    = (int)x0floor;
    
    138
    +    float x1ceil = (float)ceil( x1 );
    
    139
    +    int   x1i    = (int)x1ceil;
    
    140
    +    if ( x1i <= x0i + 1 )
    
    141
    +    {
    
    142
    +      float xmf = 0.5f * ( x + xnext ) - x0floor;
    
    143
    +      m_a[linestart + x0i] += d - d * xmf;
    
    144
    +      m_a[linestart + ( x0i + 1 )] += d * xmf;
    
    145
    +    }
    
    146
    +    else
    
    147
    +    {
    
    148
    +      float s   = 1.0f / ( x1 - x0 );
    
    149
    +      float x0f = x0 - x0floor;
    
    150
    +      float a0  = 0.5f * s * ( 1.0f - x0f ) * ( 1.0f - x0f );
    
    151
    +      float x1f = x1 - x1ceil + 1.0f;
    
    152
    +      float am  = 0.5f * s * x1f * x1f;
    
    153
    +      m_a[linestart + x0i] += d * a0;
    
    154
    +      if ( x1i == x0i + 2 )
    
    155
    +        m_a[linestart + ( x0i + 1 )] += d * ( 1.0f - a0 - am );
    
    156
    +      else
    
    157
    +      {
    
    158
    +        float a1 = s * ( 1.5f - x0f );
    
    159
    +        m_a[linestart + ( x0i + 1 )] += d * ( a1 - a0 );
    
    160
    +        for ( int xi = x0i + 2; xi < x1i - 1; xi++ )
    
    161
    +          m_a[linestart + xi] += d * s;
    
    162
    +        float a2 = a1 + ( x1i - x0i - 3 ) * s;
    
    163
    +        m_a[linestart + ( x1i - 1 )] += d * ( 1.0f - a2 - am );
    
    164
    +      }
    
    165
    +      m_a[linestart + x1i] += d * am;
    
    166
    +    }
    
    167
    +    x = xnext;
    
    168
    +  }
    
    60 169
     }
    
    61 170
     
    
    171
    +
    
    62 172
     static int
    
    63 173
     dense_conic_to( const FT_Vector* control,
    
    64 174
                     const FT_Vector* to,
    
    ... ... @@ -73,7 +183,56 @@ dense_render_quadratic( dense_worker* worker,
    73 183
                             FT_Vector* control,
    
    74 184
                             FT_Vector* to )
    
    75 185
     {
    
    186
    +  /*
    
    187
    +  Calculate devsq as the square of four times the
    
    188
    +  distance from the control point to the midpoint of the curve.
    
    189
    +  This is the place at which the curve is furthest from the
    
    190
    +  line joining the control points.
    
    191
    +
    
    192
    +  4 x point on curve = p0 + 2p1 + p2
    
    193
    +  4 x midpoint = 4p1
    
    194
    +
    
    195
    +  The division by four is omitted to save time.
    
    196
    +  */
    
    197
    +
    
    198
    +  FT_Vector aP0 = { DOWNSCALE( worker->prev_x ), DOWNSCALE( worker->prev_y ) };
    
    199
    +  FT_Vector aP1 = { control->x, control->y };
    
    200
    +  FT_Vector aP2 = { to->x, to->y };
    
    201
    +
    
    202
    +  float devx  = aP0.x - aP1.x - aP1.x + aP2.x;
    
    203
    +  float devy  = aP0.y - aP1.y - aP1.y + aP2.y;
    
    204
    +  float devsq = devx * devx + devy * devy;
    
    205
    +
    
    206
    +  if ( devsq < 0.333f )
    
    207
    +  {
    
    208
    +    dense_line_to( &aP2, worker );
    
    76 209
         return;
    
    210
    +  }
    
    211
    +
    
    212
    +  /*
    
    213
    +  According to Raph Levien, the reason for the subdivision by n (instead of
    
    214
    +  recursive division by the Casteljau system) is that "I expect the flatness
    
    215
    +  computation to be semi-expensive (it's done once rather than on each potential
    
    216
    +  subdivision) and also because you'll often get fewer subdivisions. Taking a
    
    217
    +  circular arc as a simplifying assumption, where I get n, a recursive approach
    
    218
    +  would get 2^ceil(lg n), which, if I haven't made any horrible mistakes, is
    
    219
    +  expected to be 33% more in the limit".
    
    220
    +  */
    
    221
    +
    
    222
    +  const float tol = 3.0f;
    
    223
    +  int         n   = (int)floor( sqrt( sqrt( tol * devsq ) ) )/8;
    
    224
    +  FT_Vector p      = aP0;
    
    225
    +  float     nrecip = 1.0f / ( n + 1.0f );
    
    226
    +  float     t      = 0.0f;
    
    227
    +  for ( int i = 0; i < n; i++ )
    
    228
    +  {
    
    229
    +    t += nrecip;
    
    230
    +    FT_Vector next = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) );
    
    231
    +    dense_line_to(&next, worker );
    
    232
    +    p              = next;
    
    233
    +  }
    
    234
    +
    
    235
    +  dense_line_to( &aP2, worker );
    
    77 236
     }
    
    78 237
     
    
    79 238
     static int
    
    ... ... @@ -92,7 +251,43 @@ dense_render_cubic( dense_worker* worker,
    92 251
                         FT_Vector*    control_2,
    
    93 252
                         FT_Vector*    to )
    
    94 253
     {
    
    95
    -  return;
    
    254
    +  FT_Vector aP0 = { DOWNSCALE( worker->prev_x ), DOWNSCALE( worker->prev_y ) };
    
    255
    +  FT_Vector aP1 = { control_1->x, control_1->y };
    
    256
    +  FT_Vector aP2 = { control_2->x, control_2->y };
    
    257
    +  FT_Vector aP3 = { to->x, to->y };
    
    258
    +
    
    259
    +  float     devx   = aP0.x - aP1->x - aP1->x + aP2->x;
    
    260
    +  float     devy   = aP0.y - aP1->y - aP1->y + aP2->y;
    
    261
    +  float     devsq0 = devx * devx + devy * devy;
    
    262
    +  devx             = aP1->x - aP2->x - aP2->x + aP3->x;
    
    263
    +  devy             = aP1->y - aP2->y - aP2->y + aP3->y;
    
    264
    +  float devsq1     = devx * devx + devy * devy;
    
    265
    +  float devsq      = fmax( devsq0, devsq1 );
    
    266
    +
    
    267
    +  if ( devsq < 0.333f )
    
    268
    +  {
    
    269
    +    dense_render_line( worker, aP3->x, aP3->y );
    
    270
    +    return;
    
    271
    +  }
    
    272
    +
    
    273
    +  const float tol    = 3.0f;
    
    274
    +  int         n      = (int)floor( sqrt( sqrt( tol * devsq ) ) ) / 8;
    
    275
    +  FT_Vector   p      = aP0;
    
    276
    +  float       nrecip = 1.0f / ( n + 1.0f );
    
    277
    +  float       t      = 0.0f;
    
    278
    +  for ( int i = 0; i < n; i++ )
    
    279
    +  {
    
    280
    +    t += nrecip;
    
    281
    +    FT_Vector a    = Lerp( t, Lerp( t, aP0, *aP1 ), Lerp( t, *aP1, *aP2 ) );
    
    282
    +    FT_Vector b    = Lerp( t, Lerp( t, *aP1, *aP2 ), Lerp( t, *aP2, *aP3 ) );
    
    283
    +    FT_Vector next = Lerp( t, a, b );
    
    284
    +    dense_render_line( worker, next.x, next.y );
    
    285
    +    worker->prev_x = next.x;
    
    286
    +    worker->prev_y = next.y;
    
    287
    +    p              = next;
    
    288
    +  }
    
    289
    +
    
    290
    +  dense_line_to( &aP3, worker );
    
    96 291
     }
    
    97 292
     
    
    98 293
     static int
    
    ... ... @@ -152,13 +347,78 @@ dense_render_glyph( dense_worker* worker, const FT_Bitmap* target )
    152 347
     {
    
    153 348
       FT_Error error = FT_Outline_Decompose( &( worker->outline ),
    
    154 349
                                              &dense_decompose_funcs, worker );
    
    350
    +  // Render into bitmap
    
    351
    +  const float* source = worker->m_a;
    
    352
    +
    
    353
    +  unsigned char* dest     = target->buffer;
    
    354
    +  unsigned char* dest_end = target->buffer + worker->m_w * worker->m_h;
    
    355
    +  float          value    = 0.0f;
    
    356
    +  while ( dest < dest_end )
    
    357
    +  {
    
    358
    +    value += *source++;
    
    359
    +    if ( value > 0.0f )
    
    360
    +    {
    
    361
    +      int n = (int)( fabs( value ) * 255.0f + 0.5f );
    
    362
    +      if ( n > 255 )
    
    363
    +        n = 255;
    
    364
    +      *dest = (unsigned char)n;
    
    365
    +    }
    
    366
    +    else
    
    367
    +      *dest = 0;
    
    368
    +    dest++;
    
    369
    +  }
    
    370
    +
    
    371
    +  free(worker->m_a);
    
    155 372
       return error;
    
    156 373
     }
    
    157 374
     
    
    158 375
     static int
    
    159 376
     dense_raster_render( FT_Raster raster, const FT_Raster_Params* params )
    
    160 377
     {
    
    161
    -  return 0;
    
    378
    +  const FT_Outline* outline    = (const FT_Outline*)params->source;
    
    379
    +  FT_Bitmap*  target_map = params->target;
    
    380
    +
    
    381
    +  dense_worker worker[1];
    
    382
    +
    
    383
    +  if ( !raster )
    
    384
    +    return FT_THROW( Invalid_Argument );
    
    385
    +
    
    386
    +  if ( !outline )
    
    387
    +    return FT_THROW( Invalid_Outline );
    
    388
    +
    
    389
    +  worker->outline = *outline;
    
    390
    +
    
    391
    +  if ( !target_map )
    
    392
    +    return FT_THROW( Invalid_Argument );
    
    393
    +
    
    394
    +  /* nothing to do */
    
    395
    +  if ( !target_map->width || !target_map->rows )
    
    396
    +    return 0;
    
    397
    +
    
    398
    +  if ( !target_map->buffer )
    
    399
    +    return FT_THROW( Invalid_Argument );
    
    400
    +
    
    401
    +  worker->m_origin_x = 0;
    
    402
    +  worker->m_origin_y = 0;
    
    403
    +  worker->m_w = target_map->pitch;
    
    404
    +  worker->m_h = target_map->rows;
    
    405
    +
    
    406
    +  int size = worker->m_w * worker->m_h + 4;
    
    407
    +
    
    408
    +  worker->m_a      = malloc( sizeof( float ) * size );
    
    409
    +  worker->m_a_size = size;
    
    410
    +
    
    411
    +  memset( worker->m_a, 0, ( sizeof( float ) * size ) );
    
    412
    +  /* exit if nothing to do */
    
    413
    +  if ( worker->m_w <= worker->m_origin_x || worker->m_h <= worker->m_origin_y )
    
    414
    +  {
    
    415
    +    return 0;
    
    416
    +  }
    
    417
    +
    
    418
    +  // Invert the pitch to account for different +ve y-axis direction in dense array
    
    419
    +  // (maybe temporary solution)
    
    420
    +  target_map->pitch *= -1;
    
    421
    +  return dense_render_glyph( worker, target_map );
    
    162 422
     }
    
    163 423
     
    
    164 424
     FT_DEFINE_RASTER_FUNCS(
    


  • reply via email to

    [Prev in Thread] Current Thread [Next in Thread]