summaryrefslogtreecommitdiff
path: root/src/mbgl/text/bidi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/text/bidi.cpp')
-rw-r--r--src/mbgl/text/bidi.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/mbgl/text/bidi.cpp b/src/mbgl/text/bidi.cpp
new file mode 100644
index 0000000000..2b6967110c
--- /dev/null
+++ b/src/mbgl/text/bidi.cpp
@@ -0,0 +1,53 @@
+#include <memory>
+
+#include <mbgl/text/bidi.hpp>
+#include <unicode/ubidi.h>
+#include <unicode/ushape.h>
+
+namespace mbgl {
+
+BiDi::BiDi() {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ transform = ubiditransform_open(&errorCode); // Only error is failure to allocate memory, in
+ // that case ubidi_transform would fall back to
+ // creating transform object on the fly
+}
+
+BiDi::~BiDi() {
+ if (transform)
+ ubiditransform_close(transform);
+}
+
+std::u16string BiDi::bidiTransform(const std::u16string& input) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ std::unique_ptr<UChar[]> outputText =
+ std::make_unique<UChar[]>(input.size() * 2); // Maximum output of ubidi_transform is twice
+ // the size of input according to
+ // ubidi_transform.h
+ uint32_t outputLength = ubiditransform_transform(
+ transform, input.c_str(), static_cast<int32_t>(input.size()), outputText.get(),
+ static_cast<int32_t>(input.size()) * 2,
+ UBIDI_DEFAULT_LTR, // Assume input is LTR unless strong RTL characters are found
+ UBIDI_LOGICAL, // Input is in logical order
+ UBIDI_LTR, // Output is in "visual LTR" order
+ UBIDI_VISUAL, // ''
+ UBIDI_MIRRORING_ON, // Use mirroring lookups for things like parentheses that need mirroring
+ // in RTL text
+ U_SHAPE_LETTERS_SHAPE, // Add options here for handling numbers in bidirectional text
+ &errorCode);
+
+ // If the algorithm fails for any reason, fall back to non-transformed text
+ if (U_FAILURE(errorCode))
+ return input;
+
+ return std::u16string(outputText.get(), outputLength);
+}
+
+bool BiDi::baseDirectionRightToLeft(const std::u16string& input) {
+ // This just looks for the first character with a strong direction property, it does not perform
+ // the BiDi algorithm
+ return ubidi_getBaseDirection(input.c_str(), static_cast<int32_t>(input.size())) == UBIDI_RTL;
+}
+
+} // end namespace mbgl