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-utils.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;
116 VisualModelPtr visualModel;
118 Size textArea(100.f, 60.f);
121 const Vector<FontDescriptionRun> fontDescriptions;
122 const LayoutOptions options;
123 CreateTextModel( data.text,
132 // 2) Clear the model.
134 Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
135 Vector<CharacterIndex>& glyphToCharacter = visualModel->mGlyphsToCharacters;
136 Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
137 Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
138 Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
140 // Get the glyph index.
141 GlyphIndex glyphIndex = 0u;
142 if( 0u != visualModel->mCharactersToGlyph.Count() )
144 glyphIndex = *( visualModel->mCharactersToGlyph.Begin() + data.index );
146 const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
147 const Length numberOfGlyphs = *( visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex ) + *( visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex ) - glyphIndex;
149 // Erase the glyph info from the text model.
150 // Got from the ShapeText() function.
151 glyphs.Erase( glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs );
152 glyphToCharacter.Erase( glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs );
153 charactersPerGlyph.Erase( charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs );
155 // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
156 charactersToGlyph.Erase( charactersToGlyph.Begin() + data.index,
157 charactersToGlyph.Begin() + data.index + data.numberOfCharacters );
158 glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.index,
159 glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters );
161 // Update the glyph to character indices.
162 for( Vector<CharacterIndex>::Iterator it = glyphToCharacter.Begin() + glyphIndex,
163 endIt = glyphToCharacter.End();
167 CharacterIndex& index = *it;
168 index -= data.numberOfCharacters;
173 // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
174 for( Vector<GlyphInfo>::Iterator it = glyphs.Begin(),
175 endIt = glyphs.End();
179 GlyphInfo& info = *it;
184 info.scaleFactor = 0.f;
187 // 3) Call the ShapeText() function.
189 Vector<GlyphIndex> newParagraphGlyphs;
191 ShapeText( logicalModel->mText,
192 logicalModel->mLineBreakInfo,
193 logicalModel->mScriptRuns,
194 logicalModel->mFontRuns,
197 data.numberOfCharacters,
201 newParagraphGlyphs );
203 // Clear the advance of the new paragraph glyphs.
204 for( Vector<GlyphIndex>::Iterator it = newParagraphGlyphs.Begin(),
205 endIt = newParagraphGlyphs.End();
209 GlyphInfo& info = *( glyphs.Begin() + *it );
213 // 4) Compare the results.
215 if( data.expectedNumberOfGlyphs != glyphs.Count() )
217 std::cout << " Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
221 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
223 if( !IsEqualGlyph( data.glyphs[index], glyphs[index] ) )
225 std::cout << " different glyph info, index : " << index << std::endl;
230 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
232 if( data.characterIndices[index] != glyphToCharacter[index] )
234 std::cout << " different character index, index : " << index << std::endl;
239 for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
241 if( data.charactersPerGlyph[index] != charactersPerGlyph[index] )
243 std::cout << " different character per glyph, index : " << index << std::endl;
248 if( data.expectedNumberOfNewParagraphGlyphs != newParagraphGlyphs.Count() )
250 std::cout << " Different number of new paragraph glyphs : " << newParagraphGlyphs.Count() << ", expected : " << data.expectedNumberOfNewParagraphGlyphs << std::endl;
254 for( unsigned int index = 0u; index < data.expectedNumberOfNewParagraphGlyphs; ++index )
256 if( data.newParagraphGlyphs[index] != newParagraphGlyphs[index] )
258 std::cout << " different new paragraph glyph, index : " << index << std::endl;
268 //////////////////////////////////////////////////////////
270 int UtcDaliTextShape(void)
272 tet_infoline(" UtcDaliTextShape");
274 struct GlyphInfoData glyphs02[] =
276 { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
277 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
278 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
279 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
280 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
281 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
282 { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
283 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
284 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
285 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
286 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
289 CharacterIndex characterIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
290 Length charactersPerGlyph02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
292 struct GlyphInfoData glyphs03[] =
294 { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
295 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
296 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
297 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
298 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
299 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
300 { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
301 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
302 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
303 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
304 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
305 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
306 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
307 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
308 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
309 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
310 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
313 CharacterIndex characterIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u };
314 Length charactersPerGlyph03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
315 CharacterIndex newParagraphGlyphs03[] = { 11u, 16u };
317 struct GlyphInfoData glyphs04[] =
319 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
320 { 2u, 123u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
321 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
322 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
323 { 2u, 150u, 0.f, 0.f, 0.f, 0.f, 14.f, 0.f },
324 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
325 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
326 { 2u, 151u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
327 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
328 { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
329 { 2u, 147u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
330 { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
333 CharacterIndex characterIndices04[] = { 0u, 0u, 0u, 2u, 2u, 2u, 4u, 4u, 4u, 6u, 6u, 6u };
334 Length charactersPerGlyph04[] = { 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u };
336 struct GlyphInfoData glyphs05[] =
338 { 1u, 47u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
339 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
340 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
341 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
342 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
343 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
344 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
345 { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
346 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
347 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
348 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
349 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
350 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
351 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
352 { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
353 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
354 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
355 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
356 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
357 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
358 { 1u, 87u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
359 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
360 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
361 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
362 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
363 { 1u, 87u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
364 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
365 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
366 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
367 { 1u, 84u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
368 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
369 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
370 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
371 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
372 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
373 { 1u, 5034u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
374 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
375 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
376 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
377 { 1u, 69u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
378 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
379 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
380 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
381 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
382 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
383 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
384 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
385 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
386 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
387 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
388 { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
389 { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
390 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
391 { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
392 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
393 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
394 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
395 { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
396 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
397 { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
398 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
399 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
400 { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
401 { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
402 { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
403 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
404 { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
405 { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
406 { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
407 { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
408 { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
409 { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
410 { 1u, 17u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
411 { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
414 CharacterIndex characterIndices05[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
415 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
416 20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u,
417 30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u,
418 41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u,
419 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u,
420 61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u,
421 71u, 72u, 73u, 74u };
422 Length charactersPerGlyph05[] = { 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, 1u, 1u, 1u, 1u, 1u,
425 1u, 1u, 1u, 1u, 1u, 2u, 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,
428 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
430 CharacterIndex newParagraphGlyphs05[] = { 26u };
431 CharacterIndex newParagraphGlyphs06[] = { 49u };
432 CharacterIndex newParagraphGlyphs07[] = { 73u };
434 struct ShapeInfoData data[] =
456 charactersPerGlyph02,
461 "Latin script. Some paragraphs.",
462 "Hello world\ndemo\n",
468 charactersPerGlyph03,
473 "Malayalam script. More glyphs than characters.",
480 charactersPerGlyph04,
485 "Latin script with some paragraphs. Update initial paragraph.",
486 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
492 charactersPerGlyph05,
497 "Latin script with some paragraphs. Update mid paragraph.",
498 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
504 charactersPerGlyph05,
509 "Latin script with some paragraphs. Update final paragraph.",
510 "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
516 charactersPerGlyph05,
521 const unsigned int numberOfTests = 7u;
523 for( unsigned int index = 0u; index < numberOfTests; ++index )
525 ToolkitTestApplication application;
526 if( !ShapeInfoTest( data[index] ) )
528 tet_result(TET_FAIL);
532 tet_result(TET_PASS);