📄 ftgrays.c
字号:
if ( point < limit ) { FT_Vector vec; FT_Vector v_middle; point++; tags++; tag = FT_CURVE_TAG( tags[0] ); vec.x = SCALED( point->x ); vec.y = SCALED( point->y ); if ( tag == FT_CURVE_TAG_ON ) { error = func_interface->conic_to( &v_control, &vec, user ); if ( error ) goto Exit; continue; } if ( tag != FT_CURVE_TAG_CONIC ) goto Invalid_Outline; v_middle.x = ( v_control.x + vec.x ) / 2; v_middle.y = ( v_control.y + vec.y ) / 2; error = func_interface->conic_to( &v_control, &v_middle, user ); if ( error ) goto Exit; v_control = vec; goto Do_Conic; } error = func_interface->conic_to( &v_control, &v_start, user ); goto Close; } default: /* FT_CURVE_TAG_CUBIC */ { FT_Vector vec1, vec2; if ( point + 1 > limit || FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) goto Invalid_Outline; point += 2; tags += 2; vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y ); vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y ); if ( point <= limit ) { FT_Vector vec; vec.x = SCALED( point->x ); vec.y = SCALED( point->y ); error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); if ( error ) goto Exit; continue; } error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); goto Close; } } } /* close the contour with a line segment */ error = func_interface->line_to( &v_start, user ); Close: if ( error ) goto Exit; first = last + 1; } return 0; Exit: return error; Invalid_Outline: return ErrRaster_Invalid_Outline; }#endif /* _STANDALONE_ */ typedef struct TBand_ { TPos min, max; } TBand; static int gray_convert_glyph_inner( RAS_ARG ) { static const FT_Outline_Funcs func_interface = { (FT_Outline_MoveTo_Func) gray_move_to, (FT_Outline_LineTo_Func) gray_line_to, (FT_Outline_ConicTo_Func)gray_conic_to, (FT_Outline_CubicTo_Func)gray_cubic_to, 0, 0 }; volatile int error = 0; if ( ft_setjmp( ras.jump_buffer ) == 0 ) { error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); gray_record_cell( RAS_VAR ); } else { error = ErrRaster_Memory_Overflow; } return error; } static int gray_convert_glyph( RAS_ARG ) { TBand bands[40]; TBand* volatile band; int volatile n, num_bands; TPos volatile min, max, max_y; FT_BBox* clip; /* Set up state in the raster object */ gray_compute_cbox( RAS_VAR ); /* clip to target bitmap, exit if nothing to do */ clip = &ras.clip_box; if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax || ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax ) return 0; if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin; if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin; if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax; if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax; ras.count_ex = ras.max_ex - ras.min_ex; ras.count_ey = ras.max_ey - ras.min_ey; /* simple heuristic used to speed-up the bezier decomposition -- see */ /* the code in gray_render_conic() and gray_render_cubic() for more */ /* details */ ras.conic_level = 32; ras.cubic_level = 16; { int level = 0; if ( ras.count_ex > 24 || ras.count_ey > 24 ) level++; if ( ras.count_ex > 120 || ras.count_ey > 120 ) level++; ras.conic_level <<= level; ras.cubic_level <<= level; } /* setup vertical bands */ num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size ); if ( num_bands == 0 ) num_bands = 1; if ( num_bands >= 39 ) num_bands = 39; ras.band_shoot = 0; min = ras.min_ey; max_y = ras.max_ey; for ( n = 0; n < num_bands; n++, min = max ) { max = min + ras.band_size; if ( n == num_bands - 1 || max > max_y ) max = max_y; bands[0].min = min; bands[0].max = max; band = bands; while ( band >= bands ) { TPos bottom, top, middle; int error; { PCell cells_max; int yindex; long cell_start, cell_end, cell_mod; ras.ycells = (PCell*)ras.buffer; ras.ycount = band->max - band->min; cell_start = sizeof ( PCell ) * ras.ycount; cell_mod = cell_start % sizeof ( TCell ); if ( cell_mod > 0 ) cell_start += sizeof ( TCell ) - cell_mod; cell_end = ras.buffer_size; cell_end -= cell_end % sizeof( TCell ); cells_max = (PCell)( (char*)ras.buffer + cell_end ); ras.cells = (PCell)( (char*)ras.buffer + cell_start ); if ( ras.cells >= cells_max ) goto ReduceBands; ras.max_cells = cells_max - ras.cells; if ( ras.max_cells < 2 ) goto ReduceBands; for ( yindex = 0; yindex < ras.ycount; yindex++ ) ras.ycells[yindex] = NULL; } ras.num_cells = 0; ras.invalid = 1; ras.min_ey = band->min; ras.max_ey = band->max; ras.count_ey = band->max - band->min; error = gray_convert_glyph_inner( RAS_VAR ); if ( !error ) { gray_sweep( RAS_VAR_ &ras.target ); band--; continue; } else if ( error != ErrRaster_Memory_Overflow ) return 1; ReduceBands: /* render pool overflow; we will reduce the render band by half */ bottom = band->min; top = band->max; middle = bottom + ( ( top - bottom ) >> 1 ); /* This is too complex for a single scanline; there must */ /* be some problems. */ if ( middle == bottom ) {#ifdef DEBUG_GRAYS fprintf( stderr, "Rotten glyph!\n" );#endif return 1; } if ( bottom-top >= ras.band_size ) ras.band_shoot++; band[1].min = bottom; band[1].max = middle; band[0].min = middle; band[0].max = top; band++; } } if ( ras.band_shoot > 8 && ras.band_size > 16 ) ras.band_size = ras.band_size / 2; return 0; } static int gray_raster_render( PRaster raster, const FT_Raster_Params* params ) { const FT_Outline* outline = (const FT_Outline*)params->source; const FT_Bitmap* target_map = params->target; PWorker worker; if ( !raster || !raster->buffer || !raster->buffer_size ) return ErrRaster_Invalid_Argument; /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0; if ( !outline || !outline->contours || !outline->points ) return ErrRaster_Invalid_Outline; if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 ) return ErrRaster_Invalid_Outline; worker = raster->worker; /* if direct mode is not set, we must have a target bitmap */ if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 ) { if ( !target_map ) return ErrRaster_Invalid_Argument; /* nothing to do */ if ( !target_map->width || !target_map->rows ) return 0; if ( !target_map->buffer ) return ErrRaster_Invalid_Argument; } /* this version does not support monochrome rendering */ if ( !( params->flags & FT_RASTER_FLAG_AA ) ) return ErrRaster_Invalid_Mode; /* compute clipping box */ if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 ) { /* compute clip box from target pixmap */ ras.clip_box.xMin = 0; ras.clip_box.yMin = 0; ras.clip_box.xMax = target_map->width; ras.clip_box.yMax = target_map->rows; } else if ( params->flags & FT_RASTER_FLAG_CLIP ) { ras.clip_box = params->clip_box; } else { ras.clip_box.xMin = -32768L; ras.clip_box.yMin = -32768L; ras.clip_box.xMax = 32767L; ras.clip_box.yMax = 32767L; } gray_init_cells( worker, raster->buffer, raster->buffer_size ); ras.outline = *outline; ras.num_cells = 0; ras.invalid = 1; ras.band_size = raster->band_size; ras.num_gray_spans = 0; if ( target_map ) ras.target = *target_map; ras.render_span = (FT_Raster_Span_Func)gray_render_span; ras.render_span_data = &ras; if ( params->flags & FT_RASTER_FLAG_DIRECT ) { ras.render_span = (FT_Raster_Span_Func)params->gray_spans; ras.render_span_data = params->user; } return gray_convert_glyph( worker ); } /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ /**** a static object. *****/#ifdef _STANDALONE_ static int gray_raster_new( void* memory, FT_Raster* araster ) { static TRaster the_raster; FT_UNUSED( memory ); *araster = (FT_Raster)&the_raster; FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) ); return 0; } static void gray_raster_done( FT_Raster raster ) { /* nothing */ FT_UNUSED( raster ); }#else /* _STANDALONE_ */ static int gray_raster_new( FT_Memory memory, FT_Raster* araster ) { FT_Error error; PRaster raster; *araster = 0; if ( !FT_ALLOC( raster, sizeof ( TRaster ) ) ) { raster->memory = memory; *araster = (FT_Raster)raster; } return error; } static void gray_raster_done( FT_Raster raster ) { FT_Memory memory = (FT_Memory)((PRaster)raster)->memory; FT_FREE( raster ); }#endif /* _STANDALONE_ */ static void gray_raster_reset( FT_Raster raster, char* pool_base, long pool_size ) { PRaster rast = (PRaster)raster; if ( raster ) { if ( pool_base && pool_size >= (long)sizeof ( TWorker ) + 2048 ) { PWorker worker = (PWorker)pool_base; rast->worker = worker; rast->buffer = pool_base + ( ( sizeof ( TWorker ) + sizeof ( TCell ) - 1 ) & ~( sizeof ( TCell ) - 1 ) ); rast->buffer_size = (long)( ( pool_base + pool_size ) - (char*)rast->buffer ) & ~( sizeof ( TCell ) - 1 ); rast->band_size = (int)( rast->buffer_size / ( sizeof ( TCell ) * 8 ) ); } else { rast->buffer = NULL; rast->buffer_size = 0; rast->worker = NULL; } } } const FT_Raster_Funcs ft_grays_raster = { FT_GLYPH_FORMAT_OUTLINE, (FT_Raster_New_Func) gray_raster_new, (FT_Raster_Reset_Func) gray_raster_reset, (FT_Raster_Set_Mode_Func)0, (FT_Raster_Render_Func) gray_raster_render, (FT_Raster_Done_Func) gray_raster_done };/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -