Convert more shaders in dali-toolkit and dali-scene-loader to use shader compilation...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-scroller.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/text/text-scroller.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/internal/text/text-scroller-interface.h>
26 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
27
28 namespace Dali
29 {
30
31 namespace Toolkit
32 {
33
34 namespace
35 {
36
37 #if defined ( DEBUG_ENABLED )
38   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_SCROLLING");
39 #endif
40
41 const int MINIMUM_SCROLL_SPEED = 1; // Speed should be set by Property system.
42
43 /**
44  * @brief How the text should be aligned horizontally when scrolling the text.
45  *
46  * -0.5f aligns the text to the left, 0.0f aligns the text to the center, 0.5f aligns the text to the right.
47  * The final alignment depends on two factors:
48  *   1) The alignment value of the text label (Use Text::HorizontalAlignment enumerations).
49  *   2) The text direction, i.e. whether it's LTR or RTL (0 = LTR, 1 = RTL).
50  */
51 const float HORIZONTAL_ALIGNMENT_TABLE[ Text::HorizontalAlignment::END+1 ][ 2 ] =
52 {
53   // HorizontalAlignment::BEGIN
54   {
55     -0.5f, // LTR
56     0.5f   // RTL
57   },
58
59   // HorizontalAlignment::CENTER
60   {
61     0.0f,  // LTR
62     0.0f   // RTL
63   },
64
65   // HorizontalAlignment::END
66   {
67     0.5f,  // LTR
68     -0.5f  // RTL
69   }
70 };
71
72 /**
73  * @brief How the text should be aligned vertically when scrolling the text.
74  *
75  * -0.5f aligns the text to the top, 0.0f aligns the text to the center, 0.5f aligns the text to the bottom.
76  * The alignment depends on the alignment value of the text label (Use Text::VerticalAlignment enumerations).
77  */
78 const float VERTICAL_ALIGNMENT_TABLE[ Text::VerticalAlignment::BOTTOM+1 ] =
79 {
80   -0.5f, // VerticalAlignment::TOP
81   0.0f,  // VerticalAlignment::CENTER
82   0.5f   // VerticalAlignment::BOTTOM
83 };
84
85 } // namespace
86
87 namespace Text
88 {
89
90 TextScrollerPtr TextScroller::New( ScrollerInterface& scrollerInterface )
91 {
92   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::New\n" );
93
94   TextScrollerPtr textScroller( new TextScroller( scrollerInterface) );
95   return textScroller;
96 }
97
98 void TextScroller::SetGap( int gap )
99 {
100   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetGap gap[%d]\n", gap );
101   mWrapGap = static_cast<float>(gap);
102 }
103
104 int TextScroller::GetGap() const
105 {
106   return static_cast<int>(mWrapGap);
107 }
108
109 void TextScroller::SetSpeed( int scrollSpeed )
110 {
111   mScrollSpeed = std::max( MINIMUM_SCROLL_SPEED, scrollSpeed );
112 }
113
114 int TextScroller::GetSpeed() const
115 {
116   return mScrollSpeed;
117 }
118
119 void TextScroller::SetLoopCount( int loopCount )
120 {
121   if ( loopCount >= 0 )
122   {
123     mLoopCount = loopCount;
124   }
125
126   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount [%d] Status[%s]\n", mLoopCount, (loopCount)?"looping":"stop" );
127 }
128
129 int TextScroller::GetLoopCount() const
130 {
131   return mLoopCount;
132 }
133
134 void TextScroller::SetLoopDelay( float delay )
135 {
136   mLoopDelay = delay;
137 }
138
139 float TextScroller::GetLoopDelay() const
140 {
141   return mLoopDelay;
142 }
143
144 void TextScroller::SetStopMode( TextLabel::AutoScrollStopMode::Type stopMode )
145 {
146   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetAutoScrollStopMode [%s]\n",(stopMode == TextLabel::AutoScrollStopMode::IMMEDIATE)?"IMMEDIATE":"FINISH_LOOP" );
147   mStopMode = stopMode;
148 }
149
150 void TextScroller::StopScrolling()
151 {
152   if ( mScrollAnimation && mScrollAnimation.GetState() == Animation::PLAYING )
153   {
154     switch( mStopMode )
155     {
156       case TextLabel::AutoScrollStopMode::IMMEDIATE:
157       {
158         mScrollAnimation.Stop();
159         mScrollerInterface.ScrollingFinished();
160         break;
161       }
162       case TextLabel::AutoScrollStopMode::FINISH_LOOP:
163       {
164         mScrollAnimation.SetLoopCount( 1 ); // As animation already playing this allows the current animation to finish instead of trying to stop mid-way
165         break;
166       }
167       default:
168       {
169         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Undifined AutoScrollStopMode\n" );
170       }
171     }
172   }
173   else
174   {
175     mScrollerInterface.ScrollingFinished();
176   }
177 }
178
179 TextLabel::AutoScrollStopMode::Type TextScroller::GetStopMode() const
180 {
181   return mStopMode;
182 }
183
184 TextScroller::TextScroller( ScrollerInterface& scrollerInterface )
185 : mScrollerInterface( scrollerInterface ),
186   mScrollDeltaIndex( Property::INVALID_INDEX ),
187   mScrollSpeed( MINIMUM_SCROLL_SPEED ),
188   mLoopCount( 1 ),
189   mLoopDelay( 0.0f ),
190   mWrapGap( 0.0f ),
191   mStopMode( TextLabel::AutoScrollStopMode::FINISH_LOOP )
192 {
193   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller Default Constructor\n" );
194 }
195
196 TextScroller::~TextScroller()
197 {
198 }
199
200 void TextScroller::SetParameters( Actor scrollingTextActor, Renderer renderer, TextureSet textureSet, const Size& controlSize, const Size& textureSize, const float wrapGap, CharacterDirection direction, HorizontalAlignment::Type horizontalAlignment, VerticalAlignment::Type verticalAlignment )
201 {
202   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] textureSize[%f,%f] direction[%d]\n",
203                  controlSize.x, controlSize.y, textureSize.x, textureSize.y, direction );
204
205   mRenderer = renderer;
206
207   float animationProgress = 0.0f;
208   int   remainedLoop = mLoopCount;
209   if ( mScrollAnimation )
210   {
211     if( mScrollAnimation.GetState() == Animation::PLAYING )
212     {
213       animationProgress = mScrollAnimation.GetCurrentProgress();
214
215       if( mLoopCount > 0 ) // If not a ininity loop, then calculate remained loop
216       {
217         remainedLoop = mLoopCount - ( mScrollAnimation.GetCurrentLoop() );
218         remainedLoop = ( remainedLoop <= 0 ? 1 : remainedLoop );
219       }
220     }
221     mScrollAnimation.Clear();
222
223     // Reset to the original shader and texture before scrolling
224     mRenderer.SetShader(mShader);
225     if( mTextureSet )
226     {
227       mRenderer.SetTextures( mTextureSet );
228     }
229   }
230
231   mShader = mRenderer.GetShader();
232   mTextureSet = mRenderer.GetTextures();
233
234   // Set the shader and texture for scrolling
235   Shader shader = Shader::New( SHADER_TEXT_SCROLLER_SHADER_VERT, SHADER_TEXT_SCROLLER_SHADER_FRAG, Shader::Hint::NONE );
236   mRenderer.SetShader( shader );
237   mRenderer.SetTextures( textureSet );
238
239   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters wrapGap[%f]\n", wrapGap );
240
241   float horizontalAlign;
242
243   if( textureSize.x > controlSize.x )
244   {
245     // if Text is elided, scroll should start at the begin of text.
246     horizontalAlign = HORIZONTAL_ALIGNMENT_TABLE[HorizontalAlignment::BEGIN][ direction ];
247   }
248   else
249   {
250     horizontalAlign = HORIZONTAL_ALIGNMENT_TABLE[ horizontalAlignment ][ direction ];
251   }
252
253   const float verticalAlign = VERTICAL_ALIGNMENT_TABLE[ verticalAlignment ];
254
255   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters horizontalAlign[%f], verticalAlign[%f]\n", horizontalAlign, verticalAlign );
256
257   shader.RegisterProperty( "uTextureSize", textureSize );
258   shader.RegisterProperty( "uHorizontalAlign", horizontalAlign );
259   shader.RegisterProperty( "uVerticalAlign", verticalAlign );
260   shader.RegisterProperty( "uGap", wrapGap );
261   mScrollDeltaIndex = shader.RegisterProperty( "uDelta", 0.0f );
262
263   float scrollAmount = std::max( textureSize.width, controlSize.width );
264   float scrollDuration =  scrollAmount / mScrollSpeed;
265
266   if ( direction  )
267   {
268      scrollAmount = -scrollAmount; // reverse direction of scrolling
269   }
270
271   StartScrolling( scrollingTextActor, scrollAmount, scrollDuration, remainedLoop );
272   mScrollAnimation.SetCurrentProgress(animationProgress);
273 }
274
275 void TextScroller::AutoScrollAnimationFinished( Dali::Animation& animation )
276 {
277   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::AutoScrollAnimationFinished\n" );
278   mScrollerInterface.ScrollingFinished();
279
280   // Revert to the original shader and texture after scrolling
281   mRenderer.SetShader(mShader);
282   if ( mTextureSet )
283   {
284     mRenderer.SetTextures( mTextureSet );
285   }
286 }
287
288 void TextScroller::StartScrolling( Actor scrollingTextActor, float scrollAmount, float scrollDuration, int loopCount )
289 {
290   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::StartScrolling scrollAmount[%f] scrollDuration[%f], loop[%d] speed[%d]\n", scrollAmount, scrollDuration, loopCount, mScrollSpeed );
291
292   Shader shader = mRenderer.GetShader();
293   mScrollAnimation = Animation::New( scrollDuration );
294   mScrollAnimation.AnimateTo( Property( shader, mScrollDeltaIndex ), scrollAmount, TimePeriod( mLoopDelay, scrollDuration ) );
295   mScrollAnimation.SetEndAction( Animation::DISCARD );
296   mScrollAnimation.SetLoopCount( loopCount );
297   mScrollAnimation.FinishedSignal().Connect( this, &TextScroller::AutoScrollAnimationFinished );
298   mScrollAnimation.Play();
299 }
300
301 } // namespace Text
302
303 } // namespace Toolkit
304
305 } // namespace Dali