• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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