dwrite: Implement CreateAlphaTexture().
This commit is contained in:
parent
6d1f47902b
commit
e08b77b0a9
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue