1 /*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #define LOG_TAG "webviewglue"
27
28 #include "config.h"
29
30 #include "BidiResolver.h"
31 #include "BidiRunList.h"
32 #include "GLExtras.h"
33 #include "LayerAndroid.h"
34 #include "SelectText.h"
35 #include "SkBitmap.h"
36 #include "SkBounder.h"
37 #include "SkCanvas.h"
38 #include "SkPicture.h"
39 #include "SkPoint.h"
40 #include "SkRect.h"
41 #include "SkRegion.h"
42 #include "TextRun.h"
43
44 #ifdef DEBUG_NAV_UI
45 #include <wtf/text/CString.h>
46 #endif
47
48 #define VERBOSE_LOGGING 0
49 // #define EXTRA_NOISY_LOGGING 1
50 #define DEBUG_TOUCH_HANDLES 0
51 #if DEBUG_TOUCH_HANDLES
52 #define DBG_HANDLE_LOG(format, ...) ALOGD("%s " format, __FUNCTION__, __VA_ARGS__)
53 #else
54 #define DBG_HANDLE_LOG(...)
55 #endif
56
57 // TextRunIterator has been copied verbatim from GraphicsContext.cpp
58 namespace WebCore {
59
60 class TextRunIterator {
61 public:
TextRunIterator()62 TextRunIterator()
63 : m_textRun(0)
64 , m_offset(0)
65 {
66 }
67
TextRunIterator(const TextRun * textRun,unsigned offset)68 TextRunIterator(const TextRun* textRun, unsigned offset)
69 : m_textRun(textRun)
70 , m_offset(offset)
71 {
72 }
73
TextRunIterator(const TextRunIterator & other)74 TextRunIterator(const TextRunIterator& other)
75 : m_textRun(other.m_textRun)
76 , m_offset(other.m_offset)
77 {
78 }
79
offset() const80 unsigned offset() const { return m_offset; }
increment()81 void increment() { m_offset++; }
atEnd() const82 bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); }
current() const83 UChar current() const { return (*m_textRun)[m_offset]; }
direction() const84 WTF::Unicode::Direction direction() const { return atEnd() ? WTF::Unicode::OtherNeutral : WTF::Unicode::direction(current()); }
85
operator ==(const TextRunIterator & other)86 bool operator==(const TextRunIterator& other)
87 {
88 return m_offset == other.m_offset && m_textRun == other.m_textRun;
89 }
90
operator !=(const TextRunIterator & other)91 bool operator!=(const TextRunIterator& other) { return !operator==(other); }
92
93 private:
94 const TextRun* m_textRun;
95 int m_offset;
96 };
97
98 // ReverseBidi is a trimmed-down version of GraphicsContext::drawBidiText()
ReverseBidi(UChar * chars,int len)99 void ReverseBidi(UChar* chars, int len) {
100 using namespace WTF::Unicode;
101 WTF::Vector<UChar> result;
102 result.reserveCapacity(len);
103 TextRun run(chars, len);
104 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
105 BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
106 bidiResolver.setStatus(BidiStatus(LeftToRight, LeftToRight, LeftToRight,
107 BidiContext::create(0, LeftToRight, false)));
108 bidiResolver.setPosition(TextRunIterator(&run, 0));
109 bidiResolver.createBidiRunsForLine(TextRunIterator(&run, len));
110 if (!bidiRuns.runCount())
111 return;
112 BidiCharacterRun* bidiRun = bidiRuns.firstRun();
113 while (bidiRun) {
114 int bidiStart = bidiRun->start();
115 int bidiStop = bidiRun->stop();
116 int size = result.size();
117 int bidiCount = bidiStop - bidiStart;
118 result.append(chars + bidiStart, bidiCount);
119 if (bidiRun->level() % 2) {
120 UChar* start = &result[size];
121 UChar* end = start + bidiCount;
122 // reverse the order of any RTL substrings
123 while (start < end) {
124 UChar temp = *start;
125 *start++ = *--end;
126 *end = temp;
127 }
128 start = &result[size];
129 end = start + bidiCount - 1;
130 // if the RTL substring had a surrogate pair, restore its order
131 while (start < end) {
132 UChar trail = *start++;
133 if (!U16_IS_SURROGATE(trail))
134 continue;
135 start[-1] = *start; // lead
136 *start++ = trail;
137 }
138 }
139 bidiRun = bidiRun->next();
140 }
141 bidiRuns.deleteRuns();
142 memcpy(chars, &result[0], len * sizeof(UChar));
143 }
144
145 }
146
147