2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "toolkit-text-model.h"
21 #include <dali/devel-api/text-abstraction/font-client.h>
24 #include <dali-toolkit/internal/text/bidirectional-support.h>
25 #include <dali-toolkit/internal/text/character-set-conversion.h>
26 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
27 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
28 #include <dali-toolkit/internal/text/metrics.h>
29 #include <dali-toolkit/internal/text/multi-language-support.h>
30 #include <dali-toolkit/internal/text/segmentation.h>
31 #include <dali-toolkit/internal/text/shaper.h>
32 #include <dali-toolkit/internal/text/text-controller-impl.h>
44 * @brief Frees previously allocated bidirectional resources.
46 * @param[in] bidirectionalLineInfo Bidirectional info per line.
47 * @param[in] index Index to the first line with bidirectional info to be freed.
49 void FreeBidirectionalLineInfoResources( Vector<BidirectionalLineInfoRun> bidirectionalLineInfo,
52 // Free the allocated memory used to store the conversion table in the bidirectional line info run.
53 for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfo.Begin() + index,
54 endIt = bidirectionalLineInfo.End();
58 BidirectionalLineInfoRun& bidiLineInfo = *it;
60 free( bidiLineInfo.visualToLogicalMap );
65 * @brief Clear all the model data except for LogicalModel::mText.
67 * @param[in] characterIndex Clear data starting from the index.
69 void ClearModelData( CharacterIndex characterIndex,
70 LogicalModelPtr logicalModel,
71 VisualModelPtr visualModel )
73 // n.b. This does not Clear the mText from mLogicalModel
75 // Frees previously allocated resources.
76 FreeBidirectionalLineInfoResources( logicalModel->mBidirectionalLineInfo, 0u );
78 logicalModel->mScriptRuns.Clear();
79 logicalModel->mFontRuns.Clear();
80 logicalModel->mWordBreakInfo.Clear();
81 logicalModel->mBidirectionalParagraphInfo.Clear();
82 logicalModel->mCharacterDirections.Clear();
83 logicalModel->mBidirectionalLineInfo.Clear();
84 logicalModel->mLogicalToVisualMap.Clear();
85 logicalModel->mVisualToLogicalMap.Clear();
86 visualModel->mGlyphs.Clear();
87 visualModel->mGlyphsToCharacters.Clear();
88 visualModel->mCharactersToGlyph.Clear();
89 visualModel->mCharactersPerGlyph.Clear();
90 visualModel->mGlyphsPerCharacter.Clear();
91 visualModel->mGlyphPositions.Clear();
92 visualModel->mLines.Clear();
93 visualModel->mColorRuns.Clear();
95 visualModel->ClearCaches();
98 void CreateTextModel( const std::string& text,
100 const Vector<FontDescriptionRun>& fontDescriptions,
101 const LayoutOptions& options,
103 LogicalModelPtr logicalModel,
104 VisualModelPtr visualModel )
106 // 1) Convert to utf32
107 Vector<Character>& utf32Characters = logicalModel->mText;
108 utf32Characters.Resize( text.size() );
110 const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( text.c_str() ),
112 &utf32Characters[0u] );
113 utf32Characters.Resize( numberOfCharacters );
115 // 2) Set the break and paragraph info.
116 Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo;
117 lineBreakInfo.Resize( numberOfCharacters );
119 SetLineBreakInfo( utf32Characters,
124 if( 0u == numberOfCharacters )
126 // Nothing else to do if the number of characters is zero.
130 // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
131 Vector<WordBreakInfo>& wordBreakInfo = logicalModel->mWordBreakInfo;
132 wordBreakInfo.Resize( numberOfCharacters );
134 SetWordBreakInfo( utf32Characters,
139 // 3) Set the script info.
140 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
142 Vector<ScriptRun>& scripts = logicalModel->mScriptRuns;
143 multilanguageSupport.SetScripts( utf32Characters,
148 // 4) Set the font info
149 Vector<FontDescriptionRun>& fontDescriptionRuns = logicalModel->mFontDescriptionRuns;
150 fontDescriptionRuns = fontDescriptions;
151 Vector<FontRun>& validFonts = logicalModel->mFontRuns;
153 // The default font id.
154 FontDefaults fontDefaults;
155 fontDefaults.mFontDescription.family = "";
156 fontDefaults.familyDefined = true;
157 fontDefaults.mDefaultPointSize = 12.f;
158 fontDefaults.sizeDefined = true;
160 TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
161 fontClient.SetDpi( 96u, 96u );
163 const FontId defaultFontId = fontDefaults.GetFontId( fontClient );
165 // Validates the fonts. If there is a character with no assigned font it sets a default one.
166 // After this call, fonts are validated.
167 multilanguageSupport.ValidateFonts( utf32Characters,
175 // 5) Set the bidirectional info per paragraph.
176 Vector<Character> mirroredUtf32Characters;
177 bool textMirrored = false;
179 // Reserve some space for the vector of paragraph's bidirectional info.
180 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
182 // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
183 SetBidirectionalInfo( utf32Characters,
190 // Create the paragraph info.
191 logicalModel->CreateParagraphInfo( 0u,
192 numberOfCharacters );
194 // 6) Set character directions.
195 Vector<CharacterDirection>& characterDirections = logicalModel->mCharacterDirections;
196 if( 0u != bidirectionalInfo.Count() )
198 // Only set the character directions if there is right to left characters.
199 GetCharactersDirection( bidirectionalInfo,
203 characterDirections );
206 // This paragraph has right to left text. Some characters may need to be mirrored.
207 textMirrored = GetMirroredText( utf32Characters,
212 mirroredUtf32Characters );
216 // There is no right to left characters. Clear the directions vector.
217 characterDirections.Clear();
220 // 7) Shape the text.
222 Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
223 Vector<CharacterIndex>& glyphsToCharactersMap = visualModel->mGlyphsToCharacters;
224 Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
225 Vector<GlyphIndex> newParagraphGlyphs;
227 const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
229 ShapeText( textToShape,
237 glyphsToCharactersMap,
239 newParagraphGlyphs );
241 // Create the 'number of glyphs' per character and the glyph to character conversion tables.
242 visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, numberOfCharacters );
243 visualModel->CreateCharacterToGlyphTable( 0u, 0u, numberOfCharacters );
245 const Length numberOfGlyphs = glyphs.Count();
247 // 8) Get the glyph metrics
248 MetricsPtr metrics = Metrics::New( fontClient );
250 GlyphInfo* glyphsBuffer = glyphs.Begin();
251 metrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
253 // Update the width and advance of all new paragraph characters.
254 for( Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(),
255 endIt = newParagraphGlyphs.End();
259 const GlyphIndex index = *it;
260 GlyphInfo& glyph = *( glyphsBuffer + index );
262 glyph.xBearing = 0.f;
267 // 9) Layout the text
268 LayoutEngine layoutEngine;
269 layoutEngine.SetMetrics( metrics );
270 layoutEngine.SetLayout( LayoutEngine::MULTI_LINE_BOX );
272 // Set the layout parameters.
273 const Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
274 const Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
276 LayoutParameters layoutParameters( textArea,
277 utf32Characters.Begin(),
278 lineBreakInfo.Begin(),
279 wordBreakInfo.Begin(),
280 ( 0u != characterDirections.Count() ) ? characterDirections.Begin() : NULL,
282 glyphsToCharactersMap.Begin(),
283 charactersPerGlyph.Begin(),
284 charactersToGlyph.Begin(),
285 glyphsPerCharacter.Begin(),
288 Vector<LineRun>& lines = visualModel->mLines;
290 Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
291 glyphPositions.Resize( numberOfGlyphs );
293 layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( numberOfCharacters - 1u ) ) );
295 // The initial glyph and the number of glyphs to layout.
296 layoutParameters.startGlyphIndex = 0u;
297 layoutParameters.numberOfGlyphs = numberOfGlyphs;
299 layoutEngine.LayoutText( layoutParameters,
304 // 10) Reorder the lines
305 if( 0u != bidirectionalInfo.Count() )
307 Vector<BidirectionalLineInfoRun>& bidirectionalLineInfo = logicalModel->mBidirectionalLineInfo;
310 const Length numberOfLines = lines.Count();
312 // Reorder the lines.
313 bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
314 ReorderLines( bidirectionalInfo,
318 bidirectionalLineInfo );
320 // Set the bidirectional info per line into the layout parameters.
321 layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
322 layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
324 // Set the bidirectional info into the model.
325 logicalModel->SetVisualToLogicalMap( layoutParameters.lineBidirectionalInfoRunsBuffer,
326 layoutParameters.numberOfBidirectionalInfoRuns,
328 numberOfCharacters );
330 if( options.reorder )
332 // Re-layout the text. Reorder those lines with right to left characters.
333 layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
342 layoutEngine.Align( textArea,
351 } // namespace Toolkit