2 * Copyright (c) 2015 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 <dali-toolkit/public-api/text/text-controller.h>
22 #include <dali-toolkit/public-api/text/character-set-conversion.h>
23 #include <dali-toolkit/public-api/text/layouts/layout-engine.h>
24 #include <dali-toolkit/public-api/text/logical-model.h>
25 #include <dali-toolkit/public-api/text/multi-language-support.h>
26 #include <dali-toolkit/public-api/text/script-run.h>
27 #include <dali-toolkit/public-api/text/shaper.h>
28 #include <dali-toolkit/public-api/text/text-view.h>
29 #include <dali-toolkit/public-api/text/visual-model.h>
32 #include <dali/public-api/text-abstraction/font-client.h>
44 struct Controller::Impl
48 mOperations( NO_OPERATION )
50 mLogicalModel = LogicalModel::New();
51 mVisualModel = VisualModel::New();
53 mView.SetVisualModel( mVisualModel );
55 mFontClient = TextAbstraction::FontClient::Get();
60 LogicalModelPtr mLogicalModel;
61 VisualModelPtr mVisualModel;
65 LayoutEngine mLayoutEngine;
67 TextAbstraction::FontClient mFontClient;
69 OperationsMask mOperations;
72 ControllerPtr Controller::New()
74 return ControllerPtr( new Controller() );
77 void Controller::SetText( const std::string& text )
79 // Keep until size negotiation
80 mImpl->mNewText = text;
81 mImpl->mOperations = ALL_OPERATIONS;
84 bool Controller::Relayout( const Vector2& size )
86 if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
88 // Not worth to relayout if width or height is equal to zero.
92 bool viewUpdated = false;
94 if( size != mControlSize )
96 viewUpdated = DoRelayout( size, mImpl->mOperations );
98 // Do not re-do any operation until something changes.
99 mImpl->mOperations = NO_OPERATION;
107 bool Controller::DoRelayout( const Vector2& size, OperationsMask operations )
109 bool viewUpdated( false );
111 Vector<Character> utf32Characters;
112 Length characterCount = 0u;
113 if( CONVERT_TO_UTF32 & operations )
115 std::string& text = mImpl->mNewText;
117 // Convert text into UTF-32
118 utf32Characters.Resize( text.size() );
120 // This is a bit horrible but std::string returns a (signed) char*
121 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
123 // Transform a text array encoded in utf8 into an array encoded in utf32.
124 // It returns the actual number of characters.
125 characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
126 utf32Characters.Resize( characterCount );
128 // Sets the text into the model.
129 mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount );
131 // Discard temporary text
135 const bool getScripts = GET_SCRIPTS & operations;
136 const bool validateFonts = VALIDATE_FONTS & operations;
138 Vector<ScriptRun> scripts;
139 Vector<FontRun> fonts;
140 if( getScripts || validateFonts )
142 // Validates the fonts assigned by the application or assigns default ones.
143 // It makes sure all the characters are going to be rendered by the correct font.
144 MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
148 // Retrieves the scripts used in the text.
149 multilanguageSupport.SetScripts( utf32Characters,
152 // Sets the scripts into the model.
153 mImpl->mLogicalModel->SetScripts( scripts.Begin(), scripts.Count() );
158 // Validates the fonts. If there is a character with no assigned font it sets a default one.
159 // After this call, fonts are validated.
160 multilanguageSupport.ValidateFonts( utf32Characters,
164 // Sets the fonts into the model.
165 mImpl->mLogicalModel->SetFonts( fonts.Begin(), fonts.Count() );
169 Vector<LineBreakInfo> lineBreakInfo;
170 if( GET_LINE_BREAKS & operations )
172 // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
173 // calculate the bidirectional info for each 'paragraph'.
174 // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
175 // is not shaped together).
176 lineBreakInfo.Resize( characterCount, TextAbstraction::LINE_NO_BREAK );
177 mImpl->mLogicalModel->SetLineBreakInfo( lineBreakInfo.Begin(), characterCount );
180 Vector<GlyphInfo> glyphs;
181 Vector<CharacterIndex> characterIndices;
182 Vector<Length> charactersPerGlyph;
183 if( SHAPE_TEXT & operations )
186 ShapeText( utf32Characters,
192 charactersPerGlyph );
195 if( GET_GLYPH_METRICS & operations )
197 TextAbstraction::FontClient::Get().GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
200 if( LAYOUT & operations )
202 if( 0u == glyphs.Count() )
204 const Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
206 glyphs.Resize( numberOfGlyphs );
207 characterIndices.Resize( numberOfGlyphs );
208 charactersPerGlyph.Resize( numberOfGlyphs );
210 mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
214 mImpl->mVisualModel->GetGlyphToCharacterMap( characterIndices.Begin(),
218 mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(),
223 // Update the visual model
224 mImpl->mLayoutEngine.UpdateVisualModel( size,
228 *mImpl->mVisualModel );
236 Vector3 Controller::GetNaturalSize()
238 // Operations that can be done only once until the text changes.
239 const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32 |
247 // Operations that need to be done if the size or the text changes.
248 const OperationsMask sizeOperations = static_cast<OperationsMask>( LAYOUT |
251 const float maxFloat = std::numeric_limits<float>::max();
252 DoRelayout( Vector2( maxFloat, maxFloat ),
253 static_cast<OperationsMask>( onlyOnceOperations |
256 // Do not do again the only once operations.
257 mImpl->mOperations = static_cast<OperationsMask>( mImpl->mOperations & ~onlyOnceOperations );
259 // Do the size related operations again.
260 mImpl->mOperations = static_cast<OperationsMask>( mImpl->mOperations | sizeOperations );
262 return Vector3( mImpl->mVisualModel->GetNaturalSize() );
265 float Controller::GetHeightForWidth( float width )
267 // Operations that can be done only once until the text changes.
268 const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32 |
276 // Operations that need to be done if the size or the text changes.
277 const OperationsMask sizeOperations = static_cast<OperationsMask>( LAYOUT |
280 DoRelayout( Size( width, 0.f ),
281 static_cast<OperationsMask>( onlyOnceOperations |
284 // Do not do again the only once operations.
285 mImpl->mOperations = static_cast<OperationsMask>( mImpl->mOperations & ~onlyOnceOperations );
287 // Do the size related operations again.
288 mImpl->mOperations = static_cast<OperationsMask>( mImpl->mOperations | sizeOperations );
290 return mImpl->mVisualModel->GetActualSize().height;
293 View& Controller::GetView()
298 LayoutEngine& Controller::GetLayoutEngine()
300 return mImpl->mLayoutEngine;
303 Controller::~Controller()
308 Controller::Controller()
312 mImpl = new Controller::Impl();
317 } // namespace Toolkit