📄 devfont.caching.c
字号:
case MWPF_PALETTE: /* reverse lookup palette entry for blend ;-)*/ palsrc = GETPALENTRY(gr_palette, src); paldst = GETPALENTRY(gr_palette, dst); d = REDVALUE(paldst); r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d; d = GREENVALUE(paldst); g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d; d = BLUEVALUE(paldst); b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d; *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors, MWRGB(r, g, b)); break; } }}#endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/#if HAVE_T1LIB_SUPPORT/* contributed by Vidar Hokstad*/static intt1lib_init(PSD psd){ static int inited = 0; if (inited) return 1; T1_SetBitmapPad(8); if (!T1_InitLib(0)) return 0;#ifdef T1LIB_USE_AA_HIGH T1_AASetLevel(T1_AA_HIGH);#else T1_AASetLevel(T1_AA_LOW);#endif #if 0 /* kluge: this is required if 16bpp drawarea driver is used*/ if(psd->bpp == 16) T1_AASetBitsPerPixel(16); else#endif T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8); inited = 1; return 1;}static PMWT1LIBFONTt1lib_createfont(const char *name, MWCOORD height, int attr){ PMWT1LIBFONT pf; int id; char * p; char buf[256]; /* match name against t1 font id's from t1 font database*/ for(id=0; id<T1_Get_no_fonts(); ++id) { strncpy(buf, T1_GetFontFileName(id), sizeof(buf)); /* remove extension*/ for(p=buf; *p; ++p) { if(*p == '.') { *p = 0; break; } } if(!strcmpi(name, buf)) { /* allocate font structure*/ pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1); if (!pf) return NULL; pf->fontprocs = &t1lib_procs; GdSetFontSize((PMWFONT)pf, height); GdSetFontRotation((PMWFONT)pf, 0); GdSetFontAttr((PMWFONT)pf, attr, 0); pf->fontid = id; return pf; } } return NULL;}/* * Draw ascii text string using T1LIB type font */static voidt1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y, const void *text, int cc, int flags){ PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont; const unsigned char *str = text; MWCOORD width; /* width of text area */ MWCOORD height; /* height of text area */ MWCOORD underliney; GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */#ifdef T1LIB_USE_AA_HIGH OUTPIXELVAL gvals[17]; /* Blending array for antialiasing. The steeper the values increase * near the end, the sharper the characters look, but also more jagged */ static unsigned char blend[17] = { 0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20, 0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff };#else OUTPIXELVAL gvals[5]; static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };#endif /* Check if we should throw out some fonts */ if (pf->fontattr&MWTF_ANTIALIAS) {#ifdef T1LIB_USE_AA_HIGH alphablend(psd, gvals, gr_foreground, gr_background, blend, 17); T1_AAHSetGrayValues(gvals);#else alphablend(psd, gvals, gr_foreground, gr_background, blend, 5); T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);#endif g = T1_AASetString(pf->fontid,(char *)str,cc,0, (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0); if (g && g->bits) { /*MWPIXELVAL save = gr_background;*/ width = g->metrics.rightSideBearing - g->metrics.leftSideBearing; height = g->metrics.ascent - g->metrics.descent; if(flags & MWTF_BASELINE) y -= g->metrics.ascent; else if(flags & MWTF_BOTTOM) y -= (height - 1); underliney = y + g->metrics.ascent; /* FIXME: Looks damn ugly if usebg is false. * Will be handled when using alphablending in GdArea... */ /* clipping handled in GdArea*/ /*FIXME kluge for transparency*/ /*gr_background = gr_foreground + 1;*/ /*gr_usebg = 0;*/ GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL); /*gr_background = save;*/ if (pf->fontattr & MWTF_UNDERLINE) GdLine(psd, x, underliney, x+width, underliney, FALSE); } } else { /* Do non-aa drawing */ g = T1_SetString(pf->fontid,(char *)str,cc,0, (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0); if (g && g->bits) { unsigned char * b; int xoff; int maxy; int xmod; /* I'm sure this sorry excuse for a bitmap rendering routine can * be optimized quite a bit ;) */ width = g->metrics.rightSideBearing - g->metrics.leftSideBearing; height = g->metrics.ascent - g->metrics.descent; if(flags & MWTF_BASELINE) y -= g->metrics.ascent; else if(flags & MWTF_BOTTOM) y -= (height - 1); underliney = y + g->metrics.ascent; b = g->bits; maxy = y + height; /* if ((x + width) > psd->xvirtres) { xmod = (x + width - psd->xvirtres + 7) >> 3; width = width + x + width - psd->xvirtres; } else xmod = 0;*/ xmod = 0; while (y < maxy) { unsigned char data; xoff = 0; while (xoff < width ) { if (!(xoff % 8)) { data = *b; b++; } if (GdClipPoint(psd, x+xoff,y)) { if (gr_usebg) { psd->DrawPixel(psd,x+xoff,y, data & (1 << (xoff % 8)) ? gr_foreground : gr_background); } else if (data & (1 << (xoff % 8))) { psd->DrawPixel(psd,x+xoff,y, gr_foreground); } } xoff++; } b += xmod; y++; } if (pf->fontattr & MWTF_UNDERLINE) GdLine(psd, x, underliney, x+xoff, underliney, FALSE); } } if (g && g->bits) { /* Save some memory */ free(g->bits); g->bits = 0; /* Make sure T1lib doesnt try to free it again */ } GdFixCursor(psd);}static MWBOOLt1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo){ int i; MWCOORD width, height, baseline; /* FIXME, guess all sizes*/ GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII); pfontinfo->height = height; pfontinfo->maxwidth = width; pfontinfo->baseline = 0; pfontinfo->firstchar = 32; pfontinfo->lastchar = 255; pfontinfo->fixed = TRUE; for(i=0; i<256; ++i) pfontinfo->widths[i] = width; return TRUE;}/* Get the width and height of passed text string in the current font*/static voidt1lib_gettextsize(PMWFONT pfont, const void *text, int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase){ PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont; const unsigned char * str = text; GLYPH * g; g = T1_SetString(pf->fontid, (char *)str, cc, 0, (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0); *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing; *pheight = g->metrics.ascent - g->metrics.descent; if(g && g->bits) { free(g->bits); g->bits = 0; }#if 0 BBox b; /* FIXME. Something is *VERY* wrong here */ b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0); DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx); DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly); *pwidth = (b.urx - b.llx); *pheight = (b.lly - b.ury);#endif}static voidt1lib_destroyfont(PMWFONT pfont){ PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont; T1_DeleteAllSizes(pf->fontid); free(pf);}#endif /* HAVE_T1LIB_SUPPORT*/#if HAVE_FREETYPE_SUPPORTstatic OUTPIXELVAL gray_palette[5];static intfreetype_init(PSD psd){ static int inited = 0; if (inited) return 1; /* Init freetype library */ if (TT_Init_FreeType (&engine) != TT_Err_Ok) { return 0; } /* Init kerning extension */ if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok) return 0; inited = 1; return 1;}static PMWFREETYPEFONTfreetype_createfont(const char *name, MWCOORD height, int attr){ PMWFREETYPEFONT pf; unsigned short i, n; unsigned short platform, encoding; TT_Face_Properties properties; char * p; char fontname[128]; /* check for pathname prefix*/ if (strchr(name, '/') != NULL) strcpy(fontname, name); else { strcpy(fontname, FREETYPE_FONT_DIR); strcat(fontname, "/"); strcat(fontname, name); } /* check for extension*/ if ((p = strrchr(fontname, '.')) == NULL || strcmp(p, ".ttf") != 0) { strcat(fontname, ".ttf"); } /* allocate font structure*/ pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1); if (!pf) return NULL; pf->fontprocs = &freetype_procs; /* Load face */ if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok) goto out; /* Load first kerning table */ pf->can_kern = TRUE; if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok) pf->can_kern = FALSE; else { if (TT_Get_Kerning_Directory (pf->face, &pf->directory) != TT_Err_Ok) pf->can_kern = FALSE; else { /* Support only version 0 kerning table ... */ if ((pf->directory.version != 0) || (pf->directory.nTables <= 0) || (pf->directory.tables->loaded != 1) || (pf->directory.tables->version != 0) || (pf->directory.tables->t.kern0.nPairs <= 0)) pf->can_kern = FALSE; } } /* get face properties and allocate preload arrays */ TT_Get_Face_Properties (pf->face, &properties);#if 0 /* * Use header information for ascent and descent * to compute scaled ascent/descent for current font height. */ h = properties.os2->sTypoAscender - properties.os2->sTypoDescender + properties.os2->sTypoLineGap; ascent = properties.os2->sTypoAscender + properties.os2->sTypoLineGap/2; pf->ascent = (ascent * height + h/2) / h; pf->descent = height - pf->ascent;#endif /* Create a glyph container */ if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok) goto out; /* create instance */ if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok) goto out; /* Set the instance resolution */ if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok) goto out; /* Look for a Unicode charmap: Windows flavor of Apple flavor only */ n = properties.num_CharMaps; for (i = 0; i < n; i++) { TT_Get_CharMap_ID (pf->face, i, &platform, &encoding); if (((platform == TT_PLATFORM_MICROSOFT) && (encoding == TT_MS_ID_UNICODE_CS)) || ((platform == TT_PLATFORM_APPLE_UNICODE) && (encoding == TT_APPLE_ID_DEFAULT))) { TT_Get_CharMap (pf->face, i, &pf->char_map); i = n + 1; } } if (i == n) { DPRINTF("freetype_createfont: no unicode map table\n"); goto out; } GdSetFontSize((PMWFONT)pf, height); GdSetFontRotation((PMWFONT)pf, 0); GdSetFontAttr((PMWFONT)pf, attr, 0); return pf;out: free(pf); return NULL;}static intcompute_kernval(PMWFREETYPEFONT pf, short current_glyph_code){ int i = 0; int kernval; int nPairs = pf->directory.tables->t.kern0.nPairs; TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs; if (pf->last_glyph_code != -1) { while ((pair->left != pf->last_glyph_code) && (pair->right != current_glyph_code)) { pair++; i++; if (i == nPairs) break; } if (i == nPairs) kernval = 0; else /* We round the value (hence the +32) */ kernval = (pair->value + 32) & -64; } else kernval = 0; return kernval;}static TT_UShortGet_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index){ TT_Glyph_Metrics metrics; if (TT_Load_Glyph ( pf->instance, pf->glyph, TT_Char_Index (pf->char_map,glyph_index), TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok) { /* Try to load default glyph: index 0 */ if (TT_Load_Glyph ( pf->instance, pf->glyph, 0, TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok) return 0; } TT_Get_Glyph_Metrics (pf->glyph, &metrics); return((metrics.advance & 0xFFFFFFC0) >> 6);}static MWFREETYPEFONTCACHE *find_cache_glyph ( PMWFREETYPEFONT pf, unsigned curchar ){ MWFREETYPEFONTCACHE ** inode = &pf->glyph_cache; while (1) { if (*inode == 0) { *inode = calloc(sizeof(MWFREETYPEFONTCACHE),1); (*inode)->curchar = curchar; } if (curchar < (*inode)->curchar) inode = &(*inode)->l; else if (curchar > (*inode)->curchar) inode = &(*inode)->r; else return *inode; }}static voidfree_cache_glyph ( MWFREETYPEFONTCACHE * node ){ if (node->l != 0) free_cache_glyph(node->l); if (node->r != 0) free_cache_glyph(node->r); free(node);}/* Render a single glyph*/static voiddrawchar(PMWFREETYPEFONT pf, PSD psd, unsigned curchar, int x_offset, int y_offset){ TT_F26Dot6 xmin, ymin, xmax, ymax, x, y, z; unsigned char *src, *srcptr; MWPIXELVAL *dst, *dstptr; MWPIXELVAL *bitmap; int size, width, height; TT_Outline outline; TT_BBox bbox; TT_Raster_Map Raster; TT_Error error; /*MWPIXELVAL save;*/ MWFREETYPEFONTCACHE * cache; /* we begin by grid-fitting the bounding box */ TT_Get_Glyph_Outline (pf->glyph, &outline); TT_Get_Outline_BBox (&outline, &bbox); xmin = (bbox.xMin & -64) >> 6; ymin = (bbox.yMin & -64) >> 6; xmax = ((bbox.xMax + 63) & -64) >> 6; ymax = ((bbox.yMax + 63) & -64) >> 6; width = xmax - xmin; height = ymax - ymin; size = width * height; /* now re-allocate the raster bitmap */ Raster.rows = height; Raster.width = width; if (pf->fontattr&MWTF_ANTIALIAS) Raster.cols = (Raster.width + 3) & -4; /* pad to 32-bits */ else Raster.cols = (Raster.width + 7) & -8; /* pad to 64-bits ??? */ cache = find_cache_glyph(pf,curchar); /* SDR: if cache is 0 here, something really really bad happened */ Raster.flow = TT_Flow_Up;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -