Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/layout.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index d101a5a197..40621ce170 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -3592,17 +3592,21 @@ static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout3 *iface, return max_count >= This->metrics.lineCount ? S_OK : E_NOT_SUFFICIENT_BUFFER; }
+static HRESULT layout_update_metrics(struct dwrite_textlayout *layout) +{ + return layout_compute_effective_runs(layout); +} + static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout3 *iface, DWRITE_TEXT_METRICS *metrics) { - struct dwrite_textlayout *This = impl_from_IDWriteTextLayout3(iface); - DWRITE_TEXT_METRICS1 metrics1; + struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout3(iface); HRESULT hr;
- TRACE("(%p)->(%p)\n", This, metrics); + TRACE("%p, %p.\n", iface, metrics);
- hr = IDWriteTextLayout3_GetMetrics(iface, &metrics1); + hr = layout_update_metrics(layout); if (hr == S_OK) - memcpy(metrics, &metrics1, sizeof(*metrics)); + memcpy(metrics, &layout->metrics, sizeof(*metrics));
return hr; } @@ -3932,17 +3936,15 @@ static HRESULT WINAPI dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout3 *
static HRESULT WINAPI dwritetextlayout2_GetMetrics(IDWriteTextLayout3 *iface, DWRITE_TEXT_METRICS1 *metrics) { - struct dwrite_textlayout *This = impl_from_IDWriteTextLayout3(iface); + struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout3(iface); HRESULT hr;
- TRACE("(%p)->(%p)\n", This, metrics); + TRACE("%p, %p.\n", iface, metrics);
- hr = layout_compute_effective_runs(This); - if (FAILED(hr)) - return hr; + if (SUCCEEDED(hr = layout_update_metrics(layout))) + *metrics = layout->metrics;
- *metrics = This->metrics; - return S_OK; + return hr; }
static HRESULT WINAPI dwritetextlayout2_SetVerticalGlyphOrientation(IDWriteTextLayout3 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/layout.c | 63 ++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 40621ce170..3e316c27c3 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -304,11 +304,11 @@ struct dwrite_trimmingsign {
struct dwrite_typography { IDWriteTypography IDWriteTypography_iface; - LONG ref; + LONG refcount;
DWRITE_FONT_FEATURE *features; - UINT32 allocated; - UINT32 count; + size_t capacity; + size_t count; };
static const IDWriteTextFormat2Vtbl dwritetextformatvtbl; @@ -5689,9 +5689,7 @@ HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *colle
static HRESULT WINAPI dwritetypography_QueryInterface(IDWriteTypography *iface, REFIID riid, void **obj) { - struct dwrite_typography *typography = impl_from_IDWriteTypography(iface); - - TRACE("(%p)->(%s %p)\n", typography, debugstr_guid(riid), obj); + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteTypography) || IsEqualIID(riid, &IID_IUnknown)) { *obj = iface; @@ -5709,57 +5707,61 @@ static HRESULT WINAPI dwritetypography_QueryInterface(IDWriteTypography *iface, static ULONG WINAPI dwritetypography_AddRef(IDWriteTypography *iface) { struct dwrite_typography *typography = impl_from_IDWriteTypography(iface); - ULONG ref = InterlockedIncrement(&typography->ref); - TRACE("(%p)->(%d)\n", typography, ref); - return ref; + ULONG refcount = InterlockedIncrement(&typography->refcount); + + TRACE("%p, refcount %d.\n", iface, refcount); + + return refcount; }
static ULONG WINAPI dwritetypography_Release(IDWriteTypography *iface) { struct dwrite_typography *typography = impl_from_IDWriteTypography(iface); - ULONG ref = InterlockedDecrement(&typography->ref); + ULONG refcount = InterlockedDecrement(&typography->refcount);
- TRACE("(%p)->(%d)\n", typography, ref); + TRACE("%p, refcount %d.\n", iface, refcount);
- if (!ref) { + if (!refcount) + { heap_free(typography->features); heap_free(typography); }
- return ref; + return refcount; }
static HRESULT WINAPI dwritetypography_AddFontFeature(IDWriteTypography *iface, DWRITE_FONT_FEATURE feature) { struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
- TRACE("(%p)->(%x %u)\n", typography, feature.nameTag, feature.parameter); - - if (typography->count == typography->allocated) { - DWRITE_FONT_FEATURE *ptr = heap_realloc(typography->features, 2*typography->allocated*sizeof(DWRITE_FONT_FEATURE)); - if (!ptr) - return E_OUTOFMEMORY; + TRACE("%p, %s, %u.\n", iface, debugstr_tag(feature.nameTag), feature.parameter);
- typography->features = ptr; - typography->allocated *= 2; + if (!dwrite_array_reserve((void **)&typography->features, &typography->capacity, typography->count + 1, + sizeof(*typography->features))) + { + return E_OUTOFMEMORY; }
typography->features[typography->count++] = feature; + return S_OK; }
static UINT32 WINAPI dwritetypography_GetFontFeatureCount(IDWriteTypography *iface) { struct dwrite_typography *typography = impl_from_IDWriteTypography(iface); - TRACE("(%p)\n", typography); + + TRACE("%p.\n", iface); + return typography->count; }
-static HRESULT WINAPI dwritetypography_GetFontFeature(IDWriteTypography *iface, UINT32 index, DWRITE_FONT_FEATURE *feature) +static HRESULT WINAPI dwritetypography_GetFontFeature(IDWriteTypography *iface, UINT32 index, + DWRITE_FONT_FEATURE *feature) { struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
- TRACE("(%p)->(%u %p)\n", typography, index, feature); + TRACE("%p, %u, %p.\n", iface, index, feature);
if (index >= typography->count) return E_INVALIDARG; @@ -5783,21 +5785,14 @@ HRESULT create_typography(IDWriteTypography **ret)
*ret = NULL;
- typography = heap_alloc(sizeof(*typography)); + typography = heap_alloc_zero(sizeof(*typography)); if (!typography) return E_OUTOFMEMORY;
typography->IDWriteTypography_iface.lpVtbl = &dwritetypographyvtbl; - typography->ref = 1; - typography->allocated = 2; - typography->count = 0; - - typography->features = heap_calloc(typography->allocated, sizeof(*typography->features)); - if (!typography->features) { - heap_free(typography); - return E_OUTOFMEMORY; - } + typography->refcount = 1;
*ret = &typography->IDWriteTypography_iface; + return S_OK; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/font.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 374236657b..732ca371f2 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -1670,7 +1670,7 @@ static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont3 *iface, IDWriteFont { struct dwrite_font *This = impl_from_IDWriteFont3(iface); TRACE("(%p)->(%p)\n", This, fontface); - return IDWriteFont3_CreateFontFace(iface, (IDWriteFontFace3**)fontface); + return get_fontface_from_font(This, (IDWriteFontFace4 **)fontface); }
static void WINAPI dwritefont1_GetMetrics(IDWriteFont3 *iface, DWRITE_FONT_METRICS1 *metrics)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/layout.c | 5 +++-- dlls/dwrite/tests/layout.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 3e316c27c3..2b62758075 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -1831,7 +1831,7 @@ static void layout_add_line(struct dwrite_textlayout *layout, UINT32 first_clust FLOAT descent, trailingspacewidth; BOOL append_trimming_run = FALSE; const struct layout_run *run; - FLOAT width, origin_x; + float width = 0.0f, origin_x; HRESULT hr;
/* Take a look at clusters we got for this line in reverse order to set trailing properties for current line */ @@ -1871,7 +1871,8 @@ static void layout_add_line(struct dwrite_textlayout *layout, UINT32 first_clust }
/* Does not include trailing space width */ - width = get_cluster_range_width(layout, first_cluster, last_cluster + 1); + if (!layout->clustermetrics[last_cluster].isWhitespace) + width = get_cluster_range_width(layout, first_cluster, last_cluster + 1);
/* Append trimming run if necessary */ if (width > layout->metrics.layoutWidth && layout->format.trimmingsign != NULL && diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index 14b287c8c7..8337ce7be7 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -3205,6 +3205,7 @@ static void test_GetMetrics(void) static const WCHAR str2W[] = {0x2066,')',')',0x661,'(',0x627,')',0}; static const WCHAR strW[] = {'a','b','c','d',0}; static const WCHAR str3W[] = {'a',0}; + static const WCHAR str4W[] = {' ',0}; DWRITE_CLUSTER_METRICS clusters[4]; DWRITE_TEXT_METRICS metrics; IDWriteTextFormat *format; @@ -3290,6 +3291,25 @@ todo_wine ok(metrics.lineCount == 1, "got %u\n", metrics.lineCount); IDWriteTextLayout_Release(layout);
+ /* Whitespace only. */ + hr = IDWriteFactory_CreateTextLayout(factory, str4W, 1, format, 500.0, 1000.0, &layout); + ok(hr == S_OK, "Failed to create text layout, hr %#x.\n", hr); + + memset(&metrics, 0xcc, sizeof(metrics)); + hr = IDWriteTextLayout_GetMetrics(layout, &metrics); + ok(hr == S_OK, "Failed to get layout metrics, hr %#x.\n", hr); + ok(metrics.left == 0.0f, "Unexpected value for left %f.\n", metrics.left); + ok(metrics.top == 0.0f, "Unexpected value for top %f.\n", metrics.top); + ok(metrics.width == 0.0f, "Unexpected width %f.\n", metrics.width); + ok(metrics.widthIncludingTrailingWhitespace > 0.0f, "Unexpected full width %f.\n", + metrics.widthIncludingTrailingWhitespace); + ok(metrics.height > 0.0, "Unexpected height %f.\n", metrics.height); + ok(metrics.layoutWidth == 500.0, "Unexpected box width %f.\n", metrics.layoutWidth); + ok(metrics.layoutHeight == 1000.0, "Unexpected box height %f.\n", metrics.layoutHeight); + ok(metrics.maxBidiReorderingDepth == 1, "Unexpected reordering depth %u.\n", metrics.maxBidiReorderingDepth); + ok(metrics.lineCount == 1, "Unexpected line coun %u.\n", metrics.lineCount); + IDWriteTextLayout_Release(layout); + IDWriteTextFormat_Release(format); IDWriteFactory_Release(factory); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/layout.c | 307 +++++++++++++++++++++++++------------------ 1 file changed, 181 insertions(+), 126 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 2b62758075..4e9ce14f61 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -5242,9 +5242,7 @@ HRESULT create_trimmingsign(IDWriteFactory5 *factory, IDWriteTextFormat *format,
static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat2 *iface, REFIID riid, void **obj) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - - TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteTextFormat2) || IsEqualIID(riid, &IID_IDWriteTextFormat1) || @@ -5265,150 +5263,178 @@ static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat2 *iface,
static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->(%d)\n", This, ref); - return ref; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + ULONG refcount = InterlockedIncrement(&format->ref); + + TRACE("%p, refcount %d.\n", iface, refcount); + + return refcount; }
static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - ULONG ref = InterlockedDecrement(&This->ref); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + ULONG refcount = InterlockedDecrement(&format->ref);
- TRACE("(%p)->(%d)\n", This, ref); + TRACE("%p, refcount %d.\n", iface, refcount);
- if (!ref) + if (!refcount) { - release_format_data(&This->format); - heap_free(This); + release_format_data(&format->format); + heap_free(format); }
- return ref; + return refcount; }
static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat2 *iface, DWRITE_TEXT_ALIGNMENT alignment) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%d)\n", This, alignment); - return format_set_textalignment(&This->format, alignment, NULL); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %d.\n", iface, alignment); + + return format_set_textalignment(&format->format, alignment, NULL); }
-static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat2 *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment) +static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat2 *iface, + DWRITE_PARAGRAPH_ALIGNMENT alignment) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%d)\n", This, alignment); - return format_set_paralignment(&This->format, alignment, NULL); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %d.\n", iface, alignment); + + return format_set_paralignment(&format->format, alignment, NULL); }
static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat2 *iface, DWRITE_WORD_WRAPPING wrapping) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%d)\n", This, wrapping); - return format_set_wordwrapping(&This->format, wrapping, NULL); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %d.\n", iface, wrapping); + + return format_set_wordwrapping(&format->format, wrapping, NULL); }
static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat2 *iface, DWRITE_READING_DIRECTION direction) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%d)\n", This, direction); - return format_set_readingdirection(&This->format, direction, NULL); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %d.\n", iface, direction); + + return format_set_readingdirection(&format->format, direction, NULL); }
static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat2 *iface, DWRITE_FLOW_DIRECTION direction) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%d)\n", This, direction); - return format_set_flowdirection(&This->format, direction, NULL); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %d.\n", iface, direction); + + return format_set_flowdirection(&format->format, direction, NULL); }
static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat2 *iface, FLOAT tabstop) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- TRACE("(%p)->(%f)\n", This, tabstop); + TRACE("%p, %f.\n", iface, tabstop);
if (tabstop <= 0.0f) return E_INVALIDARG;
- This->format.tabstop = tabstop; + format->format.tabstop = tabstop; return S_OK; }
static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat2 *iface, DWRITE_TRIMMING const *trimming, IDWriteInlineObject *trimming_sign) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%p %p)\n", This, trimming, trimming_sign); - return format_set_trimming(&This->format, trimming, trimming_sign, NULL); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %p, %p.\n", iface, trimming, trimming_sign); + + return format_set_trimming(&format->format, trimming, trimming_sign, NULL); }
static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat2 *iface, DWRITE_LINE_SPACING_METHOD method, FLOAT height, FLOAT baseline) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); DWRITE_LINE_SPACING spacing;
- TRACE("(%p)->(%d %f %f)\n", This, method, height, baseline); + TRACE("%p, %d, %f, %f.\n", iface, method, height, baseline);
- spacing = This->format.spacing; + spacing = format->format.spacing; spacing.method = method; spacing.height = height; spacing.baseline = baseline;
- return format_set_linespacing(&This->format, &spacing, NULL); + return format_set_linespacing(&format->format, &spacing, NULL); }
static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.textalignment; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.textalignment; }
static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.paralign; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.paralign; }
static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.wrapping; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.wrapping; }
static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.readingdir; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.readingdir; }
static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.flow; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.flow; }
static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.tabstop; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.tabstop; }
static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat2 *iface, DWRITE_TRIMMING *options, IDWriteInlineObject **trimming_sign) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%p %p)\n", This, options, trimming_sign); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- *options = This->format.trimming; - if ((*trimming_sign = This->format.trimmingsign)) + TRACE("%p, %p, %p.\n", iface, options, trimming_sign); + + *options = format->format.trimming; + if ((*trimming_sign = format->format.trimmingsign)) IDWriteInlineObject_AddRef(*trimming_sign);
return S_OK; @@ -5417,22 +5443,23 @@ static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat2 *iface, DW static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat2 *iface, DWRITE_LINE_SPACING_METHOD *method, FLOAT *spacing, FLOAT *baseline) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- *method = This->format.spacing.method; - *spacing = This->format.spacing.height; - *baseline = This->format.spacing.baseline; + TRACE("%p, %p, %p, %p.\n", iface, method, spacing, baseline); + + *method = format->format.spacing.method; + *spacing = format->format.spacing.height; + *baseline = format->format.spacing.baseline; return S_OK; }
static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat2 *iface, IDWriteFontCollection **collection) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- TRACE("(%p)->(%p)\n", This, collection); + TRACE("%p, %p.\n", iface, collection);
- *collection = This->format.collection; + *collection = format->format.collection; IDWriteFontCollection_AddRef(*collection);
return S_OK; @@ -5440,147 +5467,175 @@ static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat2 *ifa
static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.family_len; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.family_len; }
static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat2 *iface, WCHAR *name, UINT32 size) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- TRACE("(%p)->(%p %u)\n", This, name, size); + TRACE("%p, %p, %u.\n", iface, name, size);
- if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER; - strcpyW(name, This->format.family_name); + if (size <= format->format.family_len) + return E_NOT_SUFFICIENT_BUFFER; + strcpyW(name, format->format.family_name); return S_OK; }
static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.weight; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.weight; }
static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.style; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.style; }
static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.stretch; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.stretch; }
static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.fontsize; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.fontsize; }
static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.locale_len; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.locale_len; }
static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat2 *iface, WCHAR *name, UINT32 size) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- TRACE("(%p)->(%p %u)\n", This, name, size); + TRACE("%p, %p %u.\n", iface, name, size);
- if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER; - strcpyW(name, This->format.locale); + if (size <= format->format.locale_len) + return E_NOT_SUFFICIENT_BUFFER; + strcpyW(name, format->format.locale); return S_OK; }
static HRESULT WINAPI dwritetextformat1_SetVerticalGlyphOrientation(IDWriteTextFormat2 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- TRACE("(%p)->(%d)\n", This, orientation); + TRACE("%p, %d.\n", iface, orientation);
if ((UINT32)orientation > DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED) return E_INVALIDARG;
- This->format.vertical_orientation = orientation; + format->format.vertical_orientation = orientation; return S_OK; }
static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI dwritetextformat1_GetVerticalGlyphOrientation(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.vertical_orientation; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.vertical_orientation; }
static HRESULT WINAPI dwritetextformat1_SetLastLineWrapping(IDWriteTextFormat2 *iface, BOOL lastline_wrapping_enabled) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- TRACE("(%p)->(%d)\n", This, lastline_wrapping_enabled); + TRACE("%p, %d.\n", iface, lastline_wrapping_enabled);
- This->format.last_line_wrapping = !!lastline_wrapping_enabled; + format->format.last_line_wrapping = !!lastline_wrapping_enabled; return S_OK; }
static BOOL WINAPI dwritetextformat1_GetLastLineWrapping(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.last_line_wrapping; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.last_line_wrapping; }
static HRESULT WINAPI dwritetextformat1_SetOpticalAlignment(IDWriteTextFormat2 *iface, DWRITE_OPTICAL_ALIGNMENT alignment) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%d)\n", This, alignment); - return format_set_optical_alignment(&This->format, alignment); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %d.\n", iface, alignment); + + return format_set_optical_alignment(&format->format, alignment); }
static DWRITE_OPTICAL_ALIGNMENT WINAPI dwritetextformat1_GetOpticalAlignment(IDWriteTextFormat2 *iface) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)\n", This); - return This->format.optical_alignment; + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p.\n", iface); + + return format->format.optical_alignment; }
static HRESULT WINAPI dwritetextformat1_SetFontFallback(IDWriteTextFormat2 *iface, IDWriteFontFallback *fallback) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%p)\n", This, fallback); - return set_fontfallback_for_format(&This->format, fallback); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %p.\n", iface, fallback); + + return set_fontfallback_for_format(&format->format, fallback); }
static HRESULT WINAPI dwritetextformat1_GetFontFallback(IDWriteTextFormat2 *iface, IDWriteFontFallback **fallback) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%p)\n", This, fallback); - return get_fontfallback_from_format(&This->format, fallback); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %p.\n", iface, fallback); + + return get_fontfallback_from_format(&format->format, fallback); }
static HRESULT WINAPI dwritetextformat2_SetLineSpacing(IDWriteTextFormat2 *iface, DWRITE_LINE_SPACING const *spacing) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); - TRACE("(%p)->(%p)\n", This, spacing); - return format_set_linespacing(&This->format, spacing, NULL); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface); + + TRACE("%p, %p.\n", iface, spacing); + + return format_set_linespacing(&format->format, spacing, NULL); }
static HRESULT WINAPI dwritetextformat2_GetLineSpacing(IDWriteTextFormat2 *iface, DWRITE_LINE_SPACING *spacing) { - struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface); + struct dwrite_textformat *format = impl_from_IDWriteTextFormat2(iface);
- TRACE("(%p)->(%p)\n", This, spacing); + TRACE("%p, %p.\n", iface, spacing);
- *spacing = This->format.spacing; + *spacing = format->format.spacing; return S_OK; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 71 +++++++++++++++++++++++++++++++----- dlls/dwrite/font.c | 51 ++++---------------------- dlls/dwrite/freetype.c | 25 +++++++------ dlls/dwrite/opentype.c | 21 +++++++++++ 4 files changed, 103 insertions(+), 65 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index e2aa2131a1..32ccd63c3e 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -164,12 +164,69 @@ struct fontface_desc struct dwrite_font_data *font_data; /* could be NULL when face is created directly with IDWriteFactory::CreateFontFace() */ };
+struct dwrite_fonttable +{ + const BYTE *data; + void *context; + UINT32 size; + BOOL exists; +}; + struct fontfacecached { struct list entry; IDWriteFontFace4 *fontface; };
+#define GLYPH_BLOCK_SHIFT 8 +#define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT) +#define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1) +#define GLYPH_MAX 65536 + +struct dwrite_fontface +{ + IDWriteFontFace4 IDWriteFontFace4_iface; + LONG ref; + + IDWriteFontFileStream *stream; + IDWriteFontFile **files; + UINT32 file_count; + UINT32 index; + + IDWriteFactory5 *factory; + struct fontfacecached *cached; + + USHORT simulations; + DWRITE_FONT_FACE_TYPE type; + DWRITE_FONT_METRICS1 metrics; + DWRITE_CARET_METRICS caret; + struct + { + unsigned int ascent; + unsigned int descent; + } typo_metrics; + INT charmap; + UINT16 flags; + + struct dwrite_fonttable cmap; + struct dwrite_fonttable vdmx; + struct dwrite_fonttable gasp; + struct dwrite_fonttable cpal; + struct dwrite_fonttable colr; + DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE]; + + DWRITE_FONT_STYLE style; + DWRITE_FONT_STRETCH stretch; + DWRITE_FONT_WEIGHT weight; + DWRITE_PANOSE panose; + FONTSIGNATURE fontsig; + UINT32 glyph_image_formats; + + struct scriptshaping_cache *shaping_cache; + + LOGFONTW lf; +}; + extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN; extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH, FLOAT,const WCHAR*,IDWriteTextFormat**) DECLSPEC_HIDDEN; @@ -241,14 +298,6 @@ struct file_stream_desc { UINT32 face_index; };
-struct dwrite_fonttable -{ - const BYTE *data; - void *context; - UINT32 size; - BOOL exists; -}; - extern const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag, struct dwrite_fonttable *table) DECLSPEC_HIDDEN;
@@ -258,6 +307,8 @@ extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *t DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN; extern void opentype_get_font_properties(struct file_stream_desc*,struct dwrite_font_props*) DECLSPEC_HIDDEN; extern void opentype_get_font_metrics(struct file_stream_desc*,DWRITE_FONT_METRICS1*,DWRITE_CARET_METRICS*) DECLSPEC_HIDDEN; +extern void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, + unsigned int *descent) DECLSPEC_HIDDEN; extern HRESULT opentype_get_font_info_strings(const void*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; extern HRESULT opentype_get_font_familyname(struct file_stream_desc*,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; extern HRESULT opentype_get_font_facename(struct file_stream_desc*,WCHAR*,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; @@ -317,7 +368,9 @@ struct dwrite_glyphbitmap
extern BOOL init_freetype(void) DECLSPEC_HIDDEN; extern void release_freetype(void) DECLSPEC_HIDDEN; -extern HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4*,UINT16,UINT16,DWRITE_GLYPH_METRICS*) DECLSPEC_HIDDEN; + +extern HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, + DWRITE_GLYPH_METRICS *metrics) DECLSPEC_HIDDEN; extern void freetype_notify_cacheremove(IDWriteFontFace4*) DECLSPEC_HIDDEN; extern BOOL freetype_is_monospaced(IDWriteFontFace4*) DECLSPEC_HIDDEN; extern HRESULT freetype_get_glyphrun_outline(IDWriteFontFace4 *fontface, float emsize, UINT16 const *glyphs, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 732ca371f2..5a3afefb27 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -207,44 +207,6 @@ enum fontface_flags { FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3 };
-struct dwrite_fontface { - IDWriteFontFace4 IDWriteFontFace4_iface; - LONG ref; - - IDWriteFontFileStream *stream; - IDWriteFontFile **files; - UINT32 file_count; - UINT32 index; - - IDWriteFactory5 *factory; - struct fontfacecached *cached; - - USHORT simulations; - DWRITE_FONT_FACE_TYPE type; - DWRITE_FONT_METRICS1 metrics; - DWRITE_CARET_METRICS caret; - INT charmap; - UINT16 flags; - - struct dwrite_fonttable cmap; - struct dwrite_fonttable vdmx; - struct dwrite_fonttable gasp; - struct dwrite_fonttable cpal; - struct dwrite_fonttable colr; - DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE]; - - DWRITE_FONT_STYLE style; - DWRITE_FONT_STRETCH stretch; - DWRITE_FONT_WEIGHT weight; - DWRITE_PANOSE panose; - FONTSIGNATURE fontsig; - UINT32 glyph_image_formats; - - struct scriptshaping_cache *shaping_cache; - - LOGFONTW lf; -}; - struct dwrite_fontfile { IDWriteFontFile IDWriteFontFile_iface; LONG ref; @@ -636,11 +598,11 @@ static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace4 *iface) static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace4 *iface, UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *ret, BOOL is_sideways) { - struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface); + struct dwrite_fontface *fontface = impl_from_IDWriteFontFace4(iface); + unsigned int i; HRESULT hr; - UINT32 i;
- TRACE("(%p)->(%p %u %p %d)\n", This, glyphs, glyph_count, ret, is_sideways); + TRACE("%p, %p, %u, %p, %d.\n", iface, glyphs, glyph_count, ret, is_sideways);
if (!glyphs) return E_INVALIDARG; @@ -651,10 +613,10 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace4 *ifa for (i = 0; i < glyph_count; i++) { DWRITE_GLYPH_METRICS metrics;
- hr = get_cached_glyph_metrics(This, glyphs[i], &metrics); + hr = get_cached_glyph_metrics(fontface, glyphs[i], &metrics); if (hr != S_OK) { - freetype_get_design_glyph_metrics(iface, This->metrics.designUnitsPerEm, glyphs[i], &metrics); - hr = set_cached_glyph_metrics(This, glyphs[i], &metrics); + freetype_get_design_glyph_metrics(fontface, glyphs[i], &metrics); + hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics); if (FAILED(hr)) return hr; } @@ -4505,6 +4467,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li stream_desc.face_type = desc->face_type; stream_desc.face_index = desc->index; opentype_get_font_metrics(&stream_desc, &fontface->metrics, &fontface->caret); + opentype_get_font_typo_metrics(&stream_desc, &fontface->typo_metrics.ascent, &fontface->typo_metrics.descent); if (desc->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) { /* TODO: test what happens if caret is already slanted */ if (fontface->caret.slopeRise == 1) { diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index fd94829e68..16317036e3 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -263,14 +263,14 @@ void freetype_notify_cacheremove(IDWriteFontFace4 *fontface) LeaveCriticalSection(&freetype_cs); }
-HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4 *fontface, UINT16 unitsperEm, UINT16 glyph, DWRITE_GLYPH_METRICS *ret) +HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *ret) { FTC_ScalerRec scaler; FT_Size size;
- scaler.face_id = fontface; - scaler.width = unitsperEm; - scaler.height = unitsperEm; + scaler.face_id = &fontface->IDWriteFontFace4_iface; + scaler.width = fontface->metrics.designUnitsPerEm; + scaler.height = fontface->metrics.designUnitsPerEm; scaler.pixel = 1; scaler.x_res = 0; scaler.y_res = 0; @@ -278,22 +278,23 @@ HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4 *fontface, UINT16 uni EnterCriticalSection(&freetype_cs); if (pFTC_Manager_LookupSize(cache_manager, &scaler, &size) == 0) { if (pFT_Load_Glyph(size->face, glyph, FT_LOAD_NO_SCALE) == 0) { - USHORT simulations = IDWriteFontFace4_GetSimulations(fontface); FT_Glyph_Metrics *metrics = &size->face->glyph->metrics;
ret->leftSideBearing = metrics->horiBearingX; ret->advanceWidth = metrics->horiAdvance; ret->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width; - ret->topSideBearing = metrics->vertBearingY; + ret->advanceHeight = metrics->vertAdvance; - ret->bottomSideBearing = metrics->vertAdvance - metrics->vertBearingY - metrics->height; - ret->verticalOriginY = metrics->height + metrics->vertBearingY; + ret->verticalOriginY = fontface->typo_metrics.ascent; + ret->topSideBearing = fontface->typo_metrics.ascent - metrics->horiBearingY; + ret->bottomSideBearing = metrics->vertAdvance - metrics->height - ret->topSideBearing;
/* Adjust in case of bold simulation, glyphs without contours are ignored. */ - if (simulations & DWRITE_FONT_SIMULATIONS_BOLD && size->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && - size->face->glyph->outline.n_contours != 0) { + if (fontface->simulations & DWRITE_FONT_SIMULATIONS_BOLD && + size->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && size->face->glyph->outline.n_contours) + { if (ret->advanceWidth) - ret->advanceWidth += (unitsperEm + 49) / 50; + ret->advanceWidth += (fontface->metrics.designUnitsPerEm + 49) / 50; } } } @@ -929,7 +930,7 @@ void freetype_notify_cacheremove(IDWriteFontFace4 *fontface) { }
-HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4 *fontface, UINT16 unitsperEm, UINT16 glyph, DWRITE_GLYPH_METRICS *ret) +HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *ret) { return E_NOTIMPL; } diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 4772236770..e8efa1d196 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -1553,6 +1553,27 @@ HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *cmap, un return *count > max_count ? E_NOT_SUFFICIENT_BUFFER : S_OK; }
+void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, unsigned int *descent) +{ + const TT_OS2_V2 *data; + unsigned int size; + void *context; + + opentype_get_font_table(stream_desc, MS_OS2_TAG, (const void **)&data, &context, &size, NULL); + + *ascent = *descent = 0; + + if (size >= FIELD_OFFSET(TT_OS2_V2, sTypoLineGap)) + { + SHORT value = GET_BE_WORD(data->sTypoDescender); + *ascent = GET_BE_WORD(data->sTypoAscender); + *descent = value < 0 ? -value : 0; + } + + if (data) + IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, context); +} + void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT_METRICS1 *metrics, DWRITE_CARET_METRICS *caret) { void *os2_context, *head_context, *post_context, *hhea_context;