X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fbidirectional-support.cpp;h=9bf27f8bc68aef52372f35343ca52e823853bd43;hp=57dc6137a457711ba61f75c9aee655d702bab9c4;hb=750fadba87bb959c9af32e89e3f1bc7af6cb6dd2;hpb=b899c4999231a14190e804e13b941527c3c437a1 diff --git a/dali-toolkit/internal/text/bidirectional-support.cpp b/dali-toolkit/internal/text/bidirectional-support.cpp index 57dc613..9bf27f8 100644 --- a/dali-toolkit/internal/text/bidirectional-support.cpp +++ b/dali-toolkit/internal/text/bidirectional-support.cpp @@ -19,87 +19,34 @@ #include // EXTERNAL INCLUDES -#include #include +#include namespace Dali { - namespace Toolkit { - namespace Text { - -namespace -{ - -/** - * @brief Get the lines of a paragraph. - * - * @param[in] paragraphInfo The paragraph. - * @param[in] lines The lines. - * @param[in] lineIndex Index pointing the first line to be checked. - * @param[out] firstLine Index to the first line of the paragraph. - * @param[out] numberOfLines The number of lines. - */ -void GetLines( const BidirectionalParagraphInfoRun& paragraphInfo, - const Vector& lines, - unsigned int lineIndex, - unsigned int& firstLine, - unsigned int& numberOfLines ) -{ - firstLine = lineIndex; - numberOfLines = 0u; - - const CharacterIndex lastCharacterIndex = paragraphInfo.characterRun.characterIndex + paragraphInfo.characterRun.numberOfCharacters; - bool firstLineFound = false; - - for( Vector::ConstIterator it = lines.Begin() + lineIndex, - endIt = lines.End(); - it != endIt; - ++it ) - { - const LineRun& line = *it; - - if( ( line.characterRun.characterIndex + line.characterRun.numberOfCharacters > paragraphInfo.characterRun.characterIndex ) && - ( lastCharacterIndex > line.characterRun.characterIndex ) ) - { - firstLineFound = true; - ++numberOfLines; - } - else if( lastCharacterIndex <= line.characterRun.characterIndex ) - { - // nothing else to do. - break; - } - - if( !firstLineFound ) - { - ++firstLine; - } - } -} - -} // namespace - -void SetBidirectionalInfo( const Vector& text, - const Vector& scripts, - const Vector& lineBreakInfo, - CharacterIndex startIndex, - Length numberOfCharacters, - Vector& bidirectionalInfo ) +void SetBidirectionalInfo(const Vector& text, + const Vector& scripts, + const Vector& lineBreakInfo, + CharacterIndex startIndex, + Length numberOfCharacters, + Vector& bidirectionalInfo, + bool matchLayoutDirection, + Dali::LayoutDirection::Type layoutDirection) { // Find where to insert the new paragraphs. BidirectionalRunIndex bidiInfoIndex = 0u; - for( Vector::ConstIterator it = bidirectionalInfo.Begin(), - endIt = bidirectionalInfo.End(); - it != endIt; - ++it ) + for(Vector::ConstIterator it = bidirectionalInfo.Begin(), + endIt = bidirectionalInfo.End(); + it != endIt; + ++it) { const BidirectionalParagraphInfoRun& run = *it; - if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters ) + if(startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters) { // Found where to insert the bidi info. break; @@ -126,48 +73,52 @@ void SetBidirectionalInfo( const Vector& text, bool hasRightToLeftScript = false; - for( Vector::ConstIterator it = scripts.Begin(), - endIt = scripts.End(); - it != endIt; - ++it ) + for(Vector::ConstIterator it = scripts.Begin(), + endIt = scripts.End(); + it != endIt; + ++it) { - const ScriptRun& scriptRun = *it; + const ScriptRun& scriptRun = *it; const CharacterIndex lastScriptRunIndex = scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters - 1u; - if( startIndex > lastScriptRunIndex ) + if(startIndex > lastScriptRunIndex) { // Skip the run as it has already been processed. continue; } - if( lastCharacter <= scriptRun.characterRun.characterIndex ) + if(lastCharacter <= scriptRun.characterRun.characterIndex) { // Do not get bidirectional info beyond startIndex + numberOfCharacters. break; } - if( !hasRightToLeftScript && TextAbstraction::IsRightToLeftScript( scriptRun.script ) ) + if(!hasRightToLeftScript && scriptRun.isRightToLeft) { // The script is right to left. hasRightToLeftScript = true; } - if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + lastScriptRunIndex ) ) + if(TextAbstraction::LINE_MUST_BREAK == *(lineBreakInfoBuffer + lastScriptRunIndex)) { // A new paragraph has been found. - if( hasRightToLeftScript ) + if(hasRightToLeftScript) { // The Bidirectional run must have the same number of characters than the paragraph. BidirectionalParagraphInfoRun bidirectionalRun; - bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex; - bidirectionalRun.characterRun.numberOfCharacters = ( lastScriptRunIndex - paragraphCharacterIndex ) + 1u; // The must break character is part of the paragrah. + bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex; + bidirectionalRun.characterRun.numberOfCharacters = (lastScriptRunIndex - paragraphCharacterIndex) + 1u; // The must break character is part of the paragrah. // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run. - bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo( textBuffer + bidirectionalRun.characterRun.characterIndex, - bidirectionalRun.characterRun.numberOfCharacters ); + bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo(textBuffer + bidirectionalRun.characterRun.characterIndex, + bidirectionalRun.characterRun.numberOfCharacters, + matchLayoutDirection, + layoutDirection); - bidirectionalInfo.Insert( bidirectionalInfo.Begin() + bidiInfoIndex, bidirectionalRun ); + bidirectionalRun.direction = bidirectionalSupport.GetParagraphDirection(bidirectionalRun.bidirectionalInfoIndex); + + bidirectionalInfo.Insert(bidirectionalInfo.Begin() + bidiInfoIndex, bidirectionalRun); ++bidiInfoIndex; } @@ -180,10 +131,10 @@ void SetBidirectionalInfo( const Vector& text, } // Update indices of the bidi runs. - for( Vector::Iterator it = bidirectionalInfo.Begin() + bidiInfoIndex, - endIt = bidirectionalInfo.End(); - it != endIt; - ++it ) + for(Vector::Iterator it = bidirectionalInfo.Begin() + bidiInfoIndex, + endIt = bidirectionalInfo.End(); + it != endIt; + ++it) { BidirectionalParagraphInfoRun& run = *it; @@ -191,126 +142,78 @@ void SetBidirectionalInfo( const Vector& text, } } -void ReorderLines( const Vector& bidirectionalInfo, - CharacterIndex startIndex, - Length numberOfCharacters, - Vector& lineRuns, - Vector& lineInfoRuns ) +void ReorderLine(const BidirectionalParagraphInfoRun& bidirectionalParagraphInfo, + Vector& lineInfoRuns, + BidirectionalLineRunIndex bidiLineIndex, + CharacterIndex startIndex, + Length numberOfCharacters, + CharacterIndex startIndexInSecondHalfLine, + Length numberOfCharactersInSecondHalfLine, + CharacterDirection direction) { - // Find where to insert the new paragraphs. - BidirectionalLineRunIndex bidiLineInfoIndex = 0u; - for( Vector::ConstIterator it = lineInfoRuns.Begin(), - endIt = lineInfoRuns.End(); - it != endIt; - ++it ) - { - const BidirectionalLineInfoRun& run = *it; - - if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters ) - { - // Found where to insert the bidi line info. - break; - } - ++bidiLineInfoIndex; - } - // Handle to the bidirectional info module in text-abstraction. TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); - const CharacterIndex lastCharacter = startIndex + numberOfCharacters; + // Creates a bidirectional info for the line run. + BidirectionalLineInfoRun lineInfoRun; + lineInfoRun.characterRun.characterIndex = startIndex; + lineInfoRun.characterRun.numberOfCharacters = numberOfCharacters; + lineInfoRun.direction = direction; + lineInfoRun.isIdentity = true; - // Keep an index to the first line to be checked if it's contained inside the paragraph. - // Avoids check the lines from the beginning for each paragraph. - unsigned int lineIndex = 0u; + lineInfoRun.characterRunForSecondHalfLine.characterIndex = startIndexInSecondHalfLine; + lineInfoRun.characterRunForSecondHalfLine.numberOfCharacters = numberOfCharactersInSecondHalfLine; - for( Vector::ConstIterator it = bidirectionalInfo.Begin(), - endIt = bidirectionalInfo.End(); - it != endIt; - ++it ) - { - const BidirectionalParagraphInfoRun& paragraphInfo = *it; + // Allocate space for the conversion maps. + // The memory is freed after the visual to logical to visual conversion tables are built in the logical model. + lineInfoRun.visualToLogicalMap = reinterpret_cast(malloc(numberOfCharacters * sizeof(CharacterIndex))); - if( paragraphInfo.characterRun.characterIndex < startIndex ) - { - // Do not process, the paragraph has already been processed. - continue; - } + lineInfoRun.visualToLogicalMapSecondHalf = reinterpret_cast(malloc(numberOfCharactersInSecondHalfLine * sizeof(CharacterIndex))); - if( lastCharacter <= paragraphInfo.characterRun.characterIndex ) + if(nullptr != lineInfoRun.visualToLogicalMap && nullptr != lineInfoRun.visualToLogicalMapSecondHalf) + { + // Reorders the line. + bidirectionalSupport.Reorder(bidirectionalParagraphInfo.bidirectionalInfoIndex, + lineInfoRun.characterRun.characterIndex - bidirectionalParagraphInfo.characterRun.characterIndex, + lineInfoRun.characterRun.numberOfCharacters, + lineInfoRun.visualToLogicalMap); + + bidirectionalSupport.Reorder(bidirectionalParagraphInfo.bidirectionalInfoIndex, + lineInfoRun.characterRunForSecondHalfLine.characterIndex - bidirectionalParagraphInfo.characterRun.characterIndex, + lineInfoRun.characterRunForSecondHalfLine.numberOfCharacters, + lineInfoRun.visualToLogicalMapSecondHalf); + + // For those LTR lines inside a bidirectional paragraph. + // It will save to relayout the line after reordering. + for(unsigned int i = 0; i < numberOfCharacters; ++i) { - // Do not process paragraphs beyond startIndex + numberOfCharacters. - break; + if(i != *(lineInfoRun.visualToLogicalMap + i)) + { + lineInfoRun.isIdentity = false; + break; + } } - const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( paragraphInfo.bidirectionalInfoIndex ); - - // Get the lines for this paragraph. - unsigned int firstLine = 0u; - unsigned int numberOfLines = 0u; - - // Get an index to the first line and the number of lines of the current paragraph. - GetLines( paragraphInfo, - lineRuns, - lineIndex, - firstLine, - numberOfLines ); - - lineIndex = firstLine + numberOfLines; - - // Traverse the lines and reorder them - for( Vector::Iterator lineIt = lineRuns.Begin() + firstLine, - endLineIt = lineRuns.Begin() + firstLine + numberOfLines; - lineIt != endLineIt; - ++lineIt ) + for(unsigned int i = 0; i < numberOfCharactersInSecondHalfLine; ++i) { - LineRun& line = *lineIt; - - // Sets the paragraph's direction. - line.direction = direction; - - // Creates a bidirectional info for the line run. - BidirectionalLineInfoRun lineInfoRun; - lineInfoRun.characterRun.characterIndex = line.characterRun.characterIndex; - lineInfoRun.characterRun.numberOfCharacters = line.characterRun.numberOfCharacters; - lineInfoRun.direction = direction; - - // Allocate space for the conversion maps. - // The memory is freed after the visual to logical to visual conversion tables are built in the logical model. - lineInfoRun.visualToLogicalMap = reinterpret_cast( malloc( line.characterRun.numberOfCharacters * sizeof( CharacterIndex ) ) ); - - if( NULL != lineInfoRun.visualToLogicalMap ) + if(i != *(lineInfoRun.visualToLogicalMapSecondHalf + i)) { - // Reorders the line. - bidirectionalSupport.Reorder( paragraphInfo.bidirectionalInfoIndex, - line.characterRun.characterIndex - paragraphInfo.characterRun.characterIndex, - line.characterRun.numberOfCharacters, - lineInfoRun.visualToLogicalMap ); + lineInfoRun.isIdentity = false; + break; } - - // Push the run into the vector. - lineInfoRuns.Insert( lineInfoRuns.Begin() + bidiLineInfoIndex, lineInfoRun ); - ++bidiLineInfoIndex; } } - // Update indices of the bidi runs. - for( Vector::Iterator it = lineInfoRuns.Begin() + bidiLineInfoIndex, - endIt = lineInfoRuns.End(); - it != endIt; - ++it ) - { - BidirectionalLineInfoRun& run = *it; - - run.characterRun.characterIndex += numberOfCharacters; - } + // Push the run into the vector. + lineInfoRuns.Insert(lineInfoRuns.Begin() + bidiLineIndex, lineInfoRun); } -bool GetMirroredText( const Vector& text, - const Vector& directions, - const Vector& bidirectionalInfo, - CharacterIndex startIndex, - Length numberOfCharacters, - Vector& mirroredText ) +bool GetMirroredText(const Vector& text, + const Vector& directions, + const Vector& bidirectionalInfo, + CharacterIndex startIndex, + Length numberOfCharacters, + Vector& mirroredText) { bool hasTextMirrored = false; @@ -319,36 +222,36 @@ bool GetMirroredText( const Vector& text, mirroredText = text; - Character* mirroredTextBuffer = mirroredText.Begin(); - CharacterDirection* directionsBuffer = directions.Begin(); + Character* mirroredTextBuffer = mirroredText.Begin(); + CharacterDirection* directionsBuffer = directions.Begin(); - CharacterIndex index = startIndex; + CharacterIndex index = startIndex; const CharacterIndex lastCharacter = startIndex + numberOfCharacters; // Traverse the paragraphs and mirror the right to left ones. - for( Vector::ConstIterator it = bidirectionalInfo.Begin(), - endIt = bidirectionalInfo.End(); - it != endIt; - ++it ) + for(Vector::ConstIterator it = bidirectionalInfo.Begin(), + endIt = bidirectionalInfo.End(); + it != endIt; + ++it) { const BidirectionalParagraphInfoRun& paragraph = *it; - if( index >= paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters ) + if(index >= paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters) { // Skip the paragraph as it has already been processed. continue; } - if( lastCharacter <= paragraph.characterRun.characterIndex ) + if(lastCharacter <= paragraph.characterRun.characterIndex) { // Do not get mirror characters beyond startIndex + numberOfCharacters. break; } index += paragraph.characterRun.numberOfCharacters; - const bool tmpMirrored = bidirectionalSupport.GetMirroredText( mirroredTextBuffer + paragraph.characterRun.characterIndex, - directionsBuffer + paragraph.characterRun.characterIndex, - paragraph.characterRun.numberOfCharacters ); + const bool tmpMirrored = bidirectionalSupport.GetMirroredText(mirroredTextBuffer + paragraph.characterRun.characterIndex, + directionsBuffer + paragraph.characterRun.characterIndex, + paragraph.characterRun.numberOfCharacters); hasTextMirrored = hasTextMirrored || tmpMirrored; } @@ -356,27 +259,27 @@ bool GetMirroredText( const Vector& text, return hasTextMirrored; } -void GetCharactersDirection( const Vector& bidirectionalInfo, - Length totalNumberOfCharacters, - CharacterIndex startIndex, - Length numberOfCharacters, - Vector& directions ) +void GetCharactersDirection(const Vector& bidirectionalInfo, + Length totalNumberOfCharacters, + CharacterIndex startIndex, + Length numberOfCharacters, + Vector& directions) { // Handle to the bidirectional info module in text-abstraction. TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); // Resize the vector. - directions.Resize( totalNumberOfCharacters ); + directions.Resize(totalNumberOfCharacters); // Whether the current buffer is being updated or is set from scratch. const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters; - CharacterDirection* directionsBuffer = NULL; + CharacterDirection* directionsBuffer = NULL; Vector newDirections; - if( updateCurrentBuffer ) + if(updateCurrentBuffer) { - newDirections.Resize( numberOfCharacters ); + newDirections.Resize(numberOfCharacters); directionsBuffer = newDirections.Begin(); } else @@ -385,22 +288,22 @@ void GetCharactersDirection( const Vector& bidire } const CharacterIndex lastCharacter = startIndex + numberOfCharacters; - CharacterIndex index = startIndex; + CharacterIndex index = startIndex; - for( Vector::ConstIterator it = bidirectionalInfo.Begin(), - endIt = bidirectionalInfo.End(); - it != endIt; - ++it ) + for(Vector::ConstIterator it = bidirectionalInfo.Begin(), + endIt = bidirectionalInfo.End(); + it != endIt; + ++it) { const BidirectionalParagraphInfoRun& paragraph = *it; - if( index >= paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters ) + if(index >= paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters) { // Skip the paragraph as it has already been processed. continue; } - if( lastCharacter <= paragraph.characterRun.characterIndex ) + if(lastCharacter <= paragraph.characterRun.characterIndex) { // Do not get the character directions beyond startIndex + numberOfCharacters. break; @@ -408,31 +311,31 @@ void GetCharactersDirection( const Vector& bidire // Set the directions of any previous left to right characters. const Length numberOfLeftToRightCharacters = paragraph.characterRun.characterIndex - index; - if( numberOfLeftToRightCharacters > 0u ) + if(numberOfLeftToRightCharacters > 0u) { - memset( directionsBuffer + index - startIndex, false, numberOfLeftToRightCharacters * sizeof( bool ) ); + memset(directionsBuffer + index - startIndex, false, numberOfLeftToRightCharacters * sizeof(bool)); } // Set the directions of the bidirectional text. - bidirectionalSupport.GetCharactersDirection( paragraph.bidirectionalInfoIndex, - directionsBuffer + paragraph.characterRun.characterIndex - startIndex, - paragraph.characterRun.numberOfCharacters ); + bidirectionalSupport.GetCharactersDirection(paragraph.bidirectionalInfoIndex, + directionsBuffer + paragraph.characterRun.characterIndex - startIndex, + paragraph.characterRun.numberOfCharacters); // Update the index. index += paragraph.characterRun.numberOfCharacters + numberOfLeftToRightCharacters; } // Fills with left to right those paragraphs without right to left characters. - memset( directionsBuffer + index - startIndex, false, ( lastCharacter - index ) * sizeof( bool ) ); + memset(directionsBuffer + index - startIndex, false, (lastCharacter - index) * sizeof(bool)); // If the direction info is updated, it needs to be inserted in the model. - if( updateCurrentBuffer ) + if(updateCurrentBuffer) { // Insert the directions in the given buffer. - directions.Insert( directions.Begin() + startIndex, - newDirections.Begin(), - newDirections.End() ); - directions.Resize( totalNumberOfCharacters ); + directions.Insert(directions.Begin() + startIndex, + newDirections.Begin(), + newDirections.End()); + directions.Resize(totalNumberOfCharacters); } }