Module: wine Branch: master Commit: 6304a0f50a4852109e0ca78e23f4e9d853d290d6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=6304a0f50a4852109e0ca78e23...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Mon Jun 15 00:39:32 2015 +0300
dwrite: Check format directions in CreateEllipsisTrimmingSign().
---
dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/layout.c | 47 +++++++++++++++++++++++++++++++- dlls/dwrite/main.c | 4 +-- dlls/dwrite/tests/layout.c | 64 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 112 insertions(+), 5 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index cd6d08c..a692e38 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -103,7 +103,7 @@ extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT FLOAT,const WCHAR*,IDWriteTextFormat**) DECLSPEC_HIDDEN; extern HRESULT create_textlayout(const WCHAR*,UINT32,IDWriteTextFormat*,FLOAT,FLOAT,IDWriteTextLayout**) DECLSPEC_HIDDEN; extern HRESULT create_gdicompat_textlayout(const WCHAR*,UINT32,IDWriteTextFormat*,FLOAT,FLOAT,FLOAT,const DWRITE_MATRIX*,BOOL,IDWriteTextLayout**) DECLSPEC_HIDDEN; -extern HRESULT create_trimmingsign(IDWriteInlineObject**) DECLSPEC_HIDDEN; +extern HRESULT create_trimmingsign(IDWriteTextFormat*,IDWriteInlineObject**) DECLSPEC_HIDDEN; extern HRESULT create_typography(IDWriteTypography**) DECLSPEC_HIDDEN; extern HRESULT create_gdiinterop(IDWriteFactory2*,IDWriteGdiInterop**) DECLSPEC_HIDDEN; extern void release_gdiinterop(IDWriteGdiInterop*) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index bdd8ad6..bd50e8b 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -3439,12 +3439,47 @@ static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = { dwritetrimmingsign_GetBreakConditions };
-HRESULT create_trimmingsign(IDWriteInlineObject **sign) +static inline BOOL is_reading_direction_horz(DWRITE_READING_DIRECTION direction) +{ + return (direction == DWRITE_READING_DIRECTION_LEFT_TO_RIGHT) || + (direction == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT); +} + +static inline BOOL is_reading_direction_vert(DWRITE_READING_DIRECTION direction) +{ + return (direction == DWRITE_READING_DIRECTION_TOP_TO_BOTTOM) || + (direction == DWRITE_READING_DIRECTION_BOTTOM_TO_TOP); +} + +static inline BOOL is_flow_direction_horz(DWRITE_FLOW_DIRECTION direction) +{ + return (direction == DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT) || + (direction == DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT); +} + +static inline BOOL is_flow_direction_vert(DWRITE_FLOW_DIRECTION direction) +{ + return (direction == DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM) || + (direction == DWRITE_FLOW_DIRECTION_BOTTOM_TO_TOP); +} + +HRESULT create_trimmingsign(IDWriteTextFormat *format, IDWriteInlineObject **sign) { struct dwrite_trimmingsign *This; + DWRITE_READING_DIRECTION reading; + DWRITE_FLOW_DIRECTION flow;
*sign = NULL;
+ /* Validate reading/flow direction here, layout creation won't complain about + invalid combinations. */ + reading = IDWriteTextFormat_GetReadingDirection(format); + flow = IDWriteTextFormat_GetFlowDirection(format); + + if ((is_reading_direction_horz(reading) && is_flow_direction_horz(flow)) || + (is_reading_direction_vert(reading) && is_flow_direction_vert(flow))) + return DWRITE_E_FLOWDIRECTIONCONFLICTS; + This = heap_alloc(sizeof(struct dwrite_trimmingsign)); if (!This) return E_OUTOFMEMORY;
@@ -3527,7 +3562,12 @@ static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat1 *iface static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat1 *iface, DWRITE_READING_DIRECTION direction) { struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface); + TRACE("(%p)->(%d)\n", This, direction); + + if ((UINT32)direction > DWRITE_READING_DIRECTION_BOTTOM_TO_TOP) + return E_INVALIDARG; + This->format.readingdir = direction; return S_OK; } @@ -3535,7 +3575,12 @@ static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat1 *i static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat1 *iface, DWRITE_FLOW_DIRECTION direction) { struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface); + TRACE("(%p)->(%d)\n", This, direction); + + if ((UINT32)direction > DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT) + return E_INVALIDARG; + This->format.flow = direction; return S_OK; } diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 20f9d36..10597f8 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1051,8 +1051,8 @@ static HRESULT WINAPI dwritefactory_CreateEllipsisTrimmingSign(IDWriteFactory2 * IDWriteInlineObject **trimming_sign) { struct dwritefactory *This = impl_from_IDWriteFactory2(iface); - FIXME("(%p)->(%p %p): semi-stub\n", This, format, trimming_sign); - return create_trimmingsign(trimming_sign); + TRACE("(%p)->(%p %p)\n", This, format, trimming_sign); + return create_trimmingsign(format, trimming_sign); }
static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory2 *iface, IDWriteTextAnalyzer **analyzer) diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index 2b19961..f041979 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -883,8 +883,19 @@ if (0) /* crashes on native */ ok(hr == S_OK, "got 0x%08x\n", hr); ok(before == DWRITE_BREAK_CONDITION_NEUTRAL, "got %d\n", before); ok(after == DWRITE_BREAK_CONDITION_NEUTRAL, "got %d\n", after); - IDWriteInlineObject_Release(sign); + + /* non-orthogonal flow/reading combination */ + hr = IDWriteTextFormat_SetReadingDirection(format, DWRITE_READING_DIRECTION_LEFT_TO_RIGHT); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT); + ok(hr == S_OK || broken(hr == E_INVALIDARG) /* vista, win7 */, "got 0x%08x\n", hr); + if (hr == S_OK) { + hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &sign); + ok(hr == DWRITE_E_FLOWDIRECTIONCONFLICTS, "got 0x%08x\n", hr); + } + IDWriteTextFormat_Release(format); IDWriteFactory_Release(factory); } @@ -2362,6 +2373,56 @@ todo_wine { IDWriteFactory_Release(factory); }
+static void test_SetFlowDirection(void) +{ + static const WCHAR strW[] = {'a','b','c','d',0}; + DWRITE_READING_DIRECTION reading; + DWRITE_FLOW_DIRECTION flow; + IDWriteTextFormat *format; + IDWriteTextLayout *layout; + IDWriteFactory *factory; + HRESULT hr; + + factory = create_factory(); + + hr = IDWriteFactory_CreateTextFormat(factory, tahomaW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, 10.0, enusW, &format); + ok(hr == S_OK, "got 0x%08x\n", hr); + + flow = IDWriteTextFormat_GetFlowDirection(format); + ok(flow == DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM, "got %d\n", flow); + + reading = IDWriteTextFormat_GetReadingDirection(format); + ok(reading == DWRITE_READING_DIRECTION_LEFT_TO_RIGHT, "got %d\n", reading); + + hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 500.0, 1000.0, &layout); + ok(hr == S_OK, "got 0x%08x\n", hr); + IDWriteTextLayout_Release(layout); + + hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT); + ok(hr == S_OK || broken(hr == E_INVALIDARG) /* vista,win7 */, "got 0x%08x\n", hr); + if (hr == S_OK) { + hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 500.0, 1000.0, &layout); + ok(hr == S_OK, "got 0x%08x\n", hr); + IDWriteTextLayout_Release(layout); + + hr = IDWriteTextFormat_SetReadingDirection(format, DWRITE_READING_DIRECTION_TOP_TO_BOTTOM); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 500.0, 1000.0, &layout); + ok(hr == S_OK, "got 0x%08x\n", hr); + IDWriteTextLayout_Release(layout); + } + else + win_skip("DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT is not supported\n"); + + IDWriteTextFormat_Release(format); + IDWriteFactory_Release(factory); +} + START_TEST(layout) { static const WCHAR ctrlstrW[] = {0x202a,0}; @@ -2399,6 +2460,7 @@ START_TEST(layout) test_SetFontStretch(); test_SetStrikethrough(); test_GetMetrics(); + test_SetFlowDirection();
IDWriteFactory_Release(factory); }