diff -uP xft-2.1.1-orig/makebold.c xft-2.1.1-new/makebold.c --- xc/lib/Xft/makebold.c Thu Jan 1 09:00:00 1970 +++ xc/lib/Xft/makebold.c Mon Apr 5 01:58:02 2004 @@ -0,0 +1,520 @@ + +#ifndef MIN +#define MIN( x, y ) (((x) > (y)) ? (y) : (x)) +#endif + +typedef struct Target_Pixel_ +{ + FT_Byte rate[2]; + FT_Long pos[2]; + +} T_Pixel; + + +static void +BitmapDownscale (FT_Byte *buffer, + FT_Vector *origin, + short *bearingX, + short *bearingY, + int x_size, + int y_size, + FT_Fixed x_scale, + FT_Fixed y_scale, + int hmul, + int vmul) +{ + FT_Byte *mem_tmp = 0; + T_Pixel *x_tpx = 0; + T_Pixel *y_tpx = 0; + long mem_size = 0; + int vertical; + + + if (x_scale >= 0x10000L && y_scale >= 0x10000L) + return; + + x_size *= hmul; + y_size *= vmul; + + mem_size = (x_size + y_size) * sizeof(T_Pixel) + (x_size * y_size); + mem_tmp = (FT_Byte *) malloc (mem_size); + if (!mem_tmp) + return; + + memset (mem_tmp, 0, mem_size); + + x_tpx = (T_Pixel *)mem_tmp; + y_tpx = x_tpx + x_size; + + + for (vertical = 0; vertical < 2; vertical++ ) + { + FT_F26Dot6 size = vertical ? y_size : x_size; + FT_Fixed scale = vertical ? y_scale : x_scale; + T_Pixel *tpx = vertical ? y_tpx : x_tpx; + int pitch = vertical ? x_size : 1; + int mul = vertical ? vmul : hmul; + FT_F26Dot6 z, z0, z1, d0, d1, origin0, origin1; + + + origin0 = vertical ? origin->y : origin->x; + origin1 = origin0 - ((FT_MulFix (-origin0, scale) + origin0) & -64); + + if ( vertical ) + *bearingY += (origin1 - origin0) >> 6; + else + *bearingX -= (origin1 - origin0) >> 6; + + if (scale >= 0x10000L) + { + for (z = 0; z < size; z++, tpx++) { + tpx->rate[0] = 64; + tpx->pos[0] = z * pitch; + } + continue; + } + + size <<= 6; + origin0 *= mul; + origin1 *= mul; + + z0 = FT_MulFix (-origin0, scale) + origin1; + d0 = z0 & 63; + + for (z = 64; z <= size; z += 64, tpx++, z0 = z1, d0 = d1) + { + z1 = FT_MulFix (z - origin0, scale) + origin1; + d1 = z1 & 63; + + if (d1 > d0 || d1 == 0) { + if (z0 >= 0 && z0 < size) { + tpx->rate[0] = z1 - z0; + tpx->pos[0] = (z0 >> 6) * pitch; + } + } else { + if (z0 >= 0 && z0 < size) { + tpx->rate[0] = 64 - d0; + tpx->pos[0] = (z0 >> 6) * pitch; + } + + if (z1 >= 0 && z1 < size) { + tpx->rate[1] = d1; + tpx->pos[1] = (z1 >> 6) * pitch; + } + } + } + } + + + { + FT_Byte *src = buffer; + FT_Byte *dst; + FT_Byte *buf = mem_tmp + (x_size + y_size) * sizeof(T_Pixel); + long g0, g1, g2, g3, g4; + int x, y; + + + for (y = 0; y < y_size; y++, y_tpx++) + { + x_tpx = (T_Pixel *)mem_tmp; + + for (x = 0; x < x_size; x++, x_tpx++) + { + g0 = *src++; + g1 = (g0 * x_tpx->rate[0] * y_tpx->rate[0] + 0xFFF) >> 12; + g2 = (g0 * x_tpx->rate[0] * y_tpx->rate[1] + 0xFFF) >> 12; + g3 = (g0 * x_tpx->rate[1] * y_tpx->rate[0] + 0xFFF) >> 12; + g4 = (g0 * x_tpx->rate[1] * y_tpx->rate[1] + 0xFFF) >> 12; + + if (g1 > 0) { + dst = buf + x_tpx->pos[0] + y_tpx->pos[0]; + g1 += *dst; + *dst = (FT_Byte) MIN(g1, 255); + } + + if (g2 > 0) { + dst = buf + x_tpx->pos[0] + y_tpx->pos[1]; + g2 += *dst; + *dst = (FT_Byte) MIN(g2, 255); + } + + if (g3 > 0) { + dst = buf + x_tpx->pos[1] + y_tpx->pos[0]; + g3 += *dst; + *dst = (FT_Byte) MIN(g3, 255); + } + + if (g4 > 0) { + dst = buf + x_tpx->pos[1] + y_tpx->pos[1]; + g4 += *dst; + *dst = (FT_Byte) MIN(g4, 255); + } + } + } + + memcpy (buffer, buf, x_size * y_size); + } + + free (mem_tmp); +} + + +static void +MakeBoldBitmap (XftFont *pub, + FT_Bitmap *bitmap, + short *left_bearing, + short *top_bearing, + FT_F26Dot6 *advanceX, + FT_F26Dot6 *advanceY, + int *max_bufSize) +{ + XftFontInt *font = (XftFontInt *) pub; + FT_Byte *buffer = bitmap->buffer; + FT_Byte *buf_tmp = 0; + FT_F26Dot6 x_volume = font->x_volume * 2; + FT_F26Dot6 y_volume = font->y_volume * 2; + FcBool monochrome = FcFalse; + FT_F26Dot6 dx, dy; + int width, rows, pitch, hmul, vmul; + + + if (!font->info.antialias || bitmap->pixel_mode == ft_pixel_mode_mono) + monochrome = FcTrue; + + + if (y_volume > x_volume * 3 / 4) + y_volume = x_volume * 3 / 4; + + if (monochrome) { + if (x_volume < 44) + x_volume = 44; + if (font->info.xsize < 20*64) + y_volume = 0; + } else { + if (x_volume < 36) + x_volume = 36; + } + + + hmul = vmul = 1; + if (font->info.antialias) + { + switch (font->info.rgba) { + case FC_RGBA_RGB: + case FC_RGBA_BGR: + hmul = 3; + break; + case FC_RGBA_VRGB: + case FC_RGBA_VBGR: + vmul = 3; + break; + } + } + + + dx = (x_volume + 63) >> 6; + dy = (y_volume + 63) >> 6; + width = bitmap->width + dx * hmul; + rows = bitmap->rows + dy * vmul; + + *top_bearing += dy; + dx = dx / 2; + dy = ( dy + 1 ) / 2; + + if (*left_bearing > 0 || *left_bearing < -width) + width += hmul; + + if (*top_bearing < 0 || *top_bearing > rows) + rows += vmul; + + + pitch = width; + buf_tmp = (FT_Byte *) malloc ((long)pitch * rows); + if (!buf_tmp) + return; + + memset (buf_tmp, 0, (long)pitch * rows); + + dx *= hmul; + dy *= vmul; + + if (font->info.antialias) + { + int x, y; + int w = bitmap->width; + int r = bitmap->rows; + int offset = dx + dy * pitch; + + for (y = 0; y < r; y++) { + FT_Byte *src = buffer + y * bitmap->pitch; + FT_Byte *dst = buf_tmp + offset + y * pitch; + + for (x = 0; x < w; x++) + *dst++ = *src++; + } + } + else + { + int x, y, s; + int w1 = bitmap->width >> 3; + int w2 = 8 - (bitmap->width - w1 * 8); + int r = bitmap->rows; + int offset = dx + dy * pitch; + + for (y = 0; y < r; y++) { + FT_Byte *src = buffer + y * bitmap->pitch; + FT_Byte *dst = buf_tmp + offset + y * pitch; + + for (x = 0; x < w1; x++) { + FT_Byte b = *src++; + + for (s = 7; s >= 0; s--) + *dst++ = ((b >> s) & 1)? 0xff : 0x00; + } + + if (w2 < 8) { + FT_Byte b = *src; + + for (s = 7; s >= w2; s--) + *dst++ = ((b >> s) & 1)? 0xff : 0x00; + } + } + } + + { + int rows1 = bitmap->rows; + int width1 = bitmap->width; + FT_F26Dot6 x_volume1 = x_volume; + FT_F26Dot6 y_volume1 = y_volume; + int count = hmul; + int direction, rotation; /* 0=right: 1=up: 2=left: 3=down */ + + + direction = (((x_volume1 + 63) >> 6) & 1) ? 0 : 2; + rotation = (((y_volume1 + 63) >> 6) & 1) ? 1 : -1; + + if (direction == 2) + rotation = -rotation; + + x_volume1 *= hmul; + y_volume1 *= vmul; + + + while (x_volume1 > 0 || y_volume1 > 0) + { + FT_Byte* line; + FT_Byte* pos; + int g0, g1, g2; + int i, j, count1, count2, pitch1, pitch2; + FT_F26Dot6 volume; + + + if (direction & 1) + { + if (y_volume1 <= 0) + goto Next; + + volume = (y_volume1 >= 64) ? 255 : y_volume1 * 4; + line = buf_tmp + dx + + ((direction == 1) ? 0 : (rows - 1) * pitch); + count1 = width1; + count2 = rows; + pitch1 = 1; + pitch2 = (direction == 1) ? pitch : -pitch; + + rows1++; + y_volume1 -= 64; + dy -= (direction == 1) ? 1 : 0; + } + else + { + if (x_volume1 <= 0) + goto Next; + + volume = (x_volume1 >= 64) ? 255 : x_volume1 * 4; + line = buf_tmp + dy * pitch + + ((direction == 2) ? 0 : width - 1); + count1 = rows1; + count2 = width; + pitch1 = pitch; + pitch2 = (direction == 2) ? 1 : -1; + + width1++; + x_volume1 -= 64; + dx -= (direction == 2) ? 1 : 0; + } + + + for (i = 1; i <= count1; i++, line += pitch1) + { + pos = line; + g0 = 0; + g1 = *pos; + + for (j = 1; j <= count2; j++, pos += pitch2) + { + g2 = (j == count2) ? 0 : *(pos + pitch2); + + if (g1 || g2) + { + int gray = g1; + int diff0 = g1 - g0; + int diff1 = g2 - g1; + + + if (diff0 > 0 && diff1 < 0) + { + if (volume > diff0) + { + gray += diff0; + g0 = *(pos - pitch2) + volume - diff0; + + *(pos - pitch2) = (FT_Byte) MIN(g0, g1); + } + else + { + gray += volume; + } + + *pos = (FT_Byte) MIN(gray, 255); + } + else if (diff1 >= 0) + { + if ((diff0 = g2 + volume - 255) > 0) + gray += diff0; + + *pos = (FT_Byte) MIN(gray, g2); + } + } + + g0 = g1; + g1 = g2; + } + } + + Next: + if (--count == 0) + { + direction = (direction + rotation) & 3; + count = (direction & 1) ? vmul : hmul; + } + } + } + + + { + FT_Fixed x_scale, y_scale; + FT_F26Dot6 xsize = font->info.xsize; + FT_F26Dot6 ysize = font->info.ysize; + FT_F26Dot6 old_advance = *advanceX; + FT_Vector origin; + + + if (!font->fixedpitch) { + if (*advanceX > 0 && *advanceX < xsize) + *advanceX = FT_MulDiv (*advanceX + x_volume, + xsize, xsize + x_volume); + + if (monochrome && xsize < 32*64 && *advanceX <= old_advance + 64) + *advanceX = old_advance + 64; + + if (*advanceY > 0 && *advanceY < ysize) + *advanceY = FT_MulDiv (*advanceY + y_volume, + ysize, ysize + y_volume); + } + + if (monochrome) + { + if (xsize < 32*64) x_volume = 0; + if (ysize < 32*64) y_volume = 0; + } + else + { + if (xsize < 20*64) x_volume /= 2; + if (ysize < 20*64) y_volume /= 2; + } + + if (font->fixedpitch || old_advance >= xsize) + xsize = old_advance; + + x_scale = FT_DivFix (xsize, xsize + x_volume); + y_scale = FT_DivFix (ysize, ysize + y_volume); + origin.x = -(*left_bearing << 6); + origin.y = *top_bearing << 6; + + BitmapDownscale (buf_tmp, &origin, + left_bearing, top_bearing, + width / hmul, rows / vmul, + x_scale, y_scale, hmul, vmul); + } + + + { + long size, pitch1; + + + if (font->info.antialias) + pitch1 = (width + 3) & ~3; + else + pitch1 = ((width + 31) & ~31) >> 3; + + size = pitch1 * rows; + + if (size > *max_bufSize) { + buffer = (FT_Byte *) malloc (size); + if (!buffer) + goto Exit; + + bitmap->buffer = buffer; + *max_bufSize = (int)size; + } + + bitmap->pitch = pitch1; + bitmap->width = width; + bitmap->rows = rows; + memset (buffer, 0, size); + } + + + if (font->info.antialias) + { + int x, y; + + + for (y = 0; y < rows; y++) { + FT_Byte *src = buf_tmp + y * pitch; + FT_Byte *dst = buffer + y * bitmap->pitch; + + for (x = 0; x < width; x++) + *dst++ = *src++; + } + } + else + { + int x, y, s; + int w1 = width >> 3; + int w2 = 8 - (width & 7); + FT_Byte b; + + for (y = 0; y < rows; y++) { + FT_Byte *src = buf_tmp + y * pitch; + FT_Byte *dst = buffer + y * bitmap->pitch; + + for (x = 0; x < w1; x++) { + for (b = 0, s = 7; s >= 0; s--) + b |= ((*src++ >= 0x80) ? (1 << s) : 0); + *dst++ = b; + } + + if (w2 < 8) { + for (b = 0, s = 7; s >= w2; s--) + b |= ((*src++ >= 0x80) ? (1 << s) : 0); + *dst = b; + } + } + } + +Exit: + free (buf_tmp); +} + diff -uP xft-2.1.1-orig/xftfreetype.c xft-2.1.1-new/xftfreetype.c --- xc/lib/Xft/xftfreetype.c Thu Apr 17 13:29:24 2003 +++ xc/lib/Xft/xftfreetype.c Tue Sep 23 05:15:18 2003 @@ -28,6 +28,8 @@ #include "xftint.h" #include +#include + FT_Library _XftFTlibrary; #define FT_Matrix_Equal(a,b) ((a)->xx == (b)->xx && \ @@ -329,6 +331,7 @@ FcChar32 hash, *hashp; FT_Face face; int nhash; + FcBool accept_bitmap; if (!info) return FcFalse; @@ -451,13 +454,19 @@ */ fi->load_flags = FT_LOAD_DEFAULT; - /* disable bitmaps when anti-aliasing or transforming glyphs */ - /* Generally, we want to prefer bitmaps when we have them, - * even when antialiasing, because they make Han characters - * more legible. But for Japanese, we want to make the - * opposite choice, so it's controlled through fonts.conf. - */ - if ((fi->antialias && !prefer_bitmaps) || fi->transform) + /* disable bitmaps embedded in scalable fonts */ + /* when not requested or transforming glyphs */ + switch (FcPatternGetBool (pattern, "embeddedbitmap", 0, &accept_bitmap)) { + case FcResultNoMatch: + accept_bitmap = FcFalse; + break; + case FcResultMatch: + break; + default: + goto bail1; + } + + if ((!accept_bitmap && fi->antialias && !prefer_bitmaps) || fi->transform) fi->load_flags |= FT_LOAD_NO_BITMAP; /* disable hinting if requested */ @@ -553,6 +567,19 @@ } /* + * Check for weight + */ + switch (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &fi->weight)) { + case FcResultNoMatch: + fi->weight = FC_WEIGHT_MEDIUM; + break; + case FcResultMatch: + break; + default: + goto bail1; + } + + /* * Step over hash value in the structure */ hash = 0; @@ -893,6 +920,61 @@ font->max_glyph_memory = max_glyph_memory; font->use_free_glyphs = info->use_free_glyphs; + /* + * Parameters used to make a faked bold bitmap + */ + font->make_bold = FcFalse; + if (fi->weight > FC_WEIGHT_MEDIUM && + (face->style_flags & FT_STYLE_FLAG_BOLD) == 0) { + if (fi->matrix.xy == 0 || fi->matrix.yx == 0) + font->make_bold = FcTrue; + } + + font->x_volume = font->y_volume = 0; + font->fixedpitch = (fi->spacing == FC_PROPORTIONAL) ? FcFalse : FcTrue; + + if (font->make_bold) { + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table (face, ft_sfnt_os2); + FT_F26Dot6 xsize = FT_MulFix (fi->xsize, fi->matrix.xx); + FT_F26Dot6 ysize = FT_MulFix (fi->ysize, fi->matrix.yy); + + font->x_volume = xsize/80; + font->y_volume = ysize/80; + + if (os2) { + FT_Byte bSerif = os2->panose[1]; + FT_Byte bWeight = os2->panose[2]; + FT_Byte bProportion = os2->panose[3]; + + if (bSerif >= 2 && bSerif <= 10) { + font->x_volume = xsize/64; + font->y_volume = ysize/256; + } + + if (bWeight >= 2 && bWeight != 6 && bWeight <= 11) { + font->x_volume = font->x_volume * 10 / (bWeight + 4); + font->y_volume = font->y_volume * 10 / (bWeight + 4); + } + + if (bProportion == 9) + font->fixedpitch = FcTrue; + } + +#if 1 + if (xsize < 20*64 && font->x_volume < xsize/50) { + font->x_volume = font->x_volume * (40*64 - fi->xsize) / (20*64); + if (font->x_volume > xsize/50) + font->x_volume = xsize/50; + } + + if (ysize < 20*64 && font->y_volume < ysize/50) { + font->y_volume = font->y_volume * (40*64 - fi->ysize) / (20*64); + if (font->y_volume > ysize/50) + font->y_volume = ysize/50; + } +#endif + } + _XftUnlockFile (fi->file); return &font->public; diff -uP xft-2.1.1-orig/xftglyphs.c xft-2.1.1-new/xftglyphs.c --- xc/lib/Xft/xftglyphs.c Thu Apr 17 13:29:24 2003 +++ xc/lib/Xft/xftglyphs.c Tue Sep 23 04:21:29 2003 @@ -29,6 +29,8 @@ #include #include +#include "makebold.c" + static const int filters[3][3] = { /* red */ #if 0 @@ -309,7 +311,8 @@ * If the glyph is relatively large (> 1% of server memory), * don't send it until necessary */ - if (!need_bitmaps && size > info->max_glyph_memory / 100) + if (!need_bitmaps && size > info->max_glyph_memory / 100 && + !font->make_bold) continue; /* @@ -403,6 +406,45 @@ continue; } + /* + * Make bold bitmap + */ + if (font->make_bold) { + ftbit.width = width * hmul; + ftbit.rows = height * vmul; + ftbit.pitch = pitch; + ftbit.buffer = bufBitmap; + xftg->metrics.x = -xftg->metrics.x; + + if (glyphslot->format == ft_glyph_format_bitmap) + ftbit.pixel_mode = glyphslot->bitmap.pixel_mode; + + MakeBoldBitmap (pub, &ftbit, + &xftg->metrics.x, + &xftg->metrics.y, + &glyphslot->advance.x, + &glyphslot->advance.y, &bufSize); + + xftg->metrics.width = width = ftbit.width / hmul; + xftg->metrics.height = height = ftbit.rows / vmul; + xftg->metrics.x = -xftg->metrics.x; + + if (font->info.spacing == FC_PROPORTIONAL) { + xftg->metrics.xOff = TRUNC(ROUND(glyphslot->advance.x)); + xftg->metrics.yOff = -TRUNC(ROUND(glyphslot->advance.y)); + } + + pitch = ftbit.pitch; + size = pitch * height * vmul; + + if (ftbit.buffer != bufBitmap) { + if (bufBitmap != bufLocal) + free (bufBitmap); + + bufBitmap = ftbit.buffer; + } + } + if (XftDebug() & XFT_DBG_GLYPH) { printf ("glyph %d:\n", (int) glyphindex); diff -uP xft-2.1.1-orig/xftint.h xft-2.1.1-new/xftint.h --- xc/lib/Xft/xftint.h Thu Apr 17 13:29:24 2003 +++ xc/lib/Xft/xftint.h Mon Sep 22 08:39:52 2003 @@ -116,6 +116,7 @@ int spacing; FcBool minspace; int char_width; + int weight; }; /* @@ -152,6 +153,13 @@ unsigned long glyph_memory; unsigned long max_glyph_memory; FcBool use_free_glyphs; /* Use XRenderFreeGlyphs */ + /* + * Parameters used to make a faked bold bitmap + */ + FcBool make_bold; + FT_Pos x_volume; + FT_Pos y_volume; + FcBool fixedpitch; /* for CJK fixed TrueType fonts */ } XftFontInt; typedef enum _XftClipType {