📄 font_freetype2.c
字号:
faceid = (freetype2_fontdata *) calloc(sizeof(freetype2_fontdata), 1); if (!faceid) return NULL; buffercopy = (unsigned char *) malloc(length); if (!buffercopy) { free(faceid); return NULL; } memcpy(buffercopy, buffer, length); faceid->isBuffer = TRUE; faceid->data.buffer.length = length; faceid->data.buffer.data = buffercopy; faceid->refcount = 1; /*DPRINTF("Font magic = '%c%c%c%c', len = %u @ freetype2_createfontfrombuffer\n", (char)buffercopy[0], (char)buffercopy[1], (char)buffercopy[2], (char)buffercopy[3], length); */ pf = freetype2_createfont_internal(faceid, NULL, height); if (!pf) { free(faceid); } return pf;}/** * Finish loading a font. This is used for both disk-based and * memory-based fonts. * * Allocates the actual PMWFREETYPE2FONT structure, fills it in, and * actually loads the font using FreeType 2 to check the font is valid. * * @param faceid Information on how to load the font. * @param filename The filename, or NULL if loaded from memory. * @param height The font height in pixels. * @return The new font, or NULL on error. * * @internal */static PMWFREETYPE2FONTfreetype2_createfont_internal(freetype2_fontdata * faceid, char *filename, MWCOORD height){ PMWFREETYPE2FONT pf;#if HAVE_FREETYPE_2_CACHE FT_Face face; FT_Size size;#endif FT_Error error; /* allocate font structure */ pf = (PMWFREETYPE2FONT) calloc(sizeof(MWFREETYPE2FONT), 1); if (!pf) { return NULL; } pf->fontprocs = &freetype2_procs; pf->faceid = faceid; pf->filename = filename;#if HAVE_FREETYPE_2_CACHE pf->imagedesc.font.face_id = faceid; pf->imagedesc.font.pix_width = 0; /* Will be set by GdSetFontSize */ pf->imagedesc.font.pix_height = 0; /* Will be set by GdSetFontSize */#if HAVE_FREETYPE_VERSION_AFTER_OR_EQUAL(2,1,3) pf->imagedesc.flags = 0; /* Will be set by GdSetFontAttr */#else pf->imagedesc.type = 0; /* Will be set by GdSetFontAttr */#endif#if HAVE_FREETYPE_2_CMAP_CACHE pf->cmapdesc.face_id = faceid; pf->cmapdesc.type = FTC_CMAP_BY_ENCODING; pf->cmapdesc.u.encoding = ft_encoding_unicode;#endif#else /* Load face */ if (filename) { error = FT_New_Face(freetype2_library, filename, 0, &pf->face); if (error != FT_Err_Ok) { EPRINTF("Nano-X-Freetype2: Can't load font from file \"%s\" - %lx\n", filename, (unsigned long) error); goto out; } /*DPRINTF("Nano-X-Freetype2: Loading font from file \"%s\"\n", filename); */ } else { error = FT_New_Memory_Face(freetype2_library, buffer, length, 0, &pf->face); if (error != FT_Err_Ok) { EPRINTF("Nano-X-Freetype2: Can't load font from memory - %lx\n", (unsigned long) error); goto out; } /*DPRINTF("Nano-X-Freetype2: Loading font from memory\n"); */ } error = FT_Select_Charmap(pf->face, ft_encoding_unicode); if (error != FT_Err_Ok) { EPRINTF("freetype2_createfont: no unicode map table - %lx\n", (unsigned long) error); goto out; }#endif GdSetFontSize((PMWFONT) pf, height); GdSetFontRotation((PMWFONT) pf, 0); GdSetFontAttr((PMWFONT) pf, 0, 0);#if HAVE_FREETYPE_2_CACHE /* Check that the font file exists and is valid */ /*DPRINTF("freetype2_createfont_internal(): testing\n");*/ error = FTC_Manager_Lookup_Size(freetype2_cache_manager, &(pf->imagedesc.font), &face, &size); if (error != FT_Err_Ok) { EPRINTF("Nano-X-Freetype2: Freetype 2 error %lx trying to load font.\n", (unsigned long)error); free(pf); return NULL; }#endif return pf;#if ! HAVE_FREETYPE_2_CACHE out: if (pf->face != NULL) { FT_Done_Face(pf->face); } free(pf); return NULL;#endif}/** * Frees a font. * * @param pfont The font to free. Must not be NULL. */static voidfreetype2_destroyfont(PMWFONT pfont){ PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) pfont; assert(pf);#if ! HAVE_FREETYPE_2_CACHE FT_Done_Face(pf->face); if (pf->filename) free(pf->filename);#endif if (pf->faceid && pf->faceid->isBuffer) { if (--pf->faceid->refcount <= 0) {#if HAVE_FREETYPE_2_CACHE FTC_Manager_Reset(freetype2_cache_manager);#endif free(pf->faceid->data.buffer.data); free(pf->faceid); } } free(pf);}/** * Duplicates a font. Makes a new font that has the same face, attributes * and rotation as the source font. The height can be copied or a new * height can be specified. * * If the old font is a memory font, then this function does not copy the * actual buffer of font data, it merely adds another reference to it. * The reference count ensures that the buffer of font data is freed * correctly when the last font using it is freed. * * @param psrcfont The font to copy. * @param height The height of the new font, in pixels, or 0 to copy from * the source font. * @return A new font, or NULL on error. */static PMWFONTfreetype2_duplicate(PMWFONT psrcfont, MWCOORD height){ PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) psrcfont; PMWFREETYPE2FONT pnewf; assert(pf); if (height == 0) { height = pf->fontsize; } if (pf->filename) { /* Font from disk file */ char *filename;#if HAVE_FREETYPE_2_CACHE /* Stored in faceid, which is effectively static. No need * to copy. */ filename = pf->filename;#else /* Dynamically allocated, must copy. */ filename = malloc(1 + strlen(pf->filename)); if (!filename) return NULL; strcpy(filename, pf->filename);#endif pnewf = freetype2_createfont_internal(pf->faceid, filename, height); if (!pnewf) { free(filename); return NULL; } } else { pf->faceid->refcount++; pnewf = freetype2_createfont_internal(pf->faceid, NULL, height); if (!pnewf) { pf->faceid->refcount--; return NULL; } } GdSetFontAttr((PMWFONT) pnewf, pf->fontattr, 0); if (pf->fontrotation) GdSetFontRotation((PMWFONT) pnewf, pf->fontrotation); return (PMWFONT) pnewf;}/** * Set the size of a font. Caller must update pfont->fontsize. * * @param pfont The font to update. * @param fontsize The new height in pixels. */static voidfreetype2_setfontsize(PMWFONT pfont, MWCOORD fontsize){ PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) pfont; MWCOORD pixel_height; MWCOORD pixel_width; assert(pf); pf->fontsize = fontsize; /* allow create font with height=0*/ if (!fontsize) return; /* In future, set these differently to support different aspect ratios. */ pixel_height = fontsize; pixel_width = fontsize;#if HAVE_FREETYPE_2_CACHE pf->imagedesc.font.pix_width = pixel_width; pf->imagedesc.font.pix_height = pixel_height;#else /* We want real pixel sizes ... not points ... */ FT_Set_Pixel_Sizes(pf->face, pixel_width, pixel_height);#endif}/** * Set the rotation of a font. Caller must update pfont->fontrotation. * * @param pfont The font to update. * @param tenthdegrees The new rotation in tenths of degrees. */static voidfreetype2_setfontrotation(PMWFONT pfont, int tenthdegrees){ PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) pfont; assert(pf); /* Normalize so that 0 <= tenthdegrees < 3600 */ if ((tenthdegrees < 0) || (tenthdegrees >= 3600)) { tenthdegrees = tenthdegrees % 3600; if (tenthdegrees < 0) { tenthdegrees += 3600; } } pf->fontrotation = tenthdegrees; if (pf->fontrotation == 0) { /* Identity transform */ pf->matrix.yy = (FT_Fixed) (1 << 16); pf->matrix.xx = (FT_Fixed) (1 << 16); pf->matrix.yx = (FT_Fixed) 0; pf->matrix.xy = (FT_Fixed) 0; } else { FT_Angle angle = (tenthdegrees << 16) / 10; FT_Vector sincosvec; FT_Vector_Unit(&sincosvec, angle); pf->matrix.yy = sincosvec.y; pf->matrix.xx = sincosvec.y; pf->matrix.yx = sincosvec.x; pf->matrix.xy = -sincosvec.x; }}/** * Set the attributes of a font. Caller must update pfont->fontattr * before calling this function. * * @param pfont The font to update. * @param setflags Bits being set. Overrides clrflags. * @param clrflags Bits being cleared. */static voidfreetype2_setfontattr(PMWFONT pfont, int setflags, int clrflags){#if HAVE_FREETYPE_2_CACHE PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) pfont; assert(pf);#if HAVE_FREETYPE_VERSION_AFTER_OR_EQUAL(2,1,3) pf->imagedesc.flags = FT_LOAD_DEFAULT; if (!(pf->fontattr & MWTF_ANTIALIAS)) { pf->imagedesc.flags |= (FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO); }#else pf->imagedesc.type = ((pf->fontattr & MWTF_ANTIALIAS) ? ftc_image_grays : ftc_image_mono);#endif#else /* No cache. Nothing to do, just check paramater is valid. */ assert(pfont);#endif}#define ROUND_26_6_TO_INT(valuetoround) (((valuetoround) + 63) >> 6)/** * Get the advance width, ascent and descent of a character. * Complicated by the need to use the cache if possible, and to handle rotated text. * * The face and pf arguments must refer to the same font. * * Any of the output paramater pointers may be NULL if you only care * about some of the values. * * @param pf The font to use * @param face A FreeType2 face generated from pf * @param glyph_index The glyph to measure * @param padvance [out] advance width. * @param pascent [out] character ascent. * @param pdescent [out] character descent. * @return FreeType error code (0 on success). */static FT_Errorfreetype2_get_glyph_size(PMWFREETYPE2FONT pf, FT_Face face, int glyph_index, int *padvance, int *pascent, int *pdescent){ FT_Error error; assert (pf); assert (face); #if HAVE_FREETYPE_2_CACHE if (CAN_USE_FT2_CACHE(pf)) { FTC_SBit sbit; error = FTC_SBitCache_Lookup(freetype2_cache_sbit, &(pf->imagedesc), glyph_index, &sbit, NULL); if (error) return error; /*DPRINTF("sbit->top = %d, sbit->height = %d\n", sbit->top, sbit->height);*/ if (padvance) *padvance = sbit->xadvance; if (pascent) *pascent = sbit->top; if (pdescent) *pdescent = sbit->height - sbit->top; return 0; } else#endif { error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); if (error) return error; if (padvance) *padvance = ROUND_26_6_TO_INT(face->glyph->advance.x); if (pascent || pdescent) { FT_Glyph glyph; FT_BBox bbox; error = FT_Get_Glyph(face->glyph, &glyph); if (error) return error; FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &bbox); FT_Done_Glyph(glyph); if (pascent) *pascent = bbox.yMax; if (pdescent) *pdescent = -bbox.yMin; } return 0; }}/** * Get the advance width, ascent and descent of a character. * Complicated by the need to use the cache if possible, and to handle rotated text. * * The face and pf arguments must refer to the same font. * * Any of the output paramater pointers may be NULL if you only care * about some of the values. * * @param pf The font to use * @param face A FreeType2 face generated from pf * @param ch The character to measure * @param padvance [out] advance width. * @param pascent [out] character ascent. * @param pdescent [out] character descent. * @return FreeType error code (0 on success). */static FT_Errorfreetype2_get_char_size(PMWFREETYPE2FONT pf, FT_Face face, int ch, int *padvance, int *pascent, int *pdescent){ int glyph = LOOKUP_CHAR(pf, face, ch); return freetype2_get_glyph_size(pf, face, glyph, padvance, pascent, pdescent);}/** * Return information about a specified font. * * @param pfont The font to query * @param pfontinfo The destination for the font metrics information. * @return TRUE on success, FALSE on error. */static MWBOOLfreetype2_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo){ PMWFREETYPE2FONT pf = (PMWFREETYPE2FONT) pfont; FT_Face face; FT_Size size; FT_BBox *bbox; FT_Size_Metrics *metrics; int ch; int leading;#if HAVE_FREETYPE_2_CACHE FT_Error error;#endif#if MW_FEATURE_DO_NOT_TRUST_FONT_ASCENT_AND_DESCENT int font_ascent; int font_descent;#endif assert(pf); assert(pfontinfo);#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); return FALSE; }#else face = pf->face; size = face->size;#endif bbox = &(face->bbox); metrics = &(size->metrics); if (!FT_IS_SCALABLE(face)) { /* FIXME */ return FALSE; } /* Fill up the fields */ pfontinfo->maxwidth = ROUND_26_6_TO_INT(metrics->max_advance); pfontinfo->maxascent = ROUND_26_6_TO_INT(FT_MulFix(bbox->yMax, metrics->y_scale)); pfontinfo->maxdescent = ROUND_26_6_TO_INT(FT_MulFix(-bbox->yMin, metrics->y_scale)); pfontinfo->fixed = ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); pfontinfo->baseline = ROUND_26_6_TO_INT(metrics->ascender); pfontinfo->descent = ROUND_26_6_TO_INT(abs(metrics->descender)); pfontinfo->height = pfontinfo->baseline + pfontinfo->descent; leading = ROUND_26_6_TO_INT(metrics->height - (metrics->ascender + abs(metrics->descender))); pfontinfo->linespacing = pfontinfo->height + leading; //DPRINTF("Nano-X-Freetype2: Font metrics:" // "\n maxwidth = %3d" // "\n baseline = %3d max_ascent = %3d" // "\n descent = %3d max_descent = %3d" // "\n height = %3d line_spacing = %3d" // "\n\n", // pfontinfo->maxwidth, // pfontinfo->baseline, pfontinfo->max_ascent, // pfontinfo->descent, pfontinfo->max_descent, // pfontinfo->height, pfontinfo->line_spacing // ); /* FIXME: Following are hacks... */ pfontinfo->firstchar = 0; pfontinfo->lastchar = 0xFFFFU; for (ch = 0; ch < 256; ch++) { int advance; if (freetype2_get_char_size(pf, face, ch, &advance, NULL, NULL)) { /* Error - assume default */ pfontinfo->widths[ch] = pfontinfo->maxwidth; } else { /* OK, found the value. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -