2 * Copyright (c) 2018 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.
19 #include "toolkit-text-utils.h"
23 #include <dali/devel-api/text-abstraction/font-client.h>
26 #include <dali-toolkit/internal/text/bidirectional-support.h>
27 #include <dali-toolkit/internal/text/character-set-conversion.h>
28 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
29 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
30 #include <dali-toolkit/internal/text/multi-language-support.h>
31 #include <dali-toolkit/internal/text/segmentation.h>
32 #include <dali-toolkit/internal/text/shaper.h>
33 #include <dali-toolkit/internal/text/text-controller-impl.h>
45 * @brief Frees previously allocated bidirectional resources.
47 * @param[in] bidirectionalLineInfo Bidirectional info per line.
48 * @param[in] index Index to the first line with bidirectional info to be freed.
50 void FreeBidirectionalLineInfoResources( Vector<BidirectionalLineInfoRun> bidirectionalLineInfo,
53 // Free the allocated memory used to store the conversion table in the bidirectional line info run.
54 for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfo.Begin() + index,
55 endIt = bidirectionalLineInfo.End();
59 BidirectionalLineInfoRun& bidiLineInfo = *it;
61 free( bidiLineInfo.visualToLogicalMap );
66 * @brief Clear all the model data except for LogicalModel::mText.
68 * @param[in] characterIndex Clear data starting from the index.
70 void ClearModelData( CharacterIndex characterIndex,
71 LogicalModelPtr logicalModel,
72 VisualModelPtr visualModel )
74 // n.b. This does not Clear the mText from mLogicalModel
76 // Frees previously allocated resources.
77 FreeBidirectionalLineInfoResources( logicalModel->mBidirectionalLineInfo, 0u );
79 logicalModel->mScriptRuns.Clear();
80 logicalModel->mFontRuns.Clear();
81 logicalModel->mWordBreakInfo.Clear();
82 logicalModel->mBidirectionalParagraphInfo.Clear();
83 logicalModel->mCharacterDirections.Clear();
84 logicalModel->mBidirectionalLineInfo.Clear();
85 visualModel->mGlyphs.Clear();
86 visualModel->mGlyphsToCharacters.Clear();
87 visualModel->mCharactersToGlyph.Clear();
88 visualModel->mCharactersPerGlyph.Clear();
89 visualModel->mGlyphsPerCharacter.Clear();
90 visualModel->mGlyphPositions.Clear();
91 visualModel->mLines.Clear();
93 visualModel->ClearCaches();
96 void CreateTextModel( const std::string& text,
98 const Vector<FontDescriptionRun>& fontDescriptions,
99 const LayoutOptions& options,
101 LogicalModelPtr& logicalModel,
102 VisualModelPtr& visualModel,
103 MetricsPtr& metrics )
105 logicalModel = LogicalModel::New();
106 visualModel = VisualModel::New();
108 // 1) Convert to utf32
109 Vector<Character>& utf32Characters = logicalModel->mText;
110 utf32Characters.Resize( text.size() );
112 const uint32_t numberOfCharacters = ( text.size() == 0) ? 0 :
113 Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( text.c_str() ),
115 &utf32Characters[0u] );
116 utf32Characters.Resize( numberOfCharacters );
118 // 2) Set the break and paragraph info.
119 Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo;
120 lineBreakInfo.Resize( numberOfCharacters );
122 SetLineBreakInfo( utf32Characters,
127 if( 0u == numberOfCharacters )
129 // Nothing else to do if the number of characters is zero.
133 // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
134 Vector<WordBreakInfo>& wordBreakInfo = logicalModel->mWordBreakInfo;
135 wordBreakInfo.Resize( numberOfCharacters );
137 SetWordBreakInfo( utf32Characters,
142 // 3) Set the script info.
143 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
145 Vector<ScriptRun>& scripts = logicalModel->mScriptRuns;
146 multilanguageSupport.SetScripts( utf32Characters,
151 // 4) Set the font info
152 Vector<FontDescriptionRun>& fontDescriptionRuns = logicalModel->mFontDescriptionRuns;
153 fontDescriptionRuns = fontDescriptions;
154 Vector<FontRun>& validFonts = logicalModel->mFontRuns;
156 // The default font description.
157 TextAbstraction::FontDescription fontDescription;
159 TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
160 fontClient.SetDpi( 96u, 96u );
162 // Validates the fonts. If there is a character with no assigned font it sets a default one.
163 // After this call, fonts are validated.
164 multilanguageSupport.ValidateFonts( utf32Characters,
168 TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
173 // 5) Set the bidirectional info per paragraph.
174 Vector<Character> mirroredUtf32Characters;
175 bool textMirrored = false;
177 // Reserve some space for the vector of paragraph's bidirectional info.
178 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
180 // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
181 SetBidirectionalInfo( utf32Characters,
188 // Create the paragraph info.
189 logicalModel->CreateParagraphInfo( 0u,
190 numberOfCharacters );
192 // 6) Set character directions.
193 Vector<CharacterDirection>& characterDirections = logicalModel->mCharacterDirections;
194 if( 0u != bidirectionalInfo.Count() )
196 // Only set the character directions if there is right to left characters.
197 GetCharactersDirection( bidirectionalInfo,
201 characterDirections );
204 // This paragraph has right to left text. Some characters may need to be mirrored.
205 textMirrored = GetMirroredText( utf32Characters,
210 mirroredUtf32Characters );
214 // There is no right to left characters. Clear the directions vector.
215 characterDirections.Clear();
218 // 7) Shape the text.
220 Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
221 Vector<CharacterIndex>& glyphsToCharactersMap = visualModel->mGlyphsToCharacters;
222 Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
223 Vector<GlyphIndex> newParagraphGlyphs;
225 const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
227 ShapeText( textToShape,
235 glyphsToCharactersMap,
237 newParagraphGlyphs );
239 // Create the 'number of glyphs' per character and the glyph to character conversion tables.
240 visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, numberOfCharacters );
241 visualModel->CreateCharacterToGlyphTable( 0u, 0u, numberOfCharacters );
243 const Length numberOfGlyphs = glyphs.Count();
245 // 8) Get the glyph metrics
246 metrics = Metrics::New( fontClient );
248 GlyphInfo* glyphsBuffer = glyphs.Begin();
249 metrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
251 // Update the width and advance of all new paragraph characters.
252 for( Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(),
253 endIt = newParagraphGlyphs.End();
257 const GlyphIndex index = *it;
258 GlyphInfo& glyph = *( glyphsBuffer + index );
260 glyph.xBearing = 0.f;
265 // 9) Layout the text
266 Layout::Engine layoutEngine;
267 layoutEngine.SetMetrics( metrics );
268 layoutEngine.SetLayout( Layout::Engine::MULTI_LINE_BOX );
270 // Set the layout parameters.
271 const Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
272 const Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
273 float outlineWidth = visualModel->GetOutlineWidth();
274 Layout::Parameters layoutParameters( textArea,
275 utf32Characters.Begin(),
276 lineBreakInfo.Begin(),
277 wordBreakInfo.Begin(),
278 ( 0u != characterDirections.Count() ) ? characterDirections.Begin() : NULL,
280 glyphsToCharactersMap.Begin(),
281 charactersPerGlyph.Begin(),
282 charactersToGlyph.Begin(),
283 glyphsPerCharacter.Begin(),
285 Text::HorizontalAlignment::BEGIN,
286 Text::LineWrap::WORD,
290 Vector<LineRun>& lines = visualModel->mLines;
292 Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
293 glyphPositions.Resize( numberOfGlyphs );
295 layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( numberOfCharacters - 1u ) ) );
297 // The initial glyph and the number of glyphs to layout.
298 layoutParameters.startGlyphIndex = 0u;
299 layoutParameters.numberOfGlyphs = numberOfGlyphs;
300 layoutParameters.startLineIndex = 0u;
301 layoutParameters.estimatedNumberOfLines = logicalModel->mParagraphInfo.Count();
303 layoutEngine.LayoutText( layoutParameters,
309 // 10) Reorder the lines
310 if( 0u != bidirectionalInfo.Count() )
312 Vector<BidirectionalLineInfoRun>& bidirectionalLineInfo = logicalModel->mBidirectionalLineInfo;
315 const Length numberOfLines = lines.Count();
317 // Reorder the lines.
318 bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
319 ReorderLines( bidirectionalInfo,
323 bidirectionalLineInfo );
325 // Set the bidirectional info per line into the layout parameters.
326 layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
327 layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
329 if( options.reorder )
331 // Re-layout the text. Reorder those lines with right to left characters.
332 layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
341 float alignmentOffset = 0.f;
342 layoutEngine.Align( textArea,
345 Text::HorizontalAlignment::BEGIN,
351 void ConfigureTextLabel( ControllerPtr controller )
353 TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
354 fontClient.SetDpi( 93u, 93u );
356 // Set the text layout as multi-line.
357 controller->GetLayoutEngine().SetLayout( Layout::Engine::MULTI_LINE_BOX );
359 // Set cursor's width to zero.
360 controller->GetLayoutEngine().SetCursorWidth( 0 );
362 InputMethodContext inputMethodContext = InputMethodContext::New();
363 // Disables the text input.
364 controller->EnableTextInput( NULL, inputMethodContext );
366 // Disables the vertical scrolling.
367 controller->SetVerticalScrollEnabled( false );
369 // Disables the horizontal scrolling.
370 controller->SetHorizontalScrollEnabled( false );
372 // Enable the text elide.
373 controller->SetTextElideEnabled( true );
376 void ConfigureTextField( ControllerPtr controller )
378 TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
379 fontClient.SetDpi( 93u, 93u );
381 // Creates a decorator.
382 Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
385 // Set the text layout as multi-line.
386 controller->GetLayoutEngine().SetLayout( Layout::Engine::SINGLE_LINE_BOX );
388 InputMethodContext inputMethodContext = InputMethodContext::New();
389 // Enables the text input.
390 controller->EnableTextInput( decorator, inputMethodContext );
392 // Enables the vertical scrolling after the text input has been enabled.
393 controller->SetVerticalScrollEnabled( false );
395 // Disables the horizontal scrolling.
396 controller->SetHorizontalScrollEnabled( true );
398 // No maximum number of characters.
399 controller->SetMaximumNumberOfCharacters( 50u );
401 // Disable the text elide.
402 controller->SetTextElideEnabled( false );
405 void ConfigureTextEditor( ControllerPtr controller )
407 TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
408 fontClient.SetDpi( 93u, 93u );
410 // Creates a decorator.
411 Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
414 // Set the text layout as multi-line.
415 controller->GetLayoutEngine().SetLayout( Layout::Engine::MULTI_LINE_BOX );
417 InputMethodContext inputMethodContext = InputMethodContext::New();
418 // Enables the text input.
419 controller->EnableTextInput( decorator, inputMethodContext );
421 // Enables the vertical scrolling after the text input has been enabled.
422 controller->SetVerticalScrollEnabled( true );
424 // Disables the horizontal scrolling.
425 controller->SetHorizontalScrollEnabled( false );
427 // No maximum number of characters.
428 controller->SetMaximumNumberOfCharacters( std::numeric_limits<Length>::max() );
430 // Disable the text elide.
431 controller->SetTextElideEnabled( false );
436 } // namespace Toolkit