From e5a56dace042712c1d89015bcb43942dfb237af8 Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Wed, 9 Mar 2016 15:40:46 +0000 Subject: [PATCH] TextModel - Layout a given range of characters inside a text. Change-Id: Ie854d18af10553f2a4381ab6e60fc91f68c21ef0 Signed-off-by: Victor Cebollada --- .../src/dali-toolkit-internal/CMakeLists.txt | 1 + .../utc-Dali-BidirectionalSupport.cpp | 65 +- .../utc-Dali-LogicalModel.cpp | 4 + .../dali-toolkit-internal/utc-Dali-Text-Layout.cpp | 4978 ++++++++++++++++++++ .../utc-Dali-Text-MultiLanguage.cpp | 1 - .../utc-Dali-Text-Shaping.cpp | 4 + .../dali-toolkit-internal/utc-Dali-VisualModel.cpp | 8 + .../dali-toolkit-test-utils/toolkit-text-model.cpp | 40 +- .../dali-toolkit-test-utils/toolkit-text-model.h | 22 +- .../controls/text-controls/text-editor-impl.cpp | 6 +- .../controls/text-controls/text-field-impl.cpp | 6 +- .../controls/text-controls/text-label-impl.cpp | 3 +- .../internal/text/layouts/layout-engine.cpp | 715 ++- dali-toolkit/internal/text/layouts/layout-engine.h | 18 +- .../internal/text/layouts/layout-parameters.h | 47 +- .../text/rendering/atlas/text-atlas-renderer.cpp | 2 +- .../internal/text/text-controller-impl.cpp | 32 +- dali-toolkit/internal/text/text-controller-impl.h | 4 +- dali-toolkit/internal/text/text-controller.cpp | 119 +- dali-toolkit/internal/text/text-run-container.h | 117 +- dali-toolkit/internal/text/text-view-interface.h | 4 +- dali-toolkit/internal/text/text-view.cpp | 4 +- dali-toolkit/internal/text/text-view.h | 4 +- dali-toolkit/internal/text/visual-model-impl.cpp | 10 +- dali-toolkit/internal/text/visual-model-impl.h | 10 +- 25 files changed, 5903 insertions(+), 321 deletions(-) create mode 100644 automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 0852234..7696421 100644 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -15,6 +15,7 @@ SET(TC_SOURCES utc-Dali-BidirectionalSupport.cpp utc-Dali-Text-Shaping.cpp utc-Dali-VisualModel.cpp + utc-Dali-Text-Layout.cpp ) # Append list of test harness files (Won't get parsed for test cases) diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp index 92ee580..f61e539 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp @@ -86,6 +86,8 @@ struct ReorderLinesData unsigned int numberOfCharacters; ///< The number of characters. unsigned int numberOfLineInfo; ///< The number or reordered lines. BidiLineData* bidiLineData; ///< The bidirectional line info. + unsigned int numberOfLines; ///< The number of laid-out lines. + bool* lineDirections; ///< The directions of the lines. }; struct GetMirroredTextData @@ -115,8 +117,12 @@ bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data ) Size layoutSize; // Create the model. + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); @@ -215,8 +221,12 @@ bool ReorderLinesTest( const ReorderLinesData& data ) Size layoutSize; // Create the model. + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); @@ -302,6 +312,26 @@ bool ReorderLinesTest( const ReorderLinesData& data ) } } + if( data.numberOfLines != visualModel->mLines.Count() ) + { + std::cout << "Different number of lines : " << visualModel->mLines.Count() << ", expected : " << data.numberOfLines << std::endl; + + unsigned int index = 0u; + for( Vector::ConstIterator it = visualModel->mLines.Begin(), + endIt = visualModel->mLines.End(); + it != endIt; + ++it, ++index ) + { + const LineRun& line = *it; + + if( line.direction != *( data.lineDirections + index ) ) + { + std::cout << " Different line direction : " << line.direction << ", expected : " << *( data.lineDirections + index ) << std::endl; + return false; + } + } + } + return true; } @@ -314,8 +344,12 @@ bool GetMirroredTextTest( const GetMirroredTextData& data ) Size layoutSize; // Create the model. + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); @@ -382,8 +416,12 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data ) Size layoutSize; // Create the model. + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); @@ -673,6 +711,9 @@ int UtcDaliReorderLines(void) }, }; + bool directions02[] = { false, false, false, false, false, false }; + bool directions03[] = { false, false, false, false, false, true, true, true, true, true, false, false, false, false, false, true, true, true, true, true }; + struct ReorderLinesData data[] = { { @@ -681,7 +722,9 @@ int UtcDaliReorderLines(void) 0u, 0u, 0u, - bidiLine01 + bidiLine01, + 0u, + NULL }, { "Left to right text only.", @@ -689,7 +732,9 @@ int UtcDaliReorderLines(void) 0u, 51u, 0u, - bidiLine02 + bidiLine02, + 6u, + directions02 }, { "Bidirectional paragraphs.", @@ -697,7 +742,9 @@ int UtcDaliReorderLines(void) 0u, 195u, 16u, - bidiLine03 + bidiLine03, + 20u, + directions03 }, { "Bidirectional paragraphs. Update initial paragraphs.", @@ -705,7 +752,9 @@ int UtcDaliReorderLines(void) 0u, 44u, 16u, - bidiLine03 + bidiLine03, + 20u, + directions03 }, { "Bidirectional paragraphs. Update middle paragraphs.", @@ -713,7 +762,9 @@ int UtcDaliReorderLines(void) 44u, 54u, 16u, - bidiLine03 + bidiLine03, + 20u, + directions03 }, { "Bidirectional paragraphs. Update final paragraphs.", @@ -721,7 +772,9 @@ int UtcDaliReorderLines(void) 142u, 53u, 16u, - bidiLine03 + bidiLine03, + 20u, + directions03 }, }; const unsigned int numberOfTests = 6u; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp index b18e1e6..9ec9930 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp @@ -60,8 +60,12 @@ bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data ) Size layoutSize; // Create the model with the whole text. + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, data.textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp new file mode 100644 index 0000000..d849430 --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp @@ -0,0 +1,4978 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Toolkit; +using namespace Text; + +// Tests the LayoutEngine methods. + +////////////////////////////////////////////////////////// + +namespace +{ + +const std::string DEFAULT_FONT_DIR( "/resources/fonts" ); + +struct LayoutTextData +{ + std::string description; + std::string text; + Size textArea; + unsigned int numberOfFonts; + FontDescriptionRun* fontDescriptions; + Size layoutSize; + unsigned int totalNumberOfGlyphs; + float* positions; + unsigned int numberOfLines; + LineRun* lines; + LayoutEngine::Layout layout; + unsigned int startIndex; + unsigned int numberOfGlyphs; + bool ellipsis:1; + bool updated:1; +}; + +void Print( const LineRun& line ) +{ + std::cout << " glyph run, index : " << line.glyphRun.glyphIndex << ", num glyphs : " << line.glyphRun.numberOfGlyphs << std::endl; + std::cout << " character run, index : " << line.characterRun.characterIndex << ", num chars : " << line.characterRun.numberOfCharacters << std::endl; + std::cout << " width : " << line.width << std::endl; + std::cout << " ascender : " << line.ascender << std::endl; + std::cout << " descender : " << line.descender << std::endl; + std::cout << " extraLength : " << line.extraLength << std::endl; + std::cout << " alignmentOffset : " << line.alignmentOffset << std::endl; + std::cout << " direction : " << line.direction << std::endl; + std::cout << " ellipsis : " << line.ellipsis << std::endl; +} + +bool LayoutTextTest( const LayoutTextData& data ) +{ + // Load some fonts. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" ); + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" ); + + // 1) Create the model. + LogicalModelPtr logicalModel = LogicalModel::New(); + VisualModelPtr visualModel = VisualModel::New(); + Size layoutSize; + + Vector fontDescriptionRuns; + if( 0u != data.numberOfFonts ) + { + fontDescriptionRuns.Insert( fontDescriptionRuns.End(), + data.fontDescriptions, + data.fontDescriptions + data.numberOfFonts ); + } + + LayoutOptions options; + options.reorder = false; + options.align = false; + CreateTextModel( data.text, + data.textArea, + fontDescriptionRuns, + options, + layoutSize, + logicalModel, + visualModel ); + + // 2) Clear the layout. + Vector& lines = visualModel->mLines; + + const Length numberOfCharacters = logicalModel->mText.Count(); + const bool isLastNewParagraph = ( 0u == numberOfCharacters ) ? false : TextAbstraction::IsNewParagraph( *( logicalModel->mText.Begin() + ( numberOfCharacters - 1u ) ) ); + const GlyphIndex lastGlyphIndex = data.startIndex + data.numberOfGlyphs - 1u; + const bool removeLastLine = isLastNewParagraph && ( lastGlyphIndex + 1u == visualModel->mGlyphs.Count() ); + + LineIndex startRemoveIndex = 0u; + + if( 0u != lines.Count() ) + { + startRemoveIndex = lines.Count(); + LineIndex endRemoveIndex = startRemoveIndex; + ClearGlyphRuns( data.startIndex, + lastGlyphIndex + ( removeLastLine ? 1u : 0u ), + lines, + startRemoveIndex, + endRemoveIndex ); + + // Update the character runs of the lines. + const CharacterIndex* const glyphsToCharactersBuffer = visualModel->mGlyphsToCharacters.Begin(); + const Length* const charactersPerGlyph = visualModel->mCharactersPerGlyph.Begin(); + const CharacterIndex startCharacterIndex = *( glyphsToCharactersBuffer + data.startIndex ); + const CharacterIndex lastCharacterIndex = *( glyphsToCharactersBuffer + lastGlyphIndex ) + *( charactersPerGlyph + lastGlyphIndex ) - 1u; + ClearCharacterRuns( startCharacterIndex, + lastCharacterIndex + ( removeLastLine ? 1u : 0u ), + lines, + startRemoveIndex, + endRemoveIndex ); + + lines.Erase( lines.Begin() + startRemoveIndex, + lines.Begin() + endRemoveIndex ); + } + + Vector& glyphPositions = visualModel->mGlyphPositions; + + glyphPositions.Erase( glyphPositions.Begin() + data.startIndex, + glyphPositions.Begin() + data.startIndex + data.numberOfGlyphs ); + + // 3) Layout + MetricsPtr metrics = Metrics::New( fontClient ); + + LayoutEngine engine; + engine.SetMetrics( metrics ); + engine.SetTextEllipsisEnabled( data.ellipsis ); + engine.SetLayout( data.layout ); + + const Length totalNumberOfGlyphs = visualModel->mGlyphs.Count(); + + LayoutParameters layoutParameters( data.textArea, + logicalModel->mText.Begin(), + logicalModel->mLineBreakInfo.Begin(), + logicalModel->mWordBreakInfo.Begin(), + ( 0u != logicalModel->mCharacterDirections.Count() ) ? logicalModel->mCharacterDirections.Begin() : NULL, + visualModel->mGlyphs.Begin(), + visualModel->mGlyphsToCharacters.Begin(), + visualModel->mCharactersPerGlyph.Begin(), + visualModel->mCharactersToGlyph.Begin(), + visualModel->mGlyphsPerCharacter.Begin(), + totalNumberOfGlyphs ); + + layoutParameters.isLastNewParagraph = isLastNewParagraph; + + // The initial glyph and the number of glyphs to layout. + layoutParameters.startGlyphIndex = data.startIndex; + layoutParameters.numberOfGlyphs = data.numberOfGlyphs; + layoutParameters.startLineIndex = startRemoveIndex; + + layoutSize = Vector2::ZERO; + + const bool updated = engine.LayoutText( layoutParameters, + glyphPositions, + lines, + layoutSize ); + + // 4) Compare the results. + + if( updated != data.updated ) + { + std::cout << " Different updated bool : " << updated << ", expected : " << data.updated << std::endl; + return false; + } + + if( layoutSize != data.layoutSize ) + { + std::cout << " Different layout size : " << layoutSize << ", expected : " << data.layoutSize << std::endl; + return false; + } + + for( unsigned int index = 0u; index < data.totalNumberOfGlyphs; ++index ) + { + const Vector2& position = *( glyphPositions.Begin() + index ); + + if( fabsf( position.x - *( data.positions + 2u * index ) ) > Math::MACHINE_EPSILON_1000 ) + { + std::cout << " Different position for glyph " << index << " x : " << position.x << ", expected : " << *( data.positions + 2u * index ) << std::endl; + return false; + } + if( fabsf( position.y - *( data.positions + 2u * index + 1u ) ) > Math::MACHINE_EPSILON_1000 ) + { + std::cout << " Different position for glyph " << index << " y : " << position.y << ", expected : " << *( data.positions + 2u * index + 1u ) << std::endl; + return false; + } + } + + if( lines.Count() != data.numberOfLines ) + { + std::cout << " Different number of lines : " << lines.Count() << ", expected : " << data.numberOfLines << std::endl; + return false; + } + + for( unsigned int index = 0u; index < data.numberOfLines; ++index ) + { + const LineRun& line = *( lines.Begin() + index ); + const LineRun& expectedLine = *( data.lines + index ); + + if( line.glyphRun.glyphIndex != expectedLine.glyphRun.glyphIndex ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + if( line.glyphRun.numberOfGlyphs != expectedLine.glyphRun.numberOfGlyphs ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + + if( line.characterRun.characterIndex != expectedLine.characterRun.characterIndex ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + if( line.characterRun.numberOfCharacters != expectedLine.characterRun.numberOfCharacters ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + + if( fabsf( line.width - expectedLine.width ) > Math::MACHINE_EPSILON_1 ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + + if( fabsf( line.ascender - expectedLine.ascender ) > Math::MACHINE_EPSILON_1 ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + + if( fabsf( line.descender - expectedLine.descender ) > Math::MACHINE_EPSILON_1 ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + + if( fabsf( line.extraLength - expectedLine.extraLength ) > Math::MACHINE_EPSILON_1 ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + + if( line.ellipsis != expectedLine.ellipsis ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + + // Do not compare the alignment offset as it's not calculated in the layout. + // Do not compare the line direction as it's not set in the layout. + } + + return true; +} + +////////////////////////////////////////////////////////// + +struct ReLayoutRightToLeftLinesData +{ + std::string description; + std::string text; + Size textArea; + unsigned int numberOfFonts; + FontDescriptionRun* fontDescriptions; + unsigned int totalNumberOfGlyphs; + float* positions; + unsigned int startIndex; + unsigned int numberOfCharacters; +}; + +bool ReLayoutRightToLeftLinesTest( const ReLayoutRightToLeftLinesData& data ) +{ + // Load some fonts. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" ); + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" ); + + // 1) Create the model. + LogicalModelPtr logicalModel = LogicalModel::New(); + VisualModelPtr visualModel = VisualModel::New(); + Size layoutSize; + + Vector fontDescriptionRuns; + if( 0u != data.numberOfFonts ) + { + fontDescriptionRuns.Insert( fontDescriptionRuns.End(), + data.fontDescriptions, + data.fontDescriptions + data.numberOfFonts ); + } + + LayoutOptions options; + options.reorder = false; + options.align = false; + CreateTextModel( data.text, + data.textArea, + fontDescriptionRuns, + options, + layoutSize, + logicalModel, + visualModel ); + + // 2) Call the ReLayoutRightToLeftLines() method. + MetricsPtr metrics = Metrics::New( fontClient ); + + LayoutEngine engine; + engine.SetMetrics( metrics ); + + LayoutParameters layoutParameters( data.textArea, + logicalModel->mText.Begin(), + logicalModel->mLineBreakInfo.Begin(), + logicalModel->mWordBreakInfo.Begin(), + ( 0u != logicalModel->mCharacterDirections.Count() ) ? logicalModel->mCharacterDirections.Begin() : NULL, + visualModel->mGlyphs.Begin(), + visualModel->mGlyphsToCharacters.Begin(), + visualModel->mCharactersPerGlyph.Begin(), + visualModel->mCharactersToGlyph.Begin(), + visualModel->mGlyphsPerCharacter.Begin(), + visualModel->mGlyphs.Count() ); + + layoutParameters.numberOfBidirectionalInfoRuns = logicalModel->mBidirectionalLineInfo.Count(); + layoutParameters.lineBidirectionalInfoRunsBuffer = logicalModel->mBidirectionalLineInfo.Begin(); + + engine.ReLayoutRightToLeftLines( layoutParameters, + data.startIndex, + data.numberOfCharacters, + visualModel->mGlyphPositions ); + + // 3) Compare the results. + Vector& glyphPositions = visualModel->mGlyphPositions; + + if( data.totalNumberOfGlyphs != visualModel->mGlyphs.Count() ) + { + std::cout << " Different number of glyphs : " << visualModel->mGlyphs.Count() << ", expected : " << data.totalNumberOfGlyphs << std::endl; + return false; + } + + for( unsigned int index = 0u; index < data.totalNumberOfGlyphs; ++index ) + { + const Vector2& position = *( glyphPositions.Begin() + index ); + + if( fabsf( position.x - *( data.positions + 2u * index ) ) > Math::MACHINE_EPSILON_1000 ) + { + std::cout << " Different position for glyph " << index << " x : " << position.x << ", expected : " << *( data.positions + 2u * index ) << std::endl; + return false; + } + if( fabsf( position.y - *( data.positions + 2u * index + 1u ) ) > Math::MACHINE_EPSILON_1000 ) + { + std::cout << " Different position for glyph " << index << " y : " << position.y << ", expected : " << *( data.positions + 2u * index + 1u ) << std::endl; + return false; + } + } + + return true; +} + +////////////////////////////////////////////////////////// + +struct AlignData +{ + std::string description; + std::string text; + Size textArea; + unsigned int numberOfFonts; + FontDescriptionRun* fontDescriptions; + LayoutEngine::HorizontalAlignment horizontalAlignment; + LayoutEngine::VerticalAlignment verticalAlignment; + unsigned int startIndex; + unsigned int numberOfCharacters; + unsigned int numberOfLines; + float* lineOffsets; +}; + +bool AlignTest( const AlignData& data ) +{ + // Load some fonts. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" ); + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" ); + + // 1) Create the model. + LogicalModelPtr logicalModel = LogicalModel::New(); + VisualModelPtr visualModel = VisualModel::New(); + Size layoutSize; + + Vector fontDescriptionRuns; + if( 0u != data.numberOfFonts ) + { + fontDescriptionRuns.Insert( fontDescriptionRuns.End(), + data.fontDescriptions, + data.fontDescriptions + data.numberOfFonts ); + } + + LayoutOptions options; + options.align = false; + CreateTextModel( data.text, + data.textArea, + fontDescriptionRuns, + options, + layoutSize, + logicalModel, + visualModel ); + + // Call the Align method. + MetricsPtr metrics = Metrics::New( fontClient ); + + LayoutEngine engine; + engine.SetMetrics( metrics ); + + engine.SetHorizontalAlignment( data.horizontalAlignment ); + engine.SetVerticalAlignment( data.verticalAlignment ); + + engine.Align( data.textArea, + data.startIndex, + data.numberOfCharacters, + visualModel->mLines ); + + // Compare results. + if( data.numberOfLines != visualModel->mLines.Count() ) + { + std::cout << " Different number of lines : " << visualModel->mLines.Count() << ", expected : " << data.numberOfLines << std::endl; + return false; + } + + const LineRun* const linesBuffer = visualModel->mLines.Begin(); + for( unsigned int index = 0u; index < data.numberOfLines; ++index ) + { + const LineRun& line = *( linesBuffer + index ); + + if( line.alignmentOffset != *( data.lineOffsets + index ) ) + { + std::cout << " different line offset for index " << index << " : " << line.alignmentOffset << ", expected : " << *( data.lineOffsets + index ) << std::endl; + return false; + } + } + + return true; +} + +} // namespace + +////////////////////////////////////////////////////////// +// +// UtcDaliTextLayoutSetGetLayout +// UtcDaliTextLayoutSetGetTextEllipsisEnabled +// UtcDaliTextLayoutSetGetHorizontalAlignment +// UtcDaliTextLayoutSetGetVerticalAlignment +// UtcDaliTextLayoutSetGetCursorWidth +// UtcDaliTextLayoutNoText +// UtcDaliTextLayoutSmallTextArea01 +// UtcDaliTextLayoutSmallTextArea02 +// UtcDaliTextLayoutMultilineText01 +// UtcDaliTextLayoutMultilineText02 +// UtcDaliTextLayoutMultilineText03 +// UtcDaliTextLayoutMultilineText04 +// UtcDaliTextLayoutMultilineText05 +// UtcDaliTextUpdateLayout01 +// UtcDaliTextUpdateLayout02 +// UtcDaliTextUpdateLayout03 +// UtcDaliTextLayoutEllipsis01 +// UtcDaliTextLayoutEllipsis02 +// UtcDaliTextLayoutEllipsis03 +// UtcDaliTextLayoutEllipsis04 +// UtcDaliTextLayoutEllipsis04 +// UtcDaliTextReorderLayout01 +// UtcDaliTextReorderLayout02 +// UtcDaliTextReorderLayout03 +// UtcDaliTextReorderLayout04 +// UtcDaliTextAlign01 +// UtcDaliTextAlign02 +// UtcDaliTextAlign03 +// UtcDaliTextAlign04 +// UtcDaliTextAlign05 +// UtcDaliTextAlign06 +// UtcDaliTextAlign07 +// UtcDaliTextAlign08 +// UtcDaliTextAlign09 +// +////////////////////////////////////////////////////////// + +int UtcDaliTextLayoutSetGetLayout(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutSetGetLayout"); + + LayoutEngine engine; + + DALI_TEST_CHECK( LayoutEngine::SINGLE_LINE_BOX == engine.GetLayout() ); + + engine.SetLayout( LayoutEngine::MULTI_LINE_BOX ); + DALI_TEST_CHECK( LayoutEngine::MULTI_LINE_BOX == engine.GetLayout() ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutSetGetTextEllipsisEnabled(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutSetGetTextEllipsisEnabled"); + + LayoutEngine engine; + + DALI_TEST_CHECK( !engine.GetTextEllipsisEnabled() ); + + engine.SetTextEllipsisEnabled( true ); + DALI_TEST_CHECK( engine.GetTextEllipsisEnabled() ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutSetGetHorizontalAlignment(void) +{ + ToolkitTestApplication application; + tet_infoline(" "); + + LayoutEngine engine; + + DALI_TEST_CHECK( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == engine.GetHorizontalAlignment() ); + + engine.SetHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_END ); + DALI_TEST_CHECK( LayoutEngine::HORIZONTAL_ALIGN_END == engine.GetHorizontalAlignment() ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutSetGetVerticalAlignment(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutSetGetVerticalAlignment"); + + LayoutEngine engine; + + DALI_TEST_CHECK( LayoutEngine::VERTICAL_ALIGN_TOP == engine.GetVerticalAlignment() ); + + engine.SetVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP ); + DALI_TEST_CHECK( LayoutEngine::VERTICAL_ALIGN_TOP == engine.GetVerticalAlignment() ); + + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutSetGetCursorWidth(void) +{ + ToolkitTestApplication application; + tet_infoline(" "); + + LayoutEngine engine; + + DALI_TEST_EQUALS( 1, engine.GetCursorWidth(), TEST_LOCATION ); + + engine.SetCursorWidth( 2 ); + DALI_TEST_EQUALS( 2, engine.GetCursorWidth(), TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutNoText(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutNoText"); + + Size textArea(100.f, 60.f); + Size layoutSize = Vector2::ZERO; + LayoutTextData data = + { + "No text", + "", + textArea, + 0u, + NULL, + layoutSize, + 0u, + NULL, + 0u, + NULL, + LayoutEngine::MULTI_LINE_BOX, + 0u, + 0u, + false, + false + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutSmallTextArea01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutSmallTextArea01"); + + // Won't layout the text in multi-line if the width is too small. + + const std::string fontFamily( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun; + fontDescriptionRun.characterRun.characterIndex = 0u; + fontDescriptionRun.characterRun.numberOfCharacters = 11u; + fontDescriptionRun.familyLength = fontFamily.size(); + fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; + memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength ); + fontDescriptionRun.familyDefined = true; + fontDescriptionRun.weightDefined = false; + fontDescriptionRun.widthDefined = false; + fontDescriptionRun.slantDefined = false; + fontDescriptionRun.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun ); + Size textArea(1.f, 1.f); + Size layoutSize = Vector2::ZERO; + LayoutTextData data = + { + "Layout text in a small area", + "Hello world", + textArea, + 1u, + fontDescriptionRuns.Begin(), + layoutSize, + 0u, + NULL, + 0u, + NULL, + LayoutEngine::MULTI_LINE_BOX, + 0u, + 11u, + false, + false + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutSmallTextArea02(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutSmallTextArea02"); + + // Will layout the text in single line as it can be scrolled. + + const std::string fontFamily( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun; + fontDescriptionRun.characterRun.characterIndex = 0u; + fontDescriptionRun.characterRun.numberOfCharacters = 11u; + fontDescriptionRun.familyLength = fontFamily.size(); + fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; + memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength ); + fontDescriptionRun.familyDefined = true; + fontDescriptionRun.weightDefined = false; + fontDescriptionRun.widthDefined = false; + fontDescriptionRun.slantDefined = false; + fontDescriptionRun.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun ); + Size textArea(1.f, 1.f); + Size layoutSize(80.f, 20.f); + float positions[] = { 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f }; + struct LineRun line = + { + { 0u, 11u }, + { 0u, 11u }, + 80.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line ); + + LayoutTextData data = + { + "Layout text in a small area", + "Hello world", + textArea, + 1u, + fontDescriptionRuns.Begin(), + layoutSize, + 11u, + positions, + 1u, + lines.Begin(), + LayoutEngine::SINGLE_LINE_BOX, + 0u, + 11u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutMultilineText01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutMultilineText01"); + + // Layout some lines of left to right text. + + const std::string fontFamily( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun1; + fontDescriptionRun1.characterRun.characterIndex = 0u; + fontDescriptionRun1.characterRun.numberOfCharacters = 18u; + fontDescriptionRun1.familyLength = fontFamily.size(); + fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength]; + memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength ); + fontDescriptionRun1.familyDefined = true; + fontDescriptionRun1.weightDefined = false; + fontDescriptionRun1.widthDefined = false; + fontDescriptionRun1.slantDefined = false; + fontDescriptionRun1.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun2; + fontDescriptionRun2.characterRun.characterIndex = 18u; + fontDescriptionRun2.characterRun.numberOfCharacters = 31u; + fontDescriptionRun2.familyLength = fontFamily.size(); + fontDescriptionRun2.familyName = new char[fontDescriptionRun2.familyLength]; + memcpy( fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength ); + fontDescriptionRun2.familyDefined = true; + fontDescriptionRun2.weightDefined = false; + fontDescriptionRun2.widthDefined = false; + fontDescriptionRun2.slantDefined = false; + fontDescriptionRun2.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun1 ); + fontDescriptionRuns.PushBack( fontDescriptionRun2 ); + Size textArea(100.f, 300.f); + Size layoutSize(95.f, 97.f); + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, + 0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 32.f, 42.f, 23.f, + 1.f, 43.f, 9.f, 46.f, 17.f, 46.f, 27.f, 46.f, 36.f, 46.f, 45.f, 44.f, 51.f, 55.f, + 1.f, 62.f, 11.f, 62.f, 15.f, 62.f, 26.f, 65.f, 35.f, 65.f, 41.f, 65.f, 50.f, 65.f, 59.f, 63.f, 65.f, 74.f, + 1.f, 81.f, 5.f, 81.f, 9.f, 84.f, 19.f, 84.f, 28.f, 84.f, 35.f, 93.f, 41.f, 84.f, 50.f, 81.f, 54.f, 93.f, 59.f, 82.f, 66.f, 84.f, 75.f, 84.f, 83.f, 82.f, 91.f, 91.f + }; + struct LineRun line0 = + { + { 0u, 12u }, + { 0u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line1 = + { + { 12u, 6u }, + { 12u, 6u }, + 43.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line2 = + { + { 18u, 7u }, + { 18u, 7u }, + 52.f, + 15.f, + -4.f, + 5.f, + 0.f, + false, + false + }; + struct LineRun line3 = + { + { 25u, 9u }, + { 25u, 10u }, + 66.f, + 15.f, + -4.f, + 5.f, + 0.f, + false, + false + }; + struct LineRun line4 = + { + { 34u, 14u }, + { 35u, 14u }, + 95.f, + 15.f, + -4.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line0 ); + lines.PushBack( line1 ); + lines.PushBack( line2 ); + lines.PushBack( line3 ); + lines.PushBack( line4 ); + + LayoutTextData data = + { + "Layout simple multi-line text", + "Hello world demo.\n" + "Layout different lines of text.", + textArea, + 1u, + fontDescriptionRuns.Begin(), + layoutSize, + 48u, + positions, + 5u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 48u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutMultilineText02(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutMultilineText02"); + + // Layout some lines of bidirectional text. + + const std::string fontFamily1( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun1; + fontDescriptionRun1.characterRun.characterIndex = 0u; + fontDescriptionRun1.characterRun.numberOfCharacters = 17u; + fontDescriptionRun1.familyLength = fontFamily1.size(); + fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength]; + memcpy( fontDescriptionRun1.familyName, fontFamily1.c_str(), fontDescriptionRun1.familyLength ); + fontDescriptionRun1.familyDefined = true; + fontDescriptionRun1.weightDefined = false; + fontDescriptionRun1.widthDefined = false; + fontDescriptionRun1.slantDefined = false; + fontDescriptionRun1.sizeDefined = false; + + const std::string fontFamily2( "TizenSansHebrew" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun2; + fontDescriptionRun2.characterRun.characterIndex = 17u; + fontDescriptionRun2.characterRun.numberOfCharacters = 11u; + fontDescriptionRun2.familyLength = fontFamily2.size(); + fontDescriptionRun2.familyName = new char[fontDescriptionRun2.familyLength]; + memcpy( fontDescriptionRun2.familyName, fontFamily2.c_str(), fontDescriptionRun2.familyLength ); + fontDescriptionRun2.familyDefined = true; + fontDescriptionRun2.weightDefined = false; + fontDescriptionRun2.widthDefined = false; + fontDescriptionRun2.slantDefined = false; + fontDescriptionRun2.sizeDefined = false; + + const std::string fontFamily3( "TizenSansHebrew" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun3; + fontDescriptionRun3.characterRun.characterIndex = 28u; + fontDescriptionRun3.characterRun.numberOfCharacters = 10u; + fontDescriptionRun3.familyLength = fontFamily3.size(); + fontDescriptionRun3.familyName = new char[fontDescriptionRun3.familyLength]; + memcpy( fontDescriptionRun3.familyName, fontFamily3.c_str(), fontDescriptionRun3.familyLength ); + fontDescriptionRun3.familyDefined = true; + fontDescriptionRun3.weightDefined = false; + fontDescriptionRun3.widthDefined = false; + fontDescriptionRun3.slantDefined = false; + fontDescriptionRun3.sizeDefined = false; + + const std::string fontFamily4( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun4; + fontDescriptionRun4.characterRun.characterIndex = 38u; + fontDescriptionRun4.characterRun.numberOfCharacters = 17u; + fontDescriptionRun4.familyLength = fontFamily4.size(); + fontDescriptionRun4.familyName = new char[fontDescriptionRun4.familyLength]; + memcpy( fontDescriptionRun4.familyName, fontFamily4.c_str(), fontDescriptionRun4.familyLength ); + fontDescriptionRun4.familyDefined = true; + fontDescriptionRun4.weightDefined = false; + fontDescriptionRun4.widthDefined = false; + fontDescriptionRun4.slantDefined = false; + fontDescriptionRun4.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun1 ); + fontDescriptionRuns.PushBack( fontDescriptionRun2 ); + fontDescriptionRuns.PushBack( fontDescriptionRun3 ); + fontDescriptionRuns.PushBack( fontDescriptionRun4 ); + Size textArea(100.f, 300.f); + Size layoutSize(81.f, 120.f); + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, + 0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f, + 1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f, + 1.f, 65.f, 12.f, 62.f, 19.f, 65.f, 24.f, 65.f, 32.f, 75.f, 37.f, 65.f, 45.f, 65.f, 50.f, 62.f, 58.f, 65.f, 66.f, 75.f, + 1.f, 82.f, 10.f, 86.f, 18.f, 82.f, 22.f, 82.f, 25.f, 86.f, 34.f, 95.f, 38.f, 86.f, 49.f, 86.f, 59.f, 86.f, 65.f, 82.f, 68.f, 82.f, 77.f, 95.f, + 0.f, 102.f, 10.f, 106.f, 18.f, 106.f, 30.f, 106.f, 39.f, 112.f + }; + struct LineRun line0 = + { + { 0u, 12u }, + { 0u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line1 = + { + { 12u, 10u }, + { 12u, 10u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line2 = + { + { 22u, 6u }, + { 22u, 6u }, + 36.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line3 = + { + { 28u, 10u }, + { 28u, 10u }, + 67.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line4 = + { + { 38u, 12u }, + { 38u, 12u }, + 79.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line5 = + { + { 50u, 5u }, + { 50u, 5u }, + 43.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line0 ); + lines.PushBack( line1 ); + lines.PushBack( line2 ); + lines.PushBack( line3 ); + lines.PushBack( line4 ); + lines.PushBack( line5 ); + + LayoutTextData data = + { + "Layout bidirectional text.", + "Hello world demo שלום עולם.\n" + "שלום עולם hello world demo.", + textArea, + 4u, + fontDescriptionRuns.Begin(), + layoutSize, + 55u, + positions, + 6u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 55u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutMultilineText03(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutMultilineText03"); + + // Layout a long word which doesn't fit in the width of the text area. + + const std::string fontFamily( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun; + fontDescriptionRun.characterRun.characterIndex = 0u; + fontDescriptionRun.characterRun.numberOfCharacters = 29u; + fontDescriptionRun.familyLength = fontFamily.size(); + fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; + memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength ); + fontDescriptionRun.familyDefined = true; + fontDescriptionRun.weightDefined = false; + fontDescriptionRun.widthDefined = false; + fontDescriptionRun.slantDefined = false; + fontDescriptionRun.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun ); + Size textArea(100.f, 300.f); + Size layoutSize(96.f, 60.f); + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 6.f, 47.f, 6.f, 57.f, 6.f, 63.f, 2.f, 66.f, 2.f, 75.f, 2.f, 85.f, 6.f, + 1.f, 26.f, 13.f, 26.f, 23.f, 22.f, 32.f, 26.f, 40.f, 22.f, 44.f, 22.f, 47.f, 26.f, 56.f, 26.f, 67.f, 26.f, 77.f, 26.f, 83.f, 22.f, 86.f, 22.f, + 0.f, 42.f, 10.f, 46.f, 18.f, 46.f, 30.f, 46.f, 39.f, 52.f + }; + struct LineRun line0 = + { + { 0u, 12u }, + { 0u, 12u }, + 94.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line1 = + { + { 12u, 12u }, + { 12u, 12u }, + 96.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line2 = + { + { 24u, 5u }, + { 24u, 5u }, + 43.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line0 ); + lines.PushBack( line1 ); + lines.PushBack( line2 ); + + LayoutTextData data = + { + "Layout a long word which doesn't fit in the width of the text area.", + "Helloworlddemohelloworlddemo.", + textArea, + 1u, + fontDescriptionRuns.Begin(), + layoutSize, + 29u, + positions, + 3u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 29u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutMultilineText04(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutMultilineText04"); + + // Layout simple text ending with a \n. It has to add a void line at the end. + + const std::string fontFamily( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun; + fontDescriptionRun.characterRun.characterIndex = 0u; + fontDescriptionRun.characterRun.numberOfCharacters = 13u; + fontDescriptionRun.familyLength = fontFamily.size(); + fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; + memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength ); + fontDescriptionRun.familyDefined = true; + fontDescriptionRun.weightDefined = false; + fontDescriptionRun.widthDefined = false; + fontDescriptionRun.slantDefined = false; + fontDescriptionRun.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun ); + Size textArea(100.f, 300.f); + Size layoutSize(83.f, 40.f); + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 12.f, 82.f, 3.f + }; + struct LineRun line0 = + { + { 0u, 13u }, + { 0u, 13u }, + 83.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line1 = + { + { 13u, 0u }, + { 13u, 0u }, + 0.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line0 ); + lines.PushBack( line1 ); + + LayoutTextData data = + { + "Layout simple text ending with a \n.", + "Hello world.\n", + textArea, + 1u, + fontDescriptionRuns.Begin(), + layoutSize, + 13u, + positions, + 2u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 13u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutMultilineText05(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutMultilineText05"); + + // Layout simple text with one character with a different font size. + + const std::string fontFamily( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun1; + fontDescriptionRun1.characterRun.characterIndex = 0u; + fontDescriptionRun1.characterRun.numberOfCharacters = 6u; + fontDescriptionRun1.familyLength = fontFamily.size(); + fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength]; + memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength ); + fontDescriptionRun1.familyDefined = true; + fontDescriptionRun1.weightDefined = false; + fontDescriptionRun1.widthDefined = false; + fontDescriptionRun1.slantDefined = false; + fontDescriptionRun1.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun2; + fontDescriptionRun2.characterRun.characterIndex = 6u; + fontDescriptionRun2.characterRun.numberOfCharacters = 1u; + fontDescriptionRun2.familyLength = fontFamily.size(); + fontDescriptionRun2.familyName = new char[fontDescriptionRun2.familyLength]; + memcpy( fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength ); + fontDescriptionRun2.size = 1280u; + fontDescriptionRun2.familyDefined = true; + fontDescriptionRun2.weightDefined = false; + fontDescriptionRun2.widthDefined = false; + fontDescriptionRun2.slantDefined = false; + fontDescriptionRun2.sizeDefined = true; + + FontDescriptionRun fontDescriptionRun3; + fontDescriptionRun3.characterRun.characterIndex = 7u; + fontDescriptionRun3.characterRun.numberOfCharacters = 10u; + fontDescriptionRun3.familyLength = fontFamily.size(); + fontDescriptionRun3.familyName = new char[fontDescriptionRun3.familyLength]; + memcpy( fontDescriptionRun3.familyName, fontFamily.c_str(), fontDescriptionRun3.familyLength ); + fontDescriptionRun3.familyDefined = true; + fontDescriptionRun3.weightDefined = false; + fontDescriptionRun3.widthDefined = false; + fontDescriptionRun3.slantDefined = false; + fontDescriptionRun3.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun1 ); + fontDescriptionRuns.PushBack( fontDescriptionRun2 ); + fontDescriptionRuns.PushBack( fontDescriptionRun3 ); + Size textArea(100.f, 300.f); + Size layoutSize(88.f, 53.f); + float positions[] = + { + 1.f, 13.f, 12.f, 16.f, 20.f, 12.f, 24.f, 12.f, 27.f, 16.f, 36.f, 25.f, 40.f, 11.f, 59.f, 16.f, 69.f, 16.f, 75.f, 12.f, 78.f, 12.f, 87.f, 25.f, + 0.f, 35.f, 10.f, 39.f, 18.f, 39.f, 30.f, 39.f, 39.f, 45.f + }; + struct LineRun line0 = + { + { 0u, 12u }, + { 0u, 12u }, + 88.f, + 25.f, + -8.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line1 = + { + { 12u, 5u }, + { 12u, 5u }, + 43.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line0 ); + lines.PushBack( line1 ); + + LayoutTextData data = + { + "Layout simple text with one character with a different font size.", + "Hello world demo.", + textArea, + 3u, + fontDescriptionRuns.Begin(), + layoutSize, + 17u, + positions, + 2u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 17u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextUpdateLayout01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextUpdateLayout01"); + + // Layout some lines of bidirectional text. Update the paragraphs at the beginning. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 17u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 17u; + fontDescriptionRun02.characterRun.numberOfCharacters = 11u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 28u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 42u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 54u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 64u; + fontDescriptionRun06.characterRun.numberOfCharacters = 10u; + fontDescriptionRun06.familyLength = fontHebrew.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontHebrew.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun07; + fontDescriptionRun07.characterRun.characterIndex = 74u; + fontDescriptionRun07.characterRun.numberOfCharacters = 18u; + fontDescriptionRun07.familyLength = fontLatin.size(); + fontDescriptionRun07.familyName = new char[fontDescriptionRun07.familyLength]; + memcpy( fontDescriptionRun07.familyName, fontLatin.c_str(), fontDescriptionRun07.familyLength ); + fontDescriptionRun07.familyDefined = true; + fontDescriptionRun07.weightDefined = false; + fontDescriptionRun07.widthDefined = false; + fontDescriptionRun07.slantDefined = false; + fontDescriptionRun07.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun08; + fontDescriptionRun08.characterRun.characterIndex = 92u; + fontDescriptionRun08.characterRun.numberOfCharacters = 12u; + fontDescriptionRun08.familyLength = fontLatin.size(); + fontDescriptionRun08.familyName = new char[fontDescriptionRun08.familyLength]; + memcpy( fontDescriptionRun08.familyName, fontLatin.c_str(), fontDescriptionRun08.familyLength ); + fontDescriptionRun08.familyDefined = true; + fontDescriptionRun08.weightDefined = false; + fontDescriptionRun08.widthDefined = false; + fontDescriptionRun08.slantDefined = false; + fontDescriptionRun08.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun09; + fontDescriptionRun09.characterRun.characterIndex = 104u; + fontDescriptionRun09.characterRun.numberOfCharacters = 14u; + fontDescriptionRun09.familyLength = fontArabic.size(); + fontDescriptionRun09.familyName = new char[fontDescriptionRun09.familyLength]; + memcpy( fontDescriptionRun09.familyName, fontArabic.c_str(), fontDescriptionRun09.familyLength ); + fontDescriptionRun09.familyDefined = true; + fontDescriptionRun09.weightDefined = false; + fontDescriptionRun09.widthDefined = false; + fontDescriptionRun09.slantDefined = false; + fontDescriptionRun09.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun10; + fontDescriptionRun10.characterRun.characterIndex = 118u; + fontDescriptionRun10.characterRun.numberOfCharacters = 10u; + fontDescriptionRun10.familyLength = fontHebrew.size(); + fontDescriptionRun10.familyName = new char[fontDescriptionRun10.familyLength]; + memcpy( fontDescriptionRun10.familyName, fontHebrew.c_str(), fontDescriptionRun10.familyLength ); + fontDescriptionRun10.familyDefined = true; + fontDescriptionRun10.weightDefined = false; + fontDescriptionRun10.widthDefined = false; + fontDescriptionRun10.slantDefined = false; + fontDescriptionRun10.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun11; + fontDescriptionRun11.characterRun.characterIndex = 128u; + fontDescriptionRun11.characterRun.numberOfCharacters = 17u; + fontDescriptionRun11.familyLength = fontLatin.size(); + fontDescriptionRun11.familyName = new char[fontDescriptionRun11.familyLength]; + memcpy( fontDescriptionRun11.familyName, fontLatin.c_str(), fontDescriptionRun11.familyLength ); + fontDescriptionRun11.familyDefined = true; + fontDescriptionRun11.weightDefined = false; + fontDescriptionRun11.widthDefined = false; + fontDescriptionRun11.slantDefined = false; + fontDescriptionRun11.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun12; + fontDescriptionRun12.characterRun.characterIndex = 145u; + fontDescriptionRun12.characterRun.numberOfCharacters = 11u; + fontDescriptionRun12.familyLength = fontHebrew.size(); + fontDescriptionRun12.familyName = new char[fontDescriptionRun12.familyLength]; + memcpy( fontDescriptionRun12.familyName, fontHebrew.c_str(), fontDescriptionRun12.familyLength ); + fontDescriptionRun12.familyDefined = true; + fontDescriptionRun12.weightDefined = false; + fontDescriptionRun12.widthDefined = false; + fontDescriptionRun12.slantDefined = false; + fontDescriptionRun12.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun13; + fontDescriptionRun13.characterRun.characterIndex = 156u; + fontDescriptionRun13.characterRun.numberOfCharacters = 10u; + fontDescriptionRun13.familyLength = fontHebrew.size(); + fontDescriptionRun13.familyName = new char[fontDescriptionRun13.familyLength]; + memcpy( fontDescriptionRun13.familyName, fontHebrew.c_str(), fontDescriptionRun13.familyLength ); + fontDescriptionRun13.familyDefined = true; + fontDescriptionRun13.weightDefined = false; + fontDescriptionRun13.widthDefined = false; + fontDescriptionRun13.slantDefined = false; + fontDescriptionRun13.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun14; + fontDescriptionRun14.characterRun.characterIndex = 166u; + fontDescriptionRun14.characterRun.numberOfCharacters = 12u; + fontDescriptionRun14.familyLength = fontLatin.size(); + fontDescriptionRun14.familyName = new char[fontDescriptionRun14.familyLength]; + memcpy( fontDescriptionRun14.familyName, fontLatin.c_str(), fontDescriptionRun14.familyLength ); + fontDescriptionRun14.familyDefined = true; + fontDescriptionRun14.weightDefined = false; + fontDescriptionRun14.widthDefined = false; + fontDescriptionRun14.slantDefined = false; + fontDescriptionRun14.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun15; + fontDescriptionRun15.characterRun.characterIndex = 178u; + fontDescriptionRun15.characterRun.numberOfCharacters = 14u; + fontDescriptionRun15.familyLength = fontArabic.size(); + fontDescriptionRun15.familyName = new char[fontDescriptionRun15.familyLength]; + memcpy( fontDescriptionRun15.familyName, fontArabic.c_str(), fontDescriptionRun15.familyLength ); + fontDescriptionRun15.familyDefined = true; + fontDescriptionRun15.weightDefined = false; + fontDescriptionRun15.widthDefined = false; + fontDescriptionRun15.slantDefined = false; + fontDescriptionRun15.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + fontDescriptionRuns.PushBack( fontDescriptionRun07 ); + fontDescriptionRuns.PushBack( fontDescriptionRun08 ); + fontDescriptionRuns.PushBack( fontDescriptionRun09 ); + fontDescriptionRuns.PushBack( fontDescriptionRun10 ); + fontDescriptionRuns.PushBack( fontDescriptionRun11 ); + fontDescriptionRuns.PushBack( fontDescriptionRun12 ); + fontDescriptionRuns.PushBack( fontDescriptionRun13 ); + fontDescriptionRuns.PushBack( fontDescriptionRun14 ); + fontDescriptionRuns.PushBack( fontDescriptionRun15 ); + Size textArea(100.f, 300.f); + Size layoutSize(92.f, 380.f); + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, + 0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f, + 1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f, + 0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f, + 0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f, + 1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f, + 1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f, + 1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f, + 0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f, + 1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f, + 0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f, + 1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f, + 1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f, + 0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f, + 1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f, + 1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f, + 1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f, + 0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f, + }; + struct LineRun line01 = + { + { 0u, 12u }, + { 0u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line02 = + { + { 12u, 10u }, + { 12u, 10u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line03 = + { + { 22u, 6u }, + { 22u, 6u }, + 36.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line04 = + { + { 28u, 20u }, + { 28u, 20u }, + 92.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line05 = + { + { 48u, 11u }, + { 48u, 11u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line06 = + { + { 59u, 5u }, + { 59u, 5u }, + 31.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line07 = + { + { 64u, 10u }, + { 64u, 10u }, + 67.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line08 = + { + { 74u, 12u }, + { 74u, 12u }, + 79.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line09 = + { + { 86u, 6u }, + { 86u, 6u }, + 43.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line10 = + { + { 92u, 12u }, + { 92u, 12u }, + 78.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line11 = + { + { 104u, 19u }, + { 104u, 19u }, + 90.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line12 = + { + { 123u, 5u }, + { 123u, 5u }, + 31.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line13 = + { + { 128u, 12u }, + { 128u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line14 = + { + { 140u, 10u }, + { 140u, 10u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line15 = + { + { 150u, 6u }, + { 150u, 6u }, + 36.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line16 = + { + { 156u, 10u }, + { 156u, 10u }, + 67.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line17 = + { + { 166u, 12u }, + { 166u, 12u }, + 79.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line18 = + { + { 178u, 14u }, + { 178u, 14u }, + 55.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line19 = + { + { 192u, 0u }, + { 192u, 0u }, + 0.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line01 ); + lines.PushBack( line02 ); + lines.PushBack( line03 ); + lines.PushBack( line04 ); + lines.PushBack( line05 ); + lines.PushBack( line06 ); + lines.PushBack( line07 ); + lines.PushBack( line08 ); + lines.PushBack( line09 ); + lines.PushBack( line10 ); + lines.PushBack( line11 ); + lines.PushBack( line12 ); + lines.PushBack( line13 ); + lines.PushBack( line14 ); + lines.PushBack( line15 ); + lines.PushBack( line16 ); + lines.PushBack( line17 ); + lines.PushBack( line18 ); + lines.PushBack( line19 ); + + LayoutTextData data = + { + "Layout bidirectional text.", + "Hello world demo שלום עולם.\n" + "مرحبا بالعالم hello world שלום עולם\n" + "שלום עולם hello world demo.\n" + "hello world مرحبا بالعالم שלום עולם\n" + "Hello world demo שלום עולם.\n" + "שלום עולם hello world مرحبا بالعالم\n", + textArea, + 15u, + fontDescriptionRuns.Begin(), + layoutSize, + 192u, + positions, + 19u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 64u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextUpdateLayout02(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextUpdateLayout02"); + + // Layout some lines of bidirectional text. Update the paragraphs at the middle. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 17u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 17u; + fontDescriptionRun02.characterRun.numberOfCharacters = 11u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 28u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 42u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 54u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 64u; + fontDescriptionRun06.characterRun.numberOfCharacters = 10u; + fontDescriptionRun06.familyLength = fontHebrew.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontHebrew.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun07; + fontDescriptionRun07.characterRun.characterIndex = 74u; + fontDescriptionRun07.characterRun.numberOfCharacters = 18u; + fontDescriptionRun07.familyLength = fontLatin.size(); + fontDescriptionRun07.familyName = new char[fontDescriptionRun07.familyLength]; + memcpy( fontDescriptionRun07.familyName, fontLatin.c_str(), fontDescriptionRun07.familyLength ); + fontDescriptionRun07.familyDefined = true; + fontDescriptionRun07.weightDefined = false; + fontDescriptionRun07.widthDefined = false; + fontDescriptionRun07.slantDefined = false; + fontDescriptionRun07.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun08; + fontDescriptionRun08.characterRun.characterIndex = 92u; + fontDescriptionRun08.characterRun.numberOfCharacters = 12u; + fontDescriptionRun08.familyLength = fontLatin.size(); + fontDescriptionRun08.familyName = new char[fontDescriptionRun08.familyLength]; + memcpy( fontDescriptionRun08.familyName, fontLatin.c_str(), fontDescriptionRun08.familyLength ); + fontDescriptionRun08.familyDefined = true; + fontDescriptionRun08.weightDefined = false; + fontDescriptionRun08.widthDefined = false; + fontDescriptionRun08.slantDefined = false; + fontDescriptionRun08.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun09; + fontDescriptionRun09.characterRun.characterIndex = 104u; + fontDescriptionRun09.characterRun.numberOfCharacters = 14u; + fontDescriptionRun09.familyLength = fontArabic.size(); + fontDescriptionRun09.familyName = new char[fontDescriptionRun09.familyLength]; + memcpy( fontDescriptionRun09.familyName, fontArabic.c_str(), fontDescriptionRun09.familyLength ); + fontDescriptionRun09.familyDefined = true; + fontDescriptionRun09.weightDefined = false; + fontDescriptionRun09.widthDefined = false; + fontDescriptionRun09.slantDefined = false; + fontDescriptionRun09.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun10; + fontDescriptionRun10.characterRun.characterIndex = 118u; + fontDescriptionRun10.characterRun.numberOfCharacters = 10u; + fontDescriptionRun10.familyLength = fontHebrew.size(); + fontDescriptionRun10.familyName = new char[fontDescriptionRun10.familyLength]; + memcpy( fontDescriptionRun10.familyName, fontHebrew.c_str(), fontDescriptionRun10.familyLength ); + fontDescriptionRun10.familyDefined = true; + fontDescriptionRun10.weightDefined = false; + fontDescriptionRun10.widthDefined = false; + fontDescriptionRun10.slantDefined = false; + fontDescriptionRun10.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun11; + fontDescriptionRun11.characterRun.characterIndex = 128u; + fontDescriptionRun11.characterRun.numberOfCharacters = 17u; + fontDescriptionRun11.familyLength = fontLatin.size(); + fontDescriptionRun11.familyName = new char[fontDescriptionRun11.familyLength]; + memcpy( fontDescriptionRun11.familyName, fontLatin.c_str(), fontDescriptionRun11.familyLength ); + fontDescriptionRun11.familyDefined = true; + fontDescriptionRun11.weightDefined = false; + fontDescriptionRun11.widthDefined = false; + fontDescriptionRun11.slantDefined = false; + fontDescriptionRun11.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun12; + fontDescriptionRun12.characterRun.characterIndex = 145u; + fontDescriptionRun12.characterRun.numberOfCharacters = 11u; + fontDescriptionRun12.familyLength = fontHebrew.size(); + fontDescriptionRun12.familyName = new char[fontDescriptionRun12.familyLength]; + memcpy( fontDescriptionRun12.familyName, fontHebrew.c_str(), fontDescriptionRun12.familyLength ); + fontDescriptionRun12.familyDefined = true; + fontDescriptionRun12.weightDefined = false; + fontDescriptionRun12.widthDefined = false; + fontDescriptionRun12.slantDefined = false; + fontDescriptionRun12.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun13; + fontDescriptionRun13.characterRun.characterIndex = 156u; + fontDescriptionRun13.characterRun.numberOfCharacters = 10u; + fontDescriptionRun13.familyLength = fontHebrew.size(); + fontDescriptionRun13.familyName = new char[fontDescriptionRun13.familyLength]; + memcpy( fontDescriptionRun13.familyName, fontHebrew.c_str(), fontDescriptionRun13.familyLength ); + fontDescriptionRun13.familyDefined = true; + fontDescriptionRun13.weightDefined = false; + fontDescriptionRun13.widthDefined = false; + fontDescriptionRun13.slantDefined = false; + fontDescriptionRun13.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun14; + fontDescriptionRun14.characterRun.characterIndex = 166u; + fontDescriptionRun14.characterRun.numberOfCharacters = 12u; + fontDescriptionRun14.familyLength = fontLatin.size(); + fontDescriptionRun14.familyName = new char[fontDescriptionRun14.familyLength]; + memcpy( fontDescriptionRun14.familyName, fontLatin.c_str(), fontDescriptionRun14.familyLength ); + fontDescriptionRun14.familyDefined = true; + fontDescriptionRun14.weightDefined = false; + fontDescriptionRun14.widthDefined = false; + fontDescriptionRun14.slantDefined = false; + fontDescriptionRun14.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun15; + fontDescriptionRun15.characterRun.characterIndex = 178u; + fontDescriptionRun15.characterRun.numberOfCharacters = 14u; + fontDescriptionRun15.familyLength = fontArabic.size(); + fontDescriptionRun15.familyName = new char[fontDescriptionRun15.familyLength]; + memcpy( fontDescriptionRun15.familyName, fontArabic.c_str(), fontDescriptionRun15.familyLength ); + fontDescriptionRun15.familyDefined = true; + fontDescriptionRun15.weightDefined = false; + fontDescriptionRun15.widthDefined = false; + fontDescriptionRun15.slantDefined = false; + fontDescriptionRun15.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + fontDescriptionRuns.PushBack( fontDescriptionRun07 ); + fontDescriptionRuns.PushBack( fontDescriptionRun08 ); + fontDescriptionRuns.PushBack( fontDescriptionRun09 ); + fontDescriptionRuns.PushBack( fontDescriptionRun10 ); + fontDescriptionRuns.PushBack( fontDescriptionRun11 ); + fontDescriptionRuns.PushBack( fontDescriptionRun12 ); + fontDescriptionRuns.PushBack( fontDescriptionRun13 ); + fontDescriptionRuns.PushBack( fontDescriptionRun14 ); + fontDescriptionRuns.PushBack( fontDescriptionRun15 ); + Size textArea(100.f, 300.f); + Size layoutSize(92.f, 380.f); + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, + 0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f, + 1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f, + 0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f, + 0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f, + 1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f, + 1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f, + 1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f, + 0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f, + 1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f, + 0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f, + 1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f, + 1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f, + 0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f, + 1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f, + 1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f, + 1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f, + 0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f, + }; + struct LineRun line01 = + { + { 0u, 12u }, + { 0u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line02 = + { + { 12u, 10u }, + { 12u, 10u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line03 = + { + { 22u, 6u }, + { 22u, 6u }, + 36.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line04 = + { + { 28u, 20u }, + { 28u, 20u }, + 92.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line05 = + { + { 48u, 11u }, + { 48u, 11u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line06 = + { + { 59u, 5u }, + { 59u, 5u }, + 31.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line07 = + { + { 64u, 10u }, + { 64u, 10u }, + 67.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line08 = + { + { 74u, 12u }, + { 74u, 12u }, + 79.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line09 = + { + { 86u, 6u }, + { 86u, 6u }, + 43.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line10 = + { + { 92u, 12u }, + { 92u, 12u }, + 78.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line11 = + { + { 104u, 19u }, + { 104u, 19u }, + 90.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line12 = + { + { 123u, 5u }, + { 123u, 5u }, + 31.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line13 = + { + { 128u, 12u }, + { 128u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line14 = + { + { 140u, 10u }, + { 140u, 10u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line15 = + { + { 150u, 6u }, + { 150u, 6u }, + 36.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line16 = + { + { 156u, 10u }, + { 156u, 10u }, + 67.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line17 = + { + { 166u, 12u }, + { 166u, 12u }, + 79.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line18 = + { + { 178u, 14u }, + { 178u, 14u }, + 55.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line19 = + { + { 192u, 0u }, + { 192u, 0u }, + 0.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line01 ); + lines.PushBack( line02 ); + lines.PushBack( line03 ); + lines.PushBack( line04 ); + lines.PushBack( line05 ); + lines.PushBack( line06 ); + lines.PushBack( line07 ); + lines.PushBack( line08 ); + lines.PushBack( line09 ); + lines.PushBack( line10 ); + lines.PushBack( line11 ); + lines.PushBack( line12 ); + lines.PushBack( line13 ); + lines.PushBack( line14 ); + lines.PushBack( line15 ); + lines.PushBack( line16 ); + lines.PushBack( line17 ); + lines.PushBack( line18 ); + lines.PushBack( line19 ); + + LayoutTextData data = + { + "Layout bidirectional text.", + "Hello world demo שלום עולם.\n" + "مرحبا بالعالم hello world שלום עולם\n" + "שלום עולם hello world demo.\n" + "hello world مرحبا بالعالم שלום עולם\n" + "Hello world demo שלום עולם.\n" + "שלום עולם hello world مرحبا بالعالم\n", + textArea, + 15u, + fontDescriptionRuns.Begin(), + layoutSize, + 192u, + positions, + 19u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 64u, + 64u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextUpdateLayout03(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextUpdateLayout03"); + + // Layout some lines of bidirectional text. Update the paragraphs at the middle. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 17u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 17u; + fontDescriptionRun02.characterRun.numberOfCharacters = 11u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 28u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 42u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 54u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 64u; + fontDescriptionRun06.characterRun.numberOfCharacters = 10u; + fontDescriptionRun06.familyLength = fontHebrew.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontHebrew.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun07; + fontDescriptionRun07.characterRun.characterIndex = 74u; + fontDescriptionRun07.characterRun.numberOfCharacters = 18u; + fontDescriptionRun07.familyLength = fontLatin.size(); + fontDescriptionRun07.familyName = new char[fontDescriptionRun07.familyLength]; + memcpy( fontDescriptionRun07.familyName, fontLatin.c_str(), fontDescriptionRun07.familyLength ); + fontDescriptionRun07.familyDefined = true; + fontDescriptionRun07.weightDefined = false; + fontDescriptionRun07.widthDefined = false; + fontDescriptionRun07.slantDefined = false; + fontDescriptionRun07.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun08; + fontDescriptionRun08.characterRun.characterIndex = 92u; + fontDescriptionRun08.characterRun.numberOfCharacters = 12u; + fontDescriptionRun08.familyLength = fontLatin.size(); + fontDescriptionRun08.familyName = new char[fontDescriptionRun08.familyLength]; + memcpy( fontDescriptionRun08.familyName, fontLatin.c_str(), fontDescriptionRun08.familyLength ); + fontDescriptionRun08.familyDefined = true; + fontDescriptionRun08.weightDefined = false; + fontDescriptionRun08.widthDefined = false; + fontDescriptionRun08.slantDefined = false; + fontDescriptionRun08.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun09; + fontDescriptionRun09.characterRun.characterIndex = 104u; + fontDescriptionRun09.characterRun.numberOfCharacters = 14u; + fontDescriptionRun09.familyLength = fontArabic.size(); + fontDescriptionRun09.familyName = new char[fontDescriptionRun09.familyLength]; + memcpy( fontDescriptionRun09.familyName, fontArabic.c_str(), fontDescriptionRun09.familyLength ); + fontDescriptionRun09.familyDefined = true; + fontDescriptionRun09.weightDefined = false; + fontDescriptionRun09.widthDefined = false; + fontDescriptionRun09.slantDefined = false; + fontDescriptionRun09.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun10; + fontDescriptionRun10.characterRun.characterIndex = 118u; + fontDescriptionRun10.characterRun.numberOfCharacters = 10u; + fontDescriptionRun10.familyLength = fontHebrew.size(); + fontDescriptionRun10.familyName = new char[fontDescriptionRun10.familyLength]; + memcpy( fontDescriptionRun10.familyName, fontHebrew.c_str(), fontDescriptionRun10.familyLength ); + fontDescriptionRun10.familyDefined = true; + fontDescriptionRun10.weightDefined = false; + fontDescriptionRun10.widthDefined = false; + fontDescriptionRun10.slantDefined = false; + fontDescriptionRun10.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun11; + fontDescriptionRun11.characterRun.characterIndex = 128u; + fontDescriptionRun11.characterRun.numberOfCharacters = 17u; + fontDescriptionRun11.familyLength = fontLatin.size(); + fontDescriptionRun11.familyName = new char[fontDescriptionRun11.familyLength]; + memcpy( fontDescriptionRun11.familyName, fontLatin.c_str(), fontDescriptionRun11.familyLength ); + fontDescriptionRun11.familyDefined = true; + fontDescriptionRun11.weightDefined = false; + fontDescriptionRun11.widthDefined = false; + fontDescriptionRun11.slantDefined = false; + fontDescriptionRun11.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun12; + fontDescriptionRun12.characterRun.characterIndex = 145u; + fontDescriptionRun12.characterRun.numberOfCharacters = 11u; + fontDescriptionRun12.familyLength = fontHebrew.size(); + fontDescriptionRun12.familyName = new char[fontDescriptionRun12.familyLength]; + memcpy( fontDescriptionRun12.familyName, fontHebrew.c_str(), fontDescriptionRun12.familyLength ); + fontDescriptionRun12.familyDefined = true; + fontDescriptionRun12.weightDefined = false; + fontDescriptionRun12.widthDefined = false; + fontDescriptionRun12.slantDefined = false; + fontDescriptionRun12.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun13; + fontDescriptionRun13.characterRun.characterIndex = 156u; + fontDescriptionRun13.characterRun.numberOfCharacters = 10u; + fontDescriptionRun13.familyLength = fontHebrew.size(); + fontDescriptionRun13.familyName = new char[fontDescriptionRun13.familyLength]; + memcpy( fontDescriptionRun13.familyName, fontHebrew.c_str(), fontDescriptionRun13.familyLength ); + fontDescriptionRun13.familyDefined = true; + fontDescriptionRun13.weightDefined = false; + fontDescriptionRun13.widthDefined = false; + fontDescriptionRun13.slantDefined = false; + fontDescriptionRun13.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun14; + fontDescriptionRun14.characterRun.characterIndex = 166u; + fontDescriptionRun14.characterRun.numberOfCharacters = 12u; + fontDescriptionRun14.familyLength = fontLatin.size(); + fontDescriptionRun14.familyName = new char[fontDescriptionRun14.familyLength]; + memcpy( fontDescriptionRun14.familyName, fontLatin.c_str(), fontDescriptionRun14.familyLength ); + fontDescriptionRun14.familyDefined = true; + fontDescriptionRun14.weightDefined = false; + fontDescriptionRun14.widthDefined = false; + fontDescriptionRun14.slantDefined = false; + fontDescriptionRun14.sizeDefined = false; + + // Set a known font description + FontDescriptionRun fontDescriptionRun15; + fontDescriptionRun15.characterRun.characterIndex = 178u; + fontDescriptionRun15.characterRun.numberOfCharacters = 14u; + fontDescriptionRun15.familyLength = fontArabic.size(); + fontDescriptionRun15.familyName = new char[fontDescriptionRun15.familyLength]; + memcpy( fontDescriptionRun15.familyName, fontArabic.c_str(), fontDescriptionRun15.familyLength ); + fontDescriptionRun15.familyDefined = true; + fontDescriptionRun15.weightDefined = false; + fontDescriptionRun15.widthDefined = false; + fontDescriptionRun15.slantDefined = false; + fontDescriptionRun15.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + fontDescriptionRuns.PushBack( fontDescriptionRun07 ); + fontDescriptionRuns.PushBack( fontDescriptionRun08 ); + fontDescriptionRuns.PushBack( fontDescriptionRun09 ); + fontDescriptionRuns.PushBack( fontDescriptionRun10 ); + fontDescriptionRuns.PushBack( fontDescriptionRun11 ); + fontDescriptionRuns.PushBack( fontDescriptionRun12 ); + fontDescriptionRuns.PushBack( fontDescriptionRun13 ); + fontDescriptionRuns.PushBack( fontDescriptionRun14 ); + fontDescriptionRuns.PushBack( fontDescriptionRun15 ); + Size textArea(100.f, 300.f); + Size layoutSize(92.f, 380.f); + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, + 0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f, + 1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f, + 0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f, + 0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f, + 1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f, + 1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f, + 1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f, + 0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f, + 1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f, + 0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f, + 1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f, + 1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f, + 0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f, + 1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f, + 1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f, + 1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f, + 0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f, + }; + struct LineRun line01 = + { + { 0u, 12u }, + { 0u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line02 = + { + { 12u, 10u }, + { 12u, 10u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line03 = + { + { 22u, 6u }, + { 22u, 6u }, + 36.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line04 = + { + { 28u, 20u }, + { 28u, 20u }, + 92.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line05 = + { + { 48u, 11u }, + { 48u, 11u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line06 = + { + { 59u, 5u }, + { 59u, 5u }, + 31.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line07 = + { + { 64u, 10u }, + { 64u, 10u }, + 67.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line08 = + { + { 74u, 12u }, + { 74u, 12u }, + 79.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line09 = + { + { 86u, 6u }, + { 86u, 6u }, + 43.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line10 = + { + { 92u, 12u }, + { 92u, 12u }, + 78.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line11 = + { + { 104u, 19u }, + { 104u, 19u }, + 90.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line12 = + { + { 123u, 5u }, + { 123u, 5u }, + 31.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line13 = + { + { 128u, 12u }, + { 128u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line14 = + { + { 140u, 10u }, + { 140u, 10u }, + 76.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line15 = + { + { 150u, 6u }, + { 150u, 6u }, + 36.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line16 = + { + { 156u, 10u }, + { 156u, 10u }, + 67.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line17 = + { + { 166u, 12u }, + { 166u, 12u }, + 79.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + false + }; + struct LineRun line18 = + { + { 178u, 14u }, + { 178u, 14u }, + 55.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + struct LineRun line19 = + { + { 192u, 0u }, + { 192u, 0u }, + 0.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + false + }; + Vector lines; + lines.PushBack( line01 ); + lines.PushBack( line02 ); + lines.PushBack( line03 ); + lines.PushBack( line04 ); + lines.PushBack( line05 ); + lines.PushBack( line06 ); + lines.PushBack( line07 ); + lines.PushBack( line08 ); + lines.PushBack( line09 ); + lines.PushBack( line10 ); + lines.PushBack( line11 ); + lines.PushBack( line12 ); + lines.PushBack( line13 ); + lines.PushBack( line14 ); + lines.PushBack( line15 ); + lines.PushBack( line16 ); + lines.PushBack( line17 ); + lines.PushBack( line18 ); + lines.PushBack( line19 ); + + LayoutTextData data = + { + "Layout bidirectional text.", + "Hello world demo שלום עולם.\n" + "مرحبا بالعالم hello world שלום עולם\n" + "שלום עולם hello world demo.\n" + "hello world مرحبا بالعالم שלום עולם\n" + "Hello world demo שלום עולם.\n" + "שלום עולם hello world مرحبا بالعالم\n", + textArea, + 15u, + fontDescriptionRuns.Begin(), + layoutSize, + 192u, + positions, + 19u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 128u, + 64u, + false, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutEllipsis01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutEllipsis01"); + + // Layout single-line LTR text with ellipsis. + + const std::string fontLatin( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 51u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + + struct LineRun line01 = + { + { 0u, 13u }, + { 0u, 13u }, + 93.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + true + }; + Vector lines; + lines.PushBack( line01 ); + + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, 83.f, 2.f + }; + + Size textArea( 100.f, 50.f ); + Size layoutSize( 100.f, 20.f ); + + LayoutTextData data = + { + "Layout single-line LTR text with ellipsis.", + "Hello world demo hello world demo hello world demo.", + textArea, + 1u, + fontDescriptionRuns.Begin(), + layoutSize, + 13u, + positions, + 1u, + lines.Begin(), + LayoutEngine::SINGLE_LINE_BOX, + 0u, + 51u, + true, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutEllipsis02(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutEllipsis02"); + + // Layout multi-line LTR text with ellipsis. + + const std::string fontLatin( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 51u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + + struct LineRun line01 = + { + { 0u, 12u }, + { 0u, 12u }, + 81.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line02 = + { + { 12u, 12u }, + { 12u, 12u }, + 93.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + true + }; + Vector lines; + lines.PushBack( line01 ); + lines.PushBack( line02 ); + + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, + 0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 22.f, 53.f, 26.f, 61.f, 22.f, 65.f, 22.f, 68.f, 26.f, 77.f, 35.f, 81.f, 26.f + }; + + Size textArea( 100.f, 50.f ); + Size layoutSize( 100.f, 60.f ); + + LayoutTextData data = + { + "Layout multi-line LTR text with ellipsis.", + "Hello world demo hello world demo hello world demo.", + textArea, + 1u, + fontDescriptionRuns.Begin(), + layoutSize, + 24u, + positions, + 2u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 51u, + true, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutEllipsis03(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutEllipsis03"); + + // Layout single-line RTL text with ellipsis. + + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 10u; + fontDescriptionRun01.familyLength = fontHebrew.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 10u; + fontDescriptionRun02.characterRun.numberOfCharacters = 14u; + fontDescriptionRun02.familyLength = fontArabic.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 24u; + fontDescriptionRun03.characterRun.numberOfCharacters = 10u; + fontDescriptionRun03.familyLength = fontHebrew.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontHebrew.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 34u; + fontDescriptionRun04.characterRun.numberOfCharacters = 14u; + fontDescriptionRun04.familyLength = fontArabic.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontArabic.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 58u; + fontDescriptionRun06.characterRun.numberOfCharacters = 15u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + struct LineRun line01 = + { + { 0u, 16u }, + { 0u, 16u }, + 95.f, + 15.f, + -5.f, + 0.f, + 0.f, + false, + true + }; + Vector lines; + lines.PushBack( line01 ); + + float positions[] = + { + 1.f, 5.f, 12.f, 2.f, 19.f, 5.f, 24.f, 5.f, 32.f, 15.f, 37.f, 5.f, 45.f, 5.f, 50.f, 2.f, 58.f, 5.f, 66.f, 15.f, 69.f, 7.f, 76.f, 9.f, 81.f, 8.f, 87.f, 8.f, 92.f, 4.f, 94.f, 15.f, + }; + + Size textArea( 100.f, 50.f ); + Size layoutSize( 100.f, 20.f ); + + LayoutTextData data = + { + "Layout single-line RTL text with ellipsis.", + "שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + layoutSize, + 16u, + positions, + 1u, + lines.Begin(), + LayoutEngine::SINGLE_LINE_BOX, + 0u, + 72u, + true, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextLayoutEllipsis04(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLayoutEllipsis04"); + + // Layout multi-line RTL text with ellipsis. + + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 10u; + fontDescriptionRun01.familyLength = fontHebrew.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 10u; + fontDescriptionRun02.characterRun.numberOfCharacters = 14u; + fontDescriptionRun02.familyLength = fontArabic.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 24u; + fontDescriptionRun03.characterRun.numberOfCharacters = 10u; + fontDescriptionRun03.familyLength = fontHebrew.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontHebrew.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 34u; + fontDescriptionRun04.characterRun.numberOfCharacters = 14u; + fontDescriptionRun04.familyLength = fontArabic.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontArabic.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 58u; + fontDescriptionRun06.characterRun.numberOfCharacters = 15u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + struct LineRun line01 = + { + { 0u, 16u }, + { 0u, 16u }, + 96.f, + 15.f, + -5.f, + 3.f, + 0.f, + false, + false + }; + struct LineRun line02 = + { + { 16u, 18u }, + { 16u, 18u }, + 97.f, + 15.f, + -5.f, + 4.f, + 0.f, + false, + true + }; + Vector lines; + lines.PushBack( line01 ); + lines.PushBack( line02 ); + + float positions[] = + { + 1.f, 5.f, 12.f, 2.f, 19.f, 5.f, 24.f, 5.f, 32.f, 15.f, 37.f, 5.f, 45.f, 5.f, 50.f, 2.f, 58.f, 5.f, 66.f, 15.f, 69.f, 7.f, 76.f, 9.f, 81.f, 8.f, 87.f, 8.f, 92.f, 4.f, 94.f, 15.f, + 0.f, 28.f, 5.f, 24.f, 6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f, 32.f, 25.f, 43.f, 22.f, 50.f, 25.f, 55.f, 25.f, 63.f, 35.f, 68.f, 25.f, 76.f, 25.f, 81.f, 22.f, 89.f, 25.f, 97.f, 35.f + }; + + Size textArea( 100.f, 50.f ); + Size layoutSize( 100.f, 60.f ); + + LayoutTextData data = + { + "Layout single-line RTL text with ellipsis.", + "שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + layoutSize, + 34u, + positions, + 2u, + lines.Begin(), + LayoutEngine::MULTI_LINE_BOX, + 0u, + 72u, + true, + true + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextReorderLayout01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextReorderLayout01"); + + // Reorder lines. No right to left characters. + + const std::string fontLatin( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 11u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + + float positions[] = + { + 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f + }; + + Size textArea( 100.f, 300.f ); + + ReLayoutRightToLeftLinesData data = + { + "Text with no right to left text.", + "Hello world", + textArea, + 1u, + fontDescriptionRuns.Begin(), + 11u, + positions, + 0u, + 11u + }; + + if( !ReLayoutRightToLeftLinesTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextReorderLayout02(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextReorderLayout02"); + + // Reorder lines of the first paragraph. + + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 10u; + fontDescriptionRun01.familyLength = fontHebrew.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 10u; + fontDescriptionRun02.characterRun.numberOfCharacters = 14u; + fontDescriptionRun02.familyLength = fontArabic.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 24u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 38u; + fontDescriptionRun04.characterRun.numberOfCharacters = 10u; + fontDescriptionRun04.familyLength = fontHebrew.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontHebrew.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 58u; + fontDescriptionRun06.characterRun.numberOfCharacters = 15u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = + { + 87.f, 5.f, 79.f, 2.f, 74.f, 5.f, 66.f, 5.f, 61.f, 15.f, 53.f, 5.f, 48.f, 5.f, 41.f, 2.f, 32.f, 5.f, 27.f, 15.f, 20.f, 7.f, 15.f, 9.f, 8.f, 8.f, 5.f, 8.f, 4.f, 4.f, 0.f, 15.f, + 23.f, 28.f, 22.f, 24.f, 17.f, 24.f, 12.f, 27.f, 10.f, 24.f, 5.f, 24.f, 0.f, 27.f, 0.f, 35.f, + 0.f, 47.f, 7.f, 49.f, 12.f, 48.f, 18.f, 48.f, 23.f, 44.f, 25.f, 55.f, 27.f, 48.f, 32.f, 44.f, 33.f, 44.f, 37.f, 47.f, 44.f, 44.f, 45.f, 44.f, 49.f, 47.f, 55.f, 55.f, 59.f, 45.f, 70.f, 42.f, 77.f, 45.f, 82.f, 45.f, 90.f, 55.f, + 1.f, 65.f, 9.f, 65.f, 14.f, 62.f, 22.f, 65.f, 30.f, 75.f, + 1.f, 85.f, 12.f, 82.f, 19.f, 85.f, 24.f, 85.f, 32.f, 95.f, 37.f, 85.f, 45.f, 85.f, 50.f, 82.f, 58.f, 85.f, 66.f, 95.f, 69.f, 87.f, 76.f, 89.f, 81.f, 88.f, 87.f, 88.f, 92.f, 84.f, 94.f, 95.f, + 0.f, 108.f, 5.f, 104.f, 6.f, 104.f, 10.f, 107.f, 17.f, 104.f, 18.f, 104.f, 22.f, 107.f, 30.f, 113.f + }; + + Size textArea( 100.f, 300.f ); + + ReLayoutRightToLeftLinesData data = + { + "Paragraphs with right to left text.", + "שלום עולם مرحبا بالعالم\n" + "مرحبا بالعالم שלום עולם\n" + "שלום עולם مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + 72u, + positions, + 0u, + 24u + }; + + if( !ReLayoutRightToLeftLinesTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextReorderLayout03(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextReorderLayout03"); + + // Reorder lines of the mid paragraph. + + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 10u; + fontDescriptionRun01.familyLength = fontHebrew.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 10u; + fontDescriptionRun02.characterRun.numberOfCharacters = 14u; + fontDescriptionRun02.familyLength = fontArabic.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 24u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 38u; + fontDescriptionRun04.characterRun.numberOfCharacters = 10u; + fontDescriptionRun04.familyLength = fontHebrew.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontHebrew.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 58u; + fontDescriptionRun06.characterRun.numberOfCharacters = 15u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = + { + 1.f, 5.f, 12.f, 2.f, 19.f, 5.f, 24.f, 5.f, 32.f, 15.f, 37.f, 5.f, 45.f, 5.f, 50.f, 2.f, 58.f, 5.f, 66.f, 15.f, 69.f, 7.f, 76.f, 9.f, 81.f, 8.f, 87.f, 8.f, 92.f, 4.f, 94.f, 15.f, + 0.f, 28.f, 5.f, 24.f, 6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f, + 86.f, 47.f, 81.f, 49.f, 74.f, 48.f, 71.f, 48.f, 70.f, 44.f, 66.f, 55.f, 62.f, 48.f, 61.f, 44.f, 56.f, 44.f, 51.f, 47.f, 49.f, 44.f, 44.f, 44.f, 39.f, 47.f, 36.f, 55.f, 26.f, 45.f, 18.f, 42.f, 13.f, 45.f, 5.f, 45.f, 0.f, 55.f, + 22.f, 65.f, 17.f, 65.f, 10.f, 62.f, 1.f, 65.f, 0.f, 75.f, + 1.f, 85.f, 12.f, 82.f, 19.f, 85.f, 24.f, 85.f, 32.f, 95.f, 37.f, 85.f, 45.f, 85.f, 50.f, 82.f, 58.f, 85.f, 66.f, 95.f, 69.f, 87.f, 76.f, 89.f, 81.f, 88.f, 87.f, 88.f, 92.f, 84.f, 94.f, 95.f, + 0.f, 108.f, 5.f, 104.f, 6.f, 104.f, 10.f, 107.f, 17.f, 104.f, 18.f, 104.f, 22.f, 107.f, 30.f, 113.f + }; + + Size textArea( 100.f, 300.f ); + + ReLayoutRightToLeftLinesData data = + { + "Paragraphs with right to left text.", + "שלום עולם مرحبا بالعالم\n" + "مرحبا بالعالم שלום עולם\n" + "שלום עולם مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + 72u, + positions, + 24u, + 24u + }; + + if( !ReLayoutRightToLeftLinesTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextReorderLayout04(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextReorderLayout04"); + + // Reorder lines of the last paragraph. + + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 10u; + fontDescriptionRun01.familyLength = fontHebrew.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 10u; + fontDescriptionRun02.characterRun.numberOfCharacters = 14u; + fontDescriptionRun02.familyLength = fontArabic.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 24u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 38u; + fontDescriptionRun04.characterRun.numberOfCharacters = 10u; + fontDescriptionRun04.familyLength = fontHebrew.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontHebrew.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 10u; + fontDescriptionRun05.familyLength = fontHebrew.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 58u; + fontDescriptionRun06.characterRun.numberOfCharacters = 15u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = + { + 1.f, 5.f, 12.f, 2.f, 19.f, 5.f, 24.f, 5.f, 32.f, 15.f, 37.f, 5.f, 45.f, 5.f, 50.f, 2.f, 58.f, 5.f, 66.f, 15.f, 69.f, 7.f, 76.f, 9.f, 81.f, 8.f, 87.f, 8.f, 92.f, 4.f, 94.f, 15.f, + 0.f, 28.f, 5.f, 24.f, 6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f, + 0.f, 47.f, 7.f, 49.f, 12.f, 48.f, 18.f, 48.f, 23.f, 44.f, 25.f, 55.f, 27.f, 48.f, 32.f, 44.f, 33.f, 44.f, 37.f, 47.f, 44.f, 44.f, 45.f, 44.f, 49.f, 47.f, 55.f, 55.f, 59.f, 45.f, 70.f, 42.f, 77.f, 45.f, 82.f, 45.f, 90.f, 55.f, + 1.f, 65.f, 9.f, 65.f, 14.f, 62.f, 22.f, 65.f, 30.f, 75.f, + 87.f, 85.f, 79.f, 82.f, 74.f, 85.f, 66.f, 85.f, 61.f, 95.f, 53.f, 85.f, 48.f, 85.f, 41.f, 82.f, 32.f, 85.f, 27.f, 95.f, 20.f, 87.f, 15.f, 89.f, 8.f, 88.f, 5.f, 88.f, 4.f, 84.f, 0.f, 95.f, + 28.f, 108.f, 27.f, 104.f, 22.f, 104.f, 17.f, 107.f, 15.f, 104.f, 10.f, 104.f, 5.f, 107.f, 2.f, 113.f + }; + + Size textArea( 100.f, 300.f ); + + ReLayoutRightToLeftLinesData data = + { + "Paragraphs with right to left text.", + "שלום עולם مرحبا بالعالم\n" + "مرحبا بالعالم שלום עולם\n" + "שלום עולם مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + 72u, + positions, + 48u, + 24u + }; + + if( !ReLayoutRightToLeftLinesTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign01"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "Begin alignment for the first paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_BEGIN, + LayoutEngine::VERTICAL_ALIGN_TOP, + 0u, + 22u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign02(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign02"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 0.f, 0.f, 2.f, 60.f, 0.f, 0.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "Begin alignment for the mid paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_BEGIN, + LayoutEngine::VERTICAL_ALIGN_TOP, + 22u, + 26u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign03(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign03"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "Begin alignment for the last paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_BEGIN, + LayoutEngine::VERTICAL_ALIGN_TOP, + 48u, + 26u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign04(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign04"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 10.f, 16.f, 0.f, 0.f, 0.f, 0.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "Center alignment for the first paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_CENTER, + LayoutEngine::VERTICAL_ALIGN_TOP, + 0u, + 22u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign05(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign05"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 0.f, 0.f, -1.f, 30.f, 0.f, 0.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "Center alignment for the mid paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_CENTER, + LayoutEngine::VERTICAL_ALIGN_TOP, + 22u, + 26u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign06(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign06"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 0.f, 0.f, 0.f, 0.f, 10.f, 20.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "Center alignment for the last paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_CENTER, + LayoutEngine::VERTICAL_ALIGN_TOP, + 48u, + 26u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign07(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign07"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 20.f, 33.f, 0.f, 0.f, 0.f, 0.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "End alignment for the first paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_END, + LayoutEngine::VERTICAL_ALIGN_TOP, + 0u, + 22u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign08(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign08"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 0.f, 0.f, -4.f, 0.f, 0.f, 0.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "End alignment for the mid paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_END, + LayoutEngine::VERTICAL_ALIGN_TOP, + 22u, + 26u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextAlign09(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextAlign09"); + + // Calculate text alignment. + + const std::string fontLatin( "TizenSans" ); + const std::string fontHebrew( "TizenSansHebrew" ); + const std::string fontArabic( "TizenSansArabic" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun01; + fontDescriptionRun01.characterRun.characterIndex = 0u; + fontDescriptionRun01.characterRun.numberOfCharacters = 12u; + fontDescriptionRun01.familyLength = fontLatin.size(); + fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength]; + memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength ); + fontDescriptionRun01.familyDefined = true; + fontDescriptionRun01.weightDefined = false; + fontDescriptionRun01.widthDefined = false; + fontDescriptionRun01.slantDefined = false; + fontDescriptionRun01.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun02; + fontDescriptionRun02.characterRun.characterIndex = 12u; + fontDescriptionRun02.characterRun.numberOfCharacters = 10u; + fontDescriptionRun02.familyLength = fontHebrew.size(); + fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength]; + memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength ); + fontDescriptionRun02.familyDefined = true; + fontDescriptionRun02.weightDefined = false; + fontDescriptionRun02.widthDefined = false; + fontDescriptionRun02.slantDefined = false; + fontDescriptionRun02.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun03; + fontDescriptionRun03.characterRun.characterIndex = 22u; + fontDescriptionRun03.characterRun.numberOfCharacters = 14u; + fontDescriptionRun03.familyLength = fontArabic.size(); + fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength]; + memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength ); + fontDescriptionRun03.familyDefined = true; + fontDescriptionRun03.weightDefined = false; + fontDescriptionRun03.widthDefined = false; + fontDescriptionRun03.slantDefined = false; + fontDescriptionRun03.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun04; + fontDescriptionRun04.characterRun.characterIndex = 36u; + fontDescriptionRun04.characterRun.numberOfCharacters = 12u; + fontDescriptionRun04.familyLength = fontLatin.size(); + fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength]; + memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength ); + fontDescriptionRun04.familyDefined = true; + fontDescriptionRun04.weightDefined = false; + fontDescriptionRun04.widthDefined = false; + fontDescriptionRun04.slantDefined = false; + fontDescriptionRun04.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun05; + fontDescriptionRun05.characterRun.characterIndex = 48u; + fontDescriptionRun05.characterRun.numberOfCharacters = 12u; + fontDescriptionRun05.familyLength = fontLatin.size(); + fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength]; + memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength ); + fontDescriptionRun05.familyDefined = true; + fontDescriptionRun05.weightDefined = false; + fontDescriptionRun05.widthDefined = false; + fontDescriptionRun05.slantDefined = false; + fontDescriptionRun05.sizeDefined = false; + + FontDescriptionRun fontDescriptionRun06; + fontDescriptionRun06.characterRun.characterIndex = 60u; + fontDescriptionRun06.characterRun.numberOfCharacters = 14u; + fontDescriptionRun06.familyLength = fontArabic.size(); + fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength]; + memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength ); + fontDescriptionRun06.familyDefined = true; + fontDescriptionRun06.weightDefined = false; + fontDescriptionRun06.widthDefined = false; + fontDescriptionRun06.slantDefined = false; + fontDescriptionRun06.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun01 ); + fontDescriptionRuns.PushBack( fontDescriptionRun02 ); + fontDescriptionRuns.PushBack( fontDescriptionRun03 ); + fontDescriptionRuns.PushBack( fontDescriptionRun04 ); + fontDescriptionRuns.PushBack( fontDescriptionRun05 ); + fontDescriptionRuns.PushBack( fontDescriptionRun06 ); + + float positions[] = { 0.f, 0.f, 0.f, 0.f, 20.f, 40.f }; + + Size textArea( 100.f, 300.f ); + AlignData data = + { + "End alignment for the last paragraph.", + "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.", + textArea, + 6u, + fontDescriptionRuns.Begin(), + LayoutEngine::HORIZONTAL_ALIGN_END, + LayoutEngine::VERTICAL_ALIGN_TOP, + 48u, + 26u, + 6u, + positions + }; + + if( !AlignTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp index f602e8a..7fc8f71 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp @@ -245,7 +245,6 @@ bool ValidateFontTest( const ValidateFontsData& data ) const FontId defaultFontId = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + data.defaultFont, data.defaultFontSize ); - // To be completed ... Vector fontRuns; // 3) Validate the fonts. diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp index 0dd3144..9e830ec 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp @@ -117,8 +117,12 @@ bool ShapeInfoTest( const ShapeInfoData& data ) Size textArea(100.f, 60.f); Size layoutSize; + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp index 18faa9e..fdde254 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp @@ -70,8 +70,12 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data ) Size textArea(100.f, 60.f); Size layoutSize; + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); @@ -142,8 +146,12 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data ) Size textArea(100.f, 60.f); Size layoutSize; + const Vector fontDescriptions; + const LayoutOptions options; CreateTextModel( data.text, textArea, + fontDescriptions, + options, layoutSize, logicalModel, visualModel ); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp index 6786bc5..5bde6be 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp @@ -97,6 +97,8 @@ void ClearModelData( CharacterIndex characterIndex, void CreateTextModel( const std::string& text, const Size& textArea, + const Vector& fontDescriptions, + const LayoutOptions& options, Size& layoutSize, LogicalModelPtr logicalModel, VisualModelPtr visualModel ) @@ -142,6 +144,7 @@ void CreateTextModel( const std::string& text, // 4) Set the font info Vector& fontDescriptionRuns = logicalModel->mFontDescriptionRuns; + fontDescriptionRuns = fontDescriptions; Vector& validFonts = logicalModel->mFontRuns; // The default font id. @@ -262,27 +265,29 @@ void CreateTextModel( const std::string& text, // Set the layout parameters. const Vector& charactersToGlyph = visualModel->mCharactersToGlyph; const Vector& glyphsPerCharacter = visualModel->mGlyphsPerCharacter; + LayoutParameters layoutParameters( textArea, utf32Characters.Begin(), lineBreakInfo.Begin(), wordBreakInfo.Begin(), ( 0u != characterDirections.Count() ) ? characterDirections.Begin() : NULL, - glyphs.Count(), glyphs.Begin(), glyphsToCharactersMap.Begin(), - charactersPerGlyph.Begin() ); - - // Get the character to glyph conversion table and set into the layout. - layoutParameters.charactersToGlyphsBuffer = charactersToGlyph.Begin(); - // Get the glyphs per character table and set into the layout. - layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin(); + charactersPerGlyph.Begin(), + charactersToGlyph.Begin(), + glyphsPerCharacter.Begin(), + numberOfGlyphs ); Vector& lines = visualModel->mLines; Vector& glyphPositions = visualModel->mGlyphPositions; glyphPositions.Resize( numberOfGlyphs ); - layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( logicalModel->mText.Count() - 1u ) ) ); + layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( numberOfCharacters - 1u ) ) ); + + // The initial glyph and the number of glyphs to layout. + layoutParameters.startGlyphIndex = 0u; + layoutParameters.numberOfGlyphs = numberOfGlyphs; layoutEngine.LayoutText( layoutParameters, glyphPositions, @@ -315,9 +320,22 @@ void CreateTextModel( const std::string& text, 0u, numberOfCharacters ); - // Re-layout the text. Reorder those lines with right to left characters. - layoutEngine.ReLayoutRightToLeftLines( layoutParameters, - glyphPositions ); + if( options.reorder ) + { + // Re-layout the text. Reorder those lines with right to left characters. + layoutEngine.ReLayoutRightToLeftLines( layoutParameters, + 0u, + numberOfCharacters, + glyphPositions ); + } + } + + if( options.align ) + { + layoutEngine.Align( textArea, + 0u, + numberOfCharacters, + lines ); } } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.h index 02dbbcd..631b151 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.h @@ -34,17 +34,35 @@ namespace Text { /** + * @brief Some layout options. + */ +struct LayoutOptions +{ + LayoutOptions() + : reorder( true ), + align( true ) + {} + + bool reorder : 1; ///< Whether to reorder the bidirectional lines. + bool align : 1; ///< Whether to align the lines. +}; + +/** * @brief Creates and fills all the vectors of a text model: characters in utf32, segmentation info, * scripts, fonts, bidi info, glyphs, conversion tables, etc. * * @param[in] text The given text. * @param[in] textArea The area where to layout the text. + * @param[in] fontDescriptions The fonts to be used. + * @param[in] options Layout options. * @param[out] layoutSize The laid-out size. - * @param[out] Pointer to a logical text model instance. - * @param[out] Pointer to a visual text model instance. + * @param[out] logicalModel Pointer to a logical text model instance. + * @param[out] visualModel Pointer to a visual text model instance. */ void CreateTextModel( const std::string& text, const Size& textArea, + const Vector& fontDescriptions, + const LayoutOptions& options, Size& layoutSize, LogicalModelPtr logicalModel, VisualModelPtr visualModel ); diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp index a029c83..f0c3fc6 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -883,9 +883,11 @@ void TextEditor::RenderText() if( mRenderableActor ) { - const Vector2 offset = mController->GetScrollPosition() + mController->GetAlignmentOffset(); + // TODO: Scroll and alignment needs to be refactored. + const Vector2& alignmentOffset = mController->GetAlignmentOffset(); + const Vector2& scrollOffset = mController->GetScrollPosition(); - mRenderableActor.SetPosition( offset.x, offset.y ); + mRenderableActor.SetPosition( scrollOffset.x, alignmentOffset.y + scrollOffset.y ); Actor clipRootActor; if( mClipper ) diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index a0417df..981b228 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -1089,9 +1089,11 @@ void TextField::RenderText() if( mRenderableActor ) { - const Vector2 offset = mController->GetScrollPosition() + mController->GetAlignmentOffset(); + // TODO: Scroll and alignment needs to be refactored. + const Vector2& alignmentOffset = mController->GetAlignmentOffset(); + const Vector2& scrollOffset = mController->GetScrollPosition(); - mRenderableActor.SetPosition( offset.x, offset.y ); + mRenderableActor.SetPosition( scrollOffset.x, alignmentOffset.y + scrollOffset.y ); Actor clipRootActor; if( mClipper ) diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index f717bbf..7ad0bfb 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -546,8 +546,9 @@ void TextLabel::RenderText() if( renderableActor ) { + // TODO: Scroll and alignment needs to be refactored. const Vector2& alignmentOffset = mController->GetAlignmentOffset(); - renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y ); + renderableActor.SetPosition( 0.f, alignmentOffset.y ); self.Add( renderableActor ); } diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index ad513a8..9d81116 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -47,6 +47,26 @@ const float MAX_FLOAT = std::numeric_limits::max(); const bool RTL = true; const float CURSOR_WIDTH = 1.f; +Length CountParagraphs( const LayoutParameters& layoutParameters ) +{ + Length numberOfParagraphs = 0u; + + const CharacterIndex startCharacterIndex = *( layoutParameters.glyphsToCharactersBuffer + layoutParameters.startGlyphIndex ); + + const GlyphIndex lastGlyphIndex = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs - 1u; + const CharacterIndex lastCharacterIndexPlusOne = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex ); + + for( CharacterIndex index = startCharacterIndex; index < lastCharacterIndexPlusOne; ++index ) + { + if( TextAbstraction::LINE_MUST_BREAK == *( layoutParameters.lineBreakInfoBuffer + index ) ) + { + ++numberOfParagraphs; + } + } + + return numberOfParagraphs; +} + } //namespace /** @@ -172,7 +192,7 @@ struct LayoutEngine::Impl * @note This method lais out text as it were left to right. At this point is not possible to reorder the line * because the number of characters of the line is not known (one of the responsabilities of this method * is calculate that). Due to glyph's 'x' bearing, width and advance, when right to left or mixed right to left - * and left to right text is laid out, it can be small differences in the line length. One solution is to + * and left to right text is laid-out, it can be small differences in the line length. One solution is to * reorder and re-lay out the text after this method and add or remove one extra glyph if needed. However, * this method calculates which are the first and last glyphs of the line (the ones that causes the * differences). This is a good point to check if there is problems with the text exceeding the boundaries @@ -219,8 +239,9 @@ struct LayoutEngine::Impl bool oneWordLaidOut = false; + const GlyphIndex lastGlyphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs; for( GlyphIndex glyphIndex = lineLayout.glyphIndex; - glyphIndex < parameters.totalNumberOfGlyphs; + glyphIndex < lastGlyphPlusOne; ++glyphIndex ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, " glyph index : %d\n", glyphIndex ); @@ -369,7 +390,7 @@ struct LayoutEngine::Impl { DALI_LOG_INFO( gLogFilter, Debug::Verbose, " Break the word by character\n" ); - // The word's with doesn't fit in the control's with. It needs to be split by character. + // The word doesn't fit in the control's width. It needs to be split by character. if( tmpLineLayout.numberOfGlyphs > 0u ) { tmpLineLayout.numberOfCharacters -= charactersPerGlyph; @@ -420,7 +441,7 @@ struct LayoutEngine::Impl ( TextAbstraction::WORD_BREAK == wordBreakInfo ) ) { oneWordLaidOut = true; - DALI_LOG_INFO( gLogFilter, Debug::Verbose, " One word laid out\n" ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, " One word laid-out\n" ); // Current glyph is the last one of the current word. // Add the temporal layout to the current one. @@ -438,6 +459,34 @@ struct LayoutEngine::Impl DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" ); } + /** + * @brief Calculates the vertical offset to add to the new laid-out glyphs. + * + * @pre @p lineIndex must be between 0 and the number of lines (both inclusive). + * + * @param[in] lines The previously laid-out lines. + * @param[in] lineIndex Index to the line where the new laid-out lines are inserted. + * + * @return The vertical offset of the lines starting from the beginning to the line @p lineIndex. + */ + float SetParagraphOffset( const Vector& lines, + LineIndex lineIndex ) + { + float offset = 0.f; + + for( Vector::ConstIterator it = lines.Begin(), + endIt = lines.Begin() + lineIndex; + it != endIt; + ++it ) + { + const LineRun& line = *it; + + offset += line.ascender + -line.descender; + } + + return offset; + } + void SetGlyphPositions( const GlyphInfo* const glyphsBuffer, Length numberOfGlyphs, float penY, @@ -464,19 +513,327 @@ struct LayoutEngine::Impl } } + /** + * @brief Resizes the line buffer. + * + * @param[in,out] lines The vector of lines. Used when the layout is created from scratch. + * @param[in,out] newLines The vector of lines used instead of @p lines when the layout is updated. + * @param[in,out] linesCapacity The capacity of the vector (either lines or newLines). + * @param[in] updateCurrentBuffer Whether the layout is updated. + * + * @return Pointer to either lines or newLines. + */ + LineRun* ResizeLinesBuffer( Vector& lines, + Vector& newLines, + Length& linesCapacity, + bool updateCurrentBuffer ) + { + LineRun* linesBuffer = NULL; + // Reserve more space for the next lines. + linesCapacity *= 2u; + if( updateCurrentBuffer ) + { + newLines.Resize( linesCapacity ); + linesBuffer = newLines.Begin(); + } + else + { + lines.Resize( linesCapacity ); + linesBuffer = lines.Begin(); + } + + return linesBuffer; + } + + /** + * Ellipsis a line if it exceeds the width's of the bounding box. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in] layout The line layout. + * @param[in,out] layoutSize The text's layout size. + * @param[in,out] linesBuffer Pointer to the line's buffer. + * @param[in,out] glyphPositionsBuffer Pointer to the position's buffer. + * @param[in,out] numberOfLines The number of laid-out lines. + * @param[in] penY The vertical layout position. + * @param[in] currentParagraphDirection The current paragraph's direction. + * + * return Whether the line is ellipsized. + */ + bool EllipsisLine( const LayoutParameters& layoutParameters, + const LineLayout& layout, + Size& layoutSize, + LineRun* linesBuffer, + Vector2* glyphPositionsBuffer, + Length& numberOfLines, + float penY, + CharacterDirection currentParagraphDirection ) + { + const bool ellipsis = ( ( penY - layout.descender > layoutParameters.boundingBox.height ) || + ( ( mLayout == SINGLE_LINE_BOX ) && + ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) ); + + if( ellipsis ) + { + // Do not layout more lines if ellipsis is enabled. + + // The last line needs to be completely filled with characters. + // Part of a word may be used. + + LineRun* lineRun = NULL; + LineLayout ellipsisLayout; + if( 0u != numberOfLines ) + { + // Get the last line and layout it again with the 'completelyFill' flag to true. + lineRun = linesBuffer + ( numberOfLines - 1u ); + + penY -= layout.ascender - lineRun->descender; + + ellipsisLayout.glyphIndex = lineRun->glyphRun.glyphIndex; + } + else + { + // At least there is space reserved for one line. + lineRun = linesBuffer; + + lineRun->glyphRun.glyphIndex = 0u; + ellipsisLayout.glyphIndex = 0u; + + ++numberOfLines; + } + + GetLineLayoutForBox( layoutParameters, + ellipsisLayout, + currentParagraphDirection, + true ); + + lineRun->glyphRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs; + lineRun->characterRun.characterIndex = ellipsisLayout.characterIndex; + lineRun->characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters; + lineRun->width = ellipsisLayout.length; + lineRun->extraLength = ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f; + lineRun->ascender = ellipsisLayout.ascender; + lineRun->descender = ellipsisLayout.descender; + lineRun->direction = !RTL; + lineRun->ellipsis = true; + + layoutSize.width = layoutParameters.boundingBox.width; + layoutSize.height += ( lineRun->ascender + -lineRun->descender ); + + SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun->glyphRun.glyphIndex, + ellipsisLayout.numberOfGlyphs, + penY, + glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex ); + } + + return ellipsis; + } + + /** + * @brief Updates the text layout with a new laid-out line. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in] layout The line layout. + * @param[in,out] layoutSize The text's layout size. + * @param[in,out] linesBuffer Pointer to the line's buffer. + * @param[in] index Index to the vector of glyphs. + * @param[in,out] numberOfLines The number of laid-out lines. + * @param[in] isLastLine Whether the laid-out line is the last one. + */ + void UpdateTextLayout( const LayoutParameters& layoutParameters, + const LineLayout& layout, + Size& layoutSize, + LineRun* linesBuffer, + GlyphIndex index, + Length& numberOfLines, + bool isLastLine ) + { + LineRun& lineRun = *( linesBuffer + numberOfLines ); + ++numberOfLines; + + lineRun.glyphRun.glyphIndex = index; + lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs; + lineRun.characterRun.characterIndex = layout.characterIndex; + lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters; + if( isLastLine && !layoutParameters.isLastNewParagraph ) + { + const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine; + if( MULTI_LINE_BOX == mLayout ) + { + lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width; + } + else + { + lineRun.width = width; + } + + lineRun.extraLength = 0.f; + } + else + { + lineRun.width = layout.extraBearing + layout.length + layout.extraWidth; + lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f; + } + lineRun.ascender = layout.ascender; + lineRun.descender = layout.descender; + lineRun.direction = !RTL; + lineRun.ellipsis = false; + + // Update the actual size. + if( lineRun.width > layoutSize.width ) + { + layoutSize.width = lineRun.width; + } + + layoutSize.height += ( lineRun.ascender + -lineRun.descender ); + } + + /** + * @brief Updates the text layout with the last laid-out line. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in] layout The line layout. + * @param[in,out] layoutSize The text's layout size. + * @param[in,out] linesBuffer Pointer to the line's buffer. + * @param[in] index Index to the vector of glyphs. + * @param[in,out] numberOfLines The number of laid-out lines. + */ + void UpdateTextLayout( const LayoutParameters& layoutParameters, + const LineLayout& layout, + Size& layoutSize, + LineRun* linesBuffer, + GlyphIndex index, + Length& numberOfLines ) + { + // Need to add a new line with no characters but with height to increase the layoutSize.height + const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u ); + + Text::FontMetrics fontMetrics; + mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics ); + + LineRun& lineRun = *( linesBuffer + numberOfLines ); + ++numberOfLines; + + lineRun.glyphRun.glyphIndex = index + layout.numberOfGlyphs; + lineRun.glyphRun.numberOfGlyphs = 0u; + lineRun.characterRun.characterIndex = layout.characterIndex + layout.numberOfCharacters; + lineRun.characterRun.numberOfCharacters = 0u; + lineRun.width = 0.f; + lineRun.ascender = fontMetrics.ascender; + lineRun.descender = fontMetrics.descender; + lineRun.extraLength = 0.f; + lineRun.alignmentOffset = 0.f; + lineRun.direction = !RTL; + lineRun.ellipsis = false; + + layoutSize.height += ( lineRun.ascender + -lineRun.descender ); + } + + /** + * @brief Updates the text's layout size adding the size of the previously laid-out lines. + * + * @param[in] lines The vector of lines (before the new laid-out lines are inserted). + * @param[in,out] layoutSize The text's layout size. + */ + void UpdateLayoutSize( const Vector& lines, + Size& layoutSize ) + { + for( Vector::ConstIterator it = lines.Begin(), + endIt = lines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + if( line.width > layoutSize.width ) + { + layoutSize.width = line.width; + } + + layoutSize.height += ( line.ascender + -line.descender ); + } + } + + /** + * @brief Updates the indices of the character and glyph runs of the lines before the new lines are inserted. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in,out] lines The vector of lines (before the new laid-out lines are inserted). + * @param[in] characterOffset The offset to be added to the runs of characters. + * @param[in] glyphOffset The offset to be added to the runs of glyphs. + */ + void UpdateLineIndexOffsets( const LayoutParameters& layoutParameters, + Vector& lines, + Length characterOffset, + Length glyphOffset ) + { + // Update the glyph and character runs. + for( Vector::Iterator it = lines.Begin() + layoutParameters.startLineIndex, + endIt = lines.End(); + it != endIt; + ++it ) + { + LineRun& line = *it; + + line.glyphRun.glyphIndex = glyphOffset; + line.characterRun.characterIndex = characterOffset; + + glyphOffset += line.glyphRun.numberOfGlyphs; + characterOffset += line.characterRun.numberOfCharacters; + } + } + bool LayoutText( const LayoutParameters& layoutParameters, Vector& glyphPositions, Vector& lines, - Size& actualSize ) + Size& layoutSize ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->LayoutText\n" ); DALI_LOG_INFO( gLogFilter, Debug::Verbose, " box size %f, %f\n", layoutParameters.boundingBox.width, layoutParameters.boundingBox.height ); + if( 0u == layoutParameters.numberOfGlyphs ) + { + // Nothing to do if there are no glyphs to layout. + return false; + } + // Set the first paragraph's direction. CharacterDirection paragraphDirection = ( NULL != layoutParameters.characterDirectionBuffer ) ? *layoutParameters.characterDirectionBuffer : !RTL; - float penY = 0.f; - for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; ) + // Whether the layout is being updated or set from scratch. + const bool updateCurrentBuffer = layoutParameters.numberOfGlyphs < layoutParameters.totalNumberOfGlyphs; + + Vector2* glyphPositionsBuffer = NULL; + Vector newGlyphPositions; + + LineRun* linesBuffer = NULL; + Vector newLines; + + // Estimate the number of lines. + // TODO: In a next patch the paragraphs are properly managed and this can be removed. + Length linesCapacity = CountParagraphs( layoutParameters ); + Length numberOfLines = 0u; + + if( updateCurrentBuffer ) + { + newGlyphPositions.Resize( layoutParameters.numberOfGlyphs ); + glyphPositionsBuffer = newGlyphPositions.Begin(); + + newLines.Resize( linesCapacity ); + linesBuffer = newLines.Begin(); + } + else + { + glyphPositionsBuffer = glyphPositions.Begin(); + + lines.Resize( linesCapacity ); + linesBuffer = lines.Begin(); + } + + float penY = SetParagraphOffset( lines, + layoutParameters.startLineIndex ); + + const GlyphIndex lastGlyphPlusOne = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs; + for( GlyphIndex index = layoutParameters.startGlyphIndex; index < lastGlyphPlusOne; ) { CharacterDirection currentParagraphDirection = paragraphDirection; @@ -498,6 +855,8 @@ struct LayoutEngine::Impl { // The width is too small and no characters are laid-out. DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText width too small!\n\n" ); + + lines.Resize( numberOfLines ); return false; } @@ -506,167 +865,155 @@ struct LayoutEngine::Impl penY += layout.ascender; DALI_LOG_INFO( gLogFilter, Debug::Verbose, " pen y %f\n", penY ); - if( mEllipsisEnabled && - ( ( penY - layout.descender > layoutParameters.boundingBox.height ) || - ( ( mLayout == SINGLE_LINE_BOX ) && - ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) ) ) - { - // Do not layout more lines if ellipsis is enabled. - - // The last line needs to be completely filled with characters. - // Part of a word may be used. - - const Length numberOfLines = lines.Count(); - - LineRun lineRun; - LineLayout ellipsisLayout; - if( 0u != numberOfLines ) - { - // Get the last line and layout it again with the 'completelyFill' flag to true. - lineRun = *( lines.Begin() + ( numberOfLines - 1u ) ); - penY -= layout.ascender - lineRun.descender; - - ellipsisLayout.glyphIndex = lineRun.glyphRun.glyphIndex; - } - else - { - lineRun.glyphRun.glyphIndex = 0u; - ellipsisLayout.glyphIndex = 0u; - } - - GetLineLayoutForBox( layoutParameters, - ellipsisLayout, - currentParagraphDirection, - true ); - - lineRun.glyphRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs; - lineRun.characterRun.characterIndex = ellipsisLayout.characterIndex; - lineRun.characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters; - lineRun.width = ellipsisLayout.length; - lineRun.extraLength = ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f; - lineRun.ascender = ellipsisLayout.ascender; - lineRun.descender = ellipsisLayout.descender; - lineRun.direction = !RTL; - lineRun.ellipsis = true; - - actualSize.width = layoutParameters.boundingBox.width; - actualSize.height += ( lineRun.ascender + -lineRun.descender ); - - SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun.glyphRun.glyphIndex, - ellipsisLayout.numberOfGlyphs, - penY, - glyphPositions.Begin() + lineRun.glyphRun.glyphIndex ); - - if( 0u != numberOfLines ) - { - // Set the last line with the ellipsis layout. - *( lines.Begin() + ( numberOfLines - 1u ) ) = lineRun; - } - else - { - // Push the line. - lines.PushBack( lineRun ); - } + bool ellipsis = false; + if( mEllipsisEnabled ) + { + // Does the ellipsis of the last line. + ellipsis = EllipsisLine( layoutParameters, + layout, + layoutSize, + linesBuffer, + glyphPositionsBuffer, + numberOfLines, + penY, + currentParagraphDirection ); + } + if( ellipsis ) + { + // No more lines to layout. break; } else { + // Whether the last line has been laid-out. const bool isLastLine = index + layout.numberOfGlyphs == layoutParameters.totalNumberOfGlyphs; - LineRun lineRun; - lineRun.glyphRun.glyphIndex = index; - lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs; - lineRun.characterRun.characterIndex = layout.characterIndex; - lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters; - if( isLastLine && !layoutParameters.isLastNewParagraph ) + if( numberOfLines == linesCapacity ) { - const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine; - if( MULTI_LINE_BOX == mLayout ) - { - lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width; - } - else - { - lineRun.width = width; - } - - lineRun.extraLength = 0.f; + // Reserve more space for the next lines. + linesBuffer = ResizeLinesBuffer( lines, + newLines, + linesCapacity, + updateCurrentBuffer ); } - else - { - lineRun.width = layout.extraBearing + layout.length + layout.extraWidth; - lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f; - } - lineRun.ascender = layout.ascender; - lineRun.descender = layout.descender; - lineRun.direction = !RTL; - lineRun.ellipsis = false; - lines.PushBack( lineRun ); + // Updates the current text's layout with the line's layout. + UpdateTextLayout( layoutParameters, + layout, + layoutSize, + linesBuffer, + index, + numberOfLines, + isLastLine ); - // Update the actual size. - if( lineRun.width > actualSize.width ) + if( isLastLine && + layoutParameters.isLastNewParagraph && + ( mLayout == MULTI_LINE_BOX ) ) { - actualSize.width = lineRun.width; - } + // The last character of the text is a new paragraph character. + // An extra line with no characters is added to increase the text's height + // in order to place the cursor. + + if( numberOfLines == linesCapacity ) + { + // Reserve more space for the next lines. + linesBuffer = ResizeLinesBuffer( lines, + newLines, + linesCapacity, + updateCurrentBuffer ); + } - actualSize.height += ( lineRun.ascender + -lineRun.descender ); + UpdateTextLayout( layoutParameters, + layout, + layoutSize, + linesBuffer, + index, + numberOfLines ); + } // whether to add a last line. + // Sets the positions of the glyphs. SetGlyphPositions( layoutParameters.glyphsBuffer + index, layout.numberOfGlyphs, penY, - glyphPositions.Begin() + index ); + glyphPositionsBuffer + index - layoutParameters.startGlyphIndex ); + // Updates the vertical pen's position. penY += -layout.descender; // Increase the glyph index. index += layout.numberOfGlyphs; - if( isLastLine && - layoutParameters.isLastNewParagraph && - ( mLayout == MULTI_LINE_BOX ) ) - { - // Need to add a new line with no characters but with height to increase the actualSize.height - const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u ); - - Text::FontMetrics fontMetrics; - mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics ); - - LineRun lineRun; - lineRun.glyphRun.glyphIndex = 0u; - lineRun.glyphRun.numberOfGlyphs = 0u; - lineRun.characterRun.characterIndex = 0u; - lineRun.characterRun.numberOfCharacters = 0u; - lineRun.width = 0.f; - lineRun.ascender = fontMetrics.ascender; - lineRun.descender = fontMetrics.descender; - lineRun.extraLength = 0.f; - lineRun.alignmentOffset = 0.f; - lineRun.direction = !RTL; - lineRun.ellipsis = false; - - actualSize.height += ( lineRun.ascender + -lineRun.descender ); - - lines.PushBack( lineRun ); - } - } + } // no ellipsis } // end for() traversing glyphs. + if( updateCurrentBuffer ) + { + glyphPositions.Insert( glyphPositions.Begin() + layoutParameters.startGlyphIndex, + newGlyphPositions.Begin(), + newGlyphPositions.End() ); + + newLines.Resize( numberOfLines ); + + // Current text's layout size adds only the newly laid-out lines. + // Updates the layout size with the previously laid-out lines. + UpdateLayoutSize( lines, + layoutSize ); + + if( 0u != newLines.Count() ) + { + const LineRun& lastLine = *( newLines.End() - 1u ); + + const Length characterOffset = lastLine.characterRun.characterIndex + lastLine.characterRun.numberOfCharacters; + const Length glyphOffset = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs; + + // Update the indices of the runs before the new laid-out lines are inserted. + UpdateLineIndexOffsets( layoutParameters, + lines, + characterOffset, + glyphOffset ); + + // Insert the lines. + lines.Insert( lines.Begin() + layoutParameters.startLineIndex, + newLines.Begin(), + newLines.End() ); + } + } + else + { + lines.Resize( numberOfLines ); + } + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" ); return true; } void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& glyphPositions ) { + const CharacterIndex lastCharacterIndex = startIndex + numberOfCharacters; + // Traverses the paragraphs with right to left characters. for( LineIndex lineIndex = 0u; lineIndex < layoutParameters.numberOfBidirectionalInfoRuns; ++lineIndex ) { const BidirectionalLineInfoRun& bidiLine = *( layoutParameters.lineBidirectionalInfoRunsBuffer + lineIndex ); + if( startIndex >= bidiLine.characterRun.characterIndex + bidiLine.characterRun.numberOfCharacters ) + { + // Do not reorder the line if it has been already reordered. + continue; + } + + if( bidiLine.characterRun.characterIndex >= lastCharacterIndex ) + { + // Do not reorder the lines after the last requested character. + break; + } + const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *bidiLine.visualToLogicalMap; const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) ); @@ -702,48 +1049,71 @@ struct LayoutEngine::Impl } } - void Align( const Size& layoutSize, + void Align( const Size& size, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& lines ) { - // Traverse all lines and align the glyphs. + const CharacterIndex lastCharacterPlusOne = startIndex + numberOfCharacters; + // Traverse all lines and align the glyphs. for( Vector::Iterator it = lines.Begin(), endIt = lines.End(); it != endIt; ++it ) { LineRun& line = *it; - const bool isLastLine = lines.End() == it + 1u; - // Calculate the alignment offset accordingly with the align option, - // the box width, line length, and the paragraphs direction. - CalculateHorizontalAlignment( layoutSize.width, - line, - isLastLine ); + if( line.characterRun.characterIndex < startIndex ) + { + // Do not align lines which have already been aligned. + continue; + } + + if( line.characterRun.characterIndex >= lastCharacterPlusOne ) + { + // Do not align lines beyond the last laid-out character. + break; + } + + // Calculate the line's alignment offset accordingly with the align option, + // the box width, line length, and the paragraph's direction. + CalculateHorizontalAlignment( size.width, + line ); } } void CalculateHorizontalAlignment( float boxWidth, - LineRun& line, - bool isLastLine ) + LineRun& line ) { line.alignmentOffset = 0.f; const bool isRTL = RTL == line.direction; float lineLength = line.width; HorizontalAlignment alignment = mHorizontalAlignment; - if( isRTL && - ( HORIZONTAL_ALIGN_CENTER != alignment ) ) + if( isRTL ) { - if( HORIZONTAL_ALIGN_BEGIN == alignment ) - { - alignment = HORIZONTAL_ALIGN_END; - } - else + // Swap the alignment type if the line is right to left. + switch( alignment ) { - alignment = HORIZONTAL_ALIGN_BEGIN; + case HORIZONTAL_ALIGN_BEGIN: + { + alignment = HORIZONTAL_ALIGN_END; + break; + } + case HORIZONTAL_ALIGN_CENTER: + { + // Nothing to do. + break; + } + case HORIZONTAL_ALIGN_END: + { + alignment = HORIZONTAL_ALIGN_BEGIN; + break; + } } } + // Calculate the horizontal line offset. switch( alignment ) { case HORIZONTAL_ALIGN_BEGIN: @@ -754,39 +1124,16 @@ struct LayoutEngine::Impl { // 'Remove' the white spaces at the end of the line (which are at the beginning in visual order) line.alignmentOffset -= line.extraLength; - - if( isLastLine ) - { - line.alignmentOffset += std::min( line.extraLength, boxWidth - lineLength ); - } } break; } case HORIZONTAL_ALIGN_CENTER: { - if( isLastLine && !isRTL ) - { - // Add the length of the white saces at the end of the line. - lineLength += line.extraLength; - if( lineLength > boxWidth ) - { - // The line's length is longer than the box's width. - // Set the line's offset to 0 and nothing else to do. - line.alignmentOffset = 0.f; - break; - } - } - line.alignmentOffset = 0.5f * ( boxWidth - lineLength ); if( isRTL ) { line.alignmentOffset -= line.extraLength; - - if( isLastLine ) - { - line.alignmentOffset += 0.5f * std::min( line.extraLength, boxWidth - lineLength ); - } } line.alignmentOffset = floorf( line.alignmentOffset ); // try to avoid pixel alignment. @@ -794,16 +1141,6 @@ struct LayoutEngine::Impl } case HORIZONTAL_ALIGN_END: { - if( isLastLine && !isRTL ) - { - lineLength += line.extraLength; - if( lineLength > boxWidth ) - { - line.alignmentOffset = 0.f; - break; - } - } - if( isRTL ) { lineLength += line.extraLength; @@ -846,7 +1183,7 @@ void LayoutEngine::SetLayout( Layout layout ) mImpl->mLayout = layout; } -unsigned int LayoutEngine::GetLayout() const +LayoutEngine::Layout LayoutEngine::GetLayout() const { return mImpl->mLayout; } @@ -894,25 +1231,33 @@ int LayoutEngine::GetCursorWidth() const bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters, Vector& glyphPositions, Vector& lines, - Size& actualSize ) + Size& layoutSize ) { return mImpl->LayoutText( layoutParameters, glyphPositions, lines, - actualSize ); + layoutSize ); } void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& glyphPositions ) { mImpl->ReLayoutRightToLeftLines( layoutParameters, + startIndex, + numberOfCharacters, glyphPositions ); } -void LayoutEngine::Align( const Size& layoutSize, +void LayoutEngine::Align( const Size& size, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& lines ) { - mImpl->Align( layoutSize, + mImpl->Align( size, + startIndex, + numberOfCharacters, lines ); } diff --git a/dali-toolkit/internal/text/layouts/layout-engine.h b/dali-toolkit/internal/text/layouts/layout-engine.h index f866f3e..e672c53 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.h +++ b/dali-toolkit/internal/text/layouts/layout-engine.h @@ -93,7 +93,7 @@ public: * * @return The required layout. */ - unsigned int GetLayout() const; + Layout GetLayout() const; /** * @brief Enable or disable the text ellipsis. @@ -155,14 +155,14 @@ public: * @param[in] layoutParameters The parameters needed to layout the text. * @param[out] glyphPositions The positions of all the glyphs. * @param[out] lines The laid-out lines. - * @param[out] actualSize The size of the text after it has been laid-out. + * @param[out] layoutSize The size of the text after it has been laid-out. * * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character. */ bool LayoutText( const LayoutParameters& layoutParameters, Vector& glyphPositions, Vector& lines, - Size& actualSize ); + Size& layoutSize ); /** * @brief Re-lays out those lines with right to left characters. @@ -170,18 +170,26 @@ public: * It doesn't change the phisical position of the glyphs in the model but sets their new position. * * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in] startIndex Character index of the line from where the lines are reordered. + * @param[in] numberOfCharacters The number of characters. * @param[in,out] glyphPositions The positions of all the glyphs. */ void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& glyphPositions ); /** * @brief Aligns the laid out lines. * - * @param[in] layoutSize The size of the laid out the text. + * @param[in] size The size of the container where the text is laid-out. + * @param[in] startIndex Character index of the line from where the lines are aligned. + * @param[in] numberOfCharacters The number of characters. * @param[in,out] lines The laid-out lines. */ - void Align( const Size& layoutSize, + void Align( const Size& size, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& lines ); private: diff --git a/dali-toolkit/internal/text/layouts/layout-parameters.h b/dali-toolkit/internal/text/layouts/layout-parameters.h index 78746ff..238dade 100644 --- a/dali-toolkit/internal/text/layouts/layout-parameters.h +++ b/dali-toolkit/internal/text/layouts/layout-parameters.h @@ -47,49 +47,60 @@ struct LayoutParameters * @param[in] textBuffer The text buffer. * @param[in] lineBreakInfoBuffer The line break info. * @param[in] wordBreakInfoBuffer The word break info. - * @param[in] totalNumberOfGlyphs The number of glyphs. - * @param[in] glyphsBuffer A vector with glyphs. + * @param[in] characterDirectionBuffer Vector with the direction of each character. + * @param[in] glyphsBuffer Vector with glyphs. * @param[in] glyphsToCharactersBuffer Vector with indices pointing the first character of each glyph. * @param[in] charactersPerGlyphBuffer Vector with the number of characters that forms each glyph. + * @param[in] charactersToGlyphsBuffer Vector with indices pointing the first glyph of each character. + * @param[in] glyphsPerCharacterBuffer Vector with the number of glyphs shaped from the character. + * @param[in] totalNumberOfGlyphs The number of glyphs. */ LayoutParameters( const Vector2& boundingBox, const Character* const textBuffer, const LineBreakInfo* const lineBreakInfoBuffer, const WordBreakInfo* const wordBreakInfoBuffer, const CharacterDirection* const characterDirectionBuffer, - Length totalNumberOfGlyphs, const GlyphInfo* const glyphsBuffer, const CharacterIndex* const glyphsToCharactersBuffer, - const Length* const charactersPerGlyphBuffer ) + const Length* const charactersPerGlyphBuffer, + const GlyphIndex* const charactersToGlyphsBuffer, + const Length* const glyphsPerCharacterBuffer, + Length totalNumberOfGlyphs ) : boundingBox( boundingBox ), textBuffer( textBuffer ), lineBreakInfoBuffer( lineBreakInfoBuffer ), wordBreakInfoBuffer( wordBreakInfoBuffer ), characterDirectionBuffer( characterDirectionBuffer ), - totalNumberOfGlyphs( totalNumberOfGlyphs ), glyphsBuffer( glyphsBuffer ), glyphsToCharactersBuffer( glyphsToCharactersBuffer ), charactersPerGlyphBuffer( charactersPerGlyphBuffer ), - charactersToGlyphsBuffer( NULL ), - glyphsPerCharacterBuffer( NULL ), + charactersToGlyphsBuffer( charactersToGlyphsBuffer ), + glyphsPerCharacterBuffer( glyphsPerCharacterBuffer ), lineBidirectionalInfoRunsBuffer( NULL ), numberOfBidirectionalInfoRuns( 0u ), + startGlyphIndex( 0u ), + numberOfGlyphs( 0u ), + totalNumberOfGlyphs( totalNumberOfGlyphs ), + startLineIndex( 0u ), isLastNewParagraph( false ) {} - Vector2 boundingBox; - const Character* const textBuffer; - const LineBreakInfo* const lineBreakInfoBuffer; - const WordBreakInfo* const wordBreakInfoBuffer; - const CharacterDirection* const characterDirectionBuffer; - Length totalNumberOfGlyphs; - const GlyphInfo* const glyphsBuffer; - const CharacterIndex* const glyphsToCharactersBuffer; - const Length* const charactersPerGlyphBuffer; - GlyphIndex* charactersToGlyphsBuffer; ///< The character to glyph conversion table. - Length* glyphsPerCharacterBuffer; ///< The number of glyphs per character. + Vector2 boundingBox; ///< The size of the box containing the text. + const Character* const textBuffer; ///< The text buffer. + const LineBreakInfo* const lineBreakInfoBuffer; ///< The line break info. + const WordBreakInfo* const wordBreakInfoBuffer; ///< The word break info. + const CharacterDirection* const characterDirectionBuffer; ///< Vector with the direction of each character. + const GlyphInfo* const glyphsBuffer; ///< Vector with glyphs. + const CharacterIndex* const glyphsToCharactersBuffer; ///< Vector with indices pointing the first character of each glyph. + const Length* const charactersPerGlyphBuffer; ///< Vector with the number of characters that forms each glyph. + const GlyphIndex* const charactersToGlyphsBuffer; ///< Vector with indices pointing the first glyph of each character. + const Length* const glyphsPerCharacterBuffer; ///< Vector with the number of glyphs shaped from the character. BidirectionalLineInfoRun* lineBidirectionalInfoRunsBuffer; ///< Bidirectional conversion tables per line. Length numberOfBidirectionalInfoRuns; ///< The number of lines with bidirectional info. + GlyphIndex startGlyphIndex; ///< Index to the first glyph to layout. + Length numberOfGlyphs; ///< The number of glyphs to layout. + Length totalNumberOfGlyphs; ///< The number of glyphs. + LineIndex startLineIndex; ///< The line index where to insert the new lines. bool isLastNewParagraph; ///< Whether the last character is a new paragraph character. }; diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index 7d17847..88b2857 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -176,7 +176,7 @@ struct AtlasRenderer::Impl mDepth = depth; const Vector2& actorSize( view.GetControlSize() ); - const Vector2& textSize( view.GetActualSize() ); + const Vector2& textSize( view.GetLayoutSize() ); const Vector2 halfTextSize( textSize * 0.5f ); const Vector2& shadowOffset( view.GetShadowOffset() ); const Vector4& shadowColor( view.GetShadowColor() ); diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index c2c2fa8..d681730 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -678,7 +678,7 @@ void Controller::Impl::OnPanEvent( const Event& event ) if( Gesture::Started == state || Gesture::Continuing == state ) { - const Vector2& actualSize = mVisualModel->GetActualSize(); + const Vector2& actualSize = mVisualModel->GetLayoutSize(); const Vector2 currentScroll = mEventData->mScrollPosition; if( mEventData->mHorizontalScrollingEnabled ) @@ -833,7 +833,7 @@ void Controller::Impl::OnHandleEvent( const Event& event ) else if( HANDLE_SCROLLING == state ) { const float xSpeed = event.p2.mFloat; - const Vector2& actualSize = mVisualModel->GetActualSize(); + const Vector2& actualSize = mVisualModel->GetLayoutSize(); const Vector2 currentScrollPosition = mEventData->mScrollPosition; mEventData->mScrollPosition.x += xSpeed; @@ -1904,6 +1904,25 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical, cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + ( isCurrentRightToLeft ? 0.f : glyphMetrics.advance ); cursorInfo.secondaryPosition.y = cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender ); } + + if( LayoutEngine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() ) + { + // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control. + + // Note the white spaces laid-out at the end of the line might exceed the boundaries of the control. + // The reason is a wrapped line must not start with a white space so they are laid-out at the end of the line. + + if( 0.f > cursorInfo.primaryPosition.x ) + { + cursorInfo.primaryPosition.x = 0.f; + } + + const float edgeWidth = mVisualModel->mControlSize.width - static_cast( mEventData->mDecorator->GetCursorWidth() ); + if( cursorInfo.primaryPosition.x > edgeWidth ) + { + cursorInfo.primaryPosition.x = edgeWidth; + } + } } CharacterIndex Controller::Impl::CalculateNewCursorIndex( CharacterIndex index ) const @@ -2074,17 +2093,18 @@ void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position ) const float positionEnd = position.x + ( mEventData->mDecorator ? mEventData->mDecorator->GetCursorWidth() : 0.f ); // Transform the position to decorator coords. - const float offset = mEventData->mScrollPosition.x + mAlignmentOffset.x; + const float alignment = IsShowingRealText() ? mAlignmentOffset.x : 0.f; + const float offset = mEventData->mScrollPosition.x + alignment; const float decoratorPositionBegin = position.x + offset; const float decoratorPositionEnd = positionEnd + offset; if( decoratorPositionBegin < 0.f ) { - mEventData->mScrollPosition.x = -position.x - mAlignmentOffset.x; + mEventData->mScrollPosition.x = -position.x - alignment; } else if( decoratorPositionEnd > mVisualModel->mControlSize.width ) { - mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - mAlignmentOffset.x; + mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - alignment; } } @@ -2096,7 +2116,7 @@ void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo ) // Calculate the offset to match the cursor position before the character was deleted. mEventData->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x - mAlignmentOffset.x; - ClampHorizontalScroll( mVisualModel->GetActualSize() ); + ClampHorizontalScroll( mVisualModel->GetLayoutSize() ); } void Controller::Impl::RequestRelayout() diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 9ee83cc..f88ca8d 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -514,7 +514,7 @@ struct Controller::Impl * * @pre mEventData must not be NULL. (there is a text-input or selection capabilities). * - * @param[in] position A position in decorator coords. + * @param[in] position A position in text coords. * * This method is called after inserting text, moving the cursor with the grab handle or the keypad, * or moving the selection handles. @@ -526,7 +526,7 @@ struct Controller::Impl * * This method is called after deleting text. */ - void ScrollTextToMatchCursor( const CursorInfo& cursorInfo); + void ScrollTextToMatchCursor( const CursorInfo& cursorInfo ); ControlInterface& mControlInterface; ///< Reference to the text controller. LogicalModelPtr mLogicalModel; ///< Pointer to the logical model. diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 740e948..a2fec9a 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -43,7 +43,6 @@ const float MAX_FLOAT = std::numeric_limits::max(); const unsigned int POINTS_PER_INCH = 72; const std::string EMPTY_STRING(""); -const unsigned int ZERO = 0u; float ConvertToEven( float value ) { @@ -1041,7 +1040,7 @@ float Controller::GetHeightForWidth( float width ) } else { - layoutSize = mImpl->mVisualModel->GetActualSize(); + layoutSize = mImpl->mVisualModel->GetLayoutSize(); DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height ); } @@ -1065,6 +1064,7 @@ bool Controller::Relayout( const Size& size ) return glyphsRemoved; } + // Whether a new size has been set. const bool newSize = ( size != mImpl->mVisualModel->mControlSize ); if( newSize ) @@ -1339,6 +1339,8 @@ bool Controller::DoRelayout( const Size& size, const Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; const Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; const Character* const textBuffer = mImpl->mLogicalModel->mText.Begin(); + const Vector& charactersToGlyph = mImpl->mVisualModel->mCharactersToGlyph; + const Vector& glyphsPerCharacter = mImpl->mVisualModel->mGlyphsPerCharacter; // Set the layout parameters. LayoutParameters layoutParameters( size, @@ -1346,10 +1348,12 @@ bool Controller::DoRelayout( const Size& size, lineBreakInfo.Begin(), wordBreakInfo.Begin(), ( 0u != characterDirection.Count() ) ? characterDirection.Begin() : NULL, - numberOfGlyphs, glyphs.Begin(), glyphsToCharactersMap.Begin(), - charactersPerGlyph.Begin() ); + charactersPerGlyph.Begin(), + charactersToGlyph.Begin(), + glyphsPerCharacter.Begin(), + numberOfGlyphs ); // The laid-out lines. // It's not possible to know in how many lines the text is going to be laid-out, @@ -1370,6 +1374,10 @@ bool Controller::DoRelayout( const Size& size, // Whether the last character is a new paragraph character. layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mLogicalModel->mText.Count() - 1u ) ) ); + // The initial glyph and the number of glyphs to layout. + layoutParameters.startGlyphIndex = 0u; + layoutParameters.numberOfGlyphs = numberOfGlyphs; + // Update the visual model. viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, glyphPositions, @@ -1390,7 +1398,7 @@ bool Controller::DoRelayout( const Size& size, // Get the lines const Length numberOfLines = mImpl->mVisualModel->mLines.Count(); const CharacterIndex startIndex = 0u; - Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count(); + const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count(); // Reorder the lines. bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters. @@ -1410,13 +1418,10 @@ bool Controller::DoRelayout( const Size& size, startIndex, requestedNumberOfCharacters ); - // Get the character to glyph conversion table and set into the layout. - layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin(); - // Get the glyphs per character table and set into the layout. - layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin(); - // Re-layout the text. Reorder those lines with right to left characters. mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters, + startIndex, + requestedNumberOfCharacters, glyphPositions ); // Free the allocated memory used to store the conversion table in the bidirectional line info run. @@ -1438,13 +1443,13 @@ bool Controller::DoRelayout( const Size& size, // Sets the actual size. if( UPDATE_ACTUAL_SIZE & operations ) { - mImpl->mVisualModel->SetActualSize( layoutSize ); + mImpl->mVisualModel->SetLayoutSize( layoutSize ); } } // view updated } else { - layoutSize = mImpl->mVisualModel->GetActualSize(); + layoutSize = mImpl->mVisualModel->GetLayoutSize(); } if( ALIGN & operations ) @@ -1452,7 +1457,12 @@ bool Controller::DoRelayout( const Size& size, // The laid-out lines. Vector& lines = mImpl->mVisualModel->mLines; - mImpl->mLayoutEngine.Align( layoutSize, + const CharacterIndex startIndex = 0u; + const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count(); + + mImpl->mLayoutEngine.Align( size, + startIndex, + requestedNumberOfCharacters, lines ); viewUpdated = true; @@ -1525,49 +1535,62 @@ LayoutEngine::VerticalAlignment Controller::GetVerticalAlignment() const return mImpl->mLayoutEngine.GetVerticalAlignment(); } -void Controller::CalculateTextAlignment( const Size& size ) +void Controller::CalculateTextAlignment( const Size& controlSize ) { - // Get the direction of the first character. - const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u ); + Size layoutSize = mImpl->mVisualModel->GetLayoutSize(); - Size actualSize = mImpl->mVisualModel->GetActualSize(); - if( fabsf( actualSize.height ) < Math::MACHINE_EPSILON_1000 ) + if( fabsf( layoutSize.height ) < Math::MACHINE_EPSILON_1000 ) { // Get the line height of the default font. - actualSize.height = mImpl->GetDefaultFontLineHeight(); + layoutSize.height = mImpl->GetDefaultFontLineHeight(); } - // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END; - LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment(); - if( firstParagraphDirection && - ( LayoutEngine::HORIZONTAL_ALIGN_CENTER != horizontalAlignment ) ) + if( LayoutEngine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout() ) { - if( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == horizontalAlignment ) - { - horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END; - } - else - { - horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN; - } - } + // Get the direction of the first character. + const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u ); - switch( horizontalAlignment ) - { - case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: - { - mImpl->mAlignmentOffset.x = 0.f; - break; - } - case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END; + LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment(); + if( firstParagraphDirection ) { - mImpl->mAlignmentOffset.x = floorf( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment. - break; + switch( horizontalAlignment ) + { + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + // Nothing to do. + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN; + break; + } + } } - case LayoutEngine::HORIZONTAL_ALIGN_END: + + switch( horizontalAlignment ) { - mImpl->mAlignmentOffset.x = size.width - actualSize.width; - break; + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + mImpl->mAlignmentOffset.x = 0.f; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + mImpl->mAlignmentOffset.x = floorf( 0.5f * ( controlSize.width - layoutSize.width ) ); // try to avoid pixel alignment. + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + mImpl->mAlignmentOffset.x = controlSize.width - layoutSize.width; + break; + } } } @@ -1581,12 +1604,12 @@ void Controller::CalculateTextAlignment( const Size& size ) } case LayoutEngine::VERTICAL_ALIGN_CENTER: { - mImpl->mAlignmentOffset.y = floorf( 0.5f * ( size.height - actualSize.height ) ); // try to avoid pixel alignment. + mImpl->mAlignmentOffset.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment. break; } case LayoutEngine::VERTICAL_ALIGN_BOTTOM: { - mImpl->mAlignmentOffset.y = size.height - actualSize.height; + mImpl->mAlignmentOffset.y = controlSize.height - layoutSize.height; break; } } @@ -1815,7 +1838,7 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ const Length numberOfCharactersInModel = mImpl->mLogicalModel->mText.Count(); // Restrict new text to fit within Maximum characters setting - Length maxSizeOfNewText = std::min ( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount ); + Length maxSizeOfNewText = std::min( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount ); maxLengthReached = ( characterCount > maxSizeOfNewText ); // The cursor position. diff --git a/dali-toolkit/internal/text/text-run-container.h b/dali-toolkit/internal/text/text-run-container.h index 67d0373..37d7b00 100644 --- a/dali-toolkit/internal/text/text-run-container.h +++ b/dali-toolkit/internal/text/text-run-container.h @@ -47,12 +47,12 @@ void ClearCharacterRuns( CharacterIndex startIndex, uint32_t& endRemoveIndex ) { T* runsBuffer = runs.Begin(); + T* run = runsBuffer; const Length length = runs.Count(); - for( Length index = 0u; index < length; ++index ) + Length index = 0u; + for( index = 0u; index < length; ++index ) { - T* run = ( runsBuffer + index ); - if( ( run->characterRun.characterIndex <= endIndex ) && ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) ) { @@ -62,37 +62,36 @@ void ClearCharacterRuns( CharacterIndex startIndex, startRemoveIndex = index; break; } + + ++run; } - for( Length index = startRemoveIndex; index < length; ++index ) + run = ( runsBuffer + startRemoveIndex ); + for( index = startRemoveIndex; index < length; ++index ) { - T* run = ( runsBuffer + index ); - - if( ( run->characterRun.characterIndex <= endIndex ) && - ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) ) - { - // Update the index to the last run to be removed. - endRemoveIndex = index + 1u; - } - else + if( ( run->characterRun.characterIndex > endIndex ) || + ( startIndex >= run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) ) { // Run found. Nothing else to do. break; } + ++run; } + endRemoveIndex = index; // The number of characters to remove. const Length numberOfCharactersRemoved = 1u + endIndex - startIndex; // Update the character index of the next runs. + run = runsBuffer; for( Length index = 0u; index < length; ++index ) { - T* run = ( runsBuffer + index ); - if( run->characterRun.characterIndex > startIndex ) { run->characterRun.characterIndex -= numberOfCharactersRemoved; } + + ++run; } } @@ -259,6 +258,94 @@ void UpdateCharacterRuns( CharacterIndex index, } } +/** + * @brief Clears the runs starting from the given glyph index. + * + * @param[in] startIndex The starting glyph index used to remove runs. + * @param[in] endIndex The ending glyph index used to remove runs. + * @param[in,out] runs The text's runs. + * @param[out] startRemoveIndex The index to the first run to be removed. + * @param[out] endRemoveIndex The index to the last run to be removed. + */ +template< typename T > +void ClearGlyphRuns( GlyphIndex startIndex, + GlyphIndex endIndex, + Vector& runs, + uint32_t& startRemoveIndex, + uint32_t& endRemoveIndex ) +{ + T* runsBuffer = runs.Begin(); + T* run = runsBuffer; + + const Length length = runs.Count(); + Length index = 0u; + for( index = 0u; index < length; ++index ) + { + if( ( run->glyphRun.glyphIndex <= endIndex ) && + ( startIndex < run->glyphRun.glyphIndex + run->glyphRun.numberOfGlyphs ) ) + { + // Run found. + + // Set the index to the first run to be removed. + startRemoveIndex = index; + break; + } + ++run; + } + + run = ( runsBuffer + startRemoveIndex ); + for( index = startRemoveIndex; index < length; ++index ) + { + if( ( run->glyphRun.glyphIndex > endIndex ) || + ( startIndex >= run->glyphRun.glyphIndex + run->glyphRun.numberOfGlyphs ) ) + { + // Run found. Nothing else to do. + } + + ++run; + } + endRemoveIndex = index; + + // The number of glyphs to remove. + const Length numberOfGlyphsRemoved = 1u + endIndex - startIndex; + + // Update the glyph index of the next runs. + run = runsBuffer; + for( Length index = 0u; index < length; ++index ) + { + + if( run->glyphRun.glyphIndex > startIndex ) + { + run->glyphRun.glyphIndex -= numberOfGlyphsRemoved; + } + } +} + +/** + * @brief Clears the runs starting from the given glyph index. + * + * @param[in] startIndex The starting glyph index used to remove runs. + * @param[in] endIndex The ending glyph index used to remove runs. + * @param[in,out] runs The text's runs. + */ +template< typename T > +void ClearGlyphRuns( GlyphIndex startIndex, + GlyphIndex endIndex, + Vector& runs ) +{ + uint32_t startRemoveIndex = runs.Count(); + uint32_t endRemoveIndex = startRemoveIndex; + ClearGlyphRuns( startIndex, + endIndex, + runs, + startRemoveIndex, + endRemoveIndex ); + + // Remove all remaining runs. + T* runBuffer = runs.Begin(); + runs.Erase( runBuffer + startRemoveIndex, runBuffer + endRemoveIndex ); +} + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index 5f4f1b5..c121f77 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -65,12 +65,12 @@ public: virtual const Vector2& GetControlSize() const = 0; /** - * @brief Retrieves the text's actual size after it has been laid out. + * @brief Retrieves the text's layout size. * * @return The text's size. Note that this may be larger than the control size, * in the case where text is scrolling/clipped. */ - virtual const Vector2& GetActualSize() const = 0; + virtual const Vector2& GetLayoutSize() const = 0; /** * Retrieves the number of glyphs. diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index caee1f8..d57b2ec 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -65,11 +65,11 @@ const Vector2& View::GetControlSize() const return Vector2::ZERO; } -const Vector2& View::GetActualSize() const +const Vector2& View::GetLayoutSize() const { if ( mImpl->mVisualModel ) { - return mImpl->mVisualModel->GetActualSize(); + return mImpl->mVisualModel->GetLayoutSize(); } return Vector2::ZERO; diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index e58693c..0067f94 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -61,9 +61,9 @@ public: virtual const Vector2& GetControlSize() const; /** - * @copydoc Dali::Toolkit::Text::ViewInterface::GetActualSize() + * @copydoc Dali::Toolkit::Text::ViewInterface::GetLayoutSize() */ - virtual const Vector2& GetActualSize() const; + virtual const Vector2& GetLayoutSize() const; /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfGlyphs() diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index 3e9c123..138ce54 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -315,14 +315,14 @@ const Vector2& VisualModel::GetNaturalSize() const return mNaturalSize; } -void VisualModel::SetActualSize( const Vector2& size ) +void VisualModel::SetLayoutSize( const Vector2& size ) { - mActualSize = size; + mLayoutSize = size; } -const Vector2& VisualModel::GetActualSize() const +const Vector2& VisualModel::GetLayoutSize() const { - return mActualSize; + return mLayoutSize; } void VisualModel::SetTextColor( const Vector4& textColor ) @@ -414,7 +414,7 @@ VisualModel::VisualModel() mShadowOffset( Vector2::ZERO ), mUnderlineHeight( 0.0f ), mNaturalSize(), - mActualSize(), + mLayoutSize(), mCachedLineIndex( 0u ), mUnderlineEnabled( false ), mUnderlineColorSet( false ) diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index eb2e5a0..a0339a4 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -174,18 +174,18 @@ public: const Vector2& GetNaturalSize() const; /** - * @brief Sets the text's actual size after it has been laid out. + * @brief Sets the text's layout size. * * @param[in] size The text's size. */ - void SetActualSize( const Vector2& size ); + void SetLayoutSize( const Vector2& size ); /** - * @brief Retrieves the text's actual size after it has been laid out. + * @brief Retrieves the text's layout size. * * @return The text's size. */ - const Vector2& GetActualSize() const; + const Vector2& GetLayoutSize() const; /** * @brief Set the text's color @@ -318,7 +318,7 @@ public: private: Size mNaturalSize; ///< Size of the text with no line wrapping. - Size mActualSize; ///< Size of the laid-out text considering the layout properties set. + Size mLayoutSize; ///< Size of the laid-out text considering the layout properties set. // Caches to increase performance in some consecutive operations. LineIndex mCachedLineIndex; ///< Used to increase performance in consecutive calls to GetLineOfGlyph() or GetLineOfCharacter() with consecutive glyphs or characters. -- 2.7.4