Commit f9ca2bb5 authored by David Turner's avatar David Turner
Browse files

managed to re-design entirely the API in <freetype/ftglyph.h>

It is now really the "glyph factory" that Stefan was probably
dreaming about..

fixed some recent formatting errors from Werner ;-)

cleaned up the demonstration programs from most of the
rust that they had, though I'm sure someone is going to
re-format them really soon !!

"ftstring" now uses the new ftglyph.h API, and is now
faster and smaller.. yep..
parent ac39ecdc
......@@ -152,83 +152,51 @@
char bit_buffer[MAX_BUFFER];
/* Render a single glyph with the "grays" component */
/* Render a single glyph with the `grays' component */
static
FT_Error Render_Glyph( int x_offset,
int y_offset )
{
FT_Bitmap bit2;
grBitmap bit3;
int width, height, pitch, size;
int left, right, top, bottom;
int x_top, y_top;
/* first, render the glyph into an intermediate buffer */
left = FLOOR( glyph->metrics.horiBearingX );
right = CEIL( glyph->metrics.horiBearingX + glyph->metrics.width );
width = TRUNC( right - left );
top = CEIL( glyph->metrics.horiBearingY );
bottom = FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height );
height = TRUNC( top - bottom );
if ( glyph->format == ft_glyph_format_outline )
grBitmap bit3;
FT_Pos x_top, y_top;
/* first, render the glyph image into a bitmap */
if (glyph->format != ft_glyph_format_bitmap)
{
pitch = antialias ? ( width + 3 ) & -4
: ( width + 7 ) >> 3;
size = pitch * height;
if ( size > MAX_BUFFER )
return FT_Err_Out_Of_Memory;
bit2.width = width;
bit2.rows = height;
bit2.pitch = pitch;
bit2.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono;
bit2.buffer = bit_buffer;
bit3.rows = bit2.rows;
bit3.width = bit2.width;
bit3.pitch = bit2.pitch;
bit3.mode = antialias ? bit.mode : gr_pixel_mode_mono;
bit3.buffer = bit_buffer;
bit3.grays = 256;
FT_Outline_Translate( &glyph->outline, -left, -bottom );
memset( bit_buffer, 0, size );
if ( low_prec )
glyph->outline.flags &= ~ft_outline_high_precision;
error = FT_Outline_Get_Bitmap( library, &glyph->outline, &bit2 );
error = FT_Render_Glyph( glyph, antialias ? ft_render_mode_normal : ft_render_mode_mono );
if (error) return error;
}
else
/* now blit it to our display screen */
bit3.rows = glyph->bitmap.rows;
bit3.width = glyph->bitmap.width;
bit3.pitch = glyph->bitmap.pitch;
bit3.buffer = glyph->bitmap.buffer;
switch (glyph->bitmap.pixel_mode)
{
bit3.rows = glyph->bitmap.rows;
bit3.width = glyph->bitmap.width;
bit3.pitch = glyph->bitmap.pitch;
bit3.mode = gr_pixel_mode_mono;
bit3.buffer = glyph->bitmap.buffer;
bit3.grays = 0;
case ft_pixel_mode_mono:
bit3.mode = gr_pixel_mode_mono;
bit3.grays = 0;
break;
case ft_pixel_mode_grays:
bit3.mode = gr_pixel_mode_gray;
bit3.grays = glyph->bitmap.num_grays;
}
/* then, blit the image to the target surface */
x_top = x_offset + TRUNC( left );
y_top = y_offset - TRUNC( top );
#if 0
if ( bit.pitch < 0 )
y_top = bit.rows - y_top;
#endif
/* Then, blit the image to the target surface */
x_top = x_offset + glyph->bitmap_left;
y_top = y_offset - glyph->bitmap_top;
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color );
return FT_Err_Ok;
return 0;
}
static
FT_Error Reset_Scale( int pointSize )
{
......@@ -239,11 +207,6 @@
pointSize << 6,
res,
res );
if ( error )
{
/* to be written */
}
return FT_Err_Ok;
}
......
......@@ -209,10 +209,12 @@
if (!glyph->image) continue;
x = glyph->pos.x >> 6;
y = glyph->pos.y >> 6;
x = glyph->pos.x;
y = glyph->pos.y;
FT_Glyph_Get_Box( glyph->image, &cbox );
FT_Glyph_Get_CBox( glyph->image,
ft_glyph_bbox_gridfit,
&cbox );
cbox.xMin += x;
cbox.yMin += y;
......@@ -230,7 +232,7 @@
/**************************************************************
*
* Layout a string of glyphs
* Layout a string of glyphs, the glyphs are untransformed..
*
*/
static void layout_glyphs( void )
......@@ -261,9 +263,9 @@
{
FT_Vector kern;
FT_Get_Kerning( face, prev_index, glyph->glyph_index, &kern );
kern.x = FT_MulFix( kern.x, face->size->metrics.x_scale );
if (hinted) kern.x = (kern.x+32) & -64;
FT_Get_Kerning( face, prev_index, glyph->glyph_index,
hinted ? ft_kerning_default : ft_kerning_unfitted,
&kern );
origin_x += kern.x;
}
......@@ -273,28 +275,24 @@
origin.x = origin_x;
origin.y = 0;
if (transform)
FT_Vector_Transform( &origin, &trans_matrix );
/* clear existing image if there is one */
if (glyph->image)
FT_Done_Glyph(glyph->image);
/* load the glyph image */
/* for now, we take a monochrome glyph bitmap */
error = FT_Get_Glyph_Bitmap( face, glyph->glyph_index,
load_flags,
num_grays,
&origin,
(FT_BitmapGlyph*)&glyph->image );
/* load the glyph image (in its native format) */
/* for now, we take a monochrome glyph bitmap */
error = FT_Load_Glyph( face, glyph->glyph_index,
hinted ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING ) ||
FT_Get_Glyph ( face->glyph, &glyph->image );
if (error) continue;
glyph->pos = origin;
origin_x += glyph->image->advance;
origin_x += face->glyph->advance.x;
}
string_center.x = origin_x / 2;
string_center.y = 0;
if (transform)
FT_Vector_Transform( &string_center, &trans_matrix );
}
......@@ -309,62 +307,81 @@
PGlyph glyph = glyphs;
grBitmap bit3;
int n;
FT_Vector delta;
/* first of all, we must compute the general delta for the glyph */
/* set.. */
delta.x = (x << 6) - string_center.x;
delta.y = ((bit.rows-y) << 6) - string_center.y;
for ( n = 0; n < num_glyphs; n++, glyph++ )
{
FT_Glyph image;
FT_Vector vec;
if (!glyph->image)
continue;
switch (glyph->image->glyph_type)
/* copy image */
error = FT_Glyph_Copy( glyph->image, &image );
if (error) continue;
/* transform it */
vec = glyph->pos;
FT_Vector_Transform( &vec, &trans_matrix );
vec.x += delta.x;
vec.y += delta.y;
error = FT_Glyph_Transform( image, &trans_matrix, &vec );
if (!error)
{
case ft_glyph_type_bitmap:
FT_BBox bbox;
/* check bounding box, if it's not within the display surface, we */
/* don't need to render it.. */
FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
if ( bbox.xMax > 0 && bbox.yMax > 0 &&
bbox.xMin < bit.width && bbox.yMin < bit.rows )
{
/* convert to a bitmap - destroy native image */
error = FT_Glyph_To_Bitmap( &image,
ft_render_mode_normal,
0, 1 );
if (!error)
{
/* this is a bitmap, we simply blit it to our target surface */
FT_BitmapGlyph bitm = (FT_BitmapGlyph)glyph->image;
FT_Bitmap* source = &bitm->bitmap;
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)image;
FT_Bitmap* source = &bitmap->bitmap;
FT_Pos x_top, y_top;
bit3.rows = source->rows;
bit3.width = source->width;
bit3.pitch = source->pitch;
bit3.buffer = source->buffer;
switch (source->pixel_mode)
{
case ft_pixel_mode_mono:
bit3.mode = gr_pixel_mode_mono;
break;
case ft_pixel_mode_grays:
bit3.mode = gr_pixel_mode_gray;
bit3.grays = source->num_grays;
break;
default:
continue;
}
/* now render the bitmap into the display surface */
x_top = x + (glyph->pos.x >> 6) + bitm->left;
y_top = y - (glyph->pos.y >> 6) - bitm->top;
x_top = bitmap->left;
y_top = bit.rows - bitmap->top;
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color );
}
break;
#if 0
case ft_glyph_type_outline:
{
/* in the case of outlines, we directly render it into the */
/* target surface with the smooth renderer.. */
FT_OutlineGlyph out = (FT_OutlineGlyph)glyph->image;
FT_Outline_Translate( (x+pen_pos[n]) << 6, (y+
error = FT_Outline_Render(
}
break;
#endif
default:
;
}
}
FT_Done_Glyph( image );
}
}
......@@ -407,8 +424,6 @@
trans_matrix.xy = -sinus;
trans_matrix.yx = sinus;
trans_matrix.yy = cosinus;
FT_Set_Transform(face,&trans_matrix, 0);
}
/****************************************************************************/
......@@ -723,8 +738,7 @@
reset_transform();
layout_glyphs();
compute_bbox( &bbox );
render_string( (bit.width-(string_center.x >> 5))/2,
(bit.rows +(string_center.y >> 5))/2 );
render_string( bit.width/2, bit.rows/2 );
}
sprintf( Header, "%s %s (file %s)",
......
......@@ -20,15 +20,13 @@
/****************************************************************************/
#include <freetype/freetype.h>
#include <freetype/ftrender.h>
#include <freetype/ftglyph.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> /* for clock() */
#include "graph.h"
/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include <sys/param.h> */
/* to get the HZ macro which is the equivalent. */
#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
......@@ -45,51 +43,28 @@
FT_Library library;
FT_Face face;
FT_Size size;
FT_GlyphSlot glyph;
FT_Outline outline;
FT_Pos* cur_x;
FT_Pos* cur_y;
unsigned short* cur_endContour;
unsigned char* cur_touch;
FT_Outline outlines[MAX_GLYPHS];
int num_glyphs;
FT_Glyph glyphs[MAX_GLYPHS];
int tab_glyphs;
int cur_glyph;
int cur_point;
unsigned short cur_contour;
int pixel_size = CHARSIZE;
int repeat_count = 1;
int use_grays = 0;
FT_Bitmap Bit;
grBitmap bit;
int Fail;
int Num;
int vio_Height, vio_Width;
short visual; /* display glyphs while rendering */
short antialias; /* smooth fonts with gray levels */
short antialias = 1; /* smooth fonts with gray levels */
short force_low;
#define RASTER_BUFF_SIZE 128000
char raster_buff[ RASTER_BUFF_SIZE ];
static void Clear_Buffer();
static void Panic( const char* message )
static
void Panic( const char* message )
{
fprintf( stderr, "%s\n error code = 0x%04x\n", message, error );
fprintf( stderr, "%s\n", message );
exit(1);
}
/*******************************************************************/
......@@ -106,45 +81,10 @@
}
/*******************************************************************/
/* */
/* Init_Engine: */
/* */
/* Allocates bitmap, render pool and other structs... */
/* */
/*******************************************************************/
void Init_Engine( void )
{
Bit.rows = bit.rows;
Bit.width = bit.width;
Bit.pitch = bit.pitch;
Bit.buffer = bit.buffer;
Bit.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono;
Bit.num_grays = bit.grays;
Clear_Buffer();
}
/*******************************************************************/
/* */
/* Clear_Buffer: */
/* */
/* Clears current bitmap. */
/* */
/*******************************************************************/
static void Clear_Buffer( void )
{
long size = Bit.rows * Bit.pitch;
memset( Bit.buffer, 0, size );
}
/*******************************************************************/
/* */
/* LoadTrueTypeChar: */
/* LoadChar: */
/* */
/* Loads a glyph into memory. */
/* */
......@@ -152,60 +92,20 @@
FT_Error LoadChar( int idx )
{
error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT );
if ( error )
return error;
glyph->outline.flags |= ft_outline_single_pass |
ft_outline_ignore_dropouts;
if (force_low)
glyph->outline.flags &= ~ft_outline_high_precision;
/* debugging */
#if 0
if ( idx == 0 && !visual )
{
printf( "points = %d\n", outline.points );
for ( j = 0; j < outline.points; j++ )
printf( "%02x (%01hx,%01hx)\n",
j, outline.xCoord[j], outline.yCoord[j] );
printf( "\n" );
}
#endif
/* create a new outline */
FT_Outline_New( library,
glyph->outline.n_points,
glyph->outline.n_contours,
&outlines[cur_glyph] );
/* copy the glyph outline into it */
glyph->outline.flags |= ft_outline_single_pass;
if (force_low)
glyph->outline.flags &= ~ft_outline_high_precision;
FT_Outline_Copy( &glyph->outline, &outlines[cur_glyph] );
/* center outline around 0 */
FT_Glyph glyph;
/* loads the glyph in the glyph slot */
error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) ||
FT_Get_Glyph ( face->glyph, &glyph );
if ( !error )
{
FT_BBox bbox;
FT_Outline_Get_CBox( &glyph->outline, &bbox );
FT_Outline_Translate( &outlines[cur_glyph],
- ( bbox.xMax - bbox.xMin )/2,
- ( bbox.yMax - bbox.yMin )/2 );
glyphs[cur_glyph++] = glyph;
}
/* translate it */
FT_Outline_Translate( &outlines[cur_glyph],
Bit.width * 32 ,
Bit.rows * 32 );
cur_glyph++;
return FT_Err_Ok;
return error;
}
/*******************************************************************/
/* */
/* ConvertRaster: */
......@@ -216,8 +116,19 @@
FT_Error ConvertRaster( int index )
{
outlines[index].flags |= ~ft_outline_single_pass;
return FT_Outline_Get_Bitmap( library, &outlines[index], &Bit );
FT_Glyph bitmap;
FT_Error error;
bitmap = glyphs[index];
error = FT_Glyph_To_Bitmap( &bitmap,
antialias ? ft_render_mode_normal
: ft_render_mode_mono,
0,
0 );
if (!error)
FT_Done_Glyph( bitmap );
return error;
}
......@@ -229,8 +140,7 @@
fprintf( stderr, "options:\n");
fprintf( stderr, " -r : repeat count to be used (default is 1)\n" );
fprintf( stderr, " -s : character pixel size (default is 600)\n" );
fprintf( stderr, " -v : display results..\n" );
fprintf( stderr, " -g : render anti-aliased glyphs\n" );
fprintf( stderr, " -m : render monochrome glyphs (default is anti-aliased)\n" );
fprintf( stderr, " -a : use smooth anti-aliaser\n" );
fprintf( stderr, " -l : force low quality even at small sizes\n" );
exit(1);
......@@ -243,37 +153,27 @@
char filename[128 + 4];
char alt_filename[128 + 4];
char* execname;
grSurface* surface = 0;
long t, t0, tz0;
execname = argv[0];
antialias = 0;
visual = 0;
force_low = 0;
antialias = 1;
force_low = 0;
while ( argc > 1 && argv[1][0] == '-' )
{
switch ( argv[1][1] )
{
case 'g':
antialias = 1;
break;
case 'a':
use_grays = 1;
case 'm':
antialias = 0;
break;
case 'l':
force_low = 1;
break;
case 'v':
visual = 1;
break;
case 's':
argc--;
argv++;
......@@ -328,17 +228,6 @@
if ( (error = FT_Init_FreeType( &library )) )
Panic( "Error while initializing engine" );
/* set-up smooth anti-aliaser */
if (use_grays)
{
FT_Renderer smooth;
smooth = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
if (!smooth) Panic( "Could not initialize smooth anti-aliasing renderer" );
FT_Set_Renderer( library, smooth, 0, 0 );
}
/* Load face */
error = FT_New_Face( library, filename, 0, &face );
......@@ -350,7 +239,6 @@
/* get face properties and allocate preload arrays */
num_glyphs = face->num_glyphs;
glyph = face->glyph;
tab_glyphs = MAX_GLYPHS;
if ( tab_glyphs > num_glyphs )
......@@ -361,32 +249,6 @@
error = FT_Set_Pixel_Sizes( face, pixel_size, pixel_size );
if ( error ) Panic( "Could not reset instance" );
bit.mode = antialias ? gr_pixel_mode_gray : gr_pixel_mode_mono;
bit.width = 640;
bit.rows = 480;
bit.grays = 128;
if ( visual )
{
if ( !grInitDevices() )