wine/dlls/dwrite/layout.c

2756 lines
93 KiB
C
Raw Normal View History

2012-09-28 08:13:17 +00:00
/*
* Text format and layout
*
* Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
2012-09-28 08:13:17 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "dwrite_private.h"
#include "scripts.h"
#include "wine/list.h"
2012-09-28 08:13:17 +00:00
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
struct dwrite_textformat_data {
2012-10-12 13:12:57 +00:00
WCHAR *family_name;
UINT32 family_len;
2012-10-12 13:12:57 +00:00
WCHAR *locale;
UINT32 locale_len;
2012-10-12 13:12:57 +00:00
DWRITE_FONT_WEIGHT weight;
DWRITE_FONT_STYLE style;
DWRITE_FONT_STRETCH stretch;
DWRITE_PARAGRAPH_ALIGNMENT paralign;
DWRITE_READING_DIRECTION readingdir;
DWRITE_WORD_WRAPPING wrapping;
DWRITE_TEXT_ALIGNMENT textalignment;
DWRITE_FLOW_DIRECTION flow;
DWRITE_LINE_SPACING_METHOD spacingmethod;
FLOAT spacing;
FLOAT baseline;
FLOAT fontsize;
DWRITE_TRIMMING trimming;
IDWriteInlineObject *trimmingsign;
IDWriteFontCollection *collection;
};
enum layout_range_attr_kind {
LAYOUT_RANGE_ATTR_WEIGHT,
LAYOUT_RANGE_ATTR_STYLE,
LAYOUT_RANGE_ATTR_STRETCH,
LAYOUT_RANGE_ATTR_FONTSIZE,
LAYOUT_RANGE_ATTR_EFFECT,
LAYOUT_RANGE_ATTR_INLINE,
LAYOUT_RANGE_ATTR_UNDERLINE,
LAYOUT_RANGE_ATTR_STRIKETHROUGH,
LAYOUT_RANGE_ATTR_FONTCOLL,
LAYOUT_RANGE_ATTR_LOCALE,
LAYOUT_RANGE_ATTR_FONTFAMILY
};
struct layout_range_attr_value {
DWRITE_TEXT_RANGE range;
union {
DWRITE_FONT_WEIGHT weight;
DWRITE_FONT_STYLE style;
DWRITE_FONT_STRETCH stretch;
FLOAT fontsize;
IDWriteInlineObject *object;
IUnknown *effect;
BOOL underline;
BOOL strikethrough;
IDWriteFontCollection *collection;
const WCHAR *locale;
const WCHAR *fontfamily;
} u;
};
struct layout_range {
struct list entry;
DWRITE_TEXT_RANGE range;
DWRITE_FONT_WEIGHT weight;
DWRITE_FONT_STYLE style;
FLOAT fontsize;
DWRITE_FONT_STRETCH stretch;
IDWriteInlineObject *object;
IUnknown *effect;
BOOL underline;
BOOL strikethrough;
IDWriteFontCollection *collection;
WCHAR locale[LOCALE_NAME_MAX_LENGTH];
WCHAR *fontfamily;
};
struct layout_run {
struct list entry;
DWRITE_GLYPH_RUN_DESCRIPTION descr;
DWRITE_GLYPH_RUN run;
DWRITE_SCRIPT_ANALYSIS sa;
UINT16 *glyphs;
UINT16 *clustermap;
FLOAT *advances;
DWRITE_GLYPH_OFFSET *offsets;
};
struct dwrite_textlayout {
2014-10-10 09:38:54 +00:00
IDWriteTextLayout2 IDWriteTextLayout2_iface;
IDWriteTextAnalysisSink IDWriteTextAnalysisSink_iface;
IDWriteTextAnalysisSource IDWriteTextAnalysisSource_iface;
LONG ref;
WCHAR *str;
UINT32 len;
struct dwrite_textformat_data format;
FLOAT maxwidth;
FLOAT maxheight;
struct list ranges;
struct list runs;
BOOL recompute;
DWRITE_LINE_BREAKPOINT *nominal_breakpoints;
DWRITE_LINE_BREAKPOINT *actual_breakpoints;
};
struct dwrite_textformat {
2014-10-10 09:57:28 +00:00
IDWriteTextFormat1 IDWriteTextFormat1_iface;
LONG ref;
struct dwrite_textformat_data format;
};
struct dwrite_trimmingsign {
IDWriteInlineObject IDWriteInlineObject_iface;
LONG ref;
};
struct dwrite_typography {
IDWriteTypography IDWriteTypography_iface;
LONG ref;
DWRITE_FONT_FEATURE *features;
UINT32 allocated;
UINT32 count;
};
2014-10-10 09:57:28 +00:00
static const IDWriteTextFormat1Vtbl dwritetextformatvtbl;
static void release_format_data(struct dwrite_textformat_data *data)
{
if (data->collection) IDWriteFontCollection_Release(data->collection);
if (data->trimmingsign) IDWriteInlineObject_Release(data->trimmingsign);
heap_free(data->family_name);
heap_free(data->locale);
}
2014-10-10 09:38:54 +00:00
static inline struct dwrite_textlayout *impl_from_IDWriteTextLayout2(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextLayout2_iface);
2012-09-28 08:13:17 +00:00
}
static inline struct dwrite_textlayout *impl_from_IDWriteTextAnalysisSink(IDWriteTextAnalysisSink *iface)
{
return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextAnalysisSink_iface);
}
static inline struct dwrite_textlayout *impl_from_IDWriteTextAnalysisSource(IDWriteTextAnalysisSource *iface)
{
return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextAnalysisSource_iface);
}
2014-10-10 09:57:28 +00:00
static inline struct dwrite_textformat *impl_from_IDWriteTextFormat1(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
return CONTAINING_RECORD(iface, struct dwrite_textformat, IDWriteTextFormat1_iface);
}
2014-10-10 09:57:28 +00:00
static inline struct dwrite_textformat *unsafe_impl_from_IDWriteTextFormat1(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
return iface->lpVtbl == &dwritetextformatvtbl ? impl_from_IDWriteTextFormat1(iface) : NULL;
}
static inline struct dwrite_trimmingsign *impl_from_IDWriteInlineObject(IDWriteInlineObject *iface)
{
return CONTAINING_RECORD(iface, struct dwrite_trimmingsign, IDWriteInlineObject_iface);
}
static inline struct dwrite_typography *impl_from_IDWriteTypography(IDWriteTypography *iface)
{
return CONTAINING_RECORD(iface, struct dwrite_typography, IDWriteTypography_iface);
}
static struct layout_run *alloc_layout_run(void)
{
struct layout_run *ret;
ret = heap_alloc(sizeof(*ret));
if (!ret) return NULL;
ret->descr.localeName = NULL;
ret->descr.string = NULL;
ret->descr.stringLength = 0;
ret->descr.clusterMap = NULL;
ret->descr.textPosition = 0;
ret->run.fontFace = NULL;
ret->run.fontEmSize = 0.0;
ret->run.glyphCount = 0;
ret->run.glyphIndices = NULL;
ret->run.glyphAdvances = NULL;
ret->run.glyphOffsets = NULL;
ret->run.isSideways = FALSE;
ret->run.bidiLevel = 0;
ret->sa.script = Script_Unknown;
ret->sa.shapes = DWRITE_SCRIPT_SHAPES_DEFAULT;
ret->glyphs = NULL;
ret->clustermap = NULL;
ret->advances = NULL;
ret->offsets = NULL;
return ret;
}
static void free_layout_runs(struct dwrite_textlayout *layout)
{
struct layout_run *cur, *cur2;
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->runs, struct layout_run, entry) {
list_remove(&cur->entry);
if (cur->run.fontFace)
IDWriteFontFace_Release(cur->run.fontFace);
heap_free(cur->glyphs);
heap_free(cur->clustermap);
heap_free(cur->advances);
heap_free(cur->offsets);
heap_free(cur);
}
}
/* should only be called for ranges with inline objects */
static inline DWRITE_BREAK_CONDITION override_break_condition(DWRITE_BREAK_CONDITION existingbreak, DWRITE_BREAK_CONDITION newbreak)
{
switch (existingbreak) {
case DWRITE_BREAK_CONDITION_NEUTRAL:
return newbreak;
case DWRITE_BREAK_CONDITION_CAN_BREAK:
return newbreak == DWRITE_BREAK_CONDITION_NEUTRAL ? existingbreak : newbreak;
/* let's keep stronger conditions as is */
case DWRITE_BREAK_CONDITION_MAY_NOT_BREAK:
case DWRITE_BREAK_CONDITION_MUST_BREAK:
break;
default:
ERR("unknown break condition %d\n", existingbreak);
}
return existingbreak;
}
static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout, const struct layout_range *cur)
{
DWRITE_BREAK_CONDITION before, after;
HRESULT hr;
UINT32 i;
hr = IDWriteInlineObject_GetBreakConditions(cur->object, &before, &after);
if (FAILED(hr))
return hr;
if (!layout->actual_breakpoints) {
layout->actual_breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
if (!layout->actual_breakpoints)
return E_OUTOFMEMORY;
}
memcpy(layout->actual_breakpoints, layout->nominal_breakpoints, sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
for (i = cur->range.startPosition; i < cur->range.length + cur->range.startPosition; i++) {
UINT32 j = i + cur->range.startPosition;
if (i == 0) {
if (j)
layout->actual_breakpoints[j].breakConditionBefore = layout->actual_breakpoints[j-1].breakConditionAfter =
override_break_condition(layout->actual_breakpoints[j-1].breakConditionAfter, before);
else
layout->actual_breakpoints[j].breakConditionBefore = before;
layout->actual_breakpoints[j].breakConditionAfter = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK;
}
layout->actual_breakpoints[j].isWhitespace = 0;
layout->actual_breakpoints[j].isSoftHyphen = 0;
if (i == cur->range.length - 1) {
layout->actual_breakpoints[j].breakConditionBefore = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK;
if (j < layout->len - 1)
layout->actual_breakpoints[j].breakConditionAfter = layout->actual_breakpoints[j+1].breakConditionAfter =
override_break_condition(layout->actual_breakpoints[j+1].breakConditionAfter, before);
else
layout->actual_breakpoints[j].breakConditionAfter = before;
}
}
return S_OK;
}
static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos);
static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
{
IDWriteTextAnalyzer *analyzer;
struct layout_range *range;
struct layout_run *run;
HRESULT hr;
free_layout_runs(layout);
hr = get_textanalyzer(&analyzer);
if (FAILED(hr))
return hr;
LIST_FOR_EACH_ENTRY(range, &layout->ranges, struct layout_range, entry) {
/* inline objects override actual text in a range */
if (range->object) {
hr = layout_update_breakpoints_range(layout, range);
if (FAILED(hr))
return hr;
continue;
}
/* initial splitting by script */
hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &layout->IDWriteTextAnalysisSource_iface,
range->range.startPosition, range->range.length, &layout->IDWriteTextAnalysisSink_iface);
if (FAILED(hr))
break;
/* this splits it further */
hr = IDWriteTextAnalyzer_AnalyzeBidi(analyzer, &layout->IDWriteTextAnalysisSource_iface,
range->range.startPosition, range->range.length, &layout->IDWriteTextAnalysisSink_iface);
if (FAILED(hr))
break;
}
/* fill run info */
LIST_FOR_EACH_ENTRY(run, &layout->runs, struct layout_run, entry) {
DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props = NULL;
DWRITE_SHAPING_TEXT_PROPERTIES *text_props = NULL;
IDWriteFontFamily *family;
UINT32 index, max_count;
IDWriteFont *font;
BOOL exists = TRUE;
range = get_layout_range_by_pos(layout, run->descr.textPosition);
hr = IDWriteFontCollection_FindFamilyName(range->collection, range->fontfamily, &index, &exists);
if (FAILED(hr) || !exists) {
WARN("[%u,%u]: family %s not found in collection %p\n", run->descr.textPosition, run->descr.textPosition+run->descr.stringLength,
debugstr_w(range->fontfamily), range->collection);
continue;
}
hr = IDWriteFontCollection_GetFontFamily(range->collection, index, &family);
if (FAILED(hr))
continue;
hr = IDWriteFontFamily_GetFirstMatchingFont(family, range->weight, range->stretch, range->style, &font);
IDWriteFontFamily_Release(family);
if (FAILED(hr)) {
WARN("[%u,%u]: failed to get a matching font\n", run->descr.textPosition, run->descr.textPosition+run->descr.stringLength);
continue;
}
hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
IDWriteFont_Release(font);
if (FAILED(hr))
continue;
run->run.fontEmSize = range->fontsize;
run->descr.localeName = range->locale;
run->clustermap = heap_alloc(run->descr.stringLength*sizeof(UINT16));
max_count = 3*run->descr.stringLength/2 + 16;
run->glyphs = heap_alloc(max_count*sizeof(UINT16));
if (!run->clustermap || !run->glyphs)
goto memerr;
text_props = heap_alloc(run->descr.stringLength*sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
glyph_props = heap_alloc(max_count*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
if (!text_props || !glyph_props)
goto memerr;
while (1) {
hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, run->descr.string, run->descr.stringLength,
run->run.fontFace, FALSE /* FIXME */, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
NULL /* FIXME */, NULL, NULL, 0, max_count, run->clustermap, text_props, run->glyphs, glyph_props,
&run->run.glyphCount);
if (hr == E_NOT_SUFFICIENT_BUFFER) {
heap_free(run->glyphs);
heap_free(glyph_props);
max_count = run->run.glyphCount;
run->glyphs = heap_alloc(max_count*sizeof(UINT16));
glyph_props = heap_alloc(max_count*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
if (!run->glyphs || !glyph_props)
goto memerr;
continue;
}
break;
}
if (FAILED(hr)) {
heap_free(text_props);
heap_free(glyph_props);
WARN("[%u,%u]: shaping failed 0x%08x\n", run->descr.textPosition, run->descr.textPosition+run->descr.stringLength, hr);
continue;
}
run->run.glyphIndices = run->glyphs;
run->descr.clusterMap = run->clustermap;
run->advances = heap_alloc(run->run.glyphCount*sizeof(FLOAT));
run->offsets = heap_alloc(run->run.glyphCount*sizeof(DWRITE_GLYPH_OFFSET));
if (!run->advances || !run->offsets)
goto memerr;
/* now set advances and offsets */
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap, text_props,
run->descr.stringLength, run->run.glyphIndices, glyph_props, run->run.glyphCount, run->run.fontFace,
run->run.fontEmSize, FALSE /* FIXME */, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
NULL, NULL, 0, run->advances, run->offsets);
heap_free(text_props);
heap_free(glyph_props);
if (FAILED(hr))
WARN("[%u,%u]: failed to get glyph placement info, 0x%08x\n", run->descr.textPosition,
run->descr.textPosition+run->descr.stringLength, hr);
run->run.glyphAdvances = run->advances;
run->run.glyphOffsets = run->offsets;
continue;
memerr:
heap_free(text_props);
heap_free(glyph_props);
heap_free(run->clustermap);
heap_free(run->glyphs);
heap_free(run->advances);
heap_free(run->offsets);
run->advances = NULL;
run->offsets = NULL;
run->clustermap = run->glyphs = NULL;
hr = E_OUTOFMEMORY;
break;
}
IDWriteTextAnalyzer_Release(analyzer);
return hr;
}
static HRESULT layout_compute(struct dwrite_textlayout *layout)
{
HRESULT hr;
if (!layout->recompute)
return S_OK;
/* nominal breakpoints are evaluated only once, because string never changes */
if (!layout->nominal_breakpoints) {
IDWriteTextAnalyzer *analyzer;
HRESULT hr;
layout->nominal_breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
if (!layout->nominal_breakpoints)
return E_OUTOFMEMORY;
hr = get_textanalyzer(&analyzer);
if (FAILED(hr))
return hr;
hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &layout->IDWriteTextAnalysisSource_iface,
0, layout->len, &layout->IDWriteTextAnalysisSink_iface);
IDWriteTextAnalyzer_Release(analyzer);
}
hr = layout_compute_runs(layout);
if (TRACE_ON(dwrite)) {
struct layout_run *cur;
LIST_FOR_EACH_ENTRY(cur, &layout->runs, struct layout_run, entry) {
TRACE("run [%u,%u], len %u, bidilevel %u\n", cur->descr.textPosition, cur->descr.textPosition+cur->descr.stringLength-1,
cur->descr.stringLength, cur->run.bidiLevel);
}
}
layout->recompute = FALSE;
return hr;
}
/* To be used in IDWriteTextLayout methods to validate and fix passed range */
static inline BOOL validate_text_range(struct dwrite_textlayout *layout, DWRITE_TEXT_RANGE *r)
{
if (r->startPosition >= layout->len)
return FALSE;
if (r->startPosition + r->length > layout->len)
r->length = layout->len - r->startPosition;
return TRUE;
}
2014-08-15 03:10:58 +00:00
static BOOL is_same_layout_attrvalue(struct layout_range const *range, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
{
switch (attr) {
case LAYOUT_RANGE_ATTR_WEIGHT:
return range->weight == value->u.weight;
case LAYOUT_RANGE_ATTR_STYLE:
return range->style == value->u.style;
case LAYOUT_RANGE_ATTR_STRETCH:
return range->stretch == value->u.stretch;
case LAYOUT_RANGE_ATTR_FONTSIZE:
return range->fontsize == value->u.fontsize;
case LAYOUT_RANGE_ATTR_INLINE:
return range->object == value->u.object;
case LAYOUT_RANGE_ATTR_EFFECT:
return range->effect == value->u.effect;
case LAYOUT_RANGE_ATTR_UNDERLINE:
return range->underline == value->u.underline;
case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
return range->strikethrough == value->u.strikethrough;
case LAYOUT_RANGE_ATTR_FONTCOLL:
return range->collection == value->u.collection;
case LAYOUT_RANGE_ATTR_LOCALE:
return strcmpW(range->locale, value->u.locale) == 0;
case LAYOUT_RANGE_ATTR_FONTFAMILY:
return strcmpW(range->fontfamily, value->u.fontfamily) == 0;
default:
;
}
return FALSE;
}
2014-08-15 03:10:58 +00:00
static inline BOOL is_same_layout_attributes(struct layout_range const *left, struct layout_range const *right)
{
return left->weight == right->weight &&
left->style == right->style &&
left->stretch == right->stretch &&
left->fontsize == right->fontsize &&
2014-08-15 03:10:58 +00:00
left->object == right->object &&
left->effect == right->effect &&
left->underline == right->underline &&
left->strikethrough == right->strikethrough &&
left->collection == right->collection &&
!strcmpW(left->locale, right->locale) &&
!strcmpW(left->fontfamily, right->fontfamily);
2014-08-15 03:10:58 +00:00
}
static inline BOOL is_same_text_range(const DWRITE_TEXT_RANGE *left, const DWRITE_TEXT_RANGE *right)
{
return left->startPosition == right->startPosition && left->length == right->length;
}
/* Allocates range and inits it with default values from text format. */
static struct layout_range *alloc_layout_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *r)
{
struct layout_range *range;
range = heap_alloc(sizeof(*range));
if (!range) return NULL;
range->range = *r;
range->weight = layout->format.weight;
range->style = layout->format.style;
range->stretch = layout->format.stretch;
range->fontsize = layout->format.fontsize;
range->object = NULL;
range->effect = NULL;
range->underline = FALSE;
range->strikethrough = FALSE;
range->fontfamily = heap_strdupW(layout->format.family_name);
if (!range->fontfamily) {
heap_free(range);
return NULL;
}
range->collection = layout->format.collection;
if (range->collection)
IDWriteFontCollection_AddRef(range->collection);
strcpyW(range->locale, layout->format.locale);
return range;
}
static struct layout_range *alloc_layout_range_from(struct layout_range *from, const DWRITE_TEXT_RANGE *r)
{
struct layout_range *range;
range = heap_alloc(sizeof(*range));
if (!range) return NULL;
*range = *from;
range->range = *r;
/* update refcounts */
if (range->object)
IDWriteInlineObject_AddRef(range->object);
if (range->effect)
IUnknown_AddRef(range->effect);
if (range->collection)
IDWriteFontCollection_AddRef(range->collection);
return range;
}
static void free_layout_range(struct layout_range *range)
{
if (!range)
return;
if (range->object)
IDWriteInlineObject_Release(range->object);
if (range->effect)
IUnknown_Release(range->effect);
if (range->collection)
IDWriteFontCollection_Release(range->collection);
heap_free(range->fontfamily);
heap_free(range);
}
static void free_layout_ranges_list(struct dwrite_textlayout *layout)
{
struct layout_range *cur, *cur2;
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->ranges, struct layout_range, entry) {
list_remove(&cur->entry);
free_layout_range(cur);
}
}
static struct layout_range *find_outer_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *range)
{
struct layout_range *cur;
LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
if (cur->range.startPosition > range->startPosition)
return NULL;
if ((cur->range.startPosition + cur->range.length < range->startPosition + range->length) &&
(range->startPosition < cur->range.startPosition + cur->range.length))
return NULL;
if (cur->range.startPosition + cur->range.length >= range->startPosition + range->length)
return cur;
}
return NULL;
}
static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos)
{
struct layout_range *cur;
LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
DWRITE_TEXT_RANGE *r = &cur->range;
if (r->startPosition <= pos && pos < r->startPosition + r->length)
return cur;
}
return NULL;
}
static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
{
BOOL changed = FALSE;
switch (attr) {
case LAYOUT_RANGE_ATTR_WEIGHT:
changed = dest->weight != value->u.weight;
dest->weight = value->u.weight;
break;
case LAYOUT_RANGE_ATTR_STYLE:
changed = dest->style != value->u.style;
dest->style = value->u.style;
break;
case LAYOUT_RANGE_ATTR_STRETCH:
changed = dest->stretch != value->u.stretch;
dest->stretch = value->u.stretch;
break;
case LAYOUT_RANGE_ATTR_FONTSIZE:
changed = dest->fontsize != value->u.fontsize;
dest->fontsize = value->u.fontsize;
break;
case LAYOUT_RANGE_ATTR_INLINE:
changed = dest->object != value->u.object;
if (changed && dest->object)
IDWriteInlineObject_Release(dest->object);
dest->object = value->u.object;
if (dest->object)
IDWriteInlineObject_AddRef(dest->object);
break;
case LAYOUT_RANGE_ATTR_EFFECT:
changed = dest->effect != value->u.effect;
if (changed && dest->effect)
IUnknown_Release(dest->effect);
dest->effect = value->u.effect;
if (dest->effect)
IUnknown_AddRef(dest->effect);
break;
case LAYOUT_RANGE_ATTR_UNDERLINE:
changed = dest->underline != value->u.underline;
dest->underline = value->u.underline;
break;
case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
changed = dest->strikethrough != value->u.strikethrough;
dest->strikethrough = value->u.strikethrough;
break;
case LAYOUT_RANGE_ATTR_FONTCOLL:
changed = dest->collection != value->u.collection;
if (changed && dest->collection)
IDWriteFontCollection_Release(dest->collection);
dest->collection = value->u.collection;
if (dest->collection)
IDWriteFontCollection_AddRef(dest->collection);
break;
case LAYOUT_RANGE_ATTR_LOCALE:
changed = strcmpW(dest->locale, value->u.locale) != 0;
if (changed)
strcpyW(dest->locale, value->u.locale);
break;
case LAYOUT_RANGE_ATTR_FONTFAMILY:
changed = strcmpW(dest->fontfamily, value->u.fontfamily) != 0;
if (changed) {
heap_free(dest->fontfamily);
dest->fontfamily = heap_strdupW(value->u.fontfamily);
}
break;
default:
;
}
return changed;
}
static inline BOOL is_in_layout_range(const DWRITE_TEXT_RANGE *outer, const DWRITE_TEXT_RANGE *inner)
{
return (inner->startPosition >= outer->startPosition) &&
(inner->startPosition + inner->length <= outer->startPosition + outer->length);
}
static inline HRESULT return_range(const struct layout_range *range, DWRITE_TEXT_RANGE *r)
{
if (r) *r = range->range;
return S_OK;
}
/* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
{
struct layout_range *outer, *right, *left, *cur;
struct list *ranges = &layout->ranges;
2014-08-15 03:10:58 +00:00
BOOL changed = FALSE;
DWRITE_TEXT_RANGE r;
if (!validate_text_range(layout, &value->range))
return S_OK;
/* If new range is completely within existing range, split existing range in two */
if ((outer = find_outer_range(layout, &value->range))) {
/* no need to add same range */
2014-08-15 03:10:58 +00:00
if (is_same_layout_attrvalue(outer, attr, value))
return S_OK;
/* for matching range bounds just replace data */
if (is_same_text_range(&outer->range, &value->range)) {
2014-08-15 03:10:58 +00:00
changed = set_layout_range_attrval(outer, attr, value);
goto done;
}
/* add new range to the left */
if (value->range.startPosition == outer->range.startPosition) {
left = alloc_layout_range_from(outer, &value->range);
if (!left) return E_OUTOFMEMORY;
2014-08-15 03:10:58 +00:00
changed = set_layout_range_attrval(left, attr, value);
list_add_before(&outer->entry, &left->entry);
outer->range.startPosition += value->range.length;
outer->range.length -= value->range.length;
2014-08-15 03:10:58 +00:00
goto done;
}
/* add new range to the right */
if (value->range.startPosition + value->range.length == outer->range.startPosition + outer->range.length) {
right = alloc_layout_range_from(outer, &value->range);
if (!right) return E_OUTOFMEMORY;
2014-08-15 03:10:58 +00:00
changed = set_layout_range_attrval(right, attr, value);
list_add_after(&outer->entry, &right->entry);
outer->range.length -= value->range.length;
2014-08-15 03:10:58 +00:00
goto done;
}
r.startPosition = value->range.startPosition + value->range.length;
r.length = outer->range.length + outer->range.startPosition - r.startPosition;
/* right part */
right = alloc_layout_range_from(outer, &r);
/* new range in the middle */
cur = alloc_layout_range_from(outer, &value->range);
if (!right || !cur) {
free_layout_range(right);
free_layout_range(cur);
return E_OUTOFMEMORY;
}
/* reuse container range as a left part */
outer->range.length = value->range.startPosition - outer->range.startPosition;
/* new part */
set_layout_range_attrval(cur, attr, value);
list_add_after(&outer->entry, &cur->entry);
list_add_after(&cur->entry, &right->entry);
return S_OK;
}
/* Now it's only possible that given range contains some existing ranges, fully or partially.
Update all of them. */
left = get_layout_range_by_pos(layout, value->range.startPosition);
if (left->range.startPosition == value->range.startPosition)
2014-08-15 03:10:58 +00:00
changed = set_layout_range_attrval(left, attr, value);
else /* need to split */ {
r.startPosition = value->range.startPosition;
r.length = left->range.length - value->range.startPosition + left->range.startPosition;
left->range.length -= r.length;
cur = alloc_layout_range_from(left, &r);
2014-08-15 03:10:58 +00:00
changed = set_layout_range_attrval(cur, attr, value);
list_add_after(&left->entry, &cur->entry);
}
cur = LIST_ENTRY(list_next(ranges, &left->entry), struct layout_range, entry);
/* for all existing ranges covered by new one update value */
while (is_in_layout_range(&value->range, &cur->range)) {
2014-08-15 03:10:58 +00:00
changed = set_layout_range_attrval(cur, attr, value);
cur = LIST_ENTRY(list_next(ranges, &cur->entry), struct layout_range, entry);
}
/* it's possible rightmost range intersects */
if (cur && (cur->range.startPosition < value->range.startPosition + value->range.length)) {
r.startPosition = cur->range.startPosition;
r.length = value->range.startPosition + value->range.length - cur->range.startPosition;
left = alloc_layout_range_from(cur, &r);
2014-08-15 03:10:58 +00:00
changed = set_layout_range_attrval(left, attr, value);
cur->range.startPosition += left->range.length;
cur->range.length -= left->range.length;
list_add_before(&cur->entry, &left->entry);
}
2014-08-15 03:10:58 +00:00
done:
if (changed) {
struct list *next, *i;
layout->recompute = TRUE;
2014-08-15 03:10:58 +00:00
i = list_head(ranges);
while ((next = list_next(ranges, i))) {
struct layout_range *next_range = LIST_ENTRY(next, struct layout_range, entry);
cur = LIST_ENTRY(i, struct layout_range, entry);
if (is_same_layout_attributes(cur, next_range)) {
/* remove similar range */
cur->range.length += next_range->range.length;
list_remove(next);
free_layout_range(next_range);
}
else
i = list_next(ranges, i);
}
}
return S_OK;
}
static inline const WCHAR *get_string_attribute_ptr(struct layout_range *range, enum layout_range_attr_kind kind)
{
const WCHAR *str;
switch (kind) {
case LAYOUT_RANGE_ATTR_LOCALE:
str = range->locale;
break;
case LAYOUT_RANGE_ATTR_FONTFAMILY:
str = range->fontfamily;
break;
default:
str = NULL;
}
return str;
}
static HRESULT get_string_attribute_length(struct dwrite_textlayout *layout, enum layout_range_attr_kind kind, UINT32 position,
UINT32 *length, DWRITE_TEXT_RANGE *r)
{
struct layout_range *range;
const WCHAR *str;
range = get_layout_range_by_pos(layout, position);
if (!range) {
*length = 0;
return S_OK;
}
str = get_string_attribute_ptr(range, kind);
*length = strlenW(str);
return return_range(range, r);
}
static HRESULT get_string_attribute_value(struct dwrite_textlayout *layout, enum layout_range_attr_kind kind, UINT32 position,
WCHAR *ret, UINT32 length, DWRITE_TEXT_RANGE *r)
{
struct layout_range *range;
const WCHAR *str;
if (length == 0)
return E_INVALIDARG;
ret[0] = 0;
range = get_layout_range_by_pos(layout, position);
if (!range)
return E_INVALIDARG;
str = get_string_attribute_ptr(range, kind);
if (length < strlenW(str) + 1)
return E_NOT_SUFFICIENT_BUFFER;
strcpyW(ret, str);
return return_range(range, r);
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_QueryInterface(IDWriteTextLayout2 *iface, REFIID riid, void **obj)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2014-10-10 09:38:54 +00:00
if (IsEqualIID(riid, &IID_IDWriteTextLayout2) ||
IsEqualIID(riid, &IID_IDWriteTextLayout1) ||
2014-10-10 09:38:54 +00:00
IsEqualIID(riid, &IID_IDWriteTextLayout) ||
2012-09-28 08:13:17 +00:00
IsEqualIID(riid, &IID_IDWriteTextFormat) ||
2014-10-10 09:38:54 +00:00
IsEqualIID(riid, &IID_IUnknown))
2012-09-28 08:13:17 +00:00
{
*obj = iface;
2014-10-10 09:38:54 +00:00
IDWriteTextLayout2_AddRef(iface);
2012-09-28 08:13:17 +00:00
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
2014-10-10 09:38:54 +00:00
static ULONG WINAPI dwritetextlayout_AddRef(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
return ref;
}
2014-10-10 09:38:54 +00:00
static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
if (!ref) {
free_layout_ranges_list(This);
free_layout_runs(This);
release_format_data(&This->format);
heap_free(This->nominal_breakpoints);
heap_free(This->actual_breakpoints);
heap_free(This->str);
2012-09-28 08:13:17 +00:00
heap_free(This);
}
2012-09-28 08:13:17 +00:00
return ref;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetTextAlignment(IDWriteTextLayout2 *iface, DWRITE_TEXT_ALIGNMENT alignment)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%d): stub\n", This, alignment);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout2 *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%d): stub\n", This, alignment);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetWordWrapping(IDWriteTextLayout2 *iface, DWRITE_WORD_WRAPPING wrapping)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%d): stub\n", This, wrapping);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetReadingDirection(IDWriteTextLayout2 *iface, DWRITE_READING_DIRECTION direction)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%d): stub\n", This, direction);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetFlowDirection(IDWriteTextLayout2 *iface, DWRITE_FLOW_DIRECTION direction)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%d): stub\n", This, direction);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout2 *iface, FLOAT tabstop)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%f): stub\n", This, tabstop);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetTrimming(IDWriteTextLayout2 *iface, DWRITE_TRIMMING const *trimming,
2012-09-28 08:13:17 +00:00
IDWriteInlineObject *trimming_sign)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%p %p): stub\n", This, trimming, trimming_sign);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetLineSpacing(IDWriteTextLayout2 *iface, DWRITE_LINE_SPACING_METHOD spacing,
2012-09-28 08:13:17 +00:00
FLOAT line_spacing, FLOAT baseline)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%d %f %f): stub\n", This, spacing, line_spacing, baseline);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextlayout_GetTextAlignment(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.textalignment;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.paralign;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static DWRITE_WORD_WRAPPING WINAPI dwritetextlayout_GetWordWrapping(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p): stub\n", This);
return This->format.wrapping;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.readingdir;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.flow;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static FLOAT WINAPI dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p): stub\n", This);
return 0.0;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetTrimming(IDWriteTextLayout2 *iface, DWRITE_TRIMMING *options,
2012-09-28 08:13:17 +00:00
IDWriteInlineObject **trimming_sign)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
*options = This->format.trimming;
*trimming_sign = This->format.trimmingsign;
if (*trimming_sign)
IDWriteInlineObject_AddRef(*trimming_sign);
return S_OK;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout2 *iface, DWRITE_LINE_SPACING_METHOD *method,
2012-09-28 08:13:17 +00:00
FLOAT *spacing, FLOAT *baseline)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
*method = This->format.spacingmethod;
*spacing = This->format.spacing;
*baseline = This->format.baseline;
return S_OK;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout2 *iface, IDWriteFontCollection **collection)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%p)\n", This, collection);
*collection = This->format.collection;
if (*collection)
IDWriteFontCollection_AddRef(*collection);
return S_OK;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.family_len;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout2 *iface, WCHAR *name, UINT32 size)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%p %u)\n", This, name, size);
if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
strcpyW(name, This->format.family_name);
return S_OK;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.weight;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.style;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.stretch;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.fontsize;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->format.locale_len;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout2 *iface, WCHAR *name, UINT32 size)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%p %u)\n", This, name, size);
if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
strcpyW(name, This->format.locale);
return S_OK;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout2 *iface, FLOAT maxWidth)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%.1f)\n", This, maxWidth);
if (maxWidth < 0.0)
return E_INVALIDARG;
This->maxwidth = maxWidth;
return S_OK;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout2 *iface, FLOAT maxHeight)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%.1f)\n", This, maxHeight);
if (maxHeight < 0.0)
return E_INVALIDARG;
This->maxheight = maxHeight;
return S_OK;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout2 *iface, IDWriteFontCollection* collection, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%p %s)\n", This, collection, debugstr_range(&range));
value.range = range;
value.u.collection = collection;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTCOLL, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout2 *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_range(&range));
if (!name)
return E_INVALIDARG;
value.range = range;
value.u.fontfamily = name;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTFAMILY, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout2 *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%d %s)\n", This, weight, debugstr_range(&range));
value.range = range;
value.u.weight = weight;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_WEIGHT, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout2 *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%d %s)\n", This, style, debugstr_range(&range));
value.range = range;
value.u.style = style;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STYLE, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout2 *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%d %s)\n", This, stretch, debugstr_range(&range));
value.range = range;
value.u.stretch = stretch;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRETCH, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout2 *iface, FLOAT size, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%.2f %s)\n", This, size, debugstr_range(&range));
value.range = range;
value.u.fontsize = size;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTSIZE, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout2 *iface, BOOL underline, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%d %s)\n", This, underline, debugstr_range(&range));
value.range = range;
value.u.underline = underline;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_UNDERLINE, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout2 *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%d %s)\n", This, strikethrough, debugstr_range(&range));
value.range = range;
value.u.underline = strikethrough;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRIKETHROUGH, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout2 *iface, IUnknown* effect, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%p %s)\n", This, effect, debugstr_range(&range));
value.range = range;
value.u.effect = effect;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_EFFECT, &value);
2012-09-28 08:13:17 +00:00
}
static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout2 *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%p %s)\n", This, object, debugstr_range(&range));
value.range = range;
value.u.object = object;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_INLINE, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout2 *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range));
2012-09-28 08:13:17 +00:00
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout2 *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range_attr_value value;
TRACE("(%p)->(%s %s)\n", This, debugstr_w(locale), debugstr_range(&range));
if (!locale || strlenW(locale) > LOCALE_NAME_MAX_LENGTH-1)
return E_INVALIDARG;
value.range = range;
value.u.locale = locale;
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_LOCALE, &value);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->maxwidth;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout2 *iface)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)\n", This);
return This->maxheight;
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout2 *iface, UINT32 position,
IDWriteFontCollection** collection, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, collection, r);
range = get_layout_range_by_pos(This, position);
*collection = range ? range->collection : NULL;
if (*collection)
IDWriteFontCollection_AddRef(*collection);
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout2 *iface,
UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%d %p %p)\n", This, position, length, r);
return get_string_attribute_length(This, LAYOUT_RANGE_ATTR_FONTFAMILY, position, length, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout2 *iface,
UINT32 position, WCHAR *name, UINT32 length, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%u %p %u %p)\n", This, position, name, length, r);
return get_string_attribute_value(This, LAYOUT_RANGE_ATTR_FONTFAMILY, position, name, length, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout2 *iface,
UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, weight, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
*weight = range->weight;
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout2 *iface,
UINT32 position, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, style, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
*style = range->style;
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout2 *iface,
UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, stretch, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
*stretch = range->stretch;
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout2 *iface,
UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, size, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
*size = range->fontsize;
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout2 *iface,
UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, underline, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
*underline = range->underline;
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout2 *iface,
UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, strikethrough, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
*strikethrough = range->strikethrough;
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout2 *iface,
UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
if (position >= This->len)
return S_OK;
range = get_layout_range_by_pos(This, position);
*effect = range->effect;
if (*effect)
IUnknown_AddRef(*effect);
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout2 *iface,
UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
struct layout_range *range;
TRACE("(%p)->(%u %p %p)\n", This, position, object, r);
range = get_layout_range_by_pos(This, position);
*object = range ? range->object : NULL;
if (*object)
IDWriteInlineObject_AddRef(*object);
return return_range(range, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout2 *iface,
2012-09-28 08:13:17 +00:00
UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout2 *iface,
UINT32 position, UINT32* length, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%u %p %p)\n", This, position, length, r);
return get_string_attribute_length(This, LAYOUT_RANGE_ATTR_LOCALE, position, length, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout2 *iface,
UINT32 position, WCHAR* locale, UINT32 length, DWRITE_TEXT_RANGE *r)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
TRACE("(%p)->(%u %p %u %p)\n", This, position, locale, length, r);
return get_string_attribute_value(This, LAYOUT_RANGE_ATTR_LOCALE, position, locale, length, r);
2012-09-28 08:13:17 +00:00
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout2 *iface,
2012-09-28 08:13:17 +00:00
void *context, IDWriteTextRenderer* renderer, FLOAT originX, FLOAT originY)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%p %p %f %f): stub\n", This, context, renderer, originX, originY);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout2 *iface,
2012-09-28 08:13:17 +00:00
DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *actual_count)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, actual_count);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout2 *iface, DWRITE_TEXT_METRICS *metrics)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%p): stub\n", This, metrics);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout2 *iface, DWRITE_OVERHANG_METRICS *overhangs)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%p): stub\n", This, overhangs);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout2 *iface,
DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32 *count)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
HRESULT hr;
FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, count);
hr = layout_compute(This);
if (FAILED(hr))
return hr;
2012-09-28 08:13:17 +00:00
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout2 *iface, FLOAT* min_width)
2012-09-28 08:13:17 +00:00
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%p): stub\n", This, min_width);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout2 *iface,
2012-09-28 08:13:17 +00:00
FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%f %f %p %p %p): stub\n", This, pointX, pointY, is_trailinghit, is_inside, metrics);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout2 *iface,
2012-09-28 08:13:17 +00:00
UINT32 textPosition, BOOL is_trailinghit, FLOAT* pointX, FLOAT* pointY, DWRITE_HIT_TEST_METRICS *metrics)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%u %d %p %p %p): stub\n", This, textPosition, is_trailinghit, pointX, pointY, metrics);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout2 *iface,
2012-09-28 08:13:17 +00:00
UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
{
2014-10-10 09:38:54 +00:00
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
2012-09-28 08:13:17 +00:00
FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This, textPosition, textLength, originX, originY, metrics,
max_metricscount, actual_metricscount);
return E_NOTIMPL;
}
2014-10-10 09:38:54 +00:00
static HRESULT WINAPI dwritetextlayout1_SetPairKerning(IDWriteTextLayout2 *iface, BOOL is_pairkerning_enabled,
DWRITE_TEXT_RANGE range)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%d %s): stub\n", This, is_pairkerning_enabled, debugstr_range(&range));
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextlayout1_GetPairKerning(IDWriteTextLayout2 *iface, UINT32 position, BOOL *is_pairkerning_enabled,
DWRITE_TEXT_RANGE *range)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%p %p): stub\n", This, is_pairkerning_enabled, range);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout2 *iface, FLOAT leading_spacing, FLOAT trailing_spacing,
FLOAT minimum_advance_width, DWRITE_TEXT_RANGE range)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%f %f %f %s): stub\n", This, leading_spacing, trailing_spacing, minimum_advance_width, debugstr_range(&range));
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout2 *iface, UINT32 position, FLOAT* leading_spacing,
FLOAT* trailing_spacing, FLOAT* minimum_advance_width, DWRITE_TEXT_RANGE *range)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%u %p %p %p %p): stub\n", This, position, leading_spacing, trailing_spacing, minimum_advance_width, range);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextlayout2_GetMetrics(IDWriteTextLayout2 *iface, DWRITE_TEXT_METRICS1 *metrics)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%p): stub\n", This, metrics);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextlayout2_SetVerticalGlyphOrientation(IDWriteTextLayout2 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%d): stub\n", This, orientation);
return E_NOTIMPL;
}
static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI dwritetextlayout2_GetVerticalGlyphOrientation(IDWriteTextLayout2 *iface)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p): stub\n", This);
return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT;
}
static HRESULT WINAPI dwritetextlayout2_SetLastLineWrapping(IDWriteTextLayout2 *iface, BOOL lastline_wrapping_enabled)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%d): stub\n", This, lastline_wrapping_enabled);
return E_NOTIMPL;
}
static BOOL WINAPI dwritetextlayout2_GetLastLineWrapping(IDWriteTextLayout2 *iface)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p): stub\n", This);
return FALSE;
}
static HRESULT WINAPI dwritetextlayout2_SetOpticalAlignment(IDWriteTextLayout2 *iface, DWRITE_OPTICAL_ALIGNMENT alignment)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%d): stub\n", This, alignment);
return E_NOTIMPL;
}
static DWRITE_OPTICAL_ALIGNMENT WINAPI dwritetextlayout2_GetOpticalAlignment(IDWriteTextLayout2 *iface)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p): stub\n", This);
return DWRITE_OPTICAL_ALIGNMENT_NONE;
}
static HRESULT WINAPI dwritetextlayout2_SetFontFallback(IDWriteTextLayout2 *iface, IDWriteFontFallback *fallback)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%p): stub\n", This, fallback);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextlayout2_GetFontFallback(IDWriteTextLayout2 *iface, IDWriteFontFallback **fallback)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
FIXME("(%p)->(%p): stub\n", This, fallback);
return E_NOTIMPL;
}
static const IDWriteTextLayout2Vtbl dwritetextlayoutvtbl = {
2012-09-28 08:13:17 +00:00
dwritetextlayout_QueryInterface,
dwritetextlayout_AddRef,
dwritetextlayout_Release,
dwritetextlayout_SetTextAlignment,
dwritetextlayout_SetParagraphAlignment,
dwritetextlayout_SetWordWrapping,
dwritetextlayout_SetReadingDirection,
dwritetextlayout_SetFlowDirection,
dwritetextlayout_SetIncrementalTabStop,
dwritetextlayout_SetTrimming,
dwritetextlayout_SetLineSpacing,
dwritetextlayout_GetTextAlignment,
dwritetextlayout_GetParagraphAlignment,
dwritetextlayout_GetWordWrapping,
dwritetextlayout_GetReadingDirection,
dwritetextlayout_GetFlowDirection,
dwritetextlayout_GetIncrementalTabStop,
dwritetextlayout_GetTrimming,
dwritetextlayout_GetLineSpacing,
dwritetextlayout_GetFontCollection,
dwritetextlayout_GetFontFamilyNameLength,
dwritetextlayout_GetFontFamilyName,
dwritetextlayout_GetFontWeight,
dwritetextlayout_GetFontStyle,
dwritetextlayout_GetFontStretch,
dwritetextlayout_GetFontSize,
dwritetextlayout_GetLocaleNameLength,
dwritetextlayout_GetLocaleName,
dwritetextlayout_SetMaxWidth,
dwritetextlayout_SetMaxHeight,
dwritetextlayout_SetFontCollection,
dwritetextlayout_SetFontFamilyName,
dwritetextlayout_SetFontWeight,
dwritetextlayout_SetFontStyle,
dwritetextlayout_SetFontStretch,
dwritetextlayout_SetFontSize,
dwritetextlayout_SetUnderline,
dwritetextlayout_SetStrikethrough,
dwritetextlayout_SetDrawingEffect,
dwritetextlayout_SetInlineObject,
dwritetextlayout_SetTypography,
dwritetextlayout_SetLocaleName,
dwritetextlayout_GetMaxWidth,
dwritetextlayout_GetMaxHeight,
dwritetextlayout_layout_GetFontCollection,
dwritetextlayout_layout_GetFontFamilyNameLength,
dwritetextlayout_layout_GetFontFamilyName,
dwritetextlayout_layout_GetFontWeight,
dwritetextlayout_layout_GetFontStyle,
dwritetextlayout_layout_GetFontStretch,
dwritetextlayout_layout_GetFontSize,
dwritetextlayout_GetUnderline,
dwritetextlayout_GetStrikethrough,
dwritetextlayout_GetDrawingEffect,
dwritetextlayout_GetInlineObject,
dwritetextlayout_GetTypography,
dwritetextlayout_layout_GetLocaleNameLength,
dwritetextlayout_layout_GetLocaleName,
dwritetextlayout_Draw,
dwritetextlayout_GetLineMetrics,
dwritetextlayout_GetMetrics,
dwritetextlayout_GetOverhangMetrics,
dwritetextlayout_GetClusterMetrics,
dwritetextlayout_DetermineMinWidth,
dwritetextlayout_HitTestPoint,
dwritetextlayout_HitTestTextPosition,
2014-10-10 09:38:54 +00:00
dwritetextlayout_HitTestTextRange,
dwritetextlayout1_SetPairKerning,
dwritetextlayout1_GetPairKerning,
dwritetextlayout1_SetCharacterSpacing,
dwritetextlayout1_GetCharacterSpacing,
dwritetextlayout2_GetMetrics,
dwritetextlayout2_SetVerticalGlyphOrientation,
dwritetextlayout2_GetVerticalGlyphOrientation,
dwritetextlayout2_SetLastLineWrapping,
dwritetextlayout2_GetLastLineWrapping,
dwritetextlayout2_SetOpticalAlignment,
dwritetextlayout2_GetOpticalAlignment,
dwritetextlayout2_SetFontFallback,
dwritetextlayout2_GetFontFallback
2012-09-28 08:13:17 +00:00
};
static HRESULT WINAPI dwritetextlayout_sink_QueryInterface(IDWriteTextAnalysisSink *iface,
REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSink) || IsEqualIID(riid, &IID_IUnknown)) {
*obj = iface;
IDWriteTextAnalysisSink_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI dwritetextlayout_sink_AddRef(IDWriteTextAnalysisSink *iface)
{
return 2;
}
static ULONG WINAPI dwritetextlayout_sink_Release(IDWriteTextAnalysisSink *iface)
{
return 1;
}
static HRESULT WINAPI dwritetextlayout_sink_SetScriptAnalysis(IDWriteTextAnalysisSink *iface,
UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const* sa)
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink(iface);
struct layout_run *run;
TRACE("%u %u script=%d\n", position, length, sa->script);
run = alloc_layout_run();
if (!run)
return E_OUTOFMEMORY;
run->descr.string = &layout->str[position];
run->descr.stringLength = length;
run->descr.textPosition = position;
run->sa = *sa;
list_add_head(&layout->runs, &run->entry);
return S_OK;
}
static HRESULT WINAPI dwritetextlayout_sink_SetLineBreakpoints(IDWriteTextAnalysisSink *iface,
UINT32 position, UINT32 length, DWRITE_LINE_BREAKPOINT const* breakpoints)
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink(iface);
if (position + length > layout->len)
return E_FAIL;
memcpy(&layout->nominal_breakpoints[position], breakpoints, length*sizeof(DWRITE_LINE_BREAKPOINT));
return S_OK;
}
static HRESULT WINAPI dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink *iface, UINT32 position,
UINT32 length, UINT8 explicitLevel, UINT8 resolvedLevel)
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink(iface);
struct layout_run *cur;
LIST_FOR_EACH_ENTRY(cur, &layout->runs, struct layout_run, entry) {
struct layout_run *run, *run2;
/* FIXME: levels are reported in a natural forward direction, so start loop from a run we ended on */
if (position < cur->descr.textPosition || position > cur->descr.textPosition + cur->descr.stringLength)
continue;
/* full hit - just set run level */
if (cur->descr.textPosition == position && cur->descr.stringLength == length) {
cur->run.bidiLevel = resolvedLevel;
break;
}
/* current run is fully covered, move to next one */
if (cur->descr.textPosition == position && cur->descr.stringLength < length) {
cur->run.bidiLevel = resolvedLevel;
position += cur->descr.stringLength;
length -= cur->descr.stringLength;
continue;
}
/* now starting point is in a run, so it splits it */
run = alloc_layout_run();
if (!run)
return E_OUTOFMEMORY;
*run = *cur;
run->descr.textPosition = position;
run->descr.stringLength = cur->descr.stringLength - position + cur->descr.textPosition;
run->descr.string = &layout->str[position];
run->run.bidiLevel = resolvedLevel;
cur->descr.stringLength -= position - cur->descr.textPosition;
list_add_after(&cur->entry, &run->entry);
if (position + length == run->descr.textPosition + run->descr.stringLength)
break;
/* split second time */
run2 = alloc_layout_run();
if (!run2)
return E_OUTOFMEMORY;
*run2 = *cur;
run2->descr.textPosition = run->descr.textPosition + run->descr.stringLength;
run2->descr.stringLength = cur->descr.textPosition + cur->descr.stringLength - position - length;
run2->descr.string = &layout->str[run2->descr.textPosition];
run->descr.stringLength -= run2->descr.stringLength;
list_add_after(&run->entry, &run2->entry);
break;
}
return S_OK;
}
static HRESULT WINAPI dwritetextlayout_sink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface,
UINT32 position, UINT32 length, IDWriteNumberSubstitution* substitution)
{
return E_NOTIMPL;
}
static const IDWriteTextAnalysisSinkVtbl dwritetextlayoutsinkvtbl = {
dwritetextlayout_sink_QueryInterface,
dwritetextlayout_sink_AddRef,
dwritetextlayout_sink_Release,
dwritetextlayout_sink_SetScriptAnalysis,
dwritetextlayout_sink_SetLineBreakpoints,
dwritetextlayout_sink_SetBidiLevel,
dwritetextlayout_sink_SetNumberSubstitution
};
static HRESULT WINAPI dwritetextlayout_source_QueryInterface(IDWriteTextAnalysisSource *iface,
REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSource) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IDWriteTextAnalysisSource_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI dwritetextlayout_source_AddRef(IDWriteTextAnalysisSource *iface)
{
return 2;
}
static ULONG WINAPI dwritetextlayout_source_Release(IDWriteTextAnalysisSource *iface)
{
return 1;
}
static HRESULT WINAPI dwritetextlayout_source_GetTextAtPosition(IDWriteTextAnalysisSource *iface,
UINT32 position, WCHAR const** text, UINT32* text_len)
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSource(iface);
TRACE("(%p)->(%u %p %p)\n", layout, position, text, text_len);
if (position < layout->len) {
*text = &layout->str[position];
*text_len = layout->len - position;
}
else {
*text = NULL;
*text_len = 0;
}
return S_OK;
}
static HRESULT WINAPI dwritetextlayout_source_GetTextBeforePosition(IDWriteTextAnalysisSource *iface,
UINT32 position, WCHAR const** text, UINT32* text_len)
{
FIXME("%u %p %p: stub\n", position, text, text_len);
return E_NOTIMPL;
}
static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_source_GetParagraphReadingDirection(IDWriteTextAnalysisSource *iface)
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSource(iface);
return IDWriteTextLayout2_GetReadingDirection(&layout->IDWriteTextLayout2_iface);
}
static HRESULT WINAPI dwritetextlayout_source_GetLocaleName(IDWriteTextAnalysisSource *iface,
UINT32 position, UINT32* text_len, WCHAR const** locale)
{
FIXME("%u %p %p: stub\n", position, text_len, locale);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextlayout_source_GetNumberSubstitution(IDWriteTextAnalysisSource *iface,
UINT32 position, UINT32* text_len, IDWriteNumberSubstitution **substitution)
{
FIXME("%u %p %p: stub\n", position, text_len, substitution);
return E_NOTIMPL;
}
static const IDWriteTextAnalysisSourceVtbl dwritetextlayoutsourcevtbl = {
dwritetextlayout_source_QueryInterface,
dwritetextlayout_source_AddRef,
dwritetextlayout_source_Release,
dwritetextlayout_source_GetTextAtPosition,
dwritetextlayout_source_GetTextBeforePosition,
dwritetextlayout_source_GetParagraphReadingDirection,
dwritetextlayout_source_GetLocaleName,
dwritetextlayout_source_GetNumberSubstitution
};
static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
{
UINT32 len;
HRESULT hr;
layout->format.weight = IDWriteTextFormat_GetFontWeight(format);
layout->format.style = IDWriteTextFormat_GetFontStyle(format);
layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
layout->format.fontsize= IDWriteTextFormat_GetFontSize(format);
layout->format.textalignment = IDWriteTextFormat_GetTextAlignment(format);
layout->format.paralign = IDWriteTextFormat_GetParagraphAlignment(format);
layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
hr = IDWriteTextFormat_GetLineSpacing(format, &layout->format.spacingmethod,
&layout->format.spacing, &layout->format.baseline);
if (FAILED(hr))
return hr;
hr = IDWriteTextFormat_GetTrimming(format, &layout->format.trimming, &layout->format.trimmingsign);
if (FAILED(hr))
return hr;
/* locale name and length */
len = IDWriteTextFormat_GetLocaleNameLength(format);
layout->format.locale = heap_alloc((len+1)*sizeof(WCHAR));
if (!layout->format.locale)
return E_OUTOFMEMORY;
hr = IDWriteTextFormat_GetLocaleName(format, layout->format.locale, len+1);
if (FAILED(hr))
return hr;
layout->format.locale_len = len;
/* font family name and length */
len = IDWriteTextFormat_GetFontFamilyNameLength(format);
layout->format.family_name = heap_alloc((len+1)*sizeof(WCHAR));
if (!layout->format.family_name)
return E_OUTOFMEMORY;
hr = IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, len+1);
if (FAILED(hr))
return hr;
layout->format.family_len = len;
return IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
}
HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, IDWriteTextLayout **ret)
2012-09-28 08:13:17 +00:00
{
struct dwrite_textlayout *layout;
struct layout_range *range;
DWRITE_TEXT_RANGE r = { 0, len };
HRESULT hr;
2012-09-28 08:13:17 +00:00
*ret = NULL;
layout = heap_alloc(sizeof(struct dwrite_textlayout));
if (!layout) return E_OUTOFMEMORY;
layout->IDWriteTextLayout2_iface.lpVtbl = &dwritetextlayoutvtbl;
layout->IDWriteTextAnalysisSink_iface.lpVtbl = &dwritetextlayoutsinkvtbl;
layout->IDWriteTextAnalysisSource_iface.lpVtbl = &dwritetextlayoutsourcevtbl;
layout->ref = 1;
layout->len = len;
layout->maxwidth = maxwidth;
layout->maxheight = maxheight;
layout->recompute = TRUE;
layout->nominal_breakpoints = NULL;
layout->actual_breakpoints = NULL;
list_init(&layout->runs);
list_init(&layout->ranges);
memset(&layout->format, 0, sizeof(layout->format));
layout->str = heap_strdupnW(str, len);
if (len && !layout->str) {
hr = E_OUTOFMEMORY;
goto fail;
}
hr = layout_format_from_textformat(layout, format);
if (FAILED(hr))
goto fail;
range = alloc_layout_range(layout, &r);
if (!range) {
hr = E_OUTOFMEMORY;
goto fail;
}
list_add_head(&layout->ranges, &range->entry);
2012-09-28 08:13:17 +00:00
*ret = (IDWriteTextLayout*)&layout->IDWriteTextLayout2_iface;
2012-09-28 08:13:17 +00:00
return S_OK;
fail:
IDWriteTextLayout2_Release(&layout->IDWriteTextLayout2_iface);
return hr;
2012-09-28 08:13:17 +00:00
}
static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *iface, REFIID riid, void **obj)
{
struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteInlineObject)) {
*obj = iface;
IDWriteInlineObject_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI dwritetrimmingsign_AddRef(IDWriteInlineObject *iface)
{
struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
return ref;
}
static ULONG WINAPI dwritetrimmingsign_Release(IDWriteInlineObject *iface)
{
struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
if (!ref)
heap_free(This);
return ref;
}
static HRESULT WINAPI dwritetrimmingsign_Draw(IDWriteInlineObject *iface, void *context, IDWriteTextRenderer *renderer,
FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
{
struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This, context, renderer, originX, originY, is_sideways, is_rtl, drawing_effect);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
{
struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
FIXME("(%p)->(%p): stub\n", This, metrics);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
{
struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
FIXME("(%p)->(%p): stub\n", This, overhangs);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before,
DWRITE_BREAK_CONDITION *after)
{
struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
TRACE("(%p)->(%p %p)\n", This, before, after);
*before = *after = DWRITE_BREAK_CONDITION_NEUTRAL;
return S_OK;
}
static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = {
dwritetrimmingsign_QueryInterface,
dwritetrimmingsign_AddRef,
dwritetrimmingsign_Release,
dwritetrimmingsign_Draw,
dwritetrimmingsign_GetMetrics,
dwritetrimmingsign_GetOverhangMetrics,
dwritetrimmingsign_GetBreakConditions
};
HRESULT create_trimmingsign(IDWriteInlineObject **sign)
{
struct dwrite_trimmingsign *This;
*sign = NULL;
This = heap_alloc(sizeof(struct dwrite_trimmingsign));
if (!This) return E_OUTOFMEMORY;
This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
This->ref = 1;
*sign = &This->IDWriteInlineObject_iface;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat1 *iface, REFIID riid, void **obj)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2014-10-10 09:57:28 +00:00
if (IsEqualIID(riid, &IID_IDWriteTextFormat1) ||
IsEqualIID(riid, &IID_IDWriteTextFormat) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
2014-10-10 09:57:28 +00:00
IDWriteTextFormat1_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
2014-10-10 09:57:28 +00:00
static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
return ref;
}
2014-10-10 09:57:28 +00:00
static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
if (!ref)
2012-10-12 13:12:57 +00:00
{
release_format_data(&This->format);
heap_free(This);
2012-10-12 13:12:57 +00:00
}
return ref;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat1 *iface, DWRITE_TEXT_ALIGNMENT alignment)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2014-04-07 05:18:49 +00:00
TRACE("(%p)->(%d)\n", This, alignment);
This->format.textalignment = alignment;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat1 *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2014-04-07 05:18:49 +00:00
TRACE("(%p)->(%d)\n", This, alignment);
This->format.paralign = alignment;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat1 *iface, DWRITE_WORD_WRAPPING wrapping)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2014-04-07 05:18:49 +00:00
TRACE("(%p)->(%d)\n", This, wrapping);
This->format.wrapping = wrapping;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat1 *iface, DWRITE_READING_DIRECTION direction)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2014-04-07 05:18:49 +00:00
TRACE("(%p)->(%d)\n", This, direction);
This->format.readingdir = direction;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat1 *iface, DWRITE_FLOW_DIRECTION direction)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2014-04-07 05:18:49 +00:00
TRACE("(%p)->(%d)\n", This, direction);
This->format.flow = direction;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat1 *iface, FLOAT tabstop)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p)->(%f): stub\n", This, tabstop);
return E_NOTIMPL;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat1 *iface, DWRITE_TRIMMING const *trimming,
IDWriteInlineObject *trimming_sign)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)->(%p %p)\n", This, trimming, trimming_sign);
This->format.trimming = *trimming;
if (This->format.trimmingsign)
IDWriteInlineObject_Release(This->format.trimmingsign);
This->format.trimmingsign = trimming_sign;
if (This->format.trimmingsign)
IDWriteInlineObject_AddRef(This->format.trimmingsign);
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat1 *iface, DWRITE_LINE_SPACING_METHOD method,
2014-04-07 05:18:49 +00:00
FLOAT spacing, FLOAT baseline)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2014-04-07 05:18:49 +00:00
TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
This->format.spacingmethod = method;
This->format.spacing = spacing;
This->format.baseline = baseline;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.textalignment;
}
2014-10-10 09:57:28 +00:00
static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.paralign;
}
2014-10-10 09:57:28 +00:00
static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.wrapping;
}
2014-10-10 09:57:28 +00:00
static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.readingdir;
}
2014-10-10 09:57:28 +00:00
static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.flow;
}
2014-10-10 09:57:28 +00:00
static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p): stub\n", This);
return 0.0;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat1 *iface, DWRITE_TRIMMING *options,
IDWriteInlineObject **trimming_sign)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
*options = This->format.trimming;
if ((*trimming_sign = This->format.trimmingsign))
IDWriteInlineObject_AddRef(*trimming_sign);
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat1 *iface, DWRITE_LINE_SPACING_METHOD *method,
FLOAT *spacing, FLOAT *baseline)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
*method = This->format.spacingmethod;
*spacing = This->format.spacing;
*baseline = This->format.baseline;
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat1 *iface, IDWriteFontCollection **collection)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)->(%p)\n", This, collection);
*collection = This->format.collection;
IDWriteFontCollection_AddRef(*collection);
return S_OK;
}
2014-10-10 09:57:28 +00:00
static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.family_len;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat1 *iface, WCHAR *name, UINT32 size)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)->(%p %u)\n", This, name, size);
if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
strcpyW(name, This->format.family_name);
return S_OK;
}
2014-10-10 09:57:28 +00:00
static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.weight;
}
2014-10-10 09:57:28 +00:00
static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.style;
}
2014-10-10 09:57:28 +00:00
static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.stretch;
}
2014-10-10 09:57:28 +00:00
static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.fontsize;
}
2014-10-10 09:57:28 +00:00
static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat1 *iface)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)\n", This);
return This->format.locale_len;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat1 *iface, WCHAR *name, UINT32 size)
{
2014-10-10 09:57:28 +00:00
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
TRACE("(%p)->(%p %u)\n", This, name, size);
if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
strcpyW(name, This->format.locale);
return S_OK;
}
2014-10-10 09:57:28 +00:00
static HRESULT WINAPI dwritetextformat1_SetVerticalGlyphOrientation(IDWriteTextFormat1 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p)->(%d): stub\n", This, orientation);
return E_NOTIMPL;
}
static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI dwritetextformat1_GetVerticalGlyphOrientation(IDWriteTextFormat1 *iface)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p): stub\n", This);
return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT;
}
static HRESULT WINAPI dwritetextformat1_SetLastLineWrapping(IDWriteTextFormat1 *iface, BOOL lastline_wrapping_enabled)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p)->(%d): stub\n", This, lastline_wrapping_enabled);
return E_NOTIMPL;
}
static BOOL WINAPI dwritetextformat1_GetLastLineWrapping(IDWriteTextFormat1 *iface)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p): stub\n", This);
return FALSE;
}
static HRESULT WINAPI dwritetextformat1_SetOpticalAlignment(IDWriteTextFormat1 *iface, DWRITE_OPTICAL_ALIGNMENT alignment)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p)->(%d): stub\n", This, alignment);
return E_NOTIMPL;
}
static DWRITE_OPTICAL_ALIGNMENT WINAPI dwritetextformat1_GetOpticalAlignment(IDWriteTextFormat1 *iface)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p): stub\n", This);
return DWRITE_OPTICAL_ALIGNMENT_NONE;
}
static HRESULT WINAPI dwritetextformat1_SetFontFallback(IDWriteTextFormat1 *iface, IDWriteFontFallback *fallback)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p)->(%p): stub\n", This, fallback);
return E_NOTIMPL;
}
static HRESULT WINAPI dwritetextformat1_GetFontFallback(IDWriteTextFormat1 *iface, IDWriteFontFallback **fallback)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
FIXME("(%p)->(%p): stub\n", This, fallback);
return E_NOTIMPL;
}
static const IDWriteTextFormat1Vtbl dwritetextformatvtbl = {
dwritetextformat_QueryInterface,
dwritetextformat_AddRef,
dwritetextformat_Release,
dwritetextformat_SetTextAlignment,
dwritetextformat_SetParagraphAlignment,
dwritetextformat_SetWordWrapping,
dwritetextformat_SetReadingDirection,
dwritetextformat_SetFlowDirection,
dwritetextformat_SetIncrementalTabStop,
dwritetextformat_SetTrimming,
dwritetextformat_SetLineSpacing,
dwritetextformat_GetTextAlignment,
dwritetextformat_GetParagraphAlignment,
dwritetextformat_GetWordWrapping,
dwritetextformat_GetReadingDirection,
dwritetextformat_GetFlowDirection,
dwritetextformat_GetIncrementalTabStop,
dwritetextformat_GetTrimming,
dwritetextformat_GetLineSpacing,
dwritetextformat_GetFontCollection,
dwritetextformat_GetFontFamilyNameLength,
dwritetextformat_GetFontFamilyName,
dwritetextformat_GetFontWeight,
dwritetextformat_GetFontStyle,
dwritetextformat_GetFontStretch,
dwritetextformat_GetFontSize,
dwritetextformat_GetLocaleNameLength,
2014-10-10 09:57:28 +00:00
dwritetextformat_GetLocaleName,
dwritetextformat1_SetVerticalGlyphOrientation,
dwritetextformat1_GetVerticalGlyphOrientation,
dwritetextformat1_SetLastLineWrapping,
dwritetextformat1_GetLastLineWrapping,
dwritetextformat1_SetOpticalAlignment,
dwritetextformat1_GetOpticalAlignment,
dwritetextformat1_SetFontFallback,
dwritetextformat1_GetFontFallback
};
HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
2012-10-12 13:12:57 +00:00
DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
{
struct dwrite_textformat *This;
*format = NULL;
This = heap_alloc(sizeof(struct dwrite_textformat));
if (!This) return E_OUTOFMEMORY;
2014-10-10 09:57:28 +00:00
This->IDWriteTextFormat1_iface.lpVtbl = &dwritetextformatvtbl;
This->ref = 1;
This->format.family_name = heap_strdupW(family_name);
This->format.family_len = strlenW(family_name);
This->format.locale = heap_strdupW(locale);
This->format.locale_len = strlenW(locale);
This->format.weight = weight;
This->format.style = style;
This->format.fontsize = size;
This->format.stretch = stretch;
This->format.textalignment = DWRITE_TEXT_ALIGNMENT_LEADING;
This->format.paralign = DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
This->format.wrapping = DWRITE_WORD_WRAPPING_WRAP;
This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
This->format.spacingmethod = DWRITE_LINE_SPACING_METHOD_DEFAULT;
This->format.spacing = 0.0;
This->format.baseline = 0.0;
This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
This->format.trimming.delimiter = 0;
This->format.trimming.delimiterCount = 0;
This->format.trimmingsign = NULL;
This->format.collection = collection;
IDWriteFontCollection_AddRef(collection);
2014-10-10 09:57:28 +00:00
*format = (IDWriteTextFormat*)&This->IDWriteTextFormat1_iface;
return S_OK;
}
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);
if (IsEqualIID(riid, &IID_IDWriteTypography) || IsEqualIID(riid, &IID_IUnknown)) {
*obj = iface;
IDWriteTypography_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
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;
}
static ULONG WINAPI dwritetypography_Release(IDWriteTypography *iface)
{
struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
ULONG ref = InterlockedDecrement(&typography->ref);
TRACE("(%p)->(%d)\n", typography, ref);
if (!ref) {
heap_free(typography->features);
heap_free(typography);
}
return ref;
}
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;
typography->features = ptr;
typography->allocated *= 2;
}
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);
return typography->count;
}
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);
if (index >= typography->count)
return E_INVALIDARG;
*feature = typography->features[index];
return S_OK;
}
static const IDWriteTypographyVtbl dwritetypographyvtbl = {
dwritetypography_QueryInterface,
dwritetypography_AddRef,
dwritetypography_Release,
dwritetypography_AddFontFeature,
dwritetypography_GetFontFeatureCount,
dwritetypography_GetFontFeature
};
HRESULT create_typography(IDWriteTypography **ret)
{
struct dwrite_typography *typography;
*ret = NULL;
typography = heap_alloc(sizeof(*typography));
if (!typography)
return E_OUTOFMEMORY;
typography->IDWriteTypography_iface.lpVtbl = &dwritetypographyvtbl;
typography->ref = 1;
typography->allocated = 2;
typography->count = 0;
typography->features = heap_alloc(typography->allocated*sizeof(DWRITE_FONT_FEATURE));
if (!typography->features) {
heap_free(typography);
return E_OUTOFMEMORY;
}
*ret = &typography->IDWriteTypography_iface;
return S_OK;
}