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 CreateTextModel( data.text,
126 // 2) Clear the model.
128 Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
129 Vector<CharacterIndex>& glyphToCharacter = visualModel->mGlyphsToCharacters;
130 Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
131 Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
132 Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
134 // Get the glyph index.
135 GlyphIndex glyphIndex = 0u;
136 if( 0u != visualModel->mCharactersToGlyph.Count() )
138 glyphIndex = *( visualModel->mCharactersToGlyph.Begin() + data.index );
140 const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
141 const Length numberOfGlyphs = *( visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex ) + *( visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex ) - glyphIndex;
143 // Erase the glyph info from the text model.
144 // Got from the ShapeText() function.
145 glyphs.Erase( glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs );
146 glyphToCharacter.Erase( glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs );
147 charactersPerGlyph.Erase( charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs );
149 // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
150 charactersToGlyph.Erase( charactersToGlyph.Begin() + data.index,
151 charactersToGlyph.Begin() + data.index + data.numberOfCharacters );
152 glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.index,
153 glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters );
155 // Update the glyph to character indices.
156 for( Vector<CharacterIndex>::Iterator it = glyphToCharacter.Begin() + glyphIndex,
157 endIt = glyphToCharacter.End();
161 CharacterIndex& index = *it;
162 index -= data.numberOfCharacters;
167 // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
168 for( Vector<GlyphInfo>::Iterator it = glyphs.Begin(),
169 endIt = glyphs.End();
173 GlyphInfo& info = *it;
178 info.scaleFactor = 0.f;
181 // 3) Call the ShapeText() function.
183 Vector<GlyphIndex> newParagraphGlyphs;
185 ShapeText( logicalModel->mText,
186 logicalModel->mLineBreakInfo,
187 logicalModel->mScriptRuns,
188 logicalModel->mFontRuns,
191 data.numberOfCharacters,
195 newParagraphGlyphs );
197 // Clear the advance of the new paragraph glyphs.
198 for( Vector<GlyphIndex>::Iterator it = newParagraphGlyphs.Begin(),
199 endIt = newParagraphGlyphs.End();
203 GlyphInfo& info = *( glyphs.Begin() + *it );
207 // 4) Compare the results.
209 if( data.expectedNumberOfGlyphs != glyphs.Count() )
211 std::cout << " Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
215 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
217 if( !IsEqualGlyph( data.glyphs[index], glyphs[index] ) )
219 std::cout << " different glyph info, index : " << index << std::endl;
224 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
226 if( data.characterIndices[index] != glyphToCharacter[index] )
228 std::cout << " different character index, index : " << index << std::endl;
233 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
235 if( data.charactersPerGlyph[index] != charactersPerGlyph[index] )
237 std::cout << " different character per glyph, index : " << index << std::endl;
242 if( data.expectedNumberOfNewParagraphGlyphs != newParagraphGlyphs.Count() )
244 std::cout << " Different number of new paragraph glyphs : " << newParagraphGlyphs.Count() << ", expected : " << data.expectedNumberOfNewParagraphGlyphs << std::endl;
248 for( unsigned int index = 0u; index < data.expectedNumberOfNewParagraphGlyphs; ++index )
250 if( data.newParagraphGlyphs[index] != newParagraphGlyphs[index] )
252 std::cout << " different new paragraph glyph, index : " << index << std::endl;
262 //////////////////////////////////////////////////////////
264 int UtcDaliTextShape(void)
266 ToolkitTestApplication application;
267 tet_infoline(" UtcDaliTextShape");
269 struct GlyphInfoData glyphs02[] =
271 { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
272 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
273 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
274 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
275 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
276 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
277 { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
278 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
279 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
280 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
281 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
284 CharacterIndex characterIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
285 Length charactersPerGlyph02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
287 struct GlyphInfoData glyphs03[] =
289 { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
290 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
291 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
292 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
293 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
294 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
295 { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
296 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
297 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
298 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
299 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
300 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
301 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
302 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
303 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
304 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
305 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
308 CharacterIndex characterIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u };
309 Length charactersPerGlyph03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
310 CharacterIndex newParagraphGlyphs03[] = { 11u, 16u };
312 struct GlyphInfoData glyphs04[] =
314 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
315 { 2u, 123u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
316 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
317 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
318 { 2u, 150u, 0.f, 0.f, 0.f, 0.f, 14.f, 0.f },
319 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
320 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
321 { 2u, 151u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
322 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
323 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
324 { 2u, 147u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
325 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
328 CharacterIndex characterIndices04[] = { 0u, 0u, 0u, 2u, 2u, 2u, 4u, 4u, 4u, 6u, 6u, 6u };
329 Length charactersPerGlyph04[] = { 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u };
331 struct GlyphInfoData glyphs05[] =
333 { 1u, 47u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
334 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
335 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
336 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
337 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
338 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
339 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
340 { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
341 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
342 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
343 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
344 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
345 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
346 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
347 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
348 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
349 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
350 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
351 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
352 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
353 { 1u, 87u, 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, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
356 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
357 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
358 { 1u, 87u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
359 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
360 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
361 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
362 { 1u, 84u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
363 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
364 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
365 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
366 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
367 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
368 { 1u, 5034u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
369 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
370 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
371 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
372 { 1u, 69u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
373 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
374 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
375 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
376 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
377 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
378 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
379 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
380 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
381 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
382 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
383 { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
384 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
385 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
386 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
387 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
388 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
389 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
390 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
391 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
392 { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
393 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
394 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
395 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
396 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
397 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
398 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
399 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
400 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
401 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
402 { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
403 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
404 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
405 { 1u, 17u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
406 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
409 CharacterIndex characterIndices05[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
410 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
411 20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u,
412 30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u,
413 41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u,
414 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u,
415 61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u,
416 71u, 72u, 73u, 74u };
417 Length charactersPerGlyph05[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
418 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
419 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
420 1u, 1u, 1u, 1u, 1u, 2u, 1u, 1u, 1u, 1u,
421 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,
425 CharacterIndex newParagraphGlyphs05[] = { 26u };
426 CharacterIndex newParagraphGlyphs06[] = { 49u };
427 CharacterIndex newParagraphGlyphs07[] = { 73u };
429 struct ShapeInfoData data[] =
451 charactersPerGlyph02,
456 "Latin script. Some paragraphs.",
457 "Hello world\ndemo\n",
463 charactersPerGlyph03,
468 "Malayalam script. More glyphs than characters.",
475 charactersPerGlyph04,
480 "Latin script with some paragraphs. Update initial paragraph.",
481 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
487 charactersPerGlyph05,
492 "Latin script with some paragraphs. Update mid paragraph.",
493 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
499 charactersPerGlyph05,
504 "Latin script with some paragraphs. Update final paragraph.",
505 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
511 charactersPerGlyph05,
516 const unsigned int numberOfTests = 7u;
518 for( unsigned int index = 0u; index < numberOfTests; ++index )
520 if( !ShapeInfoTest( data[index] ) )
522 tet_result(TET_FAIL);
526 tet_result(TET_PASS);