📄 font_freetype2.c
字号:
pfontinfo->widths[ch] = advance; } //EPRINTF("pfontinfo->widths[%d]=%d\n", i, pfontinfo->widths[i]); } return TRUE;}/** * Draws text onto a screen or pixmap. * * @param pfont The font to use. * @param psd The device to draw on. * @param ax The destination X co-ordinate. * @param ay The destination Y co-ordinate. * @param text The string to display, in 16-bit Unicode form. * @param cc The number of characters (not bytes) in text. * @param flags Flags. */static voidfreetype2_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay, const void *text, int cc, MWTEXTFLAGS flags){ PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) pfont; FT_Face face; FT_Size size; const unsigned short *str = text; FT_Vector pos; int i; FT_Glyph glyph; FT_Error error; FT_Vector kerning_delta; int curchar; int use_kerning; int last_glyph_code = 0; /* Used for kerning */ driver_gc_t blit_instructions; int blit_op; assert(pf); assert(psd); assert(text); //DPRINTF("Nano-X-Freetype2: freetype2_drawtext(x=%d, y=%d) called\n", ax, ay);#if HAVE_FREETYPE_2_CACHE error = FTC_Manager_Lookup_Size(freetype2_cache_manager, &(pf->imagedesc.font), &face, &size); if (error) { EPRINTF("Freetype 2 error 0x%x getting font for drawtext.\n", error); return; }#else face = pf->face; size = face->size;#endif use_kerning = ((pf->fontattr & MWTF_KERNING) && FT_HAS_KERNING(face)); /* Initialize the parts of blit_instructions we won't change */ blit_instructions.fg_color = gr_foreground; blit_instructions.bg_color = gr_background; blit_instructions.gr_usebg = gr_usebg; blit_instructions.srcx = 0; blit_instructions.srcy = 0; blit_instructions.dst_linelen = 0; /* Unused. */ if (pf->fontattr & MWTF_ANTIALIAS) { blit_op = PSDOP_ALPHACOL; } else { blit_op = PSDOP_BITMAP_BYTES_MSB_FIRST; } /* * Offset the starting point if necessary, * FreeType always aligns at baseline */ if (flags & MWTF_BOTTOM) { pos.y = (abs(size->metrics.descender) + 63) & ~63; /* descent */ } else if (flags & MWTF_TOP) { pos.y = -(size->metrics.ascender + 63) & ~63; /* -ascent */ } else { pos.y = 0; }#if 1 if ((pf->fontrotation != 0)#if HAVE_FREETYPE_2_CACHE || (!CAN_USE_FT2_CACHE(pf)) /* Cache does not support bitmaps >256x256 */#endif ) { /* Use slow routine for rotated text */#endif FT_BitmapGlyph bitmapglyph; FT_Bitmap *bitmap; FT_Render_Mode render_mode = (pf-> fontattr & MWTF_ANTIALIAS) ? ft_render_mode_normal : ft_render_mode_mono; /*DPRINTF("Nano-X-Freetype2: freetype2_drawtext() using SLOW routine\n"); */ pos.x = 0; for (i = 0; i < cc; i++) { curchar = LOOKUP_CHAR(pf, face, str[i]); if (use_kerning && last_glyph_code && curchar) { FT_Get_Kerning(face, last_glyph_code, curchar, ft_kerning_default, &kerning_delta); //DPRINTF("Nano-X-Freetype2: freetype2_drawtext(): kerning_delta.x=%d, /64=%d\n", // (int)kerning_delta.x, (int)kerning_delta.x/64); pos.x += kerning_delta.x & (~63); } last_glyph_code = curchar; /* FIXME: Should use an image cache to optimize * rendering of rotated text. */ error = FT_Load_Glyph(face, curchar, FT_LOAD_DEFAULT); if (error) continue; error = FT_Get_Glyph(face->glyph, &glyph); if (error) continue; // translate the glyph image now.. FT_Glyph_Transform(glyph, 0, &pos); //DPRINTF("Nano-X-Freetype2: freetype2_drawtext(): glyph->advance.x=%d, >>16=%d\n", (int)glyph->advance.x, (int)glyph->advance.x>>16); pos.x += (glyph->advance.x >> 10) & (~63); if (pf->fontrotation) { // rotate the glyph image now.. FT_Glyph_Transform(glyph, &pf->matrix, 0); } // convert glyph image to bitmap // error = FT_Glyph_To_Bitmap(&glyph, render_mode, 0, // no additional translation 1); // do not destroy copy in "image" if (!error) { bitmapglyph = (FT_BitmapGlyph) glyph; bitmap = &(bitmapglyph->bitmap); blit_instructions.dstx = ax + bitmapglyph->left; blit_instructions.dsty = ay - bitmapglyph->top; blit_instructions.dstw = bitmap->width; blit_instructions.dsth = bitmap->rows; blit_instructions.src_linelen = bitmap->pitch; blit_instructions.pixels = bitmap->buffer; blit_instructions.misc = bitmap->buffer; //DPRINTF("Nano-X-Freetype2: freetype2_draw_bitmap_%s(ax=%d, ay=%d, gl->l=%d, gl->t=%d)\n", // ((pf->fontattr & MWTF_ANTIALIAS) ? "alpha" : "mono"), ax, ay, bitmapglyph->left, bitmapglyph->top); if ((blit_instructions.dstw > 0) && (blit_instructions.dsth > 0)) { GdDrawAreaInternal(psd, &blit_instructions, blit_op); } FT_Done_Glyph(glyph); } }#if 1 } else { /* No rotation - optimized loop */#if HAVE_FREETYPE_2_CACHE FTC_SBit sbit;#else FT_Bitmap *bitmap;#endif ay += (pos.y >> 6); for (i = 0; i < cc; i++) { curchar = LOOKUP_CHAR(pf, face, str[i]); if (use_kerning && last_glyph_code && curchar) { FT_Get_Kerning(face, last_glyph_code, curchar, ft_kerning_default, &kerning_delta); ax += (kerning_delta.x >> 6); } last_glyph_code = curchar;#if HAVE_FREETYPE_2_CACHE error = FTC_SBitCache_Lookup(freetype2_cache_sbit, &(pf->imagedesc), curchar, &sbit, NULL); if (error) continue; blit_instructions.dstx = ax + sbit->left; blit_instructions.dsty = ay - sbit->top; blit_instructions.dstw = sbit->width; blit_instructions.dsth = sbit->height; blit_instructions.src_linelen = sbit->pitch; blit_instructions.pixels = sbit->buffer; blit_instructions.misc = sbit->buffer; ax += sbit->xadvance;#else error = FT_Load_Glyph(face, curchar, (pf->fontattr & MWTF_ANTIALIAS) ? (FT_LOAD_RENDER | FT_LOAD_MONOCHROME) : FT_LOAD_RENDER); if (error) continue; bitmap = &(face->glyph->bitmap); blit_instructions.dstx = ax + face->glyph->bitmap_left; blit_instructions.dsty = ay - face->glyph->bitmap_top; blit_instructions.dstw = bitmap->width; blit_instructions.dsth = bitmap->rows; blit_instructions.src_linelen = bitmap->pitch; blit_instructions.pixels = bitmap->buffer; blit_instructions.misc = bitmap->buffer; /* Wierdness: After FT_Load_Glyph, face->glyph->advance.x is in 26.6. * After a translation with FT_Glyph_Transform, it is in 16.16. * Must be a FreeType 2.0.8 bug. */ ax += (face->glyph->advance.x >> 6);#endif if ((blit_instructions.dstw > 0) && (blit_instructions.dsth > 0)) { GdDrawAreaInternal(psd, &blit_instructions, blit_op); } } }#endif GdFixCursor(psd);// FIXME// if (pf->fontattr & MWTF_UNDERLINE)// GdLine(psd, startx, starty, x, y, FALSE);}/** * Measures text, which can be rotated. This is slower than the * non-rotated version. * * @param pf The font to use. * @param text The string to measure, in 16-bit Unicode form. * @param cc The number of characters (not bytes) in text. * @param pwidth [out] the width in pixels * @param pheight [out] the height in pixels * @param pbase [out] the base in pixels * * @internal */static voidfreetype2_gettextsize_rotated(PMWFREETYPE2FONT pf, const void *text, int cc, MWCOORD * pwidth, MWCOORD * pheight, MWCOORD * pbase){ FT_Face face; FT_Size size; const unsigned short *str = text; FT_Vector pos; int i; FT_Glyph glyph; FT_Error error; FT_Vector kerning_delta; int curchar; int use_kerning; int last_glyph_code = 0; /* Used for kerning */ FT_BBox bbox; FT_BBox glyph_bbox;#if HAVE_FREETYPE_2_CACHE error = FTC_Manager_Lookup_Size(freetype2_cache_manager, &(pf->imagedesc.font), &face, &size); if (error) { EPRINTF("Freetype 2 error 0x%x getting font info.\n", error); *pwidth = 0; *pheight = 0; *pbase = 0; return; }#else face = pf->face; size = face->size;#endif use_kerning = ((pf->fontattr & MWTF_KERNING) && FT_HAS_KERNING(face)); bbox.xMin = 0; bbox.yMin = 0; bbox.xMax = 0; bbox.yMax = 0; /* * Starting point */ pos.x = 0; pos.y = 0; for (i = 0; i < cc; i++) { curchar = LOOKUP_CHAR(pf, face, str[i]); if (use_kerning && last_glyph_code && curchar) { FT_Get_Kerning(face, last_glyph_code, curchar, ft_kerning_default, &kerning_delta); pos.x += kerning_delta.x & (~63); } last_glyph_code = curchar; /* FIXME: Should use an image cache to optimize * rendering of rotated text. */ error = FT_Load_Glyph(face, curchar, FT_LOAD_DEFAULT); if (error) continue; error = FT_Get_Glyph(face->glyph, &glyph); if (error) continue; //DPRINTF("Nano-X-Freetype2: freetype2_gettextsize(): glyph '%c' at %d,%d, advance=%d\n", // str[i], (pos.x>>6), (pos.y>>6), (glyph->advance.x >> 16)); // translate the glyph image now.. FT_Glyph_Transform(glyph, 0, &pos); pos.x += (glyph->advance.x >> 10) & (~63); if (pf->fontrotation) { // rotate the glyph image now.. FT_Glyph_Transform(glyph, &pf->matrix, 0); } if (i == 0) { FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &bbox); } else { FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox); //DPRINTF("Nano-X-Freetype2: freetype2_gettextsize(): glyph cbox (%d,%d)-(%d,%d)\n", // (glyph_bbox.xMin/*>>6*/), (glyph_bbox.yMin/*>>6*/), // (glyph_bbox.xMax/*>>6*/), (glyph_bbox.yMax/*>>6*/)); if (glyph_bbox.xMin < bbox.xMin) bbox.xMin = glyph_bbox.xMin; if (glyph_bbox.yMin < bbox.yMin) bbox.yMin = glyph_bbox.yMin; if (glyph_bbox.xMax > bbox.xMax) bbox.xMax = glyph_bbox.xMax; if (glyph_bbox.yMax > bbox.yMax) bbox.yMax = glyph_bbox.yMax; } FT_Done_Glyph(glyph); //DPRINTF("Nano-X-Freetype2: freetype2_gettextsize(): total cbox (%d,%d)-(%d,%d)\n", // (bbox.xMin/*>>6*/), (bbox.yMin/*>>6*/), (bbox.xMax/*>>6*/), (bbox.yMax/*>>6*/)); } *pwidth = bbox.xMax /*>> 6 */ ; *pheight = (bbox.yMax - bbox.yMin) /*>> 6 */ ; *pbase = -(bbox.yMin /*>> 6 */ ); //DPRINTF("Nano-X-Freetype2: freetype2_gettextsize(): numchars = %d, w = %d, h = %d, base = %d\n", // cc, *pwidth, *pheight, *pbase);}/** * Measures text, which must not be rotated. This is faster than the * rotated version. This uses the cache system, if available, so * the caller must check that they CAN_USE_FT2_CACHE(). * * @param pf The font to use. * @param text The string to measure, in 16-bit Unicode form. * @param char_count The number of characters (not bytes) in text. * @param pwidth [out] the width in pixels * @param pheight [out] the height in pixels * @param pbase [out] the base in pixels * * @internal */static voidfreetype2_gettextsize_fast(PMWFREETYPE2FONT pf, const void *text, int char_count, MWCOORD * pwidth, MWCOORD * pheight, MWCOORD * pbase){ FT_Face face; FT_Size size; const unsigned short *str = text; int char_index; int total_advance; int max_ascent; int max_descent; int advance; int ascent; int descent; FT_Error error; FT_Vector kerning_delta; int use_kerning; int cur_glyph_code; int last_glyph_code = 0; /* Used for kerning */#if HAVE_FREETYPE_2_CACHE error = FTC_Manager_Lookup_Size(freetype2_cache_manager, &(pf->imagedesc.font), &face, &size); if (error) { EPRINTF("Freetype 2 error 0x%x getting font info.\n", error); *pwidth = 0; *pheight = 0; *pbase = 0; return; }#else face = pf->face; size = face->size;#endif use_kerning = ((pf->fontattr & MWTF_KERNING) && FT_HAS_KERNING(face)); /* * Starting point */ total_advance = 0; max_ascent = 0; max_descent = 0; for (char_index = 0; char_index < char_count; char_index++) { cur_glyph_code = LOOKUP_CHAR(pf, face, str[char_index]); if (use_kerning && last_glyph_code && cur_glyph_code) { FT_Get_Kerning(face, last_glyph_code, cur_glyph_code, ft_kerning_default, &kerning_delta); /*EPRINTF("Nano-X-Freetype2: freetype2_gettextsize(): %d + kerning %d (delta was %d unscaled).\n", (int)ax, (int)(kerning_delta.x >> 6), (int)kerning_delta.x); */ total_advance += (kerning_delta.x >> 6); } last_glyph_code = cur_glyph_code; error = freetype2_get_glyph_size(pf, face, cur_glyph_code, &advance, &ascent, &descent); if (error) continue; total_advance += advance; if (max_ascent < ascent) max_ascent = ascent; if (max_descent < descent) max_descent = descent; } *pwidth = total_advance; *pheight = max_ascent + max_descent; *pbase = max_ascent; /*EPRINTF("Nano-X-Freetype2: freetype2_gettextsize(): numchars = %d, w = %d, h = %d, base = %d\n", cc, *pwidth, *pheight, *pbase); */}/** * Measures text. * * @param pfont The font to use. * @param text The string to measure, in 16-bit Unicode form. * @param cc The number of characters (not bytes) in text. * @param flags Flags specifying the encoding of text. * @param pwidth [out] the width in pixels * @param pheight [out] the height in pixels * @param pbase [out] the base in pixels */static voidfreetype2_gettextsize(PMWFONT pfont, const void *text, int cc,MWTEXTFLAGS flags, MWCOORD * pwidth, MWCOORD * pheight, MWCOORD * pbase){ PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) pfont; assert(pf); assert(text); assert(pwidth); assert(pheight); assert(pbase); if ((pf->fontrotation != 0)#if HAVE_FREETYPE_2_CACHE || (!CAN_USE_FT2_CACHE(pf))#endif ) { /* Use slow routine for rotated text */ /* EPRINTF("Nano-X-Freetype2: freetype2_gettextsize() using SLOW routine\n"); */ freetype2_gettextsize_rotated(pf, text, cc, pwidth, pheight, pbase); } else { freetype2_gettextsize_fast(pf, text, cc, pwidth, pheight, pbase); }}#if 0 /* FIXME not yet used *//* * Get the human-readable name of a font, given it's filename. * * Returns NULL if font is invalid or does not contain a name. * Otherwise, returns a malloc'd ASCII string. */char *freetype2_get_name(const char *filename){ FT_Face face; char *result = NULL; assert(filename); /* Load face */ if (FT_New_Face(freetype2_library, filename, 0, &face) == FT_Err_Ok) { result = malloc(strlen(face->family_name) + 1); if (result != NULL) { strcpy(result, face->family_name); } FT_Done_Face(face); } return result;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -