X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller.cpp;h=79185bae4d6404fae217f43f4b7c0e9ea29b0b9d;hp=b0fb0d1dcd609eafbddfccc110247789b87d2242;hb=6f62c2545af5b288bf447c380ccfb562cc7a4370;hpb=0a88df264063357348ba3e2caee1258e90e55cfb diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index b0fb0d1..79185ba 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -18,7 +18,14 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include +#include +#include +#include + // INTERNAL INCLUDES +#include #include #include #include @@ -30,17 +37,12 @@ #include #include -// EXTERNAL INCLUDES -#include -#include -#include -#include - using std::vector; namespace { const float MAX_FLOAT = std::numeric_limits::max(); +const std::string EMPTY_STRING; } // namespace namespace Dali @@ -100,7 +102,9 @@ struct Controller::TextInput : mLogicalModel( logicalModel ), mVisualModel( visualModel ), mDecorator( decorator ), - mState( INACTIVE ) + mState( INACTIVE ), + mDecoratorUpdated( false ), + mCursorBlinkEnabled( true ) { } @@ -153,6 +157,14 @@ struct Controller::TextInput void OnKeyboardFocus( bool hasFocus ) { + if( !hasFocus ) + { + ChangeState( INACTIVE ); + } + else + { + ChangeState( EDITING ); + } } void OnKeyEvent( const Event& event ) @@ -240,8 +252,14 @@ struct Controller::TextInput GetClosestCursorPosition( xPosition, yPosition, height ); mDecorator->SetPosition( PRIMARY_CURSOR, xPosition, yPosition, height ); + mDecorator->HidePopup(); mDecoratorUpdated = true; } + else if ( GRAB_HANDLE_RELEASED == state ) + { + mDecorator->ShowPopup(); + } + } void ChangeState( State newState ) @@ -256,6 +274,7 @@ struct Controller::TextInput mDecorator->StopCursorBlink(); mDecorator->SetGrabHandleActive( false ); mDecorator->SetSelectionActive( false ); + mDecorator->HidePopup(); mDecoratorUpdated = true; } else if ( SELECTING == mState ) @@ -269,7 +288,10 @@ struct Controller::TextInput else if( EDITING == mState ) { mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); - mDecorator->StartCursorBlink(); + if( mCursorBlinkEnabled ) + { + mDecorator->StartCursorBlink(); + } mDecorator->SetGrabHandleActive( true ); mDecorator->SetSelectionActive( false ); mDecoratorUpdated = true; @@ -339,7 +361,8 @@ struct Controller::TextInput State mState; - bool mDecoratorUpdated; + bool mDecoratorUpdated : 1; + bool mCursorBlinkEnabled : 1; }; struct Controller::FontDefaults @@ -426,6 +449,18 @@ void Controller::SetText( const std::string& text ) // The natural size needs to be re-calculated. mImpl->mRecalculateNaturalSize = true; + // Reset buffers. + mImpl->mLogicalModel->SetText( NULL, 0u ); + mImpl->mLogicalModel->SetScripts( NULL, 0u ); + mImpl->mLogicalModel->SetFonts( NULL, 0u ); + mImpl->mLogicalModel->SetLineBreakInfo( NULL, 0u ); + mImpl->mLogicalModel->SetWordBreakInfo( NULL, 0u ); + mImpl->mLogicalModel->SetBidirectionalInfo( NULL, 0u ); + mImpl->mLogicalModel->SetVisualToLogicalMap( NULL, 0u ); + mImpl->mVisualModel->SetGlyphs( NULL, NULL, NULL, 0u ); + mImpl->mVisualModel->SetGlyphPositions( NULL, 0u ); + mImpl->mVisualModel->SetLines( NULL, 0u ); + if( mImpl->mTextInput ) { // Cancel previously queued events @@ -483,7 +518,7 @@ const std::string& Controller::GetDefaultFontFamily() const return mImpl->mFontDefaults->mDefaultFontFamily; } - return Dali::String::EMPTY; + return EMPTY_STRING; } void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle ) @@ -506,7 +541,7 @@ const std::string& Controller::GetDefaultFontStyle() const return mImpl->mFontDefaults->mDefaultFontStyle; } - return Dali::String::EMPTY; + return EMPTY_STRING; } void Controller::SetDefaultPointSize( float pointSize ) @@ -532,6 +567,20 @@ float Controller::GetDefaultPointSize() const return 0.0f; } +void Controller::GetDefaultFonts( Vector& fonts, Length numberOfCharacters ) +{ + if( mImpl->mFontDefaults ) + { + FontRun fontRun; + fontRun.characterRun.characterIndex = 0; + fontRun.characterRun.numberOfCharacters = numberOfCharacters; + fontRun.fontId = mImpl->mFontDefaults->GetFontId( mImpl->mFontClient ); + fontRun.isDefault = true; + + fonts.PushBack( fontRun ); + } +} + void Controller::EnableTextInput( DecoratorPtr decorator ) { if( !mImpl->mTextInput ) @@ -540,12 +589,45 @@ void Controller::EnableTextInput( DecoratorPtr decorator ) } } +void Controller::SetEnableCursorBlink( bool enable ) +{ + DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "TextInput disabled" ); + + if( mImpl->mTextInput ) + { + mImpl->mTextInput->mCursorBlinkEnabled = enable; + + if( !enable && + mImpl->mTextInput->mDecorator ) + { + mImpl->mTextInput->mDecorator->StopCursorBlink(); + } + } +} + +bool Controller::GetEnableCursorBlink() const +{ + if( mImpl->mTextInput ) + { + return mImpl->mTextInput->mCursorBlinkEnabled; + } + + return false; +} + bool Controller::Relayout( const Vector2& size ) { if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) { + bool glyphsRemoved( false ); + if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() ) + { + mImpl->mVisualModel->SetGlyphPositions( NULL, 0u ); + glyphsRemoved = true; + } + // Not worth to relayout if width or height is equal to zero. - return false; + return glyphsRemoved; } if( size != mImpl->mControlSize ) @@ -611,6 +693,8 @@ bool Controller::DoRelayout( const Vector2& size, text.clear(); } + const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); + Vector lineBreakInfo; if( GET_LINE_BREAKS & operations ) { @@ -642,12 +726,7 @@ bool Controller::DoRelayout( const Vector2& size, const bool validateFonts = VALIDATE_FONTS & operations; Vector scripts; - Vector fonts; - - if( mImpl->mFontDefaults ) - { - // TODO - pass into ValidateFonts - } + Vector validFonts; if( getScripts || validateFonts ) { @@ -668,27 +747,100 @@ bool Controller::DoRelayout( const Vector2& size, if( validateFonts ) { + // Copy the requested font defaults received via the property system. + // These may not be valid i.e. may not contain glyphs for the necessary scripts. + GetDefaultFonts( validFonts, numberOfCharacters ); + // Validates the fonts. If there is a character with no assigned font it sets a default one. // After this call, fonts are validated. multilanguageSupport.ValidateFonts( utf32Characters, scripts, - fonts ); + validFonts ); // Sets the fonts into the model. - mImpl->mLogicalModel->SetFonts( fonts.Begin(), fonts.Count() ); + mImpl->mLogicalModel->SetFonts( validFonts.Begin(), validFonts.Count() ); } } + Vector bidirectionalInfo; + if( BIDI_INFO & operations ) + { + // Some vectors with data needed to get the paragraph's bidirectional info may be void + // after the first time the text has been laid out. + // Fill the vectors again. + + if( 0u == utf32Characters.Count() ) + { + utf32Characters.Resize( numberOfCharacters ); + + mImpl->mLogicalModel->GetText( utf32Characters.Begin(), + 0u, + numberOfCharacters ); + } + + if( 0u == lineBreakInfo.Count() ) + { + lineBreakInfo.Resize( numberOfCharacters ); + + mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(), + 0u, + numberOfCharacters ); + } + + if( 0u == scripts.Count() ) + { + scripts.Resize( mImpl->mLogicalModel->GetNumberOfScriptRuns( 0u, + numberOfCharacters ) ); + mImpl->mLogicalModel->GetScriptRuns( scripts.Begin(), + 0u, + numberOfCharacters ); + } + + // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's + // bidirectional info. + + Length numberOfParagraphs = 0u; + + const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + for( Length index = 0u; index < characterCount; ++index ) + { + if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) ) + { + ++numberOfParagraphs; + } + } + + bidirectionalInfo.Reserve( numberOfParagraphs ); + + // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts. + SetBidirectionalInfo( utf32Characters, + scripts, + lineBreakInfo, + bidirectionalInfo ); + + mImpl->mLogicalModel->SetBidirectionalInfo( bidirectionalInfo.Begin(), + bidirectionalInfo.Count() ); + } + Vector glyphs; Vector glyphsToCharactersMap; Vector charactersPerGlyph; if( SHAPE_TEXT & operations ) { + if( 0u == validFonts.Count() ) + { + validFonts.Resize( mImpl->mLogicalModel->GetNumberOfFontRuns( 0u, + numberOfCharacters ) ); + mImpl->mLogicalModel->GetFontRuns( validFonts.Begin(), + 0u, + numberOfCharacters ); + } + // Shapes the text. ShapeText( utf32Characters, lineBreakInfo, scripts, - fonts, + validFonts, glyphs, glyphsToCharactersMap, charactersPerGlyph ); @@ -711,34 +863,48 @@ bool Controller::DoRelayout( const Vector2& size, if( LAYOUT & operations ) { + // Some vectors with data needed to layout and reorder may be void + // after the first time the text has been laid out. + // Fill the vectors again. + const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); + numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs(); - if( 0u == numberOfGlyphs ) + if( 0u == lineBreakInfo.Count() ) { - numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs(); - lineBreakInfo.Resize( numberOfCharacters ); - wordBreakInfo.Resize( numberOfCharacters ); - glyphs.Resize( numberOfGlyphs ); - glyphsToCharactersMap.Resize( numberOfGlyphs ); - charactersPerGlyph.Resize( numberOfGlyphs ); - mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(), 0u, numberOfCharacters ); + } + if( 0u == wordBreakInfo.Count() ) + { + wordBreakInfo.Resize( numberOfCharacters ); mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(), 0u, numberOfCharacters ); + } + if( 0u == glyphs.Count() ) + { + glyphs.Resize( numberOfGlyphs ); mImpl->mVisualModel->GetGlyphs( glyphs.Begin(), 0u, numberOfGlyphs ); + } + if( 0u == glyphsToCharactersMap.Count() ) + { + glyphsToCharactersMap.Resize( numberOfGlyphs ); mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(), 0u, numberOfGlyphs ); + } + if( 0u == charactersPerGlyph.Count() ) + { + charactersPerGlyph.Resize( numberOfGlyphs ); mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(), 0u, numberOfGlyphs ); @@ -772,6 +938,76 @@ bool Controller::DoRelayout( const Vector2& size, if( viewUpdated ) { + // Reorder the lines + if( REORDER & operations ) + { + const Length numberOfBidiParagraphs = mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters ); + + if( 0u == bidirectionalInfo.Count() ) + { + bidirectionalInfo.Resize( numberOfBidiParagraphs ); + mImpl->mLogicalModel->GetBidirectionalInfo( bidirectionalInfo.Begin(), + 0u, + numberOfCharacters ); + } + + // Check first if there are paragraphs with bidirectional info. + if( 0u != bidirectionalInfo.Count() ) + { + // Get the lines + const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines(); + + // Reorder the lines. + Vector lineBidirectionalInfoRuns; + lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters. + ReorderLines( bidirectionalInfo, + lines, + lineBidirectionalInfoRuns ); + + // Set the bidirectional info into the model. + const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count(); + mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(), + numberOfBidirectionalInfoRuns ); + + // Set the bidirectional info per line into the layout parameters. + layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin(); + layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns; + + // Get the character to glyph conversion table and set into the layout. + Vector characterToGlyphMap; + characterToGlyphMap.Resize( numberOfCharacters ); + + layoutParameters.charactersToGlyphsBuffer = characterToGlyphMap.Begin(); + mImpl->mVisualModel->GetCharacterToGlyphMap( layoutParameters.charactersToGlyphsBuffer, + 0u, + numberOfCharacters ); + + // Get the glyphs per character table and set into the layout. + Vector glyphsPerCharacter; + glyphsPerCharacter.Resize( numberOfCharacters ); + + layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin(); + mImpl->mVisualModel->GetGlyphsPerCharacterMap( layoutParameters.glyphsPerCharacterBuffer, + 0u, + numberOfCharacters ); + + // Re-layout the text. Reorder those lines with right to left characters. + mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters, + glyphPositions ); + + // Free the allocated memory used to store the conversion table in the bidirectional line info run. + for( Vector::Iterator it = lineBidirectionalInfoRuns.Begin(), + endIt = lineBidirectionalInfoRuns.End(); + it != endIt; + ++it ) + { + BidirectionalLineInfoRun& bidiLineInfo = *it; + + free( bidiLineInfo.visualToLogicalMap ); + } + } + } + // Sets the positions into the model. if( UPDATE_POSITIONS & operations ) {