Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/font.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 74e6b929ecd..392c1dd0ee8 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -3932,9 +3932,6 @@ static HRESULT init_font_data(const struct fontface_desc *desc, struct dwrite_fo data->file = desc->files[0]; data->face_index = desc->index; data->face_type = desc->face_type; - data->simulations = DWRITE_FONT_SIMULATIONS_NONE; - data->bold_sim_tested = 0; - data->oblique_sim_tested = 0; IDWriteFontFile_AddRef(data->file);
stream_desc.stream = desc->stream;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/tests/layout.c | 94 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-)
diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index 52f17820e5e..eb47997f22f 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -190,11 +190,17 @@ static IDWriteTextAnalysisSourceVtbl analysissourcevtbl = {
static IDWriteTextAnalysisSource analysissource = { &analysissourcevtbl };
+static void *create_factory_iid(REFIID riid) +{ + IUnknown *factory = NULL; + DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, riid, &factory); + return factory; +} + static IDWriteFactory *create_factory(void) { - IDWriteFactory *factory; - HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory); - ok(hr == S_OK, "got 0x%08x\n", hr); + IDWriteFactory *factory = create_factory_iid(&IID_IDWriteFactory); + ok(factory != NULL, "Failed to create factory.\n"); return factory; }
@@ -5860,6 +5866,87 @@ static void test_automatic_font_axes(void) IDWriteFactory_Release(factory); }
+static void test_text_format_axes(void) +{ + IDWriteFontCollection *collection; + IDWriteFontCollection2 *collection2; + DWRITE_FONT_AXIS_VALUE axis; + IDWriteTextFormat3 *format3; + DWRITE_FONT_STRETCH stretch; + DWRITE_FONT_WEIGHT weight; + IDWriteTextFormat *format; + IDWriteFactory6 *factory; + DWRITE_FONT_STYLE style; + DWRITE_FONT_FAMILY_MODEL model; + unsigned int count; + HRESULT hr; + + factory = create_factory_iid(&IID_IDWriteFactory6); + + if (!factory) + { + win_skip("Text format does not support variations.\n"); + return; + } + + hr = IDWriteFactory6_CreateTextFormat(factory, L"test_family", NULL, NULL, 0, 10.0f, L"en-us", &format3); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + +if (SUCCEEDED(hr)) +{ + hr = IDWriteTextFormat3_GetFontCollection(format3, &collection); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDWriteFontCollection_QueryInterface(collection, &IID_IDWriteFontCollection2, (void **)&collection2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + model = IDWriteFontCollection2_GetFontFamilyModel(collection2); + ok(model == DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC, "Unexpected model %d.\n", model); + + IDWriteFontCollection_Release(collection); + IDWriteFontCollection2_Release(collection2); + + count = IDWriteTextFormat3_GetFontAxisValueCount(format3); + ok(!count, "Unexpected axis count %u.\n", count); + + stretch = IDWriteTextFormat3_GetFontStretch(format3); + ok(stretch == DWRITE_FONT_STRETCH_NORMAL, "Unexpected font stretch %d.\n", stretch); + + style = IDWriteTextFormat3_GetFontStyle(format3); + ok(style == DWRITE_FONT_STYLE_NORMAL, "Unexpected font style %d.\n", style); + + weight = IDWriteTextFormat3_GetFontWeight(format3); + ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "Unexpected font weight %d.\n", weight); + + /* Regular properties are not set from axis values. */ + axis.axisTag = DWRITE_FONT_AXIS_TAG_WEIGHT; + axis.value = 200.0f; + hr = IDWriteTextFormat3_SetFontAxisValues(format3, &axis, 1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + weight = IDWriteTextFormat3_GetFontWeight(format3); + ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "Unexpected font weight %d.\n", weight); + + IDWriteTextFormat3_Release(format3); +} + hr = IDWriteFactory_CreateTextFormat((IDWriteFactory *)factory, L"test_family", NULL, + DWRITE_FONT_WEIGHT_BOLD, DWRITE_FONT_STYLE_ITALIC, DWRITE_FONT_STRETCH_EXPANDED, + 10.0f, L"en-us", &format); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat3, (void **)&format3); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + count = IDWriteTextFormat3_GetFontAxisValueCount(format3); + ok(!count, "Unexpected axis count %u.\n", count); + + IDWriteTextFormat3_Release(format3); + IDWriteTextFormat_Release(format); + + IDWriteFactory6_Release(factory); +} + START_TEST(layout) { IDWriteFactory *factory; @@ -5912,6 +5999,7 @@ START_TEST(layout) test_GetOverhangMetrics(); test_tab_stops(); test_automatic_font_axes(); + test_text_format_axes();
IDWriteFactory_Release(factory); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 1 + dlls/dwrite/font.c | 146 +++++++++++++++++++++++++++++++++++ dlls/dwrite/main.c | 12 +-- dlls/dwrite/tests/font.c | 17 ++-- 4 files changed, 161 insertions(+), 15 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index f3636876251..9fd9e0bc68f 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -346,6 +346,7 @@ extern void factory_unlock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN; extern HRESULT create_inmemory_fileloader(IDWriteInMemoryFontFileLoader **loader) DECLSPEC_HIDDEN; extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index, IDWriteFontResource **resource) DECLSPEC_HIDDEN; +extern HRESULT create_fontset_builder(IDWriteFactory7 *factory, IDWriteFontSetBuilder2 **ret) DECLSPEC_HIDDEN;
struct dwrite_fontface;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 392c1dd0ee8..014240a1c8f 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -250,6 +250,13 @@ struct dwrite_fontresource IDWriteFactory7 *factory; };
+struct dwrite_fontset_builder +{ + IDWriteFontSetBuilder2 IDWriteFontSetBuilder2_iface; + LONG refcount; + IDWriteFactory7 *factory; +}; + static void dwrite_grab_font_table(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context) { struct dwrite_fontface *fontface = context; @@ -373,6 +380,11 @@ static struct dwrite_fontresource *impl_from_IDWriteFontResource(IDWriteFontReso return CONTAINING_RECORD(iface, struct dwrite_fontresource, IDWriteFontResource_iface); }
+static struct dwrite_fontset_builder *impl_from_IDWriteFontSetBuilder2(IDWriteFontSetBuilder2 *iface) +{ + return CONTAINING_RECORD(iface, struct dwrite_fontset_builder, IDWriteFontSetBuilder2_iface); +} + static HRESULT get_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *metrics) { static const DWRITE_GLYPH_METRICS nil; @@ -7105,3 +7117,137 @@ HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UI
return S_OK; } + +static HRESULT WINAPI dwritefontsetbuilder_QueryInterface(IDWriteFontSetBuilder2 *iface, + REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IDWriteFontSetBuilder2) || + IsEqualIID(riid, &IID_IDWriteFontSetBuilder1) || + IsEqualIID(riid, &IID_IDWriteFontSetBuilder) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IDWriteFontSetBuilder2_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI dwritefontsetbuilder_AddRef(IDWriteFontSetBuilder2 *iface) +{ + struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface); + ULONG refcount = InterlockedIncrement(&builder->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI dwritefontsetbuilder_Release(IDWriteFontSetBuilder2 *iface) +{ + struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface); + ULONG refcount = InterlockedDecrement(&builder->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + IDWriteFactory7_Release(builder->factory); + heap_free(builder); + } + + return refcount; +} + +static HRESULT WINAPI dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2 *iface, + IDWriteFontFaceReference *ref, DWRITE_FONT_PROPERTY const *props, UINT32 prop_count) +{ + FIXME("%p, %p, %p, %u.\n", iface, ref, props, prop_count); + + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2 *iface, + IDWriteFontFaceReference *ref) +{ + FIXME("%p, %p.\n", iface, ref); + + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2 *iface, IDWriteFontSet *fontset) +{ + FIXME("%p, %p.\n", iface, fontset); + + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2 *iface, IDWriteFontSet **fontset) +{ + FIXME("%p, %p.\n", iface, fontset); + + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2 *iface, IDWriteFontFile *file) +{ + FIXME("%p, %p.\n", iface, file); + + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2 *iface, IDWriteFontFile *file, + unsigned int face_index, DWRITE_FONT_SIMULATIONS simulations, const DWRITE_FONT_AXIS_VALUE *axis_values, + unsigned int num_values, const DWRITE_FONT_AXIS_RANGE *axis_ranges, unsigned int num_ranges, + const DWRITE_FONT_PROPERTY *props, unsigned int num_properties) +{ + FIXME("%p, %p, %u, %#x, %p, %u, %p, %u, %p, %u.\n", iface, file, face_index, simulations, axis_values, num_values, + axis_ranges, num_ranges, props, num_properties); + + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2 *iface, const WCHAR *filepath) +{ + FIXME("%p, %s.\n", iface, debugstr_w(filepath)); + + return E_NOTIMPL; +} + +static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl = +{ + dwritefontsetbuilder_QueryInterface, + dwritefontsetbuilder_AddRef, + dwritefontsetbuilder_Release, + dwritefontsetbuilder_AddFontFaceReference_, + dwritefontsetbuilder_AddFontFaceReference, + dwritefontsetbuilder_AddFontSet, + dwritefontsetbuilder_CreateFontSet, + dwritefontsetbuilder1_AddFontFile, + dwritefontsetbuilder2_AddFont, + dwritefontsetbuilder2_AddFontFile, +}; + +HRESULT create_fontset_builder(IDWriteFactory7 *factory, IDWriteFontSetBuilder2 **ret) +{ + struct dwrite_fontset_builder *builder; + + *ret = NULL; + + if (!(builder = heap_alloc_zero(sizeof(*builder)))) + return E_OUTOFMEMORY; + + builder->IDWriteFontSetBuilder2_iface.lpVtbl = &fontsetbuildervtbl; + builder->refcount = 1; + builder->factory = factory; + IDWriteFactory7_AddRef(builder->factory); + + *ret = &builder->IDWriteFontSetBuilder2_iface; + + return S_OK; +} diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index dd9bd4dc6a3..0cc0edd1ffc 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1501,9 +1501,9 @@ static HRESULT WINAPI dwritefactory3_GetSystemFontSet(IDWriteFactory7 *iface, ID
static HRESULT WINAPI dwritefactory3_CreateFontSetBuilder(IDWriteFactory7 *iface, IDWriteFontSetBuilder **builder) { - FIXME("%p, %p: stub\n", iface, builder); + TRACE("%p, %p.\n", iface, builder);
- return E_NOTIMPL; + return create_fontset_builder(iface, (IDWriteFontSetBuilder2 **)builder); }
static HRESULT WINAPI dwritefactory3_CreateFontCollectionFromFontSet(IDWriteFactory7 *iface, IDWriteFontSet *fontset, @@ -1644,9 +1644,9 @@ static HRESULT WINAPI dwritefactory4_ComputeGlyphOrigins(IDWriteFactory7 *iface,
static HRESULT WINAPI dwritefactory5_CreateFontSetBuilder(IDWriteFactory7 *iface, IDWriteFontSetBuilder1 **builder) { - FIXME("%p, %p: stub\n", iface, builder); + TRACE("%p, %p.\n", iface, builder);
- return E_NOTIMPL; + return create_fontset_builder(iface, (IDWriteFontSetBuilder2 **)builder); }
static HRESULT WINAPI dwritefactory5_CreateInMemoryFontFileLoader(IDWriteFactory7 *iface, @@ -1725,9 +1725,9 @@ static HRESULT WINAPI dwritefactory6_CreateFontCollectionFromFontSet(IDWriteFact
static HRESULT WINAPI dwritefactory6_CreateFontSetBuilder(IDWriteFactory7 *iface, IDWriteFontSetBuilder2 **builder) { - FIXME("%p, %p.\n", iface, builder); + TRACE("%p, %p.\n", iface, builder);
- return E_NOTIMPL; + return create_fontset_builder(iface, builder); }
static HRESULT WINAPI dwritefactory6_CreateTextFormat(IDWriteFactory7 *iface, const WCHAR *familyname, diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 193f8ed9c48..872405b1639 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -9371,21 +9371,15 @@ static void test_fontsetbuilder(void) HRESULT hr;
factory = create_factory_iid(&IID_IDWriteFactory3); - if (!factory) { - skip("IDWriteFontSetBuilder is not supported.\n"); + if (!factory) + { + win_skip("IDWriteFontSetBuilder is not supported.\n"); return; }
EXPECT_REF(factory, 1); hr = IDWriteFactory3_CreateFontSetBuilder(factory, &builder); -todo_wine ok(hr == S_OK, "Failed to create font set builder, hr %#x.\n", hr); - - if (FAILED(hr)) { - IDWriteFactory3_Release(factory); - return; - } - EXPECT_REF(factory, 2); IDWriteFontSetBuilder_Release(builder);
@@ -9419,12 +9413,16 @@ todo_wine
EXPECT_REF(ref, 1); hr = IDWriteFontSetBuilder_AddFontFaceReference(builder, ref); + todo_wine ok(hr == S_OK, "Failed to add fontface reference, hr %#x.\n", hr); EXPECT_REF(ref, 1);
hr = IDWriteFontSetBuilder_CreateFontSet(builder, &fontset); + todo_wine ok(hr == S_OK, "Failed to create a font set, hr %#x.\n", hr);
+ if (SUCCEEDED(hr)) + { setcount = IDWriteFontSet_GetFontCount(fontset); ok(setcount == 1, "Unexpected font count %u.\n", setcount);
@@ -9490,6 +9488,7 @@ todo_wine }
IDWriteFontSet_Release(fontset); + } IDWriteFontFaceReference_Release(ref); IDWriteFontSetBuilder_Release(builder);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/analyzer.c | 19 ++++++++----------- dlls/dwrite/dwrite_private.h | 1 + 2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index 7ee8e18eff7..7446665674a 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -1154,7 +1154,6 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, struct scriptshaping_context context = { 0 }; struct dwrite_fontface *font_obj; WCHAR digits[NATIVE_DIGITS_LEN]; - unsigned int script; HRESULT hr;
TRACE("(%s:%u %p %d %d %s %s %p %p %p %u %u %p %p %p %p %p)\n", debugstr_wn(text, length), @@ -1172,6 +1171,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, font_obj = unsafe_impl_from_IDWriteFontFace(fontface);
context.cache = fontface_get_shaping_cache(font_obj); + context.script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; context.text = text; context.length = length; context.is_rtl = is_rtl; @@ -1190,8 +1190,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * max_glyph_count); context.table = &context.cache->gsub;
- script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; - scriptprops = &dwritescripts_properties[script]; + scriptprops = &dwritescripts_properties[context.script]; hr = shape_get_glyphs(&context, scriptprops->scripttags); if (SUCCEEDED(hr)) { @@ -1217,7 +1216,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2 const struct dwritescript_properties *scriptprops; struct scriptshaping_context context; struct dwrite_fontface *font_obj; - unsigned int i, script; + unsigned int i; HRESULT hr;
TRACE("%s, %p, %p, %u, %p, %p, %u, %p, %.2f, %d, %d, %s, %s, %p, %p, %u, %p, %p.\n", debugstr_wn(text, text_len), @@ -1243,10 +1242,8 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2 offsets[i].ascenderOffset = 0.0f; }
- script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; - scriptprops = &dwritescripts_properties[script]; - context.cache = fontface_get_shaping_cache(font_obj); + context.script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; context.text = text; context.length = text_len; context.is_rtl = is_rtl; @@ -1267,6 +1264,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2 context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count); context.table = &context.cache->gpos;
+ scriptprops = &dwritescripts_properties[context.script]; hr = shape_get_positions(&context, scriptprops->scripttags);
heap_free(context.glyph_infos); @@ -1286,7 +1284,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite struct scriptshaping_context context; DWRITE_MEASURING_MODE measuring_mode; struct dwrite_fontface *font_obj; - unsigned int i, script; + unsigned int i; HRESULT hr;
TRACE("%s, %p, %p, %u, %p, %p, %u, %p, %.2f, %.2f, %p, %d, %d, %d, %s, %s, %p, %p, %u, %p, %p.\n", @@ -1314,10 +1312,8 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite offsets[i].ascenderOffset = 0.0f; }
- script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; - scriptprops = &dwritescripts_properties[script]; - context.cache = fontface_get_shaping_cache(font_obj); + context.script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; context.text = text; context.length = text_len; context.is_rtl = is_rtl; @@ -1338,6 +1334,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count); context.table = &context.cache->gpos;
+ scriptprops = &dwritescripts_properties[context.script]; hr = shape_get_positions(&context, scriptprops->scripttags);
heap_free(context.glyph_infos); diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 9fd9e0bc68f..485fcdb1f16 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -539,6 +539,7 @@ typedef void (*p_apply_context_lookup)(struct scriptshaping_context *context, un struct scriptshaping_context { struct scriptshaping_cache *cache; + unsigned int script; UINT32 language_tag;
const WCHAR *text;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/Makefile.in | 3 +- dlls/dwrite/dwrite_private.h | 71 +++++++++++++++++++++--------------- dlls/dwrite/opentype.c | 3 +- dlls/dwrite/shape.c | 42 +++++++++++++++++++-- dlls/dwrite/shapers/arabic.c | 66 +++++++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 35 deletions(-) create mode 100644 dlls/dwrite/shapers/arabic.c
diff --git a/dlls/dwrite/Makefile.in b/dlls/dwrite/Makefile.in index c91ad0bd167..feac36f3cb2 100644 --- a/dlls/dwrite/Makefile.in +++ b/dlls/dwrite/Makefile.in @@ -17,4 +17,5 @@ C_SRCS = \ mirror.c \ opentype.c \ scripts.c \ - shape.c + shape.c \ + shapers/arabic.c diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 485fcdb1f16..76d49ae5104 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -536,9 +536,51 @@ struct scriptshaping_context;
typedef void (*p_apply_context_lookup)(struct scriptshaping_context *context, unsigned int lookup_index);
+enum shaping_feature_flags +{ + FEATURE_GLOBAL = 0x1, + FEATURE_GLOBAL_SEARCH = 0x2, + FEATURE_MANUAL_ZWNJ = 0x4, + FEATURE_MANUAL_ZWJ = 0x8, + FEATURE_MANUAL_JOINERS = FEATURE_MANUAL_ZWNJ | FEATURE_MANUAL_ZWJ, +}; + +struct shaping_feature +{ + unsigned int tag; + unsigned int index; + unsigned int flags; + unsigned int max_value; + unsigned int default_value; + unsigned int mask; + unsigned int shift; + unsigned int stage; +}; + +struct shaping_features +{ + struct shaping_feature *features; + size_t count; + size_t capacity; + unsigned int stage; +}; + +struct shaper +{ + void (*collect_features)(struct scriptshaping_context *context, struct shaping_features *features); + void (*setup_masks)(struct scriptshaping_context *context, const struct shaping_features *features); +}; + +extern const struct shaper arabic_shaper DECLSPEC_HIDDEN; + +extern void shape_enable_feature(struct shaping_features *features, unsigned int tag, + unsigned int flags) DECLSPEC_HIDDEN; +extern void shape_start_next_stage(struct shaping_features *features) DECLSPEC_HIDDEN; + struct scriptshaping_context { struct scriptshaping_cache *cache; + const struct shaper *shaper; unsigned int script; UINT32 language_tag;
@@ -615,35 +657,6 @@ extern struct scriptshaping_cache *create_scriptshaping_cache(void *context, extern void release_scriptshaping_cache(struct scriptshaping_cache*) DECLSPEC_HIDDEN; extern struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface) DECLSPEC_HIDDEN;
-enum shaping_feature_flags -{ - FEATURE_GLOBAL = 0x1, - FEATURE_GLOBAL_SEARCH = 0x2, - FEATURE_MANUAL_ZWNJ = 0x4, - FEATURE_MANUAL_ZWJ = 0x8, - FEATURE_MANUAL_JOINERS = FEATURE_MANUAL_ZWNJ | FEATURE_MANUAL_ZWJ, -}; - -struct shaping_feature -{ - unsigned int tag; - unsigned int index; - unsigned int flags; - unsigned int max_value; - unsigned int default_value; - unsigned int mask; - unsigned int shift; - unsigned int stage; -}; - -struct shaping_features -{ - struct shaping_feature *features; - size_t count; - size_t capacity; - unsigned int stage; -}; - extern void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache) DECLSPEC_HIDDEN; extern DWORD opentype_layout_find_script(const struct scriptshaping_cache *cache, DWORD kind, DWORD tag, unsigned int *script_index) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index a025227dfda..20534460d09 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -4647,7 +4647,8 @@ static void opentype_layout_set_glyph_masks(struct scriptshaping_context *contex for (g = 0; g < context->glyph_count; ++g) context->glyph_infos[g].mask = context->global_mask;
- /* FIXME: set shaper masks */ + if (context->shaper->setup_masks) + context->shaper->setup_masks(context, features);
for (r = 0, start_char = 0; r < context->user_features.range_count; ++r) { diff --git a/dlls/dwrite/shape.c b/dlls/dwrite/shape.c index 567ec5fa54f..53b392c88e2 100644 --- a/dlls/dwrite/shape.c +++ b/dlls/dwrite/shape.c @@ -27,6 +27,7 @@ #define COBJMACROS
#include "dwrite_private.h" +#include "scripts.h" #include "winternl.h"
#include "wine/debug.h" @@ -135,6 +136,17 @@ static void shape_add_feature(struct shaping_features *features, unsigned int ta shape_add_feature_full(features, tag, FEATURE_GLOBAL, 1); }
+void shape_enable_feature(struct shaping_features *features, unsigned int tag, + unsigned int flags) +{ + shape_add_feature_full(features, tag, FEATURE_GLOBAL | flags, 1); +} + +void shape_start_next_stage(struct shaping_features *features) +{ + features->stage++; +} + static int features_sorting_compare(const void *a, const void *b) { const struct shaping_feature *left = a, *right = b; @@ -187,6 +199,21 @@ static void shape_merge_features(struct scriptshaping_context *context, struct s features->count = j + 1; }
+static const struct shaper null_shaper; + +static void shape_set_shaper(struct scriptshaping_context *context) +{ + switch (context->script) + { + case Script_Arabic: + case Script_Syriac: + context->shaper = &arabic_shaper; + break; + default: + context->shaper = &null_shaper; + } +} + HRESULT shape_get_positions(struct scriptshaping_context *context, const unsigned int *scripts) { static const struct shaping_feature common_features[] = @@ -206,6 +233,8 @@ HRESULT shape_get_positions(struct scriptshaping_context *context, const unsigne unsigned int script_index, language_index, script, i; struct shaping_features features = { 0 };
+ shape_set_shaper(context); + for (i = 0; i < ARRAY_SIZE(common_features); ++i) shape_add_feature_full(&features, common_features[i].tag, FEATURE_GLOBAL | common_features[i].flags, 1);
@@ -279,20 +308,25 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i struct shaping_features features = { 0 }; unsigned int i;
+ shape_set_shaper(context); + if (!context->is_sideways) { if (context->is_rtl) { - shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','a')); + shape_enable_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','a'), 0); shape_add_feature_full(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), 0, 1); } else { - shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','a')); - shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','m')); + shape_enable_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','a'), 0); + shape_enable_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','m'), 0); } }
+ if (context->shaper->collect_features) + context->shaper->collect_features(context, &features); + for (i = 0; i < ARRAY_SIZE(common_features); ++i) shape_add_feature(&features, common_features[i]);
@@ -303,7 +337,7 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i shape_add_feature(&features, horizontal_features[i]); } else - shape_add_feature_full(&features, DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t'), FEATURE_GLOBAL | FEATURE_GLOBAL_SEARCH, 1); + shape_enable_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t'), FEATURE_GLOBAL_SEARCH);
shape_merge_features(context, &features);
diff --git a/dlls/dwrite/shapers/arabic.c b/dlls/dwrite/shapers/arabic.c new file mode 100644 index 00000000000..d8c6c9495c0 --- /dev/null +++ b/dlls/dwrite/shapers/arabic.c @@ -0,0 +1,66 @@ +/* + * Copyright HarfBuzz Project authors + * Copyright 2020 Nikolay Sivov for CodeWeavers + * + * 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 + */ + +#include "dwrite_private.h" + +static const unsigned int arabic_features[] = +{ + DWRITE_MAKE_OPENTYPE_TAG('i','s','o','l'), + DWRITE_MAKE_OPENTYPE_TAG('f','i','n','a'), + DWRITE_MAKE_OPENTYPE_TAG('f','i','n','2'), + DWRITE_MAKE_OPENTYPE_TAG('f','i','n','3'), + DWRITE_MAKE_OPENTYPE_TAG('m','e','d','i'), + DWRITE_MAKE_OPENTYPE_TAG('m','e','d','2'), + DWRITE_MAKE_OPENTYPE_TAG('i','n','i','t'), +}; + +static void arabic_collect_features(struct scriptshaping_context *context, + struct shaping_features *features) +{ + unsigned int i; + + shape_enable_feature(features, DWRITE_MAKE_OPENTYPE_TAG('c','c','m','p'), 0); + shape_enable_feature(features, DWRITE_MAKE_OPENTYPE_TAG('l','o','c','l'), 0); + shape_start_next_stage(features); + + for (i = 0; i < ARRAY_SIZE(arabic_features); ++i) + { + shape_enable_feature(features, arabic_features[i], 0); + shape_start_next_stage(features); + } + + shape_enable_feature(features, DWRITE_MAKE_OPENTYPE_TAG('r','l','i','g'), FEATURE_MANUAL_ZWJ); + + shape_enable_feature(features, DWRITE_MAKE_OPENTYPE_TAG('r','c','l','t'), FEATURE_MANUAL_ZWJ); + shape_enable_feature(features, DWRITE_MAKE_OPENTYPE_TAG('c','a','l','t'), FEATURE_MANUAL_ZWJ); + shape_start_next_stage(features); + + shape_enable_feature(features, DWRITE_MAKE_OPENTYPE_TAG('m','s','e','t'), 0); +} + +static void arabic_setup_masks(struct scriptshaping_context *context, + const struct shaping_features *features) +{ +} + +const struct shaper arabic_shaper = +{ + arabic_collect_features, + arabic_setup_masks, +};