Module: wine Branch: master Commit: e03febf2a2809cc37c90dd17d00e3abd53b78dad URL: https://source.winehq.org/git/wine.git/?a=commit;h=e03febf2a2809cc37c90dd17d...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Thu Jan 21 16:36:54 2021 +0300
dwrite: Add a stub Arabic shaper.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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(-)
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, +};