/* text draw truetypefont * * 2004/01/30 */ #include #include #include #include #ifdef HAVE_ICONV_H #include #endif #ifdef HAVE_FT2BUILD_H #include #include FT_FREETYPE_H #endif #include #include "driver.h" #include "driverlib.h" # define RpD ((2 * M_PI) / 360.) /* radians/degree */ # define D2R(d) (double)(d * RpD) /* degrees->radians */ /*#define DEBUG_LOG(S) {FILE *fp = fopen("debug.TXT","a");fputs(S,fp);fclose(fp);} */ /*#define DEBUG_LOG_INT(D) {FILE *fp = fopen("debug.TXT","a");fprintf(fp,"%d",D);fclose(fp);} */ /*#define DEBUG_LOG_DOUBLE(D) {FILE *fp = fopen("debug.TXT","a");fprintf(fp,"%f",D);fclose(fp);} */ #ifdef HAVE_FT2BUILD_H static int convert_str(const char *, const char *, unsigned char **); static void release_convert_str(unsigned char *); static void set_matrix(FT_Matrix *, double); static void draw_text(FT_Face, FT_Vector *, FT_Matrix *, const unsigned char *, int, int); static void draw_bitmap(FT_Bitmap *, FT_Int, FT_Int); static void set_text_box(FT_Bitmap *, FT_Int, FT_Int); #endif static int fdont_draw = 0; static double ft, fb, fl, fr; static const char *font_get_encoding(void) { if (!encoding) encoding = G_store("ISO-8859-1"); return encoding; } static void draw_main(double x, double y, double text_size_x, double text_size_y, double text_rotation, const char *string) { #ifdef HAVE_FT2BUILD_H FT_Library library; FT_Face face; FT_Matrix matrix; /*FT_UInt glyph_index; */ FT_Vector pen; FT_Error ans; const char *filename; const char *encoding; int font_index; unsigned char *out; int outlen; /* get file name */ filename = font_get_freetype_name(); encoding = font_get_encoding(); font_index = font_get_index(); /* set freetype */ ans = FT_Init_FreeType(&library); if (ans) { /* DEBUG_LOG("Text3 error: ft init\n"); */ return; } ans = FT_New_Face(library, filename, font_index, &face); if (ans == FT_Err_Unknown_File_Format) { /* DEBUG_LOG("Text3 error: ft new face 1\n"); */ FT_Done_FreeType(library); return; } else if (ans) { /* DEBUG_LOG("Text3 error: ft new face 2\n"); */ FT_Done_FreeType(library); return; } /* ans = FT_Set_Pixel_Sizes(face,10,10); */ /* ans = FT_Set_Char_Size(face,text_size_x*64,text_size_y*64,0,0); */ /* ans = FT_Set_Char_Size(face,10*64,0,72,0); */ /* ans = FT_Set_Char_Size(face,text_size_x*64,text_size_y*64,72,72); */ ans = FT_Set_Char_Size(face, (int)(text_size_x * 64), (int)(text_size_y * 64), 100, 100); /* ans = FT_Set_Pixel_Sizes( face, 0, (int)text_size_y ); */ if (ans) { /* DEBUG_LOG("Text3 error: ft set size\n"); */ FT_Done_Face(face); FT_Done_FreeType(library); return; } /* init point */ pen.x = x * 64; /* pen.y = 0; */ pen.y = (screen_height - y) * 64; /* convert string to:shift-jis from:encoding */ outlen = convert_str(encoding, string, &out); /* set matrix */ set_matrix(&matrix, D2R(text_rotation)); /* draw */ draw_text(face, &pen, &matrix, out, outlen, 0); /* release */ release_convert_str(out); /* FT_done */ FT_Done_Face(face); FT_Done_FreeType(library); #endif } #ifdef HAVE_FT2BUILD_H static void set_matrix(FT_Matrix * matrix, double rotation) { /* rotation is in radians */ matrix->xx = (FT_Fixed) (cos(rotation) * 0x10000); matrix->xy = (FT_Fixed) (-sin(rotation) * 0x10000); matrix->yx = (FT_Fixed) (sin(rotation) * 0x10000); matrix->yy = (FT_Fixed) (cos(rotation) * 0x10000); } static int convert_str(const char *from, const char *in, unsigned char **out) { size_t len, i, res; const unsigned char *p1; unsigned char *p2; len = strlen(in); res = 2 * (len + 1); *out = G_calloc(1, res); p1 = in; p2 = *out; #ifdef HAVE_ICONV_H { size_t ret; iconv_t cd; i = res; if ((cd = iconv_open("UCS-2BE", from)) < 0) return -1; ret = iconv(cd, (char **)&p1, &len, (char **)&p2, &i); iconv_close(cd); res -= i; } #else for (i = 0; i <= len; i++) /* Pad each character out to 2 bytes, i.e. UCS-2 Big Endian encoding * (note low byte has already been zeroed by G_calloc() call) */ p2[2 * i + 1] = p1[i]; res = 2 * len; #endif return res; } static void release_convert_str(unsigned char *out) { G_free(out); } static void draw_text(FT_Face face, FT_Vector * pen, FT_Matrix * matrix, const unsigned char *out, int len, int color) { FT_ULong ch; FT_Error ans; FT_GlyphSlot slot = face->glyph; int i; for (i = 0; i < len; i += 2) { ch = (out[i] << 8) | out[i + 1]; if (ch == 10) continue; /* transform */ FT_Set_Transform(face, matrix, pen); /* get glyph image */ ans = FT_Load_Char(face, ch, FT_LOAD_NO_BITMAP); if (ans) continue; ans = FT_Render_Glyph(face->glyph, ft_render_mode_normal); if (ans) continue; /* draw bitmap */ if (!fdont_draw) draw_bitmap(&slot->bitmap, slot->bitmap_left, screen_height - slot->bitmap_top); else set_text_box(&slot->bitmap, slot->bitmap_left, screen_height - slot->bitmap_top); /* increment pen position */ pen->x += slot->advance.x; pen->y += slot->advance.y; } } static void set_text_box(FT_Bitmap * bitmap, FT_Int x, FT_Int y) { FT_Int xMax = x + bitmap->width; FT_Int yMax = y + bitmap->rows; if ((x == xMax) || (y == yMax)) return; if (x < fl) fl = x; if (xMax > fr) fr = xMax; if (y < ft) ft = y; if (yMax > fb) fb = yMax; } static void draw_bitmap(FT_Bitmap * bitmap, FT_Int x, FT_Int y) { static unsigned char *buf; static int nalloc; int w, h; int bw = bitmap->width; int bh = bitmap->rows; const unsigned char *sbuf = bitmap->buffer; int offset, i, j; double x1, y1, x2, y2; x1 = x; y1 = y; x2 = x1 + bw; y2 = y1 + bh; w = x2 - x1; h = y2 - y1; if (w <= 0 || h <= 0) return; offset = ((int)y1 - y) * bw + (int)x1 - x; if (nalloc < w * h) { nalloc = w * h; buf = G_realloc(buf, nalloc); } for (j = 0; j < h; j++) for (i = 0; i < w; i++) buf[j * w + i] = sbuf[offset + j * bw + i]; COM_Pos_abs(x1, y1); DRV_draw_bitmap(w, h, 128, buf); } #endif void soft_text_freetype(double x, double y, double text_size_x, double text_size_y, double text_rotation, const char *string) { text_size_x *= 25.0; text_size_y *= 25.0; draw_main(x, y, text_size_x, text_size_y, text_rotation, string); } void soft_text_ext_freetype(double x, double y, double text_size_x, double text_size_y, double text_rotation, const char *string) { fdont_draw = 1; text_size_x *= 25.0; text_size_y *= 25.0; ft = 999999; fb = 0; fl = 999999; fr = 0; /* draw_main(x,y,text_size_x,text_size_y,text_rotation,string); */ /* draw_main(0,0,text_size_x,text_size_y,text_rotation,string); */ draw_main(0, y, text_size_x, text_size_y, text_rotation, string); /* ft += y; */ /* fb += y; */ fl += x; fr += x; fdont_draw = 0; } void get_text_ext_freetype(double *top, double *bot, double *left, double *rite) { *top = ft; *bot = fb; *left = fl; *rite = fr; }