diff --git a/gdk/gdk-private.h b/gdk/gdk-private.h index 0c83002bfc..551ecac9aa 100644 --- a/gdk/gdk-private.h +++ b/gdk/gdk-private.h @@ -36,4 +36,8 @@ gboolean gdk_should_use_portal (void); const gchar * gdk_get_startup_notification_id (void); +PangoDirection gdk_unichar_direction (gunichar ch); +PangoDirection gdk_find_base_dir (const char *text, + int len); + #endif /* __GDK__PRIVATE_H__ */ diff --git a/gdk/gdk.c b/gdk/gdk.c index d623afabf9..6954ef772e 100644 --- a/gdk/gdk.c +++ b/gdk/gdk.c @@ -40,6 +40,8 @@ #include #include +#include + /** * SECTION:general @@ -343,3 +345,45 @@ gdk_should_use_portal (void) * management for you. */ +PangoDirection +gdk_unichar_direction (gunichar ch) +{ + FriBidiCharType fribidi_ch_type; + + G_STATIC_ASSERT (sizeof (FriBidiChar) == sizeof (gunichar)); + + fribidi_ch_type = fribidi_get_bidi_type (ch); + + if (!FRIBIDI_IS_STRONG (fribidi_ch_type)) + return PANGO_DIRECTION_NEUTRAL; + else if (FRIBIDI_IS_RTL (fribidi_ch_type)) + return PANGO_DIRECTION_RTL; + else + return PANGO_DIRECTION_LTR; +} + +PangoDirection +gdk_find_base_dir (const gchar *text, + gint length) +{ + PangoDirection dir = PANGO_DIRECTION_NEUTRAL; + const gchar *p; + + g_return_val_if_fail (text != NULL || length == 0, PANGO_DIRECTION_NEUTRAL); + + p = text; + while ((length < 0 || p < text + length) && *p) + { + gunichar wc = g_utf8_get_char (p); + + dir = gdk_unichar_direction (wc); + + if (dir != PANGO_DIRECTION_NEUTRAL) + break; + + p = g_utf8_next_char (p); + } + + return dir; +} + diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index f64f38dd4b..a8c4bb6176 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -351,7 +351,6 @@ void gdk_synthesize_surface_state (GdkSurface *surface, GdkSurfaceState unset_flags, GdkSurfaceState set_flags); - G_END_DECLS #endif /* __GDK_INTERNALS_H__ */ diff --git a/gdk/meson.build b/gdk/meson.build index d68307392b..a7b5f2e630 100644 --- a/gdk/meson.build +++ b/gdk/meson.build @@ -168,6 +168,7 @@ gdk_deps = [ pixbuf_dep, cairo_dep, pango_dep, + fribidi_dep, cairogobj_dep, glib_dep, gobject_dep, diff --git a/gdk/wayland/gdkkeys-wayland.c b/gdk/wayland/gdkkeys-wayland.c index cad938f5f0..9a6809d23b 100644 --- a/gdk/wayland/gdkkeys-wayland.c +++ b/gdk/wayland/gdkkeys-wayland.c @@ -31,12 +31,13 @@ #include #include #include +#include #include "gdk.h" #include "gdkwayland.h" #include "gdkprivate-wayland.h" -#include "gdkinternals.h" +#include "gdk-private.h" #include "gdkkeysprivate.h" #include @@ -499,7 +500,7 @@ update_direction (GdkWaylandKeymap *keymap) { PangoDirection dir; - dir = pango_unichar_direction (xkb_keysym_to_utf32 (syms[sym])); + dir = gdk_unichar_direction (xkb_keysym_to_utf32 (syms[sym])); switch (dir) { case PANGO_DIRECTION_RTL: diff --git a/gdk/x11/gdkkeys-x11.c b/gdk/x11/gdkkeys-x11.c index be54e66e18..4c27ac3472 100644 --- a/gdk/x11/gdkkeys-x11.c +++ b/gdk/x11/gdkkeys-x11.c @@ -29,6 +29,7 @@ #include "gdkkeysyms.h" #include "gdkprivate-x11.h" #include "gdkdisplay-x11.h" +#include "gdk-private.h" #include #include @@ -480,7 +481,7 @@ get_direction (XkbDescRec *xkb, { gint level = 0; KeySym sym = XkbKeySymEntry (xkb, code, level, group); - PangoDirection dir = pango_unichar_direction (gdk_keyval_to_unicode (sym)); + PangoDirection dir = gdk_unichar_direction (gdk_keyval_to_unicode (sym)); switch (dir) { diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index f5231424e4..2115852aa3 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -5477,7 +5477,7 @@ gtk_entry_create_layout (GtkEntry *entry, PangoDirection pango_dir; if (gtk_entry_get_display_mode (entry) == DISPLAY_NORMAL) - pango_dir = pango_find_base_dir (display_text, n_bytes); + pango_dir = gdk_find_base_dir (display_text, n_bytes); else pango_dir = PANGO_DIRECTION_NEUTRAL; diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index a51e96d8b1..a4f9b5398f 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -66,6 +66,8 @@ #include "gtkdebug.h" #include "gtktextmarkprivate.h" #include "gtktextsegment.h" +#include "gtkpango.h" +#include "gdk-private.h" /* * Types @@ -595,8 +597,7 @@ gtk_text_btree_resolve_bidi (GtkTextIter *start, { PangoDirection pango_dir; - pango_dir = pango_find_base_dir (seg->body.chars, - seg->byte_count); + pango_dir = gdk_find_base_dir (seg->body.chars, seg->byte_count); if (pango_dir != PANGO_DIRECTION_NEUTRAL) { diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index bbdf7efb68..2950ad7dec 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -56,6 +56,7 @@ #include "gtktoolbar.h" #include "gtkmagnifierprivate.h" #include "gtkemojichooser.h" +#include "gtkpango.h" #include "a11y/gtktextviewaccessibleprivate.h" @@ -5831,7 +5832,7 @@ iter_line_is_rtl (const GtkTextIter *iter) gtk_text_iter_set_line_offset (&start, 0); gtk_text_iter_forward_line (&end); text = gtk_text_iter_get_visible_text (&start, &end); - direction = pango_find_base_dir (text, -1); + direction = gdk_find_base_dir (text, -1); g_free (text); diff --git a/gtk/meson.build b/gtk/meson.build index e45b18bf8e..57784e415c 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -872,6 +872,7 @@ gtk_deps = [ platform_gio_dep, pangocairo_dep, pango_dep, + fribidi_dep, cairogobj_dep, cairo_dep, fontconfig_dep, diff --git a/meson.build b/meson.build index 0385d15b07..6579ee4f27 100644 --- a/meson.build +++ b/meson.build @@ -28,6 +28,7 @@ endif glib_req = '>= @0@.@1@.@2@'.format(glib_major_req, glib_minor_req, glib_micro_req) pango_req = '>= 1.41.0' +fribidi_req = '>= 0.19.7' atk_req = '>= 2.15.1' cairo_req = '>= 1.14.0' gdk_pixbuf_req = '>= 2.30.0' @@ -325,6 +326,8 @@ cairo_dep = dependency('cairo', version: cairo_req, required : cc.get_id() cairogobj_dep = dependency('cairo-gobject', version: cairo_req, required : cc.get_id() != 'msvc') pango_dep = dependency('pango', version: pango_req, fallback : ['pango', 'libpango_dep']) +fribidi_dep = dependency('fribidi', version: fribidi_req, + fallback : ['fribidi', 'libfribidi_dep']) # Require PangoFT2 if on X11 or wayland require_pangoft2 = wayland_enabled or x11_enabled