dwrite: Implement grayscale rendering mode.

This commit is contained in:
Nikolay Sivov 2015-08-27 08:39:45 +03:00 committed by Alexandre Julliard
parent 3f4a284f58
commit 26fbbdc48b
3 changed files with 130 additions and 51 deletions

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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, &copy) == 0) {
pFT_Outline_Copy(src, &copy);
pFT_Outline_Translate(&copy, -bbox->left << 6, bbox->bottom << 6);
pFT_Outline_Get_Bitmap(library, &copy, &ft_bitmap);
pFT_Outline_Done(library, &copy);
}
}
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, &copy) == 0) {
pFT_Outline_Copy(src, &copy);
pFT_Outline_Translate(&copy, -bbox->left << 6, bbox->bottom << 6);
pFT_Outline_Get_Bitmap(library, &copy, &ft_bitmap);
pFT_Outline_Done(library, &copy);
}
}
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, &copy) == 0) {
pFT_Outline_Copy(src, &copy);
pFT_Outline_Translate(&copy, -bbox->left << 6, bbox->bottom << 6);
pFT_Outline_Get_Bitmap(library, &copy, &ft_bitmap);
pFT_Outline_Done(library, &copy);
}
}
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)