[PATCH 4/4] dwrite: Implement parameter validation for CreateAlphaTexture()
Nikolay Sivov
nsivov at codeweavers.com
Wed Jul 29 04:00:26 CDT 2015
---
-------------- next part --------------
>From 74f9b445bf913133ae92fb7848c58d01782e5238 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Wed, 29 Jul 2015 11:55:15 +0300
Subject: [PATCH 4/4] dwrite: Implement parameter validation for
CreateAlphaTexture()
---
dlls/dwrite/font.c | 109 +++++++++++++++++++++++++-----------
dlls/dwrite/tests/font.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 220 insertions(+), 31 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 60efcf3..a3f58b9 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -2911,75 +2911,122 @@ static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface)
return ref;
}
-static HRESULT WINAPI glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type, RECT *bounds)
+static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *analysis, RECT *bounds)
{
- struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
IDWriteFontFace2 *fontface2;
BOOL nohint, is_rtl;
FLOAT origin_x;
HRESULT hr;
UINT32 i;
- TRACE("(%p)->(%d %p)\n", This, type, bounds);
-
- if ((UINT32)type > DWRITE_TEXTURE_CLEARTYPE_3x1) {
- memset(bounds, 0, sizeof(*bounds));
- return E_INVALIDARG;
- }
-
- if ((type == DWRITE_TEXTURE_ALIASED_1x1 && This->rendering_mode != DWRITE_RENDERING_MODE_ALIASED) ||
- (type == DWRITE_TEXTURE_CLEARTYPE_3x1 && This->rendering_mode == DWRITE_RENDERING_MODE_ALIASED)) {
- memset(bounds, 0, sizeof(*bounds));
- return S_OK;
- }
-
- if (This->ready & RUNANALYSIS_BOUNDS) {
- *bounds = This->bounds;
- return S_OK;
+ if (analysis->ready & RUNANALYSIS_BOUNDS) {
+ *bounds = analysis->bounds;
+ return;
}
- if (This->run.isSideways)
+ if (analysis->run.isSideways)
FIXME("sideways runs are not supported.\n");
- hr = IDWriteFontFace_QueryInterface(This->run.fontFace, &IID_IDWriteFontFace2, (void**)&fontface2);
+ hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace2, (void**)&fontface2);
if (FAILED(hr))
WARN("failed to get IDWriteFontFace2, 0x%08x\n", hr);
- nohint = This->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || This->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
+ nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
/* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
for any non-zero glyph ascender */
origin_x = 0.0;
- is_rtl = This->run.bidiLevel & 1;
- for (i = 0; i < This->run.glyphCount; i++) {
- const DWRITE_GLYPH_OFFSET *offset = &This->offsets[i];
- FLOAT advance = This->advances[i];
+ 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];
RECT bbox;
- freetype_get_glyph_bbox(fontface2, This->run.fontEmSize * This->ppdip, This->run.glyphIndices[i], nohint, &bbox);
+ freetype_get_glyph_bbox(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], nohint, &bbox);
if (is_rtl)
OffsetRect(&bbox, origin_x - offset->advanceOffset - advance, -offset->ascenderOffset);
else
OffsetRect(&bbox, origin_x + offset->advanceOffset, offset->ascenderOffset);
- UnionRect(&This->bounds, &This->bounds, &bbox);
+ UnionRect(&analysis->bounds, &analysis->bounds, &bbox);
origin_x += is_rtl ? -advance : advance;
}
IDWriteFontFace2_Release(fontface2);
- This->ready |= RUNANALYSIS_BOUNDS;
- *bounds = This->bounds;
+ analysis->ready |= RUNANALYSIS_BOUNDS;
+ *bounds = analysis->bounds;
+}
+
+static HRESULT WINAPI glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type, RECT *bounds)
+{
+ struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
+
+ TRACE("(%p)->(%d %p)\n", This, type, bounds);
+
+ if ((UINT32)type > DWRITE_TEXTURE_CLEARTYPE_3x1) {
+ memset(bounds, 0, sizeof(*bounds));
+ return E_INVALIDARG;
+ }
+
+ if ((type == DWRITE_TEXTURE_ALIASED_1x1 && This->rendering_mode != DWRITE_RENDERING_MODE_ALIASED) ||
+ (type == DWRITE_TEXTURE_CLEARTYPE_3x1 && This->rendering_mode == DWRITE_RENDERING_MODE_ALIASED)) {
+ memset(bounds, 0, sizeof(*bounds));
+ return S_OK;
+ }
+
+ glyphrunanalysis_get_texturebounds(This, bounds);
return S_OK;
}
static HRESULT WINAPI glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type,
- RECT const* bounds, BYTE* alphaValues, UINT32 bufferSize)
+ RECT const *bounds, BYTE *bitmap, UINT32 size)
{
struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
- FIXME("(%p)->(%d %p %p %u): stub\n", This, type, bounds, alphaValues, bufferSize);
+ UINT32 required;
+ RECT runbounds;
+
+ FIXME("(%p)->(%d %s %p %u): stub\n", This, type, wine_dbgstr_rect(bounds), bitmap, size);
+
+ if (!bounds || !bitmap || (UINT32)type > DWRITE_TEXTURE_CLEARTYPE_3x1)
+ return E_INVALIDARG;
+
+ /* make sure buffer is large enough for requested texture type */
+ required = (bounds->right - bounds->left) * (bounds->bottom - bounds->top);
+ if (type == DWRITE_TEXTURE_CLEARTYPE_3x1)
+ required *= 3;
+
+ if (size < required)
+ return E_NOT_SUFFICIENT_BUFFER;
+
+ /* validate requested texture type with rendering mode */
+ switch (This->rendering_mode)
+ {
+ case DWRITE_RENDERING_MODE_ALIASED:
+ if (type != DWRITE_TEXTURE_ALIASED_1x1)
+ return DWRITE_E_UNSUPPORTEDOPERATION;
+ break;
+ case DWRITE_RENDERING_MODE_GDI_CLASSIC:
+ case DWRITE_RENDERING_MODE_GDI_NATURAL:
+ case DWRITE_RENDERING_MODE_NATURAL:
+ case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC:
+ if (type != DWRITE_TEXTURE_CLEARTYPE_3x1)
+ return DWRITE_E_UNSUPPORTEDOPERATION;
+ break;
+ default:
+ ;
+ }
+
+ 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;
+ }
+
return E_NOTIMPL;
}
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 08de0d9..aeb84bb 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -4449,6 +4449,147 @@ static void test_GetAlphaBlendParams(void)
IDWriteFactory_Release(factory);
}
+static void test_CreateAlphaTexture(void)
+{
+ IDWriteGlyphRunAnalysis *analysis;
+ DWRITE_GLYPH_METRICS metrics;
+ DWRITE_GLYPH_OFFSET offset;
+ IDWriteFontFace *fontface;
+ IDWriteFactory *factory;
+ DWRITE_GLYPH_RUN run;
+ UINT32 ch, size;
+ BYTE buff[1024];
+ RECT bounds, r;
+ FLOAT advance;
+ UINT16 glyph;
+ HRESULT hr;
+
+ factory = create_factory();
+ fontface = create_fontface(factory);
+
+ ch = 'A';
+ glyph = 0;
+ hr = IDWriteFontFace_GetGlyphIndices(fontface, &ch, 1, &glyph);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(glyph > 0, "got %u\n", glyph);
+
+ hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, &glyph, 1, &metrics, FALSE);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ advance = metrics.advanceWidth;
+
+ offset.advanceOffset = 0.0;
+ offset.ascenderOffset = 0.0;
+
+ run.fontFace = fontface;
+ run.fontEmSize = 24.0;
+ run.glyphCount = 1;
+ run.glyphIndices = &glyph;
+ run.glyphAdvances = &advance;
+ run.glyphOffsets = &offset;
+ run.isSideways = FALSE;
+ run.bidiLevel = 0;
+
+ hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
+ DWRITE_RENDERING_MODE_NATURAL, DWRITE_MEASURING_MODE_NATURAL,
+ 0.0, 0.0, &analysis);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ SetRectEmpty(&bounds);
+ hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!IsRectEmpty(&bounds), "got empty rect\n");
+ size = (bounds.right - bounds.left)*(bounds.bottom - bounds.top)*3;
+ ok(sizeof(buff) >= size, "required %u\n", size);
+
+ /* invalid type value */
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1+1, &bounds, buff, sizeof(buff));
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
+
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds, buff, 2);
+ ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
+
+ /* vista version allows texture type mismatch, mark it broken for now */
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds, buff, sizeof(buff));
+ ok(hr == DWRITE_E_UNSUPPORTEDOPERATION || broken(hr == S_OK), "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf || broken(buff[0] == 0), "got %1x\n", buff[0]);
+
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds, buff, size-1);
+ ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
+
+ IDWriteGlyphRunAnalysis_Release(analysis);
+
+ hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
+ DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
+ 0.0, 0.0, &analysis);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ SetRectEmpty(&bounds);
+ hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!IsRectEmpty(&bounds), "got empty rect\n");
+ size = (bounds.right - bounds.left)*(bounds.bottom - bounds.top);
+ ok(sizeof(buff) >= size, "required %u\n", size);
+
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, NULL, buff, sizeof(buff));
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
+
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, NULL, NULL, sizeof(buff));
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, NULL, buff, 0);
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
+
+ /* buffer size is not enough */
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds, buff, size-1);
+ ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
+
+ /* request texture for rectangle that doesn't intersect */
+ memset(buff, 0xcf, sizeof(buff));
+ r = bounds;
+ OffsetRect(&r, (bounds.right - bounds.left)*2, 0);
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &r, buff, sizeof(buff));
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(buff[0] == 0, "got %1x\n", buff[0]);
+
+ memset(buff, 0xcf, sizeof(buff));
+ r = bounds;
+ OffsetRect(&r, (bounds.right - bounds.left)*2, 0);
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &r, buff, sizeof(buff));
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(buff[0] == 0, "got %1x\n", buff[0]);
+
+ /* request texture for rectangle that doesn't intersect, small buffer */
+ memset(buff, 0xcf, sizeof(buff));
+ r = bounds;
+ OffsetRect(&r, (bounds.right - bounds.left)*2, 0);
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &r, buff, size-1);
+ ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
+
+ /* vista version allows texture type mismatch, mark it broken for now */
+ memset(buff, 0xcf, sizeof(buff));
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds, buff, sizeof(buff));
+ ok(hr == DWRITE_E_UNSUPPORTEDOPERATION || broken(hr == S_OK), "got 0x%08x\n", hr);
+ ok(buff[0] == 0xcf || broken(buff[0] == 0), "got %1x\n", buff[0]);
+
+ IDWriteGlyphRunAnalysis_Release(analysis);
+ IDWriteFontFace_Release(fontface);
+ IDWriteFactory_Release(factory);
+}
+
START_TEST(font)
{
IDWriteFactory *factory;
@@ -4497,6 +4638,7 @@ START_TEST(font)
test_GetGdiCompatibleGlyphAdvances();
test_GetRecommendedRenderingMode();
test_GetAlphaBlendParams();
+ test_CreateAlphaTexture();
IDWriteFactory_Release(factory);
}
--
2.1.4
More information about the wine-patches
mailing list