Reducing the size of ImageActor 99/26399/6
authorKimmo Hoikka <kimmo.hoikka@samsung.com>
Thu, 21 Aug 2014 16:15:00 +0000 (17:15 +0100)
committerKimmo Hoikka <kimmo.hoikka@samsung.com>
Fri, 29 Aug 2014 16:30:33 +0000 (09:30 -0700)
[Problem] memory consumption
[Cause] unnecessary connectiontracker instance
[Solution] remove it and implement connectiontrackerinterface instead

Before
-----

Dali-demo
ImageActors 55 * 336b = 18.480b
Cube transition
ImageActors 969 * 336b = 325.584b

After
-----
Dali-demo
ImageActors 55 * 296b = 16.280b
Cube transition
ImageActors 969 * 296b = 286.824b

Saving 11% of RAM

Change-Id: Icfbaca952dd066dce8d05695ed5e5e471ca176c9

dali/internal/event/actors/image-actor-impl.cpp
dali/internal/event/actors/image-actor-impl.h

index f192359..03b892e 100644 (file)
@@ -101,37 +101,15 @@ ImageActorPtr ImageActor::New( Image* anImage )
   ImageActorPtr actor( new ImageActor() );
   ImagePtr theImage( anImage );
 
-  // Second-phase construction
+  // Second-phase construction of base class
   actor->Initialize();
-  NinePatchImage* ninePatchImage = NULL;
-
-  // Automatically convert upcasted nine-patch images to cropped bitmap
-  ninePatchImage = NinePatchImage::GetNinePatchImage( anImage );
-
-  if( ninePatchImage != NULL )
-  {
-    theImage = ninePatchImage->CreateCroppedBitmapImage();
-    // Note, if theImage is empty, the nine-patch image was not loaded
-  }
 
   // Create the attachment
   actor->mImageAttachment = ImageAttachment::New( *actor->mNode, theImage.Get() );
   actor->Attach( *actor->mImageAttachment );
 
-  // Adjust the actor's size
-  if( theImage )
-  {
-    actor->mImageNext.Set( theImage.Get(), false );
-    actor->OnImageSet( *theImage );
-    actor->SetNaturalSize( *theImage );
-  }
-
-  if( ninePatchImage != NULL )
-  {
-    actor->SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
-    Vector4 border = ninePatchImage->GetStretchBorders();
-    actor->SetNinePatchBorder( border, true );
-  }
+  // don't call the external version as attachment already has the image
+  actor->SetImageInternal( NULL, anImage );
 
   return actor;
 }
@@ -169,34 +147,7 @@ void ImageActor::SetImage( Image* image )
     return;
   }
 
-  mLoadedConnection.DisconnectAll();
-
-  ImagePtr imagePtr( image );
-
-  // Automatically convert nine-patch images to cropped bitmap
-  NinePatchImage* ninePatchImage = NinePatchImage::GetNinePatchImage( image );
-  if( ninePatchImage )
-  {
-    imagePtr = ninePatchImage->CreateCroppedBitmapImage();
-  }
-
-  mImageNext.Set( imagePtr.Get(), OnStage() );
-
-  if( ninePatchImage )
-  {
-    SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
-    SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
-  }
-
-  if ( !imagePtr )
-  {
-    mImageAttachment->SetImage( NULL );
-  }
-  else
-  {
-    // don't disconnect currently shown image until we made sure that the new one is loaded
-    OnImageSet( *imagePtr.Get() );
-  }
+  SetImageInternal( currentImage, image );
 }
 
 Dali::Image ImageActor::GetImage()
@@ -321,33 +272,37 @@ RenderableAttachment& ImageActor::GetRenderableAttachment() const
   return *mImageAttachment;
 }
 
+void ImageActor::SignalConnected( SlotObserver*, CallbackBase* )
+{
+  // nothing to do as we only ever connect to one signal, which we disconnect from in the destructor
+}
+
+void ImageActor::SignalDisconnected( SlotObserver*, CallbackBase* )
+{
+  // nothing to do as we only ever connect to one signal, which we disconnect from in the destructor
+  // also worth noting that we own the image whose signal we connect to so in practice this method is never called.
+}
+
 ImageActor::ImageActor()
 : RenderableActor(),
+  mFadeInDuration( 1.0f ),
   mUsingNaturalSize(true),
   mInternalSetSize(false),
   mFadeIn( false ),
-  mFadeInitial( true ),
-  mLoadedConnection( this ),
-  mFadeInDuration( 1.0f )
+  mFadeInitial( true )
 {
 }
 
 ImageActor::~ImageActor()
 {
-  // ScopedConnection disconnects automatically
-}
-
-void ImageActor::OnImageSet( Image& image )
-{
-  // observe image loaded
-  if( Dali::ResourceLoading == image.GetLoadingState() && ! image.GetFilename().empty() )
-  {
-    image.LoadingFinishedSignal().Connect( mLoadedConnection, &ImageActor::ImageLoaded );
-  }
-  else
+  if( mImageAttachment )
   {
-    // image already loaded, or generated
-    ImageLoaded( Dali::Image(&image) );
+    Dali::Image image = mImageAttachment->GetImage();
+    if( image )
+    {
+      // just call Disconnect as if not connected it is a no-op
+      image.LoadingFinishedSignal().Disconnect( this, &ImageActor::ImageLoaded );
+    }
   }
 }
 
@@ -688,6 +643,46 @@ Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
   return ret;
 }
 
+void ImageActor::SetImageInternal( Image* currentImage, Image* image )
+{
+  if( currentImage )
+  {
+    // just call Disconnect as if not connected it is a no-op
+    currentImage->LoadingFinishedSignal().Disconnect( this, &ImageActor::ImageLoaded );
+  }
+
+  ImagePtr imagePtr( image );
+  // Automatically convert nine-patch images to cropped bitmap
+  NinePatchImage* ninePatchImage = NinePatchImage::GetNinePatchImage( image );
+  if( ninePatchImage )
+  {
+    imagePtr = ninePatchImage->CreateCroppedBitmapImage();
+  }
+  mImageNext.Set( imagePtr.Get(), OnStage() );
+  if( ninePatchImage )
+  {
+    SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
+    SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
+  }
+  if( !imagePtr )
+  {
+    mImageAttachment->SetImage( NULL );
+  }
+  else
+  {
+    // don't disconnect currently shown image until we made sure that the new one is loaded
+    if( Dali::ResourceLoading == image->GetLoadingState() && !image->GetFilename().empty() )
+    {
+      // observe image loading, @todo stop using signals internally!
+      image->LoadingFinishedSignal().Connect( this, &ImageActor::ImageLoaded );
+    }
+    else
+    {
+      // image already loaded, generated or 9 patch
+      ImageLoaded( Dali::Image( image ) );
+    }
+  }
+}
 
 } // namespace Internal
 
index cf3d0c4..beac18d 100644 (file)
@@ -48,7 +48,7 @@ class Image;
  * mImageAttachment's member object. The first one points to the Image object that is going to
  * be displayed next, the second one to the Image that is currently being displayed.
  */
-class ImageActor : public RenderableActor
+class ImageActor : public RenderableActor, public ConnectionTrackerInterface
 {
 public:
 
@@ -240,6 +240,18 @@ private: // From RenderableActor
    */
   virtual RenderableAttachment& GetRenderableAttachment() const;
 
+private: // From ConnectionTrackerInterface
+
+  /**
+   * @copydoc SignalObserver::SignalConnected
+   */
+  virtual void SignalConnected( SlotObserver*, CallbackBase* );
+
+  /**
+   * @copydoc ConnectionTrackerInterface::SignalDisconnected
+   */
+  virtual void SignalDisconnected(Dali::SlotObserver*, Dali::CallbackBase* );
+
 protected:
 
   /**
@@ -254,13 +266,12 @@ protected:
 
 private:
 
-  // Helper for overloads of SetImage().
-  void OnImageSet( Image& image );
-
-  // Helper to set the actor to the image's natural size
+  /**
+   * Helper to set the actor to the image's natural size
+   * @param image that is used
+   */
   void SetNaturalSize( Image& image );
 
-
   /**
    * From Actor.
    * This is called after SizeSet() has been called.
@@ -293,21 +304,26 @@ private:
    */
   void FadeIn();
 
+  /**
+   * Helper to set image internally
+   * @param currentImage
+   * @param image to set
+   */
+  void SetImageInternal( Image* currentImage, Image* image );
+
 private:
 
   ImageAttachmentPtr mImageAttachment; ///< Used to display the image (holds a pointer to currently showed Image)
   ImageConnector     mImageNext;       ///< Manages the Image this ImageActor will show (used when changing displayed image)
 
-  // flags, compressed to bitfield (uses only 4 bytes)
-  bool mUsingNaturalSize:1; ///< True only when the actor is using
-  bool mInternalSetSize:1;  ///< True whilst setting size internally, false at all other times
-  bool mFadeIn:1;           ///< True if fade in animation is enabled
-  bool mFadeInitial:1;      ///< True if fading in for the first time
-
-  SlotDelegate<ImageActor> mLoadedConnection; ///< Tracks the connection to the "loading finished" signal
-
   // For fade-in animations
-  float        mFadeInDuration;  ///< Length of animation
+  float mFadeInDuration;  ///< Length of animation
+
+  // flags, compressed to bitfield (uses only 4 bytes)
+  bool mUsingNaturalSize:1;      ///< True only when the actor is using
+  bool mInternalSetSize:1;       ///< True whilst setting size internally, false at all other times
+  bool mFadeIn:1;                ///< True if fade in animation is enabled
+  bool mFadeInitial:1;           ///< True if fading in for the first time
 
   static bool mFirstInstance ;
   static DefaultPropertyLookup* mDefaultImageActorPropertyLookup; ///< Default properties