Commit 5137aaa9 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Implement parameter validation for CreateAlphaTexture().

parent b50416aa
......@@ -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;
}
......
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment