Nikolay Sivov : dwrite: Add a stub Arabic shaper.

Alexandre Julliard julliard at winehq.org
Thu Jan 21 16:19:16 CST 2021


Module: wine
Branch: master
Commit: e03febf2a2809cc37c90dd17d00e3abd53b78dad
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e03febf2a2809cc37c90dd17d00e3abd53b78dad

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Thu Jan 21 16:36:54 2021 +0300

dwrite: Add a stub Arabic shaper.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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,
+};




More information about the wine-cvs mailing list