From: apl Date: Fri, 14 Mar 2014 09:05:51 +0000 (+0400) Subject: GEOM_Displayer - Loading textures with non-ansi paths. X-Git-Tag: V7_4_0a1~10 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=8bbd6e250f95b32eecee9f030750c5ddf96fc155;p=modules%2Fgeom.git GEOM_Displayer - Loading textures with non-ansi paths. - Loading textures using Qt tools. - Image caching. --- diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx index 349cc934a..11db53e92 100644 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -106,6 +106,8 @@ #include #include #include +#include +#include #include @@ -136,6 +138,127 @@ // Hard-coded value of shape deflection coefficient for VTK viewer const double VTK_MIN_DEFLECTION = 0.001; +// Pixmap caching support +namespace +{ + typedef NCollection_Map SetOfAISShapes; + typedef NCollection_DataMap PixmapUsageMap; + typedef QMap 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().ChangeRow(aLine); + + // convert pixels from ARGB to renderer-compatible RGBA + 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( 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 ); diff --git a/src/GEOMGUI/GEOM_Displayer.h b/src/GEOMGUI/GEOM_Displayer.h index dba95ec3e..c610239de 100644 --- a/src/GEOMGUI/GEOM_Displayer.h +++ b/src/GEOMGUI/GEOM_Displayer.h @@ -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*/