]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
GEOM_Displayer - Loading textures with non-ansi paths.
authorapl <apl@opencascade.com>
Fri, 14 Mar 2014 09:05:51 +0000 (13:05 +0400)
committerapl <apl@opencascade.com>
Fri, 14 Mar 2014 09:05:51 +0000 (13:05 +0400)
- Loading textures using Qt tools.
- Image caching.

src/GEOMGUI/GEOM_Displayer.cxx
src/GEOMGUI/GEOM_Displayer.h

index 349cc934a3dd482ca6c2eca0b2d026eccdc267f0..11db53e9278f76c194ebeeb7404f2be81e3db775 100644 (file)
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopoDS.hxx>
+#include <NCollection_DataMap.hxx>
+#include <NCollection_Map.hxx>
 
 #include <Prs3d_ShadingAspect.hxx>
 
 // Hard-coded value of shape deflection coefficient for VTK viewer
 const double VTK_MIN_DEFLECTION = 0.001;
 
+// Pixmap caching support
+namespace
+{
+  typedef NCollection_Map<Handle(GEOM_AISShape)>                    SetOfAISShapes;
+  typedef NCollection_DataMap<Handle(Image_PixMap), SetOfAISShapes> PixmapUsageMap;
+  typedef QMap<QString, Handle(Image_PixMap)>                       PixmapCacheMap;
+
+  static inline PixmapUsageMap& getPixmapUsageMap()
+  {
+    static PixmapUsageMap aMap;
+    return aMap;
+  }
+
+  static inline PixmapCacheMap& getPixmapCacheMap()
+  {
+    static PixmapCacheMap aMap;
+    return aMap;
+  }
+
+  //===========================================================================
+  // Function : cacheTextureFor
+  // Purpose  : Load and cache image for the specified presentation.
+  //===========================================================================
+  static inline Handle(Image_PixMap) cacheTextureFor( const QString& thePath,
+                                                      const Handle(GEOM_AISShape)& theShape )
+  {
+    if ( thePath.isEmpty() )
+      return NULL;
+
+    PixmapUsageMap& aPixmapUsersMap = getPixmapUsageMap();
+    PixmapCacheMap& aPixmapCacheMap = getPixmapCacheMap();
+
+    Handle(Image_PixMap) aPixmap = aPixmapCacheMap.value( thePath, NULL );
+    if ( !aPixmap.IsNull() ) {
+      // point that the texture is used by the presentation
+      if ( !aPixmapUsersMap.IsBound( aPixmap ) )
+        aPixmapUsersMap.Bind( aPixmap, SetOfAISShapes() );
+
+      aPixmapUsersMap.ChangeFind( aPixmap ).Add( theShape );
+
+      return aPixmap;
+    }
+
+    // convert texture to compatible image format
+    QImage anImage = QImage( thePath ).convertToFormat( QImage::Format_ARGB32 );
+    if ( anImage.isNull() )
+      return NULL;
+
+    aPixmap = new Image_PixMap();
+    aPixmap->InitTrash( Image_PixMap::ImgBGRA, anImage.width(), anImage.height() );
+    aPixmap->SetTopDown( Standard_True );
+
+    const uchar* aImageBytes = anImage.bits();
+
+    for ( int aLine = anImage.height() - 1; aLine >= 0; --aLine ) {
+      Image_ColorBGRA* aPixmapBytes = aPixmap->EditData<Image_ColorBGRA>().ChangeRow(aLine);\r
+\r
+      // convert pixels from ARGB to renderer-compatible RGBA\r
+      for ( int aByte = 0; aByte < anImage.width(); ++aByte ) {
+        aPixmapBytes->b() = (Standard_Byte) *aImageBytes++;
+        aPixmapBytes->g() = (Standard_Byte) *aImageBytes++;
+        aPixmapBytes->r() = (Standard_Byte) *aImageBytes++;
+        aPixmapBytes->a() = (Standard_Byte) *aImageBytes++;
+        aPixmapBytes++;
+      }
+    }
+
+    aPixmapCacheMap.insert( thePath, aPixmap );
+
+    if ( !aPixmapUsersMap.IsBound( aPixmap ) )
+      aPixmapUsersMap.Bind( aPixmap, SetOfAISShapes() );
+
+    aPixmapUsersMap.ChangeFind( aPixmap ).Add( theShape );
+
+    return aPixmap;
+  }
+
+  //===========================================================================
+  // Function : releaseTextures
+  // Purpose  : Releases cached textures found for the specified presentation.
+  //===========================================================================
+  static inline void releaseTextures( const SALOME_OCCPrs* thePrs )
+  {
+    const SOCC_Prs* anOccPrs = dynamic_cast<const SOCC_Prs*>( thePrs );
+
+    AIS_ListOfInteractive aListOfIO;
+
+    anOccPrs->GetObjects( aListOfIO );
+
+    AIS_ListIteratorOfListOfInteractive aIterateIO( aListOfIO );
+
+    PixmapUsageMap& aPixmapUsersMap = getPixmapUsageMap();
+    PixmapCacheMap& aPixmapCacheMap = getPixmapCacheMap();
+
+    for ( ; aIterateIO.More(); aIterateIO.Next() )
+    {
+      Handle(GEOM_AISShape) aAISShape =
+        Handle(GEOM_AISShape)::DownCast( aIterateIO.Value() );
+
+      if ( aAISShape.IsNull() )
+        continue;
+
+      const Handle(Image_PixMap)& aPixmap = aAISShape->TexturePixMap();
+      if ( aPixmap.IsNull() )
+        continue;
+
+      if ( !aPixmapUsersMap.IsBound( aPixmap ) )
+        continue;
+
+      SetOfAISShapes& aUsersShapes = aPixmapUsersMap.ChangeFind( aPixmap );
+
+      aUsersShapes.Remove( aAISShape );
+
+      if ( aUsersShapes.IsEmpty() ) {
+        aPixmapUsersMap.UnBind( aPixmap );
+        aPixmapCacheMap.remove( aPixmapCacheMap.key( aPixmap ) );
+      }
+    }
+  }
+}
+
 //================================================================
 // Function : getActiveStudy
 // Purpose  : Get active study, returns 0 if no open study frame
@@ -729,10 +852,10 @@ void GEOM_Displayer::updateShapeProperties( const Handle(GEOM_AISShape)& AISShap
   AISShape->SetOwnDeviationCoefficient( qMax( propMap.value( GEOM::propertyName( GEOM::Deflection ) ).toDouble(), GEOM::minDeflection() ) );
 
   // set texture
-  bool textureAdded = false;
+  QString aImagePath;
   if ( HasTexture() ) {
     // predefined display texture, manually set to displayer via GEOM_Displayer::SetTexture() function 
-    AISShape->SetTextureFileName( TCollection_AsciiString( GetTexture().c_str() ) );
+    aImagePath = GetTexture().c_str();
     if ( ! entry.isEmpty() ) {
       // check that study is active
       SalomeApp_Study* study = getActiveStudy();
@@ -745,21 +868,23 @@ void GEOM_Displayer::updateShapeProperties( const Handle(GEOM_AISShape)& AISShap
         propMap = getObjectProperties( study, entry, myViewFrame );
       }
     }
-    textureAdded = true;
   }
   else {
-    // Texture from properties
-    QString aTexture = propMap.value( GEOM::propertyName( GEOM::Texture ) ).toString();
-    if ( !aTexture.isEmpty() ) {
-      AISShape->SetTextureFileName( TCollection_AsciiString( aTexture.toUtf8().constData() ) );
-       textureAdded = true;
-    }
+    aImagePath = propMap.value( GEOM::propertyName( GEOM::Texture ) ).toString();
   }
-  if ( textureAdded ){ 
+
+  Handle(Image_PixMap) aPixmap;
+  if ( !aImagePath.isEmpty() )
+    aPixmap = cacheTextureFor( aImagePath, AISShape );
+
+  // apply image to shape
+  if ( !aPixmap.IsNull() ) {
+    AISShape->SetTexturePixMap( aPixmap );
     AISShape->SetTextureMapOn();
     AISShape->DisableTextureModulate();
   }
+  else
+    AISShape->SetTextureMapOff();
 
   // set line width
   AISShape->SetWidth( HasWidth() ?
@@ -1823,6 +1948,12 @@ void GEOM_Displayer::AfterDisplay( SALOME_View* v, const SALOME_OCCPrs* p )
   UpdateColorScale(false,false);
 }
 
+void GEOM_Displayer::BeforeErase( SALOME_View* v, const SALOME_OCCPrs* p )
+{
+  LightApp_Displayer::BeforeErase( v, p );
+  releaseTextures( p );
+}
+
 void GEOM_Displayer::AfterErase( SALOME_View* v, const SALOME_OCCPrs* p )
 {
   LightApp_Displayer::AfterErase( v, p );
index dba95ec3eff8ccdd82198c36e2640a88f92f1b75..c610239de08b0d937fd6af51318e6eeac57a0e13 100644 (file)
@@ -175,6 +175,7 @@ public:
   virtual void  Update( SALOME_VTKPrs* );
   virtual void  BeforeDisplay( SALOME_View*, const SALOME_OCCPrs* );
   virtual void  AfterDisplay ( SALOME_View*, const SALOME_OCCPrs* );
+  virtual void  BeforeErase  ( SALOME_View*, const SALOME_OCCPrs* );
   virtual void  AfterErase   ( SALOME_View*, const SALOME_OCCPrs* );
 
   /* This methos is used for activisation/deactivisation of objects to be displayed*/