--- libXft-2.1.7/src/xftglyphs.c.orig 2005-10-28 11:31:01.000000000 +0800 +++ libXft-2.1.7/src/xftglyphs.c 2005-10-29 18:35:30.000000000 +0800 @@ -81,9 +81,13 @@ XftFontLoadGlyphs (Display *dpy, FT_GlyphSlot glyphslot; XftGlyph *xftg; Glyph glyph; + int load_flags; unsigned char bufLocal[4096]; unsigned char *bufBitmap = bufLocal; int bufSize = sizeof (bufLocal); + unsigned char bufEmboldenLocal[4096]; + unsigned char *bufEmboldenBitmap = bufEmboldenLocal; + int emboldenBufSize = sizeof (bufEmboldenLocal); int size, pitch; unsigned char bufLocalRgba[4096]; unsigned char *bufBitmapRgba = bufLocalRgba; @@ -98,8 +102,9 @@ XftFontLoadGlyphs (Display *dpy, FT_Matrix matrix; FT_Vector vector; Bool subpixel = False; + Bool lazy_embolden = False; FT_Face face; - + if (!info) return; @@ -145,7 +150,7 @@ XftFontLoadGlyphs (Display *dpy, */ if (xftg->glyph_memory) continue; - + load_flags = font->info.load_flags; error = FT_Load_Glyph (face, glyphindex, font->info.load_flags); if (error) { @@ -155,9 +160,9 @@ XftFontLoadGlyphs (Display *dpy, * bitmap and let things look bad instead of * missing the glyph */ - if (font->info.load_flags & FT_LOAD_NO_BITMAP) - error = FT_Load_Glyph (face, glyphindex, - font->info.load_flags & ~FT_LOAD_NO_BITMAP); + if (load_flags & FT_LOAD_NO_BITMAP) + load_flags &= ~FT_LOAD_NO_BITMAP; + error = FT_Load_Glyph (face, glyphindex, load_flags); if (error) continue; } @@ -170,6 +175,11 @@ XftFontLoadGlyphs (Display *dpy, glyphslot = face->glyph; #if HAVE_FT_GLYPHSLOT_EMBOLDEN + lazy_embolden = False; + if (glyphslot->format == ft_glyph_format_outline && + !font->info.antialias && + !(font->info.load_flags & FT_LOAD_NO_HINTING)) + lazy_embolden = True; /* * Embolden if required */ @@ -329,6 +339,131 @@ XftFontLoadGlyphs (Display *dpy, } memset (bufBitmap, 0, size); +#if HAVE_FT_GLYPHSLOT_EMBOLDEN + if (lazy_embolden && font->info.embolden) { + FT_GlyphSlot glyphslot; + int orig_pitch; + int orig_size; + int orig_width; + int orig_height; + int orig_left, orig_right, orig_top, orig_bottom; + + error = FT_Load_Glyph (face, glyphindex, load_flags); + if (error) + continue; + + glyphslot = face->glyph; + if(font->info.transform) + { + /* + * calculate the true width by transforming all four corners. + */ + int xc, yc; + orig_left = orig_right = orig_top = orig_bottom = 0; + for(xc = 0; xc <= 1; xc ++) { + for(yc = 0; yc <= 1; yc++) { + vector.x = glyphslot->metrics.horiBearingX + xc * glyphslot->metrics.width; + vector.y = glyphslot->metrics.horiBearingY - yc * glyphslot->metrics.height; + FT_Vector_Transform(&vector, &font->info.matrix); + if(xc == 0 && yc == 0) { + orig_left = orig_right = vector.x; + orig_top = orig_bottom = vector.y; + } else { + if(orig_left > vector.x) orig_left = vector.x; + if(orig_right < vector.x) orig_right = vector.x; + if(orig_bottom > vector.y) orig_bottom = vector.y; + if(orig_top < vector.y) orig_top = vector.y; + } + + } + } + orig_left = FLOOR(orig_left); + orig_right = CEIL(orig_right); + orig_bottom = FLOOR(orig_bottom); + orig_top = CEIL(orig_top); + } else { + orig_left = FLOOR( glyphslot->metrics.horiBearingX ); + orig_right = CEIL( glyphslot->metrics.horiBearingX + glyphslot->metrics.width ); + + orig_top = CEIL( glyphslot->metrics.horiBearingY ); + orig_bottom = FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height ); + } + + orig_width = TRUNC( orig_right - orig_left); + orig_height = TRUNC( orig_top - orig_bottom ); + + /* + * Clip charcell glyphs to the bounding box + * XXX transformed? + */ + if (font->info.spacing >= FC_CHARCELL && !font->info.transform) + { + if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT) + { + if (TRUNC(orig_bottom) > font->public.max_advance_width) + { + int adjust; + + adjust = orig_bottom - (font->public.max_advance_width << 6); + if (adjust > orig_top) + adjust = orig_top; + orig_top -= adjust; + orig_bottom -= adjust; + orig_height = font->public.max_advance_width; + } + } + else + { + if (TRUNC(orig_right) > font->public.max_advance_width) + { + int adjust; + + adjust = orig_right - (font->public.max_advance_width << 6); + if (adjust > orig_left) + adjust = orig_left; + orig_left -= adjust; + orig_right -= adjust; + orig_width = font->public.max_advance_width; + } + } + } + + orig_pitch = ((orig_width + 31) & ~31) >> 3; + + orig_size = orig_pitch * orig_height * vmul; + + if (orig_size > emboldenBufSize) + { + if (bufEmboldenBitmap != bufEmboldenLocal) + free (bufEmboldenBitmap); + bufEmboldenBitmap = (unsigned char *) malloc (size); + if (!bufEmboldenBitmap) + continue; + emboldenBufSize = size; + } + memset (bufEmboldenBitmap, 0, orig_size); + + glyphslot->bitmap.width = orig_width * hmul; + glyphslot->bitmap.rows = orig_height * vmul; + glyphslot->bitmap.pitch = orig_pitch; + glyphslot->bitmap.pixel_mode = ft_pixel_mode_mono; + glyphslot->bitmap.buffer = bufEmboldenBitmap; + + if (subpixel) + FT_Outline_Transform (&glyphslot->outline, &matrix); + FT_Outline_Translate ( &glyphslot->outline, -left*hmul, -bottom*vmul ); + FT_Outline_Get_Bitmap( _XftFTlibrary, &glyphslot->outline, &glyphslot->bitmap); + + glyphslot->format = ft_glyph_format_bitmap; + FT_GlyphSlot_Embolden (glyphslot); + + if (height - glyphslot->bitmap.rows > 0) + xftg->metrics.y -= ((height - glyphslot->bitmap.rows) / 2.0 + 0.5); + if (pitch < glyphslot->bitmap.pitch) + continue; + } +#endif + /* * Rasterize into the local buffer */ @@ -603,6 +738,8 @@ XftFontLoadGlyphs (Display *dpy, } if (bufBitmap != bufLocal) free (bufBitmap); + if (bufEmboldenBitmap != bufEmboldenLocal) + free (bufEmboldenBitmap); if (bufBitmapRgba != bufLocalRgba) free (bufBitmapRgba); XftUnlockFace (&font->public);