Browse Source

text: Support explicit direction even with harfbuzz disabled

Fixes #1591
rdb 1 year ago
parent
commit
23772c4722
1 changed files with 41 additions and 0 deletions
  1. 41 0
      panda/src/text/textAssembler.cxx

+ 41 - 0
panda/src/text/textAssembler.cxx

@@ -1411,6 +1411,10 @@ assemble_row(TextAssembler::TextRow &row,
   PN_stdfloat xpos = 0.0f;
   PN_stdfloat xpos = 0.0f;
   align = TextProperties::A_left;
   align = TextProperties::A_left;
 
 
+  TextProperties::Direction dir = TextProperties::D_ltr;
+  size_t rtl_begin = 0;
+  PN_stdfloat rtl_begin_xpos = 0.0f;
+
   // Remember previous character, for kerning.
   // Remember previous character, for kerning.
   int prev_char = -1;
   int prev_char = -1;
 
 
@@ -1472,6 +1476,8 @@ assemble_row(TextAssembler::TextRow &row,
         // Shape the buffer accumulated so far.
         // Shape the buffer accumulated so far.
         shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties);
         shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties);
         hb_buffer_reset(harfbuff);
         hb_buffer_reset(harfbuff);
+        rtl_begin = placed_glyphs.size();
+        rtl_begin_xpos = xpos;
 
 
       } else if (harfbuff == nullptr && text_use_harfbuzz &&
       } else if (harfbuff == nullptr && text_use_harfbuzz &&
                  font->is_of_type(DynamicTextFont::get_class_type())) {
                  font->is_of_type(DynamicTextFont::get_class_type())) {
@@ -1486,6 +1492,29 @@ assemble_row(TextAssembler::TextRow &row,
     }
     }
 #endif
 #endif
 
 
+    // When not using harfbuzz, check if the direction was set explicitly.
+    if (properties->has_direction() && properties->get_direction() != dir) {
+      if (dir == TextProperties::D_rtl) {
+        // Flip the preceding characters.
+        PN_stdfloat xpos2 = xpos;
+        size_t i = placed_glyphs.size();
+        while (i > rtl_begin) {
+          --i;
+          PN_stdfloat new_xpos = rtl_begin_xpos + (xpos - xpos2);
+          xpos2 = placed_glyphs[i]._xpos;
+          placed_glyphs[i]._xpos = new_xpos;
+        }
+        dir = TextProperties::D_ltr;
+      }
+      else if (dir == TextProperties::D_ltr) {
+        // When switching to right-to-left, keep track of the first glyph that
+        // was RTL so that we can later offset the X positions.
+        dir = TextProperties::D_rtl;
+        rtl_begin = placed_glyphs.size();
+        rtl_begin_xpos = xpos;
+      }
+    }
+
     if (character == ' ') {
     if (character == ' ') {
       // A space is a special case.
       // A space is a special case.
       xpos += properties->get_glyph_scale() * properties->get_text_scale() * font->get_space_advance();
       xpos += properties->get_glyph_scale() * properties->get_text_scale() * font->get_space_advance();
@@ -1651,6 +1680,18 @@ assemble_row(TextAssembler::TextRow &row,
     }
     }
   }
   }
 
 
+  if (dir == TextProperties::D_rtl) {
+    // Flip the preceding characters.
+    PN_stdfloat xpos2 = xpos;
+    size_t i = placed_glyphs.size();
+    while (i > rtl_begin) {
+      --i;
+      PN_stdfloat new_xpos = rtl_begin_xpos + (xpos - xpos2);
+      xpos2 = placed_glyphs[i]._xpos;
+      placed_glyphs[i]._xpos = new_xpos;
+    }
+  }
+
 #ifdef HAVE_HARFBUZZ
 #ifdef HAVE_HARFBUZZ
   if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) {
   if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) {
     shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties);
     shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties);