70 int access(
char *filename,
int flag )
73 infile = fopen( filename,
"r" );
88 #define makeunixslash( b ) do { char *I; for ( I = b; *I != 0; *I++ ) if ( *I == '\\' ) *I = '/';} while ( 0 ) 93 #ifdef PL_HAVE_FREETYPE 97 #define FT_Data _FT_Data_ 111 #define TEXT_SCALING_FACTOR .7 116 #define NTEXT_ALLOC 1024 122 #define Debug6( a, b, c, d, e, f ) do { if ( pls->debug ) { fprintf( stderr, a, b, c, d, e, f ); } } while ( 0 ) 132 void pl_set_extended_cmap0(
PLStream *
pls,
int ncol0_width,
int ncol0_org );
133 void pl_RemakeFreeType_text_from_buffer(
PLStream *
pls );
138 static void FT_PlotChar(
PLStream *
pls, FT_Data *FT, FT_GlyphSlot slot,
int x,
int y );
140 static PLFLT CalculateIncrement(
int bg,
int fg,
int levels );
150 static void FT_StrX_YW(
PLStream *
pls,
const PLUNICODE *
text,
short len,
int *xx,
int *yy,
int *overyy,
int *underyy );
165 FT_Data *FT = (FT_Data *) pls->
FT;
167 FT_Vector akerning, adjust;
168 int x = 0,
y = 0, startingy;
180 y -= (int) FT->face->size->metrics.height;
189 for ( i = 0; i < len; i++ )
196 switch ( text[i + 1] )
200 adjust.y = FT->face->size->metrics.height / 2;
202 FT_Vector_Transform( &adjust, &FT->matrix );
206 *overyy =
y - startingy < *overyy ?
y - startingy : *overyy;
212 adjust.y = -FT->face->size->metrics.height / 2;
214 FT_Vector_Transform( &adjust, &FT->matrix );
218 *underyy = startingy -
y < *underyy ? startingy -
y : *underyy;
226 FT_SetFace( pls, text[i] );
227 *yy = (int) ( FT->face->size->metrics.height > -*yy ? -FT->face->size->metrics.height : *yy );
232 if ( ( i > 0 ) && FT_HAS_KERNING( FT->face ) )
234 FT_Get_Kerning( FT->face,
239 x += (int) ( akerning.x >> 6 );
252 FT_Load_Char( FT->face, text[i], FT_LOAD_MONOCHROME + FT_LOAD_RENDER );
260 x += (int) ( FT->face->glyph->advance.x );
261 y -= (int) ( FT->face->glyph->advance.y );
290 FT_Data *FT = (FT_Data *) pls->
FT;
291 short i = 0, last_char = -1;
292 FT_Vector akerning, adjust;
314 #ifdef DODGIE_DECENDER_HACK 315 adjust.y = ( FT->face->descender >> 6 ) * 3;
317 adjust.y = ( FT->face->descender >> 6 );
328 FT_Vector_Transform( &adjust, &FT->matrix );
347 for ( i = 0; i < len; i++ )
354 switch ( text[i + 1] )
367 adjust.y = FT->face->size->metrics.height / 2;
369 FT_Vector_Transform( &adjust, &FT->matrix );
377 adjust.y = -FT->face->size->metrics.height / 2;
379 FT_Vector_Transform( &adjust, &FT->matrix );
386 else if ( text[i] & PL_FCI_MARK )
389 FT_SetFace( pls, text[i] );
390 FT = (FT_Data *) pls->
FT;
391 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
396 if ( ( last_char != -1 ) && ( i > 0 ) && FT_HAS_KERNING( FT->face ) )
398 FT_Get_Kerning( FT->face,
401 ft_kerning_default, &akerning );
402 x += (int) akerning.x;
403 y -= (
int) akerning.y;
407 FT_Load_Char( FT->face, text[i], ( FT->smooth_text == 0 ) ? FT_LOAD_MONOCHROME + FT_LOAD_RENDER : FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT );
408 FT_PlotChar( pls, FT, FT->face->glyph,
411 x += (int) FT->face->glyph->advance.x;
412 y -= (
int) FT->face->glyph->advance.y;
427 FT_PlotChar(
PLStream *pls, FT_Data *FT, FT_GlyphSlot slot,
430 unsigned char bittest;
432 int n = slot->bitmap.pitch;
433 int current_pixel_colour;
438 short imin, imax, kmin, kmax;
441 PLINT clipxmin, clipymin, clipxmax, clipymax, tmp;
442 PLINT clpxmi, clpxma, clpymi, clpyma;
452 difilt( &clipxmin, &clipymin, 1, &clpxmi, &clpxma, &clpymi, &clpyma );
453 difilt( &clipxmax, &clipymax, 1, &clpxmi, &clpxma, &clpymi, &clpyma );
457 if ( FT->scale != 0.0 )
459 clipxmin = (
PLINT) ( clipxmin / FT->scale );
460 clipxmax = (
PLINT) ( clipxmax / FT->scale );
461 if ( FT->invert_y == 1 )
463 clipymin = (
PLINT) ( FT->ymax - ( clipymin / FT->scale ) );
464 clipymax = (
PLINT) ( FT->ymax - ( clipymax / FT->scale ) );
468 clipymin = (
PLINT) ( clipymin / FT->scale );
469 clipymax = (
PLINT) ( clipymax / FT->scale );
474 clipxmin = (
PLINT) ( clipxmin / FT->scalex );
475 clipxmax = (
PLINT) ( clipxmax / FT->scalex );
477 if ( FT->invert_y == 1 )
479 clipymin = (
PLINT) ( FT->ymax - ( clipymin / FT->scaley ) );
480 clipymax = (
PLINT) ( FT->ymax - ( clipymax / FT->scaley ) );
484 clipymin = (
PLINT) ( clipymin / FT->scaley );
485 clipymax = (
PLINT) ( clipymax / FT->scaley );
488 if ( clipxmin > clipxmax )
494 if ( clipymin > clipymax )
505 if ( slot->bitmap.pixel_mode == ft_pixel_mode_mono )
507 x += slot->bitmap_left;
508 y -= slot->bitmap_top;
510 imin = (short)
MAX( 0, clipymin - y );
511 imax = (short)
MIN( slot->bitmap.rows, clipymax - y );
512 for ( i = imin; i < imax; i++ )
514 for ( k = 0; k < n; k++ )
517 for ( j = 0; j < 8; j++ )
519 if ( ( bittest & (
unsigned char) slot->bitmap.buffer[( i * n ) + k] ) == bittest )
521 xx = x + ( k * 8 ) + j;
522 if ( ( xx >= clipxmin ) && ( xx <= clipxmax ) )
523 FT->pixel( pls, xx, y + i );
535 x += slot->bitmap_left;
536 y -= slot->bitmap_top;
538 imin = (short)
MAX( 0, clipymin - y );
539 imax = (short)
MIN( slot->bitmap.rows, clipymax - y );
540 kmin = (short)
MAX( 0, clipxmin - x );
541 kmax = (short)
MIN( slot->bitmap.width, clipxmax - x );
542 for ( i = imin; i < imax; i++ )
544 for ( k = kmin; k < kmax; k++ )
546 FT->shade = ( slot->bitmap.buffer[( i * slot->bitmap.width ) + k] );
549 if ( ( FT->BLENDED_ANTIALIASING == 1 ) && ( FT->read_pixel != NULL ) )
552 if ( FT->shade == 255 )
554 FT->pixel( pls, x + k, y + i );
558 current_pixel_colour = FT->read_pixel( pls, x + k, y + i );
560 G = GetGValue( current_pixel_colour );
561 R = GetRValue( current_pixel_colour );
562 B = GetBValue( current_pixel_colour );
563 alpha_a = (float) FT->shade / 255.0;
580 R = (
int) ( ( ( plsc->curcolor.r - R ) * alpha_a ) + R );
581 G = (int) ( ( ( plsc->curcolor.g - G ) * alpha_a ) + G );
582 B = (int) ( ( ( plsc->curcolor.b - B ) * alpha_a ) + B );
584 FT->set_pixel( pls, x + k, y + i, RGB( R > 255 ? 255 : R, G > 255 ? 255 : G, B > 255 ? 255 : B ) );
589 FT->col_idx = FT->ncol0_width - ( ( FT->ncol0_width * FT->shade ) / 255 );
590 FT->last_icol0 = pls->
icol0;
591 plcol0( pls->
icol0 + ( FT->col_idx * ( FT->ncol0_org - 1 ) ) );
592 FT->pixel( pls, x + k, y + i );
609 void plD_FreeType_init(
PLStream *pls )
617 "PLPLOT_FREETYPE_SANS_FONT",
618 "PLPLOT_FREETYPE_SERIF_FONT",
619 "PLPLOT_FREETYPE_MONO_FONT",
620 "PLPLOT_FREETYPE_SCRIPT_FONT",
621 "PLPLOT_FREETYPE_SYMBOL_FONT",
622 "PLPLOT_FREETYPE_SANS_ITALIC_FONT",
623 "PLPLOT_FREETYPE_SERIF_ITALIC_FONT",
624 "PLPLOT_FREETYPE_MONO_ITALIC_FONT",
625 "PLPLOT_FREETYPE_SCRIPT_ITALIC_FONT",
626 "PLPLOT_FREETYPE_SYMBOL_ITALIC_FONT",
627 "PLPLOT_FREETYPE_SANS_OBLIQUE_FONT",
628 "PLPLOT_FREETYPE_SERIF_OBLIQUE_FONT",
629 "PLPLOT_FREETYPE_MONO_OBLIQUE_FONT",
630 "PLPLOT_FREETYPE_SCRIPT_OBLIQUE_FONT",
631 "PLPLOT_FREETYPE_SYMBOL_OBLIQUE_FONT",
632 "PLPLOT_FREETYPE_SANS_BOLD_FONT",
633 "PLPLOT_FREETYPE_SERIF_BOLD_FONT",
634 "PLPLOT_FREETYPE_MONO_BOLD_FONT",
635 "PLPLOT_FREETYPE_SCRIPT_BOLD_FONT",
636 "PLPLOT_FREETYPE_SYMBOL_BOLD_FONT",
637 "PLPLOT_FREETYPE_SANS_BOLD_ITALIC_FONT",
638 "PLPLOT_FREETYPE_SERIF_BOLD_ITALIC_FONT",
639 "PLPLOT_FREETYPE_MONO_BOLD_ITALIC_FONT",
640 "PLPLOT_FREETYPE_SCRIPT_BOLD_ITALIC_FONT",
641 "PLPLOT_FREETYPE_SYMBOL_BOLD_ITALIC_FONT",
642 "PLPLOT_FREETYPE_SANS_BOLD_OBLIQUE_FONT",
643 "PLPLOT_FREETYPE_SERIF_BOLD_OBLIQUE_FONT",
644 "PLPLOT_FREETYPE_MONO_BOLD_OBLIQUE_FONT",
645 "PLPLOT_FREETYPE_SCRIPT_BOLD_OBLIQUE_FONT",
646 "PLPLOT_FREETYPE_SYMBOL_BOLD_OBLIQUE_FONT" 650 #if defined ( MSDOS ) || defined ( _WIN32 ) 651 static char *default_font_names[] = {
"arial.ttf",
"times.ttf",
"timesi.ttf",
"arial.ttf",
655 b = getenv(
"WINDIR" );
665 plwarn(
"Freetype seems already to have been initialised!" );
669 if ( ( pls->
FT = calloc( 1, (
size_t)
sizeof ( FT_Data ) ) ) == NULL )
670 plexit(
"Could not allocate memory for Freetype" );
672 FT = (FT_Data *) pls->
FT;
674 if ( ( FT->textbuf = calloc( NTEXT_ALLOC, 1 ) ) == NULL )
675 plexit(
"Could not allocate memory for Freetype text buffer" );
677 if ( FT_Init_FreeType( &FT->library ) )
678 plexit(
"Could not initialise Freetype library" );
683 #if defined ( MSDOS ) || defined ( _WIN32 ) 688 if ( ( a = getenv(
"PLPLOT_FREETYPE_FONT_DIR" ) ) != NULL )
692 else if ( WINDIR_PATH == NULL )
695 if (
access(
"c:\\windows\\fonts\\arial.ttf",
F_OK ) == 0 )
697 strcpy( font_dir,
"c:/windows/fonts/" );
699 else if (
access(
"c:\\windows\\system\\arial.ttf",
F_OK ) == 0 )
701 strcpy( font_dir,
"c:/windows/system/" );
704 plwarn(
"Could not find font path; I sure hope you have defined fonts manually !" );
709 strncat( WINDIR_PATH,
"\\fonts\\arial.ttf",
PLPLOT_MAX_PATH - 1 - strlen( WINDIR_PATH ) );
712 b = strrchr( WINDIR_PATH,
'\\' );
716 strcpy( font_dir, WINDIR_PATH );
719 plwarn(
"Could not find font path; I sure hope you have defined fonts manually !" );
724 fprintf( stderr,
"%s\n", font_dir );
735 if ( ( a = getenv(
"PLPLOT_FREETYPE_FONT_DIR" ) ) != NULL )
751 if ( ( a = getenv( env_font_names[i] ) ) != NULL )
765 if ( ( a[0] ==
'/' ) || ( a[0] ==
'~' ) )
772 strncat( FT->font_name[i], a,
PLPLOT_MAX_PATH - 1 - strlen( FT->font_name[i] ) );
784 if ( ( infile = fopen( FT->font_name[i],
"r" ) ) == NULL )
788 "plD_FreeType_init: Could not find the freetype compatible font:\n %s",
798 if ( FT->font_name[i][0] ==
'\0' )
799 FontLookup[i].pfont = NULL;
801 FontLookup[i].pfont = (
unsigned char *) FT->font_name[i];
818 FT_Data *FT = (FT_Data *) pls->
FT;
819 double font_size = pls->
chrht * 72 / 25.4;
822 FT->chrht = pls->
chrht;
823 FT->xdpi = pls->
xdpi;
824 FT->ydpi = pls->
ydpi;
826 if ( fci != FT->fci )
829 if ( font_name == NULL )
832 plexit(
"FT_SetFace: Bad FCI and no previous valid font to fall back on" );
834 plwarn(
"FT_SetFace: Bad FCI. Falling back to previous font." );
840 if ( FT->face != NULL )
842 FT_Done_Face( FT->face );
846 if ( FT->face == NULL )
848 if ( FT_New_Face( FT->library, font_name, 0, &FT->face ) )
849 plexit(
"FT_SetFace: Error loading a font in freetype" );
854 if ( FT->face->charmap == NULL )
855 FT_Select_Charmap( FT->face, FT->face->charmaps[0]->encoding );
858 FT_Set_Char_Size( FT->face, 0,
859 (FT_F26Dot6) ( font_size * 64 / TEXT_SCALING_FACTOR ), (FT_UInt) pls->
xdpi,
860 (FT_UInt) pls->
ydpi );
873 FT_Data *FT = (FT_Data *) pls->
FT;
875 int w = 0, h = 0, overh = 0, underh = 0;
881 int prevlineheights = 0;
901 if ( ( FT->fci != fci ) || ( FT->chrht != pls->
chrht ) || ( FT->xdpi != pls->
xdpi ) || ( FT->ydpi != pls->
ydpi ) )
902 FT_SetFace( pls, fci );
907 Debug6(
"%s %d %d %d %d\n",
"plD_render_freetype_text:",
908 FT->face->underline_position >> 6,
909 FT->face->descender >> 6,
910 FT->face->ascender >> 6,
911 ( ( FT->face->underline_position * -1 ) + FT->face->ascender ) >> 6 );
932 FT->matrix.xx = 0x10000;
933 FT->matrix.xy = 0x00000;
934 FT->matrix.yx = 0x00000;
935 FT->matrix.yy = 0x10000;
937 FT_Vector_Transform( &FT->pos, &FT->matrix );
938 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
940 FT_StrX_YW( pls,
line, (
short) linelen, &w, &h, &overh, &underh );
965 height_factor = (
PLFLT) ( FT->face->ascender - FT->face->descender )
966 / FT->face->ascender;
967 height = (FT_Fixed) ( 0x10000 * height_factor );
970 FT->matrix.xx = (FT_Fixed) ( (
PLFLT) height * t[0] );
971 FT->matrix.xy = (FT_Fixed) ( (
PLFLT) height * t[2] );
972 FT->matrix.yx = (FT_Fixed) ( (
PLFLT) height * t[1] );
973 FT->matrix.yy = (FT_Fixed) ( (
PLFLT) height * t[3] );
975 FT->matrix.xx = (FT_Fixed) ( (
PLFLT) height * t[0] );
976 FT->matrix.xy = (FT_Fixed) ( (
PLFLT) height * t[1] );
977 FT->matrix.yx = (FT_Fixed) ( (
PLFLT) height * t[2] );
978 FT->matrix.yy = (FT_Fixed) ( (
PLFLT) height * t[3] );
989 Cos_A = cos( angle );
990 Sin_A = sin( angle );
992 matrix.xx = (FT_Fixed) ( (
PLFLT) 0x10000 * Cos_A );
995 matrix.xy = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A * -1.0 );
996 matrix.yx = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A );
998 matrix.xy = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A );
999 matrix.yx = (FT_Fixed) ( (
PLFLT) 0x10000 * Sin_A * -1.0 );
1002 matrix.yy = (FT_Fixed) ( (
PLFLT) 0x10000 * Cos_A );
1004 FT_Matrix_Multiply( &matrix, &FT->matrix );
1016 FT_Vector_Transform( &FT->pos, &FT->matrix );
1028 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
1044 if ( FT->scale != 0.0 )
1046 x = (int) ( args->
x / FT->scale );
1048 if ( FT->invert_y == 1 )
1049 y = (int) ( FT->ymax - ( args->
y / FT->scale ) );
1051 y = (int) ( args->
y / FT->scale );
1055 x = (int) ( args->
x / FT->scalex );
1057 if ( FT->invert_y == 1 )
1058 y = (int) ( FT->ymax - ( args->
y / FT->scaley ) );
1060 y = (int) ( args->
y / FT->scaley );
1085 #ifdef DODGIE_DECENDER_HACK 1112 adjust.x = (FT_Pos) ( args->
just *
ROUND( (
PLFLT) FT->face->glyph->metrics.width / 64.0 ) );
1113 adjust.y = (FT_Pos)
ROUND( (
PLFLT) FT->face->glyph->metrics.height / 128.0 );
1127 ROUND( (
PLFLT) FT->face->size->metrics.height / height_factor / 128.0 - ( prevlineheights + overh ) / 64.0 );
1128 adjust.x = (FT_Pos) ( args->
just *
ROUND( w / 64.0 ) );
1131 FT_Vector_Transform( &adjust, &FT->matrix );
1133 x -= (int) adjust.x;
1134 y += (
int) adjust.y;
1136 FT_WriteStrW( pls,
line, (
short) linelen, x, y );
1141 line += linelen + 1;
1142 prevlineheights += h + overh + underh;
1147 plD_render_freetype_sym( pls, args );
1159 void plD_FreeType_Destroy(
PLStream *pls )
1161 FT_Data *FT = (FT_Data *) pls->
FT;
1166 if ( ( FT->smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) )
1169 free( FT->textbuf );
1170 FT_Done_Library( FT->library );
1185 static PLFLT CalculateIncrement(
int bg,
int fg,
int levels )
1192 ret = ( ( fg + 1 ) - bg ) / levels;
1194 ret = ( ( ( fg - 1 ) - bg ) / levels );
1214 void pl_set_extended_cmap0(
PLStream *pls,
int ncol0_width,
int ncol0_org )
1218 PLFLT r_inc, g_inc, b_inc;
1220 for ( i = 1; i < ncol0_org; i++ )
1226 r_inc = CalculateIncrement( pls->
cmap0[0].
r, r, ncol0_width );
1227 g_inc = CalculateIncrement( pls->
cmap0[0].
g, g, ncol0_width );
1228 b_inc = CalculateIncrement( pls->
cmap0[0].
b, b, ncol0_width );
1230 for ( j = 0, k = ncol0_org + i - 1; j < ncol0_width; j++, k += ( ncol0_org - 1 ) )
1235 if ( ( r < 0 ) || ( g < 0 ) || ( b < 0 ) )
1238 plscol0( k, ( r > 0xff ? 0xff : r ), ( g > 0xff ? 0xff : g ), ( b > 0xff ? 0xff : b ) );
1258 FT_Data *FT = (FT_Data *) pls->
FT;
1263 if ( FT->scale != 0.0 )
1265 x = (int) ( args->
x / FT->scale );
1267 if ( FT->invert_y == 1 )
1268 y = (int) ( FT->ymax - ( args->
y / FT->scale ) );
1270 y = (int) ( args->
y / FT->scale );
1274 x = (int) ( args->
x / FT->scalex );
1276 if ( FT->invert_y == 1 )
1277 y = (int) ( FT->ymax - ( args->
y / FT->scaley ) );
1279 y = (int) ( args->
y / FT->scaley );
1299 #ifdef DODGIE_DECENDER_HACK 1300 adjust.y = ( FT->face->descender >> 6 ) * 3;
1302 adjust.y = ( FT->face->descender >> 6 );
1306 FT_Vector_Transform( &adjust, &FT->matrix );
1307 x += (int) adjust.x;
1308 y -= (
int) adjust.y;
1311 FT_SetFace( pls, fci );
1313 FT = (FT_Data *) pls->
FT;
1314 FT_Set_Transform( FT->face, &FT->matrix, &FT->pos );
1316 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 );
1326 x -= (int) ( ( FT->face->glyph->advance.x >> 6 ) / 2 );
1327 FT_PlotChar( pls, FT, FT->face->glyph, x, y );
void plexit(PLCHAR_VECTOR errormsg)
#define PLDLLIMPEXP_DATA(type)
const char * PLCHAR_VECTOR
#define PL_FCI_IMPOSSIBLE
const unsigned char * pfont
static const FCI_to_FontName_Table TrueTypeLookup[N_TrueTypeLookup]
void difilt(PLINT *xsc, PLINT *ysc, PLINT npts, PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma)
static PLStream * pls[PL_NSTREAMS]
unsigned short unicode_array_len
#define PL_FREETYPE_FONT_DIR
PLCHAR_VECTOR plP_FCI2FontName(PLUNICODE fci, const FCI_to_FontName_Table lookup[], const int nlookup)
void plwarn(PLCHAR_VECTOR errormsg)
int access(char *filename, int flag)
PLUNICODE * unicode_array