66 #if !defined ( WIN32 ) || defined ( __GNUC__ )
71 int access(
char *filename,
int flag )
74 infile = fopen( filename,
"r" );
87 #define makeunixslash( b ) do { char *I; for ( I = b; *I != 0; *I++ ) if ( *I == '\\' ) *I = '/';} while ( 0 )
92 #ifdef PL_HAVE_FREETYPE
96 #define FT_Data _FT_Data_
110 #define TEXT_SCALING_FACTOR .7
115 #define NTEXT_ALLOC 1024
121 #define Debug6( a, b, c, d, e, f ) do { if ( pls->debug ) { fprintf( stderr, a, b, c, d, e, f ); } } while ( 0 )
128 void plD_FreeType_init(
PLStream *pls );
130 void plD_FreeType_Destroy(
PLStream *pls );
131 void pl_set_extended_cmap0(
PLStream *pls,
int ncol0_width,
int ncol0_org );
132 void pl_RemakeFreeType_text_from_buffer(
PLStream *pls );
137 static void FT_PlotChar(
PLStream *pls, FT_Data *FT, FT_GlyphSlot slot,
int x,
int y );
139 static PLFLT CalculateIncrement(
int bg,
int fg,
int levels );
149 static void FT_StrX_YW(
PLStream *pls,
const PLUNICODE *
text,
short len,
int *xx,
int *yy,
int *overyy,
int *underyy );
162 FT_StrX_YW(
PLStream *pls,
const PLUNICODE *
text,
short len,
int *xx,
int *yy,
int *overyy,
int *underyy )
164 FT_Data *FT = (FT_Data *) pls->
FT;
166 FT_Vector akerning, adjust;
167 int x = 0,
y = 0, startingy;
179 y -= (int) FT->face->size->metrics.height;
188 for ( i = 0; i < len; i++ )
195 switch ( text[i + 1] )
199 adjust.y = FT->face->size->metrics.height / 2;
201 FT_Vector_Transform( &adjust, &FT->matrix );
205 *overyy =
y - startingy < *overyy ?
y - startingy : *overyy;
211 adjust.y = -FT->face->size->metrics.height / 2;
213 FT_Vector_Transform( &adjust, &FT->matrix );
217 *underyy = startingy -
y < *underyy ? startingy -
y : *underyy;
225 FT_SetFace( pls, text[i] );
226 *yy = (int) ( FT->face->size->metrics.height > -*yy ? -FT->face->size->metrics.height : *yy );
231 if ( ( i > 0 ) && FT_HAS_KERNING( FT->face ) )
233 FT_Get_Kerning( FT->face,
238 x += (int) ( akerning.x >> 6 );
251 FT_Load_Char( FT->face, text[i], FT_LOAD_MONOCHROME + FT_LOAD_RENDER );
259 x += (int) ( FT->face->glyph->advance.x );
260 y -= (int) ( FT->face->glyph->advance.y );
289 FT_Data *FT = (FT_Data *) pls->
FT;
290 short i = 0, last_char = -1;
291 FT_Vector akerning, adjust;
313 #ifdef DODGIE_DECENDER_HACK
314 adjust.y = ( FT->face->descender >> 6 ) * 3;
316 adjust.y = ( FT->face->descender >> 6 );
327 FT_Vector_Transform( &adjust, &FT->matrix );
346 for ( i = 0; i < len; i++ )
353 switch ( text[i + 1] )
366 adjust.y = FT->face->size->metrics.height / 2;
368 FT_Vector_Transform( &adjust, &FT->matrix );
376 adjust.y = -FT->face->size->metrics.height / 2;
378 FT_Vector_Transform( &adjust, &FT->matrix );
385 else if ( text[i] & PL_FCI_MARK )
388 FT_SetFace( pls, text[i] );
389 FT = (FT_Data *) pls->
FT;
390 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
395 if ( ( last_char != -1 ) && ( i > 0 ) && FT_HAS_KERNING( FT->face ) )
397 FT_Get_Kerning( FT->face,
400 ft_kerning_default, &akerning );
401 x += (int) akerning.x;
402 y -= (
int) akerning.y;
406 FT_Load_Char( FT->face, text[i], ( FT->smooth_text == 0 ) ? FT_LOAD_MONOCHROME + FT_LOAD_RENDER : FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT );
407 FT_PlotChar( pls, FT, FT->face->glyph,
410 x += (int) FT->face->glyph->advance.x;
411 y -= (
int) FT->face->glyph->advance.y;
426 FT_PlotChar(
PLStream *pls, FT_Data *FT, FT_GlyphSlot slot,
429 unsigned char bittest;
431 int n = slot->bitmap.pitch;
432 int current_pixel_colour;
437 short imin, imax, kmin, kmax;
440 PLINT clipxmin, clipymin, clipxmax, clipymax, tmp;
441 PLINT clpxmi, clpxma, clpymi, clpyma;
451 difilt( &clipxmin, &clipymin, 1, &clpxmi, &clpxma, &clpymi, &clpyma );
452 difilt( &clipxmax, &clipymax, 1, &clpxmi, &clpxma, &clpymi, &clpyma );
456 if ( FT->scale != 0.0 )
458 clipxmin = (
PLINT) ( clipxmin / FT->scale );
459 clipxmax = (
PLINT) ( clipxmax / FT->scale );
460 if ( FT->invert_y == 1 )
462 clipymin = (
PLINT) ( FT->ymax - ( clipymin / FT->scale ) );
463 clipymax = (
PLINT) ( FT->ymax - ( clipymax / FT->scale ) );
467 clipymin = (
PLINT) ( clipymin / FT->scale );
468 clipymax = (
PLINT) ( clipymax / FT->scale );
473 clipxmin = (
PLINT) ( clipxmin / FT->scalex );
474 clipxmax = (
PLINT) ( clipxmax / FT->scalex );
476 if ( FT->invert_y == 1 )
478 clipymin = (
PLINT) ( FT->ymax - ( clipymin / FT->scaley ) );
479 clipymax = (
PLINT) ( FT->ymax - ( clipymax / FT->scaley ) );
483 clipymin = (
PLINT) ( clipymin / FT->scaley );
484 clipymax = (
PLINT) ( clipymax / FT->scaley );
487 if ( clipxmin > clipxmax )
493 if ( clipymin > clipymax )
504 if ( slot->bitmap.pixel_mode == ft_pixel_mode_mono )
506 x += slot->bitmap_left;
507 y -= slot->bitmap_top;
509 imin = (short)
MAX( 0, clipymin - y );
510 imax = (short)
MIN( slot->bitmap.rows, clipymax - y );
511 for ( i = imin; i < imax; i++ )
513 for ( k = 0; k < n; k++ )
516 for ( j = 0; j < 8; j++ )
518 if ( ( bittest & (
unsigned char) slot->bitmap.buffer[( i * n ) + k] ) == bittest )
520 xx = x + ( k * 8 ) + j;
521 if ( ( xx >= clipxmin ) && ( xx <= clipxmax ) )
522 FT->pixel( pls, xx, y + i );
534 x += slot->bitmap_left;
535 y -= slot->bitmap_top;
537 imin = (short)
MAX( 0, clipymin - y );
538 imax = (short)
MIN( slot->bitmap.rows, clipymax - y );
539 kmin = (short)
MAX( 0, clipxmin - x );
540 kmax = (short)
MIN( slot->bitmap.width, clipxmax - x );
541 for ( i = imin; i < imax; i++ )
543 for ( k = kmin; k < kmax; k++ )
545 FT->shade = ( slot->bitmap.buffer[( i * slot->bitmap.width ) + k] );
548 if ( ( FT->BLENDED_ANTIALIASING == 1 ) && ( FT->read_pixel != NULL ) )
551 if ( FT->shade == 255 )
553 FT->pixel( pls, x + k, y + i );
557 current_pixel_colour = FT->read_pixel( pls, x + k, y + i );
559 G = GetGValue( current_pixel_colour );
560 R = GetRValue( current_pixel_colour );
561 B = GetBValue( current_pixel_colour );
562 alpha_a = (float) FT->shade / 255.0;
579 R = (
int) ( ( ( plsc->curcolor.r - R ) * alpha_a ) + R );
580 G = (int) ( ( ( plsc->curcolor.g - G ) * alpha_a ) + G );
581 B = (int) ( ( ( plsc->curcolor.b - B ) * alpha_a ) + B );
583 FT->set_pixel( pls, x + k, y + i, RGB( R > 255 ? 255 : R, G > 255 ? 255 : G, B > 255 ? 255 : B ) );
588 FT->col_idx = FT->ncol0_width - ( ( FT->ncol0_width * FT->shade ) / 255 );
589 FT->last_icol0 = pls->
icol0;
590 plcol0( pls->
icol0 + ( FT->col_idx * ( FT->ncol0_org - 1 ) ) );
591 FT->pixel( pls, x + k, y + i );
608 void plD_FreeType_init(
PLStream *pls )
616 "PLPLOT_FREETYPE_SANS_FONT",
617 "PLPLOT_FREETYPE_SERIF_FONT",
618 "PLPLOT_FREETYPE_MONO_FONT",
619 "PLPLOT_FREETYPE_SCRIPT_FONT",
620 "PLPLOT_FREETYPE_SYMBOL_FONT",
621 "PLPLOT_FREETYPE_SANS_ITALIC_FONT",
622 "PLPLOT_FREETYPE_SERIF_ITALIC_FONT",
623 "PLPLOT_FREETYPE_MONO_ITALIC_FONT",
624 "PLPLOT_FREETYPE_SCRIPT_ITALIC_FONT",
625 "PLPLOT_FREETYPE_SYMBOL_ITALIC_FONT",
626 "PLPLOT_FREETYPE_SANS_OBLIQUE_FONT",
627 "PLPLOT_FREETYPE_SERIF_OBLIQUE_FONT",
628 "PLPLOT_FREETYPE_MONO_OBLIQUE_FONT",
629 "PLPLOT_FREETYPE_SCRIPT_OBLIQUE_FONT",
630 "PLPLOT_FREETYPE_SYMBOL_OBLIQUE_FONT",
631 "PLPLOT_FREETYPE_SANS_BOLD_FONT",
632 "PLPLOT_FREETYPE_SERIF_BOLD_FONT",
633 "PLPLOT_FREETYPE_MONO_BOLD_FONT",
634 "PLPLOT_FREETYPE_SCRIPT_BOLD_FONT",
635 "PLPLOT_FREETYPE_SYMBOL_BOLD_FONT",
636 "PLPLOT_FREETYPE_SANS_BOLD_ITALIC_FONT",
637 "PLPLOT_FREETYPE_SERIF_BOLD_ITALIC_FONT",
638 "PLPLOT_FREETYPE_MONO_BOLD_ITALIC_FONT",
639 "PLPLOT_FREETYPE_SCRIPT_BOLD_ITALIC_FONT",
640 "PLPLOT_FREETYPE_SYMBOL_BOLD_ITALIC_FONT",
641 "PLPLOT_FREETYPE_SANS_BOLD_OBLIQUE_FONT",
642 "PLPLOT_FREETYPE_SERIF_BOLD_OBLIQUE_FONT",
643 "PLPLOT_FREETYPE_MONO_BOLD_OBLIQUE_FONT",
644 "PLPLOT_FREETYPE_SCRIPT_BOLD_OBLIQUE_FONT",
645 "PLPLOT_FREETYPE_SYMBOL_BOLD_OBLIQUE_FONT"
649 #if defined ( MSDOS ) || defined ( WIN32 )
650 static char *default_font_names[] = {
"arial.ttf",
"times.ttf",
"timesi.ttf",
"arial.ttf",
654 b = getenv(
"WINDIR" );
664 plwarn(
"Freetype seems already to have been initialised!" );
668 if ( ( pls->
FT = calloc( 1, (
size_t)
sizeof ( FT_Data ) ) ) == NULL )
669 plexit(
"Could not allocate memory for Freetype" );
671 FT = (FT_Data *) pls->
FT;
673 if ( ( FT->textbuf = calloc( NTEXT_ALLOC, 1 ) ) == NULL )
674 plexit(
"Could not allocate memory for Freetype text buffer" );
676 if ( FT_Init_FreeType( &FT->library ) )
677 plexit(
"Could not initialise Freetype library" );
682 #if defined ( MSDOS ) || defined ( WIN32 )
687 if ( ( a = getenv(
"PLPLOT_FREETYPE_FONT_DIR" ) ) != NULL )
691 else if ( WINDIR_PATH == NULL )
694 if ( access(
"c:\\windows\\fonts\\arial.ttf", F_OK ) == 0 )
696 strcpy( font_dir,
"c:/windows/fonts/" );
698 else if ( access(
"c:\\windows\\system\\arial.ttf", F_OK ) == 0 )
700 strcpy( font_dir,
"c:/windows/system/" );
703 plwarn(
"Could not find font path; I sure hope you have defined fonts manually !" );
708 strncat( WINDIR_PATH,
"\\fonts\\arial.ttf",
PLPLOT_MAX_PATH - 1 - strlen( WINDIR_PATH ) );
709 if ( access( WINDIR_PATH, F_OK ) == 0 )
711 b = strrchr( WINDIR_PATH,
'\\' );
715 strcpy( font_dir, WINDIR_PATH );
718 plwarn(
"Could not find font path; I sure hope you have defined fonts manually !" );
723 fprintf( stderr,
"%s\n", font_dir );
734 if ( ( a = getenv(
"PLPLOT_FREETYPE_FONT_DIR" ) ) != NULL )
750 if ( ( a = getenv( env_font_names[i] ) ) != NULL )
764 if ( ( a[0] ==
'/' ) || ( a[0] ==
'~' ) )
771 strncat( FT->font_name[i], a,
PLPLOT_MAX_PATH - 1 - strlen( FT->font_name[i] ) );
783 if ( ( infile = fopen( FT->font_name[i],
"r" ) ) == NULL )
787 "plD_FreeType_init: Could not find the freetype compatible font:\n %s",
797 if ( FT->font_name[i][0] ==
'\0' )
798 FontLookup[i].pfont = NULL;
800 FontLookup[i].pfont = (
unsigned char *) FT->font_name[i];
817 FT_Data *FT = (FT_Data *) pls->
FT;
818 double font_size = pls->
chrht * 72 / 25.4;
821 FT->chrht = pls->
chrht;
822 FT->xdpi = pls->
xdpi;
823 FT->ydpi = pls->
ydpi;
825 if ( fci != FT->fci )
827 const char *font_name =
plP_FCI2FontName( fci, FontLookup, N_TrueTypeLookup );
828 if ( font_name == NULL )
831 plexit(
"FT_SetFace: Bad FCI and no previous valid font to fall back on" );
833 plwarn(
"FT_SetFace: Bad FCI. Falling back to previous font." );
839 if ( FT->face != NULL )
841 FT_Done_Face( FT->face );
845 if ( FT->face == NULL )
847 if ( FT_New_Face( FT->library, font_name, 0, &FT->face ) )
848 plexit(
"FT_SetFace: Error loading a font in freetype" );
853 if ( FT->face->charmap == NULL )
854 FT_Select_Charmap( FT->face, FT->face->charmaps[0]->encoding );
857 FT_Set_Char_Size( FT->face, 0,
858 (FT_F26Dot6) ( font_size * 64 / TEXT_SCALING_FACTOR ), (FT_UInt) pls->
xdpi,
859 (FT_UInt) pls->
ydpi );
872 FT_Data *FT = (FT_Data *) pls->
FT;
874 int w = 0, h = 0, overh = 0, underh = 0;
880 int prevlineheights = 0;
900 if ( ( FT->fci != fci ) || ( FT->chrht != pls->
chrht ) || ( FT->xdpi != pls->
xdpi ) || ( FT->ydpi != pls->
ydpi ) )
901 FT_SetFace( pls, fci );
906 Debug6(
"%s %d %d %d %d\n",
"plD_render_freetype_text:",
907 FT->face->underline_position >> 6,
908 FT->face->descender >> 6,
909 FT->face->ascender >> 6,
910 ( ( FT->face->underline_position * -1 ) + FT->face->ascender ) >> 6 );
931 FT->matrix.xx = 0x10000;
932 FT->matrix.xy = 0x00000;
933 FT->matrix.yx = 0x00000;
934 FT->matrix.yy = 0x10000;
936 FT_Vector_Transform( &FT->pos, &FT->matrix );
937 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
939 FT_StrX_YW( pls,
line, (
short) linelen, &w, &h, &overh, &underh );
964 height_factor = (
PLFLT) ( FT->face->ascender - FT->face->descender )
965 / FT->face->ascender;
966 height = (FT_Fixed) ( 0x10000 * height_factor );
969 FT->matrix.xx = (FT_Fixed) ( (
PLFLT) height * t[0] );
970 FT->matrix.xy = (FT_Fixed) ( (
PLFLT) height * t[2] );
971 FT->matrix.yx = (FT_Fixed) ( (
PLFLT) height * t[1] );
972 FT->matrix.yy = (FT_Fixed) ( (
PLFLT) height * t[3] );
974 FT->matrix.xx = (FT_Fixed) ( (
PLFLT) height * t[0] );
975 FT->matrix.xy = (FT_Fixed) ( (
PLFLT) height * t[1] );
976 FT->matrix.yx = (FT_Fixed) ( (
PLFLT) height * t[2] );
977 FT->matrix.yy = (FT_Fixed) ( (
PLFLT) height * t[3] );
988 Cos_A = cos( angle );
989 Sin_A = sin( angle );
991 matrix.xx = (FT_Fixed) ( (
PLFLT) 0x10000 * Cos_A );
994 matrix.xy = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A * -1.0 );
995 matrix.yx = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A );
997 matrix.xy = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A );
998 matrix.yx = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A * -1.0 );
1001 matrix.yy = (FT_Fixed) ( (
PLFLT) 0x10000 * Cos_A );
1003 FT_Matrix_Multiply( &matrix, &FT->matrix );
1015 FT_Vector_Transform( &FT->pos, &FT->matrix );
1027 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
1043 if ( FT->scale != 0.0 )
1045 x = (int) ( args->
x / FT->scale );
1047 if ( FT->invert_y == 1 )
1048 y = (int) ( FT->ymax - ( args->
y / FT->scale ) );
1050 y = (int) ( args->
y / FT->scale );
1054 x = (int) ( args->
x / FT->scalex );
1056 if ( FT->invert_y == 1 )
1057 y = (int) ( FT->ymax - ( args->
y / FT->scaley ) );
1059 y = (int) ( args->
y / FT->scaley );
1084 #ifdef DODGIE_DECENDER_HACK
1111 adjust.x = (FT_Pos) ( args->
just *
ROUND( (
PLFLT) FT->face->glyph->metrics.width / 64.0 ) );
1112 adjust.y = (FT_Pos)
ROUND( (
PLFLT) FT->face->glyph->metrics.height / 128.0 );
1126 ROUND( (
PLFLT) FT->face->size->metrics.height / height_factor / 128.0 - ( prevlineheights + overh ) / 64.0 );
1127 adjust.x = (FT_Pos) ( args->
just *
ROUND( w / 64.0 ) );
1130 FT_Vector_Transform( &adjust, &FT->matrix );
1132 x -= (int) adjust.x;
1133 y += (
int) adjust.y;
1135 FT_WriteStrW( pls,
line, (
short) linelen, x, y );
1140 line += linelen + 1;
1141 prevlineheights += h + overh + underh;
1146 plD_render_freetype_sym( pls, args );
1158 void plD_FreeType_Destroy(
PLStream *pls )
1160 FT_Data *FT = (FT_Data *) pls->
FT;
1165 if ( ( FT->smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) )
1168 free( FT->textbuf );
1169 FT_Done_Library( FT->library );
1184 static PLFLT CalculateIncrement(
int bg,
int fg,
int levels )
1191 ret = ( ( fg + 1 ) - bg ) / levels;
1193 ret = ( ( ( fg - 1 ) - bg ) / levels );
1213 void pl_set_extended_cmap0(
PLStream *pls,
int ncol0_width,
int ncol0_org )
1217 PLFLT r_inc, g_inc, b_inc;
1219 for ( i = 1; i < ncol0_org; i++ )
1225 r_inc = CalculateIncrement( pls->
cmap0[0].
r, r, ncol0_width );
1226 g_inc = CalculateIncrement( pls->
cmap0[0].
g, g, ncol0_width );
1227 b_inc = CalculateIncrement( pls->
cmap0[0].
b, b, ncol0_width );
1229 for ( j = 0, k = ncol0_org + i - 1; j < ncol0_width; j++, k += ( ncol0_org - 1 ) )
1234 if ( ( r < 0 ) || ( g < 0 ) || ( b < 0 ) )
1237 plscol0( k, ( r > 0xff ? 0xff : r ), ( g > 0xff ? 0xff : g ), ( b > 0xff ? 0xff : b ) );
1257 FT_Data *FT = (FT_Data *) pls->
FT;
1262 if ( FT->scale != 0.0 )
1264 x = (int) ( args->
x / FT->scale );
1266 if ( FT->invert_y == 1 )
1267 y = (int) ( FT->ymax - ( args->
y / FT->scale ) );
1269 y = (int) ( args->
y / FT->scale );
1273 x = (int) ( args->
x / FT->scalex );
1275 if ( FT->invert_y == 1 )
1276 y = (int) ( FT->ymax - ( args->
y / FT->scaley ) );
1278 y = (int) ( args->
y / FT->scaley );
1298 #ifdef DODGIE_DECENDER_HACK
1299 adjust.y = ( FT->face->descender >> 6 ) * 3;
1301 adjust.y = ( FT->face->descender >> 6 );
1305 FT_Vector_Transform( &adjust, &FT->matrix );
1306 x += (int) adjust.x;
1307 y -= (
int) adjust.y;
1310 FT_SetFace( pls, fci );
1312 FT = (FT_Data *) pls->
FT;
1313 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
1315 FT_Load_Char( FT->face, args->
unicode_char, ( FT->smooth_text == 0 ) ? FT_LOAD_MONOCHROME + FT_LOAD_RENDER : FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT );
1325 x -= (int) ( ( FT->face->glyph->advance.x >> 6 ) / 2 );
1326 FT_PlotChar( pls, FT, FT->face->glyph, x, y );