diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 39043d924e9..a7b8c462f92 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -199,6 +199,7 @@ struct dwrite_glyphbitmap { INT pitch; RECT bbox; BYTE *buf; + DWRITE_TEXTURE_TYPE type; }; extern BOOL init_freetype(void) DECLSPEC_HIDDEN; @@ -212,7 +213,7 @@ extern UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32,INT) DECLSPEC_HID extern BOOL freetype_has_kerning_pairs(IDWriteFontFace2*) DECLSPEC_HIDDEN; extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2*,UINT16,UINT16) DECLSPEC_HIDDEN; extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; -extern void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; +extern BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; extern INT freetype_get_charmap_index(IDWriteFontFace2*,BOOL*) DECLSPEC_HIDDEN; extern INT32 freetype_get_glyph_advance(IDWriteFontFace2*,FLOAT,UINT16,DWRITE_MEASURING_MODE) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index f66d49c2f15..1b9b6a2b310 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -3622,6 +3622,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip; glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; + glyph_bitmap.type = type; bbox = &glyph_bitmap.bbox; for (i = 0; i < analysis->run.glyphCount; i++) { @@ -3629,6 +3630,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW FLOAT advance = analysis->advances[i]; int x, y, width, height; BYTE *src, *dst; + BOOL is_1bpp; glyph_bitmap.index = analysis->run.glyphIndices[i]; freetype_get_glyph_bbox(&glyph_bitmap); @@ -3640,10 +3642,14 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW width = bbox->right - bbox->left; height = bbox->bottom - bbox->top; - glyph_bitmap.pitch = ((width + 31) >> 5) << 2; + + if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) + glyph_bitmap.pitch = (width + 3) / 4 * 4; + else + glyph_bitmap.pitch = ((width + 31) >> 5) << 2; glyph_bitmap.buf = src = heap_alloc_zero(height * glyph_bitmap.pitch); - freetype_get_glyph_bitmap(&glyph_bitmap); + is_1bpp = freetype_get_glyph_bitmap(&glyph_bitmap); if (is_rtl) OffsetRect(bbox, origin_x - advance, 0); @@ -3658,21 +3664,32 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW /* blit to analysis bitmap */ dst = get_pixel_ptr(analysis->bitmap, type, bbox, &analysis->bounds); - /* convert 1bpp to 8bpp/24bpp */ - if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) { - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) - dst[3*x] = dst[3*x+1] = dst[3*x+2] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0; - src += get_dib_stride(width, 1); - dst += (analysis->bounds.right - analysis->bounds.left) * 3; + if (is_1bpp) { + /* convert 1bpp to 8bpp/24bpp */ + if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[3*x] = dst[3*x+1] = dst[3*x+2] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0; + src += glyph_bitmap.pitch; + dst += (analysis->bounds.right - analysis->bounds.left) * 3; + } + } + else { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) + dst[x] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0; + src += get_dib_stride(width, 1); + dst += analysis->bounds.right - analysis->bounds.left; + } } } else { + /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */ for (y = 0; y < height; y++) { for (x = 0; x < width; x++) - dst[x] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0; - src += get_dib_stride(width, 1); - dst += analysis->bounds.right - analysis->bounds.left; + dst[3*x] = dst[3*x+1] = dst[3*x+2] = src[x]; + src += glyph_bitmap.pitch; + dst += (analysis->bounds.right - analysis->bounds.left) * 3; } } diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index 1f7e6a9f99f..4eaef0299c5 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -510,10 +510,101 @@ void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap) bitmap->bbox.bottom = -bbox.yMin; } -void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) +static BOOL freetype_get_aliased_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_Glyph glyph) { const RECT *bbox = &bitmap->bbox; + int width = bbox->right - bbox->left; + int height = bbox->bottom - bbox->top; + + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { + FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; + const FT_Outline *src = &outline->outline; + FT_Bitmap ft_bitmap; + FT_Outline copy; + + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = bitmap->pitch; + ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO; + ft_bitmap.buffer = bitmap->buf; + + /* Note: FreeType will only set 'black' bits for us. */ + if (pFT_Outline_New(library, src->n_points, src->n_contours, ©) == 0) { + pFT_Outline_Copy(src, ©); + pFT_Outline_Translate(©, -bbox->left << 6, bbox->bottom << 6); + pFT_Outline_Get_Bitmap(library, ©, &ft_bitmap); + pFT_Outline_Done(library, ©); + } + } + else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { + FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; + BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; + int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); + int h = min(height, ft_bitmap->rows); + + while (h--) { + memcpy(dst, src, w); + src += ft_bitmap->pitch; + dst += bitmap->pitch; + } + } + else + FIXME("format %x not handled\n", glyph->format); + + return TRUE; +} + +static BOOL freetype_get_aa_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_Glyph glyph) +{ + const RECT *bbox = &bitmap->bbox; + int width = bbox->right - bbox->left; + int height = bbox->bottom - bbox->top; + BOOL ret = FALSE; + + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { + FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; + const FT_Outline *src = &outline->outline; + FT_Bitmap ft_bitmap; + FT_Outline copy; + + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = bitmap->pitch; + ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + ft_bitmap.buffer = bitmap->buf; + + /* Note: FreeType will only set 'black' bits for us. */ + if (pFT_Outline_New(library, src->n_points, src->n_contours, ©) == 0) { + pFT_Outline_Copy(src, ©); + pFT_Outline_Translate(©, -bbox->left << 6, bbox->bottom << 6); + pFT_Outline_Get_Bitmap(library, ©, &ft_bitmap); + pFT_Outline_Done(library, ©); + } + } + else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { + FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; + BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; + int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); + int h = min(height, ft_bitmap->rows); + + while (h--) { + memcpy(dst, src, w); + src += ft_bitmap->pitch; + dst += bitmap->pitch; + } + + ret = TRUE; + } + else + FIXME("format %x not handled\n", glyph->format); + + return ret; +} + +BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) +{ FTC_ImageTypeRec imagetype; + BOOL ret = FALSE; FT_Glyph glyph; imagetype.face_id = bitmap->fontface; @@ -523,45 +614,14 @@ void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) EnterCriticalSection(&freetype_cs); if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) { - int width = bbox->right - bbox->left; - int height = bbox->bottom - bbox->top; - - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; - const FT_Outline *src = &outline->outline; - FT_Bitmap ft_bitmap; - FT_Outline copy; - - ft_bitmap.width = width; - ft_bitmap.rows = height; - ft_bitmap.pitch = bitmap->pitch; - ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO; - ft_bitmap.buffer = bitmap->buf; - - /* Note: FreeType will only set 'black' bits for us. */ - if (pFT_Outline_New(library, src->n_points, src->n_contours, ©) == 0) { - pFT_Outline_Copy(src, ©); - pFT_Outline_Translate(©, -bbox->left << 6, bbox->bottom << 6); - pFT_Outline_Get_Bitmap(library, ©, &ft_bitmap); - pFT_Outline_Done(library, ©); - } - } - else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { - FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; - BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; - int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); - int h = min(height, ft_bitmap->rows); - - while (h--) { - memcpy(dst, src, w); - src += ft_bitmap->pitch; - dst += bitmap->pitch; - } - } + if (bitmap->type == DWRITE_TEXTURE_CLEARTYPE_3x1) + ret = freetype_get_aa_glyph_bitmap(bitmap, glyph); else - FIXME("format %x not handled\n", glyph->format); + ret = freetype_get_aliased_glyph_bitmap(bitmap, glyph); } LeaveCriticalSection(&freetype_cs); + + return ret; } INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol) @@ -675,8 +735,9 @@ void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap) memset(&bitmap->bbox, 0, sizeof(bitmap->bbox)); } -void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) +BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) { + return FALSE; } INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol)