[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