382 {
383 Short y_min; /* band's minimum */
384 Short y_max; /* band's maximum */
385
386 } black_TBand;
387
388
389 #define AlignProfileSize \
390 ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
391
392
393 #undef RAS_ARG
394 #undef RAS_ARGS
395 #undef RAS_VAR
396 #undef RAS_VARS
397
398 #ifdef FT_STATIC_RASTER
399
400
401 #define RAS_ARGS /* void */
402 #define RAS_ARG /* void */
403
404 #define RAS_VARS /* void */
405 #define RAS_VAR /* void */
406
407 #define FT_UNUSED_RASTER do { } while ( 0 )
408
409
410 #else /* !FT_STATIC_RASTER */
411
412
413 #define RAS_ARGS black_PWorker worker,
414 #define RAS_ARG black_PWorker worker
415
416 #define RAS_VARS worker,
417 #define RAS_VAR worker
418
419 #define FT_UNUSED_RASTER FT_UNUSED( worker )
420
421
422 #endif /* !FT_STATIC_RASTER */
529 /* should be performed to control */
530 /* drop-out accurately when calling */
531 /* Render_Glyph. */
532
533 TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
534
535 black_TBand band_stack[16]; /* band stack used for sub-banding */
536 Int band_top; /* band stack top */
537
538 };
539
540
541 typedef struct black_TRaster_
542 {
543 void* memory;
544
545 } black_TRaster, *black_PRaster;
546
547 #ifdef FT_STATIC_RASTER
548
549 static black_TWorker cur_ras;
550 #define ras cur_ras
551
552 #else /* !FT_STATIC_RASTER */
553
554 #define ras (*worker)
555
556 #endif /* !FT_STATIC_RASTER */
557
558
559 /*************************************************************************/
560 /*************************************************************************/
561 /** **/
562 /** PROFILES COMPUTATION **/
563 /** **/
564 /*************************************************************************/
565 /*************************************************************************/
566
567
568 /**************************************************************************
569 *
570 * @Function:
644 * SUCCESS on success. FAILURE in case of overflow or of incoherent
645 * profile.
646 */
647 static Bool
648 New_Profile( RAS_ARGS TStates aState,
649 Bool overshoot )
650 {
651 if ( !ras.fProfile )
652 {
653 ras.cProfile = (PProfile)ras.top;
654 ras.fProfile = ras.cProfile;
655 ras.top += AlignProfileSize;
656 }
657
658 if ( ras.top >= ras.maxBuff )
659 {
660 ras.error = FT_THROW( Overflow );
661 return FAILURE;
662 }
663
664 ras.cProfile->flags = 0;
665 ras.cProfile->start = 0;
666 ras.cProfile->height = 0;
667 ras.cProfile->offset = ras.top;
668 ras.cProfile->link = (PProfile)0;
669 ras.cProfile->next = (PProfile)0;
670 ras.cProfile->flags = ras.dropOutControl;
671
672 switch ( aState )
673 {
674 case Ascending_State:
675 ras.cProfile->flags |= Flow_Up;
676 if ( overshoot )
677 ras.cProfile->flags |= Overshoot_Bottom;
678
679 FT_TRACE6(( " new ascending profile = %p\n", ras.cProfile ));
680 break;
681
682 case Descending_State:
683 if ( overshoot )
684 ras.cProfile->flags |= Overshoot_Top;
897 * Split_Conic
898 *
899 * @Description:
900 * Subdivide one conic Bezier into two joint sub-arcs in the Bezier
901 * stack.
902 *
903 * @Input:
904 * None (subdivided Bezier is taken from the top of the stack).
905 *
906 * @Note:
907 * This routine is the `beef' of this component. It is _the_ inner
908 * loop that should be optimized to hell to get the best performance.
909 */
910 static void
911 Split_Conic( TPoint* base )
912 {
913 Long a, b;
914
915
916 base[4].x = base[2].x;
917 b = base[1].x;
918 a = base[3].x = ( base[2].x + b ) / 2;
919 b = base[1].x = ( base[0].x + b ) / 2;
920 base[2].x = ( a + b ) / 2;
921
922 base[4].y = base[2].y;
923 b = base[1].y;
924 a = base[3].y = ( base[2].y + b ) / 2;
925 b = base[1].y = ( base[0].y + b ) / 2;
926 base[2].y = ( a + b ) / 2;
927
928 /* hand optimized. gcc doesn't seem to be too good at common */
929 /* expression substitution and instruction scheduling ;-) */
930 }
931
932
933 /**************************************************************************
934 *
935 * @Function:
936 * Split_Cubic
937 *
938 * @Description:
939 * Subdivide a third-order Bezier arc into two joint sub-arcs in the
940 * Bezier stack.
941 *
942 * @Note:
943 * This routine is the `beef' of the component. It is one of _the_
944 * inner loops that should be optimized like hell to get the best
945 * performance.
946 */
947 static void
948 Split_Cubic( TPoint* base )
949 {
950 Long a, b, c, d;
951
952
953 base[6].x = base[3].x;
954 c = base[1].x;
955 d = base[2].x;
956 base[1].x = a = ( base[0].x + c + 1 ) >> 1;
957 base[5].x = b = ( base[3].x + d + 1 ) >> 1;
958 c = ( c + d + 1 ) >> 1;
959 base[2].x = a = ( a + c + 1 ) >> 1;
960 base[4].x = b = ( b + c + 1 ) >> 1;
961 base[3].x = ( a + b + 1 ) >> 1;
962
963 base[6].y = base[3].y;
964 c = base[1].y;
965 d = base[2].y;
966 base[1].y = a = ( base[0].y + c + 1 ) >> 1;
967 base[5].y = b = ( base[3].y + d + 1 ) >> 1;
968 c = ( c + d + 1 ) >> 1;
969 base[2].y = a = ( a + c + 1 ) >> 1;
970 base[4].y = b = ( b + c + 1 ) >> 1;
971 base[3].y = ( a + b + 1 ) >> 1;
972 }
973
974
975 /**************************************************************************
976 *
977 * @Function:
978 * Line_Up
979 *
980 * @Description:
981 * Compute the x-coordinates of an ascending line segment and store
982 * them in the render pool.
983 *
984 * @Input:
985 * x1 ::
986 * The x-coordinate of the segment's start point.
987 *
988 * y1 ::
989 * The y-coordinate of the segment's start point.
990 *
991 * x2 ::
2767 P = Q;
2768 }
2769
2770 /* sort the drawing lists */
2771
2772 Sort( &draw_left );
2773 Sort( &draw_right );
2774
2775 y_change = (Short)ras.sizeBuff[-ras.numTurns--];
2776 y_height = (Short)( y_change - y );
2777
2778 while ( y < y_change )
2779 {
2780 /* let's trace */
2781
2782 dropouts = 0;
2783
2784 P_Left = draw_left;
2785 P_Right = draw_right;
2786
2787 while ( P_Left )
2788 {
2789 x1 = P_Left ->X;
2790 x2 = P_Right->X;
2791
2792 if ( x1 > x2 )
2793 {
2794 xs = x1;
2795 x1 = x2;
2796 x2 = xs;
2797 }
2798
2799 e1 = FLOOR( x1 );
2800 e2 = CEILING( x2 );
2801
2802 if ( x2 - x1 <= ras.precision &&
2803 e1 != x1 && e2 != x2 )
2804 {
2805 if ( e1 > e2 || e2 == e1 + ras.precision )
2806 {
2807 Int dropOutControl = P_Left->flags & 7;
2868 if ( P->height == 0 )
2869 DelOld( &draw_right, P );
2870 P = Q;
2871 }
2872 }
2873
2874 /* for gray-scaling, flush the bitmap scanline cache */
2875 while ( y <= max_Y )
2876 {
2877 ras.Proc_Sweep_Step( RAS_VAR );
2878 y++;
2879 }
2880
2881 return SUCCESS;
2882
2883 Scan_DropOuts:
2884
2885 P_Left = draw_left;
2886 P_Right = draw_right;
2887
2888 while ( P_Left )
2889 {
2890 if ( P_Left->countL )
2891 {
2892 P_Left->countL = 0;
2893 #if 0
2894 dropouts--; /* -- this is useful when debugging only */
2895 #endif
2896 ras.Proc_Sweep_Drop( RAS_VARS y,
2897 P_Left->X,
2898 P_Right->X,
2899 P_Left,
2900 P_Right );
2901 }
2902
2903 P_Left = P_Left->link;
2904 P_Right = P_Right->link;
2905 }
2906
2907 goto Next_Line;
2908 }
3240 static int
3241 ft_black_set_mode( FT_Raster raster,
3242 ULong mode,
3243 void* args )
3244 {
3245 FT_UNUSED( raster );
3246 FT_UNUSED( mode );
3247 FT_UNUSED( args );
3248
3249 return 0;
3250 }
3251
3252
3253 static int
3254 ft_black_render( FT_Raster raster,
3255 const FT_Raster_Params* params )
3256 {
3257 const FT_Outline* outline = (const FT_Outline*)params->source;
3258 const FT_Bitmap* target_map = params->target;
3259
3260 black_TWorker worker[1];
3261
3262 Long buffer[FT_MAX_BLACK_POOL];
3263
3264
3265 if ( !raster )
3266 return FT_THROW( Not_Ini );
3267
3268 if ( !outline )
3269 return FT_THROW( Invalid );
3270
3271 /* return immediately if the outline is empty */
3272 if ( outline->n_points == 0 || outline->n_contours <= 0 )
3273 return Raster_Err_None;
3274
3275 if ( !outline->contours || !outline->points )
3276 return FT_THROW( Invalid );
3277
3278 if ( outline->n_points !=
3279 outline->contours[outline->n_contours - 1] + 1 )
3280 return FT_THROW( Invalid );
3282 /* this version of the raster does not support direct rendering, sorry */
3283 if ( params->flags & FT_RASTER_FLAG_DIRECT )
3284 return FT_THROW( Unsupported );
3285
3286 if ( params->flags & FT_RASTER_FLAG_AA )
3287 return FT_THROW( Unsupported );
3288
3289 if ( !target_map )
3290 return FT_THROW( Invalid );
3291
3292 /* nothing to do */
3293 if ( !target_map->width || !target_map->rows )
3294 return Raster_Err_None;
3295
3296 if ( !target_map->buffer )
3297 return FT_THROW( Invalid );
3298
3299 ras.outline = *outline;
3300 ras.target = *target_map;
3301
3302 worker->buff = buffer;
3303 worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
3304
3305 return Render_Glyph( RAS_VAR );
3306 }
3307
3308
3309 FT_DEFINE_RASTER_FUNCS(
3310 ft_standard_raster,
3311
3312 FT_GLYPH_FORMAT_OUTLINE,
3313
3314 (FT_Raster_New_Func) ft_black_new, /* raster_new */
3315 (FT_Raster_Reset_Func) ft_black_reset, /* raster_reset */
3316 (FT_Raster_Set_Mode_Func)ft_black_set_mode, /* raster_set_mode */
3317 (FT_Raster_Render_Func) ft_black_render, /* raster_render */
3318 (FT_Raster_Done_Func) ft_black_done /* raster_done */
3319 )
3320
3321
3322 /* END */
|
382 {
383 Short y_min; /* band's minimum */
384 Short y_max; /* band's maximum */
385
386 } black_TBand;
387
388
389 #define AlignProfileSize \
390 ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
391
392
393 #undef RAS_ARG
394 #undef RAS_ARGS
395 #undef RAS_VAR
396 #undef RAS_VARS
397
398 #ifdef FT_STATIC_RASTER
399
400
401 #define RAS_ARGS /* void */
402 #define RAS_ARG void
403
404 #define RAS_VARS /* void */
405 #define RAS_VAR /* void */
406
407 #define FT_UNUSED_RASTER do { } while ( 0 )
408
409
410 #else /* !FT_STATIC_RASTER */
411
412
413 #define RAS_ARGS black_PWorker worker,
414 #define RAS_ARG black_PWorker worker
415
416 #define RAS_VARS worker,
417 #define RAS_VAR worker
418
419 #define FT_UNUSED_RASTER FT_UNUSED( worker )
420
421
422 #endif /* !FT_STATIC_RASTER */
529 /* should be performed to control */
530 /* drop-out accurately when calling */
531 /* Render_Glyph. */
532
533 TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
534
535 black_TBand band_stack[16]; /* band stack used for sub-banding */
536 Int band_top; /* band stack top */
537
538 };
539
540
541 typedef struct black_TRaster_
542 {
543 void* memory;
544
545 } black_TRaster, *black_PRaster;
546
547 #ifdef FT_STATIC_RASTER
548
549 static black_TWorker ras;
550
551 #else /* !FT_STATIC_RASTER */
552
553 #define ras (*worker)
554
555 #endif /* !FT_STATIC_RASTER */
556
557
558 /*************************************************************************/
559 /*************************************************************************/
560 /** **/
561 /** PROFILES COMPUTATION **/
562 /** **/
563 /*************************************************************************/
564 /*************************************************************************/
565
566
567 /**************************************************************************
568 *
569 * @Function:
643 * SUCCESS on success. FAILURE in case of overflow or of incoherent
644 * profile.
645 */
646 static Bool
647 New_Profile( RAS_ARGS TStates aState,
648 Bool overshoot )
649 {
650 if ( !ras.fProfile )
651 {
652 ras.cProfile = (PProfile)ras.top;
653 ras.fProfile = ras.cProfile;
654 ras.top += AlignProfileSize;
655 }
656
657 if ( ras.top >= ras.maxBuff )
658 {
659 ras.error = FT_THROW( Overflow );
660 return FAILURE;
661 }
662
663 ras.cProfile->start = 0;
664 ras.cProfile->height = 0;
665 ras.cProfile->offset = ras.top;
666 ras.cProfile->link = (PProfile)0;
667 ras.cProfile->next = (PProfile)0;
668 ras.cProfile->flags = ras.dropOutControl;
669
670 switch ( aState )
671 {
672 case Ascending_State:
673 ras.cProfile->flags |= Flow_Up;
674 if ( overshoot )
675 ras.cProfile->flags |= Overshoot_Bottom;
676
677 FT_TRACE6(( " new ascending profile = %p\n", ras.cProfile ));
678 break;
679
680 case Descending_State:
681 if ( overshoot )
682 ras.cProfile->flags |= Overshoot_Top;
895 * Split_Conic
896 *
897 * @Description:
898 * Subdivide one conic Bezier into two joint sub-arcs in the Bezier
899 * stack.
900 *
901 * @Input:
902 * None (subdivided Bezier is taken from the top of the stack).
903 *
904 * @Note:
905 * This routine is the `beef' of this component. It is _the_ inner
906 * loop that should be optimized to hell to get the best performance.
907 */
908 static void
909 Split_Conic( TPoint* base )
910 {
911 Long a, b;
912
913
914 base[4].x = base[2].x;
915 a = base[0].x + base[1].x;
916 b = base[1].x + base[2].x;
917 base[3].x = b >> 1;
918 base[2].x = ( a + b ) >> 2;
919 base[1].x = a >> 1;
920
921 base[4].y = base[2].y;
922 a = base[0].y + base[1].y;
923 b = base[1].y + base[2].y;
924 base[3].y = b >> 1;
925 base[2].y = ( a + b ) >> 2;
926 base[1].y = a >> 1;
927
928 /* hand optimized. gcc doesn't seem to be too good at common */
929 /* expression substitution and instruction scheduling ;-) */
930 }
931
932
933 /**************************************************************************
934 *
935 * @Function:
936 * Split_Cubic
937 *
938 * @Description:
939 * Subdivide a third-order Bezier arc into two joint sub-arcs in the
940 * Bezier stack.
941 *
942 * @Note:
943 * This routine is the `beef' of the component. It is one of _the_
944 * inner loops that should be optimized like hell to get the best
945 * performance.
946 */
947 static void
948 Split_Cubic( TPoint* base )
949 {
950 Long a, b, c;
951
952
953 base[6].x = base[3].x;
954 a = base[0].x + base[1].x;
955 b = base[1].x + base[2].x;
956 c = base[2].x + base[3].x;
957 base[5].x = c >> 1;
958 c += b;
959 base[4].x = c >> 2;
960 base[1].x = a >> 1;
961 a += b;
962 base[2].x = a >> 2;
963 base[3].x = ( a + c ) >> 3;
964
965 base[6].y = base[3].y;
966 a = base[0].y + base[1].y;
967 b = base[1].y + base[2].y;
968 c = base[2].y + base[3].y;
969 base[5].y = c >> 1;
970 c += b;
971 base[4].y = c >> 2;
972 base[1].y = a >> 1;
973 a += b;
974 base[2].y = a >> 2;
975 base[3].y = ( a + c ) >> 3;
976 }
977
978
979 /**************************************************************************
980 *
981 * @Function:
982 * Line_Up
983 *
984 * @Description:
985 * Compute the x-coordinates of an ascending line segment and store
986 * them in the render pool.
987 *
988 * @Input:
989 * x1 ::
990 * The x-coordinate of the segment's start point.
991 *
992 * y1 ::
993 * The y-coordinate of the segment's start point.
994 *
995 * x2 ::
2771 P = Q;
2772 }
2773
2774 /* sort the drawing lists */
2775
2776 Sort( &draw_left );
2777 Sort( &draw_right );
2778
2779 y_change = (Short)ras.sizeBuff[-ras.numTurns--];
2780 y_height = (Short)( y_change - y );
2781
2782 while ( y < y_change )
2783 {
2784 /* let's trace */
2785
2786 dropouts = 0;
2787
2788 P_Left = draw_left;
2789 P_Right = draw_right;
2790
2791 while ( P_Left && P_Right )
2792 {
2793 x1 = P_Left ->X;
2794 x2 = P_Right->X;
2795
2796 if ( x1 > x2 )
2797 {
2798 xs = x1;
2799 x1 = x2;
2800 x2 = xs;
2801 }
2802
2803 e1 = FLOOR( x1 );
2804 e2 = CEILING( x2 );
2805
2806 if ( x2 - x1 <= ras.precision &&
2807 e1 != x1 && e2 != x2 )
2808 {
2809 if ( e1 > e2 || e2 == e1 + ras.precision )
2810 {
2811 Int dropOutControl = P_Left->flags & 7;
2872 if ( P->height == 0 )
2873 DelOld( &draw_right, P );
2874 P = Q;
2875 }
2876 }
2877
2878 /* for gray-scaling, flush the bitmap scanline cache */
2879 while ( y <= max_Y )
2880 {
2881 ras.Proc_Sweep_Step( RAS_VAR );
2882 y++;
2883 }
2884
2885 return SUCCESS;
2886
2887 Scan_DropOuts:
2888
2889 P_Left = draw_left;
2890 P_Right = draw_right;
2891
2892 while ( P_Left && P_Right )
2893 {
2894 if ( P_Left->countL )
2895 {
2896 P_Left->countL = 0;
2897 #if 0
2898 dropouts--; /* -- this is useful when debugging only */
2899 #endif
2900 ras.Proc_Sweep_Drop( RAS_VARS y,
2901 P_Left->X,
2902 P_Right->X,
2903 P_Left,
2904 P_Right );
2905 }
2906
2907 P_Left = P_Left->link;
2908 P_Right = P_Right->link;
2909 }
2910
2911 goto Next_Line;
2912 }
3244 static int
3245 ft_black_set_mode( FT_Raster raster,
3246 ULong mode,
3247 void* args )
3248 {
3249 FT_UNUSED( raster );
3250 FT_UNUSED( mode );
3251 FT_UNUSED( args );
3252
3253 return 0;
3254 }
3255
3256
3257 static int
3258 ft_black_render( FT_Raster raster,
3259 const FT_Raster_Params* params )
3260 {
3261 const FT_Outline* outline = (const FT_Outline*)params->source;
3262 const FT_Bitmap* target_map = params->target;
3263
3264 #ifndef FT_STATIC_RASTER
3265 black_TWorker worker[1];
3266 #endif
3267
3268 Long buffer[FT_MAX_BLACK_POOL];
3269
3270
3271 if ( !raster )
3272 return FT_THROW( Not_Ini );
3273
3274 if ( !outline )
3275 return FT_THROW( Invalid );
3276
3277 /* return immediately if the outline is empty */
3278 if ( outline->n_points == 0 || outline->n_contours <= 0 )
3279 return Raster_Err_None;
3280
3281 if ( !outline->contours || !outline->points )
3282 return FT_THROW( Invalid );
3283
3284 if ( outline->n_points !=
3285 outline->contours[outline->n_contours - 1] + 1 )
3286 return FT_THROW( Invalid );
3288 /* this version of the raster does not support direct rendering, sorry */
3289 if ( params->flags & FT_RASTER_FLAG_DIRECT )
3290 return FT_THROW( Unsupported );
3291
3292 if ( params->flags & FT_RASTER_FLAG_AA )
3293 return FT_THROW( Unsupported );
3294
3295 if ( !target_map )
3296 return FT_THROW( Invalid );
3297
3298 /* nothing to do */
3299 if ( !target_map->width || !target_map->rows )
3300 return Raster_Err_None;
3301
3302 if ( !target_map->buffer )
3303 return FT_THROW( Invalid );
3304
3305 ras.outline = *outline;
3306 ras.target = *target_map;
3307
3308 ras.buff = buffer;
3309 ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
3310
3311 return Render_Glyph( RAS_VAR );
3312 }
3313
3314
3315 FT_DEFINE_RASTER_FUNCS(
3316 ft_standard_raster,
3317
3318 FT_GLYPH_FORMAT_OUTLINE,
3319
3320 (FT_Raster_New_Func) ft_black_new, /* raster_new */
3321 (FT_Raster_Reset_Func) ft_black_reset, /* raster_reset */
3322 (FT_Raster_Set_Mode_Func)ft_black_set_mode, /* raster_set_mode */
3323 (FT_Raster_Render_Func) ft_black_render, /* raster_render */
3324 (FT_Raster_Done_Func) ft_black_done /* raster_done */
3325 )
3326
3327
3328 /* END */
|