X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=base%2Fdali-toolkit%2Finternal%2Fcontrols%2Ftext-view%2Ftext-view-processor.cpp;h=40f1fab2ae7cdf4ef92d4ae5a98abcf684117d5f;hp=a485a6e6e02f9a29493282de0eae067f349000a2;hb=b8c93847cc736bfc69876fd087ab06474fbfbe47;hpb=8c06d1257654f498737607c2dc9153d9178ece43 diff --git a/base/dali-toolkit/internal/controls/text-view/text-view-processor.cpp b/base/dali-toolkit/internal/controls/text-view/text-view-processor.cpp index a485a6e..40f1fab 100644 --- a/base/dali-toolkit/internal/controls/text-view/text-view-processor.cpp +++ b/base/dali-toolkit/internal/controls/text-view/text-view-processor.cpp @@ -19,10 +19,12 @@ #include // INTERNAL INCLUDES +#include #include #include #include #include +#include namespace Dali { @@ -84,7 +86,8 @@ void UpdateLayoutInfo( TextLayoutInfo& textLayoutInfo ) TextInfoIndices::TextInfoIndices() : mParagraphIndex( 0u ), mWordIndex( 0u ), - mCharacterIndex( 0u ) + mCharacterIndex( 0u ), + mCharacterParagraphIndex( 0u ) { } @@ -93,7 +96,8 @@ TextInfoIndices::TextInfoIndices( const std::size_t paragraphIndex, const std::size_t characterIndex ) : mParagraphIndex( paragraphIndex ), mWordIndex( wordIndex ), - mCharacterIndex( characterIndex ) + mCharacterIndex( characterIndex ), + mCharacterParagraphIndex( 0u ) { } @@ -101,7 +105,8 @@ bool TextInfoIndices::operator==( const TextInfoIndices& indices ) const { return ( ( mParagraphIndex == indices.mParagraphIndex ) && ( mWordIndex == indices.mWordIndex ) && - ( mCharacterIndex == indices.mCharacterIndex ) ); + ( mCharacterIndex == indices.mCharacterIndex ) && + ( mCharacterParagraphIndex == indices.mCharacterParagraphIndex ) ); } ///////////////////// @@ -114,8 +119,19 @@ TextLayoutInfo::TextLayoutInfo() mMaxItalicsOffset( 0.f ), mNumberOfCharacters( 0u ), mParagraphsLayoutInfo(), - mEllipsizeLayoutInfo() + mEllipsizeLayoutInfo(), + mEllipsisText( "..." ), + mEllipsisTextStyles() { + // Sets default styles for the default ellipsis text. + mEllipsisTextStyles.PushBack( new TextStyle() ); + mEllipsisTextStyles.PushBack( new TextStyle() ); + mEllipsisTextStyles.PushBack( new TextStyle() ); +} + +TextLayoutInfo::~TextLayoutInfo() +{ + ClearStyles(); } TextLayoutInfo::TextLayoutInfo( const TextLayoutInfo& text ) @@ -124,8 +140,14 @@ TextLayoutInfo::TextLayoutInfo( const TextLayoutInfo& text ) mMaxItalicsOffset( text.mMaxItalicsOffset ), mNumberOfCharacters( text.mNumberOfCharacters ), mParagraphsLayoutInfo( text.mParagraphsLayoutInfo ), - mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo ) + mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo ), + mEllipsisText( text.mEllipsisText ), + mEllipsisTextStyles() { + for( Vector::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it ) + { + mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) ); + } } TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text ) @@ -138,11 +160,27 @@ TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text ) mNumberOfCharacters = text.mNumberOfCharacters; mParagraphsLayoutInfo = text.mParagraphsLayoutInfo; mEllipsizeLayoutInfo = text.mEllipsizeLayoutInfo; - } + mEllipsisText = text.mEllipsisText; + ClearStyles(); + + for( Vector::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it ) + { + mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) ); + } + } return *this; } +void TextLayoutInfo::ClearStyles() +{ + for( Vector::Iterator it = mEllipsisTextStyles.Begin(), endIt = mEllipsisTextStyles.End(); it != endIt; ++it ) + { + delete *it; + } + mEllipsisTextStyles.Clear(); +} + ///////////////////////////////////////////////////////////////////////////////////////////// void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, @@ -152,9 +190,11 @@ void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, // * Traverse the given text spliting it in paragraphs and each paragraph in words. // * White spaces and new paragraph characters are alone in one word. // * Bidirectional text is processed in each paragraph. + // It creates the conversion tables + // It does the ligatures if there is arabic glyphs. + // It doesn't reorder the text as it must be done for each line not for the paragraph. // * Generates a layout data structure to store layout information (size, position, ascender, text direction, etc) and metrics of all characters. - // * Generates a text-actor data structure to store text, style and text-actors. - // TODO: finish and test the bidirectional implementation. + // * Store text for each paragraph and the style for each character. // Collect previously created text-actors. std::vector textActors; @@ -168,49 +208,77 @@ void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, } // Store the ellipsize layout info before clearing the previous created info. + // TODO: fix this. Don't clear the ellipsis layout, store it somewhere else ... const WordLayoutInfo ellipsizeInfo = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo; + Dali::Text ellipsisText = relayoutData.mTextLayoutInfo.mEllipsisText; + Vector ellipsisTextStyles = relayoutData.mTextLayoutInfo.mEllipsisTextStyles; + relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Clear(); - // clear previous created info. + // clear previously created info. relayoutData.mTextLayoutInfo = TextLayoutInfo(); relayoutData.mCharacterLogicalToVisualMap.clear(); relayoutData.mCharacterVisualToLogicalMap.clear(); // Sets the ellipsize layout info. relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = ellipsizeInfo; + relayoutData.mTextLayoutInfo.mEllipsisText = ellipsisText; + relayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsisTextStyles; // Split the whole text in paragraphs. - std::vector paragraphs; + // It returns a vector of Text with all the paragraphs. + // and for each paragraph a vector of styles per character. TODO: don't create a style per character. + std::vector paragraphs; + std::vector< Vector > styles; TextProcessor::SplitInParagraphs( text, - paragraphs ); + paragraphs, + styles ); + + // Reserve space for the current number of paragraphs. + relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.resize( paragraphs.size(), ParagraphLayoutInfo() ); // Traverse all paragraphs - for( std::vector::const_iterator paragraphIt = paragraphs.begin(), paragraphEndIt = paragraphs.end(); paragraphIt != paragraphEndIt; ++paragraphIt ) + std::size_t paragraphIndex = 0u; + std::vector::iterator paragraphIt, paragraphEndIt; + std::vector< Vector >::const_iterator styleIt, styleEndIt; + for( paragraphIt = paragraphs.begin(), paragraphEndIt = paragraphs.end(), + styleIt = styles.begin(), styleEndIt = styles.end(); + ( paragraphIt != paragraphEndIt ) && ( styleIt != styleEndIt ); + ++paragraphIndex, + ++paragraphIt, + ++styleIt ) { - const MarkupProcessor::StyledTextArray& paragraph( *paragraphIt ); + // Gets the paragraph and the styles for each character. + Text& paragraph( *paragraphIt ); + const Vector& textStyles( *styleIt ); + + // Retrieve the data structure for the current paragraph. + ParagraphLayoutInfo& paragraphLayoutInfo = *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ); - // Data structures for the new paragraph - ParagraphLayoutInfo paragraphLayoutInfo; + // Sets text and styles. + paragraphLayoutInfo.mText = paragraph; + paragraphLayoutInfo.mTextStyles = textStyles; - // Fills the paragraph data structures with the layout info. - CreateParagraphInfo( paragraph, - relayoutData, - paragraphLayoutInfo ); + // Fills the paragraph data structure with the layout info. - if( 0u < paragraphLayoutInfo.mNumberOfCharacters ) + if( !paragraph.IsEmpty() ) { + CreateParagraphInfo( relayoutData, + paragraphLayoutInfo ); + // do not add the line offset if the paragraph has no characters. paragraphLayoutInfo.mSize.height += layoutParameters.mLineHeightOffset; paragraphLayoutInfo.mLineHeightOffset = layoutParameters.mLineHeightOffset; } else { - // line height needs to be added for the last paragraph. + // This paragraph has no text. i.e. the previous paragraph ends with '\n'. + // Even though, line height needs to be set in order to align the whole text correctly. float lineHeight = 0.f; // Get the last character of the last paragraph. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) + if( 0u < paragraphIndex ) { - const ParagraphLayoutInfo& paragraphInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); + const ParagraphLayoutInfo& paragraphInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + ( paragraphIndex - 1u ) ) ); const CharacterLayoutInfo characterInfo = GetLastCharacterLayoutInfo( paragraphInfo ); @@ -220,16 +288,21 @@ void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, paragraphLayoutInfo.mSize.height = lineHeight; } + // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text. + // If there is right to left text, it needs to be updated every time the text is relaid-out. + for( std::size_t index = 0u; index < paragraphLayoutInfo.mNumberOfCharacters; ++index ) + { + relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); + relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); + } + // Update layout info for the whole text. UpdateSize( relayoutData.mTextLayoutInfo.mWholeTextSize, paragraphLayoutInfo.mSize, GrowHeight ); relayoutData.mTextLayoutInfo.mNumberOfCharacters += paragraphLayoutInfo.mNumberOfCharacters; - - // Add the paragraph to the current text. - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.push_back( paragraphLayoutInfo ); } // end of paragraphs } -void UpdateTextInfo( const std::size_t position, +void UpdateTextInfo( std::size_t position, const MarkupProcessor::StyledTextArray& text, const TextView::LayoutParameters& layoutParameters, TextView::RelayoutData& relayoutData ) @@ -242,7 +315,7 @@ void UpdateTextInfo( const std::size_t position, // * Merge the last paragraph of the new text to the last part or the split paragraph. // * Add paragraphs between first and last of the new text. // * Merge the first part of the split paragraph with the first paragraph of the new text. - // * Update layout info and create new text actors if needed. + // * Update the layout info for the whole text. // Early returns: @@ -269,6 +342,15 @@ void UpdateTextInfo( const std::size_t position, DALI_ASSERT_ALWAYS( !"TextViewProcessor::UpdateTextInfo (insert). Trying to insert text out of bounds." ); } + + // TODO + // If in the insertion is involved right to left text, + // check the neighbour characters is needed. + // i.e. Arabic characters may have four different glyphs (isolated, end, middle, begin). + // So check the neighbours on each side is needed in order to render + // the correct ligatures. + + TextView::RelayoutData relayoutDataForNewText; // Creates layout info for the given text. @@ -277,8 +359,8 @@ void UpdateTextInfo( const std::size_t position, layoutParameters, relayoutDataForNewText ); - // Update logical-to-visual and visual-to-logical tables. - // TODO: check that for mixed RTL/LTR text. + // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text. + // If there is right to left text, it needs to be updated every time the text is relaid-out. std::size_t index = 0u; for( std::size_t i = 0u; i < relayoutDataForNewText.mTextLayoutInfo.mNumberOfCharacters; ++i ) { @@ -335,6 +417,13 @@ void UpdateTextInfo( const std::size_t position, const WordLayoutInfo& wordLayoutInfo( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ); textInfoIndices.mCharacterIndex = wordLayoutInfo.mCharactersLayoutInfo.size(); + + // Sets the character index within the paragraph. + textInfoIndices.mCharacterParagraphIndex = 0u; + for( WordLayoutInfoContainer::const_iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it ) + { + textInfoIndices.mCharacterParagraphIndex += wordLayoutInfo.mCharactersLayoutInfo.size(); + } } } } @@ -382,8 +471,8 @@ void UpdateTextInfo( const std::size_t position, UpdateLayoutInfo( relayoutData.mTextLayoutInfo ); } -void UpdateTextInfo( const std::size_t position, - const std::size_t numberOfCharacters, +void UpdateTextInfo( std::size_t position, + std::size_t numberOfCharacters, const TextView::LayoutParameters& layoutParameters, TextView::RelayoutData& relayoutData, const TextOperationOnRemove clearText ) @@ -414,7 +503,8 @@ void UpdateTextInfo( const std::size_t position, // Asserts if trying to delete text out of bounds. DALI_ASSERT_ALWAYS( position + numberOfCharacters <= relayoutData.mTextLayoutInfo.mNumberOfCharacters && "TextViewProcessor::UpdateTextInfo. ERROR: trying to delete characters out of boundary" ); - // Remove characters from character to visual map and vs //TODO: check this for RTL text!! + // Remove characters from character to visual map and vs. + // If there is right to left text, it needs to be updated every time the text is relaid-out. relayoutData.mCharacterLogicalToVisualMap.erase( relayoutData.mCharacterLogicalToVisualMap.end() - numberOfCharacters, relayoutData.mCharacterLogicalToVisualMap.end() ); relayoutData.mCharacterVisualToLogicalMap.erase( relayoutData.mCharacterVisualToLogicalMap.end() - numberOfCharacters, relayoutData.mCharacterVisualToLogicalMap.end() ); @@ -521,6 +611,19 @@ void UpdateTextInfo( const std::size_t position, // As paragraphIndexBegin has been increased just to not to remove the paragraph, decrease now is needed to access it. ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex - 1u ) ); + // Remove the characters from the text and the styles. + paragraphLayout.mText.Remove( textInfoIndicesBegin.mCharacterParagraphIndex, paragraphLayout.mNumberOfCharacters - textInfoIndicesBegin.mCharacterParagraphIndex ); + + for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex, + endIt = paragraphLayout.mTextStyles.End(); + it != endIt; + ++it ) + { + delete *it; + } + paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex, + paragraphLayout.mTextStyles.End() ); + if( ( textInfoIndicesBegin.mWordIndex + 1u < paragraphLayout.mWordsLayoutInfo.size() ) || ( 0u == textInfoIndicesBegin.mCharacterIndex ) ) { // Remove extra words within current paragraph. (and current word if whole characters are removed) @@ -577,6 +680,21 @@ void UpdateTextInfo( const std::size_t position, // Get the last paragraph. ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ) ); + // Remove the characters from the text and the styles. + const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u; + + paragraphLayout.mText.Remove( 0u, lastCharacterIndex ); + + for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin(), + endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex; + it != endIt; + ++it ) + { + delete *it; + } + paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin(), + paragraphLayout.mTextStyles.Begin() + lastCharacterIndex ); + // Check if is needed remove the whole word. (If the character index is pointing just after the end of the word) const WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) ); bool removeWholeWord = wordLayout.mCharactersLayoutInfo.size() == textInfoIndicesEnd.mCharacterIndex + 1u; @@ -634,6 +752,22 @@ void UpdateTextInfo( const std::size_t position, // Paragraph which contains the characters to be deleted. ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex ) ); + // Remove the characters from the text and the styles. + const std::size_t firstCharacterIndex = textInfoIndicesBegin.mCharacterParagraphIndex; + const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u; + + paragraphLayout.mText.Remove( firstCharacterIndex, lastCharacterIndex - firstCharacterIndex ); + + for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin() + firstCharacterIndex, + endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex; + it != endIt; + ++it ) + { + delete *it; + } + paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + firstCharacterIndex, + paragraphLayout.mTextStyles.Begin() + lastCharacterIndex ); + // Remove the characters from the paragraph layout info. It returns whether the current paragraph can be merged with the next one. RemoveCharactersFromParagraphInfo( relayoutData, numberOfCharacters, @@ -730,8 +864,8 @@ void UpdateTextInfo( const std::size_t position, relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromBegin ); } -void UpdateTextInfo( const std::size_t position, - const std::size_t numberOfCharacters, +void UpdateTextInfo( std::size_t position, + std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text, const TextView::LayoutParameters& layoutParameters, TextView::RelayoutData& relayoutData ) @@ -788,6 +922,17 @@ void UpdateTextInfo( const TextStyle& style, { ParagraphLayoutInfo& paragraph( *paragraphIt ); + std::size_t index = 0u; + for( Vector::Iterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it ) + { + (*it)->Copy( style, mask ); + + // Checks if the font family supports all glyphs. If not, chooses a most suitable one. + ChooseFontFamilyName( paragraph.mText[index], *(*it) ); + + ++index; + } + for( WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); wordIt != wordEndIt; ++wordIt ) @@ -800,11 +945,6 @@ void UpdateTextInfo( const TextStyle& style, { CharacterLayoutInfo& characterLayout( *characterIt ); - characterLayout.mStyledText.mStyle.Copy( style, mask ); - - // Checks if the font family supports all glyphs. If not, chooses a most suitable one. - ChooseFontFamilyName( characterLayout.mStyledText ); - // Mark the character to be set the new style into the text-actor. characterLayout.mSetStyle = true; } // end characters