VTK
|
00001 /*========================================================================= 00002 00003 Program: Visualization Toolkit 00004 Module: vtkOpenGLContextDevice2DPrivate.h 00005 00006 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 00007 All rights reserved. 00008 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00015 00032 #ifndef __vtkOpenGLContextDevice2DPrivate_h 00033 #define __vtkOpenGLContextDevice2DPrivate_h 00034 00035 #include "vtkOpenGLContextDevice2D.h" 00036 00037 #include "vtkColor.h" 00038 #include "vtkTextProperty.h" 00039 #include "vtkFreeTypeTools.h" 00040 #include "vtkStdString.h" 00041 #include "vtkUnicodeString.h" 00042 00043 #include <algorithm> 00044 #include <list> 00045 #include <utility> 00046 00047 // .NAME vtkTextureImageCache - store vtkTexture and vtkImageData identified by 00048 // a unique key. 00049 // .SECTION Description 00050 // Creating and initializing a texture can be time consuming, 00051 // vtkTextureImageCache offers the ability to reuse them as much as possible. 00052 template <class Key> 00053 class vtkTextureImageCache 00054 { 00055 public: 00056 struct CacheData 00057 { 00058 vtkSmartPointer<vtkImageData> ImageData; 00059 vtkSmartPointer<vtkTexture> Texture; 00060 // Dimensions of the text. Used for generating texture coords when the image 00061 // dimensions are scaled to a power of two. 00062 int TextWidth; 00063 int TextHeight; 00064 }; 00065 00067 00068 struct CacheElement: public std::pair<Key, CacheData> 00069 { 00070 // Default constructor 00071 CacheElement() 00072 : std::pair<Key, CacheData>(Key(), CacheData()){} 00073 // Construct a partial CacheElement with no CacheData 00074 // This can be used for temporary CacheElement used to search a given 00075 // key into the cache list. 00076 CacheElement(const Key& key) 00077 : std::pair<Key, CacheData>(key, CacheData()){} 00078 // Standard constructor of CacheElement 00079 CacheElement(const Key& key, const CacheData& cacheData) 00080 : std::pair<Key, CacheData>(key, cacheData){} 00081 // Operator tuned to be used when searching into the cache list using 00082 // std::find() 00083 bool operator==(const CacheElement& other)const 00084 { 00085 // Here we cheat and make the comparison only on the key, this allows 00086 // us to use std::find() to search for a given key. 00087 return this->first == other.first; 00088 } 00089 }; 00091 00093 00095 vtkTextureImageCache() 00096 { 00097 this->MaxSize = 50; 00098 } 00100 00102 00104 bool IsKeyInCache(const Key& key)const 00105 { 00106 return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end(); 00107 } 00109 00114 CacheData& GetCacheData(const Key& key); 00115 00117 00119 void ReleaseGraphicsResources(vtkWindow* window) 00120 { 00121 typename std::list<CacheElement >::iterator it; 00122 for (it = this->Cache.begin(); it != this->Cache.end(); ++it) 00123 { 00124 it->second.Texture->ReleaseGraphicsResources(window); 00125 } 00126 } 00128 00129 protected: 00131 00133 CacheData& AddCacheData(const Key& key, const CacheData& cacheData) 00134 { 00135 assert(!this->IsKeyInCache(key)); 00136 if (this->Cache.size() >= this->MaxSize) 00137 { 00138 this->Cache.pop_back(); 00139 } 00140 this->Cache.push_front(CacheElement(key, cacheData)); 00141 return this->Cache.begin()->second; 00142 } 00144 00146 std::list<CacheElement > Cache; 00148 00149 size_t MaxSize; 00150 }; 00152 00153 template<class Key> 00154 typename vtkTextureImageCache<Key>::CacheData& vtkTextureImageCache<Key> 00155 ::GetCacheData(const Key& key) 00156 { 00157 typename std::list<CacheElement>::iterator it = 00158 std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key)); 00159 if (it != this->Cache.end()) 00160 { 00161 return it->second; 00162 } 00163 CacheData cacheData; 00164 cacheData.ImageData = vtkSmartPointer<vtkImageData>::New(); 00165 cacheData.Texture = vtkSmartPointer<vtkTexture>::New(); 00166 cacheData.Texture->SetInputData(cacheData.ImageData); 00167 cacheData.TextWidth = 0; 00168 cacheData.TextHeight = 0; 00169 return this->AddCacheData(key, cacheData); 00170 } 00171 00172 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text 00173 // .SECTION Description 00174 // Uniquely describe a pair of vtkTextProperty and text. 00175 template <class StringType> 00176 struct TextPropertyKey 00177 { 00179 00180 static unsigned int GetIdFromTextProperty(vtkTextProperty* textProperty) 00181 { 00182 unsigned long id; 00183 vtkFreeTypeTools::GetInstance()->MapTextPropertyToId(textProperty, &id); 00184 return static_cast<unsigned int>(id); 00185 } 00187 00189 00190 TextPropertyKey(vtkTextProperty* textProperty, const StringType& text) 00191 { 00192 this->TextPropertyId = GetIdFromTextProperty(textProperty); 00193 this->FontSize = textProperty->GetFontSize(); 00194 double color[3]; 00195 textProperty->GetColor(color); 00196 this->Color.Set(static_cast<unsigned char>(color[0] * 255), 00197 static_cast<unsigned char>(color[1] * 255), 00198 static_cast<unsigned char>(color[2] * 255), 00199 static_cast<unsigned char>(textProperty->GetOpacity() * 255)); 00200 this->Text = text; 00201 } 00203 00205 00207 bool operator==(const TextPropertyKey& other)const 00208 { 00209 return this->TextPropertyId == other.TextPropertyId && 00210 this->FontSize == other.FontSize && 00211 this->Text == other.Text && 00212 this->Color[0] == other.Color[0] && 00213 this->Color[1] == other.Color[1] && 00214 this->Color[2] == other.Color[2] && 00215 this->Color[3] == other.Color[3]; 00216 } 00218 00219 unsigned short FontSize; 00220 vtkColor4ub Color; 00221 // States in the function not to use more than 32 bits - int works fine here. 00222 unsigned int TextPropertyId; 00223 StringType Text; 00224 }; 00225 00226 typedef TextPropertyKey<vtkStdString> UTF8TextPropertyKey; 00227 typedef TextPropertyKey<vtkUnicodeString> UTF16TextPropertyKey; 00228 00229 class vtkOpenGLContextDevice2D::Private 00230 { 00231 public: 00232 Private() 00233 { 00234 this->Texture = NULL; 00235 this->TextureProperties = vtkContextDevice2D::Linear | 00236 vtkContextDevice2D::Stretch; 00237 this->SpriteTexture = NULL; 00238 this->SavedLighting = GL_TRUE; 00239 this->SavedDepthTest = GL_TRUE; 00240 this->SavedAlphaTest = GL_TRUE; 00241 this->SavedStencilTest = GL_TRUE; 00242 this->SavedBlend = GL_TRUE; 00243 this->SavedDrawBuffer = 0; 00244 this->SavedClearColor[0] = this->SavedClearColor[1] = 00245 this->SavedClearColor[2] = 00246 this->SavedClearColor[3] = 0.0f; 00247 this->TextCounter = 0; 00248 this->GLExtensionsLoaded = false; 00249 this->OpenGL15 = false; 00250 this->OpenGL20 = false; 00251 this->GLSL = false; 00252 this->PowerOfTwoTextures = true; 00253 } 00254 00255 ~Private() 00256 { 00257 if (this->Texture) 00258 { 00259 this->Texture->Delete(); 00260 this->Texture = NULL; 00261 } 00262 if (this->SpriteTexture) 00263 { 00264 this->SpriteTexture->Delete(); 00265 this->SpriteTexture = NULL; 00266 } 00267 } 00268 00269 void SaveGLState(bool colorBuffer = false) 00270 { 00271 this->SavedLighting = glIsEnabled(GL_LIGHTING); 00272 this->SavedDepthTest = glIsEnabled(GL_DEPTH_TEST); 00273 00274 if (colorBuffer) 00275 { 00276 this->SavedAlphaTest = glIsEnabled(GL_ALPHA_TEST); 00277 this->SavedStencilTest = glIsEnabled(GL_STENCIL_TEST); 00278 this->SavedBlend = glIsEnabled(GL_BLEND); 00279 glGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor); 00280 glGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer); 00281 } 00282 } 00283 00284 void RestoreGLState(bool colorBuffer = false) 00285 { 00286 this->SetGLCapability(GL_LIGHTING, this->SavedLighting); 00287 this->SetGLCapability(GL_DEPTH_TEST, this->SavedDepthTest); 00288 00289 if (colorBuffer) 00290 { 00291 this->SetGLCapability(GL_ALPHA_TEST, this->SavedAlphaTest); 00292 this->SetGLCapability(GL_STENCIL_TEST, this->SavedStencilTest); 00293 this->SetGLCapability(GL_BLEND, this->SavedBlend); 00294 00295 if(this->SavedDrawBuffer != GL_BACK_LEFT) 00296 { 00297 glDrawBuffer(this->SavedDrawBuffer); 00298 } 00299 00300 int i = 0; 00301 bool colorDiffer = false; 00302 while(!colorDiffer && i < 4) 00303 { 00304 colorDiffer=this->SavedClearColor[i++] != 0.0; 00305 } 00306 if(colorDiffer) 00307 { 00308 glClearColor(this->SavedClearColor[0], 00309 this->SavedClearColor[1], 00310 this->SavedClearColor[2], 00311 this->SavedClearColor[3]); 00312 } 00313 } 00314 } 00315 00316 void SetGLCapability(GLenum capability, GLboolean state) 00317 { 00318 if (state) 00319 { 00320 glEnable(capability); 00321 } 00322 else 00323 { 00324 glDisable(capability); 00325 } 00326 } 00327 00328 float* TexCoords(float* f, int n) 00329 { 00330 float* texCoord = new float[2*n]; 00331 float minX = f[0]; float minY = f[1]; 00332 float maxX = f[0]; float maxY = f[1]; 00333 float* fptr = f; 00334 for(int i = 0; i < n; ++i) 00335 { 00336 minX = fptr[0] < minX ? fptr[0] : minX; 00337 maxX = fptr[0] > maxX ? fptr[0] : maxX; 00338 minY = fptr[1] < minY ? fptr[1] : minY; 00339 maxY = fptr[1] > maxY ? fptr[1] : maxY; 00340 fptr+=2; 00341 } 00342 fptr = f; 00343 if (this->TextureProperties & vtkContextDevice2D::Repeat) 00344 { 00345 double* textureBounds = this->Texture->GetInput()->GetBounds(); 00346 float rangeX = (textureBounds[1] - textureBounds[0]) ? 00347 textureBounds[1] - textureBounds[0] : 1.; 00348 float rangeY = (textureBounds[3] - textureBounds[2]) ? 00349 textureBounds[3] - textureBounds[2] : 1.; 00350 for (int i = 0; i < n; ++i) 00351 { 00352 texCoord[i*2] = (fptr[0]-minX) / rangeX; 00353 texCoord[i*2+1] = (fptr[1]-minY) / rangeY; 00354 fptr+=2; 00355 } 00356 } 00357 else // this->TextureProperties & vtkContextDevice2D::Stretch 00358 { 00359 float rangeX = (maxX - minX)? maxX - minX : 1.f; 00360 float rangeY = (maxY - minY)? maxY - minY : 1.f; 00361 for (int i = 0; i < n; ++i) 00362 { 00363 texCoord[i*2] = (fptr[0]-minX)/rangeX; 00364 texCoord[i*2+1] = (fptr[1]-minY)/rangeY; 00365 fptr+=2; 00366 } 00367 } 00368 return texCoord; 00369 } 00370 00371 vtkVector2i FindPowerOfTwo(const vtkVector2i& size) 00372 { 00373 vtkVector2i pow2(1, 1); 00374 for (int i = 0; i < 2; ++i) 00375 { 00376 while (pow2[i] < size[i]) 00377 { 00378 pow2[i] *= 2; 00379 } 00380 } 00381 return pow2; 00382 } 00383 00384 GLuint TextureFromImage(vtkImageData *image, vtkVector2f& texCoords) 00385 { 00386 if (image->GetScalarType() != VTK_UNSIGNED_CHAR) 00387 { 00388 cout << "Error = not an unsigned char..." << endl; 00389 return 0; 00390 } 00391 int bytesPerPixel = image->GetNumberOfScalarComponents(); 00392 int size[3]; 00393 image->GetDimensions(size); 00394 vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1])); 00395 00396 for (int i = 0; i < 2; ++i) 00397 { 00398 texCoords[i] = size[i] / float(newImg[i]); 00399 } 00400 00401 unsigned char *dataPtr = 00402 new unsigned char[newImg[0] * newImg[1] * bytesPerPixel]; 00403 unsigned char *origPtr = 00404 static_cast<unsigned char*>(image->GetScalarPointer()); 00405 00406 for (int i = 0; i < newImg[0]; ++i) 00407 { 00408 for (int j = 0; j < newImg[1]; ++j) 00409 { 00410 for (int k = 0; k < bytesPerPixel; ++k) 00411 { 00412 if (i < size[0] && j < size[1]) 00413 { 00414 dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] = 00415 origPtr[i * bytesPerPixel + j * size[0] * bytesPerPixel + k]; 00416 } 00417 else 00418 { 00419 dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] = 00420 k == 3 ? 0 : 255; 00421 } 00422 } 00423 } 00424 } 00425 00426 GLuint tmpIndex(0); 00427 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA; 00428 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8; 00429 00430 glGenTextures(1, &tmpIndex); 00431 glBindTexture(GL_TEXTURE_2D, tmpIndex); 00432 00433 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE); 00434 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE); 00435 00436 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00437 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00438 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 00439 vtkgl::CLAMP_TO_EDGE ); 00440 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 00441 vtkgl::CLAMP_TO_EDGE ); 00442 00443 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat, 00444 newImg[0], newImg[1], 0, glFormat, 00445 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr)); 00446 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0)); 00447 glEnable(GL_ALPHA_TEST); 00448 glMatrixMode(GL_TEXTURE); 00449 glLoadIdentity(); 00450 glMatrixMode(GL_MODELVIEW); 00451 glEnable(GL_TEXTURE_2D); 00452 delete [] dataPtr; 00453 return tmpIndex; 00454 } 00455 00456 GLuint TextureFromImage(vtkImageData *image) 00457 { 00458 if (image->GetScalarType() != VTK_UNSIGNED_CHAR) 00459 { 00460 cout << "Error = not an unsigned char..." << endl; 00461 return 0; 00462 } 00463 int bytesPerPixel = image->GetNumberOfScalarComponents(); 00464 int size[3]; 00465 image->GetDimensions(size); 00466 00467 unsigned char *dataPtr = 00468 static_cast<unsigned char*>(image->GetScalarPointer()); 00469 GLuint tmpIndex(0); 00470 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA; 00471 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8; 00472 00473 glGenTextures(1, &tmpIndex); 00474 glBindTexture(GL_TEXTURE_2D, tmpIndex); 00475 00476 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE); 00477 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE); 00478 00479 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00480 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00481 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 00482 vtkgl::CLAMP_TO_EDGE ); 00483 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 00484 vtkgl::CLAMP_TO_EDGE ); 00485 00486 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat, 00487 size[0], size[1], 0, glFormat, 00488 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr)); 00489 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0)); 00490 glEnable(GL_ALPHA_TEST); 00491 glMatrixMode(GL_TEXTURE); 00492 glLoadIdentity(); 00493 glMatrixMode(GL_MODELVIEW); 00494 glEnable(GL_TEXTURE_2D); 00495 return tmpIndex; 00496 } 00497 00498 vtkTexture *Texture; 00499 unsigned int TextureProperties; 00500 vtkTexture *SpriteTexture; 00501 // Store the previous GL state so that we can restore it when complete 00502 GLboolean SavedLighting; 00503 GLboolean SavedDepthTest; 00504 GLboolean SavedAlphaTest; 00505 GLboolean SavedStencilTest; 00506 GLboolean SavedBlend; 00507 GLint SavedDrawBuffer; 00508 GLfloat SavedClearColor[4]; 00509 00510 int TextCounter; 00511 vtkVector2i Dim; 00512 vtkVector2i Offset; 00513 bool GLExtensionsLoaded; 00514 bool OpenGL15; 00515 bool OpenGL20; 00516 bool GLSL; 00517 bool PowerOfTwoTextures; 00518 00520 00522 mutable vtkTextureImageCache<UTF16TextPropertyKey> TextTextureCache; 00523 mutable vtkTextureImageCache<UTF8TextPropertyKey> MathTextTextureCache; 00524 }; 00526 00527 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H 00528 // VTK-HeaderTest-Exclude: vtkOpenGLContextDevice2DPrivate.h