b41b841ecd553867d36f6cd5974b120fc89b0adf
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / text-view / text-processor.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // FILE HEADER
19 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
20
21 namespace Dali
22 {
23
24 namespace Toolkit
25 {
26
27 namespace Internal
28 {
29
30 namespace TextProcessor
31 {
32
33 void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray,
34                         std::vector<Text>& paragraphs,
35                         std::vector< Vector<TextStyle*> >& styles )
36 {
37   // Stores the text for a paragraph.
38   Text paragraph;
39
40   // Stores the styles for each character of the paragraph.
41   Vector<TextStyle*> stylesForParagraph;
42
43   // Traverses all styled texts of the array.
44   for( MarkupProcessor::StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it )
45   {
46     const MarkupProcessor::StyledText& styledText( *it );
47
48     // Traverses all the characters of the styled text (It may have more than one).
49     for( size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i )
50     {
51       const Dali::Character character = styledText.mText[i];
52
53       if( character.IsNewLine() ) // LF
54       {
55         // The character is a new paragraph character.
56
57         // Append the new paragraph character.
58         paragraph.Append( character );
59
60         // Creates a new text style for the character and insert it to the vector of styles for that paragraph.
61         TextStyle* style = new TextStyle( styledText.mStyle );
62         stylesForParagraph.PushBack( style );
63
64         // Inserts the paragraph and the styles to the vector of paragraphs and the vector of styles.
65         paragraphs.push_back( paragraph );
66         styles.push_back( stylesForParagraph );
67
68         // Clears the text and the vector of styles for the next paragraph.
69         paragraph = Text();
70         stylesForParagraph.Clear();
71       }
72       else
73       {
74         // The character is not a new paragraph character.
75
76         // Append it to the paragraph's text
77         paragraph.Append( character );
78
79         // Add the style to the vector of styles for that paragraph.
80         TextStyle* style = new TextStyle( styledText.mStyle );
81         stylesForParagraph.PushBack( style );
82       }
83     }
84   }
85
86   // This paragraph could be empty if the last character of the previous paragraph is a 'new paragraph' character
87   // and is the last of the text.
88   paragraphs.push_back( paragraph );
89   styles.push_back( stylesForParagraph );
90 }
91
92 void SplitInWords( const Dali::Text& paragraph,
93                    Vector<std::size_t>& positions )
94 {
95   const std::size_t length = paragraph.GetLength();
96
97   // Magic number: Let's soupose there is ~6 characters per word. Used to do less memory reallocation inside Vector.
98   const size_t magicNumberOfWords = ( length / 6u ) + 1u;
99
100   // Find the positions of the new paragraph characters.
101   positions.Reserve( magicNumberOfWords );
102
103   // Find the position of all white spaces. A new paragraph character is also considered a white space but it doesn't matter at this point.
104   paragraph.Find( Text::WHITE_SPACE, 0u, length - 1u, positions );
105 }
106
107 /**
108  * Wheather the character of the text pointed by the given offset is a white space.
109  *
110  * @param[in] text The text.
111  * @param[in] offset Offset pointing the character.
112  *
113  * @return \e true if the character pointed by the offset is a white space.
114  */
115 bool IsWhiteSpace( const MarkupProcessor::StyledTextArray& text, size_t offset )
116 {
117   DALI_ASSERT_DEBUG( offset < text.size() );
118
119   // assume 1 Character per StyledText
120   return ( *( text.begin() + offset ) ).mText[0u].IsWhiteSpace();
121 }
122
123 void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end)
124 {
125   const size_t size(text.size());
126   offset = std::min(offset, size-1u);
127
128   size_t i(offset);
129   size_t j(offset);
130
131   // if currently looking at whitespace, then search left and right for non-whitespace.
132   if(IsWhiteSpace(text, offset))
133   {
134     // scan left until non-white space / beginning of string.
135     while(i > 0u && IsWhiteSpace(text, i))
136     {
137       i--;
138     }
139
140     // scan right until non-white space / end of string.
141     while(j < size && IsWhiteSpace(text, j))
142     {
143       j++;
144     }
145   }
146
147   // check if r.h.s. word is closer than l.h.s. word
148   if( (j - offset) < // distance to closest right word <
149       (offset - i) ) // distance to closest left word
150   {
151     // point left and right markers on start of right word
152     i = j;
153   }
154   else
155   {
156     // point left and right markers on end of left word
157     j = i;
158   }
159
160   // expand left and right markers to encompase entire word
161   while(i > 0u && !IsWhiteSpace(text, i-1u))
162   {
163     i--;
164   }
165
166   while(j < size && !IsWhiteSpace(text, j))
167   {
168     j++;
169   }
170
171   // If both markers at same position and is whitespace then word is a whitespace word
172   if ( i == j )
173   {
174     while(j < size && IsWhiteSpace(text, j))
175     {
176       j++;
177     }
178   }
179
180   start = i;
181   end = j;
182 }
183
184 } // namespace TextProcessor
185
186 } // namespace Internal
187
188 } // namespace DaliToolkit
189
190 } // namespace Dali