2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
19 #include <dali/internal/event/actor-attachments/text-attachment-impl.h>
23 #include <dali/public-api/common/dali-common.h>
24 #include <dali/internal/update/node-attachments/scene-graph-text-attachment.h>
25 #include <dali/internal/event/common/stage-impl.h>
26 #include <dali/internal/common/text-parameters.h>
35 TextAttachmentPtr TextAttachment::New( const SceneGraph::Node& parentNode, const TextArray& text, FontPointer font, bool isLeftToRight )
37 StagePtr stage = Stage::GetCurrent();
39 TextAttachmentPtr attachment( new TextAttachment( *stage ) );
41 // Second-phase construction
43 attachment->mFont = font;
44 attachment->mText = text;
45 attachment->mIsLeftToRight = isLeftToRight;
47 // Transfer object ownership of scene-object to message
48 SceneGraph::TextAttachment* sceneObject = SceneGraph::TextAttachment::New();
50 AttachToNodeMessage( stage->GetUpdateManager(), parentNode, sceneObject );
52 // Keep raw pointer for message passing
53 attachment->mSceneObject = sceneObject;
55 attachment->SetSmoothEdge(attachment->mSmoothing); // adjust smoothedge for font weight
60 TextAttachment::TextAttachment( Stage& stage )
61 : RenderableAttachment( stage ),
62 mTextRequestHelper( *this ),
63 mUnderlineEnabled( false ),
67 mUnderlineChanged( true ),
68 mItalicsChanged( true ),
69 mItalicsEnabled( false ),
70 mTextureIdSet( false ),
72 mSmoothing(Dali::TextStyle::DEFAULT_SMOOTH_EDGE_DISTANCE_FIELD),
73 mItalicsAngle( Radian(0.0f) ),
74 mUnderlineThickness( 0.f ),
75 mUnderlinePosition( 0.f ),
76 mTextSize( Vector3::ZERO ),
77 mWeight( TextStyle::REGULAR ),
82 TextAttachment::~TextAttachment()
87 void TextAttachment::SetText(const TextArray& text)
89 // return if the text hasn't changed
90 if( (text.size() == mText.size() ) &&
91 std::equal(mText.begin(), mText.end(), text.begin ()) )
96 // Cache for public getters
101 void TextAttachment::SetFont(Font& font)
107 // References the font
112 void TextAttachment::SetGradientColor( const Vector4& color )
114 AllocateTextParameters();
116 if( mTextParameters->mGradientColor != color )
118 mTextParameters->mGradientColor = color;
120 SetGradientColorMessage( mStage->GetUpdateInterface(), *mSceneObject, color );
124 const Vector4& TextAttachment::GetGradientColor() const
126 if( mTextParameters )
128 return mTextParameters->mGradientColor;
132 return TextStyle::DEFAULT_GRADIENT_COLOR;
136 void TextAttachment::SetGradientStartPoint( const Vector2& position )
138 AllocateTextParameters();
140 if( mTextParameters->mGradientStartPoint != position )
142 mTextParameters->mGradientStartPoint = position;
144 SetGradientStartPointMessage( mStage->GetUpdateInterface(), *mSceneObject, position );
148 const Vector2& TextAttachment::GetGradientStartPoint() const
150 if( mTextParameters )
152 return mTextParameters->mGradientStartPoint;
156 return TextStyle::DEFAULT_GRADIENT_START_POINT;
160 void TextAttachment::SetGradientEndPoint( const Vector2& position )
162 AllocateTextParameters();
164 if( mTextParameters->mGradientEndPoint != position )
166 mTextParameters->mGradientEndPoint = position;
168 SetGradientEndPointMessage( mStage->GetUpdateInterface(), *mSceneObject, position );
172 const Vector2& TextAttachment::GetGradientEndPoint() const
174 if( mTextParameters )
176 return mTextParameters->mGradientEndPoint;
180 return TextStyle::DEFAULT_GRADIENT_END_POINT;
184 void TextAttachment::SetSmoothEdge( float smoothEdge )
186 mSmoothing = smoothEdge;
187 float weightedSmoothing = smoothEdge;
189 // Adjust edge smoothing for font weight
190 const float BOLDER = 0.20f;
191 const float LIGHTER = 1.65f;
192 const float offset = 1.0f - ( ( 1.0f / Dali::TextStyle::EXTRABLACK ) * mWeight );
193 weightedSmoothing *= BOLDER + ( ( LIGHTER - BOLDER ) * offset );
194 weightedSmoothing = std::max( 0.0f, weightedSmoothing );
195 weightedSmoothing = std::min( 1.0f, weightedSmoothing );
197 SetSmoothEdgeMessage( mStage->GetUpdateInterface(), *mSceneObject, weightedSmoothing );
200 float TextAttachment::GetSmoothEdge() const
205 void TextAttachment::SetOutline( bool enable, const Vector4& color, const Vector2& thickness )
207 AllocateTextParameters();
209 if (enable != mTextParameters->mOutlineEnabled || color != mTextParameters->mOutlineColor || thickness != mTextParameters->mOutline)
211 mTextParameters->SetOutline( enable, color, thickness );
213 SetOutlineMessage( mStage->GetUpdateInterface(), *mSceneObject, enable, color, thickness );
217 bool TextAttachment::GetOutline() const
219 bool result( false );
221 if( mTextParameters )
223 result = mTextParameters->mOutlineEnabled;
229 void TextAttachment::GetOutlineParams( Vector4& color, Vector2& thickness ) const
231 if( mTextParameters )
233 color = mTextParameters->mOutlineColor;
234 thickness = mTextParameters->mOutline;
238 color = TextStyle::DEFAULT_OUTLINE_COLOR;
239 thickness = TextStyle::DEFAULT_OUTLINE_THICKNESS;
243 void TextAttachment::SetGlow( bool enable, const Vector4& color, float intensity )
245 AllocateTextParameters();
247 if (enable != mTextParameters->mGlowEnabled || color != mTextParameters->mGlowColor || fabsf(intensity - mTextParameters->mGlow) > Math::MACHINE_EPSILON_1000)
249 mTextParameters->SetGlow( enable, color, intensity );
251 SetGlowMessage( mStage->GetUpdateInterface(), *mSceneObject, enable, color, intensity );
255 bool TextAttachment::GetGlow() const
257 bool result( false );
259 if( mTextParameters )
261 result = mTextParameters->mGlowEnabled;
267 void TextAttachment::GetGlowParams( Vector4& color, float& intensity) const
269 if( mTextParameters )
271 color = mTextParameters->mGlowColor;
272 intensity = mTextParameters->mGlow;
276 color = TextStyle::DEFAULT_GLOW_COLOR;
277 intensity = TextStyle::DEFAULT_GLOW_INTENSITY;
281 void TextAttachment::SetShadow(bool enable, const Vector4& color, const Vector2& offset, const float size)
283 AllocateTextParameters();
285 if (enable != mTextParameters->mDropShadowEnabled ||
286 color != mTextParameters->mDropShadowColor ||
287 offset != mTextParameters->mDropShadow ||
288 fabsf(size - mTextParameters->mDropShadowSize) > Math::MACHINE_EPSILON_1 )
290 mTextParameters->SetShadow( enable, color, offset, size );
292 const float unitPointSize( 64.0f );
293 const float unitsToPixels( mFont->GetUnitsToPixels());
295 float shadowSize( (size * 0.25f) / unitsToPixels );
297 Vector2 shadowOffset( offset * ( unitPointSize / mFont->GetPointSize() ) );
299 SetDropShadowMessage( mStage->GetUpdateInterface(), *mSceneObject, enable, color, shadowOffset, shadowSize );
303 bool TextAttachment::GetShadow() const
305 bool result( false );
307 if( mTextParameters )
309 result = mTextParameters->mDropShadowEnabled;
315 void TextAttachment::GetShadowParams( Vector4& color, Vector2& offset, float& size ) const
317 if( mTextParameters )
319 color = mTextParameters->mDropShadowColor;
320 offset = mTextParameters->mDropShadow;
321 size = mTextParameters->mDropShadowSize;
325 color = TextStyle::DEFAULT_SHADOW_COLOR;
326 offset = TextStyle::DEFAULT_SHADOW_OFFSET;
327 size = TextStyle::DEFAULT_SHADOW_SIZE;
331 void TextAttachment::SetTextColor(const Vector4& color)
333 bool sendMessage( false );
335 if( NULL == mTextColor )
337 if( color != TextStyle::DEFAULT_TEXT_COLOR )
339 // A color (different from default) has been set, so allocate storage for the text color
340 mTextColor = new Vector4( color );
346 if( *mTextColor != color )
348 // text color has changed
356 SetTextColorMessage( mStage->GetUpdateInterface(), *mSceneObject, color );
360 Vector4 TextAttachment::GetTextColor() const
364 if( NULL != mTextColor )
370 color = TextStyle::DEFAULT_TEXT_COLOR;
376 void TextAttachment::SetItalics( const Radian& angle )
378 if ( angle != mItalicsAngle )
380 mItalicsChanged = true;
381 mItalicsAngle = angle;
383 Radian radian0( 0.0f );
385 if( radian0 != mItalicsAngle )
387 mItalicsEnabled = true;
391 mItalicsEnabled = false;
395 const Radian& TextAttachment::GetItalics() const
397 return mItalicsAngle;
400 void TextAttachment::SetUnderline( bool enable, float thickness, float position )
402 if ( enable != mUnderlineEnabled )
404 mUnderlineEnabled = enable;
405 mUnderlineChanged = true;
408 if( mUnderlineEnabled )
410 if( fabsf( thickness - mUnderlineThickness ) > Math::MACHINE_EPSILON_0 )
412 mUnderlineThickness = thickness;
413 mUnderlineChanged = true;
416 if( fabsf( position - mUnderlinePosition ) > Math::MACHINE_EPSILON_0 )
418 mUnderlinePosition = position;
419 mUnderlineChanged = true;
424 bool TextAttachment::GetUnderline() const
426 return mUnderlineEnabled;
429 float TextAttachment::GetUnderlineThickness() const
431 return mUnderlineThickness;
434 float TextAttachment::GetUnderlinePosition() const
436 return mUnderlinePosition;
439 void TextAttachment::SetWeight( TextStyle::Weight weight )
443 SetSmoothEdge(mSmoothing);
446 TextStyle::Weight TextAttachment::GetWeight() const
451 Vector3 TextAttachment::MeasureText() const
453 return mFont->MeasureText( mText );
456 void TextAttachment::TextChanged()
458 DALI_LOG_INFO(Debug::Filter::gResource, Debug::Verbose, "TextAttachment::TextChanged() TextModified:%s TextEmpty:%s\n", IsTextModified()?"Y":"N", mText.empty()?"Y":"N");
460 if( !IsTextModified() )
465 // if the underline or italics have changed we trigger a text request
466 if( mUnderlineChanged || mItalicsChanged )
471 TextFormat format( mUnderlineEnabled, mIsLeftToRight, mItalicsEnabled, mItalicsAngle, mFont->GetPointSize(), mUnderlineThickness, mUnderlinePosition );
473 if ( mTextChanged && mFontChanged )
475 mVertexBuffer = mTextRequestHelper.SetTextAndFont( mText, mFont, format );
477 else if( mTextChanged )
479 mVertexBuffer = mTextRequestHelper.SetText( mText, format );
481 else if ( mFontChanged )
483 mVertexBuffer = mTextRequestHelper.SetFont( mFont, format );
486 // sceneObject is being used in a separate thread; queue a message to set
489 mTextChanged = false;
490 mFontChanged = false;
491 mUnderlineChanged = false;
492 mItalicsChanged = false;
495 bool TextAttachment::IsTextLoaded()
497 bool loaded = mTextRequestHelper.IsTextLoaded();
498 if( loaded && !mTextureIdSet )
500 mTextureIdSet = true;
506 void TextAttachment::TextureResized( const TextureIdList& oldTextureIds, unsigned int newTextureId )
508 bool matched( false );
510 // check if resized texture is the one we are using
511 for( std::size_t i = 0, count = oldTextureIds.size(); i < count; ++i )
513 if( oldTextureIds[i] == mTextureId )
520 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "TextAttachment::TextureResized() Current texture: %d New texture: %d\n", mTextureId, newTextureId);
522 if( newTextureId == mTextureId )
524 // nothing has changed, we are using the new texture already
528 // the texture we're using has been replaced
529 // re-request the text vertex information and update the texture id on the scene graph text attachment
532 mTextRequestHelper.TextureChanged( mTextureId, newTextureId );
533 mTextureId = newTextureId;
540 void TextAttachment::TextureSplit( FontId fontId, const TextureIdList& oldTextureIds, unsigned int newTextureId )
542 // currently not supported.
543 // the implementation will be if( fontId == mFont->GetId() ) TextureResized(..);
546 bool TextAttachment::IsTextModified()
548 return ( mTextChanged || mFontChanged || mUnderlineChanged || mItalicsChanged );
551 void TextAttachment::AllocateTextParameters()
553 if( !mTextParameters )
555 mTextParameters = new TextParameters;
559 void TextAttachment::OnStageConnection2()
564 void TextAttachment::OnStageDisconnection2()
569 const SceneGraph::RenderableAttachment& TextAttachment::GetSceneObject() const
571 DALI_ASSERT_DEBUG( mSceneObject != NULL );
572 return *mSceneObject;
575 void TextAttachment::SetTextChanges()
577 // record the natural size of the text
578 mTextSize = mVertexBuffer->mVertexMax;
580 // remember the texture id, so we can detect atlas resizes / splits
581 mTextureId = mVertexBuffer->mTextureId;
583 EventToUpdate& eventToUpdate( mStage->GetUpdateInterface() );
584 const SceneGraph::TextAttachment& attachment( *mSceneObject );
586 if( mTextChanged || mFontChanged )
588 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "TextAttachment::SetTextChanges() Sending VertexBuffer to attachment:%p textureId:%d\n", &attachment, mVertexBuffer->mTextureId);
590 // release the vertex buffer to pass ownership to the scene-graph-text-attachment
591 SetTextVertexBufferMessage( eventToUpdate, attachment, *mVertexBuffer.Release() );
596 } // namespace Internal