[PATCH 2/3] dwrite: Implement CreateAlphaTexture()
Nikolay Sivov
nsivov at codeweavers.com
Thu Jul 30 17:30:08 CDT 2015
---
-------------- next part --------------
From 50a0d4951df87963e9aaba0950a9bde63442239f Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri, 31 Jul 2015 01:20:25 +0300
Subject: [PATCH 2/3] dwrite: Implement CreateAlphaTexture()
---
dlls/dwrite/dwrite_private.h | 1 +
dlls/dwrite/font.c | 130 ++++++++++++++++++++++++++++++++++++++++---
dlls/dwrite/freetype.c | 65 +++++++++++++++++++++-
include/dwrite.idl | 2 +
4 files changed, 189 insertions(+), 9 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 59bef03..b0168ae 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -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
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 5f32c31..d72f8a6 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -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);
-
- /* special case when there's nothing to return */
- if (!IntersectRect(&runbounds, &runbounds, bounds)) {
- memset(bitmap, 0, size);
- return S_OK;
+ 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;
+
+ 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;
diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c
index 0e8b976..711d601 100644
--- a/dlls/dwrite/freetype.c
+++ b/dlls/dwrite/freetype.c
@@ -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 */
diff --git a/include/dwrite.idl b/include/dwrite.idl
index 2ae5164..bb41b4f 100644
--- a/include/dwrite.idl
+++ b/include/dwrite.idl
@@ -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,
--
2.1.4
More information about the wine-patches
mailing list