dwrite: Implement CreateAlphaTexture().

This commit is contained in:
Nikolay Sivov 2015-07-31 01:30:08 +03:00 committed by Alexandre Julliard
parent 6d1f47902b
commit e08b77b0a9
4 changed files with 188 additions and 8 deletions

View file

@ -189,6 +189,7 @@ extern UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32) DECLSPEC_HIDDEN;
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(IDWriteFontFace2*,FLOAT,UINT16,BOOL,RECT*) DECLSPEC_HIDDEN;
extern void freetype_get_glyph_bitmap(IDWriteFontFace2*,FLOAT,UINT16,const RECT*,BYTE*) DECLSPEC_HIDDEN;
/* Glyph shaping */
enum SCRIPT_JUSTIFY

View file

@ -1,6 +1,7 @@
/*
* Font and collections
*
* Copyright 2011 Huw Davies
* Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
* Copyright 2014 Aric Stewart for CodeWeavers
*
@ -108,6 +109,7 @@ struct dwrite_fonttable {
enum runanalysis_readystate {
RUNANALYSIS_BOUNDS = 1 << 0,
RUNANALYSIS_BITMAP = 1 << 1,
};
struct dwrite_glyphrunanalysis {
@ -122,8 +124,10 @@ struct dwrite_glyphrunanalysis {
UINT16 *glyphs;
FLOAT *advances;
DWRITE_GLYPH_OFFSET *offsets;
RECT bounds;
UINT8 ready;
RECT bounds;
BYTE *bitmap;
};
#define GLYPH_BLOCK_SHIFT 8
@ -2907,6 +2911,7 @@ static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface)
heap_free(This->glyphs);
heap_free(This->advances);
heap_free(This->offsets);
heap_free(This->bitmap);
heap_free(This);
}
@ -2986,6 +2991,99 @@ static HRESULT WINAPI glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnal
return S_OK;
}
static inline int get_dib_stride( int width, int bpp )
{
return ((width * bpp + 31) >> 3) & ~3;
}
static inline BYTE *get_pixel_ptr(BYTE *ptr, DWRITE_TEXTURE_TYPE type, const RECT *runbounds, const RECT *bounds)
{
if (type == DWRITE_TEXTURE_CLEARTYPE_3x1)
return ptr + (runbounds->top - bounds->top) * (bounds->right - bounds->left) * 3 +
(runbounds->left - bounds->left) * 3;
else
return ptr + (runbounds->top - bounds->top) * (bounds->right - bounds->left) +
runbounds->left - bounds->left;
}
static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DWRITE_TEXTURE_TYPE type)
{
static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
IDWriteFontFace2 *fontface2;
BOOL is_rtl, nohint;
FLOAT origin_x;
UINT32 i, size;
IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace2, (void**)&fontface2);
nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
size = (analysis->bounds.right - analysis->bounds.left)*(analysis->bounds.bottom - analysis->bounds.top);
if (type == DWRITE_TEXTURE_CLEARTYPE_3x1)
size *= 3;
analysis->bitmap = heap_alloc_zero(size);
origin_x = 0.0;
is_rtl = analysis->run.bidiLevel & 1;
for (i = 0; i < analysis->run.glyphCount; i++) {
const DWRITE_GLYPH_OFFSET *offset = &analysis->offsets[i];
FLOAT advance = analysis->advances[i];
int pitch, x, y, width, height;
BYTE *glyph, *src, *dst;
RECT bbox;
freetype_get_glyph_bbox(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], nohint, &bbox);
if (IsRectEmpty(&bbox)) {
origin_x += is_rtl ? -advance : advance;
continue;
}
width = bbox.right - bbox.left;
height = bbox.bottom - bbox.top;
pitch = ((width + 31) >> 5) << 2;
src = glyph = heap_alloc_zero((bbox.bottom - bbox.top) * pitch);
freetype_get_glyph_bitmap(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], &bbox, glyph);
if (is_rtl)
OffsetRect(&bbox, origin_x - offset->advanceOffset - advance, -offset->ascenderOffset);
else
OffsetRect(&bbox, origin_x + offset->advanceOffset, offset->ascenderOffset);
OffsetRect(&bbox, analysis->originX, analysis->originY);
/* 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;
}
}
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;
}
}
heap_free(glyph);
origin_x += is_rtl ? -advance : advance;
}
IDWriteFontFace2_Release(fontface2);
analysis->ready |= RUNANALYSIS_BITMAP;
}
static HRESULT WINAPI glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type,
RECT const *bounds, BYTE *bitmap, UINT32 size)
{
@ -2993,7 +3091,7 @@ static HRESULT WINAPI glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysi
UINT32 required;
RECT runbounds;
FIXME("(%p)->(%d %s %p %u): stub\n", This, type, wine_dbgstr_rect(bounds), bitmap, size);
TRACE("(%p)->(%d %s %p %u)\n", This, type, wine_dbgstr_rect(bounds), bitmap, size);
if (!bounds || !bitmap || (UINT32)type > DWRITE_TEXTURE_CLEARTYPE_3x1)
return E_INVALIDARG;
@ -3024,15 +3122,30 @@ static HRESULT WINAPI glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysi
;
}
memset(bitmap, 0, size);
glyphrunanalysis_get_texturebounds(This, &runbounds);
if (IntersectRect(&runbounds, &runbounds, bounds)) {
int pixel_size = type == DWRITE_TEXTURE_CLEARTYPE_3x1 ? 3 : 1;
int src_width = (This->bounds.right - This->bounds.left) * pixel_size;
int dst_width = (bounds->right - bounds->left) * pixel_size;
int draw_width = (runbounds.right - runbounds.left) * pixel_size;
BYTE *src, *dst;
int y;
/* special case when there's nothing to return */
if (!IntersectRect(&runbounds, &runbounds, bounds)) {
memset(bitmap, 0, size);
return S_OK;
if (!(This->ready & RUNANALYSIS_BITMAP))
glyphrunanalysis_render(This, type);
src = get_pixel_ptr(This->bitmap, type, &runbounds, &This->bounds);
dst = get_pixel_ptr(bitmap, type, &runbounds, bounds);
for (y = 0; y < runbounds.bottom - runbounds.top; y++) {
memcpy(dst, src, draw_width);
src += src_width;
dst += dst_width;
}
}
return E_NOTIMPL;
return S_OK;
}
static HRESULT WINAPI glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis *iface, IDWriteRenderingParams *params,
@ -3099,6 +3212,7 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_GLY
analysis->ref = 1;
analysis->rendering_mode = rendering_mode;
analysis->ready = 0;
analysis->bitmap = NULL;
analysis->ppdip = ppdip;
analysis->originX = originX;
analysis->originY = originY;

View file

@ -70,7 +70,9 @@ MAKE_FUNCPTR(FT_Init_FreeType);
MAKE_FUNCPTR(FT_Library_Version);
MAKE_FUNCPTR(FT_Load_Glyph);
MAKE_FUNCPTR(FT_New_Memory_Face);
MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
MAKE_FUNCPTR(FT_Outline_Transform);
MAKE_FUNCPTR(FT_Outline_Translate);
MAKE_FUNCPTR(FTC_CMapCache_Lookup);
MAKE_FUNCPTR(FTC_CMapCache_New);
MAKE_FUNCPTR(FTC_ImageCache_Lookup);
@ -146,7 +148,9 @@ BOOL init_freetype(void)
LOAD_FUNCPTR(FT_Library_Version)
LOAD_FUNCPTR(FT_Load_Glyph)
LOAD_FUNCPTR(FT_New_Memory_Face)
LOAD_FUNCPTR(FT_Outline_Get_Bitmap)
LOAD_FUNCPTR(FT_Outline_Transform)
LOAD_FUNCPTR(FT_Outline_Translate)
LOAD_FUNCPTR(FTC_CMapCache_Lookup)
LOAD_FUNCPTR(FTC_CMapCache_New)
LOAD_FUNCPTR(FTC_ImageCache_Lookup)
@ -473,7 +477,7 @@ void freetype_get_glyph_bbox(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 in
imagetype.face_id = fontface;
imagetype.width = 0;
imagetype.height = emSize;
imagetype.flags = nohint ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
imagetype.flags = FT_LOAD_DEFAULT;
EnterCriticalSection(&freetype_cs);
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0)
@ -487,6 +491,59 @@ void freetype_get_glyph_bbox(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 in
ret->bottom = -bbox.yMin;
}
void freetype_get_glyph_bitmap(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, const RECT *bbox, BYTE *buf)
{
FTC_ImageTypeRec imagetype;
FT_Glyph glyph;
imagetype.face_id = fontface;
imagetype.width = 0;
imagetype.height = emSize;
imagetype.flags = FT_LOAD_DEFAULT;
EnterCriticalSection(&freetype_cs);
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0) {
int width = bbox->right - bbox->left;
int pitch = ((width + 31) >> 5) << 2;
int height = bbox->bottom - bbox->top;
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
FT_Bitmap ft_bitmap;
ft_bitmap.width = width;
ft_bitmap.rows = height;
ft_bitmap.pitch = pitch;
ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
ft_bitmap.buffer = buf;
pFT_Outline_Translate(&outline->outline, -bbox->left, -bbox->bottom);
/* Note: FreeType will only set 'black' bits for us. */
memset(buf, 0, height*pitch);
pFT_Outline_Get_Bitmap(library, &outline->outline, &ft_bitmap);
}
else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
FT_Bitmap *bitmap = &((FT_BitmapGlyph)glyph)->bitmap;
BYTE *src = bitmap->buffer, *dst = buf;
int w = min(pitch, (bitmap->width + 7) >> 3);
int h = min(height, bitmap->rows);
memset(buf, 0, height*pitch);
while (h--) {
memcpy(dst, src, w);
src += bitmap->pitch;
dst += pitch;
}
}
else
FIXME("format %d not handled\n", glyph->format);
}
LeaveCriticalSection(&freetype_cs);
}
#else /* HAVE_FREETYPE */
BOOL init_freetype(void)
@ -543,4 +600,10 @@ void freetype_get_glyph_bbox(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 in
ret->left = ret->right = ret->top = ret->bottom = 0;
}
void freetype_get_glyph_bitmap(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, const RECT *bbox, BYTE *buf)
{
UINT32 size = (bbox->right - bbox->left)*(bbox->bottom - bbox->top);
memset(buf, 0, size);
}
#endif /* HAVE_FREETYPE */

View file

@ -328,6 +328,8 @@ typedef enum DWRITE_NUMBER_SUBSTITUTION_METHOD
DWRITE_NUMBER_SUBSTITUTION_METHOD_TRADITIONAL
} DWRITE_NUMBER_SUBSTITUTION_METHOD;
cpp_quote("#define DWRITE_ALPHA_MAX 255")
typedef enum DWRITE_TEXTURE_TYPE
{
DWRITE_TEXTURE_ALIASED_1x1,