Add bidirectional text tct.
For this, made CreateTextModel() can support markup text.
Change-Id: I13ad4025635ba257611875284563bce09d8c6192
Signed-off-by: minho.sun <minho.sun@samsung.com>
#include <dali-toolkit/internal/text/segmentation.h>
#include <dali-toolkit/internal/text/shaper.h>
#include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/markup-processor.h>
namespace Dali
{
Size& layoutSize,
LogicalModelPtr& logicalModel,
VisualModelPtr& visualModel,
- MetricsPtr& metrics )
+ MetricsPtr& metrics,
+ bool markupProcessorEnabled )
{
logicalModel = LogicalModel::New();
visualModel = VisualModel::New();
+ MarkupProcessData markupProcessData( logicalModel->mColorRuns,
+ logicalModel->mFontDescriptionRuns );
+
+ Length textSize = 0u;
+ const uint8_t* utf8 = NULL;
+ if( markupProcessorEnabled )
+ {
+ ProcessMarkupString( text, markupProcessData );
+ textSize = markupProcessData.markupProcessedText.size();
+
+ // This is a bit horrible but std::string returns a (signed) char*
+ utf8 = reinterpret_cast<const uint8_t*>( markupProcessData.markupProcessedText.c_str() );
+ }
+ else
+ {
+ textSize = text.size();
+
+ // This is a bit horrible but std::string returns a (signed) char*
+ utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
+ }
+
// 1) Convert to utf32
Vector<Character>& utf32Characters = logicalModel->mText;
- utf32Characters.Resize( text.size() );
+ utf32Characters.Resize( textSize );
- const uint32_t numberOfCharacters = ( text.size() == 0) ? 0 :
- Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( text.c_str() ),
- text.size(),
- &utf32Characters[0u] );
- utf32Characters.Resize( numberOfCharacters );
+ // Transform a text array encoded in utf8 into an array encoded in utf32.
+ // It returns the actual number of characters.
+ Length characterCount = Utf8ToUtf32( utf8, textSize, utf32Characters.Begin() );
+ utf32Characters.Resize( characterCount );
// 2) Set the break and paragraph info.
Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo;
- lineBreakInfo.Resize( numberOfCharacters );
+ lineBreakInfo.Resize( characterCount );
SetLineBreakInfo( utf32Characters,
0u,
- numberOfCharacters,
+ characterCount,
lineBreakInfo );
- if( 0u == numberOfCharacters )
+ if( 0u == characterCount )
{
// Nothing else to do if the number of characters is zero.
return;
// Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
Vector<WordBreakInfo>& wordBreakInfo = logicalModel->mWordBreakInfo;
- wordBreakInfo.Resize( numberOfCharacters );
+ wordBreakInfo.Resize( characterCount );
SetWordBreakInfo( utf32Characters,
0u,
- numberOfCharacters,
+ characterCount,
wordBreakInfo );
// 3) Set the script info.
Vector<ScriptRun>& scripts = logicalModel->mScriptRuns;
multilanguageSupport.SetScripts( utf32Characters,
0u,
- numberOfCharacters,
+ characterCount,
scripts );
// 4) Set the font info
fontDescription,
TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
0u,
- numberOfCharacters,
+ characterCount,
validFonts );
// 5) Set the bidirectional info per paragraph.
scripts,
lineBreakInfo,
0u,
- numberOfCharacters,
+ characterCount,
bidirectionalInfo );
// Create the paragraph info.
logicalModel->CreateParagraphInfo( 0u,
- numberOfCharacters );
+ characterCount );
// 6) Set character directions.
Vector<CharacterDirection>& characterDirections = logicalModel->mCharacterDirections;
{
// Only set the character directions if there is right to left characters.
GetCharactersDirection( bidirectionalInfo,
- numberOfCharacters,
+ characterCount,
0u,
- numberOfCharacters,
+ characterCount,
characterDirections );
characterDirections,
bidirectionalInfo,
0u,
- numberOfCharacters,
+ characterCount,
mirroredUtf32Characters );
}
else
validFonts,
0u,
0u,
- numberOfCharacters,
+ characterCount,
glyphs,
glyphsToCharactersMap,
charactersPerGlyph,
newParagraphGlyphs );
// Create the 'number of glyphs' per character and the glyph to character conversion tables.
- visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, numberOfCharacters );
- visualModel->CreateCharacterToGlyphTable( 0u, 0u, numberOfCharacters );
+ visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, characterCount );
+ visualModel->CreateCharacterToGlyphTable( 0u, 0u, characterCount );
const Length numberOfGlyphs = glyphs.Count();
Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
glyphPositions.Resize( numberOfGlyphs );
- layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( numberOfCharacters - 1u ) ) );
+ layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( characterCount - 1u ) ) );
// The initial glyph and the number of glyphs to layout.
layoutParameters.startGlyphIndex = 0u;
bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
ReorderLines( bidirectionalInfo,
0u,
- numberOfCharacters,
+ characterCount,
lines,
bidirectionalLineInfo );
// Re-layout the text. Reorder those lines with right to left characters.
layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
0u,
- numberOfCharacters,
+ characterCount,
glyphPositions );
}
}
float alignmentOffset = 0.f;
layoutEngine.Align( textArea,
0u,
- numberOfCharacters,
+ characterCount,
Text::HorizontalAlignment::BEGIN,
lines,
alignmentOffset );
* @param[out] logicalModel Pointer to a logical text model instance.
* @param[out] visualModel Pointer to a visual text model instance.
* @param[out] metrics Pointer to a wrapper around FontClient used to get metrics.
+ * @param[in] markupProcessorEnabled Enable markup processor to use markup text.
*/
void CreateTextModel( const std::string& text,
const Size& textArea,
Size& layoutSize,
LogicalModelPtr& logicalModel,
VisualModelPtr& visualModel,
- MetricsPtr& metrics );
+ MetricsPtr& metrics,
+ bool markupProcessorEnabled );
/**
* @brief Configures the text @p controller similarly to the one configured by the text-label.
struct GetCharactersDirectionData
{
- std::string description; ///< Description of the test.
- std::string text; ///< Input text.
- unsigned int startIndex; ///< The index from where the model is updated.
- unsigned int numberOfCharacters; ///< The number of characters.
- bool* directions; ///< The expected directions.
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The index from where the model is updated.
+ unsigned int numberOfCharacters; ///< The number of characters.
+ bool* directions; ///< The expected directions.
+ bool markupProcessorEnabled; ///< Enable markup processor to use markup text.
};
bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Clear the bidirectional paragraph info data.
Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Clear the bidirectional line info data.
uint32_t startRemoveIndex = logicalModel->mBidirectionalLineInfo.Count();
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Call the GetMirroredText() function for the whole text
Vector<Character> mirroredText;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ data.markupProcessorEnabled );
Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
true, true, true, true, true, true, true, true, true, true,
true, true, false, false, false, false, false };
+ bool directions06[] = {
+ true, true, true, true, true, true, true, true, true, true,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false };
+
struct GetCharactersDirectionData data[] =
{
{
"",
0u,
0u,
- directions01
+ directions01,
+ false
},
{
"Left to right characters only",
"Hello world\nhello world demo",
0u,
28u,
- directions02
+ directions02,
+ false
},
{
"Right to left characters only",
"שלום עולם\nשלום עולם",
0u,
19u,
- directions03
+ directions03,
+ false
},
{
"Mix of bidirectional text",
"Hello world\nhello world שלום עולם\nשלום עולם hello world",
0u,
55u,
- directions04
+ directions04,
+ false
},
{
"Mix of bidirectional text. With more paragraphs.",
" مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
0u,
227u,
- directions05
+ directions05,
+ false
},
{
"Mix of bidirectional text. With more paragraphs. Update first paragraph.",
" مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
0u,
17u,
- directions05
+ directions05,
+ false
},
{
"Mix of bidirectional text. With more paragraphs. Update from character 29",
" مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
29u,
134u,
- directions05
+ directions05,
+ false
},
{
"Mix of bidirectional text. With more paragraphs. Update from character 163",
" مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
163u,
35u,
- directions05
+ directions05,
+ false
+ },
+ {
+ "Mix of bidirectional text. With brackets and LRM",
+ "שלום עולם ‎(hello)[world]‎",
+ 0u,
+ 26u,
+ directions06,
+ true
}
};
- const unsigned int numberOfTests = 8u;
+ const unsigned int numberOfTests = 9u;
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Clear the paragraphs.
Vector<ParagraphRun>& paragraphs = logicalModel->mParagraphInfo;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Find the paragraphs.
Vector<ParagraphRunIndex> paragraphs;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
for( unsigned int index = 0; index < data.numberOfTests; ++index )
{
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
{
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
{
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
for( unsigned int index = 0; index < data.numberOfTests; ++index )
{
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
for( unsigned int index = 0; index < data.numberOfTests; ++index )
{
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
GetCursorPositionParameters parameters;
parameters.visualModel = visualModel;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
for( unsigned int index = 0; index < data.numberOfTests; ++index )
{
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Clear the layout.
Vector<LineRun>& lines = visualModel->mLines;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Call the ReLayoutRightToLeftLines() method.
Layout::Engine engine;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// Call the Align method.
Layout::Engine engine;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
// 2) Clear the model.
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
layoutSize,
logicalModel,
visualModel,
- metrics );
+ metrics,
+ false );
Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;