127#define FT_COMPONENT bsdf
166 } BSDF_TRaster, *BSDF_PRaster;
236 SDF_Raster_Params params;
247 static const ED zero_ed = { 0, { 0, 0 }, 0 };
292#define CHECK_NEIGHBOR( x_offset, y_offset ) \
295 if ( x + x_offset >= 0 && x + x_offset < w && \
296 y + y_offset >= 0 && y + y_offset < r ) \
300 to_check = dm + y_offset * w + x_offset; \
301 if ( to_check->alpha == 0 ) \
310 bsdf_is_edge( ED* dm,
318 FT_Int num_neighbors = 0;
321 if ( dm->alpha == 0 )
324 if ( dm->alpha > 0 && dm->alpha < 255 )
331 CHECK_NEIGHBOR( 0, -1 );
334 CHECK_NEIGHBOR( 0, 1 );
337 CHECK_NEIGHBOR( -1, 0 );
340 CHECK_NEIGHBOR( 1, 0 );
343 CHECK_NEIGHBOR( -1, -1 );
346 CHECK_NEIGHBOR( 1, -1 );
349 CHECK_NEIGHBOR( -1, 1 );
352 CHECK_NEIGHBOR( 1, 1 );
354 if ( num_neighbors != 8 )
401 compute_edge_distance( ED* current,
445 FT_16D16_Vec g = { 0, 0 };
446 FT_16D16 dist, current_alpha;
454 if ( x <= 0 || x >= w - 1 ||
455 y <= 0 || y >= r - 1 )
459 alphas[0] = 256 * (FT_16D16)current[-w - 1].alpha;
460 alphas[1] = 256 * (FT_16D16)current[-w ].alpha;
461 alphas[2] = 256 * (FT_16D16)current[-w + 1].alpha;
462 alphas[3] = 256 * (FT_16D16)current[ -1].alpha;
463 alphas[4] = 256 * (FT_16D16)current[ 0].alpha;
464 alphas[5] = 256 * (FT_16D16)current[ 1].alpha;
465 alphas[6] = 256 * (FT_16D16)current[ w - 1].alpha;
466 alphas[7] = 256 * (FT_16D16)current[ w ].alpha;
467 alphas[8] = 256 * (FT_16D16)current[ w + 1].alpha;
469 current_alpha = alphas[4];
484 FT_MulFix( alphas[3], 92681 ) -
487 FT_MulFix( alphas[5], 92681 ) +
491 FT_MulFix( alphas[1], 92681 ) -
494 FT_MulFix( alphas[7], 92681 ) +
497 FT_Vector_NormLen( &g );
504 if ( g.x == 0 || g.y == 0 )
505 dist = ONE / 2 - alphas[4];
521 a1 = FT_DivFix( gy, gx ) / 2;
523 if ( current_alpha < a1 )
524 dist = ( gx + gy ) / 2 -
525 square_root( 2 * FT_MulFix( gx,
529 else if ( current_alpha < ( ONE - a1 ) )
530 dist = FT_MulFix( ONE / 2 - current_alpha, gx );
533 dist = -( gx + gy ) / 2 +
534 square_root( 2 * FT_MulFix( gx,
536 ONE - current_alpha ) ) );
539 g.x = FT_MulFix( g.x, dist );
540 g.y = FT_MulFix( g.y, dist );
570 bsdf_approximate_edge( BSDF_Worker* worker )
572 FT_Error error = FT_Err_Ok;
578 if ( !worker || !worker->distance_map )
580 error = FT_THROW( Invalid_Argument );
584 ed = worker->distance_map;
586 for ( j = 0; j < worker->rows; j++ )
588 for ( i = 0; i < worker->width; i++ )
590 index = j * worker->width + i;
592 if ( bsdf_is_edge( worker->distance_map + index,
598 ed[index].prox = compute_edge_distance( ed + index,
602 ed[index].dist = VECTOR_LENGTH_16D16( ed[index].prox );
607 ed[index].dist = 400 * ONE;
608 ed[index].prox.x = 200 * ONE;
609 ed[index].prox.y = 200 * ONE;
643 bsdf_init_distance_map(
const FT_Bitmap* source,
644 BSDF_Worker* worker )
646 FT_Error error = FT_Err_Ok;
648 FT_Int x_diff, y_diff;
649 FT_Int t_i, t_j, s_i, s_j;
655 if ( !source || !worker )
657 error = FT_THROW( Invalid_Argument );
665 if ( worker->width < (FT_Int)source->width ||
666 worker->rows < (FT_Int)source->rows )
668 error = FT_THROW( Invalid_Argument );
673 if ( source->pixel_mode == FT_PIXEL_MODE_NONE )
675 FT_ERROR((
"bsdf_copy_source_to_target:"
676 " Invalid pixel mode of source bitmap" ));
677 error = FT_THROW( Invalid_Argument );
681#ifdef FT_DEBUG_LEVEL_TRACE
682 if ( source->pixel_mode == FT_PIXEL_MODE_MONO )
684 FT_TRACE0((
"bsdf_copy_source_to_target:"
685 " The `bsdf' renderer can convert monochrome\n" ));
687 " bitmaps to SDF but the results are not perfect\n" ));
689 " because there is no way to approximate actual\n" ));
691 " outlines from monochrome bitmaps. Consider\n" ));
693 " using an anti-aliased bitmap instead.\n" ));
699 x_diff = worker->width - (int)source->width;
700 y_diff = worker->rows - (int)source->rows;
705 t = (ED*)worker->distance_map;
716 switch ( source->pixel_mode )
718 case FT_PIXEL_MODE_MONO:
720 FT_Int t_width = worker->width;
721 FT_Int t_rows = worker->rows;
722 FT_Int s_width = (int)source->width;
723 FT_Int s_rows = (int)source->rows;
726 for ( t_j = 0; t_j < t_rows; t_j++ )
728 for ( t_i = 0; t_i < t_width; t_i++ )
730 FT_Int t_index = t_j * t_width + t_i;
736 t[t_index] = zero_ed;
743 if ( s_i < 0 || s_i >= s_width ||
744 s_j < 0 || s_j >= s_rows )
747 if ( worker->params.flip_y )
748 s_index = ( s_rows - s_j - 1 ) * source->pitch;
750 s_index = s_j * source->pitch;
752 div = s_index + s_i / 8;
756 byte = (FT_Byte)( 1 << mod );
758 t[t_index].alpha = pixel &
byte ? 255 : 0;
764 case FT_PIXEL_MODE_GRAY:
766 FT_Int t_width = worker->width;
767 FT_Int t_rows = worker->rows;
768 FT_Int s_width = (int)source->width;
769 FT_Int s_rows = (int)source->rows;
773 for ( t_j = 0; t_j < t_rows; t_j++ )
775 for ( t_i = 0; t_i < t_width; t_i++ )
777 FT_Int t_index = t_j * t_width + t_i;
781 t[t_index] = zero_ed;
788 if ( s_i < 0 || s_i >= s_width ||
789 s_j < 0 || s_j >= s_rows )
792 if ( worker->params.flip_y )
793 s_index = ( s_rows - s_j - 1 ) * s_width + s_i;
795 s_index = s_j * s_width + s_i;
798 t[t_index].alpha = s[s_index];
805 FT_ERROR((
"bsdf_copy_source_to_target:"
806 " unsopported pixel mode of source bitmap\n" ));
808 error = FT_THROW( Unimplemented_Feature );
846 compare_neighbor( ED* current,
851#if USE_SQUARED_DISTANCES
852 FT_16D16 edge_threshold = ONE / 4;
854 FT_16D16 edge_threshold = ONE / 2;
858 FT_16D16_Vec dist_vec;
865 if ( current->dist <= edge_threshold )
868 to_check = current + ( y_offset * width ) + x_offset;
882 dist = to_check->dist - ONE;
884 if ( dist < current->dist )
886 dist_vec = to_check->prox;
888 dist_vec.x += x_offset * ONE;
889 dist_vec.y += y_offset * ONE;
890 dist = VECTOR_LENGTH_16D16( dist_vec );
892 if ( dist < current->dist )
894 current->dist = dist;
895 current->prox = dist_vec;
917 first_pass( BSDF_Worker* worker )
924 dm = worker->distance_map;
933 for ( j = 1; j < r; j++ )
941 for ( i = 1; i < w - 1; i++ )
944 current = dm + index;
947 compare_neighbor( current, -1, -1, w );
949 compare_neighbor( current, 0, -1, w );
951 compare_neighbor( current, 1, -1, w );
953 compare_neighbor( current, -1, 0, w );
958 for ( i = w - 2; i >= 0; i-- )
961 current = dm + index;
964 compare_neighbor( current, 1, 0, w );
986 second_pass( BSDF_Worker* worker )
993 dm = worker->distance_map;
1002 for ( j = r - 2; j >= 0; j-- )
1010 for ( i = 1; i < w - 1; i++ )
1013 current = dm + index;
1016 compare_neighbor( current, -1, 1, w );
1018 compare_neighbor( current, 0, 1, w );
1020 compare_neighbor( current, 1, 1, w );
1022 compare_neighbor( current, -1, 0, w );
1027 for ( i = w - 2; i >= 0; i-- )
1030 current = dm + index;
1033 compare_neighbor( current, 1, 0, w );
1057 edt8( BSDF_Worker* worker )
1059 FT_Error error = FT_Err_Ok;
1062 if ( !worker || !worker->distance_map )
1064 error = FT_THROW( Invalid_Argument );
1069 first_pass( worker );
1072 second_pass( worker );
1102 finalize_sdf( BSDF_Worker* worker,
1103 const FT_Bitmap* target )
1105 FT_Error error = FT_Err_Ok;
1110 FT_SDFFormat* t_buffer;
1111 FT_16D16 sp_sq, spread;
1114 if ( !worker || !target )
1116 error = FT_THROW( Invalid_Argument );
1120 w = (int)target->width;
1121 r = (int)target->rows;
1122 t_buffer = (FT_SDFFormat*)target->buffer;
1124 if ( w != worker->width ||
1127 error = FT_THROW( Invalid_Argument );
1131 spread = (FT_16D16)FT_INT_16D16( worker->params.spread );
1133#if USE_SQUARED_DISTANCES
1134 sp_sq = (FT_16D16)FT_INT_16D16( worker->params.spread *
1135 worker->params.spread );
1137 sp_sq = (FT_16D16)FT_INT_16D16( worker->params.spread );
1140 for ( j = 0; j < r; j++ )
1142 for ( i = 0; i < w; i++ )
1146 FT_SDFFormat final_dist;
1151 dist = worker->distance_map[index].dist;
1153 if ( dist < 0 || dist > sp_sq )
1156#if USE_SQUARED_DISTANCES
1157 dist = square_root( dist );
1162 sign = worker->distance_map[index].alpha < 127 ? -1 : 1;
1165 if ( worker->params.flip_sign )
1169 final_dist = map_fixed_to_sdf( dist * sign, spread );
1171 t_buffer[index] = final_dist;
1188 bsdf_raster_new(
void* memory_,
1189 FT_Raster* araster_ )
1191 FT_Memory memory = (FT_Memory)memory_;
1192 BSDF_PRaster* araster = (BSDF_PRaster*)araster_;
1195 BSDF_PRaster raster = NULL;
1198 if ( !FT_NEW( raster ) )
1199 raster->memory = memory;
1209 bsdf_raster_reset( FT_Raster raster,
1210 unsigned char* pool_base,
1211 unsigned long pool_size )
1213 FT_UNUSED( raster );
1214 FT_UNUSED( pool_base );
1215 FT_UNUSED( pool_size );
1221 bsdf_raster_set_mode( FT_Raster raster,
1225 FT_UNUSED( raster );
1235 bsdf_raster_render( FT_Raster raster,
1236 const FT_Raster_Params* params )
1238 FT_Error error = FT_Err_Ok;
1239 FT_Memory memory = NULL;
1241 const FT_Bitmap* source = NULL;
1242 const FT_Bitmap* target = NULL;
1244 BSDF_TRaster* bsdf_raster = (BSDF_TRaster*)raster;
1247 const SDF_Raster_Params* sdf_params = (
const SDF_Raster_Params*)params;
1250 worker.distance_map = NULL;
1253 if ( !raster || !params )
1255 error = FT_THROW( Invalid_Argument );
1260 if ( sdf_params->root.flags != FT_RASTER_FLAG_SDF )
1262 error = FT_THROW( Raster_Corrupted );
1266 source = (
const FT_Bitmap*)sdf_params->root.source;
1267 target = (
const FT_Bitmap*)sdf_params->root.target;
1270 if ( !source || !target )
1272 error = FT_THROW( Invalid_Argument );
1276 memory = bsdf_raster->memory;
1279 FT_TRACE0((
"bsdf_raster_render: Raster not set up properly,\n" ));
1280 FT_TRACE0((
" unable to find memory handle.\n" ));
1282 error = FT_THROW( Invalid_Handle );
1287 if ( sdf_params->spread > MAX_SPREAD ||
1288 sdf_params->spread < MIN_SPREAD )
1290 FT_TRACE0((
"bsdf_raster_render:"
1291 " The `spread' field of `SDF_Raster_Params'\n" ));
1293 " is invalid; the value of this field must be\n" ));
1295 " within [%d, %d].\n",
1296 MIN_SPREAD, MAX_SPREAD ));
1298 " Also, you must pass `SDF_Raster_Params'\n" ));
1300 " instead of the default `FT_Raster_Params'\n" ));
1302 " while calling this function and set the fields\n" ));
1304 " accordingly.\n" ));
1306 error = FT_THROW( Invalid_Argument );
1313 if ( FT_QALLOC_MULT( worker.distance_map, target->rows,
1314 target->width * sizeof ( *worker.distance_map ) ) )
1317 worker.width = (int)target->width;
1318 worker.rows = (int)target->rows;
1319 worker.params = *sdf_params;
1321 FT_CALL( bsdf_init_distance_map( source, &worker ) );
1322 FT_CALL( bsdf_approximate_edge( &worker ) );
1323 FT_CALL( edt8( &worker ) );
1324 FT_CALL( finalize_sdf( &worker, target ) );
1326 FT_TRACE0((
"bsdf_raster_render: Total memory used = %ld\n",
1327 worker.width * worker.rows *
1328 (
long)sizeof ( *worker.distance_map ) ));
1331 if ( worker.distance_map )
1332 FT_FREE( worker.distance_map );
1340 bsdf_raster_done( FT_Raster raster )
1342 FT_Memory memory = (FT_Memory)((BSDF_TRaster*)raster)->memory;
1349 FT_DEFINE_RASTER_FUNCS(
1350 ft_bitmap_sdf_raster,
1352 FT_GLYPH_FORMAT_BITMAP,
1354 (FT_Raster_New_Func) bsdf_raster_new,
1355 (FT_Raster_Reset_Func) bsdf_raster_reset,
1356 (FT_Raster_Set_Mode_Func)bsdf_raster_set_mode,
1357 (FT_Raster_Render_Func) bsdf_raster_render,
1358 (FT_Raster_Done_Func) bsdf_raster_done