Bug 1431025 - Use encoding_rs::mem::is_utf16_bidi() as the implementation of HasRTLChars(). draft
authorHenri Sivonen <hsivonen@hsivonen.fi>
Thu, 18 Jan 2018 14:28:15 +0200
changeset 737961 877ce5e313ab58724138497fce0d18fc547ec693
parent 737960 87fed30c57597ade9c70b3509c41fcc26f54b6e1
push id96806
push userbmo:hsivonen@hsivonen.fi
push dateThu, 25 Jan 2018 12:34:23 +0000
bugs1431025
milestone60.0a1
Bug 1431025 - Use encoding_rs::mem::is_utf16_bidi() as the implementation of HasRTLChars(). MozReview-Commit-ID: KnaI7wIndVf
dom/base/nsGenericDOMDataNode.cpp
dom/base/nsTextFragment.cpp
intl/encoding_glue/src/lib.rs
intl/unicharutil/util/nsBidiUtils.cpp
intl/unicharutil/util/nsBidiUtils.h
layout/base/nsBidiPresUtils.cpp
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -344,17 +344,17 @@ nsGenericDOMDataNode::SetTextInternal(ui
 
     // Copy over appropriate data
     if (aOffset) {
       mText.AppendTo(to, 0, aOffset);
     }
     if (aLength) {
       to.Append(aBuffer, aLength);
       if (!bidi && (!document || !document->GetBidiEnabled())) {
-        bidi = HasRTLChars(aBuffer, aLength);
+        bidi = HasRTLChars(MakeSpan(aBuffer, aLength));
       }
     }
     if (endOffset != textLength) {
       mText.AppendTo(to, endOffset, textLength - endOffset);
     }
 
     // If this is marked as "maybe modified frequently", the text should be
     // stored as char16_t since converting char* to char16_t* is expensive.
--- a/dom/base/nsTextFragment.cpp
+++ b/dom/base/nsTextFragment.cpp
@@ -503,13 +503,13 @@ nsTextFragment::SizeOfExcludingThis(mozi
 }
 
 // To save time we only do this when we really want to know, not during
 // every allocation
 void
 nsTextFragment::UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength)
 {
   if (mState.mIs2b && !mState.mIsBidi) {
-    if (HasRTLChars(aBuffer, aLength)) {
+    if (HasRTLChars(MakeSpan(aBuffer, aLength))) {
       mState.mIsBidi = true;
     }
   }
 }
--- a/intl/encoding_glue/src/lib.rs
+++ b/intl/encoding_glue/src/lib.rs
@@ -578,8 +578,15 @@ fn checked_min(one: Option<usize>, other
             Some(::std::cmp::min(a, b))
         } else {
             Some(a)
         }
     } else {
         other
     }
 }
+
+// Bindings for encoding_rs::mem. These may move to a separate crate in the future.
+
+#[no_mangle]
+pub unsafe extern "C" fn encoding_mem_is_utf16_bidi(buffer: *const u16, len: usize) -> bool {
+    encoding_rs::mem::is_utf16_bidi(::std::slice::from_raw_parts(buffer, len))
+}
--- a/intl/unicharutil/util/nsBidiUtils.cpp
+++ b/intl/unicharutil/util/nsBidiUtils.cpp
@@ -80,26 +80,8 @@ nsresult HandleNumbers(char16_t* aBuffer
         aBuffer[i] = HandleNumberInChar(aBuffer[i], !!(i>0 ? aBuffer[i-1] : 0), aNumFlag);
       break;
     case IBMBIDI_NUMERAL_NOMINAL:
     default:
       break;
   }
   return NS_OK;
 }
-
-bool HasRTLChars(const char16_t* aText, uint32_t aLength)
-{
-  // This is used to determine whether a string has right-to-left characters
-  // that mean it will require bidi processing.
-  const char16_t* cp = aText;
-  const char16_t* end = cp + aLength;
-  while (cp < end) {
-    char16_t ch = *cp++;
-    if (ch < mozilla::kMinRTLChar) {
-      continue;
-    }
-    if (UTF16_CODE_UNIT_IS_BIDI(ch) || IsBidiControlRTL(ch)) {
-      return true;
-    }
-  }
-  return false;
-}
--- a/intl/unicharutil/util/nsBidiUtils.h
+++ b/intl/unicharutil/util/nsBidiUtils.h
@@ -3,16 +3,24 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsBidiUtils_h__
 #define nsBidiUtils_h__
 
 #include "nsString.h"
 
+extern "C" {
+
+bool
+encoding_mem_is_utf16_bidi(char16_t const* buffer,
+                           size_t len);
+
+}
+
    /**
     *  Read ftp://ftp.unicode.org/Public/UNIDATA/ReadMe-Latest.txt
     *  section BIDIRECTIONAL PROPERTIES
     *  for the detailed definition of the following categories
     *
     *  The values here must match the equivalents in %bidicategorycode in
     *  mozilla/intl/unicharutil/tools/genUnicodePropertyData.pl,
     *  and must also match the values used by ICU's UCharDirection.
@@ -120,49 +128,46 @@ typedef enum nsCharType nsCharType;
 #define RLO_CHAR 0x202e
 
 #define LRI_CHAR 0x2066
 #define RLI_CHAR 0x2067
 #define FSI_CHAR 0x2068
 #define PDI_CHAR 0x2069
 
 #define ALM_CHAR 0x061C
-   inline bool IsBidiControl(uint32_t aChar) {
-     return ((LRE_CHAR <= aChar && aChar <= RLO_CHAR) ||
-             (LRI_CHAR <= aChar && aChar <= PDI_CHAR) ||
-             (aChar == ALM_CHAR) ||
-             (aChar & 0xfffffe) == LRM_CHAR);
-   }
+  inline bool IsBidiControl(uint32_t aChar) {
+    return ((LRE_CHAR <= aChar && aChar <= RLO_CHAR) ||
+            (LRI_CHAR <= aChar && aChar <= PDI_CHAR) ||
+            (aChar == ALM_CHAR) ||
+            (aChar & 0xfffffe) == LRM_CHAR);
+  }
 
   /**
    * Give a UTF-32 codepoint
    * Return true if the codepoint is a Bidi control character that may result
    * in RTL directionality and therefore needs to trigger bidi resolution;
    * return false otherwise.
    */
-   inline bool IsBidiControlRTL(uint32_t aChar) {
-     return aChar == RLM_CHAR ||
-            aChar == RLE_CHAR ||
-            aChar == RLO_CHAR ||
-            aChar == RLI_CHAR ||
-            aChar == ALM_CHAR;
-   }
+  inline bool IsBidiControlRTL(uint32_t aChar) {
+    return aChar == RLM_CHAR ||
+           aChar == RLE_CHAR ||
+           aChar == RLO_CHAR ||
+           aChar == RLI_CHAR ||
+           aChar == ALM_CHAR;
+  }
 
   /**
-   * Give a 16-bit (UTF-16) text buffer and length
+   * Give a 16-bit (UTF-16) text buffer
    * @return true if the string contains right-to-left characters
    */
-   bool HasRTLChars(const char16_t* aText, uint32_t aLength);
-
-  /**
-   * Convenience function to call the above on an nsAString.
-   */
-   inline bool HasRTLChars(const nsAString& aString) {
-     return HasRTLChars(aString.BeginReading(), aString.Length());
-   }
+  inline bool HasRTLChars(mozilla::Span<const char16_t> aBuffer) {
+    // Span ensures we never pass a nullptr to Rust--even if the
+    // length of the buffer is zero.
+    return encoding_mem_is_utf16_bidi(aBuffer.Elements(), aBuffer.Length());
+  }
 
 // These values are shared with Preferences dialog
 //  ------------------
 //  If Pref values are to be changed
 //  in the XUL file of Prefs. the values
 //  Must be changed here too..
 //  ------------------
 //
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -1328,17 +1328,17 @@ nsBidiPresUtils::ChildListMayRequireBidi
         }
 
         // Check whether the text frame has any RTL characters; if so, bidi
         // resolution will be needed.
         nsIContent* content = frame->GetContent();
         if (content != *aCurrContent) {
           *aCurrContent = content;
           const nsTextFragment* txt = content->GetText();
-          if (txt->Is2b() && HasRTLChars(txt->Get2b(), txt->GetLength())) {
+          if (txt->Is2b() && HasRTLChars(MakeSpan(txt->Get2b(), txt->GetLength()))) {
             return true;
           }
         }
       }
     } else if (ChildListMayRequireBidi(frame->PrincipalChildList().FirstChild(),
                                        aCurrContent)) {
       return true;
     }