Commit aa1bd1e0 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite/layout: Pass user features to shaping calls.

parent d4784a92
......@@ -648,7 +648,33 @@ static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout,
return S_OK;
}
static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos);
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, h.entry)
{
DWRITE_TEXT_RANGE *r = &cur->h.range;
if (r->startPosition <= pos && pos < r->startPosition + r->length)
return cur;
}
return NULL;
}
static struct layout_range_header *get_layout_range_header_by_pos(struct list *ranges, UINT32 pos)
{
struct layout_range_header *cur;
LIST_FOR_EACH_ENTRY(cur, ranges, struct layout_range_header, entry)
{
DWRITE_TEXT_RANGE *r = &cur->range;
if (r->startPosition <= pos && pos < r->startPosition + r->length)
return cur;
}
return NULL;
}
static inline DWRITE_LINE_BREAKPOINT get_effective_breakpoint(const struct dwrite_textlayout *layout, UINT32 pos)
{
......@@ -940,14 +966,123 @@ struct shaping_context
struct regular_layout_run *run;
DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props;
DWRITE_SHAPING_TEXT_PROPERTIES *text_props;
struct
{
DWRITE_TYPOGRAPHIC_FEATURES **features;
unsigned int *range_lengths;
unsigned int range_count;
} user_features;
};
static void layout_shape_clear_user_features_context(struct shaping_context *context)
{
unsigned int i;
for (i = 0; i < context->user_features.range_count; ++i)
{
heap_free(context->user_features.features[i]->features);
heap_free(context->user_features.features[i]);
}
heap_free(context->user_features.features);
memset(&context->user_features, 0, sizeof(context->user_features));
}
static void layout_shape_clear_context(struct shaping_context *context)
{
layout_shape_clear_user_features_context(context);
heap_free(context->glyph_props);
heap_free(context->text_props);
}
static HRESULT layout_shape_add_empty_user_features_range(struct shaping_context *context, unsigned int length)
{
DWRITE_TYPOGRAPHIC_FEATURES *features;
unsigned int r = context->user_features.range_count;
if (!(context->user_features.features[r] = heap_alloc_zero(sizeof(*features))))
return E_OUTOFMEMORY;
context->user_features.range_lengths[r] = length;
context->user_features.range_count++;
return S_OK;
}
static HRESULT layout_shape_get_user_features(struct dwrite_textlayout *layout, struct shaping_context *context)
{
unsigned int i, f, start = 0, r, covered_length = 0, length, feature_count;
struct regular_layout_run *run = context->run;
DWRITE_TYPOGRAPHIC_FEATURES *features;
struct layout_range_iface *range;
IDWriteTypography *typography;
HRESULT hr = E_OUTOFMEMORY;
range = (struct layout_range_iface *)get_layout_range_header_by_pos(&layout->typographies, 0);
if (range->h.range.length >= run->descr.stringLength && !range->iface)
return S_OK;
if (!(context->user_features.features = heap_calloc(run->descr.stringLength, sizeof(*context->user_features.features))))
goto failed;
if (!(context->user_features.range_lengths = heap_calloc(run->descr.stringLength, sizeof(*context->user_features.range_lengths))))
goto failed;
for (i = run->descr.textPosition; i < run->descr.textPosition + run->descr.stringLength; ++i)
{
range = (struct layout_range_iface *)get_layout_range_header_by_pos(&layout->typographies, i);
if (!range || !range->iface) continue;
typography = (IDWriteTypography *)range->iface;
feature_count = IDWriteTypography_GetFontFeatureCount(typography);
if (!feature_count)
{
i = range->h.range.length - i + 1;
continue;
}
if (start != i)
{
if (FAILED(hr = layout_shape_add_empty_user_features_range(context, i - start))) goto failed;
covered_length += i - start;
start += range->h.range.length;
}
r = context->user_features.range_count;
if (!(features = context->user_features.features[r] = heap_alloc(sizeof(*features))))
goto failed;
context->user_features.range_lengths[r] = length = min(run->descr.textPosition + run->descr.stringLength,
range->h.range.startPosition + range->h.range.length) - i;
features->featureCount = feature_count;
if (!(features->features = heap_calloc(feature_count, sizeof(*features->features))))
goto failed;
for (f = 0; f < feature_count; ++f)
{
IDWriteTypography_GetFontFeature(typography, f, &features->features[f]);
}
i += length;
covered_length += length;
context->user_features.range_count++;
}
if (context->user_features.range_count && covered_length < run->descr.stringLength)
{
if (FAILED(hr = layout_shape_add_empty_user_features_range(context, run->descr.stringLength - covered_length)))
goto failed;
}
hr = S_OK;
failed:
if (!context->user_features.range_count || FAILED(hr))
layout_shape_clear_user_features_context(context);
return hr;
}
static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct shaping_context *context)
{
struct regular_layout_run *run = context->run;
......@@ -969,11 +1104,16 @@ static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct
if (!context->text_props || !context->glyph_props)
return E_OUTOFMEMORY;
if (FAILED(hr = layout_shape_get_user_features(layout, context)))
return hr;
for (;;)
{
hr = IDWriteTextAnalyzer_GetGlyphs(context->analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace,
run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL /* FIXME */, NULL,
NULL, 0, max_count, run->clustermap, context->text_props, run->glyphs, context->glyph_props, &run->glyphcount);
run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL /* FIXME */,
(const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features, context->user_features.range_lengths,
context->user_features.range_count, max_count, run->clustermap, context->text_props, run->glyphs,
context->glyph_props, &run->glyphcount);
if (hr == E_NOT_SUFFICIENT_BUFFER)
{
heap_free(run->glyphs);
......@@ -1020,12 +1160,14 @@ static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, stru
context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount,
run->run.fontFace, run->run.fontEmSize, layout->ppdip, &layout->transform,
layout->measuringmode == DWRITE_MEASURING_MODE_GDI_NATURAL, run->run.isSideways, run->run.bidiLevel & 1,
&run->sa, run->descr.localeName, NULL, NULL, 0, run->advances, run->offsets);
&run->sa, run->descr.localeName, (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features,
context->user_features.range_lengths, context->user_features.range_count, run->advances, run->offsets);
else
hr = IDWriteTextAnalyzer_GetGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap,
context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount,
run->run.fontFace, run->run.fontEmSize, run->run.isSideways, run->run.bidiLevel & 1, &run->sa,
run->descr.localeName, NULL, NULL, 0, run->advances, run->offsets);
run->descr.localeName, (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features,
context->user_features.range_lengths, context->user_features.range_count, run->advances, run->offsets);
if (FAILED(hr))
{
......@@ -1204,19 +1346,6 @@ static inline FLOAT get_cluster_range_width(struct dwrite_textlayout *layout, UI
return width;
}
static struct layout_range_header *get_layout_range_header_by_pos(struct list *ranges, UINT32 pos)
{
struct layout_range_header *cur;
LIST_FOR_EACH_ENTRY(cur, ranges, struct layout_range_header, entry) {
DWRITE_TEXT_RANGE *r = &cur->range;
if (r->startPosition <= pos && pos < r->startPosition + r->length)
return cur;
}
return NULL;
}
static inline IUnknown *layout_get_effect_from_pos(struct dwrite_textlayout *layout, UINT32 pos)
{
struct layout_range_header *h = get_layout_range_header_by_pos(&layout->effects, pos);
......@@ -2483,19 +2612,6 @@ static struct layout_range_header *find_outer_range(struct list *ranges, const D
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, h.entry) {
DWRITE_TEXT_RANGE *r = &cur->h.range;
if (r->startPosition <= pos && pos < r->startPosition + r->length)
return cur;
}
return NULL;
}
static inline BOOL set_layout_range_iface_attr(IUnknown **dest, IUnknown *value)
{
if (*dest == value) return FALSE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment