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/layouts/layout-engine.h>
22 #include <dali/public-api/math/vector2.h>
23 #include <dali/public-api/text-abstraction/font-client.h>
26 #include <dali-toolkit/public-api/text/logical-model.h>
27 #include <dali-toolkit/public-api/text/visual-model.h>
38 struct LayoutEngine::Impl
41 : mLayout( LayoutEngine::SINGLE_LINE_BOX )
43 mFontClient = TextAbstraction::FontClient::Get();
46 void UpdateVisualModel( const Vector2& boundingBox, const LogicalModel& logicalModel, VisualModel& visualModel )
48 // TODO Switch between different layouts
50 TextAbstraction::FontId fontId = mFontClient.GetFontId( "/usr/share/fonts/truetype/ubuntu-font-family/UbuntuMono-R.ttf", 13*64 );
52 const Length characterCount = logicalModel.GetNumberOfCharacters();
54 Vector<GlyphInfo> glyphs;
55 glyphs.Reserve( characterCount );
57 Vector<CharacterIndex> characterIndices;
58 characterIndices.Reserve( characterCount );
60 std::vector<Length> charactersPerGlyph;
61 charactersPerGlyph.assign( characterCount, 1 );
63 for( unsigned int i=0; i<characterCount; ++i )
66 logicalModel.GetText( i, &charcode, 1 );
68 // TODO - Perform shaping to get correct glyph indices
69 GlyphIndex glyphIndex = mFontClient.GetGlyphIndex( fontId, charcode );
71 glyphs.PushBack( GlyphInfo(fontId, glyphIndex) );
72 characterIndices.PushBack( 1 );
75 if( mFontClient.GetGlyphMetrics( &glyphs[0], glyphs.Size() ) )
77 visualModel.SetGlyphs( &glyphs[0],
79 &charactersPerGlyph[0],
82 UpdateGlyphPositions( boundingBox, visualModel );
86 void UpdateGlyphPositions( const Vector2& boundingBox, VisualModel& visualModel )
88 if( LayoutEngine::SINGLE_LINE_BOX == mLayout )
90 SingleLineLayout( boundingBox, visualModel );
94 MultiLineLayout( boundingBox, visualModel );
98 // TODO - Rewrite this to handle bidi
99 void SingleLineLayout( const Vector2& boundingBox, VisualModel& visualModel )
101 Length glyphCount = visualModel.GetNumberOfGlyphs();
103 std::vector<Vector2> glyphPositions;
104 glyphPositions.reserve( glyphCount );
108 // FIXME Single font assumption
109 Text::FontMetrics fontMetrics;
110 GlyphInfo firstGlyph;
111 visualModel.GetGlyphs( 0, &firstGlyph, 1 );
112 mFontClient.GetFontMetrics( firstGlyph.fontId, fontMetrics );
115 float penY( fontMetrics.ascender ); // Move to baseline
117 for( unsigned int i=0; i<glyphCount; ++i )
120 visualModel.GetGlyphs( i, &glyph, 1 );
122 glyphPositions.push_back( Vector2( penX + glyph.xBearing,
123 penY - glyph.yBearing ) );
125 penX += glyph.advance;
128 visualModel.SetGlyphPositions( &glyphPositions[0], glyphCount );
132 // TODO - Rewrite this to handle bidi
133 void MultiLineLayout( const Vector2& boundingBox, VisualModel& visualModel )
135 Length glyphCount = visualModel.GetNumberOfGlyphs();
137 std::vector<Vector2> glyphPositions;
138 glyphPositions.reserve( glyphCount );
142 // FIXME Single font assumption
143 Text::FontMetrics fontMetrics;
144 GlyphInfo firstGlyph;
145 visualModel.GetGlyphs( 0, &firstGlyph, 1 );
146 mFontClient.GetFontMetrics( firstGlyph.fontId, fontMetrics );
149 float penY( fontMetrics.ascender ); // Move to baseline
152 while( i < glyphCount )
154 // Skip initial whitespace
155 for( ; i<glyphCount; ++i )
158 visualModel.GetGlyphs( i, &glyph, 1 );
160 if( glyph.width > 0 &&
167 glyphPositions.push_back( Vector2( penX + glyph.xBearing,
168 penY - glyph.yBearing ) );
172 // Find last glyph for the next line
173 unsigned int endIndex = i;
174 float endPenX = penX;
176 for( ; j<glyphCount; ++j )
179 visualModel.GetGlyphs( j, &glyph, 1 );
181 endPenX += glyph.advance;
183 if( glyph.width <= 0 ||
186 // Potential line end found
189 else if( endPenX > boundingBox.width )
195 // If end of text or no whitespace found
196 if( glyphCount == j ||
202 for( ; i<endIndex; ++i )
205 visualModel.GetGlyphs( i, &glyph, 1 );
207 glyphPositions.push_back( Vector2( penX + glyph.xBearing,
208 penY - glyph.yBearing ) );
210 penX += glyph.advance;
215 penY += fontMetrics.height;
218 visualModel.SetGlyphPositions( &glyphPositions[0], glyphCount );
222 unsigned int mLayout;
224 TextAbstraction::FontClient mFontClient;
227 LayoutEngine::LayoutEngine()
230 mImpl = new LayoutEngine::Impl();
233 LayoutEngine::~LayoutEngine()
238 void LayoutEngine::SetLayout( Layout layout )
240 mImpl->mLayout = layout;
243 void LayoutEngine::UpdateVisualModel( const Vector2& boundingBox, const LogicalModel& logicalModel, VisualModel& visualModel )
245 mImpl->UpdateVisualModel( boundingBox, logicalModel, visualModel );
250 } // namespace Toolkit