# Append list of test harness files (Won't get parsed for test cases)
LIST(APPEND TC_SOURCES
../dali-toolkit/dali-toolkit-test-utils/toolkit-accessibility-manager.cpp
- ../dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-application.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-imf-manager.cpp
DALI_TEST_EQUALS( characterLayoutInfo.mUnderlineThickness, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo.mUnderlinePosition, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_CHECK( !characterLayoutInfo.mGlyphActor );
- DALI_TEST_CHECK( characterLayoutInfo.mStyledText.mText.IsEmpty() );
DALI_TEST_EQUALS( characterLayoutInfo.mColorAlpha, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_CHECK( NULL == characterLayoutInfo.mGradientInfo );
DALI_TEST_CHECK( characterLayoutInfo.mIsVisible );
- DALI_TEST_CHECK( characterLayoutInfo.mSetText );
- DALI_TEST_CHECK( characterLayoutInfo.mSetStyle );
+ DALI_TEST_CHECK( !characterLayoutInfo.mSetText );
+ DALI_TEST_CHECK( !characterLayoutInfo.mSetStyle );
TextViewProcessor::WordLayoutInfo wordLayoutInfo;
DALI_TEST_EQUALS( wordLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
characterLayoutInfo.mUnderlinePosition = 1.f;
characterLayoutInfo.mGlyphActor = TextActor::New( "Hello" );
- characterLayoutInfo.mStyledText.mText = Text( "Hello" );
TextViewProcessor::GradientInfo* info = new TextViewProcessor::GradientInfo();
info->mGradientColor = Vector4( 1.f, 1.f, 1.f, 1.f );
DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_CHECK( characterLayoutInfo1.mGlyphActor );
- DALI_TEST_EQUALS( characterLayoutInfo1.mStyledText.mText.GetLength(), 5u, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo1.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_CHECK( characterLayoutInfo2.mGlyphActor );
- DALI_TEST_EQUALS( characterLayoutInfo2.mStyledText.mText.GetLength(), 5u, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo2.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
// Internal headers are allowed here
#include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
using namespace Dali;
using namespace Dali::Toolkit;
bool TestBeginsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location )
{
- // Creates a styled text with the markup or plain string.
- MarkupProcessor::StyledTextArray styledText;
- MarkupProcessor::GetStyledTextArray( input, styledText, true );
+ // Creates a text with the string.
+ Text text( input );
- const bool ret = ( result == TextProcessor::BeginsRightToLeftCharacter( styledText ) );
+ const bool ret = ( result == TextProcessor::BeginsRightToLeftCharacter( text ) );
if( !ret )
{
bool TestContainsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location )
{
- // Creates a styled text with the markup or plain string.
- MarkupProcessor::StyledTextArray styledText;
- MarkupProcessor::GetStyledTextArray( input, styledText, true );
+ // Creates a text with the string.
+ Text text( input );
- const bool ret = ( result == TextProcessor::ContainsRightToLeftCharacter( styledText ) );
+ const bool ret = ( result == TextProcessor::ContainsRightToLeftCharacter( text ) );
if( !ret )
{
MarkupProcessor::StyledTextArray styledText;
MarkupProcessor::GetStyledTextArray( test.inputText, styledText, true );
- std::vector<MarkupProcessor::StyledTextArray> paragraphs;
+ std::vector<Text> paragraphs;
+ std::vector< Vector<TextStyle*> > styles;
TextProcessor::SplitInParagraphs( styledText,
- paragraphs );
+ paragraphs,
+ styles );
if( paragraphs.size() != test.resultNumberOfParagraphs )
{
{
std::string inputText;
- std::size_t resultNumberOfWords;
+ std::size_t resultNumberOfSeparators;
};
bool TestSplitInWords( const SplitInWordsTest& test, const char* location )
{
- // Creates a styled text with the markup or plain string.
- MarkupProcessor::StyledTextArray styledText;
- MarkupProcessor::GetStyledTextArray( test.inputText, styledText, true );
+ // Creates a text with the string.
+ Text text( test.inputText );
- std::vector<MarkupProcessor::StyledTextArray> words;
+ Vector<std::size_t> positions;
- TextProcessor::SplitInWords( styledText,
- words );
+ TextProcessor::SplitInWords( text,
+ positions );
- if( words.size() != test.resultNumberOfWords )
+ if( positions.Count() != test.resultNumberOfSeparators )
{
tet_printf( "Fail. %s", location );
- tet_printf( "Different number of words, result %d, expected result %d", words.size(), test.resultNumberOfWords );
+ tet_printf( "Different number of separators, result %d, expected result %d", positions.Count(), test.resultNumberOfSeparators );
return false;
}
{
{
std::string( "Hello world, hello word!" ),
- 7
+ 3u
},
+ {
+ std::string( "Hello world\n" ),
+ 2u
+ }
};
- const std::size_t numberOfTests( 1 );
+ const std::size_t numberOfTests( 2u );
for( std::size_t index = 0; index < numberOfTests; ++index )
{
// Creaqte indices.
TextViewProcessor::TextInfoIndices indices( 0u, test.wordIndex, test.characterIndex );
+ indices.mCharacterParagraphIndex = test.characterParagraphIndex;
// Get the input paragraph.
TextViewProcessor::ParagraphLayoutInfo inputParagraphLayout;
std::string input;
std::size_t wordIndex;
std::size_t characterIndex;
+ std::size_t characterParagraphIndex;
float lineHeightOffset;
std::string firstResult;
std::string lastResult;
{
std::cout << "[" << textActor.GetText() << "]";
}
- else
- {
- std::cout << "{" << character.mStyledText.mText.GetText() << "}";
- }
}
void Print( const TextViewProcessor::WordLayoutInfo& word )
std::cout << "||" << std::endl;
}
-std::string GetText( const TextViewProcessor::CharacterLayoutInfo& character )
-{
- return character.mStyledText.mText.GetText();
-}
-
-std::string GetText( const TextViewProcessor::WordLayoutInfo& word )
+std::string GetText( const TextViewProcessor::WordLayoutInfo& word, const Text& paragraphText )
{
- std::string text;
+ Text text;
- for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator it = word.mCharactersLayoutInfo.begin(), endIt = word.mCharactersLayoutInfo.end(); it != endIt; ++it )
- {
- text += GetText( *it );
- }
+ paragraphText.GetSubText( word.mFirstCharacter, word.mFirstCharacter + word.mCharactersLayoutInfo.size() - 1u, text );
- return text;
+ return text.GetText();
}
std::string GetText( const TextViewProcessor::ParagraphLayoutInfo& paragraph )
for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it = paragraph.mWordsLayoutInfo.begin(), endIt = paragraph.mWordsLayoutInfo.end(); it != endIt; ++it )
{
- text += GetText( *it );
+ text += GetText( *it, paragraph.mText );
}
return text;
return false;
}
- text1 = character1.mStyledText.mText.GetText();
- style1 = character1.mStyledText.mStyle;
-
- text2 = character2.mStyledText.mText.GetText();
- style2 = character2.mStyledText.mStyle;
-
- if( text1 != text2 )
- {
- return false;
- }
-
- if( style1 != style2 )
- {
- std::cout << " style1 : " << std::endl;
- TextViewProcessor::dbgPrint( style1 );
-
- std::cout << " style2 : " << std::endl;
- TextViewProcessor::dbgPrint( style2 );
- return false;
- }
-
return true;
}
* @param input The input word.
* @param wordIndex Index to the word within the paragraph where to split it.
* @param characterIndex Where to split the word.
+ * @param characterIndex Character index within the paragraph.
* @param lineHeightOffset Offset between lines.
* @param firstResult First part of the split paragraph.
* @param lastResult Last part of the split paragraph.
const std::string& input,
size_t wordIndex,
size_t characterIndex,
+ size_t characterParagraphIndex,
float lineHeightOffset,
const std::string& firstResult,
const std::string& lastResult,
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
relayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
firstRelayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..."),
true ),
lastRelayoutData );
TextViewProcessor::ParagraphLayoutInfo lastParagraphLayoutInfo;
TextViewProcessor::TextInfoIndices indices( 0, wordIndex, characterIndex );
+ indices.mCharacterParagraphIndex = characterParagraphIndex;
SplitParagraph( indices,
PointSize( lineHeightOffset ),
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
firstRelayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
lastRelayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
resultRelayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
relayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
resultRelayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
relayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true ),
resultRelayoutData );
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Center,
PointSize( lineHeightOffset ),
- std::string( "..." ),
true );
switch( operation )
layoutInfo12.mBearing = BEARING_12;
layoutInfo12.mAscender = ASCENDER_12;
- TextStyle style10;
- style10.SetFontName( "" );
- style10.SetFontPointSize( PointSize( 10.f ) );
- TextStyle style12;
- style12.SetFontName( "" );
-
- layoutInfo12.mStyledText.mStyle = style12;
- layoutInfo10.mStyledText.mStyle = style10;
-
// Words
TextViewProcessor::WordLayoutInfo wordLayout1, wordLayout2, wordLayout3, wordLayout4;
wordLayout1.mAscender = ASCENDER_12;
wordLayout1.mType = TextViewProcessor::NoSeparator;
- layoutInfo12.mStyledText.mText = Text( "H" );
wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // H
- layoutInfo12.mStyledText.mText = Text( "e" );
wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // e
- layoutInfo12.mStyledText.mText = Text( "l" );
wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
- layoutInfo10.mStyledText.mText = Text( "l" );
wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // l
- layoutInfo10.mStyledText.mText = Text( "o" );
wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
// (white space)
wordLayout2.mSize = Size( ADVANCE_10, HEIGHT_10 );
wordLayout2.mAscender = ASCENDER_10;
wordLayout2.mType = TextViewProcessor::WordSeparator;
- layoutInfo10.mStyledText.mText = Text( " " );
wordLayout2.mCharactersLayoutInfo.push_back( layoutInfo10 ); // (white space)
// world!
wordLayout3.mSize = Size( 2.f * ADVANCE_10 + 4.f * ADVANCE_12, HEIGHT_12 );
wordLayout3.mAscender = ASCENDER_12;
wordLayout3.mType = TextViewProcessor::NoSeparator;
- layoutInfo10.mStyledText.mText = Text( "w" );
wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // w
- layoutInfo10.mStyledText.mText = Text( "o" );
wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
- layoutInfo12.mStyledText.mText = Text( "r" );
wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // r
- layoutInfo12.mStyledText.mText = Text( "l" );
wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
- layoutInfo12.mStyledText.mText = Text( "d" );
wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // d
- layoutInfo12.mStyledText.mText = Text( "!" );
wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // !
// (new paragraph character)
wordLayout4.mSize = Size( 0.f, HEIGHT_12 );
wordLayout4.mAscender = ASCENDER_12;
wordLayout4.mType = TextViewProcessor::ParagraphSeparator;
- layoutInfo12.mStyledText.mText = Text( "\n" );
layoutInfo12.mSize.width = 0.f;
wordLayout4.mCharactersLayoutInfo.push_back( layoutInfo12 ); // (new paragraph char)
std::string( "Hello <font size='30'>w</font>orl<font size='10'>dhello</font> world" )
},
// * Remove RTL text within LTR
- /* TODO check this when RTL text is working
{
std::string( "Remove within the same paragraph, RTL text within LTR." ),
Remove,
0.f,
std::string( "Hello worlello world" )
},
- */
// * Remove whole paragraph
{
std::string( "Remove whole paragraph" ),
std::string( "Touch <b>me\nhello\n</b>world" )
},
};
- const std::size_t numberOfTests( 21u );
+ const std::size_t numberOfTests( 22u );
for( std::size_t index = 0u; index < numberOfTests; ++index )
{
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
0,
0,
+ 0,
3.f,
std::string( "" ),
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
10,
4,
+ 36,
0.f,
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
std::string( "" ),
std::string("<font size='10'>Hello </font>wor<font size='12'>ld, hello wo</font>rld"),
2,
4,
+ 10,
0.f,
std::string("<font size='10'>Hello </font>wor<font size='12'>l</font>"),
std::string("<font size='12'>d, hello wo</font>rld")
- }
- /* TODO RTL
+ },
{
std::string( "Split paragraph, wordPosition 6, position 0." ),
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
6,
0,
+ 21,
0.f,
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום " ),
std::string( "עולם text text" ),
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
4,
0,
+ 17,
0.f,
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> " ),
std::string( "שלום עולם text text" ),
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
8,
0,
+ 27,
6.f,
std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם " ),
std::string( "text text" ),
},
- */
};
- const std::size_t numberOfTests( 3u );
+ const std::size_t numberOfTests( 6u );
for( std::size_t index = 0u; index < numberOfTests; ++index )
{
test.input,
test.wordIndex,
test.characterIndex,
+ test.characterParagraphIndex,
test.lineHeightOffset,
test.firstResult,
test.lastResult,
0.f,
std::string( "Hello world, this is a whole paragraph" )
},
- /* TODO RTL
{
std::string( "Merge paragraphs: last starting with RTL text and first ending with RTL" ),
std::string( "Hello world, שלום" ),
3.f,
std::string( "Hello world, שלום עולם, hello world." )
},
- */
{
std::string( "Merge paragraphs. Don't merge words" ),
std::string( "Hello world," ),
std::string( "Hello world, this is a whole paragraph" )
},
};
- const std::size_t numberOfTests( 4u );
+ const std::size_t numberOfTests( 6u );
for( std::size_t index = 0u; index < numberOfTests; ++index )
{
# Append list of test harness files (Won't get parsed for test cases)
LIST(APPEND TC_SOURCES
../dali-toolkit/dali-toolkit-test-utils/toolkit-accessibility-manager.cpp
- ../dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-application.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-imf-manager.cpp
# Append list of test harness files (Won't get parsed for test cases)
LIST(APPEND TC_SOURCES
dali-toolkit-test-utils/toolkit-accessibility-manager.cpp
- dali-toolkit-test-utils/toolkit-adaptor.cpp
dali-toolkit-test-utils/toolkit-application.cpp
dali-toolkit-test-utils/toolkit-clipboard.cpp
dali-toolkit-test-utils/toolkit-imf-manager.cpp
inline void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
+ mScissorParams.x = x;
+ mScissorParams.y = y;
+ mScissorParams.width = width;
+ mScissorParams.height = height;
}
inline void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
ATTRIB_TYPE_LAST
};
+ struct ScissorParams
+ {
+ GLint x;
+ GLint y;
+ GLsizei width;
+ GLsizei height;
+
+ ScissorParams() : x( 0 ), y( 0 ), width( 0 ), height( 0 ) { }
+ };
+
+ // Methods to check scissor tests
+ inline const ScissorParams& GetScissorParams() const { return mScissorParams; }
private:
GLuint mCurrentProgram;
mVertexAttribArrayState[ index ] = state;
mVertexAttribArrayChanged = true;
}
+
+ ScissorParams mScissorParams;
};
template <>
+++ /dev/null
-/*
- * Copyright (c) 2014 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.
- *
- */
-
-#define __DALI_ADAPTOR_H__
-#define __DALI_ACCESSIBILITY_MANAGER_H__
-#define __DALI_TIMER_H__
-#define __DALI_CLIPBOARD_H__
-#define __DALI_IMF_MANAGER_H__
-
-#include "toolkit-adaptor.h"
-#include <map>
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/signals/dali-signal-v2.h>
-
-namespace Dali
-{
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-class TestRenderSurface : public RenderSurface
-{
-public:
- TestRenderSurface(){}
- virtual ~TestRenderSurface(){}
- virtual SurfaceType GetType() { return RenderSurface::WINDOW; }
- virtual Dali::Any GetSurface() { return Dali::Any(); }
- virtual Dali::Any GetDisplay() { return Dali::Any(); }
- virtual PositionSize GetPositionSize() const { return PositionSize(0, 0, 640, 480);}
-};
-
-typedef Dali::Rect<int> PositionSize;
-
-/**
- * Stub for the Adaptor
- */
-class Adaptor
-{
-public:
-
- typedef SignalV2< void ( Adaptor& ) > AdaptorSignalV2;
-
-public:
-
- Adaptor(ToolkitAdaptor& toolkitAdaptor);
- ~Adaptor();
-
-public:
-
- void Start();
- void Pause();
- void Resume();
- void Stop();
- bool AddIdle(boost::function<void(void)> callBack);
- void FeedEvent(TouchPoint& point, int timeStamp);
- bool MoveResize(const PositionSize& positionSize);
- void SurfaceResized(const PositionSize& positionSize);
- void ReplaceSurface(RenderSurface& surface);
- void RenderSync();
- RenderSurface& GetSurface();
-
-public: // static methods
- static Adaptor& Get();
- static bool IsAvailable();
-
-public: // Signals
-
- AdaptorSignalV2& SignalResize();
-
- void EmitSignalResize()
- {
- mResizeSignal.Emit( *this );
- }
-
-private:
-
- // Undefined
- Adaptor(const Adaptor&);
- Adaptor& operator=(Adaptor&);
-
- AdaptorSignalV2 mResizeSignal;
- TestRenderSurface mRenderSurface;
- ToolkitAdaptor& mToolkitAdaptor;
-};
-
-namespace
-{
-Adaptor* gAdaptor = NULL;
-
-}
-
-Adaptor::Adaptor(ToolkitAdaptor& toolkitAdaptor)
-: mToolkitAdaptor(toolkitAdaptor)
-{
-}
-
-Adaptor::~Adaptor()
-{
-
-}
-
-void Adaptor::Start()
-{
- mToolkitAdaptor.mFunctionsCalled.Start = true;
-}
-
-void Adaptor::Pause()
-{
- mToolkitAdaptor.mFunctionsCalled.Pause = true;
-}
-
-void Adaptor::Resume()
-{
- mToolkitAdaptor.mFunctionsCalled.Resume = true;
-}
-
-void Adaptor::Stop()
-{
- mToolkitAdaptor.mFunctionsCalled.Stop = true;
-}
-
-bool Adaptor::AddIdle(boost::function<void(void)> callBack)
-{
- mToolkitAdaptor.mFunctionsCalled.AddIdle = true;
- mToolkitAdaptor.mLastIdleAdded = callBack;
- return true;
-}
-
-void Adaptor::FeedEvent(TouchPoint& point, int timeStamp)
-{
- mToolkitAdaptor.mFunctionsCalled.FeedEvent = true;
- mToolkitAdaptor.mLastTouchPointFed = point;
- mToolkitAdaptor.mLastTimeStampFed = timeStamp;
-}
-
-bool Adaptor::MoveResize(const PositionSize& positionSize)
-{
- mToolkitAdaptor.mFunctionsCalled.MoveResize = true;
- mToolkitAdaptor.mLastSizeSet = positionSize;
- return true;
-}
-
-void Adaptor::SurfaceResized(const PositionSize& positionSize)
-{
- mToolkitAdaptor.mFunctionsCalled.SurfaceResized = true;
- mToolkitAdaptor.mLastSizeSet = positionSize;
-}
-
-void Adaptor::ReplaceSurface(RenderSurface& surface)
-{
- mToolkitAdaptor.mFunctionsCalled.ReplaceSurface = true;
-}
-
-void Adaptor::RenderSync()
-{
- mToolkitAdaptor.mFunctionsCalled.RenderSync = true;
-}
-
-RenderSurface& Adaptor::GetSurface()
-{
- mToolkitAdaptor.mFunctionsCalled.GetSurface = true;
- return mRenderSurface;
-}
-
-Adaptor& Adaptor::Get()
-{
- DALI_ASSERT_ALWAYS(gAdaptor);
- gAdaptor->mToolkitAdaptor.mFunctionsCalled.Get = true;
- return *gAdaptor;
-}
-
-bool Adaptor::IsAvailable()
-{
- bool available(false);
-
- if (gAdaptor)
- {
- gAdaptor->mToolkitAdaptor.mFunctionsCalled.IsAvailable = true;
- available = true;
- }
-
- return available;
-}
-
-Adaptor::AdaptorSignalV2& Adaptor::SignalResize()
-{
- mToolkitAdaptor.mFunctionsCalled.SignalResize = true;
- return mResizeSignal;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-ToolkitAdaptor::ToolkitAdaptor()
-: mLastTouchPointFed(0, TouchPoint::Down, 0.0f, 0.0f),
- mLastTimeStampFed(0),
- mStyleMonitor(StyleMonitor::Get()),
- mAccessibilityManager(AccessibilityManager::Get()),
- mImfManager(ImfManager::Get()),
- mAdaptorStub(new Adaptor(*this))
-{
- gAdaptor = mAdaptorStub;
-}
-
-ToolkitAdaptor::~ToolkitAdaptor()
-{
- delete mAdaptorStub;
- gAdaptor = NULL;
-}
-
-void ToolkitAdaptor::EmitSignalResize()
-{
- mAdaptorStub->EmitSignalResize();
-}
-
-} // namespace Dali
+++ /dev/null
-#ifndef __DALI_TOOLKIT_TOOLKIT_ADAPTOR_H__
-#define __DALI_TOOLKIT_TOOLKIT_ADAPTOR_H__
-
-/*
- * Copyright (c) 2014 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.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <boost/function.hpp>
-
-// INTERNAL INCLUDES
-#include "toolkit-style-monitor.h"
-#include "toolkit-accessibility-manager.h"
-#include "toolkit-timer.h"
-#include "toolkit-imf-manager.h"
-#include "toolkit-clipboard-event-notifier.h"
-
-#include <dali/public-api/events/touch-point.h>
-#include <dali/public-api/math/rect.h>
-
-namespace Dali
-{
-
-class Adaptor;
-
-typedef Dali::Rect<int> PositionSize;
-
-/**
- * This creates a stubbed Adaptor so that internal Toolkit Adaptor calls work.
- * Furthermore, it provides an interface to see if certain methods were invoked.
- */
-class ToolkitAdaptor
-{
-public: // Construction & Destruction
-
- ToolkitAdaptor();
- ~ToolkitAdaptor();
-
-public: // Getters
-
- boost::function<void(void)> GetLastIdleAdded() const
- {
- return mLastIdleAdded;
- }
-
- TouchPoint GetLastTouchPointFed() const
- {
- return mLastTouchPointFed;
- }
-
- int GetLastTimeStampFed() const
- {
- return mLastTimeStampFed;
- }
-
- PositionSize GetLastSizeSet() const
- {
- return mLastSizeSet;
- }
-
- StyleMonitor& GetToolkitStyleMonitor()
- {
- return mStyleMonitor;
- }
-
- AccessibilityManager& GetAccessibilityManager()
- {
- return mAccessibilityManager;
- }
-
- ToolkitClipboardEventNotifier& GetClipboardEventNotifier()
- {
- return mClipboardEventNotifier;
- }
-
-public: // Signal Emissions
-
- void EmitSignalResize();
-
-public: // TEST FUNCTIONS
-
- // Enumeration of Adaptor methods
- enum TestFuncEnum
- {
- StartType,
- PauseType,
- ResumeType,
- StopType,
- AddIdleType,
- FeedEventType,
- MoveResizeType,
- SurfaceResizedType,
- ReplaceSurfaceType,
- RenderSyncType,
- GetSurfaceType,
- GetType,
- IsAvailableType,
- RegisterSingletonType,
- GetSingletonType,
- SignalResizeType,
- };
-
- void Reset()
- {
- mFunctionsCalled.Reset();
- }
-
- bool WasCalled(TestFuncEnum func)
- {
- switch(func)
- {
- case StartType: return mFunctionsCalled.Start;
- case PauseType: return mFunctionsCalled.Pause;
- case ResumeType: return mFunctionsCalled.Resume;
- case StopType: return mFunctionsCalled.Stop;
- case AddIdleType: return mFunctionsCalled.AddIdle;
- case FeedEventType: return mFunctionsCalled.FeedEvent;
- case MoveResizeType: return mFunctionsCalled.MoveResize;
- case SurfaceResizedType: return mFunctionsCalled.SurfaceResized;
- case ReplaceSurfaceType: return mFunctionsCalled.ReplaceSurface;
- case RenderSyncType: return mFunctionsCalled.RenderSync;
- case GetSurfaceType: return mFunctionsCalled.GetSurface;
- case GetType: return mFunctionsCalled.Get;
- case IsAvailableType: return mFunctionsCalled.IsAvailable;
- case RegisterSingletonType: return mFunctionsCalled.RegisterSingleton;
- case GetSingletonType: return mFunctionsCalled.GetSingleton;
- case SignalResizeType: return mFunctionsCalled.SignalResize;
- }
- return false;
- }
-
- void ResetCallStatistics(TestFuncEnum func)
- {
- switch(func)
- {
- case StartType: mFunctionsCalled.Start = false; break;
- case PauseType: mFunctionsCalled.Pause = false; break;
- case ResumeType: mFunctionsCalled.Resume = false; break;
- case StopType: mFunctionsCalled.Stop = false; break;
- case AddIdleType: mFunctionsCalled.AddIdle = false; break;
- case FeedEventType: mFunctionsCalled.FeedEvent = false; break;
- case MoveResizeType: mFunctionsCalled.MoveResize = false; break;
- case SurfaceResizedType: mFunctionsCalled.SurfaceResized = false; break;
- case ReplaceSurfaceType: mFunctionsCalled.ReplaceSurface = false; break;
- case RenderSyncType: mFunctionsCalled.RenderSync = false; break;
- case GetSurfaceType: mFunctionsCalled.GetSurface = false; break;
- case GetType: mFunctionsCalled.Get = false; break;
- case IsAvailableType: mFunctionsCalled.IsAvailable = false; break;
- case RegisterSingletonType: mFunctionsCalled.RegisterSingleton = false; break;
- case GetSingletonType: mFunctionsCalled.GetSingleton = false; break;
- case SignalResizeType: mFunctionsCalled.SignalResize = false; break;
- }
- }
-
-private:
-
- struct TestFunctions
- {
- TestFunctions()
- : Start(false),
- Pause(false),
- Resume(false),
- Stop(false),
- AddIdle(false),
- FeedEvent(false),
- MoveResize(false),
- SurfaceResized(false),
- ReplaceSurface(false),
- RenderSync(false),
- GetSurface(false),
- Get(false),
- IsAvailable(false),
- RegisterSingleton(false),
- GetSingleton(false),
- SignalResize(false)
- {
- }
-
- void Reset()
- {
- Start = false;
- Pause = false;
- Resume = false;
- Stop = false;
- AddIdle = false;
- FeedEvent = false;
- MoveResize = false;
- SurfaceResized = false;
- ReplaceSurface = false;
- RenderSync = false;
- GetSurface = false;
- Get = false;
- IsAvailable = false;
- RegisterSingleton = false;
- GetSingleton = false;
- SignalResize = false;
- }
-
- bool Start;
- bool Pause;
- bool Resume;
- bool Stop;
- bool AddIdle;
- bool FeedEvent;
- bool MoveResize;
- bool SurfaceResized;
- bool ReplaceSurface;
- bool RenderSync;
- bool GetSurface;
- bool Get;
- bool IsAvailable;
- bool RegisterSingleton;
- bool GetSingleton;
- bool SignalResize;
- };
-
- TestFunctions mFunctionsCalled;
-
- // Last set information
- boost::function<void(void)> mLastIdleAdded;
- TouchPoint mLastTouchPointFed;
- int mLastTimeStampFed;
- PositionSize mLastSizeSet;
-
- // Contains Test functions for the Style Monitor
- StyleMonitor mStyleMonitor;
-
- // Stub for AccessibilityManager
- AccessibilityManager mAccessibilityManager;
-
- // Stub for ClipboardEventNotifier
- ToolkitClipboardEventNotifier mClipboardEventNotifier;
-
- ImfManager mImfManager;
-
- // The Adaptor Stub
- Adaptor* mAdaptorStub;
- friend class Adaptor;
-};
-
-} // namespace Dali
-
-#endif // __DALI_TOOLKIT_TOOLKIT_ADAPTOR_H__
namespace Dali
{
-namespace
-{
-ToolkitClipboardEventNotifier* gToolkitClipboardEventNotifier(NULL);
-} // unnamed namespace
-
namespace Internal
{
namespace Adaptor
{
-/**
- * Stub for the ClipboardEventNotifier
- */
-class ClipboardEventNotifier : public BaseObject
+class ClipboardEventNotifier : public Dali::BaseObject
{
-public: // Creation & Destruction
+public:
+
+ typedef Dali::ClipboardEventNotifier::ClipboardEventSignalV2 ClipboardEventSignalV2;
+ // Creation
+ static Dali::ClipboardEventNotifier New();
static Dali::ClipboardEventNotifier Get();
+ // Public API
+ const std::string& GetContent() const;
+ void SetContent( const std::string& content );
+ void ClearContent();
+ void EmitContentSelectedSignal();
+
+ // Signals
+ ClipboardEventSignalV2& ContentSelectedSignal()
+ {
+ return mContentSelectedSignalV2;
+ }
+
+private:
+ // Construction & Destruction
ClipboardEventNotifier();
- ClipboardEventNotifier(ToolkitClipboardEventNotifier *clipboardEventNotifier);
- ~ClipboardEventNotifier();
+ virtual ~ClipboardEventNotifier();
+
+ // Undefined
+ ClipboardEventNotifier( const ClipboardEventNotifier& );
+ ClipboardEventNotifier& operator=( ClipboardEventNotifier& );
+
+private:
-public: // Signals
+ std::string mContent; ///< The current selected content.
+ ClipboardEventSignalV2 mContentSelectedSignalV2;
- Dali::ClipboardEventNotifier::ClipboardEventSignalV2& SignalContentSelected()
+ static Dali::ClipboardEventNotifier mToolkitClipboardEventNotifier;
+
+public:
+
+ // Helpers for public-api forwarding methods
+
+ inline static Internal::Adaptor::ClipboardEventNotifier& GetImplementation(Dali::ClipboardEventNotifier& detector)
{
- return mClipboardSignal;
+ DALI_ASSERT_ALWAYS( detector && "ClipboardEventNotifier handle is empty" );
+
+ BaseObject& handle = detector.GetBaseObject();
+
+ return static_cast<Internal::Adaptor::ClipboardEventNotifier&>(handle);
}
-private:
+ inline static const Internal::Adaptor::ClipboardEventNotifier& GetImplementation(const Dali::ClipboardEventNotifier& detector)
+ {
+ DALI_ASSERT_ALWAYS( detector && "ClipboardEventNotifier handle is empty" );
+
+ const BaseObject& handle = detector.GetBaseObject();
- ToolkitClipboardEventNotifier* mToolkitClipboardEventNotifier;
- Dali::ClipboardEventNotifier::ClipboardEventSignalV2 mClipboardSignal;
+ return static_cast<const Internal::Adaptor::ClipboardEventNotifier&>(handle);
+ }
};
+Dali::ClipboardEventNotifier ClipboardEventNotifier::mToolkitClipboardEventNotifier;
+
+Dali::ClipboardEventNotifier ClipboardEventNotifier::New()
+{
+ return Get();
+}
+
Dali::ClipboardEventNotifier ClipboardEventNotifier::Get()
{
- return gToolkitClipboardEventNotifier->GetClipboardEventNotifier();
+ if ( !mToolkitClipboardEventNotifier )
+ {
+ mToolkitClipboardEventNotifier = Dali::ClipboardEventNotifier( new ClipboardEventNotifier );
+ }
+ return mToolkitClipboardEventNotifier;
}
-ClipboardEventNotifier::ClipboardEventNotifier()
-: mToolkitClipboardEventNotifier(NULL)
+const std::string& ClipboardEventNotifier::GetContent() const
+{
+ return mContent;
+}
+
+void ClipboardEventNotifier::SetContent( const std::string& content )
{
+ mContent = content;
}
-ClipboardEventNotifier::ClipboardEventNotifier(ToolkitClipboardEventNotifier *clipboardEventNotifier)
-: mToolkitClipboardEventNotifier(clipboardEventNotifier)
+void ClipboardEventNotifier::ClearContent()
+{
+ mContent.clear();
+}
+
+void ClipboardEventNotifier::EmitContentSelectedSignal()
+{
+ if ( !mContentSelectedSignalV2.Empty() )
+ {
+ Dali::ClipboardEventNotifier handle( this );
+ mContentSelectedSignalV2.Emit( handle );
+ }
+}
+
+ClipboardEventNotifier::ClipboardEventNotifier()
+: mContent()
{
}
}
} // namespace Adaptor
-
} // namespace Internal
////////////////////////////////////////////////////////////////////////////////////////////////////
-ToolkitClipboardEventNotifier::ToolkitClipboardEventNotifier()
-: mClipboardEventNotifierStub(new Internal::Adaptor::ClipboardEventNotifier(this)),
- mClipboardEventNotifier( mClipboardEventNotifierStub )
+const char* const ClipboardEventNotifier::SIGNAL_CONTENT_SELECTED( "content-selected" );
+
+ClipboardEventNotifier::ClipboardEventNotifier()
+{
+}
+
+ClipboardEventNotifier ClipboardEventNotifier::Get()
+{
+ return Internal::Adaptor::ClipboardEventNotifier::Get();
+}
+
+ClipboardEventNotifier::~ClipboardEventNotifier()
+{
+}
+
+const std::string& ClipboardEventNotifier::GetContent() const
+{
+ return Internal::Adaptor::ClipboardEventNotifier::GetImplementation(*this).GetContent();
+}
+
+void ClipboardEventNotifier::SetContent( const std::string& content )
+{
+ Internal::Adaptor::ClipboardEventNotifier::GetImplementation(*this).SetContent(content);
+}
+
+void ClipboardEventNotifier::ClearContent()
+{
+ Internal::Adaptor::ClipboardEventNotifier::GetImplementation(*this).ClearContent();
+}
+
+void ClipboardEventNotifier::EmitContentSelectedSignal()
{
- gToolkitClipboardEventNotifier = this;
+ Internal::Adaptor::ClipboardEventNotifier::GetImplementation(*this).EmitContentSelectedSignal();
}
-ToolkitClipboardEventNotifier::~ToolkitClipboardEventNotifier()
+ClipboardEventNotifier::ClipboardEventSignalV2& ClipboardEventNotifier::ContentSelectedSignal()
{
- gToolkitClipboardEventNotifier = NULL;
+ return Internal::Adaptor::ClipboardEventNotifier::GetImplementation(*this).ContentSelectedSignal();
}
-ClipboardEventNotifier ToolkitClipboardEventNotifier::GetClipboardEventNotifier()
+ClipboardEventNotifier::ClipboardEventNotifier( Internal::Adaptor::ClipboardEventNotifier* notifier )
+: BaseHandle( notifier )
{
- return mClipboardEventNotifier;
}
} // namespace Dali
#include <string>
// PUBLIC INCLUDES
-#include <dali/public-api/adaptor-framework/clipboard-event-notifier.h>
+#define __DALI_CLIPBOARD_EVENT_NOTIFIER_H__
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/signals/dali-signal-v2.h>
+
namespace Dali
{
}
}
-/**
- * This creates a stubbed ClipboardEventNotifier so that internal Toolkit Adaptor calls work.
- */
-class ToolkitClipboardEventNotifier
+class ClipboardEventNotifier : public BaseHandle
{
-public: // Constants
-
-public: // Construction & Destruction
-
- ToolkitClipboardEventNotifier();
- ~ToolkitClipboardEventNotifier();
-
-public: // Getters
-
- ClipboardEventNotifier GetClipboardEventNotifier();
-
-public: // Signal Emissions
+public:
+ typedef SignalV2< void ( ClipboardEventNotifier& ) > ClipboardEventSignalV2;
+ static const char* const SIGNAL_CONTENT_SELECTED; ///< name "content-selected"
- ClipboardEventNotifier::ClipboardEventSignalV2& SignalContentSelected();
+ ClipboardEventNotifier();
+ static ClipboardEventNotifier Get();
+ ~ClipboardEventNotifier();
-public: // TEST FUNCTIONS
+ const std::string& GetContent() const;
+ void SetContent( const std::string& content );
+ void ClearContent();
-private:
+ void EmitContentSelectedSignal();
+ ClipboardEventSignalV2& ContentSelectedSignal();
- Internal::Adaptor::ClipboardEventNotifier* mClipboardEventNotifierStub;
- friend class Internal::Adaptor::ClipboardEventNotifier;
- ClipboardEventNotifier mClipboardEventNotifier; // Hold a handle ourselves.
+ ClipboardEventNotifier( Internal::Adaptor::ClipboardEventNotifier* notifier );
};
} // namespace Dali
// INTERNAL INCLUDES
#include <dali-test-suite-utils.h>
-#include "toolkit-adaptor.h"
#include "toolkit-orientation.h"
namespace Dali
mCore = NULL;
}
- inline ToolkitAdaptor& GetAdaptor()
- {
- return mAdaptor;
- }
-
//ToolkitOrientation& GetOrientation()
//{
//return mOrientation;
//}
private:
- ToolkitAdaptor mAdaptor;
//ToolkitOrientation mOrientation;
};
// Need to override adaptor classes for toolkit test harness, so include
// test harness headers before dali headers.
#include <dali-toolkit-test-suite-utils.h>
+#include "toolkit-style-monitor.h"
#include <dali.h>
#include <dali-toolkit/dali-toolkit.h>
DALI_TEST_EQUALS( dummyImpl.fontChangeCalled, false, TEST_LOCATION );
StyleChange styleChange;
styleChange.defaultFontChange = true;
- Dali::StyleMonitor styleMonitor = application.GetAdaptor().GetToolkitStyleMonitor();
+ Dali::StyleMonitor styleMonitor = StyleMonitor::Get();
styleMonitor.EmitStyleChangeSignal(styleChange);
DALI_TEST_EQUALS( dummyImpl.fontChangeCalled, true, TEST_LOCATION );
return ss.str();
}
+#if defined(DEBUG_ENABLED)
std::string PropertyValueToString( const Property::Value& value )
{
return ret;
}
+#endif // DEBUG_ENABLED
/*
* Recursively collects all stylesin a node (An array of style names).
}
else
{
- DALI_SCRIPT_WARNING("No styles section to create style '%s'\n", styleName.c_str());
return false;
}
}
// Do nothing.
}
-void Button::OnStageDisconnection()
+void Button::OnControlStageDisconnection()
{
- if( ButtonUp != mState )
- {
- OnTouchPointLeave(); // Notification for derived classes.
- mState = ButtonUp;
- }
+ OnButtonStageDisconnection(); // Notification for derived classes.
+ mState = ButtonUp;
}
void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
*/
virtual float OnAnimationTimeRequested() const;
+ /**
+ * This method is called when the button is removed from the stage.
+ * Could be reimplemented in subclasses to provide specific behaviour.
+ */
+ virtual void OnButtonStageDisconnection() { }
+
public:
/**
*/
virtual void OnControlSizeSet( const Vector3& targetSize );
+ /**
+ * Callback received when the button is disconnected from the stage.
+ * It resets the button status.
+ */
+ void OnControlStageDisconnection();
+
private:
/**
private:
- /**
- * Callback received when the button is disconected from the stage.
- * It resets the button status.
- */
- void OnStageDisconnection();
-
-private:
-
// Undefined
Button( const Button& );
return GetPushButtonPainter( mPainter )->GetAnimationTime();
}
+void PushButton::OnButtonStageDisconnection()
+{
+ if( ButtonDown == mState )
+ {
+ if( !mToggleButton )
+ {
+ Toolkit::PushButton handle( GetOwner() );
+
+ // Notifies the painter the button has been released.
+ GetPushButtonPainter( mPainter )->Released( handle );
+
+ if( mAutoRepeating )
+ {
+ mAutoRepeatingTimer.Reset();
+ }
+ }
+ }
+}
+
PushButton::PushButton()
: Button(),
mAutoRepeating( false ),
*/
virtual float OnAnimationTimeRequested() const;
+ /**
+ * This method is called when the button is removed from the stage.
+ */
+ virtual void OnButtonStageDisconnection();
+
protected: // From Control
/**
SelectionFinished ///< Finished selected section
};
-/**
- * Whether the given style is the default style or not.
- * @param[in] style The given style.
- * @return \e true if the given style is the default. Otherwise it returns \e false.
- */
-bool IsDefaultStyle( const TextStyle& style )
-{
- return DEFAULT_TEXT_STYLE == style;
-}
-
-/**
- * Whether the given styled text is using the default style or not.
- * @param[in] textArray The given text.
- * @return \e true if the given styled text is using the default style. Otherwise it returns \e false.
- */
-bool IsTextDefaultStyle( const Toolkit::MarkupProcessor::StyledTextArray& textArray )
-{
- for( Toolkit::MarkupProcessor::StyledTextArray::const_iterator it = textArray.begin(), endIt = textArray.end(); it != endIt; ++it )
- {
- const TextStyle& style( (*it).mStyle );
-
- if( !IsDefaultStyle( style ) )
- {
- return false;
- }
- }
-
- return true;
-}
-
std::size_t FindVisibleCharacterLeft( std::size_t cursorPosition, const Toolkit::TextView::CharacterLayoutInfoContainer& characterLayoutInfoTable )
{
for( Toolkit::TextView::CharacterLayoutInfoContainer::const_reverse_iterator it = characterLayoutInfoTable.rbegin() + characterLayoutInfoTable.size() - cursorPosition, endIt = characterLayoutInfoTable.rend();
TextInputPtr textInput(new TextInput());
// Pass ownership to CustomActor via derived handle
Dali::Toolkit::TextInput handle(*textInput);
+ handle.SetName( "TextInput");
textInput->Initialize();
-
return handle;
}
mClipboard = Clipboard::Get(); // Store handle to clipboard
// Now in edit mode we can accept string to paste from clipboard
- if( Adaptor::IsAvailable() )
+ ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
+ if ( notifier )
{
- ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
- if ( notifier )
- {
- notifier.ContentSelectedSignal().Connect( this, &TextInput::OnClipboardTextSelected );
- }
+ notifier.ContentSelectedSignal().Connect( this, &TextInput::OnClipboardTextSelected );
}
}
mClipboard.Reset();
// No longer in edit mode so do not want to receive string from clipboard
- if( Adaptor::IsAvailable() )
+ ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
+ if ( notifier )
{
- ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
- if ( notifier )
- {
- notifier.ContentSelectedSignal().Disconnect( this, &TextInput::OnClipboardTextSelected );
- }
- Clipboard clipboard = Clipboard::Get();
+ notifier.ContentSelectedSignal().Disconnect( this, &TextInput::OnClipboardTextSelected );
+ }
- if ( clipboard )
- {
- clipboard.HideClipboard();
- }
+ Clipboard clipboard = Clipboard::Get();
+ if ( clipboard )
+ {
+ clipboard.HideClipboard();
}
}
{
Actor self = Self();
mActiveLayer = Layer::New();
+ mActiveLayer.SetName ( "ActiveLayerActor" );
mActiveLayer.SetAnchorPoint( AnchorPoint::CENTER);
mActiveLayer.SetParentOrigin( ParentOrigin::CENTER);
mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition();
ReturnClosestIndex( tap.localPoint, mCursorPosition );
+ std::size_t start = 0;
+ std::size_t end = 0;
+ Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end );
+
+ mCursorPosition = end; // Ensure cursor is positioned at end of selected word
+
ImfManager imfManager = ImfManager::Get();
if ( imfManager )
{
imfManager.NotifyCursorPosition();
}
- std::size_t start = 0;
- std::size_t end = 0;
- Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end );
-
- SelectText( start, end );
+ if ( !mStyledText.at(end-1).mText[0].IsWhiteSpace() )
+ {
+ SelectText( start, end );
+ ShowPopupCutCopyPaste();
+ }
+ else
+ {
+ RemoveHighlight( false ); // Remove highlight but do not auto hide popup
+ HidePopup( false ); // Hide popup with setting to do auto show.
+ SetUpPopupSelection( false ); // Set to false so if nearest word is whitespace it will not show cut button.
+ ShowPopup();
+ }
}
- // if no text but clipboard has content then show paste option
- if ( ( mClipboard && mClipboard.NumberOfItems() ) || !mStyledText.empty() )
+ else if ( mClipboard && mClipboard.NumberOfItems() )
{
ShowPopupCutCopyPaste();
}
{
// Set the initial cursor position in the tap point.
ReturnClosestIndex(tap.localPoint, mCursorPosition );
-
- // Create the grab handle.
- // TODO Make this a re-usable function.
- if ( IsGrabHandleEnabled() )
- {
- const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition);
-
- CreateGrabHandle();
-
- mActualGrabHandlePosition.x = cursorPosition.x; // Set grab handle to be at the cursor position
- mActualGrabHandlePosition.y = cursorPosition.y; // Set grab handle to be at the cursor position
- mGrabHandle.SetPosition( mActualGrabHandlePosition + UI_OFFSET );
- ShowGrabHandleAndSetVisibility( mIsGrabHandleInScrollArea );
-
- }
-
- // Edit mode started after grab handle created to ensure the signal InputStarted is sent last.
- // This is used to ensure if selecting text hides the grab handle then this code is run after grab handle is created,
- // otherwise the Grab handle will be shown when selecting.
-
StartEditMode();
}
}
}
}
+ // Edit mode started after grab handle created to ensure the signal InputStarted is sent last.
+ // This is used to ensure if selecting text hides the grab handle then this code is run after grab handle is created,
+ // otherwise the Grab handle will be shown when selecting.
if ( createGrabHandle && IsGrabHandleEnabled() )
{
const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition);
{
DALI_LOG_INFO( gLogFilter, Debug::General, "OnLongPress\n" );
+ // Ignore longpress if in selection mode already
+ if( mHighlightMeshActor )
+ {
+ return;
+ }
+
if(longPress.state == Dali::Gesture::Started)
{
// Start edit mode on long press
mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition();
ReturnClosestIndex( longPress.localPoint, mCursorPosition );
+ std::size_t start = 0;
+ std::size_t end = 0;
+ Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end );
+
+ mCursorPosition = end; // Ensure cursor is positioned at end of selected word
+
ImfManager imfManager = ImfManager::Get();
if ( imfManager )
{
imfManager.SetCursorPosition ( mCursorPosition );
imfManager.NotifyCursorPosition();
}
- std::size_t start = 0;
- std::size_t end = 0;
- Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end );
SelectText( start, end );
}
{
bool preEditFlagPreviouslySet( mPreEditFlag );
- if (mHighlightMeshActor)
- {
- // replaces highlighted text with new line
- DeleteHighlightedText( false );
- }
+ // replaces highlighted text with new line
+ DeleteHighlightedText( false );
+
mCursorPosition = mCursorPosition + InsertAt( Text( NEWLINE ), mCursorPosition, 0 );
// If we are in pre-edit mode then pressing enter will cause a commit. But the commit string does not include the
// Some text may be selected, hiding keyboard causes an empty keystring to be sent, we don't want to delete highlight in this case
if ( !keyString.empty() )
{
- if ( mHighlightMeshActor )
- {
- // replaces highlighted text with new character
- DeleteHighlightedText( false );
- }
-
+ // replaces highlighted text with new character
+ DeleteHighlightedText( false );
// Received key String
- mCursorPosition = mCursorPosition + InsertAt( Text( keyString ), mCursorPosition, 0 );
+ mCursorPosition += InsertAt( Text( keyString ), mCursorPosition, 0 );
update = true;
EmitTextModified();
}
void TextInput::CreateTextViewActor()
{
mDisplayedTextView = Toolkit::TextView::New();
+ mDisplayedTextView.SetName( "DisplayedTextView ");
mDisplayedTextView.SetMarkupProcessingEnabled( mMarkUpEnabled );
mDisplayedTextView.SetParentOrigin(ParentOrigin::TOP_LEFT);
mDisplayedTextView.SetAnchorPoint(AnchorPoint::TOP_LEFT);
{
DALI_LOG_INFO( gLogFilter, Debug::General, "DeleteHighlightedText handlePosOne[%u] handlePosTwo[%u]\n", mSelectionHandleOnePosition, mSelectionHandleTwoPosition);
- if(mHighlightMeshActor)
+ if( mHighlightMeshActor )
{
mCursorPosition = std::min( mSelectionHandleOnePosition, mSelectionHandleTwoPosition );
{
ImageActor cursor;
cursor = CreateSolidColorActor(color);
+ cursor.SetName( "Cursor" );
cursor.SetParentOrigin(ParentOrigin::TOP_LEFT);
- cursor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
+ cursor.SetAnchorPoint(AnchorPoint::BOTTOM_LEFT);
cursor.SetVisible(false);
return cursor;
{
// Get height of cursor and set its size
Size size( CURSOR_THICKNESS, 0.0f );
- if (!mTextLayoutInfo.mCharacterLayoutInfoTable.empty())
+ if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() )
{
size.height = GetRowRectFromCharacterPosition( GetVisualPosition( mCursorPosition ) ).height;
}
void TextInput::CreateGrabArea( Actor& parent )
{
mGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move
+ mGrabArea.SetName( "GrabArea" );
mGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
mGrabArea.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), RelativeToConstraint( DEFAULT_GRAB_HANDLE_RELATIVE_SIZE ) ) ); // grab area to be larger than text actor
mGrabArea.TouchedSignal().Connect(this,&TextInput::OnPressDown);
mTapDetector.Attach( mGrabArea );
mPanGestureDetector.Attach( mGrabArea );
+ mLongPressDetector.Attach( mGrabArea );
parent.Add(mGrabArea);
}
ShowPopup();
}
-void TextInput::SetUpPopupSelection()
+void TextInput::SetUpPopupSelection( bool showCutButton )
{
ClearPopup();
mPopupPanel.CreateOrderedListOfOptions(); // todo Move this so only run when order has changed
{
mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelectAll, true );
mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelect, true );
- mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, true );
+ mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, showCutButton );
}
// if clipboard has valid contents then offer paste option
if( mClipboard && mClipboard.NumberOfItems() )
// between RTL and LTR text...
if(characterPosition != mTextLayoutInfo.mCharacterLogicalToVisualMap.size())
{
- std::size_t visualCharacterAltPosition = mTextLayoutInfo.mCharacterLogicalToVisualMap[characterPosition] - 1;
+ std::size_t visualCharacterAltPosition = mTextLayoutInfo.mCharacterLogicalToVisualMap[characterPosition]; // VCC TODO: find why in the previous patch it was a -1 here.
DALI_ASSERT_ALWAYS(visualCharacterAltPosition < mTextLayoutInfo.mCharacterLayoutInfoTable.size());
const Toolkit::TextView::CharacterLayoutInfo& infoAlt = mTextLayoutInfo.mCharacterLayoutInfoTable[ visualCharacterAltPosition ];
// When replacing highlighted text keyboard should ignore current word at cursor hence notify keyboard that the cursor is at the start of the highlight.
mSelectingText = true;
- mCursorPosition = std::min( start, end ); // Set cursor position to start of highlighted text.
-
- ImfManager imfManager = ImfManager::Get();
- if ( imfManager )
- {
- imfManager.SetCursorPosition ( mCursorPosition );
- imfManager.SetSurroundingText( GetText() );
- imfManager.NotifyCursorPosition();
- }
- // As the imfManager has been notified of the new cursor position we do not need to reset the pre-edit as it will be updated instead.
+ std::size_t selectionStartPosition = std::min( start, end );
// Hide grab handle when selecting.
ShowGrabHandleAndSetVisibility( false );
UpdateHighlight();
const TextStyle oldInputStyle( mInputStyle );
- mInputStyle = GetStyleAt( mCursorPosition ); // Inherit style from selected position.
+ mInputStyle = GetStyleAt( selectionStartPosition ); // Inherit style from selected position.
if( oldInputStyle != mInputStyle )
{
}
// Removes highlight and resumes edit mode state
-void TextInput::RemoveHighlight()
+void TextInput::RemoveHighlight( bool hidePopup )
{
DALI_LOG_INFO(gLogFilter, Debug::General, "RemoveHighlight\n");
// NOTE: We cannot dereference mHighlightMesh, due
// to a bug in how the scene-graph MeshRenderer uses the Mesh data incorrectly.
- HidePopup();
+ if ( hidePopup )
+ {
+ HidePopup();
+ }
}
mSelectionHandleOnePosition = 0;
/**
* Setup the selection popup and clipboard if relevant so the correct options are shown when ShowPopup is called.
+ * @param[in] showCutButton Flag to show or hide cut button, in some cases like whitespace we do not want to cut just select.
+ * default is true.
*/
- void SetUpPopupSelection();
+ void SetUpPopupSelection( bool showCutButton = true );
/**
* Return the logical index containing the character position closest to the source.
/**
* Hide highlight shown between selection handles.
+ * @param[in] hidePopup flag to hide the popup too, default is to hide popup.
*/
- void RemoveHighlight();
+ void RemoveHighlight( bool hidePopup = true );
/**
* Highlights text that has been selected
* 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
+ * http://www.apache.org/license/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,
#include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
+#include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
#include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
+#include <dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h>
// EXTERNAL INCLUDES
#include <cmath>
Vector3 position;
Size size;
Vector4 color;
- TextViewProcessor::GradientInfo* gradientInfo;
+ TextViewProcessor::CharacterLayoutInfo* characterLayout;
};
void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo,
const float lineHeight )
{
currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color );
- if( NULL != currentTextActorInfo.gradientInfo )
+ if( ( NULL != currentTextActorInfo.characterLayout ) &&
+ ( NULL != currentTextActorInfo.characterLayout->mGradientInfo ) )
{
- currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.gradientInfo->mGradientColor );
- currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.gradientInfo->mStartPoint );
- currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.gradientInfo->mEndPoint );
+ currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.characterLayout->mGradientInfo->mGradientColor );
+ currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.characterLayout->mGradientInfo->mStartPoint );
+ currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.characterLayout->mGradientInfo->mEndPoint );
}
// The italics offset is used in the offscreen rendering. When text is in italics, it may exceed the text-view's boundary
subLineInfo.mMaxAscender *= shrinkFactor;
}
+
+/**
+ * Sets a character of a line of a bidirectional paragraph in the new position.
+ *
+ * @param[in] wordsLayoutInfo Layout info of all the words of the paragraph.
+ * @param[in] index Index within the paragraph to the character to be set in the new position.
+ * @param[in,out] character Reference to the character in the new position.
+ */
+void SetCharacter( const TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo,
+ std::size_t index,
+ TextViewProcessor::CharacterLayoutInfo& character )
+{
+ // Traverse all the characters of the paragraph till the one pointed by index is found.
+ std::size_t traversedCharacters = 0u;
+ for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = wordsLayoutInfo.begin(),
+ wordEndIt = wordsLayoutInfo.end();
+ wordIt != wordEndIt;
+ ++wordIt )
+ {
+ const TextViewProcessor::WordLayoutInfo& word( *wordIt );
+
+ const std::size_t numberOfCharacters = word.mCharactersLayoutInfo.size();
+ if( index < traversedCharacters + numberOfCharacters )
+ {
+ character = *( word.mCharactersLayoutInfo.begin() + ( index - traversedCharacters ) );
+ return;
+ }
+ traversedCharacters += numberOfCharacters;
+ }
+}
+
+/**
+ * Reorders the layout info of each line of the paragraph.
+ *
+ * Uses the visual to logical conversion table to order the text, styles and character's layout (metrics).
+ *
+ * @param[in,out] rtlParagraph Layout info for the paragraph with rtl text.
+ */
+void ReorderLayout( TextViewProcessor::ParagraphLayoutInfo& paragraph )
+{
+ // Clear any previous right to left layout.
+ if( NULL != paragraph.mRightToLeftLayout )
+ {
+ paragraph.mRightToLeftLayout->Clear();
+ paragraph.mRightToLeftLayout->mPreviousLayoutCleared = true;
+ }
+ else
+ {
+ // Create a new right to left layout if there isn't any.
+ paragraph.mRightToLeftLayout = new TextViewProcessor::RightToLeftParagraphLayout();
+ }
+
+ // Reorder Text and Styles.
+
+ // Reserve space for the styles.
+ paragraph.mRightToLeftLayout->mTextStyles.Reserve( paragraph.mTextStyles.Count() );
+
+ // Traverses all the bidirectional info per line.
+ for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it )
+ {
+ TextProcessor::BidirectionalLineInfo* info( *it );
+
+ const std::size_t characterParagraphIndex = info->mCharacterParagraphIndex;
+ const Vector<int>& visualToLogicalMap = info->mVisualToLogicalMap;
+
+ // The text can be appended as it's already reordered.
+ paragraph.mRightToLeftLayout->mText.Append( info->mText );
+
+ // The visual to logical map needs to be used to reorder the styles.
+ for( std::size_t index = 0u, size = visualToLogicalMap.Count(); index < size; ++index )
+ {
+ paragraph.mRightToLeftLayout->mTextStyles.PushBack( *( paragraph.mTextStyles.Begin() + ( characterParagraphIndex + *( visualToLogicalMap.Begin() + index ) ) ) );
+ }
+ }
+
+ // Reorder Layout Info.
+
+ // Reserve space for the new word layout.
+ paragraph.mRightToLeftLayout->mWordsLayoutInfo.reserve( paragraph.mWordsLayoutInfo.size() );
+
+ // Traverses all the bidirectional info per line.
+ for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it )
+ {
+ TextProcessor::BidirectionalLineInfo* info( *it );
+
+ // Reserve space for all characters.
+ TextViewProcessor::CharacterLayoutInfoContainer characters;
+ characters.resize( info->mNumberOfCharacters );
+
+ // Uses the visual to logical map to set every character in its new position.
+ for( std::size_t index = 0u; index < info->mNumberOfCharacters; ++index )
+ {
+ SetCharacter( paragraph.mWordsLayoutInfo,
+ info->mCharacterParagraphIndex + info->mVisualToLogicalMap[index],
+ *( characters.begin() + index ) );
+ }
+
+ // Sets the new 'x' position for each character.
+ float xPosition = 0.f;
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it )
+ {
+ TextViewProcessor::CharacterLayoutInfo& character( *it );
+
+ character.mPosition.x = xPosition;
+ xPosition += character.mSize.width;
+ }
+
+ // Split the reordered text in words.
+ std::size_t previousPosition = 0u;
+ Vector<std::size_t> positions;
+ TextProcessor::SplitInWords( info->mText, positions );
+
+ // Sets the characters into the words they belong to.
+ for( Vector<size_t>::ConstIterator it = positions.Begin(), endIt = positions.End(); it != endIt; ++it )
+ {
+ const std::size_t position = *it;
+
+ TextViewProcessor::WordLayoutInfo word;
+ word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(),
+ characters.begin() + previousPosition,
+ characters.begin() + position );
+
+ if( !word.mCharactersLayoutInfo.empty() )
+ {
+ // Updates the layout of the word.
+ TextViewProcessor::UpdateLayoutInfo( word );
+
+ paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word );
+ }
+
+ // white space or new paragraph.
+ TextViewProcessor::WordLayoutInfo space;
+ space.mCharactersLayoutInfo.insert( space.mCharactersLayoutInfo.end(),
+ characters.begin() + position,
+ characters.begin() + position + 1u );
+
+ TextViewProcessor::UpdateLayoutInfo( space );
+
+ paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( space );
+
+ previousPosition = position + 1u;
+ }
+
+ // The last word.
+ if( previousPosition < paragraph.mRightToLeftLayout->mText.GetLength() )
+ {
+ TextViewProcessor::WordLayoutInfo word;
+ word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(),
+ characters.begin() + previousPosition,
+ characters.end() );
+
+ TextViewProcessor::UpdateLayoutInfo( word );
+
+ paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word );
+ }
+ }
+}
+
+/**
+ * Creates the bidirectional info needed to reorder each line of the paragraph.
+ *
+ * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info.
+ * @param[in,out] paragraph Layout info for the paragraph.
+ * @param[in] characterGlobalIndex Index to the character within the whole text.
+ * @param[in] lineLayoutInfoIndex Index to the table of lines.
+ */
+void CreateBidirectionalInfoForLines( TextView::RelayoutData& relayoutData,
+ TextViewProcessor::ParagraphLayoutInfo& paragraph,
+ std::size_t& characterGlobalIndex,
+ std::size_t& lineLayoutInfoIndex )
+{
+ const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number or laid out lines.
+ bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last laid out line.
+
+ // Clear previously created bidirectional info.
+ paragraph.ClearBidirectionalInfo();
+
+ std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph).
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+ wordIt != wordEndIt;
+ ++wordIt )
+ {
+ TextViewProcessor::WordLayoutInfo& word( *wordIt );
+
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
+ characterIt != characterEndIt;
+ ++characterIt )
+ {
+ TextProcessor::BidirectionalLineInfo* bidirectionalLineInfo = NULL;
+
+ // Check if there is a new line.
+ const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex );
+
+ if( newLine )
+ {
+ // Point to the next line.
+ ++lineLayoutInfoIndex;
+ if( lineLayoutInfoIndex >= lineLayoutInfoSize )
+ {
+ // Arrived at last line.
+ lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector.
+ }
+
+ // Number of characters of the line.
+ const size_t numberOfCharacters = ( lineLayoutEnd ? relayoutData.mTextLayoutInfo.mNumberOfCharacters : relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ) - characterGlobalIndex;
+
+ // There is right to left characters in this line. It needs to be reordered.
+ bidirectionalLineInfo = new TextProcessor::BidirectionalLineInfo();
+ bidirectionalLineInfo->mCharacterParagraphIndex = characterParagraphIndex;
+ bidirectionalLineInfo->mNumberOfCharacters = numberOfCharacters;
+
+ // Set all the Text's characters in the visual order and creates the mapping tables.
+ TextProcessor::ReorderLine( paragraph.mBidirectionalParagraphInfo,
+ bidirectionalLineInfo );
+
+ paragraph.mBidirectionalLinesInfo.PushBack( bidirectionalLineInfo );
+
+ for( std::size_t index = 0u; index < numberOfCharacters; ++index )
+ {
+ relayoutData.mCharacterLogicalToVisualMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mLogicalToVisualMap[index] );
+ relayoutData.mCharacterVisualToLogicalMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mVisualToLogicalMap[index] );
+ }
+ }
+
+ ++characterGlobalIndex;
+ ++characterParagraphIndex;
+ } // characters
+ } // words
+}
+
+void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData )
+{
+ // Reset conversion tables shared through public-api
+ relayoutData.mCharacterLogicalToVisualMap.clear();
+ relayoutData.mCharacterVisualToLogicalMap.clear();
+
+ std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text).
+ std::size_t lineLayoutInfoIndex = 0u; // Index to the line info.
+
+ for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
+ paragraphIt != paragraphEndIt;
+ ++paragraphIt )
+ {
+ TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
+
+ if( NULL != paragraph.mBidirectionalParagraphInfo )
+ {
+ // There is right to left text in this paragraph.
+
+ // Creates the bidirectional info needed to reorder each line of the paragraph.
+ CreateBidirectionalInfoForLines( relayoutData,
+ paragraph,
+ characterGlobalIndex,
+ lineLayoutInfoIndex );
+
+ // Reorder each line of the paragraph
+ ReorderLayout( paragraph );
+ }
+ else
+ {
+ // Identity in case the paragraph has no right to left text.
+ for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index )
+ {
+ const std::size_t globalIndex = characterGlobalIndex + index;
+ relayoutData.mCharacterLogicalToVisualMap.push_back( globalIndex );
+ relayoutData.mCharacterVisualToLogicalMap.push_back( globalIndex );
+ }
+ characterGlobalIndex += paragraph.mNumberOfCharacters;
+ }
+ } // paragraphs
+}
+
float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth )
{
float xOffset( 0.f );
const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width );
const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height );
- std::size_t lineJustificationIndex = 0u; // Index to the first position of the vector which stores all line justification info.
- std::size_t infoTableCharacterIndex = 0u;
+ // Index to the global character (within the whole text).
+ std::size_t characterGlobalIndex = 0u;
+
+ // Index to the line info.
+ std::size_t lineLayoutInfoIndex = 0u;
relayoutParameters.mIndices.mParagraphIndex = 0u;
float justificationOffset = 0.f;
+ const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines.
+ bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line.
+
relayoutParameters.mIndices.mWordIndex = 0u;
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
- endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+ const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+ endWordLayoutIt = wordsLayoutInfo.end();
wordLayoutIt != endWordLayoutIt;
++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
{
for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
+ ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++characterGlobalIndex )
{
TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
- // Calculate line justification offset.
- if( lineJustificationIndex < relayoutData.mLineJustificationInfo.size() )
+ // Check if there is a new line.
+ const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex );
+
+ if( newLine )
{
- const TextView::LineJustificationInfo lineJustificationInfo( *( relayoutData.mLineJustificationInfo.begin() + lineJustificationIndex ) );
+ // Calculate line justification offset.
+ justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, relayoutData.mLines[lineLayoutInfoIndex].mSize.width );
- if( relayoutParameters.mIndices == lineJustificationInfo.mIndices )
+ // Point to the next line.
+ ++lineLayoutInfoIndex;
+ if( lineLayoutInfoIndex >= lineLayoutInfoSize )
{
- justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, lineJustificationInfo.mLineLength );
- ++lineJustificationIndex; // increase the index to point the next position in the vector.
+ // Arrived at last line.
+ lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector.
}
}
// Updates the size and position table for text-input with the alignment offset.
Vector3 positionOffset( characterLayoutInfo.mPosition );
- std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
+ std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + characterGlobalIndex;
Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt );
characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x;
characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ),
positionOffset,
( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ),
- false, // VCC set the correct direction if needed.
- true,
+ characterLayoutInfo.mIsRightToLeft, // whether the character is right to left.
+ true, // whether the character is visible.
descender );
relayoutData.mCharacterLayoutInfoTable.push_back( characterLayoutTableInfo );
void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
+ const TextStyle& style,
RelayoutParameters& relayoutParameters,
FadeParameters& fadeParameters,
TextView::RelayoutData& relayoutData )
Vector2 startPoint = Vector2::ZERO;
Vector2 endPoint = Vector2::ZERO;
- if( NULL == characterLayoutInfo.mGradientInfo )
- {
- characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
- }
-
if( !( rightFadeOut && leftFadeOut ) )
{
// Current implementation can't set gradient parameters for a text-actor exceeding at the same time the left and the right boundaries.
if( rightFadeOut )
{
- gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+ gradientColor = style.GetTextColor();
// Calculates gradient coeficients.
characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mRightAlphaCoeficients.x * position.x + fadeParameters.mRightAlphaCoeficients.y );
gradientColor.a *= std::max( 0.f, fadeParameters.mRightAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mRightAlphaCoeficients.y );
- startPoint = Vector2( std::max( 0.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ), 0.5f );
- endPoint = Vector2( std::min( 1.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ), 0.5f );
+ startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ) ), 0.5f );
+ endPoint = Vector2( std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ) ), 0.5f );
+
+ if( NULL == characterLayoutInfo.mGradientInfo )
+ {
+ characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+ }
}
else if( leftFadeOut )
{
- gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+ gradientColor = style.GetTextColor();
// Calculates gradient coeficients.
characterLayoutInfo.mColorAlpha = std::min( 1.f, fadeParameters.mLeftAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mLeftAlphaCoeficients.y );
gradientColor.a *= gradientColor.a * std::max( 0.f, fadeParameters.mLeftAlphaCoeficients.x * position.x + fadeParameters.mLeftAlphaCoeficients.y );
- startPoint = Vector2( std::max( 0.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ), 0.5f );
- endPoint = Vector2( std::min( 1.f, -position.x / size.width ), 0.5f );
+ startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ) ), 0.5f );
+ endPoint = Vector2( std::min( 1.f, std::max( 0.f, -position.x / size.width ) ), 0.5f );
+
+ if( NULL == characterLayoutInfo.mGradientInfo )
+ {
+ characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+ }
}
}
// Current implementation can't set gradient parameters for a text-actor exceeding at the same time the top and the bottom boundaries.
if( bottomFadeOut )
{
- gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+ gradientColor = style.GetTextColor();
// Calculates gradient coeficients.
characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mBottomAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mBottomAlphaCoeficients.y );
gradientColor.a *= std::max( 0.f, fadeParameters.mBottomAlphaCoeficients.x * position.y + fadeParameters.mBottomAlphaCoeficients.y );
- startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
- endPoint = Vector2( 0.5f, std::min( 1.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) );
+ startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) );
+ endPoint = Vector2( 0.5f, std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) ) );
+
+ if( NULL == characterLayoutInfo.mGradientInfo )
+ {
+ characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+ }
}
else if( topFadeOut )
{
- gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+ gradientColor = style.GetTextColor();
// Calculates gradient coeficients.
characterLayoutInfo.mColorAlpha *= gradientColor.a * std::min( 1.f, fadeParameters.mTopAlphaCoeficients.x * position.y + fadeParameters.mTopAlphaCoeficients.y );
gradientColor.a *= std::max( 0.f, fadeParameters.mTopAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mTopAlphaCoeficients.y );
- startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
- endPoint = Vector2( 0.5f, std::min( 1.f, -characterPositionMinusHeight / size.height ) );
+ startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) );
+ endPoint = Vector2( 0.5f, std::min( 1.f, std::max( 0.f, -characterPositionMinusHeight / size.height ) ) );
+
+ if( NULL == characterLayoutInfo.mGradientInfo )
+ {
+ characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+ }
}
}
- characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor;
- characterLayoutInfo.mGradientInfo->mStartPoint = startPoint;
- characterLayoutInfo.mGradientInfo->mEndPoint = endPoint;
+ if( NULL != characterLayoutInfo.mGradientInfo )
+ {
+ characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor;
+ characterLayoutInfo.mGradientInfo->mStartPoint = startPoint;
+ characterLayoutInfo.mGradientInfo->mEndPoint = endPoint;
+ }
}
else
{
float bearingOffset = 0.f;
// Create ellipsize text-actor.
+ std::size_t characterIndex = 0u;
for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator ellipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.begin(),
endEllipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.end();
ellipsizeCharacterLayoutIt != endEllipsizeCharacterLayoutIt;
- ++ellipsizeCharacterLayoutIt )
+ ++ellipsizeCharacterLayoutIt, ++characterIndex )
{
const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt );
+ const TextStyle& style = *( *( relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin() + characterIndex ) );
if( isColorGlyph ||
( isColorGlyph != ellipsizeCharacterLayoutInfo.mIsColorGlyph ) ||
- ( ellipsizeStyle != ellipsizeCharacterLayoutInfo.mStyledText.mStyle ) )
+ ( ellipsizeStyle != style ) )
{
// The style is different, so a new text-actor is needed.
if( !ellipsizeText.IsEmpty() )
}
// Resets the current ellipsize info.
- ellipsizeText = ellipsizeCharacterLayoutInfo.mStyledText.mText;
- ellipsizeStyle = ellipsizeCharacterLayoutInfo.mStyledText.mStyle;
+ ellipsizeText = Text( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] );
+ ellipsizeStyle = style;
ellipsizeSize = ellipsizeCharacterLayoutInfo.mSize;
isColorGlyph = ellipsizeCharacterLayoutInfo.mIsColorGlyph;
else
{
// Updates text and size with the new character.
- ellipsizeText.Append( ellipsizeCharacterLayoutInfo.mStyledText.mText );
+ ellipsizeText.Append( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] );
TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize );
}
}
std::size_t wordCount = 0u;
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + firstIndices.mWordIndex,
- endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u;
+ const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin() + firstIndices.mWordIndex,
+ endWordLayoutIt = wordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u;
wordLayoutIt != endWordLayoutIt;
++wordLayoutIt, ++wordCount )
{
++paragraphLayoutIt )
{
TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
+ std::size_t characterIndex = 0u;
+
+ const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
- endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+ endWordLayoutIt = wordsLayoutInfo.end();
wordLayoutIt != endWordLayoutIt;
++wordLayoutIt )
{
for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt )
+ ++characterLayoutIt, ++characterIndex )
{
TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
characterLayoutInfo.mIsVisible = true;
delete characterLayoutInfo.mGradientInfo;
characterLayoutInfo.mGradientInfo = NULL;
- characterLayoutInfo.mColorAlpha = characterLayoutInfo.mStyledText.mStyle.GetTextColor().a;
+ characterLayoutInfo.mColorAlpha = ( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) )->GetTextColor().a;
} // end characters
} // end words
} // end paragraphs
{
TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
+ std::size_t characterIndex = 0u;
relayoutParameters.mIndices.mWordIndex = 0u;
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
- endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+ const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+ endWordLayoutIt = wordsLayoutInfo.end();
wordLayoutIt != endWordLayoutIt;
++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
{
for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
+ ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex, ++characterIndex )
{
TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
// Calculates the visibility for the current character.
CalculateVisibilityForFade( layoutParameters,
characterLayoutInfo,
+ *( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) ),
relayoutParameters,
fadeParameters,
relayoutData );
// Set the text-actor for the current traversed text.
if( currentTextActorInfo.textActor )
{
- currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+ if( ( NULL != currentTextActorInfo.characterLayout ) &&
+ currentTextActorInfo.characterLayout->mSetText )
+ {
+ currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+ currentTextActorInfo.characterLayout->mSetText = false;
+ }
currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
paragraph.mSize.height );
}
+ float rightToLeftOffset = 0.f;
+ if( character.IsWhiteSpace() )
+ {
+ // In left to right text, a word never starts with a white space but
+ // it may happen in right to left text as the text is reversed.
+ // The text alignment and justification offset is calculated without this white space.
+ // It causes a missalignment which can be corrected by removing the size of the white space.
+ rightToLeftOffset = characterLayout.mSize.width * relayoutData.mShrinkFactor;
+ }
+
currentTextActorInfo.text = Text( character );
- currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x,
+ currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x - rightToLeftOffset,
characterLayout.mPosition.y + characterLayout.mOffset.y,
characterLayout.mPosition.z );
currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor;
currentTextActorInfo.color = style.GetTextColor();
currentTextActorInfo.color.a = characterLayout.mColorAlpha;
- currentTextActorInfo.gradientInfo = characterLayout.mGradientInfo;
-
TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
if( createGlyphActors )
textActor.SetTextStyle( style );
}
}
+ characterLayout.mSetText = true;
+ currentTextActorInfo.characterLayout = &characterLayout;
+
characterLayout.mGlyphActor = textActor;
}
*/
void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters,
TextView::RelayoutData& relayoutData,
- TextViewProcessor::ParagraphLayoutInfo& paragraph,
+ TextViewProcessor::ParagraphLayoutInfo& paragraphLayout,
std::size_t& characterGlobalIndex,
std::size_t& lineLayoutInfoIndex,
bool createGlyphActors )
{
CurrentTextActorInfo currentTextActorInfo;
+ currentTextActorInfo.characterLayout = NULL;
const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines.
bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line.
std::vector<TextActor> textActorsToRemove; // Keep a vector of text-actors to be included into the cache.
+ // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout.
+ const bool isRightToLeftLayout = NULL != paragraphLayout.mRightToLeftLayout;
+
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayout.mWordsLayoutInfo;
+ Text& text = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mText : paragraphLayout.mText;
+ Vector<TextStyle*>& textStyles = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mTextStyles : paragraphLayout.mTextStyles;
+
+ // In case the previous right to left layout has been cleared, all text-actors have been removed as well. If this bool is set to true, text-actors will be created again.
+ const bool previousRightToLeftLayoutCleared = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mPreviousLayoutCleared : false;
+
std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph).
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end();
wordIt != wordEndIt;
++wordIt )
{
- TextViewProcessor::WordLayoutInfo& word( *wordIt );
+ TextViewProcessor::WordLayoutInfo& wordLayout( *wordIt );
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = wordLayout.mCharactersLayoutInfo.begin(), characterEndIt = wordLayout.mCharactersLayoutInfo.end();
characterIt != characterEndIt;
++characterIt )
{
}
// Do not create a glyph-actor if there is no text.
- const Character character = characterLayout.mStyledText.mText[0u]; // there are only one character per character layout.
- const TextStyle& style = characterLayout.mStyledText.mStyle;
+ const Character character = text[characterParagraphIndex];
+ const TextStyle& style = *( *( textStyles.Begin() + characterParagraphIndex ) );
bool appendCharacter = false;
if( characterLayout.mIsColorGlyph ||
- !character.IsWhiteSpace() || // A new paragraph character is also a white space.
- ( character.IsWhiteSpace() && style.IsUnderlineEnabled() ) )
+ ( TextViewProcessor::NoSeparator == wordLayout.mType ) ||
+ ( ( TextViewProcessor::WordSeparator == wordLayout.mType ) && style.IsUnderlineEnabled() ) )
{
// Do not create a glyph-actor if it's a white space (without underline) or a new paragraph character.
characterLayout.mSetText = false;
characterLayout.mSetStyle = false;
- // There is a new style or a new line.
- glyphActorCreatedForLine = true;
-
if( characterLayout.mIsColorGlyph )
{
CreateEmoticon( visualParameters,
{
CreateTextActor( visualParameters,
relayoutData,
- paragraph,
+ paragraphLayout,
characterLayout,
character,
style,
currentTextActorInfo,
- createGlyphActors );
+ createGlyphActors || previousRightToLeftLayoutCleared );
}
+ // There is a new style or a new line.
+ glyphActorCreatedForLine = true;
+
// Update style to be checked with next characters.
currentStyle = style;
currentGradientInfo = characterLayout.mGradientInfo;
if( appendCharacter )
{
// Add the character to the current text-actor and update the size.
- if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != word.mType ) )
+ if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != wordLayout.mType ) )
{
currentTextActorInfo.text.Append( character );
{
if( currentTextActorInfo.textActor )
{
- currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+ if( ( NULL != currentTextActorInfo.characterLayout ) &&
+ currentTextActorInfo.characterLayout->mSetText )
+ {
+ currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+ currentTextActorInfo.characterLayout->mSetText = false;
+ }
currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
SetVisualParameters( currentTextActorInfo,
visualParameters,
relayoutData,
- paragraph.mSize.height );
+ paragraphLayout.mSize.height );
}
}
{
TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+ std::size_t characterIndex = 0u;
+
+ const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout;
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo;
+
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end();
wordIt != wordEndIt;
++wordIt )
{
for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
characterIt != characterEndIt;
- ++characterIt )
+ ++characterIt, ++characterIndex )
{
TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
+ const TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) );
// Check if current character is the first of a new line
const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) &&
++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
}
- if( character.mStyledText.mStyle.IsUnderlineEnabled() )
+ if( style.IsUnderlineEnabled() )
{
if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't.
isNewLine ) // Current character is underlined and is the first of current line.
++paragraphIt )
{
TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
+ std::size_t characterIndex = 0u;
+
+ const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout;
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo;
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end();
wordIt != wordEndIt;
++wordIt )
{
for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
characterIt != characterEndIt;
- ++characterIt )
+ ++characterIt, ++characterIndex )
{
TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
+ TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) );
// Check if current character is the first of a new line
}
}
- if( character.mStyledText.mStyle.IsUnderlineEnabled() )
+ if( style.IsUnderlineEnabled() )
{
if( textUnderlineStatus.mCurrentUnderlineStatus )
{
const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset;
// Sets the underline's parameters.
- character.mStyledText.mStyle.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
+ style.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
// Mark the character to be set the new style into the text-actor.
character.mSetStyle = true;
{
TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
- endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+ // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout.
+ const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+ TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+ endWordLayoutIt = wordsLayoutInfo.end();
wordLayoutIt != endWordLayoutIt;
++wordLayoutIt )
{
*/
// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/alignment/alignment.h>
+#include <dali-toolkit/public-api/controls/text-view/text-view.h>
#include <dali-toolkit/internal/controls/text-view/text-view-impl.h>
-#include <dali-toolkit/internal/controls/text-view/text-view-processor-types.h>
namespace Dali
{
LineLayoutInfo& layoutInfo );
/**
+ * Reorders the text layout of each line of each paragraph of the text.
+ *
+ * @param[in,out] relayoutData The text-view's data structures.
+ */
+void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData );
+
+/**
* Calculates the \e x offset position for the whole text.
*
* @param[in] horizontalTextAlignment The horizontal alignment type.
*
* @param[in] layoutParameters The layout parameters.
* @param[in] characterLayoutInfo Character layout info.
+ * @param[in] style The style of the character. Used to get the color (and alpha) of the character.
* @param[in,out] relayoutParameters Temporary layout parameters.
* @param[in,out] fadeParameters Temporary fade parameters.
* @param[in,out] relayoutData The text-view's data structures.
*/
void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
+ const TextStyle& style,
RelayoutParameters& relayoutParameters,
FadeParameters& fadeParameters,
TextView::RelayoutData& relayoutData );
TextView::RelayoutData& relayoutData );
/**
+ * Replace the text which exceeds the boundary by the ellipsis text.
*
+ * @param[in] layoutParameters The layout parameters.
+ * @param[in,out] ellipsisParameters Temporary ellipsis parameters.
+ * @param[in,out] relayoutData The text-view's data structures.
*/
void EllipsizeLine( const TextView::LayoutParameters& layoutParameters,
EllipsizeParameters& ellipsizeParameters,
1.f, // Shrink factor
subLineInfo );
- // Stores some info to calculate the line justification in a post-process.
- TextView::LineJustificationInfo justificationInfo;
-
- justificationInfo.mIndices = relayoutParameters.mIndices;
- justificationInfo.mLineLength = subLineInfo.mLineLength;
-
- relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
Toolkit::TextView::LineLayoutInfo lineInfo;
lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
{
if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
{
- relayoutData.mLineJustificationInfo.clear();
CalculateSizeAndPosition( layoutParameters,
relayoutData );
+ TextViewRelayout::ReorderRightToLeftLayout( relayoutData );
+
TextViewRelayout::SetUnderlineInfo( relayoutData );
}
1.f, // Shrink factor
subLineInfo );
- // Stores some info to calculate the line justification in a post-process.
- TextView::LineJustificationInfo justificationInfo;
-
- justificationInfo.mIndices = relayoutParameters.mIndices;
- justificationInfo.mLineLength = subLineInfo.mLineLength;
-
- relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
Toolkit::TextView::LineLayoutInfo lineInfo;
lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
relayoutParameters.mWordSize = wordLayoutInfo.mSize;
relayoutParameters.mIndices.mCharacterIndex = 0u;
- if( relayoutParameters.mIsNewLine )
- {
- // Stores some info to calculate the line justification in a post-process.
- const bool isSplitOriginal = layoutParameters.mExceedPolicy == TextView::SplitOriginal;
-
- if( !isSplitOriginal )
- {
- TextView::LineJustificationInfo justificationInfo;
-
- justificationInfo.mIndices = relayoutParameters.mIndices;
- justificationInfo.mLineLength = relayoutParameters.mParagraphSize.width;
-
- relayoutData.mLineJustificationInfo.push_back( justificationInfo );
- }
- }
-
for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
characterLayoutIt != endCharacterLayoutIt;
{
if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
{
- relayoutData.mLineJustificationInfo.clear();
CalculateSizeAndPosition( layoutParameters,
relayoutData );
+ TextViewRelayout::ReorderRightToLeftLayout( relayoutData );
+
TextViewRelayout::SetUnderlineInfo( relayoutData );
}
}
}
- // Stores some info to calculate the line justification in a post-process.
- TextView::LineJustificationInfo justificationInfo;
-
- justificationInfo.mIndices = relayoutParameters.mIndices;
- justificationInfo.mLineLength = subLineInfo.mLineLength;
-
- relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
Toolkit::TextView::LineLayoutInfo lineInfo;
lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
1.f, // Shrink factor.
subLineInfo );
- // Stores some info to calculate the line justification in a post-process.
- TextView::LineJustificationInfo justificationInfo;
-
- justificationInfo.mIndices = relayoutParameters.mIndices;
- justificationInfo.mLineLength = subLineInfo.mLineLength;
-
- relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
Toolkit::TextView::LineLayoutInfo lineInfo;
lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
relayoutData.mShrinkFactor,
subLineInfo );
- // Stores some info to calculate the line justification in a post-process.
- TextView::LineJustificationInfo justificationInfo;
-
- justificationInfo.mIndices = relayoutParameters.mIndices;
- justificationInfo.mLineLength = subLineInfo.mLineLength;
-
- relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
Toolkit::TextView::LineLayoutInfo lineInfo;
lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
const float parentWidth = relayoutData.mTextViewSize.width;
TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo;
- relayoutData.mLineJustificationInfo.clear();
-
// Reset the text height. This value is returned in order to shrink further or not the text.
newTextHeight = 0.f;
lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph.
relayoutData.mLines.push_back( lineInfo );
-
- // Stores some info to calculate the line justification in a post-process.
- TextView::LineJustificationInfo justificationInfo;
-
- justificationInfo.mIndices = indices;
- justificationInfo.mLineLength = subLineInfo.mLineLength;
-
- relayoutData.mLineJustificationInfo.push_back( justificationInfo );
}
else
{
{
if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
{
- relayoutData.mLineJustificationInfo.clear();
CalculateSizeAndPosition( layoutParameters,
relayoutData );
+ TextViewRelayout::ReorderRightToLeftLayout( relayoutData );
+
TextViewRelayout::SetUnderlineInfo( relayoutData );
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace TextProcessor
+{
+
+BidirectionalParagraphInfo::BidirectionalParagraphInfo()
+: mDirection( FRIBIDI_TYPE_ON ),
+ mCharactersTypeBuffer(),
+ mLevelsBuffer(),
+ mLogicalUnicodeBuffer()
+{
+}
+
+BidirectionalParagraphInfo::~BidirectionalParagraphInfo()
+{
+}
+
+BidirectionalParagraphInfo::BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info )
+: mDirection( info.mDirection ),
+ mCharactersTypeBuffer( info.mCharactersTypeBuffer ),
+ mLevelsBuffer( info.mLevelsBuffer ),
+ mLogicalUnicodeBuffer( info.mLogicalUnicodeBuffer )
+{
+}
+
+BidirectionalParagraphInfo& BidirectionalParagraphInfo::operator=( const BidirectionalParagraphInfo& info )
+{
+ if( this != &info )
+ {
+ mDirection = info.mDirection;
+ mCharactersTypeBuffer = info.mCharactersTypeBuffer;
+ mLevelsBuffer = info.mLevelsBuffer;
+ mLogicalUnicodeBuffer = info.mLogicalUnicodeBuffer;
+ }
+
+ return *this;
+}
+
+BidirectionalLineInfo::BidirectionalLineInfo()
+: mCharacterParagraphIndex(),
+ mNumberOfCharacters(),
+ mText(),
+ mVisualToLogicalMap(),
+ mLogicalToVisualMap()
+{
+}
+
+BidirectionalLineInfo::~BidirectionalLineInfo()
+{
+}
+
+BidirectionalLineInfo::BidirectionalLineInfo( const BidirectionalLineInfo& info )
+: mCharacterParagraphIndex( info.mCharacterParagraphIndex ),
+ mNumberOfCharacters( info.mNumberOfCharacters ),
+ mText( info.mText ),
+ mVisualToLogicalMap( info.mVisualToLogicalMap ),
+ mLogicalToVisualMap( info.mLogicalToVisualMap )
+{
+}
+
+BidirectionalLineInfo& BidirectionalLineInfo::operator=( const BidirectionalLineInfo& info )
+{
+ if( this != &info )
+ {
+ mCharacterParagraphIndex = info.mCharacterParagraphIndex;
+ mNumberOfCharacters = info.mNumberOfCharacters;
+ mText = info.mText;
+ mVisualToLogicalMap = info.mVisualToLogicalMap;
+ mLogicalToVisualMap = info.mLogicalToVisualMap;
+ }
+
+ return *this;
+}
+
+bool BeginsRightToLeftCharacter( const Text& text )
+{
+ for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
+ {
+ Character::CharacterDirection direction = text[i].GetCharacterDirection();
+ if( direction != Character::Neutral )
+ {
+ return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak );
+ }
+ }
+
+ return false;
+}
+
+bool ContainsRightToLeftCharacter( const Dali::Text& text )
+{
+ for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
+ {
+ Character::CharacterDirection direction = ( text[i] ).GetCharacterDirection();
+ if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ProcessBidirectionalText( Text& paragraph, BidirectionalParagraphInfo* info )
+{
+ if( paragraph.IsEmpty() )
+ {
+ // nothing to do if the paragraph is empty.
+ return;
+ }
+
+ const std::size_t stringSize = paragraph.GetText().size();
+
+ // Text buffer in logical order. Coded in unicode.
+ info->mLogicalUnicodeBuffer.resize( stringSize + 1u, 0u );
+ FriBidiChar* logicalUnicodeBufferPointer = &info->mLogicalUnicodeBuffer[0u];
+
+ // Converts from utf8 to unicode.
+ const std::size_t length = fribidi_charset_to_unicode( FRIBIDI_CHAR_SET_UTF8, paragraph.GetText().c_str(), stringSize, logicalUnicodeBufferPointer );
+
+ // Character type buffer.
+ info->mCharactersTypeBuffer.resize( length, 0u );
+
+ // Levels buffer.
+ info->mLevelsBuffer.resize( length, 0u );
+
+ // Joining type buffer.
+ std::vector<FriBidiJoiningType> joiningTypeBuffer;
+ joiningTypeBuffer.resize( length, 0u );
+
+ // Pointers to the buffers.
+ FriBidiCharType* charactersTypeBufferPointer = &info->mCharactersTypeBuffer[0u];
+ FriBidiLevel* levelsBufferPointer = &info->mLevelsBuffer[0u];
+ FriBidiJoiningType* joiningTypeBufferPointer = &joiningTypeBuffer[0u];
+
+ // Retrieves the type of each character.
+ fribidi_get_bidi_types( logicalUnicodeBufferPointer, length, charactersTypeBufferPointer );
+
+ // Retrieves the paragraph direction.
+ info->mDirection = fribidi_get_par_direction( charactersTypeBufferPointer, length );
+
+ // Retrieve the embedding levels.
+ fribidi_get_par_embedding_levels( charactersTypeBufferPointer, length, &info->mDirection, levelsBufferPointer );
+
+ // Retrieve the joining types.
+ fribidi_get_joining_types( logicalUnicodeBufferPointer, length, joiningTypeBufferPointer );
+
+ fribidi_join_arabic( charactersTypeBufferPointer, length, levelsBufferPointer, joiningTypeBufferPointer );
+
+ const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
+
+ fribidi_shape( flags, levelsBufferPointer, length, joiningTypeBufferPointer, logicalUnicodeBufferPointer );
+
+ std::vector<char> bidiTextConverted;
+
+ bidiTextConverted.resize( length * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
+ // Currently Dali doesn't support this UTF-8 extension. Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
+
+ fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, logicalUnicodeBufferPointer, length, &bidiTextConverted[0] );
+
+ paragraph = Text( &bidiTextConverted[0u] );
+}
+
+void ReorderLine( BidirectionalParagraphInfo* paragraphInfo,
+ BidirectionalLineInfo* lineInfo )
+{
+ const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
+
+ lineInfo->mVisualToLogicalMap.Resize( lineInfo->mNumberOfCharacters, 0u );
+ lineInfo->mLogicalToVisualMap.Resize( lineInfo->mNumberOfCharacters, 0u );
+
+ std::vector<FriBidiChar> visualUnicodeBuffer;
+ visualUnicodeBuffer.insert( visualUnicodeBuffer.end(),
+ paragraphInfo->mLogicalUnicodeBuffer.begin() + lineInfo->mCharacterParagraphIndex,
+ paragraphInfo->mLogicalUnicodeBuffer.begin() + ( lineInfo->mCharacterParagraphIndex + lineInfo->mNumberOfCharacters ) );
+
+ // Pointers to the buffers.
+ FriBidiCharType* charactersTypeBufferPointer = ¶graphInfo->mCharactersTypeBuffer[lineInfo->mCharacterParagraphIndex];
+ FriBidiLevel* levelsBufferPointer = ¶graphInfo->mLevelsBuffer[lineInfo->mCharacterParagraphIndex];
+ FriBidiChar* visualUnicodeBufferPointer = &visualUnicodeBuffer[0u];
+ FriBidiStrIndex* visualToLogicalMapPointer = &lineInfo->mVisualToLogicalMap[0u];
+
+ // Initialize the visual to logical mapping table to the identity. Otherwise fribidi_reorder_line fails to retrieve a valid mapping table.
+ for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index )
+ {
+ lineInfo->mVisualToLogicalMap[ index ] = index;
+ }
+
+ fribidi_reorder_line( flags,
+ charactersTypeBufferPointer,
+ lineInfo->mNumberOfCharacters,
+ 0u,
+ paragraphInfo->mDirection,
+ levelsBufferPointer,
+ visualUnicodeBufferPointer,
+ visualToLogicalMapPointer );
+
+ // Fill the logical to visual mapping table.
+ for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index )
+ {
+ lineInfo->mLogicalToVisualMap[ lineInfo->mVisualToLogicalMap[ index ] ] = index;
+ }
+
+ std::vector<char> bidiTextConverted;
+
+ bidiTextConverted.resize( lineInfo->mNumberOfCharacters * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
+ // Currently Dali doesn't support this UTF-8 extension.
+ // Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
+
+ fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, visualUnicodeBufferPointer, lineInfo->mNumberOfCharacters, &bidiTextConverted[0u] );
+
+ lineInfo->mText = Text( &bidiTextConverted[0u] );
+}
+
+} // namespace TextProcessor
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__
+#define __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__
+
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/text/text.h>
+
+// EXTERNAL INCLUDES
+#include <fribidi/fribidi.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace TextProcessor
+{
+
+/**
+ * Stores the text containing right to left characters and info for each character needed by fribidi to reorder a line.
+ */
+struct BidirectionalParagraphInfo
+{
+ /**
+ * Default constructor.
+ *
+ * Initializes all members to their default values.
+ */
+ BidirectionalParagraphInfo();
+
+ /**
+ * Default destructor.
+ */
+ ~BidirectionalParagraphInfo();
+
+ /**
+ * Copy constructor.
+ */
+ BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info );
+
+ /**
+ * Assignment operator.
+ */
+ BidirectionalParagraphInfo& operator=( const BidirectionalParagraphInfo& info );
+
+ FriBidiParType mDirection; ///< The paragraph direction.
+ std::vector<FriBidiCharType> mCharactersTypeBuffer; ///< Character type buffer.
+ std::vector<FriBidiLevel> mLevelsBuffer; ///< Levels buffer.
+ std::vector<FriBidiChar> mLogicalUnicodeBuffer; ///< Text buffer in logical order. Coded in unicode.
+};
+
+/**
+ * Stores the reordered text, the conversion tables for a paragraph's line,
+ * the index to the first character of the line and the number of characters.
+ */
+struct BidirectionalLineInfo
+{
+ /**
+ * Default constructor.
+ *
+ * Initializes all members to their default values.
+ */
+ BidirectionalLineInfo();
+
+ /**
+ * Default destructor.
+ */
+ ~BidirectionalLineInfo();
+
+ /**
+ * Copy constructor.
+ */
+ BidirectionalLineInfo( const BidirectionalLineInfo& info );
+
+ /**
+ * Assignment operator.
+ */
+ BidirectionalLineInfo& operator=( const BidirectionalLineInfo& info );
+
+ std::size_t mCharacterParagraphIndex; ///< Index within the paragraph of the first character of the line.
+ std::size_t mNumberOfCharacters; ///< Number of characters of the line.
+ Text mText; ///< Text in visual order.
+ Vector<int> mVisualToLogicalMap; ///< The character position map from the visual output text to the logical input text.
+ Vector<int> mLogicalToVisualMap; ///< The character position map from the logical input text to the visual output text.
+};
+
+/**
+ * Whether the text begins with right-to-left (bidirectional) character.
+ * @param [in] text The given text.
+ * @return \e true if the text begins right-to-left character.
+ */
+bool BeginsRightToLeftCharacter( const Text& text );
+
+/**
+ * Whether the text contains any right-to-left (bidirectional) character.
+ * @param [in] text The given text.
+ * @return \e true if the text contains right-to-left character.
+ */
+bool ContainsRightToLeftCharacter( const Text& text );
+
+/**
+ * Processes a bidirectional paragraph's text.
+ *
+ * It stores the paragraph's direction (the direction of the first non neutral character),
+ * the direction of all characters, and the ligatures in case of arabic glyphs.
+ *
+ * It doesn't reorder the paragraph as this task must be done per line.
+ * The stored info is needed to reorder each line of the paragraph.
+ *
+ * @param[in] paragraph The paragraph to be processed.
+ * @param[out] info Struct containing the needed info to reorder each line of the paragraph.
+ */
+void ProcessBidirectionalText( Text& paragraph,
+ BidirectionalParagraphInfo* info );
+
+/**
+ * Reorders one line of the paragraph according the Unicode Bidirectional Algorithm.
+ *
+ * The result is the text in the visual order and the conversion tables: logical <--> visual order
+ *
+ * @param[in] paragraphInfo Struct containing the needed info to reorder each line of the paragraph.
+ * @param[in,out] lineInfo Struct containing (in) A character index pointing the first character of the line and the number of characters, (out) the reordered line and the conversion tables.
+ */
+void ReorderLine( BidirectionalParagraphInfo* paragraphInfo,
+ BidirectionalLineInfo* lineInfo );
+
+} // namespace TextProcessor
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__
+
// FILE HEADER
#include <dali-toolkit/internal/controls/text-view/text-processor.h>
-// EXTERNAL INCLUDES
-#include <fribidi/fribidi.h>
-
namespace Dali
{
namespace TextProcessor
{
-void SplitInParagraphs( const MarkupProcessor::StyledTextArray& text,
- std::vector<MarkupProcessor::StyledTextArray>& paragraphs )
+void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray,
+ std::vector<Text>& paragraphs,
+ std::vector< Vector<TextStyle*> >& styles )
{
- MarkupProcessor::StyledTextArray paragraph;
- for( MarkupProcessor::StyledTextArray::const_iterator it = text.begin(), endIt = text.end(); it != endIt; ++it )
+ // Stores the text for a paragraph.
+ Text paragraph;
+
+ // Stores the styles for each character of the paragraph.
+ Vector<TextStyle*> stylesForParagraph;
+
+ // Traverses all styled texts of the array.
+ for( MarkupProcessor::StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it )
{
const MarkupProcessor::StyledText& styledText( *it );
+ // Traverses all the characters of the styled text (It may have more than one).
for( size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i )
{
const Dali::Character character = styledText.mText[i];
if( character.IsNewLine() ) // LF
{
- Text newText( character );
- MarkupProcessor::StyledText newStyledText( newText, styledText.mStyle );
- paragraph.push_back( newStyledText );
+ // The character is a new paragraph character.
- paragraphs.push_back( paragraph );
- paragraph.clear();
- }
- else
- {
- Text newText( character );
- MarkupProcessor::StyledText newStyledText( newText, styledText.mStyle );
- paragraph.push_back( newStyledText );
- }
- }
- }
+ // Append the new paragraph character.
+ paragraph.Append( character );
- // This paragraph could be empty if the last character of the previous paragraph is a 'new paragraph' character
- // and is the last of the text.
- paragraphs.push_back( paragraph );
-}
+ // Creates a new text style for the character and insert it to the vector of styles for that paragraph.
+ TextStyle* style = new TextStyle( styledText.mStyle );
+ stylesForParagraph.PushBack( style );
-void SplitInWords( const MarkupProcessor::StyledTextArray& paragraph,
- std::vector<MarkupProcessor::StyledTextArray>& words )
-{
- MarkupProcessor::StyledTextArray word;
- for( MarkupProcessor::StyledTextArray::const_iterator it = paragraph.begin(), endIt = paragraph.end(); it != endIt; ++it )
- {
- const MarkupProcessor::StyledText& styledText( *it );
- const Dali::Character character = styledText.mText[0u];
+ // Inserts the paragraph and the styles to the vector of paragraphs and the vector of styles.
+ paragraphs.push_back( paragraph );
+ styles.push_back( stylesForParagraph );
- if( character.IsWhiteSpace() )
- {
- // When a separator is found, the previous word is added to the list,
- // then a new word is initialized and the separator is also added as a word.
- if( !word.empty() )
- {
- words.push_back( word );
- word.clear(); // initializes a new word.
+ // Clears the text and the vector of styles for the next paragraph.
+ paragraph = Text();
+ stylesForParagraph.Clear();
}
-
- // Separator added as a word.
- MarkupProcessor::StyledText separatorChar;
- separatorChar.mText.Append( character );
- separatorChar.mStyle = styledText.mStyle;
-
- MarkupProcessor::StyledTextArray separatorWord;
- separatorWord.push_back( separatorChar );
-
- words.push_back( separatorWord );
- }
- else
- {
- MarkupProcessor::StyledText styledChar;
- styledChar.mStyle = styledText.mStyle;
- styledChar.mText.Append( character );
-
- // Add the character to the current word.
- word.push_back( styledChar );
- }
- }
-
- //Finally the last word need to be added.
- if( !word.empty() )
- {
- words.push_back( word );
- }
-}
-
-bool BeginsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& styledText )
-{
- for( MarkupProcessor::StyledTextArray::const_iterator it = styledText.begin(), endIt = styledText.end(); it != endIt; ++it )
- {
- const Text& text( (*it).mText );
-
- for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
- {
- Character::CharacterDirection direction = text[i].GetCharacterDirection();
- if( direction != Character::Neutral )
+ else
{
- return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak );
- }
- }
- }
-
- return false;
-}
-
-bool BeginsRightToLeftCharacter( const Text& text )
-{
- for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
- {
- Character::CharacterDirection direction = text[i].GetCharacterDirection();
- if( direction != Character::Neutral )
- {
- return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak );
- }
- }
-
- return false;
-}
+ // The character is not a new paragraph character.
-bool ContainsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& styledText )
-{
- for( MarkupProcessor::StyledTextArray::const_iterator it = styledText.begin(), endIt = styledText.end(); it != endIt; ++it )
- {
- const Text& text( (*it).mText );
+ // Append it to the paragraph's text
+ paragraph.Append( character );
- for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
- {
- Character::CharacterDirection direction = text[i].GetCharacterDirection();
- if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) )
- {
- return true;
+ // Add the style to the vector of styles for that paragraph.
+ TextStyle* style = new TextStyle( styledText.mStyle );
+ stylesForParagraph.PushBack( style );
}
}
}
- return false;
-}
-
-bool ContainsRightToLeftCharacter( const Dali::Text& text )
-{
- for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
- {
- Character::CharacterDirection direction = ( text[i] ).GetCharacterDirection();
- if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) )
- {
- return true;
- }
- }
-
- return false;
+ // This paragraph could be empty if the last character of the previous paragraph is a 'new paragraph' character
+ // and is the last of the text.
+ paragraphs.push_back( paragraph );
+ styles.push_back( stylesForParagraph );
}
-void ConvertBidirectionalText( const MarkupProcessor::StyledTextArray& line,
- MarkupProcessor::StyledTextArray& convertedText,
- std::vector<int>& logicalToVisualMap,
- std::vector<int>& visualToLogicalMap )
+void SplitInWords( const Dali::Text& paragraph,
+ Vector<std::size_t>& positions )
{
- // Clean vectors first. This function doesn't use any previous value.
- logicalToVisualMap.clear();
- visualToLogicalMap.clear();
- convertedText.clear();
-
- if( line.empty() )
- {
- // nothing to do if the line is empty.
- return;
- }
-
- // Get the plain text from the line to be reordered by the BiDirectional algorithm.
- std::string textToBeConverted;
- GetPlainString( line, textToBeConverted );
-
- const std::size_t stringSize = textToBeConverted.size();
-
- std::vector<FriBidiChar> logicalStrBuffer;
- std::vector<FriBidiChar> visualStrBuffer;
- // unicode length <= UTF-8 length in bytes (reserve one extra for terminator)
- // pad these buffers with 0's, as it's unclear what fribidi_log2vis does w.r.t.
- // the length of it's output content (appears the same as input content, and does
- // not seem to generate bidi marks i.e. FRIBIDI_CHAR_LRM/FRIBIDI_CHAR_RLM)
- logicalStrBuffer.resize( stringSize+1u, 0u );
- visualStrBuffer.resize( stringSize+1u, 0u );
- FriBidiChar *logicalStr( &logicalStrBuffer[0u] );
- FriBidiChar *visualStr( &visualStrBuffer[0u] );
-
- // Convert UTF-8 string to unicode string
- const std::size_t length = fribidi_charset_to_unicode( FRIBIDI_CHAR_SET_UTF8, textToBeConverted.c_str(), stringSize, logicalStr );
-
- if( 0u == length )
- {
- DALI_ASSERT_DEBUG( !"TextProcessor::ConvertBidirectionalText. Error when calling at fribidi_charset_to_unicode" );
+ const std::size_t length = paragraph.GetLength();
- return;
- }
-
- logicalToVisualMap.resize( length );
- visualToLogicalMap.resize( length );
-
- // Convert and reorder the string as specified by the Unicode Bidirectional Algorithm
- FriBidiCharType baseDirection = FRIBIDI_TYPE_ON;
- fribidi_boolean log2vis = fribidi_log2vis( logicalStr, length, &baseDirection, visualStr, &logicalToVisualMap[0u], &visualToLogicalMap[0u], NULL );
-
- if(log2vis)
- {
- // Convert the unicode string back to the UTF-8 string
- std::vector<char> bidiTextConverted;
-
- bidiTextConverted.resize( length * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
- // Currently Dali doesn't support this UTF-8 extension. Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
-
- fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, visualStr, length, &bidiTextConverted[0u] );
+ // Magic number: Let's soupose there is ~6 characters per word. Used to do less memory reallocation inside Vector.
+ const size_t magicNumberOfWords = ( length / 6u ) + 1u;
- textToBeConverted = &bidiTextConverted[0u];
+ // Find the positions of the new paragraph characters.
+ positions.Reserve( magicNumberOfWords );
- // After reorder the text, rebuild the text with the original styles is needed.
- // To assign the original style is needed to use the characterLogicalToVisualMap table.
- Text text( &bidiTextConverted[0u] );
-
- // Split the line in words.
- // Add the correct styles for the characters after they are reordered.
-
- for( size_t i = 0u; i < length; ++i )
- {
- const Character character( text[i] );
-
- MarkupProcessor::StyledText styledText;
- styledText.mText.Append( character );
- styledText.mStyle = line[visualToLogicalMap[i]].mStyle;
-
- convertedText.push_back( styledText );
- }
- }
+ // Find the position of all white spaces. A new paragraph character is also considered a white space but it doesn't matter at this point.
+ paragraph.Find( Text::WHITE_SPACE, 0u, length - 1u, positions );
}
/**
DALI_ASSERT_DEBUG( offset < text.size() );
// assume 1 Character per StyledText
- return text[offset].mText[0u].IsWhiteSpace();
+ return ( *( text.begin() + offset ) ).mText[0u].IsWhiteSpace();
}
void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end)
j++;
}
+ // If both markers at same position and is whitespace then word is a whitespace word
+ if ( i == j )
+ {
+ while(j < size && IsWhiteSpace(text, j))
+ {
+ j++;
+ }
+
+ while(i > 0 && IsWhiteSpace(text, i-1))
+ {
+ i--;
+ }
+ }
+
start = i;
end = j;
}
namespace TextProcessor
{
+// Forward declarations.
+struct BidirectionalParagraphInfo;
/**
* Splits the given text in paragraphs.
* @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but
* not necessarily the case for text in TextView)
*
- * @param [in] text The given text.
+ * @param [in] styledTextArray The given text.
* @param [out] paragraphs The text split in paragraphs.
+ * @param [out] styles The styles of each character of each paragraph.
*/
-void SplitInParagraphs( const MarkupProcessor::StyledTextArray& text,
- std::vector<MarkupProcessor::StyledTextArray>& paragraphs );
+void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray,
+ std::vector<Text>& paragraphs,
+ std::vector< Vector<TextStyle*> >& styles );
/**
- * Splits the given paragraph in words.
- *
- * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but
- * not necessarily the case for text in TextView)
+ * Finds the position of all word separators (currently white spaces and new paragraph characters '\n') in the given text.
*
* @param [in] paragraph The given paragraph.
- * @param [out] words The paragraph split in words.
- */
-void SplitInWords( const MarkupProcessor::StyledTextArray& paragraph,
- std::vector<MarkupProcessor::StyledTextArray>& words );
-
-/**
- * Whether the text begins with right-to-left (bidirectional) character.
- * @param [in] text The given text.
- * @return \e true if the text begins right-to-left character.
- */
-bool BeginsRightToLeftCharacter( const Text& text );
-
-/**
- * @copydoc BeginsRightToLeftCharacter( const Text& text )
- */
-bool BeginsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& text );
-
-/**
- * Whether the text contains any right-to-left (bidirectional) character.
- * @param [in] text The given text.
- * @return \e true if the text contains right-to-left character.
- */
-bool ContainsRightToLeftCharacter( const Text& text );
-
-/**
- * @copydoc ContainsRightToLeftCharacter( const Text& text )
- */
-bool ContainsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& text );
-
-/**
- * Convert the text as specified by the Unicode Bidirectional Algorithm.
- * The text is converted only if it is bidirectional.
- * @param[in] line The line of text to be converted.
- * @param[out] convertedText The text converted.
- * @param[out] logicalToVisualMap The character position map from the logical input text to the visual output text.
- * @param[out] visualToLogicalMap The character position map from the visual output text to the logical input text.
+ * @param [out] positions Positions within the paragraph of all word sepatators.
*/
- void ConvertBidirectionalText( const MarkupProcessor::StyledTextArray& line,
- MarkupProcessor::StyledTextArray& convertedText,
- std::vector<int>& logicalToVisualMap,
- std::vector<int>& visualToLogicalMap );
+void SplitInWords( const Text& paragraph,
+ Vector<std::size_t>& positions );
/**
* Finds the nearest word in a string to a specified
mPosition(),
mOffset(),
mGlyphActor(),
- mStyledText(),
mColorAlpha( 1.f ),
mGradientInfo( NULL ),
mIsVisible( true ),
- mSetText( true ),
- mSetStyle( true ),
- mIsColorGlyph( false )
+ mSetText( false ),
+ mSetStyle( false ),
+ mIsColorGlyph( false ),
+ mIsRightToLeft( false )
{
}
mPosition( character.mPosition ),
mOffset( character.mOffset ),
mGlyphActor( character.mGlyphActor ),
- mStyledText( character.mStyledText ),
mColorAlpha( character.mColorAlpha ),
mGradientInfo( ( NULL == character.mGradientInfo ) ? NULL : new GradientInfo( *character.mGradientInfo ) ), // Copies the gradient info.
mIsVisible( character.mIsVisible ),
mSetText( character.mSetText ),
mSetStyle( character.mSetStyle ),
- mIsColorGlyph( character.mIsColorGlyph )
+ mIsColorGlyph( character.mIsColorGlyph ),
+ mIsRightToLeft( character.mIsRightToLeft )
{
}
mOffset = character.mOffset;
mGlyphActor = character.mGlyphActor;
- mStyledText = character.mStyledText;
mColorAlpha = character.mColorAlpha;
mSetText = character.mSetText;
mSetStyle = character.mSetStyle;
mIsColorGlyph = character.mIsColorGlyph;
+ mIsRightToLeft = character.mIsRightToLeft;
return *this;
}
#include <dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h>
#include <dali-toolkit/internal/controls/text-view/split-by-word-policies.h>
#include <dali-toolkit/internal/controls/text-view/split-by-char-policies.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
#include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
#include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
#include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
{
- // Creates metadata with the Insert operation.
- TextViewProcessorMetadata metadata;
- metadata.mType = TextView::TextInserted;
- metadata.mPosition = position;
- metadata.mText = text;
+ std::string textStr;
+ MarkupProcessor::GetPlainString( text, textStr );
- // Store metadata.
- mTextViewProcessorOperations.push_back( metadata );
+ if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
+ TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
+ {
+ // Temporary fix. Creates the whole layout if there is rtl text.
- // Updates current styled text.
- mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
+ MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
+ textToSet.insert( textToSet.begin() + position, text.begin(), text.end() );
+ SetText( textToSet );
+ }
+ else
+ {
+ // Creates metadata with the Insert operation.
+ TextViewProcessorMetadata metadata;
+ metadata.mType = TextView::TextInserted;
+ metadata.mPosition = position;
+ metadata.mText = text;
- // Request to be relaid out
- RelayoutRequest();
+ // Store metadata.
+ mTextViewProcessorOperations.push_back( metadata );
- // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
- mRelayoutOperations = RELAYOUT_ALL;
+ // Updates current styled text.
+ mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
+
+ // Request to be relaid out
+ RelayoutRequest();
+
+ // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
+ mRelayoutOperations = RELAYOUT_ALL;
+ }
}
void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text )
{
- // Creates metadata with the Insert operation.
- TextViewProcessorMetadata metadata;
- metadata.mType = TextView::TextReplaced;
- metadata.mPosition = position;
- metadata.mNumberOfCharacters = numberOfCharacters;
- metadata.mText = text;
+ std::string textStr;
+ MarkupProcessor::GetPlainString( text, textStr );
- // Store metadata.
- mTextViewProcessorOperations.push_back( metadata );
+ if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
+ TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
+ {
+ // Temporary fix. Creates the whole layout if there is rtl text.
- // Updates current styled text.
- MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
- mCurrentStyledText.erase( it, it + numberOfCharacters );
- it = mCurrentStyledText.begin() + position;
- mCurrentStyledText.insert( it, text.begin(), text.end() );
+ // Updates current styled text.
+ MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
- // Request to be relaid out
- RelayoutRequest();
+ MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
+ textToSet.erase( it, it + numberOfCharacters );
+ it = textToSet.begin() + position;
+ textToSet.insert( it, text.begin(), text.end() );
- // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
- mRelayoutOperations = RELAYOUT_ALL;
+ SetText( textToSet );
+ }
+ else
+ {
+ // Creates metadata with the Insert operation.
+ TextViewProcessorMetadata metadata;
+ metadata.mType = TextView::TextReplaced;
+ metadata.mPosition = position;
+ metadata.mNumberOfCharacters = numberOfCharacters;
+ metadata.mText = text;
+
+ // Store metadata.
+ mTextViewProcessorOperations.push_back( metadata );
+
+ // Updates current styled text.
+ MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
+ mCurrentStyledText.erase( it, it + numberOfCharacters );
+ it = mCurrentStyledText.begin() + position;
+ mCurrentStyledText.insert( it, text.begin(), text.end() );
+
+ // Request to be relaid out
+ RelayoutRequest();
+
+ // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
+ mRelayoutOperations = RELAYOUT_ALL;
+ }
}
void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters )
{
- // Creates metadata with the Remove operation.
- TextViewProcessorMetadata metadata;
- metadata.mType = TextView::TextRemoved;
- metadata.mPosition = position;
- metadata.mNumberOfCharacters = numberOfCharacters;
+ if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
+ {
+ // Temporary fix. Creates the whole layout if there is rtl text.
- // Store metadata.
- mTextViewProcessorOperations.push_back( metadata );
+ // Updates current styled text.
+ MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
+ MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
+ textToSet.erase( it, it + numberOfCharacters );
- // Updates current styled text.
- MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
- mCurrentStyledText.erase( it, it + numberOfCharacters );
+ SetText( textToSet );
+ }
+ else
+ {
+ // Creates metadata with the Remove operation.
+ TextViewProcessorMetadata metadata;
+ metadata.mType = TextView::TextRemoved;
+ metadata.mPosition = position;
+ metadata.mNumberOfCharacters = numberOfCharacters;
- // Request to be relaid out
- RelayoutRequest();
+ // Store metadata.
+ mTextViewProcessorOperations.push_back( metadata );
- // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
- mRelayoutOperations = RELAYOUT_ALL;
+ // Updates current styled text.
+ MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
+ mCurrentStyledText.erase( it, it + numberOfCharacters );
+
+ // Request to be relaid out
+ RelayoutRequest();
+
+ // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
+ mRelayoutOperations = RELAYOUT_ALL;
+ }
}
std::string TextView::GetText() const
}
// Sets the new style to the ellipsize text
- if( !mLayoutParameters.mEllipsizeText.empty() )
+ // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors.
+ if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() )
{
- for( MarkupProcessor::StyledTextArray::iterator it = mLayoutParameters.mEllipsizeText.begin(), endIt = mLayoutParameters.mEllipsizeText.end(); it != endIt; ++it )
+ for( Vector<TextStyle*>::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(),
+ endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End();
+ it != endIt;
+ ++it )
{
- (*it).mStyle.Copy( style, mask );
+ (*it)->Copy( style, mask );
}
- SetEllipsizeText( mLayoutParameters.mEllipsizeText );
+ SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles );
}
}
MarkupProcessor::StyledTextArray styledText;
MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
+ // Creates the ellipsis layout info and sets the text and styles.
SetEllipsizeText( styledText );
}
void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
{
- mLayoutParameters.mEllipsizeText = ellipsizeText;
+ // Converts the styled text array into a Text and a vector of TextStyles.
+ Text text;
+ Vector<TextStyle*> styles;
+ for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it )
+ {
+ const MarkupProcessor::StyledText& styledText( *it );
- mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
+ text.Append( styledText.mText );
+ styles.PushBack( new TextStyle( styledText.mStyle ) );
+ }
- TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
- mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+ // Creates the ellipsis layout info and sets the text and styles.
+ SetEllipsizeText( text, styles );
+}
+
+void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles )
+{
+ // Sets the text and styles for the ellipsis text.
+ mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText;
+ mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles;
+
+ // Creates the ellipsis layout info.
+ CreateEllipsizeLayout();
// Request to be relaid out
RelayoutRequest();
std::string TextView::GetEllipsizeText() const
{
- std::string text;
- for( MarkupProcessor::StyledTextArray::const_iterator it = mLayoutParameters.mEllipsizeText.begin(), endIt = mLayoutParameters.mEllipsizeText.end(); it != endIt; ++it )
- {
- text.append( (*it).mText.GetText() );
- }
-
- return text;
+ return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText();
}
void TextView::GetTextLayoutInfo()
{
mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
}
-
}
}
}
mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
mLineJustification( Toolkit::TextView::Left ),
mLineHeightOffset( 0.f ),
- mEllipsizeText(),
mMarkUpEnabled( false )
{
- // Sets ellipsize text
- MarkupProcessor::StyledTextArray styledEllipsize;
- MarkupProcessor::GetStyledTextArray( std::string( "..." ), mEllipsizeText, false );
}
TextView::LayoutParameters::~LayoutParameters()
Toolkit::Alignment::Type alignmentType,
Toolkit::TextView::LineJustification lineJustification,
float lineHeightOffset,
- const std::string& ellipsizeText,
bool markUpEnabled )
: mMultilinePolicy( multilinePolicy ),
mWidthExceedPolicy( widthExceedPolicy ),
mVerticalAlignment(),
mLineJustification( lineJustification ),
mLineHeightOffset( lineHeightOffset ),
- mEllipsizeText(),
mMarkUpEnabled( markUpEnabled )
{
// Sets alignment
mHorizontalAlignment = horizontalAlignment;
mVerticalAlignment = verticalAlignment;
-
- // Sets ellipsize text
- MarkupProcessor::StyledTextArray styledEllipsize;
- MarkupProcessor::GetStyledTextArray( ellipsizeText, mEllipsizeText, mMarkUpEnabled );
}
TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
mVerticalAlignment( layoutParameters.mVerticalAlignment ),
mLineJustification( layoutParameters.mLineJustification ),
mLineHeightOffset( layoutParameters.mLineHeightOffset ),
- mEllipsizeText( layoutParameters.mEllipsizeText ),
mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
{
}
mVerticalAlignment = layoutParameters.mVerticalAlignment;
mLineJustification = layoutParameters.mLineJustification;
mLineHeightOffset = layoutParameters.mLineHeightOffset;
- mEllipsizeText = layoutParameters.mEllipsizeText;
mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
return *this;
static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
Toolkit::TextView::Left,
PointSize( 0.f ),
- std::string( "..." ),
false ),
mVisualParameters(),
mRelayoutData(),
mPreviousSnapshotModeEnabled( false ),
mMarkUpEnabled( false )
{
- TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
- mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+ // Creates the ellipsis layout info.
+ CreateEllipsizeLayout();
}
TextView::~TextView()
void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
{
- mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
- TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
- mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+ // Creates the ellipsis layout info.
+ CreateEllipsizeLayout();
SetText( mCurrentStyledText );
}
}
}
+ if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) ||
+ ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) )
+ {
+ if( mRelayoutOperations & RELAYOUT_ALIGNMENT )
+ {
+ // If the text of the alignment changes and a fade exceed policy is set,
+ // some characters may need new TextActor.
+ mRelayoutOperations = RELAYOUT_ALL;
+ }
+ }
+
// Remove glyph-actors from text-view
if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
{
return rootActor;
}
+void TextView::CreateEllipsizeLayout()
+{
+ // Creates the ellipsis layout info for the ellipsis text and styles.
+ mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
+ mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() );
+ TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText,
+ mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles,
+ mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+}
+
void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
{
bool newValue( propertyValue.Get<bool>() );
TextViewProcessorMetadataType mType; ///< Stores the type of operation.
std::size_t mPosition; ///< Character position within the text.
- std::size_t mNumberOfCharacters; ///< Number of characters to be removed/ replaced.
+ std::size_t mNumberOfCharacters; ///< Number of characters to be removed/replaced.
MarkupProcessor::StyledTextArray mText; ///< The new text.
TextStyle::Mask mStyleMask; ///< The style mask.
};
void SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText );
/**
+ * @copydoc SetEllipsizeText()
+ */
+ void SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles );
+
+ /**
* @copydoc GetEllipsizeText()
*/
std::string GetEllipsizeText() const;
Actor GetRootActor() const;
/**
+ * Creates the ellipsize text layout.
+ */
+ void CreateEllipsizeLayout();
+
+ /**
* Handle SetProperty for markup processing.
* @param[in] propertyValue The new property value.
*/
Toolkit::Alignment::Type alignment,
Toolkit::TextView::LineJustification lineJustification,
float lineHeightOffset,
- const std::string& ellipsizeText,
bool markUpEnabled );
/**
LayoutParameters& operator=( const LayoutParameters& layoutParameters );
Toolkit::TextView::MultilinePolicy mMultilinePolicy; ///< Stores the multiline policy.
- TextView::ExceedPolicy mExceedPolicy; ///< Stores a combination of both policies;
+ TextView::ExceedPolicy mExceedPolicy; ///< Stores a combination of both policies.
Toolkit::TextView::ExceedPolicy mWidthExceedPolicy; ///< Stores the text width exceed policy.
Toolkit::TextView::ExceedPolicy mHeightExceedPolicy; ///< Stores the text height exceed policy.
Toolkit::Alignment::Type mHorizontalAlignment; ///< Stores the horizontal alignment for the whole text.
Toolkit::Alignment::Type mVerticalAlignment; ///< Stores the vertical alignment for the whole text.
Toolkit::TextView::LineJustification mLineJustification; ///< Stores the line justification.
float mLineHeightOffset; ///< Line height offset to be addded to the font line height (measured in PointSize).
- MarkupProcessor::StyledTextArray mEllipsizeText; ///< Stores the ellipsize text
- bool mMarkUpEnabled:1; ///< Is markup string scanning enabled
+ bool mMarkUpEnabled:1; ///< Is markup string scanning enabled.
};
/**
};
/**
- * Temporary data used to calculate line justification.
- */
- struct LineJustificationInfo
- {
- TextViewProcessor::TextInfoIndices mIndices; ///< Indices to the first character of the new line.
- float mLineLength; ///< Length of the line (or portion of line).
- };
-
- /**
* The results of the relayout process.
*/
struct RelayoutData
Toolkit::TextView::CharacterLayoutInfoContainer mCharacterLayoutInfoTable; ///< Stores layout info per character sorted by the character's visual index.
Toolkit::TextView::LineLayoutInfoContainer mLines; ///< Stores an index to the first character of each line.
Size mTextSizeForRelayoutOption; ///< Stores the text size after relayout.
- std::vector<LineJustificationInfo> mLineJustificationInfo; ///< Stores justification info per line.
TextActorCache mTextActorCache; ///< Stores previously created text-actors to be reused.
};
#include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
#include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
#include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
namespace Dali
{
// Layout info.
/////////////////////
+void RightToLeftParagraphLayout::Clear()
+{
+ mWordsLayoutInfo.clear();
+ mText = Text();
+ mTextStyles.Clear();
+}
+
ParagraphLayoutInfo::ParagraphLayoutInfo()
: mSize(),
mAscender( 0.f ),
mLineHeightOffset( 0.f ),
+ mFirstCharacter( 0u ),
mNumberOfCharacters( 0u ),
- mWordsLayoutInfo()
+ mWordsLayoutInfo(),
+ mText(),
+ mTextStyles(),
+ mRightToLeftLayout( NULL ),
+ mBidirectionalParagraphInfo( NULL ),
+ mBidirectionalLinesInfo()
{
}
ParagraphLayoutInfo::~ParagraphLayoutInfo()
{
+ if( NULL != mRightToLeftLayout )
+ {
+ // TextStyle pointers are the same than the ones stored at ParagraphLayoutInfo::mTextStyles.
+ // Do not delete them, just clear the vector.
+ mRightToLeftLayout->mTextStyles.Clear();
+
+ delete mRightToLeftLayout;
+ }
+
+ // Clears text styles. It destroys TextStyle objects.
+ ClearStyles();
+
+ // Deletes the bidirectional info for the whole paragraph.
+ delete mBidirectionalParagraphInfo;
+
+ // Clears the bidirectional info for all lines. Destroys the BidirectionalLineInfo objects.
+ ClearBidirectionalInfo();
}
ParagraphLayoutInfo::ParagraphLayoutInfo( const ParagraphLayoutInfo& paragraph )
: mSize( paragraph.mSize ),
mAscender( paragraph.mAscender ),
mLineHeightOffset( paragraph.mLineHeightOffset ),
+ mFirstCharacter( paragraph.mFirstCharacter ),
mNumberOfCharacters( paragraph.mNumberOfCharacters ),
- mWordsLayoutInfo( paragraph.mWordsLayoutInfo )
+ mWordsLayoutInfo( paragraph.mWordsLayoutInfo ),
+ mText( paragraph.mText ),
+ mTextStyles(),
+ mRightToLeftLayout( NULL ),
+ // Copies bidirectional info for the whole paragraph.
+ mBidirectionalParagraphInfo( ( NULL == paragraph.mBidirectionalParagraphInfo ) ? NULL : new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo ) ),
+ mBidirectionalLinesInfo()
{
+ // Copies styles.
+ for( Vector<TextStyle*>::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it )
+ {
+ mTextStyles.PushBack( new TextStyle( *(*it) ) );
+ }
+
+ // Copies bidirectional info for each line.
+ for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it )
+ {
+ mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) );
+ }
}
ParagraphLayoutInfo& ParagraphLayoutInfo::operator=( const ParagraphLayoutInfo& paragraph )
mSize = paragraph.mSize;
mAscender = paragraph.mAscender;
mLineHeightOffset = paragraph.mLineHeightOffset;
+ mFirstCharacter = paragraph.mFirstCharacter;
mNumberOfCharacters = paragraph.mNumberOfCharacters;
mWordsLayoutInfo = paragraph.mWordsLayoutInfo;
+ mText = paragraph.mText;
- return *this;
-}
+ // If it has styles, destroy them.
+ ClearStyles();
-void CreateParagraphInfo( const MarkupProcessor::StyledTextArray& paragraph,
- TextView::RelayoutData& relayoutData,
- ParagraphLayoutInfo& paragraphLayoutInfo )
-{
- // Split the paragraph in words.
- // TODO: Proper RTL support.
- MarkupProcessor::StyledTextArray convertedParagraph;
- if( TextProcessor::ContainsRightToLeftCharacter( paragraph ) )
+ // Copies styles.
+ for( Vector<TextStyle*>::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it )
{
- // If the text is bidirectional, the characters will be converted and reordered
- // as specified by the Unicode Bidirectional Algorithm.
+ mTextStyles.PushBack( new TextStyle( *(*it) ) );
+ }
- // Reorders the paragraph and converts arabic glyphs (if any).
- TextProcessor::ConvertBidirectionalText( paragraph,
- convertedParagraph,
- relayoutData.mCharacterLogicalToVisualMap,
- relayoutData.mCharacterVisualToLogicalMap);
+ // Copies the paragraph's bidirectiona info.
+ if( NULL == paragraph.mBidirectionalParagraphInfo )
+ {
+ // The source doesn't have bidirectiona info. Deletes the current one.
+ delete mBidirectionalParagraphInfo;
+ mBidirectionalParagraphInfo = NULL;
}
else
{
- // No bidirectional text to process.
- convertedParagraph = paragraph;
-
- // Create trivial bidirectional map tables.
- std::size_t index = 0u;
- for( MarkupProcessor::StyledTextArray::const_iterator it = convertedParagraph.begin(), endIt = convertedParagraph.end(); it != endIt; ++it )
+ // The source has bidirectional info.
+ if( NULL != mBidirectionalParagraphInfo )
{
- const MarkupProcessor::StyledText& styledText( *it );
-
- for( std::size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i )
- {
- relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index );
- relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index );
- ++index;
- }
+ // It it has, copy to it.
+ *mBidirectionalParagraphInfo = *paragraph.mBidirectionalParagraphInfo;
+ }
+ else
+ {
+ // If it doesn't have, create a new one.
+ mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo );
}
}
- // Split the paragraph in words
- std::vector<MarkupProcessor::StyledTextArray> words;
- TextProcessor::SplitInWords( convertedParagraph, words );
+ // If it has bidirectiona info per line, destroy them.
+ ClearBidirectionalInfo();
- // if last word has a new paragraph separator, create a new word.
- if( !words.empty() )
+ // Copies bidirectional info per line.
+ for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it )
{
- MarkupProcessor::StyledTextArray& word( *( words.end() - 1u ) );
- if( word.size() > 1u )
- {
- // do nothing if the word has only one character.
- MarkupProcessor::StyledText& styledText( *( word.end() - 1u ) );
- if( !styledText.mText.IsEmpty() )
- {
- const std::size_t length = styledText.mText.GetLength();
- if( styledText.mText[length-1u].IsNewLine() )
- {
- // Last character of this word is a new paragraph character.
+ mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) );
+ }
- // Remove paragraph separator character from current word.
- styledText.mText.Remove( length - 1u, 1u );
+ return *this;
+}
- // Create a new word with the paragraph separator character.
- MarkupProcessor::StyledText newParagraphText( Text( styledText.mText[length-1u] ), styledText.mStyle );
+void ParagraphLayoutInfo::ClearBidirectionalInfo()
+{
+ // Destroys the bidirectional infor per line.
+ for( Vector<TextProcessor::BidirectionalLineInfo*>::Iterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it )
+ {
+ delete *it;
+ }
+ mBidirectionalLinesInfo.Clear();
+}
- MarkupProcessor::StyledTextArray newParagraphWord;
- newParagraphWord.push_back( newParagraphText );
+void ParagraphLayoutInfo::ClearStyles()
+{
+ // Destroys the styles.
+ for( Vector<TextStyle*>::Iterator it = mTextStyles.Begin(), endIt = mTextStyles.End(); it != endIt; ++it )
+ {
+ delete *it;
+ }
+ mTextStyles.Clear();
+}
- words.push_back( newParagraphWord );
- }
- }
- }
+void CreateParagraphInfo( TextView::RelayoutData& relayoutData,
+ ParagraphLayoutInfo& paragraphLayoutInfo )
+{
+ if( TextProcessor::ContainsRightToLeftCharacter( paragraphLayoutInfo.mText ) )
+ {
+ // If the text is bidirectional, the characters will be converted and reordered
+ // as specified by the Unicode Bidirectional Algorithm.
+
+ paragraphLayoutInfo.mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo();
+
+ TextProcessor::ProcessBidirectionalText( paragraphLayoutInfo.mText, paragraphLayoutInfo.mBidirectionalParagraphInfo );
}
- std::string lastCharacterFont; // Keeps the font used by the last character. It's used to set the font to a word separator.
+ // Split the paragraph in words. It retrieves the positions of white spaces and the last '\n' if there is one.
+ Vector<std::size_t> positions;
+ TextProcessor::SplitInWords( paragraphLayoutInfo.mText, positions );
- // Traverse all words.
- for( std::vector<MarkupProcessor::StyledTextArray>::const_iterator wordIt = words.begin(), wordEndIt = words.end(); wordIt != wordEndIt; ++wordIt )
- {
- const MarkupProcessor::StyledTextArray& word( *wordIt );
+ const std::size_t lastCharacterIndex = paragraphLayoutInfo.mText.GetLength() - 1u;
+ const bool isLastCharacterParagraphSeparator = paragraphLayoutInfo.mText.IsNewLine( lastCharacterIndex );
- // Data structures for the new word.
- WordLayoutInfo wordLayoutInfo;
+ // The number of words is ~the number of white spaces found + 1u.
+ // White spaces are also words.
+ // New line characters are also white spaces. If the last character is a white space the +1 is not needed.
+ const std::size_t numberOfWords = 2u * positions.Count() + ( isLastCharacterParagraphSeparator ? 0u : 1u );
- CreateWordTextInfo( word,
- wordLayoutInfo );
+ // Reserve space for all the words.
+ paragraphLayoutInfo.mWordsLayoutInfo.resize( numberOfWords, WordLayoutInfo() );
+
+ // Traverses all positions creating and setting all character layout info objects to every word.
+ std::size_t wordIndex = 0u;
+ Vector<std::size_t>::ConstIterator positionIt = positions.Begin();
+ Vector<std::size_t>::ConstIterator positionEndIt = positions.End();
+ std::size_t from = 0u;
+ for( std::size_t positionIndex = 0u, size = positions.Count() + 1u; positionIndex < size; ++positionIndex )
+ {
+ const bool isEndPosition = positionIt == positionEndIt;
+ const std::size_t to = isEndPosition ? lastCharacterIndex + 1u : *positionIt;
- // White space's size could be different depending on the type of font. It's important to use the same font than the previous character to
- // avoid 'jumps' of characters when there is a switch between one text-actor per character and one text-actor per line and/or style.
- if( WordSeparator == wordLayoutInfo.mType )
+ if( from < to )
{
- // If current word is a word separator (white space) then the font of the last character is set.
- for( CharacterLayoutInfoContainer::iterator characterIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), characterEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
- characterIt != characterEndIt;
- ++characterIt )
- {
- CharacterLayoutInfo& characterLayout( *characterIt );
+ // The word is not a white space.
+ WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex );
+ ++wordIndex;
+ // Sets the index within the paragraph to the first character of the word.
+ wordLayoutInfo.mFirstCharacter = from;
+ // Creates character layout info objects.
+ wordLayoutInfo.mCharactersLayoutInfo.resize( ( to - from ), CharacterLayoutInfo() );
+ }
- characterLayout.mStyledText.mStyle.SetFontName( lastCharacterFont );
- }
+ if( !isEndPosition )
+ {
+ // Create a word for the white space.
+ WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex );
+ ++wordIndex;
+ // Sets the index within the paragraph to the white space.
+ wordLayoutInfo.mFirstCharacter = to;
+ wordLayoutInfo.mType = WordSeparator;
+
+ CharacterLayoutInfo characterLayoutInfo;
+ wordLayoutInfo.mCharactersLayoutInfo.push_back( characterLayoutInfo );
+ }
+
+ from = to + 1u;
+
+ if( !isEndPosition )
+ {
+ // next white space position.
+ ++positionIt;
}
else
{
- // kepps the font of the last character.
- if( !wordLayoutInfo.mCharactersLayoutInfo.empty() )
+ // All white space positiona have been traversed.
+ // It may be some extra words. i.e if the text is \n.
+ // Erase them.
+ paragraphLayoutInfo.mWordsLayoutInfo.erase( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex, paragraphLayoutInfo.mWordsLayoutInfo.end() );
+
+ // Check if the last character is a new paragraph character.
+ if( isLastCharacterParagraphSeparator )
{
- lastCharacterFont = ( *( wordLayoutInfo.mCharactersLayoutInfo.end() - 1u ) ).mStyledText.mStyle.GetFontName();
+ ( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ).mType = ParagraphSeparator;
}
}
+ }
- // Update the max word width figure.
- relayoutData.mTextLayoutInfo.mMaxWordWidth = std::max( relayoutData.mTextLayoutInfo.mMaxWordWidth, wordLayoutInfo.mSize.width );
+ // Traverse all words and fill the layout info.
+ for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it )
+ {
+ WordLayoutInfo& wordLayoutInfo( *it );
+
+ CreateWordTextInfo( paragraphLayoutInfo.mText,
+ paragraphLayoutInfo.mTextStyles,
+ wordLayoutInfo );
// Update layout info for the current paragraph.
+ UpdateSize( paragraphLayoutInfo.mSize, wordLayoutInfo.mSize );
paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, wordLayoutInfo.mAscender );
paragraphLayoutInfo.mNumberOfCharacters += wordLayoutInfo.mCharactersLayoutInfo.size();
- UpdateSize( paragraphLayoutInfo.mSize, wordLayoutInfo.mSize );
- // Add the word to the current paragraph.
- paragraphLayoutInfo.mWordsLayoutInfo.push_back( wordLayoutInfo );
+ // Update the max word width figure.
+ relayoutData.mTextLayoutInfo.mMaxWordWidth = std::max( relayoutData.mTextLayoutInfo.mMaxWordWidth, wordLayoutInfo.mSize.width );
} // end of words
}
void UpdateLayoutInfo( ParagraphLayoutInfo& paragraphLayoutInfo, float lineHeightOffset )
{
// Update layout info.
+
+ // Initialize members to be updated.
paragraphLayoutInfo.mSize = Size::ZERO;
paragraphLayoutInfo.mAscender = 0.f;
paragraphLayoutInfo.mNumberOfCharacters = 0u;
+
+ // Traverses all words.
for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
it != endIt;
++it )
{
WordLayoutInfo& word( *it );
+ // Sets the index within the paragraph to the first character of the word.
+ word.mFirstCharacter = paragraphLayoutInfo.mNumberOfCharacters;
+
+ // Updates the paragraph's size.
UpdateSize( paragraphLayoutInfo.mSize, word.mSize );
+
+ // Updates the paragraph's max asender.
paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, word.mAscender );
+
+ // Updates the paragraph's number of characters.
paragraphLayoutInfo.mNumberOfCharacters += word.mCharactersLayoutInfo.size();
}
+ // Sets the line height offset.
paragraphLayoutInfo.mSize.height += lineHeightOffset;
paragraphLayoutInfo.mLineHeightOffset = lineHeightOffset;
}
// 6) update layout info of the first paragraph.
UpdateLayoutInfo( firstParagraphLayoutInfo, lineHeightOffset );
+
+ // 7) Split text and styles.
+
+ // Copies the whole text to the last part of the paragraph.
+ lastParagraphLayoutInfo.mText = firstParagraphLayoutInfo.mText;
+
+ // Removes from the first part of the paragraph the text that goes to the last part.
+ firstParagraphLayoutInfo.mText.Remove( indices.mCharacterParagraphIndex, firstParagraphLayoutInfo.mText.GetLength() - indices.mCharacterParagraphIndex );
+
+ // Removes from the last part of the paragraph the text that remains in the first part.
+ lastParagraphLayoutInfo.mText.Remove( 0u, indices.mCharacterParagraphIndex );
+
+ // Sets the character's styles for the last part of the paragraph.
+ lastParagraphLayoutInfo.mTextStyles.Insert( lastParagraphLayoutInfo.mTextStyles.End(),
+ firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex,
+ firstParagraphLayoutInfo.mTextStyles.End() );
+
+ // Removes the character's styles that go to the last part of the paragraph.
+ firstParagraphLayoutInfo.mTextStyles.Erase( firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex,
+ firstParagraphLayoutInfo.mTextStyles.End() );
}
void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo,
// Merge layout info
// Insert the layout of the words.
+ const std::size_t numberOfWords = firstParagraphLayoutInfo.mWordsLayoutInfo.size();
firstParagraphLayoutInfo.mWordsLayoutInfo.insert( firstParagraphLayoutInfo.mWordsLayoutInfo.end(),
lastParagraphLayoutInfo.mWordsLayoutInfo.begin() + index, lastParagraphLayoutInfo.mWordsLayoutInfo.end() );
+ // Increase the index of the first character of each inserted word.
+ for( WordLayoutInfoContainer::iterator it = firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + numberOfWords, endIt = firstParagraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it )
+ {
+ WordLayoutInfo& word( *it );
+ word.mFirstCharacter += firstParagraphLayoutInfo.mNumberOfCharacters;
+ }
+
// Update the size and other layout parameters.
UpdateSize( firstParagraphLayoutInfo.mSize, lastParagraphLayoutInfo.mSize );
firstParagraphLayoutInfo.mAscender = std::max( firstParagraphLayoutInfo.mAscender, lastParagraphLayoutInfo.mAscender );
firstParagraphLayoutInfo.mLineHeightOffset = std::max( firstParagraphLayoutInfo.mLineHeightOffset, lastParagraphLayoutInfo.mLineHeightOffset );
firstParagraphLayoutInfo.mNumberOfCharacters += lastParagraphLayoutInfo.mNumberOfCharacters;
+
+ // Merge text and styles.
+ firstParagraphLayoutInfo.mText.Append( lastParagraphLayoutInfo.mText );
+ for( Vector<TextStyle*>::ConstIterator it = lastParagraphLayoutInfo.mTextStyles.Begin(), endIt = lastParagraphLayoutInfo.mTextStyles.End(); it != endIt; ++it )
+ {
+ firstParagraphLayoutInfo.mTextStyles.PushBack( new TextStyle( *(*it) ) );
+ }
}
WordLayoutInfo GetLastWordLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo )
/**
* Creates a data structure with info to layout the paragraph, and data structures with useful info to modify the layout data structure if characters are added or removed.
*
- * @param[in] paragraph The styled paragraph.
* @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text).
* @param[out] paragraphLayoutInfo Layout info for the whole paragraph.
*/
-void CreateParagraphInfo( const MarkupProcessor::StyledTextArray& line,
- TextView::RelayoutData& relayoutData,
+void CreateParagraphInfo( TextView::RelayoutData& relayoutData,
ParagraphLayoutInfo& paragraphLayoutInfo );
/**
#include <dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h>
// INTERNAL INCLUDES
-#include <dali/public-api/actors/text-actor.h>
+#include <dali-toolkit/internal/controls/text-view/text-view-processor-types.h>
namespace Dali
{
void dbgPrint( const WordLayoutInfo& word )
{
- for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end();
- characterIt != endCharacterIt;
- ++characterIt )
- {
- const CharacterLayoutInfo& character( *characterIt );
-
- std::cout << "[" << character.mSize << std::endl;
- std::cout << " ascender " << character.mAscender << std::endl;
-
- TextActor textActor = TextActor::DownCast( character.mGlyphActor );
- if( textActor )
- {
- std::cout << "[" << textActor.GetText() << "]";
- }
- else
- {
- std::cout << "[ImageActor]" << std::endl;
- }
- std::cout << "{" << character.mStyledText.mText.GetText() << "}";
- }
- std::cout << " size " << word.mSize << std::endl;
- std::cout << " ascender " << word.mAscender << std::endl;
- std::cout << " num char " << word.mCharactersLayoutInfo.size() << std::endl;
- std::cout << " type ";
+ std::cout << " size " << word.mSize << std::endl;
+ std::cout << " ascender " << word.mAscender << std::endl;
+ std::cout << " type ";
switch( word.mType )
{
case NoSeparator:
break;
}
}
+ std::cout << " first char " << word.mFirstCharacter << std::endl;
+ std::cout << " num char " << word.mCharactersLayoutInfo.size() << std::endl;
+ for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end();
+ characterIt != endCharacterIt;
+ ++characterIt )
+ {
+ const CharacterLayoutInfo& character( *characterIt );
+
+ std::cout << "[" << character.mSize << std::endl;
+ std::cout << " ascender " << character.mAscender << std::endl;
+ }
}
void dbgPrint( const ParagraphLayoutInfo& paragraph )
{
std::cout << "< ";
+ std::cout << " text : [" << paragraph.mText.GetText() << "]" << std::endl;
+ std::cout << " number of styles : " << paragraph.mTextStyles.Count() << std::endl;
std::cout << paragraph.mSize;
for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin(), endWordIt = paragraph.mWordsLayoutInfo.end();
wordIt != endWordIt;
std::cout << " paragraph : " << indices.mParagraphIndex << std::endl;
std::cout << " word : " << indices.mWordIndex << std::endl;
std::cout << " char : " << indices.mCharacterIndex << std::endl;
+ std::cout << " char in paragraph : " << indices.mCharacterParagraphIndex << std::endl;
}
void dbgPrint( const MarkupProcessor::StyledTextArray& textArray )
}
}
-void dbgPrintText( const WordLayoutInfo& word )
-{
- for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end();
- characterIt != endCharacterIt;
- ++characterIt )
- {
- const CharacterLayoutInfo& character( *characterIt );
-
- std::cout << character.mStyledText.mText.GetText();
- }
-}
-
} // namespace TextViewProcessor
} // namespace Internal
*/
// INTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
#include <dali-toolkit/public-api/markup-processor/markup-processor.h>
-#include <dali-toolkit/internal/controls/text-view/text-view-processor-types.h>
+#include <dali/integration-api/debug.h>
namespace Dali
{
+//Forward declarations.
+class TextStyle;
+
namespace Toolkit
{
namespace TextViewProcessor
{
+//Forward declarations.
+struct WordLayoutInfo;
+struct ParagraphLayoutInfo;
+struct TextLayoutInfo;
+struct TextInfoIndices;
+
#if defined(DEBUG_ENABLED)
extern Debug::Filter* gTextViewProcessorLogFilter;
#endif
void dbgPrint( const TextInfoIndices& indices );
void dbgPrint( const MarkupProcessor::StyledTextArray& text );
-void dbgPrintText( const WordLayoutInfo& word );
-
} // namespace TextViewProcessor
} // namespace Internal
return ( character.IsNewLine() ? ParagraphSeparator : ( character.IsWhiteSpace() ? WordSeparator : NoSeparator ) );
}
-void ChooseFontFamilyName( MarkupProcessor::StyledText& text )
+void ChooseFontFamilyName( const Character& character, TextStyle& style )
{
DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::ChooseFontFamilyName\n" );
- DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " input font name: [%s]\n", text.mStyle.GetFontName().c_str() );
+ DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " input font name: [%s]\n", style.GetFontName().c_str() );
bool userDefinedFontFamilyName = false;
// First check if there is a font defined in the style and it supports the given text.
- if( !text.mStyle.GetFontName().empty() )
+ if( !style.GetFontName().empty() )
{
- const FontParameters fontParams( text.mStyle.GetFontName(), text.mStyle.GetFontStyle() , text.mStyle.GetFontPointSize() );
+ const FontParameters fontParams( style.GetFontName(), style.GetFontStyle() , style.GetFontPointSize() );
const Font font = Font::New( fontParams );
- if( !font.IsDefaultSystemFont() && font.AllGlyphsSupported( text.mText ) )
+ if( !font.IsDefaultSystemFont() && font.AllGlyphsSupported( character ) )
{
userDefinedFontFamilyName = true;
}
const Font defaultSystemFont = Font::New();
// At this point no font is set or doesn't support the given text.
- if( !defaultSystemFont.AllGlyphsSupported( text.mText ) )
+ if( !defaultSystemFont.AllGlyphsSupported( character ) )
{
// If the default system font doesn't support the given text,
// an appropiate font is selected.
- text.mStyle.SetFontName( Font::GetFamilyForText( text.mText ) );
+ style.SetFontName( Font::GetFamilyForText( character ) );
// @TODO Font::GetFamilyForText() should return font family and font style.
}
else
{
// All characters are supported with default font, so use it
- text.mStyle.SetFontName( "" );
+ style.SetFontName( "" );
}
}
- DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " output font name: [%s]\n", text.mStyle.GetFontName().c_str() );
+ DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " output font name: [%s]\n", style.GetFontName().c_str() );
DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::ChooseFontFamilyName\n" );
}
++paragraphIt, ++indices.mParagraphIndex )
{
const ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt );
+ std::size_t currentCharactersTraversed = currentIndex; // stores how many characters have been traversed until this paragraph.
if( currentIndex + paragraphLayoutInfo.mNumberOfCharacters > index )
{
{
// The character is in this word
indices.mCharacterIndex = index - currentIndex;
+ indices.mCharacterParagraphIndex = index - currentCharactersTraversed;
found = true;
}
else
TextSeparatorType GetTextSeparatorType( const Character& character );
/**
- * Choose a suitable font family name for the given styled text.
+ * Choose a suitable font family name for the given character.
*
- * It may modify the text-style of the given text by setting a suitable font-family.
+ * It may modify the text-style of the given character by setting a suitable font-family.
*
- * @param[in,out] text Text with style.
+ * @param[in] character The character.
+ * @param[in,out] style The style of the character.
*/
-void ChooseFontFamilyName( MarkupProcessor::StyledText& text );
+void ChooseFontFamilyName( const Character& character, TextStyle& style );
/**
* Retrieves the line, word and character indices for the given global character's index.
// INTERNAL INCLUDES
#include <dali/public-api/actors/renderable-actor.h>
-#include <dali-toolkit/public-api/markup-processor/markup-processor.h>
+#include <dali/public-api/text/text.h>
namespace Dali
{
+class TextStyle;
+
namespace Toolkit
{
namespace Internal
{
+namespace TextProcessor
+{
+// Forward declarations.
+struct BidirectionalParagraphInfo;
+struct BidirectionalLineInfo;
+} // namespace TextProcessor
+
namespace TextViewProcessor
{
std::size_t mParagraphIndex; ///< The paragraph index within the text.
std::size_t mWordIndex; ///< The word index within the paragraph.
std::size_t mCharacterIndex; ///< The character index within the word.
+ std::size_t mCharacterParagraphIndex; ///< The character index within the paragraph.
};
/**
CharacterLayoutInfo& operator=( const CharacterLayoutInfo& character );
// Metrics of the glyph.
- Size mSize; ///< Height of the font and advance (the horizontal distance from the origin of the current character and the next one).
- float mBearing; ///< Vertical distance from the baseline to the top of the glyph's boundary box.
- float mAscender; ///< Distance from the base line to the top of the line.
- float mUnderlineThickness; ///< The underline's thickness.
- float mUnderlinePosition; ///< The underline's position.
+ Size mSize; ///< Height of the font and advance (the horizontal distance from the origin of the current character and the next one).
+ float mBearing; ///< Vertical distance from the baseline to the top of the glyph's boundary box.
+ float mAscender; ///< Distance from the base line to the top of the line.
+ float mUnderlineThickness; ///< The underline's thickness.
+ float mUnderlinePosition; ///< The underline's position.
// Position and alignment offset. It depends on the lay-out.
- Vector3 mPosition; ///< Position within the text-view
- Vector2 mOffset; ///< Alignment and justification offset.
-
- RenderableActor mGlyphActor; ///< Handle to a text-actor.
- MarkupProcessor::StyledText mStyledText; ///< Stores the text and its style.
- float mColorAlpha; ///< Alpha component for the initial text color when text is faded.
- GradientInfo* mGradientInfo; ///< Stores gradient info.
-
- bool mIsVisible:1; ///< Whether the text-actor is visible.
- bool mSetText:1; ///< Whether a new text needs to be set in the text-actor.
- bool mSetStyle:1; ///< Whether a new style needs to be set in the text-actor.
- bool mIsColorGlyph:1; ///< Whether this character is an emoticon.
+ Vector3 mPosition; ///< Position within the text-view
+ Vector2 mOffset; ///< Alignment and justification offset.
+
+ RenderableActor mGlyphActor; ///< Handle to a text-actor.
+ float mColorAlpha; ///< Alpha component for the initial text color when text is faded.
+ GradientInfo* mGradientInfo; ///< Stores gradient info.
+
+ bool mIsVisible:1; ///< Whether the text-actor is visible.
+ bool mSetText:1; ///< Whether a new text needs to be set in the text-actor.
+ bool mSetStyle:1; ///< Whether a new style needs to be set in the text-actor.
+ bool mIsColorGlyph:1; ///< Whether this character is an emoticon.
+ bool mIsRightToLeft:1; ///< Whether this character is right to left.
};
typedef std::vector<CharacterLayoutInfo> CharacterLayoutInfoContainer;
Size mSize; ///< Size of the word.
float mAscender; ///< Max of all ascenders of all characters.
TextSeparatorType mType; ///< Whether this word is a word separator, a line separator or is not a separator.
+ std::size_t mFirstCharacter; ///< Index to the first character of the word within the paragraph.
CharacterLayoutInfoContainer mCharactersLayoutInfo; ///< Layout info for all characters.
};
typedef std::vector<WordLayoutInfo> WordLayoutInfoContainer;
/**
+ * Stores the reordered layout for right to left text.
+ */
+struct RightToLeftParagraphLayout
+{
+ RightToLeftParagraphLayout()
+ : mWordsLayoutInfo(),
+ mText(),
+ mTextStyles(),
+ mPreviousLayoutCleared( false )
+ {
+ }
+
+ WordLayoutInfoContainer mWordsLayoutInfo; ///< Layout info for all words.
+ Text mText; ///< Stores the text.
+ Vector<TextStyle*> mTextStyles; ///< Stores the style per each character.
+ bool mPreviousLayoutCleared:1; ///< Whether the previous right to left layout has been cleared.
+
+ /**
+ * Clears the word layout vector, the text and the vector of styles.
+ */
+ void Clear();
+};
+
+/**
* Layout information for a paragraph.
*/
struct ParagraphLayoutInfo
/**
* Default destructor.
*
- * Clears all words.
+ * Clears all words, deletes all text styles, the paragraph bidirectional info and all bidirectional infor for each line.
*/
~ParagraphLayoutInfo();
*/
ParagraphLayoutInfo& operator=( const ParagraphLayoutInfo& paragraph );
+ /**
+ * Deletes the bidirectional info for each line.
+ */
+ void ClearBidirectionalInfo();
+
+private:
+
+ /**
+ * Deletes all text styles.
+ */
+ void ClearStyles();
+
+public:
Size mSize; ///< Size of the paragraph.
float mAscender; ///< Max of all ascenders of all words.
float mLineHeightOffset; ///< Line height offset.
+ std::size_t mFirstCharacter; ///< Index to the first character of the paragraph.
std::size_t mNumberOfCharacters; ///< Stores the number of characters.
WordLayoutInfoContainer mWordsLayoutInfo; ///< Layout info for all words.
+ Text mText; ///< Stores the text.
+ Vector<TextStyle*> mTextStyles; ///< Stores the style per each character.
+ RightToLeftParagraphLayout* mRightToLeftLayout; ///< Stores the reordered layout for the paragraph.
+ TextProcessor::BidirectionalParagraphInfo* mBidirectionalParagraphInfo; ///< Contains bidirectional info for the whole paragraph. Set to NULL if the paragraph has left to right characters only.
+ Vector<TextProcessor::BidirectionalLineInfo*> mBidirectionalLinesInfo; ///< Contains bidirectional info for each laid-out line.
};
typedef std::vector<ParagraphLayoutInfo> ParagraphLayoutInfoContainer;
TextLayoutInfo();
/**
+ * Defualt destructor.
+ *
+ * Clears the paragraph vector, the ellipsis text and deletes all ellipsis styles.
+ */
+ ~TextLayoutInfo();
+
+ /**
* Copy constructor.
*/
TextLayoutInfo( const TextLayoutInfo& text );
*/
TextLayoutInfo& operator=( const TextLayoutInfo& text );
+private:
+ /**
+ * Deletes all the ellipsis text styles.
+ */
+ void ClearStyles();
+
+public:
Size mWholeTextSize; ///< width and height of the whole text.
float mMaxWordWidth; ///< maximum width between all words.
float mMaxItalicsOffset; ///< When rendering text-view in offscreen an extra width offset is needed to prevent italic characters to be cut if they are in the right edge.
std::size_t mNumberOfCharacters; ///< Stores the number of characters.
ParagraphLayoutInfoContainer mParagraphsLayoutInfo; ///< Layout information for all paragraphs.
WordLayoutInfo mEllipsizeLayoutInfo; ///< Layout information for the ellipsize text.
+ Dali::Text mEllipsisText; ///< The ellipsis text.
+ Vector<TextStyle*> mEllipsisTextStyles; ///< Stores the style per each character of the ellipsis text.
};
} // namespace TextViewProcessor
#include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
#include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
#include <dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h>
#include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
#include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
namespace Dali
{
TextInfoIndices::TextInfoIndices()
: mParagraphIndex( 0u ),
mWordIndex( 0u ),
- mCharacterIndex( 0u )
+ mCharacterIndex( 0u ),
+ mCharacterParagraphIndex( 0u )
{
}
const std::size_t characterIndex )
: mParagraphIndex( paragraphIndex ),
mWordIndex( wordIndex ),
- mCharacterIndex( characterIndex )
+ mCharacterIndex( characterIndex ),
+ mCharacterParagraphIndex( 0u )
{
}
{
return ( ( mParagraphIndex == indices.mParagraphIndex ) &&
( mWordIndex == indices.mWordIndex ) &&
- ( mCharacterIndex == indices.mCharacterIndex ) );
+ ( mCharacterIndex == indices.mCharacterIndex ) &&
+ ( mCharacterParagraphIndex == indices.mCharacterParagraphIndex ) );
}
/////////////////////
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 )
mMaxItalicsOffset( text.mMaxItalicsOffset ),
mNumberOfCharacters( text.mNumberOfCharacters ),
mParagraphsLayoutInfo( text.mParagraphsLayoutInfo ),
- mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo )
+ mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo ),
+ mEllipsisText( text.mEllipsisText ),
+ mEllipsisTextStyles()
{
+ for( Vector<TextStyle*>::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it )
+ {
+ mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) );
+ }
}
TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text )
mNumberOfCharacters = text.mNumberOfCharacters;
mParagraphsLayoutInfo = text.mParagraphsLayoutInfo;
mEllipsizeLayoutInfo = text.mEllipsizeLayoutInfo;
- }
+ mEllipsisText = text.mEllipsisText;
+ ClearStyles();
+
+ for( Vector<TextStyle*>::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it )
+ {
+ mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) );
+ }
+ }
return *this;
}
+void TextLayoutInfo::ClearStyles()
+{
+ for( Vector<TextStyle*>::Iterator it = mEllipsisTextStyles.Begin(), endIt = mEllipsisTextStyles.End(); it != endIt; ++it )
+ {
+ delete *it;
+ }
+ mEllipsisTextStyles.Clear();
+}
+
/////////////////////////////////////////////////////////////////////////////////////////////
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<TextActor> textActors;
}
// 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<TextStyle*> 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<MarkupProcessor::StyledTextArray> 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<Text> paragraphs;
+ std::vector< Vector<TextStyle*> > 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<MarkupProcessor::StyledTextArray>::const_iterator paragraphIt = paragraphs.begin(), paragraphEndIt = paragraphs.end(); paragraphIt != paragraphEndIt; ++paragraphIt )
+ std::size_t paragraphIndex = 0u;
+ std::vector<Text>::iterator paragraphIt, paragraphEndIt;
+ std::vector< Vector<TextStyle*> >::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<TextStyle*>& 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 );
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 )
// * 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:
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.
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 )
{
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();
+ }
}
}
}
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 )
// 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() );
// 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<TextStyle*>::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)
// 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<TextStyle*>::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;
// 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<TextStyle*>::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,
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 )
{
ParagraphLayoutInfo& paragraph( *paragraphIt );
+ std::size_t index = 0u;
+ for( Vector<TextStyle*>::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 )
{
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
const std::string EMOJI_FONT_NAME( "SamsungEmoji" ); // Emoticons font family name.
-/**
- * Updates the word size and ascender.
- *
- * It's called after deleting some characters.
- *
- * @param[in] wordLayout The word layout info.
- */
-void UpdateLayoutInfo( WordLayoutInfo& wordLayout )
-{
- // Initialize layout info for the whole word.
- wordLayout.mSize = Size::ZERO;
- wordLayout.mAscender = 0.f;
-
- // Traverse the character layout info to update the word layout.
- for( CharacterLayoutInfoContainer::iterator layoutIt = wordLayout.mCharactersLayoutInfo.begin(), layoutEndIt = wordLayout.mCharactersLayoutInfo.end();
- layoutIt != layoutEndIt;
- ++layoutIt )
- {
- // Layout info for the current character.
- CharacterLayoutInfo& layoutInfo( *layoutIt );
-
- // Update layout info for the current word.
- UpdateSize( wordLayout.mSize, layoutInfo.mSize );
- wordLayout.mAscender = std::max( wordLayout.mAscender, layoutInfo.mAscender );
- }
-}
-
} // namespace
/////////////////////
: mSize(),
mAscender( 0.f ),
mType( NoSeparator ),
+ mFirstCharacter( 0u ),
mCharactersLayoutInfo()
{
}
: mSize( word.mSize ),
mAscender( word.mAscender ),
mType( word.mType ),
+ mFirstCharacter( word.mFirstCharacter ),
mCharactersLayoutInfo( word.mCharactersLayoutInfo )
{
}
mSize = word.mSize;
mAscender = word.mAscender;
mType = word.mType;
+ mFirstCharacter = word.mFirstCharacter;
mCharactersLayoutInfo = word.mCharactersLayoutInfo;
return *this;
}
-void CreateWordTextInfo( const MarkupProcessor::StyledTextArray& word,
+void CreateWordTextInfo( const Text& paragraph,
+ Vector<TextStyle*>& textStyles,
WordLayoutInfo& wordLayoutInfo )
{
DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::CreateWordTextInfo\n" );
// Split in characters.
- for( MarkupProcessor::StyledTextArray::const_iterator charIt = word.begin(), charEndIt = word.end(); charIt != charEndIt; ++charIt )
+ std::size_t characterIndex = wordLayoutInfo.mFirstCharacter;
+ for( CharacterLayoutInfoContainer::iterator it = wordLayoutInfo.mCharactersLayoutInfo.begin(),
+ endIt = wordLayoutInfo.mCharactersLayoutInfo.end();
+ it != endIt;
+ ++it, ++characterIndex )
{
- const MarkupProcessor::StyledText& styledText( *charIt );
+ // Gets a reference of the character's layout info.
+ CharacterLayoutInfo& characterLayoutInfo( *it );
+
+ // Gets the character and the style for that character from the paragraph.
+ Character character = paragraph[characterIndex];
+ TextStyle* textStyle = *( textStyles.Begin() + characterIndex );
- const std::size_t length = styledText.mText.GetLength();
+ // Checks whether the character is an emoticon.
+ characterLayoutInfo.mIsColorGlyph = GlyphImage::IsColorGlyph( character );
+ DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " Is color glyph: %s\n", ( characterLayoutInfo.mIsColorGlyph ? "True" : "False" ) );
- // It could be a group of characters.
- for( std::size_t index = 0u; index < length; ++index )
+ if( characterLayoutInfo.mIsColorGlyph )
{
- MarkupProcessor::StyledText styledCharacter;
- styledCharacter.mStyle = styledText.mStyle;
- Character character = styledText.mText[index];
- styledCharacter.mText.Append( character );
+ // If the character is an emoticon a predefined font is set.
+ textStyle->SetFontName( EMOJI_FONT_NAME );
+ }
+ else
+ {
+ // Checks if the font family and the font style set in the text style supports the character.
+ // If not, it chooses the right font for the given character and style.
+ ChooseFontFamilyName( character, *textStyle );
+ }
- // Create layout character info.
- CharacterLayoutInfo characterLayoutInfo;
+ // Checks whether the charcter is right to left.
+ const Character::CharacterDirection direction = character.GetCharacterDirection();
+ characterLayoutInfo.mIsRightToLeft = ( ( direction == Character::RightToLeft ) ||
+ ( direction == Character::RightToLeftWeak ) );
- characterLayoutInfo.mIsColorGlyph = GlyphImage::IsColorGlyph( character );
- DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " Is color glyph: %s\n", ( characterLayoutInfo.mIsColorGlyph ? "True" : "False" ) );
+ // Gets the metrics of the font.
+ const Font font = Font::New( FontParameters( textStyle->GetFontName(), textStyle->GetFontStyle(), textStyle->GetFontPointSize() ) );
+ const Font::Metrics metrics = font.GetMetrics( character );
+ const float ascender = font.GetAscender();
- if( characterLayoutInfo.mIsColorGlyph )
- {
- styledCharacter.mStyle.SetFontName( EMOJI_FONT_NAME );
- }
- else
- {
- //Choose the right font for the given character and style.
- ChooseFontFamilyName( styledCharacter );
- }
-
- // Gets the metrics of the font.
- const Font font = Font::New( FontParameters( styledCharacter.mStyle.GetFontName(), styledCharacter.mStyle.GetFontStyle(), styledCharacter.mStyle.GetFontPointSize() ) );
- const Font::Metrics metrics = font.GetMetrics( character );
- const float ascender = font.GetAscender();
+ // Fill Natural size info for current character.
- // The font line's height is used as character's height.
- characterLayoutInfo.mSize.height = font.GetLineHeight();
+ // The font line's height is used as character's height.
+ characterLayoutInfo.mSize.height = font.GetLineHeight();
- // The character's advance is used as charcter's width.
- characterLayoutInfo.mSize.width = metrics.GetAdvance();
+ // The character's advance is used as charcter's width.
+ characterLayoutInfo.mSize.width = metrics.GetAdvance();
- // The ascender and bearing are used to position correctly glyphs of different font sizes.
- characterLayoutInfo.mAscender = ascender;
- characterLayoutInfo.mBearing = metrics.GetBearing();
-
- if( character.IsNewLine() && !characterLayoutInfo.mIsColorGlyph )
- {
- // A new paragraph character doesn't have any width.
- characterLayoutInfo.mSize.width = 0.f;
- }
+ // The ascender and bearing are used to position correctly glyphs of different font sizes.
+ characterLayoutInfo.mAscender = ascender;
+ characterLayoutInfo.mBearing = metrics.GetBearing();
- // Set's the underline thickness and position.
- // Both thickness and position includes the vertical pad adjust used in effects like glow or shadow.
- if( styledCharacter.mStyle.IsUnderlineEnabled() )
- {
- characterLayoutInfo.mUnderlineThickness = font.GetUnderlineThickness();
- characterLayoutInfo.mUnderlinePosition = font.GetUnderlinePosition();
- }
+ if( character.IsNewLine() && !characterLayoutInfo.mIsColorGlyph )
+ {
+ // A new paragraph character '\n' doesn't have any width.
+ characterLayoutInfo.mSize.width = 0.f;
+ }
- // stores the styled text.
- characterLayoutInfo.mStyledText.mText = styledCharacter.mText;
- characterLayoutInfo.mStyledText.mStyle = styledCharacter.mStyle;
+ // Set's the underline thickness and position.
+ // Both thickness and position includes the vertical pad adjust used in effects like glow or shadow.
+ if( textStyle->IsUnderlineEnabled() )
+ {
+ characterLayoutInfo.mUnderlineThickness = font.GetUnderlineThickness();
+ characterLayoutInfo.mUnderlinePosition = font.GetUnderlinePosition();
+ }
- // Add character layout info to the word layout info and update it.
- wordLayoutInfo.mCharactersLayoutInfo.push_back( characterLayoutInfo );
- UpdateSize( wordLayoutInfo.mSize, characterLayoutInfo.mSize );
- wordLayoutInfo.mAscender = std::max( wordLayoutInfo.mAscender, characterLayoutInfo.mAscender );
- wordLayoutInfo.mType = GetTextSeparatorType( character );
- } // end of each character in the group of characters.
+ // Updates the word size and ascender.
+ UpdateSize( wordLayoutInfo.mSize, characterLayoutInfo.mSize );
+ wordLayoutInfo.mAscender = std::max( wordLayoutInfo.mAscender, characterLayoutInfo.mAscender );
} // end of characters in the word.
DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::CreateWordTextInfo\n" );
}
+void UpdateLayoutInfo( WordLayoutInfo& wordLayout )
+{
+ // Initialize layout info for the whole word.
+ wordLayout.mSize = Size::ZERO;
+ wordLayout.mAscender = 0.f;
+
+ // Traverse the character layout info to update the word layout.
+ for( CharacterLayoutInfoContainer::iterator layoutIt = wordLayout.mCharactersLayoutInfo.begin(), layoutEndIt = wordLayout.mCharactersLayoutInfo.end();
+ layoutIt != layoutEndIt;
+ ++layoutIt )
+ {
+ // Layout info for the current character.
+ CharacterLayoutInfo& layoutInfo( *layoutIt );
+
+ // Update layout info for the current word.
+ UpdateSize( wordLayout.mSize, layoutInfo.mSize );
+ wordLayout.mAscender = std::max( wordLayout.mAscender, layoutInfo.mAscender );
+ }
+}
+
void RemoveCharactersFromWordInfo( TextView::RelayoutData& relayoutData,
const std::size_t numberOfCharacters,
bool& mergeWords,
/**
* Creates a data structure with info to layout the word, and data structures with useful info to modify the layout data structure if characters are added or removed.
*
- * @param[in] word The styled word.
+ * @param[in] paragraphText The paragraph's text.
+ * @param[in] textStyles The styles for each character of the paragraph.
* @param[out] wordLayoutInfo Layout info for all characters of the word.
*/
-void CreateWordTextInfo( const MarkupProcessor::StyledTextArray& word,
+void CreateWordTextInfo( const Text& paragraphText,
+ Vector<TextStyle*>& textStyles,
WordLayoutInfo& wordLayoutInfo );
/**
+ * Updates the word size and ascender.
+ *
+ * It's called after deleting some characters, split a word in two,
+ * or when a new word is created when right to left text is reordered.
+ *
+ * @param[in] wordLayout The word layout info.
+ */
+void UpdateLayoutInfo( WordLayoutInfo& wordLayout );
+
+/**
* Removes a given number of characters from the given word.
*
* It calls the RemoveCharactersFromWord() function to remove characters from the word.
+++ /dev/null
-/*
- * Copyright (c) 2014 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.
- *
- */
-
-// CLASS HEADER
-#include "localized-control-factory-impl.h"
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/control-impl.h>
-#include <dali/integration-api/debug.h>
-
-// EXTERNAL INCLUDES
-#include <libintl.h>
-
-using std::string;
-using namespace Dali;
-
-namespace Dali
-{
-
-namespace Toolkit
-{
-
-namespace Internal
-{
-
-namespace // unnamed namespace
-{
-
-
-}
-
-LocalizedControlFactory::LocalizedControlFactory()
-: mObjectEntries(),
- mSignalsConnected( false )
-{
-}
-
-LocalizedControlFactory::~LocalizedControlFactory()
-{
-}
-
-Dali::Toolkit::TextView LocalizedControlFactory::CreateLocalizedTextView( const std::string& textID, const std::string& textDomain, const std::string& textViewTheme )
-{
- if( !mSignalsConnected )
- {
- Stage::GetCurrent().GetObjectRegistry().ObjectDestroyedSignal().Connect( this, &LocalizedControlFactory::OnObjectDestruction );
- Adaptor::Get().LanguageChangedSignal().Connect( this, &LocalizedControlFactory::OnLanguageChanged );
- mSignalsConnected = true;
- }
-
- const string& localizedText = dgettext(textDomain.c_str(), textID.c_str());
- Dali::Toolkit::TextView textView = Dali::Toolkit::TextView::New();
- textView.SetText(localizedText);
-
- LocalisedStringInfo info(textID, textDomain, textViewTheme);
-
- mObjectEntries[textView.GetObjectPtr()] = info;
-
- return textView;
-}
-
-void LocalizedControlFactory::OnObjectDestruction( const Dali::RefObject* objectPointer )
-{
- if(!mObjectEntries.empty())
- {
- //Needs optimization. All the destructed objects are currently checked for existence in entries.
- mObjectEntries.erase(objectPointer);
- }
-}
-
-void LocalizedControlFactory::OnLanguageChanged( Dali::Adaptor& adaptor)
-{
- if(!mObjectEntries.empty())
- {
- ObjectEntriesIterator iter = mObjectEntries.begin();
- ObjectEntriesIterator iterEnd = mObjectEntries.end();
- while(iter != iterEnd)
- {
- RefObject* refObjectPtr = const_cast<RefObject*> (iter->first);
- BaseHandle handle(static_cast<BaseObject*>(refObjectPtr));
- LocalisedStringInfo info = iter->second;
-
- const string& localizedText = dgettext(info.textDomain.c_str(), info.textID.c_str());
-
- Toolkit::TextView textView = Dali::Toolkit::TextView::DownCast( handle );
-
- if(textView)
- {
- textView.SetText( localizedText );
- }
- else
- {
- DALI_ASSERT_ALWAYS(false && "Corrupt TextView internal pointer in entries!");
- }
-
- ++iter;
- }
- }
-}
-
-
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
+++ /dev/null
-#ifndef __DALI_TOOLKIT_INTERNAL_LOCALIZED_CONTROL_FACTORY_H__
-#define __DALI_TOOLKIT_INTERNAL_LOCALIZED_CONTROL_FACTORY_H__
-
-/*
- * Copyright (c) 2014 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.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-#include <set>
-
-// INTERNAL INCLUDES
-#include <dali/dali.h>
-#include <dali-toolkit/public-api/factory/localized-control-factory.h>
-
-namespace Dali
-{
-
-namespace Toolkit
-{
-
-namespace Internal
-{
-
-/**
- * @copydoc Toolkit::LocalizedControlFactory
- */
-class LocalizedControlFactory : public Dali::BaseObject, public ConnectionTracker
-{
-public:
-
- /**
- * Structure used to store/retrieve localisation info.
- */
- struct LocalisedStringInfo
- {
- LocalisedStringInfo()
- {
- }
-
- LocalisedStringInfo(std::string id, std::string domain, std::string theme)
- : textID(id),
- textDomain(domain),
- textViewTheme(theme)
- {
-
- }
-
- std::string textID;
- std::string textDomain;
- std::string textViewTheme;
- };
-
- typedef std::map< const Dali::RefObject*, LocalisedStringInfo > ObjectEntriesContainer;
- typedef ObjectEntriesContainer::iterator ObjectEntriesIterator;
- typedef ObjectEntriesContainer::const_iterator ObjectEntriesConstIterator;
-
- /**
- * Construct a new LocalizedControlFactory.
- */
- LocalizedControlFactory();
-
- /**
- * @copydoc Toolkit::LocalizedControlFactory::CreateLocalizedTextView
- */
- Dali::Toolkit::TextView CreateLocalizedTextView( const std::string& textID, const std::string& textDomain, const std::string& textViewTheme );
-
-protected:
-
- /**
- * Destructor
- */
- virtual ~LocalizedControlFactory();
-
-private:
-
- /**
- * Callback for Object destructed signal.
- * @param objectPointer Pointer to a RefObject
- */
- void OnObjectDestruction( const Dali::RefObject* objectPointer );
-
- /**
- * Callback for language changed signal.
- * @param adaptor Reference to a Dali::Adaptor instance
- */
- void OnLanguageChanged( Dali::Adaptor& adaptor);
-
-private:
-
- // Undefined
- LocalizedControlFactory(const LocalizedControlFactory&);
- LocalizedControlFactory& operator=(const LocalizedControlFactory& rhs);
-
-private:
-
- ObjectEntriesContainer mObjectEntries;
- bool mSignalsConnected:1;
-
-};
-
-} // namespace Internal
-
-inline Internal::LocalizedControlFactory& GetImpl(Dali::Toolkit::LocalizedControlFactory& obj)
-{
- DALI_ASSERT_ALWAYS(obj);
-
- Dali::BaseObject& handle = obj.GetBaseObject();
-
- return static_cast<Internal::LocalizedControlFactory&>(handle);
-}
-
-inline const Internal::LocalizedControlFactory& GetImpl(const Dali::Toolkit::LocalizedControlFactory& obj)
-{
- DALI_ASSERT_ALWAYS(obj);
-
- const Dali::BaseObject& handle = obj.GetBaseObject();
-
- return static_cast<const Internal::LocalizedControlFactory&>(handle);
-}
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // __DALI_TOOLKIT_INTERNAL_LOCALIZED_CONTROL_FACTORY_H__
$(toolkit_base_src_dir)/controls/text-view/split-by-char-policies.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-actor-cache.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-processor.cpp \
+ $(toolkit_base_src_dir)/controls/text-view/text-processor-bidirectional-info.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-view-impl.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-view-character-processor.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-view-paragraph-processor.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-view-processor-dbg.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-view-processor-helper-functions.cpp \
$(toolkit_base_src_dir)/controls/text-view/text-view-word-processor.cpp \
- $(toolkit_base_src_dir)/factory/localized-control-factory-impl.cpp \
$(toolkit_base_src_dir)/focus-manager/focus-manager-impl.cpp \
$(toolkit_base_src_dir)/focus-manager/keyboard-focus-manager-impl.cpp \
$(toolkit_base_src_dir)/focus-manager/keyinput-focus-manager-impl.cpp \
RequestDefaultTheme();
- if( Adaptor::IsAvailable() )
+ StyleMonitor styleMonitor( StyleMonitor::Get() );
+ if( styleMonitor )
{
- StyleMonitor::Get().StyleChangeSignal().Connect( this, &StyleManager::StyleMonitorChange );
+ styleMonitor.StyleChangeSignal().Connect( this, &StyleManager::StyleMonitorChange );
}
}
{
actor.SetColor( color );
actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
+ actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
* @brief Sets the background color of the control.
*
* @param[in] color The required background color of the control
+ *
+ * @note The background color fully blends with the actor color.
*/
void SetBackgroundColor( const Vector4& color );
+++ /dev/null
-/*
- * Copyright (c) 2014 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.
- *
- */
-
-// CLASS HEADER
-
-#include <dali-toolkit/public-api/factory/localized-control-factory.h>
-
-// EXTERNAL INCLUDES
-
-// INTERNAL INCLUDES
-
-#include <dali-toolkit/internal/factory/localized-control-factory-impl.h>
-
-namespace Dali
-{
-
-namespace Toolkit
-{
-
-Dali::Toolkit::TextView LocalizedControlFactory::CreateLocalizedTextView( const std::string& textID, const std::string& textDomain, const std::string& textViewTheme )
-{
- LocalizedControlFactory factory = Get();
- return GetImpl(factory).CreateLocalizedTextView(textID, textDomain, textViewTheme);
-}
-
-LocalizedControlFactory::LocalizedControlFactory()
-{
-}
-
-LocalizedControlFactory::~LocalizedControlFactory()
-{
-}
-
-LocalizedControlFactory LocalizedControlFactory::Get()
-{
- LocalizedControlFactory factory;
-
- // Check whether the focus factory is already created
- SingletonService singletonService( SingletonService::Get() );
- if ( singletonService )
- {
- Dali::BaseHandle handle = singletonService.GetSingleton(typeid(LocalizedControlFactory));
- if(handle)
- {
- // If so, downcast the handle of singleton to focus factory
- factory = LocalizedControlFactory(dynamic_cast<Internal::LocalizedControlFactory*>(handle.GetObjectPtr()));
- }
-
- if(!factory)
- {
- // If not, create the focus factory and register it as a singleton
- factory = LocalizedControlFactory(new Internal::LocalizedControlFactory());
- singletonService.Register(typeid(factory), factory);
- }
- }
-
- return factory;
-}
-
-LocalizedControlFactory::LocalizedControlFactory(Internal::LocalizedControlFactory *impl)
- : BaseHandle(impl)
-{
-}
-
-} // namespace Toolkit
-
-} // namespace Dali
+++ /dev/null
-#ifndef __DALI_TOOLKIT_LOCALIZED_CONTROL_FACTORY_H__
-#define __DALI_TOOLKIT_LOCALIZED_CONTROL_FACTORY_H__
-
-/*
- * Copyright (c) 2014 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.
- *
- */
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/text-view/text-view.h>
-
-namespace Dali DALI_IMPORT_API
-{
-
-namespace Toolkit
-{
-
-namespace Internal DALI_INTERNAL
-{
-class LocalizedControlFactory;
-}
-
-/**
- * @brief This class provides functionality for creating controls which have localized text.
- *
- * This class keeps track of objects created using its factory methods, and updates them
- * when the system language changes.
- *
- * Warning: If the developer calls SetText on the object to overwrite the managed TextView,
- * then it leads to an inconsistent state where the object will be overwritten with the
- * localized text when language/locale changes.
- */
-
-class LocalizedControlFactory : public BaseHandle
-{
-public:
-
- /**
- * @brief Creates a localized TextView, which is automatically updated when the locale or language changes.
- *
- * @pre The LocalizedControlFactory has been initialized.
- *
- * @param textID The id of the localized text with which a platform request (gettext) for localized text can be made.
- * @param textDomain The text domain for the localized text. Eg "sys_string"
- * @param textViewTheme A string containing style info about various properties of TextView for different
- * locale/language.
- * @return handle to a new localized TextView
- */
- static Dali::Toolkit::TextView CreateLocalizedTextView( const std::string& textID, const std::string& textDomain = "sys_string", const std::string& textViewTheme = "{}" );
-
-
-private:
-
- /**
- * @brief Create a LocalizedControlFactory handle; this can be initialised with LocalizedControlFactory::New().
- *
- * Calling member functions with an uninitialised handle is not allowed.
- */
- LocalizedControlFactory();
-
- /**
- * @brief Destructor
- *
- * This is non-virtual since derived Handle types must not contain data or virtual methods.
- */
- ~LocalizedControlFactory();
-
- /**
- * @brief Get the singleton of LocalizedControlFactory object.
- *
- * @return A handle to the LocalizedControlFactory control.
- */
- static LocalizedControlFactory Get();
-
- /**
- * @brief Allows the creation of this Control from an Internal::LocalizedControlFactory pointer.
- *
- * @param[in] impl A pointer to the internal LocalizedControlFactory.
- */
- LocalizedControlFactory(Internal::LocalizedControlFactory *impl);
-}; // class LocalizedControlFactory
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // __DALI_TOOLKIT_LOCALIZED_CONTROL_FACTORY_H__
$(public_api_base_src_dir)/controls/table-view/table-view.cpp \
$(public_api_base_src_dir)/controls/text-input/text-input.cpp \
$(public_api_base_src_dir)/controls/text-view/text-view.cpp \
- $(public_api_base_src_dir)/factory/localized-control-factory.cpp \
$(public_api_base_src_dir)/focus-manager/focus-manager.cpp \
$(public_api_base_src_dir)/focus-manager/keyboard-focus-manager.cpp \
$(public_api_base_src_dir)/focus-manager/keyinput-focus-manager.cpp \
public_api_base_text_view_header_files = \
$(public_api_base_src_dir)/controls/text-view/text-view.h
-public_api_base_factory_header_files = \
- $(public_api_base_src_dir)/factory/localized-control-factory.h
-
public_api_base_focus_manager_header_files = \
$(public_api_base_src_dir)/focus-manager/keyinput-focus-manager.h \
$(public_api_base_src_dir)/focus-manager/focus-manager.h \
publicapibasetableview_HEADERS = $(public_api_base_table_view_header_files)
publicapibasetextview_HEADERS = $(public_api_base_text_view_header_files)
publicapibasetextinput_HEADERS = $(public_api_base_text_input_header_files)
-publicapibasefactory_HEADERS = $(public_api_base_factory_header_files)
publicapibasefocusmanager_HEADERS = $(public_api_base_focus_manager_header_files)
publicapibasemarkupprocessor_HEADERS = $(public_api_base_markup_processor_header_files)
publicapibaseshadereffects_HEADERS = $(public_api_base_shader_effects_header_files)
* - \link resource-tracking Resource Tracking \endlink
* - \link performance-profiling Performance Profiling \endlink
*
-*/
+ * \section Performance
+ * - \link performance-tips Performance Tips \endlink
+ * - \link texture-atlases Texture Atlases \endlink
+ * - \link Texture_Compression Compressing Textures \endlink
+ *
+ */
/*! \page scene-graph
*
* <h2 class="pg">Background</h2>
* The Dali rendering pipeline has 2 stages.
* Each stage is typically run once per frame.
- *
- * <ul>
- * <li> 1. Update
+ * <h3> 1. Update </h3>
* <ul>
- * <li> Run animations
- * <li> Run constraints
- * <li> Run physics
- * <li> Update the scene-graph
+ * <li> Run animations</li>
+ * <li> Run constraints</li>
+ * <li> Run physics</li>
+ * <li> Update the scene-graph</li>
* </ul>
- * <li> 2. Render
+ * <h3> 2. Render </h3>
* <ul>
- * <li> Upload 3D data using OpenGL ( textures, vertex buffers etc).
- * <li> Draw the scene using OpenGL
- * </ul>
+ * <li> Upload 3D data using OpenGL ( textures, vertex buffers etc).</li>
+ * <li> Draw the scene using OpenGL</li>
* </ul>
*
+ *
* To run at 60 FPS (16 milliseconds per frame), it is recommended to stay below the following times:
* <ul>
- * <li> Update: 4 milliseconds
- * <li> Render: 4 milliseconds
+ * <li> Update: 4 milliseconds</li>
+ * <li> Render: 4 milliseconds</li>
* </ul>
*
* This will leave enough time for the output to be composited (if the system uses a compositor) and to avoid using
* If nothing is animating Dali will enter a paused state to save power. At this
* point nothing will be logged.
*
- * <h2 class="pg">Performance advice </h2>
- *
- *
- * <h3> Tips to reduce update times: </h3>
- * <ul>
- * <li> Keep the actor count as small as possible.
- * <ul>
- * <li> Less actors == less processing
- * <li> Try to keep invisible or un-used actors off the stage. Don't have hidden views on the stage.
- * </ul>
- * <li> Ensure constraints are kept as simple as possible
- * </ul>
- *
- * <h3> Tips to reduce render times: </h3>
- *
- * <ul>
- * <li> Keep the visible actor count as small as possible == less draw calls
- * <li> If using a fixed set of images, try pre-generating a texture-atlas.
- * <ul>
- * <li> For each image within the Atlas, use ImageActor.SetPixelArea() to use it.
- * <li> This reduces texture state changes when rendering.
- * </ul>
- * <li> Try to use 9-patch when you need to stretch an image while maintaining the border size.
- * <ul>
- * <li> See ImageActor::STYLE_NINE_PATCH
- * </ul>
- * <li> When using layers try to disable the depth test to avoid the depth buffer being cleared.
- * <li> If writing custom shaders, try to keep them as simple as possible.
- * <li> Try to keep texture sizes as small as possible.
- * </ul>
*
* <h2 class="pg">Application profiling</h2>
*
* <li> DALI_RENDER_END. Dali render task has finished
* </ul>
*
- * <h3> Checking ftrace is working on Tizen</h3>
+ * <h3> Checking ftrace is working on Linux</h3>
*
* Documentation for ftrace:
* Follow these instructions to ensure the debugfs has been mounted, and the kernel you are using
--- /dev/null
+/*! \page performance-tips Performance Tips
+
+
+<table>
+ <tr>
+ <th>High CPU occupancy <br></th>
+ </tr>
+ <tr>
+ <td>
+ - Try to reduce actor count ( less actors == less processing) <br>
+ - Delete any actors that are not visible, or move them off stage <br>
+ - Use TextureAtlases ( greatly reduces OpenGL driver calls to glBindTexture <br>
+ - Optimise / reduce any constraints used
+ </td>
+ </tr>
+</table>
+<br><br>
+<table>
+ <tr>
+ <th>High GPU occupancy <br></th>
+ </tr>
+ <tr>
+ <td>
+ - Reduce visible actor count ( == less draw calls) <br>
+ - For 2D UI graphics which require no z sorting use @code Actor::SetDrawMode( DrawMode::OVERLAY );
+// In this mode depth testing is turned off and order is determined by the hierachy (depth-first search order).
+ @endcode
+ - Use TextureAtlases ( reduces state changes in the GPU) <br>
+ - Use compressed textures
+ - Use lower quality textures, e.g. smaller, lower number of bits per pixel
+ - Use Dali::NinePatchImage where possible.
+ - Avoid using too many textures which contain alpha and require blending
+ - Avoid using too many Dali::Layer with depth testing enabled. Otherwise the layer has to clear the depth buffer.
+ - Optimise any shaders used. Pixel shaders should be kept as lean as possible.
+ </td>
+ </tr>
+</table>
+
+ */
--- /dev/null
+/*! \page texture-atlases Texture Atlases
+ *
+ * <h2 class="pg">Using Texture Atlases in DALi </h2>
+ *
+ *
+ * <h3> Example demo application </h3>
+
+ \image html image-wall.jpg
+
+
+<h3> Application above is running slow as there are many small individual images displayed (50)</h3>
+
+<table>
+ <tr>
+ <td> Launch Time </td>
+ <td> Slow </td>
+ <td> Has to perform: <br>- 50 file open requests and multiple reads for each image</td>
+ </tr>
+ <tr>
+ <td> Memory Usage </td>
+ <td> High </td>
+ <td> Has to create:
+ <br>- 50 Dali::Image objects
+ <br>- 50 OpenGL Textures
+ </td>
+ </tr>
+ <tr>
+ <td>Rendering Performance </td>
+ <td> Slow </td>
+ <td> Has to perform:
+ <br>- 50 glBindTexture calls per frame ( each OpenGL calls takes time)
+ <br>- 50 a frame = 3000 calls per second @60 FPS.
+ <br>- Texture switching is a major state change in the GPU
+ </td>
+ </tr>
+</table>
+<br><br>
+
+
+* <h3> Solutions to problem: Use a Texture Atlas</h3>
+
+A texture atlas is simply one larger image that contains smaller images. A texture atlas is sometimes called a
+sprite sheet, bitmap sheet or texture pack.
+
+ \image html atlas.jpg
+
+<br>
+Dali::ImageActor has the ability to display a portion of an image using ImageActor::PixelArea setting.
+For example to display the first 3 image in the atlas
+
+ \image html example-code.jpg
+
+<h3> Result of using an Atlas</h3>
+<table>
+ <tr>
+ <td> Launch Time </td>
+ <td> Fast </td>
+ <td> Has to perform: <br>- 1 file open request </td>
+ </tr>
+ <tr>
+ <td> Memory Usage </td>
+ <td> Better </td>
+ <td> Has to create:
+ <br>- 1 Dali::Image objects
+ <br>- 1 OpenGL Textures
+ </td>
+ </tr>
+ <tr>
+ <td>Rendering Performance </td>
+ <td> Fast </td>
+ <td> Has to perform:
+ <br>- 1 glBindTexture calls per frame ( each OpenGL calls takes time)
+ <br>- 1 a frame = 6- calls per second @60 FPS.
+ </td>
+ </tr>
+</table>
+<br>
+<h2> Atlas creation guide </h2>
+
+Many tools exist for creating texture atlases.<br>
+In the following example we are using a tool called TexturePacker as DALi has an exporter script for it.
+The exporter automatically generates a source file that has the ImageActor::PixelArea pre-defined.
+<br>
+<ul>
+ <li> Download http://www.codeandweb.com/texturepacker </li>
+ <li> Launch TexturePacker </li>
+ <li> Go to the menu File -> Preferences</li>
+ <li> Set the "Exporter directory" to be the location of dali-toolkit/texture-atlas-exporter <br></li>
+ \image html texture-packer-preferences.jpg
+ <br>
+ <li> <b> Restart the application! </b></li>
+ <li> Select DALi 3D framework for new project</li>
+ <br>
+ \image html texture-packer-startup.jpg
+ <br>
+ <li><h3> Create the atlas </h3> <br></li>
+ \image html texture-packer-add-sprites.jpg <br><br>
+ <li><h3> Click publish to produce the files </h3></li><br><br>
+ \image html texture-packer-publish.jpg <br><br>
+</ul>
+<h2> Using the generated cpp file </h2>
+
+The generated cpp file contains 3 different ways of describing the atlas. <br>
+Copy and paste the section that best suits your application.
+<ul><li> Lookup table. Includes code for storing the table in a std::map for fast lookup.</li>
+<li> constants. </li>
+<li> JavaScript property map ( see the Dali JavaScript programming guide on how to use it).
+</ul>
+<h3> Using the lookup table </h3>
+
+Cut and paste the lookup table code into your application.
+
+\code
+
+\\ The following code is automatically generated.
+\\
+const char* ATLAS_FILE_NAME( "my_first_atlas.png" ); ///< Atlas image filename
+
+/**
+ * Structure to hold image name and position within the atlas.
+ *
+ */
+struct ImageInfo
+{
+ const char* name;
+ unsigned int x,y,w,h;
+ Dali::BlendingMode::Type blendMode; // only enable blending if image has alpha
+};
+
+/**
+ * lookup table
+ */
+const ImageInfo ImageAtlas[]=
+{
+ { "blocks-ball", 2, 198, 51, 51, BlendingMode::ON },
+ { "bubble-ball", 288, 74, 32, 32, BlendingMode::ON },
+ { "gallery-small-52", 2, 2, 128, 128, BlendingMode::OFF },
+ { "icon-change", 219, 2, 37, 34, BlendingMode::ON },
+ { "icon-cluster-carousel", 180, 2, 37, 34, BlendingMode::ON }
+};
+
+const ImageInfo* GetImageInfo(const char* name)
+{
+ typedef std::map< const char*, const ImageInfo* > LookupMap;
+ static LookupMap lookup;
+ if( lookup.empty() )
+ {
+ for( unsigned int i = 0; i < ATLAS_IMAGE_COUNT; ++i)
+ {
+ lookup[ ImageAtlas[i].name ] = &ImageAtlas[i];
+ }
+ }
+ LookupMap::const_iterator iter = lookup.find(name);
+ if( iter != lookup.end() )
+ {
+ return (*iter).second;
+ }
+ DALI_ASSERT_ALWAYS(0 && "image name not found in atlas");
+ return NULL;
+}
+
+\endcode
+
+To use the lookup table you can do something like this:
+\code
+
+// Example function on how to get an image info from the table
+
+std::string fileName = std::string( DALI_IMAGE_DIR ) + ATLAS_FILE_NAME;
+Image imageImage = Image::New( fileName );
+
+const ImageInfo* info(NULL);
+
+info = GetImageInfo("blocks-ball");
+if( info)
+{
+ ImageActor ballActor = ImageActor::New( imageAtlas, ImageActor::PixelArea( info->x, info->y, info->w, info->h) );
+ ballActor->SetBlendMode( info->blendMode );
+}
+info = GetImageInfo("bubble-ball");
+if( info)
+{
+ ImageActor bubbleActor = ImageActor::New( imageAtlas, ImageActor::PixelArea( info->x, info->y, info->w, info->h) );
+ bubbleActor->SetBlendMode( info->blendMode );
+}
+
+\endcode
+<h3> Using the constant definitions </h3>
+
+1. Cut and paste the constant definition code into your application.
+
+You'll notice the code below won't compile because C++ variables can't have a dash character.<br>
+E.g. BLOCKS-BALL, BUBBLE-BALL will cause errors. Do a search and replace for - and replace with underscores.
+This is one reason why using lookup table which holds the filename as a string maybe easier to use.
+
+\code
+\\ The following code is automatically generated.
+\\
+const char* ATLAS_FILE_NAME( "my_first_atlas.png" );
+
+/**
+ * Structure to hold position / blend mode within the atlas.
+ *
+ */
+struct ImageInfo
+{
+ ImageInfo(unsigned int x,unsigned int y,unsigned int w,unsigned int h, Dali::BlendingMode::Type mode)
+ :pixelArea(x,y,w,h),blendMode(mode)
+ {}
+ ImageActor::PixelArea pixelArea;
+ Dali::BlendingMode::Type blendMode; // only enable blending if image has alpha
+};
+
+
+const ImageInfo BLOCKS-BALL( 2, 198, 51, 51 ,BlendingMode::ON );
+const ImageInfo BUBBLE-BALL( 288, 74, 32, 32 ,BlendingMode::ON );
+const ImageInfo GALLERY-SMALL-52( 2, 2, 128, 128 ,BlendingMode::OFF );
+\endcode
+
+2. To use it, you can copy example code from the generated cpp file which looks
+like this
+\code
+void LoadAtlasImages()
+{
+ std::string fileName = std::string(DALI_IMAGE_DIR) + ATLAS_FILE_NAME;
+ Image atlasImage = Image::New( fileName );
+ ImageActor Blocksball = ImageActor::New( atlasImage, BLOCKS_BALL.pixelArea);
+ Blocksball.SetBlendMode( BLOCKS_BALL.blendMode );
+
+ ImageActor Bubbleball = ImageActor::New( atlasImage, BUBBLE_BALL.pixelArea);
+ Bubbleball.SetBlendMode( BUBBLE_BALL.blendMode );
+ ...
+ \endcode
+
+
+
+<br><br>
+<h2> Atlas creation tips </h2>
+
+<ul>
+ <li> Compress the atlas - \link Texture_Compression Compressing Textures \endlink <br></li>
+ <li> Avoid adding large images to the Atlas.<br>
+ E.g. don't add background images to it. Medium to large images should
+ be kept seperate. <br><br>
+ \image html atlas-size.jpg
+ <br><br>
+ </li>
+ <li> Try to ensure the atlas contains only images that are frequently used. <br>
+ There's no point in having images taking up GPU texture memory if they're not displayed.<br>
+ </li>
+ <li> Avoid very large atlases <br>
+ Try to create multiple atlases based on how they are used within your application.<br>
+ <br>
+ Alternatively Texture packer has the option to split atlases ( search help for Multipack)
+ </li>
+</ul>
+
+
+
+ */
+
--- /dev/null
+
+/*! \page Texture_Compression Texture Compression
+
+
+Using compressing the textures will:
+<ul>
+<li> Speed up rendering in time the GPU == less power used due to less texture data being transferred.
+<li> Reduce texture memory usage.
+<li> Speed up load times. Smaller files mean quicker load times.
+</ul>
+<br><br>
+DALi supports the KTX file format.
+You just load the compressed texture like you would any other image.
+\code
+Image::New("my_compressed_file.ktx");
+\endcode
+<br>
+ARMS texture compression tool<br>
+http://malideveloper.arm.com/develop-for-mali/tools/asset-creation/mali-gpu-texture-compression-tool/ <br>
+
+Here is an example of using the ARM compression tool.
+\image html compression-options.jpg
+
+<br><br>
+
+\image html compression-example.jpg
+<br>
+<br>
+As shown above the ETC-1 compression format does not support alpha.<br> As a work around the tool will export
+the alpha as a seperate compressed image.<br>
+In order to combine both the images you need to use a custom shader.<br>
+Here is an example shader:<br>
+\code
+ const char* const COMPRESSED_RGB_PLUS_SEPARATE_ALPHA_FRAGMENT_SOURCE =
+ "\n"
+ "void main()\n"
+ "{\n"
+ " vec4 v4Color = (texture2D(sTexture, vTexCoord) * uColor);\n"
+ " v4Color.a = texture2D(sEffect, vTexCoord ).r;\n"
+ " gl_FragColor = v4Color;"
+ "}\n";
+
+
+ mShaderEffect = ShaderEffect::New( "", COMPRESSED_RGB_PLUS_SEPARATE_ALPHA_FRAGMENT_SOURCE);
+
+ mAtlasImageRGB = Image::New( ATLAS_RGB_FILENAME.KTX);
+
+ mAtlasImageAlpha = Image::New( ATLAS_ALPHA_FILENAME.KTX );
+
+ mShaderEffect.SetEffectImage( mAtlasImageAlpha );
+
+
+
+ // to create Image Actor
+ ImageActor imageActor = ImageActor::New( mAtlasImageRGB, GetImagePosition( info) );
+
+ imageActor.SetShaderEffect( mShaderEffect );
+
+ imageActor.SetBlendMode(BlendingMode::ON);
+
+\endcode
+
+
+ */
#include <dali-toolkit/public-api/controls/text-input/text-input.h>
#include <dali-toolkit/public-api/controls/text-view/text-view.h>
#include <dali-toolkit/public-api/enums.h>
-#include <dali-toolkit/public-api/factory/localized-control-factory.h>
#include <dali-toolkit/public-api/focus-manager/focus-manager.h>
#include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
#include <dali-toolkit/public-api/markup-processor/markup-processor.h>
return seed;
}
-float genRandomFloat(unsigned int& seed, unsigned int offset)
-{
- return static_cast<float>(genRandom(seed, offset)) / 0xffffffff;
-}
-
float genRandomFloat(unsigned int& seed, unsigned int offset, float min, float max)
{
const float f = static_cast<float>(genRandom(seed, offset)) / 0xffffffff;
}
};
-/**
- * Returns relative border (0.0f...1.0f x 0.0f...1.0f)
- * from an absolute pixel specified border.
- * @param[in] absolute A border using absolute pixel coordinates
- * @param[in] width The width of the texture
- * @param[in] height The height of the texture.
- * @return A border relative to the size of the Image texture dimensions.
- */
-Vector4 GetRelativeBorder(Vector4 absolute, float width, float height)
-{
- return Vector4( absolute.x / width,
- absolute.y / height,
- absolute.z / width,
- absolute.w / height);
-}
-
}
namespace Dali
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 9;
+const unsigned int TOOLKIT_MICRO_VERSION = 10;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.0.9
+Version: 1.0.10
Release: 1
Group: System/Libraries
License: Apache-2.0
--- /dev/null
+// Created with TexturePacker (http://www.codeandweb.com/texturepacker)
+// DALi Exporter: nick.holland@partner.samsung.com
+//
+// {{smartUpdateKey}}
+
+// For your application cut and paste either:
+//
+// 1. Lookup table.
+// 2. Constants.
+// 3. JavaScript property map for using with DALi JS.
+
+// Note: If you use one option, then delete code for the other two
+
+
+
+
+//
+// 1. ------ lookup table method ------
+//
+// Handy if you want to get image with a postfix, e.g. image_1, image_2, image_3
+// Or if some of the image names contain special characters which are not allowed
+// in constant definitions ( e.g. spaces and full stops).
+
+
+const char* ATLAS_FILE_NAME( "{{texture.fullName}}" ); ///< Atlas image filename
+
+
+/**
+ * Structure to hold image name and position within the atlas.
+ *
+ */
+struct ImageInfo
+{
+ const char* name;
+ unsigned int x,y,w,h;
+ Dali::BlendingMode::Type blendMode; // only enable blending if image has alpha
+};
+
+/**
+ * lookup table
+ */
+const ImageInfo ImageAtlas[]=
+{
+{% for sprite in allSprites %} { "{{sprite.trimmedName}}", {{sprite.frameRect.x}}, {{sprite.frameRect.y}}, {{sprite.frameRect.width}}, {{sprite.frameRect.height}}, {%if sprite.isSolid %}BlendingMode::OFF{% else%}BlendingMode::ON{% endif %} }{% if not forloop.last %},{% endif %}
+{% endfor %}
+};
+
+const unsigned int ATLAS_IMAGE_COUNT = sizeof(ImageAtlas)/sizeof(ImageAtlas[0]);
+
+// Example function on how to get an image info from the table
+//
+// std::string fileName = std::string( DALI_IMAGE_DIR ) + ATLAS_FILE_NAME;
+// Image imageAtlas = Image::New( fileName );
+//
+//
+// const ImageInfo* info = GetImageInfo("left_icon");
+//
+// if( info)
+// {
+// ImageActor myActor = ImageActor::New( imageAtlas, ImageActor::PixelArea( info->x, info->y, info->w, info->h) );
+// myActor->SetBlendMode( info->blendMode );
+//
+//
+
+const ImageInfo* GetImageInfo(const char* name)
+{
+ typedef std::map< const char*, const ImageInfo* > LookupMap;
+ static LookupMap lookup;
+ if( lookup.empty() )
+ {
+ for( unsigned int i = 0; i < ATLAS_IMAGE_COUNT; ++i)
+ {
+ lookup[ ImageAtlas[i].name ] = &ImageAtlas[i];
+ }
+ }
+ LookupMap::const_iterator iter = lookup.find(name);
+ if( iter != lookup.end() )
+ {
+ return (*iter).second;
+ }
+ DALI_ASSERT_ALWAYS(0 && "image name not found in atlas");
+ return NULL;
+}
+
+//
+//
+// 2. ------ constants code ------
+//
+//
+
+const char* ATLAS_FILE_NAME( "{{texture.fullName}}" );
+
+/**
+ * Structure to hold position / blend mode within the atlas.
+ *
+ */
+struct ImageInfo
+{
+ ImageInfo(unsigned int x,unsigned int y,unsigned int w,unsigned int h, Dali::BlendingMode::Type mode)
+ :pixelArea(x,y,w,h),blendMode(mode)
+ {}
+ ImageActor::PixelArea pixelArea;
+ Dali::BlendingMode::Type blendMode; // only enable blending if image had alpha
+};
+
+{% for sprite in allSprites %}const ImageInfo {{ sprite.trimmedName|upper}}( {{sprite.frameRect.x}}, {{sprite.frameRect.y}}, {{sprite.frameRect.width}}, {{sprite.frameRect.height}} ,{%if sprite.isSolid %}BlendingMode::OFF{% else%}BlendingMode::ON{% endif %} );
+{% endfor %}
+
+
+// Example on using the Atlas, please delete this code.
+void LoadAtlasImages()
+{
+ std::string fileName = std::string(DALI_IMAGE_DIR) + ATLAS_FILE_NAME;
+ Image atlasImage = Image::New( fileName );
+ {% for sprite in allSprites %}ImageActor {{sprite.trimmedName|capfirst}} = ImageActor::New( atlasImage, {{sprite.trimmedName|upper}}.pixelArea);
+ {{sprite.trimmedName|capfirst}}.SetBlendMode( {{sprite.trimmedName|upper}}.blendMode );
+
+ {% endfor %}
+}
+
+//
+//
+// 3. ------ JavaScript key/value lookup table ------
+//
+//
+//
+
+ATLAS_IMAGE_LIST : [
+{% for sprite in allSprites %} { name: "{{sprite.trimmedName}}", x: {{sprite.frameRect.x}}, y:{{sprite.frameRect.y}}, w:{{sprite.frameRect.width}}, h:{{sprite.frameRect.height}}, {%if sprite.isSolid %}dali.BLENDING_OFF{% else%}dali.BLENDING_ON{% endif %} }{% if not forloop.last %},{% endif %}
+{% endfor %}
+]
\ No newline at end of file
--- /dev/null
+<exporter version="1.0">
+ <!-- identifier of the exporter -->
+ <name>dali_exporter</name>
+
+ <!-- display name of the exporter for the combo box -->
+ <displayName>DALi 3D</displayName>
+
+ <!-- description of the exporter -->
+ <description>DALi 3D exporter for TexturePacker</description>
+
+ <!-- exporter version -->
+ <version>1.0</version>
+
+ <!-- currently only one file allowed - more to come soon -->
+ <files>
+ <file>
+ <!-- name of this file variable -->
+ <name>maintext</name>
+
+ <!-- human readable name (for GUI) -->
+ <displayName>.cpp file</displayName>
+
+ <!-- file extension for the file -->
+ <fileExtension>cpp</fileExtension>
+
+ <!-- name of the template file -->
+ <template>dali3d_exporter.cpp</template>
+ </file>
+ </files>
+
+ <!-- target framework supports trimming -->
+ <supportsTrimming>no</supportsTrimming>
+
+ <!-- target framework supports rotated sprites -->
+ <supportsRotation>no</supportsRotation>
+
+ <!-- supports npot sizes -->
+ <supportsNPOT>yes</supportsNPOT>
+
+ <!-- supports file name stripping (remove .png etc.) -->
+ <supportsTrimSpriteNames>yes</supportsTrimSpriteNames>
+
+ <!-- supports texture subpath -->
+ <supportsTextureSubPath>yes</supportsTextureSubPath>
+</exporter>
\ No newline at end of file