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.
21 #include <dali-toolkit/internal/text/shaper.h>
22 #include <dali-toolkit-test-suite-utils.h>
23 #include <dali-toolkit/dali-toolkit.h>
24 #include <toolkit-text-model.h>
27 using namespace Toolkit;
30 // Tests the following function.
31 // void ShapeText( const Vector<Character>& text,
32 // const Vector<LineBreakInfo>& lineBreakInfo,
33 // const Vector<ScriptRun>& scripts,
34 // const Vector<FontRun>& fonts,
35 // CharacterIndex startCharacterIndex,
36 // GlyphIndex startGlyphIndex,
37 // Length numberOfCharacters,
38 // Vector<GlyphInfo>& glyphs,
39 // Vector<CharacterIndex>& glyphToCharacterMap,
40 // Vector<Length>& charactersPerGlyph,
41 // Vector<GlyphIndex>& newParagraphGlyphs );
43 //////////////////////////////////////////////////////////
50 FontId fontId; ///< Identifies the font containing the glyph
51 GlyphIndex index; ///< Uniquely identifies a glyph for a given FontId
52 float width; ///< The width of the glyph
53 float height; ///< The height of the glyph
54 float xBearing; ///< The distance from the cursor position to the leftmost border of the glyph
55 float yBearing; ///< The distance from the baseline to the topmost border of the glyph
56 float advance; ///< The distance to move the cursor for this glyph
57 float scaleFactor; ///< The scaling applied (fixed-size fonts only)
60 bool IsEqualGlyph ( const GlyphInfoData& glyphData, const GlyphInfo& glyph )
62 if( glyphData.fontId != glyph.fontId )
66 if( glyphData.index != glyph.index )
70 if( fabsf( glyphData.width - glyph.width ) > Math::MACHINE_EPSILON_1000 )
74 if( fabsf( glyphData.height - glyph.height ) > Math::MACHINE_EPSILON_1000 )
78 if( fabsf( glyphData.xBearing - glyph.xBearing ) > Math::MACHINE_EPSILON_1000 )
82 if( fabsf( glyphData.yBearing - glyph.yBearing ) > Math::MACHINE_EPSILON_1000 )
86 if( fabsf( glyphData.advance - glyph.advance ) > Math::MACHINE_EPSILON_1000 )
90 if( fabsf( glyphData.scaleFactor - glyph.scaleFactor ) > Math::MACHINE_EPSILON_1000 )
100 std::string description; ///< Description of the test.
101 std::string text; ///< input text.
102 uint32_t index; ///< The index from where to start to query the break info.
103 uint32_t numberOfCharacters; ///< The requested number of characters.
104 uint32_t expectedNumberOfGlyphs; ///< The expected number of glyphs.
105 GlyphInfoData* glyphs; ///< The glyphs.
106 CharacterIndex* characterIndices; ///< The character index for each glyph.
107 Length* charactersPerGlyph; ///< The characters per glyph.
108 uint32_t expectedNumberOfNewParagraphGlyphs; ///< The expected number of glyphs.
109 GlyphIndex* newParagraphGlyphs; ///< Indices to the new paragraphs glyphs.
112 bool ShapeInfoTest( const ShapeInfoData& data )
114 // 1) Create the model.
115 LogicalModelPtr logicalModel = LogicalModel::New();
116 VisualModelPtr visualModel = VisualModel::New();
117 Size textArea(100.f, 60.f);
120 const Vector<FontDescriptionRun> fontDescriptions;
121 const LayoutOptions options;
122 CreateTextModel( data.text,
130 // 2) Clear the model.
132 Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
133 Vector<CharacterIndex>& glyphToCharacter = visualModel->mGlyphsToCharacters;
134 Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
135 Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
136 Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
138 // Get the glyph index.
139 GlyphIndex glyphIndex = 0u;
140 if( 0u != visualModel->mCharactersToGlyph.Count() )
142 glyphIndex = *( visualModel->mCharactersToGlyph.Begin() + data.index );
144 const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
145 const Length numberOfGlyphs = *( visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex ) + *( visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex ) - glyphIndex;
147 // Erase the glyph info from the text model.
148 // Got from the ShapeText() function.
149 glyphs.Erase( glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs );
150 glyphToCharacter.Erase( glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs );
151 charactersPerGlyph.Erase( charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs );
153 // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
154 charactersToGlyph.Erase( charactersToGlyph.Begin() + data.index,
155 charactersToGlyph.Begin() + data.index + data.numberOfCharacters );
156 glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.index,
157 glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters );
159 // Update the glyph to character indices.
160 for( Vector<CharacterIndex>::Iterator it = glyphToCharacter.Begin() + glyphIndex,
161 endIt = glyphToCharacter.End();
165 CharacterIndex& index = *it;
166 index -= data.numberOfCharacters;
171 // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
172 for( Vector<GlyphInfo>::Iterator it = glyphs.Begin(),
173 endIt = glyphs.End();
177 GlyphInfo& info = *it;
182 info.scaleFactor = 0.f;
185 // 3) Call the ShapeText() function.
187 Vector<GlyphIndex> newParagraphGlyphs;
189 ShapeText( logicalModel->mText,
190 logicalModel->mLineBreakInfo,
191 logicalModel->mScriptRuns,
192 logicalModel->mFontRuns,
195 data.numberOfCharacters,
199 newParagraphGlyphs );
201 // Clear the advance of the new paragraph glyphs.
202 for( Vector<GlyphIndex>::Iterator it = newParagraphGlyphs.Begin(),
203 endIt = newParagraphGlyphs.End();
207 GlyphInfo& info = *( glyphs.Begin() + *it );
211 // 4) Compare the results.
213 if( data.expectedNumberOfGlyphs != glyphs.Count() )
215 std::cout << " Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
219 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
221 if( !IsEqualGlyph( data.glyphs[index], glyphs[index] ) )
223 std::cout << " different glyph info, index : " << index << std::endl;
228 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
230 if( data.characterIndices[index] != glyphToCharacter[index] )
232 std::cout << " different character index, index : " << index << std::endl;
237 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
239 if( data.charactersPerGlyph[index] != charactersPerGlyph[index] )
241 std::cout << " different character per glyph, index : " << index << std::endl;
246 if( data.expectedNumberOfNewParagraphGlyphs != newParagraphGlyphs.Count() )
248 std::cout << " Different number of new paragraph glyphs : " << newParagraphGlyphs.Count() << ", expected : " << data.expectedNumberOfNewParagraphGlyphs << std::endl;
252 for( unsigned int index = 0u; index < data.expectedNumberOfNewParagraphGlyphs; ++index )
254 if( data.newParagraphGlyphs[index] != newParagraphGlyphs[index] )
256 std::cout << " different new paragraph glyph, index : " << index << std::endl;
266 //////////////////////////////////////////////////////////
268 int UtcDaliTextShape(void)
270 ToolkitTestApplication application;
271 tet_infoline(" UtcDaliTextShape");
273 struct GlyphInfoData glyphs02[] =
275 { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
276 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
277 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
278 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
279 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
280 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
281 { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
282 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
283 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
284 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
285 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
288 CharacterIndex characterIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
289 Length charactersPerGlyph02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
291 struct GlyphInfoData glyphs03[] =
293 { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
294 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
295 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
296 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
297 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
298 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
299 { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
300 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
301 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
302 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
303 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
304 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
305 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
306 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
307 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
308 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
309 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
312 CharacterIndex characterIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u };
313 Length charactersPerGlyph03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
314 CharacterIndex newParagraphGlyphs03[] = { 11u, 16u };
316 struct GlyphInfoData glyphs04[] =
318 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
319 { 2u, 123u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
320 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
321 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
322 { 2u, 150u, 0.f, 0.f, 0.f, 0.f, 14.f, 0.f },
323 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
324 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
325 { 2u, 151u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
326 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
327 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
328 { 2u, 147u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
329 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
332 CharacterIndex characterIndices04[] = { 0u, 0u, 0u, 2u, 2u, 2u, 4u, 4u, 4u, 6u, 6u, 6u };
333 Length charactersPerGlyph04[] = { 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u };
335 struct GlyphInfoData glyphs05[] =
337 { 1u, 47u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
338 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
339 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
340 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
341 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
342 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
343 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
344 { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
345 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
346 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
347 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
348 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
349 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
350 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
351 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
352 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
353 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
354 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
355 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
356 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
357 { 1u, 87u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
358 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
359 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
360 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
361 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
362 { 1u, 87u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
363 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
364 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
365 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
366 { 1u, 84u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
367 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
368 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
369 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
370 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
371 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
372 { 1u, 5034u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
373 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
374 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
375 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
376 { 1u, 69u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
377 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
378 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
379 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
380 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
381 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
382 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
383 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
384 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
385 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
386 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
387 { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
388 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
389 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
390 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
391 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
392 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
393 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
394 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
395 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
396 { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
397 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
398 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
399 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
400 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
401 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
402 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
403 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
404 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
405 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
406 { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
407 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
408 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
409 { 1u, 17u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
410 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
413 CharacterIndex characterIndices05[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
414 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
415 20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u,
416 30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u,
417 41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u,
418 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u,
419 61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u,
420 71u, 72u, 73u, 74u };
421 Length charactersPerGlyph05[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
422 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
423 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
424 1u, 1u, 1u, 1u, 1u, 2u, 1u, 1u, 1u, 1u,
425 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
426 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
427 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
429 CharacterIndex newParagraphGlyphs05[] = { 26u };
430 CharacterIndex newParagraphGlyphs06[] = { 49u };
431 CharacterIndex newParagraphGlyphs07[] = { 73u };
433 struct ShapeInfoData data[] =
455 charactersPerGlyph02,
460 "Latin script. Some paragraphs.",
461 "Hello world\ndemo\n",
467 charactersPerGlyph03,
472 "Malayalam script. More glyphs than characters.",
479 charactersPerGlyph04,
484 "Latin script with some paragraphs. Update initial paragraph.",
485 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
491 charactersPerGlyph05,
496 "Latin script with some paragraphs. Update mid paragraph.",
497 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
503 charactersPerGlyph05,
508 "Latin script with some paragraphs. Update final paragraph.",
509 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
515 charactersPerGlyph05,
520 const unsigned int numberOfTests = 7u;
522 for( unsigned int index = 0u; index < numberOfTests; ++index )
524 if( !ShapeInfoTest( data[index] ) )
526 tet_result(TET_FAIL);
530 tet_result(TET_PASS);