VTK
vtkOpenGLContextDevice2DPrivate.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkOpenGLContextDevice2DPrivate.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
33 #ifndef vtkOpenGLContextDevice2DPrivate_h
34 #define vtkOpenGLContextDevice2DPrivate_h
35 
37 
38 #include "vtkColor.h"
39 #include "vtkTextProperty.h"
40 #include "vtkFreeTypeTools.h"
41 #include "vtkStdString.h"
42 #include "vtkUnicodeString.h"
43 
44 #include <algorithm>
45 #include <list>
46 #include <utility>
47 
48 // .NAME vtkTextureImageCache - store vtkTexture and vtkImageData identified by
49 // a unique key.
50 // .SECTION Description
51 // Creating and initializing a texture can be time consuming,
52 // vtkTextureImageCache offers the ability to reuse them as much as possible.
53 template <class Key>
55 {
56 public:
57  struct CacheData
58  {
61  // Dimensions of the text. Used for generating texture coords when the image
62  // dimensions are scaled to a power of two.
63  int TextWidth;
65  };
66 
68 
71  struct CacheElement: public std::pair<Key, CacheData>
72  {
73  // Default constructor
75  : std::pair<Key, CacheData>(Key(), CacheData()){}
76  // Construct a partial CacheElement with no CacheData
77  // This can be used for temporary CacheElement used to search a given
78  // key into the cache list.
79  CacheElement(const Key& key)
80  : std::pair<Key, CacheData>(key, CacheData()){}
81  // Standard constructor of CacheElement
82  CacheElement(const Key& key, const CacheData& cacheData)
83  : std::pair<Key, CacheData>(key, cacheData){}
84  // Operator tuned to be used when searching into the cache list using
85  // std::find()
86  bool operator==(const CacheElement& other)const
87  {
88  // Here we cheat and make the comparison only on the key, this allows
89  // us to use std::find() to search for a given key.
90  return this->first == other.first;
91  }
92  };
94 
99  {
100  this->MaxSize = 50;
101  }
102 
107  bool IsKeyInCache(const Key& key)const
108  {
109  return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end();
110  }
111 
118  CacheData& GetCacheData(const Key& key);
119 
121 
126  {
127  typename std::list<CacheElement >::iterator it;
128  for (it = this->Cache.begin(); it != this->Cache.end(); ++it)
129  {
130  it->second.Texture->ReleaseGraphicsResources(window);
131  }
132  }
134 
135 protected:
137 
141  CacheData& AddCacheData(const Key& key, const CacheData& cacheData)
142  {
143  assert(!this->IsKeyInCache(key));
144  if (this->Cache.size() >= this->MaxSize)
145  {
146  this->Cache.pop_back();
147  }
148  this->Cache.push_front(CacheElement(key, cacheData));
149  return this->Cache.begin()->second;
150  }
152 
156  std::list<CacheElement > Cache;
158 
161  size_t MaxSize;
162 };
164 
165 template<class Key>
167 ::GetCacheData(const Key& key)
168 {
169  typename std::list<CacheElement>::iterator it =
170  std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key));
171  if (it != this->Cache.end())
172  {
173  return it->second;
174  }
175  CacheData cacheData;
178  cacheData.Texture->SetInputData(cacheData.ImageData);
179  cacheData.TextWidth = 0;
180  cacheData.TextHeight = 0;
181  return this->AddCacheData(key, cacheData);
182 }
183 
184 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text
185 // .SECTION Description
186 // Uniquely describe a pair of vtkTextProperty and text.
187 template <class StringType>
189 {
191 
194  static unsigned int GetIdFromTextProperty(vtkTextProperty* textProperty)
195  {
196  size_t id;
198  // Truncation on 64-bit machines! The id is a pointer.
199  return static_cast<unsigned int>(id);
200  }
202 
204 
207  TextPropertyKey(vtkTextProperty* textProperty, const StringType& text,
208  int dpi)
209  {
210  this->TextPropertyId = GetIdFromTextProperty(textProperty);
211  this->FontSize = textProperty->GetFontSize();
212  double color[3];
213  textProperty->GetColor(color);
214  this->Color.Set(static_cast<unsigned char>(color[0] * 255),
215  static_cast<unsigned char>(color[1] * 255),
216  static_cast<unsigned char>(color[2] * 255),
217  static_cast<unsigned char>(textProperty->GetOpacity() * 255));
218  this->Text = text;
219  this->DPI = dpi;
220  }
222 
227  bool operator==(const TextPropertyKey& other)const
228  {
229  return this->TextPropertyId == other.TextPropertyId &&
230  this->FontSize == other.FontSize &&
231  this->Text == other.Text &&
232  this->Color[0] == other.Color[0] &&
233  this->Color[1] == other.Color[1] &&
234  this->Color[2] == other.Color[2] &&
235  this->Color[3] == other.Color[3] &&
236  this->DPI == other.DPI;
237  }
238 
239  unsigned short FontSize;
241  // States in the function not to use more than 32 bits - int works fine here.
242  unsigned int TextPropertyId;
243  StringType Text;
244  int DPI;
245 };
246 
249 
251 {
252 public:
254  {
255  this->Texture = NULL;
258  this->SpriteTexture = NULL;
259  this->SavedLighting = GL_TRUE;
260  this->SavedDepthTest = GL_TRUE;
261  this->SavedAlphaTest = GL_TRUE;
262  this->SavedStencilTest = GL_TRUE;
263  this->SavedBlend = GL_TRUE;
264  this->SavedDrawBuffer = 0;
265  this->SavedClearColor[0] = this->SavedClearColor[1] =
266  this->SavedClearColor[2] =
267  this->SavedClearColor[3] = 0.0f;
268  this->TextCounter = 0;
269  this->GLExtensionsLoaded = false;
270  this->OpenGL15 = false;
271  this->OpenGL20 = false;
272  this->GLSL = false;
273  this->PowerOfTwoTextures = true;
274  }
275 
277  {
278  if (this->Texture)
279  {
280  this->Texture->Delete();
281  this->Texture = NULL;
282  }
283  if (this->SpriteTexture)
284  {
285  this->SpriteTexture->Delete();
286  this->SpriteTexture = NULL;
287  }
288  }
289 
290  void SaveGLState(bool colorBuffer = false)
291  {
292  this->SavedLighting = glIsEnabled(GL_LIGHTING);
293  this->SavedDepthTest = glIsEnabled(GL_DEPTH_TEST);
294 
295  if (colorBuffer)
296  {
297  this->SavedAlphaTest = glIsEnabled(GL_ALPHA_TEST);
298  this->SavedStencilTest = glIsEnabled(GL_STENCIL_TEST);
299  this->SavedBlend = glIsEnabled(GL_BLEND);
300  glGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor);
301  glGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer);
302  }
303  }
304 
305  void RestoreGLState(bool colorBuffer = false)
306  {
307  this->SetGLCapability(GL_LIGHTING, this->SavedLighting);
308  this->SetGLCapability(GL_DEPTH_TEST, this->SavedDepthTest);
309 
310  if (colorBuffer)
311  {
312  this->SetGLCapability(GL_ALPHA_TEST, this->SavedAlphaTest);
313  this->SetGLCapability(GL_STENCIL_TEST, this->SavedStencilTest);
314  this->SetGLCapability(GL_BLEND, this->SavedBlend);
315 
316  if(this->SavedDrawBuffer != GL_BACK_LEFT)
317  {
318  glDrawBuffer(this->SavedDrawBuffer);
319  }
320 
321  int i = 0;
322  bool colorDiffer = false;
323  while(!colorDiffer && i < 4)
324  {
325  colorDiffer=this->SavedClearColor[i++] != 0.0;
326  }
327  if(colorDiffer)
328  {
329  glClearColor(this->SavedClearColor[0],
330  this->SavedClearColor[1],
331  this->SavedClearColor[2],
332  this->SavedClearColor[3]);
333  }
334  }
335  }
336 
337  void SetGLCapability(GLenum capability, GLboolean state)
338  {
339  if (state)
340  {
341  glEnable(capability);
342  }
343  else
344  {
345  glDisable(capability);
346  }
347  }
348 
349  float* TexCoords(float* f, int n)
350  {
351  float* texCoord = new float[2*n];
352  float minX = f[0]; float minY = f[1];
353  float maxX = f[0]; float maxY = f[1];
354  float* fptr = f;
355  for(int i = 0; i < n; ++i)
356  {
357  minX = fptr[0] < minX ? fptr[0] : minX;
358  maxX = fptr[0] > maxX ? fptr[0] : maxX;
359  minY = fptr[1] < minY ? fptr[1] : minY;
360  maxY = fptr[1] > maxY ? fptr[1] : maxY;
361  fptr+=2;
362  }
363  fptr = f;
365  {
366  double* textureBounds = this->Texture->GetInput()->GetBounds();
367  float rangeX = (textureBounds[1] - textureBounds[0]) ?
368  textureBounds[1] - textureBounds[0] : 1.;
369  float rangeY = (textureBounds[3] - textureBounds[2]) ?
370  textureBounds[3] - textureBounds[2] : 1.;
371  for (int i = 0; i < n; ++i)
372  {
373  texCoord[i*2] = (fptr[0]-minX) / rangeX;
374  texCoord[i*2+1] = (fptr[1]-minY) / rangeY;
375  fptr+=2;
376  }
377  }
378  else // this->TextureProperties & vtkContextDevice2D::Stretch
379  {
380  float rangeX = (maxX - minX)? maxX - minX : 1.f;
381  float rangeY = (maxY - minY)? maxY - minY : 1.f;
382  for (int i = 0; i < n; ++i)
383  {
384  texCoord[i*2] = (fptr[0]-minX)/rangeX;
385  texCoord[i*2+1] = (fptr[1]-minY)/rangeY;
386  fptr+=2;
387  }
388  }
389  return texCoord;
390  }
391 
393  {
394  vtkVector2i pow2(1, 1);
395  for (int i = 0; i < 2; ++i)
396  {
397  while (pow2[i] < size[i])
398  {
399  pow2[i] *= 2;
400  }
401  }
402  return pow2;
403  }
404 
406  {
407  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
408  {
409  cout << "Error = not an unsigned char..." << endl;
410  return 0;
411  }
412  int bytesPerPixel = image->GetNumberOfScalarComponents();
413  int size[3];
414  image->GetDimensions(size);
415  vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1]));
416 
417  for (int i = 0; i < 2; ++i)
418  {
419  texCoords[i] = size[i] / float(newImg[i]);
420  }
421 
422  unsigned char *dataPtr =
423  new unsigned char[newImg[0] * newImg[1] * bytesPerPixel];
424  unsigned char *origPtr =
425  static_cast<unsigned char*>(image->GetScalarPointer());
426 
427  for (int i = 0; i < newImg[0]; ++i)
428  {
429  for (int j = 0; j < newImg[1]; ++j)
430  {
431  for (int k = 0; k < bytesPerPixel; ++k)
432  {
433  if (i < size[0] && j < size[1])
434  {
435  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] =
436  origPtr[i * bytesPerPixel + j * size[0] * bytesPerPixel + k];
437  }
438  else
439  {
440  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] =
441  k == 3 ? 0 : 255;
442  }
443  }
444  }
445  }
446 
447  GLuint tmpIndex(0);
448  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
449  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
450 
451  glGenTextures(1, &tmpIndex);
452  glBindTexture(GL_TEXTURE_2D, tmpIndex);
453 
454  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
455  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
456 
457  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
458  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
459  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
460  vtkgl::CLAMP_TO_EDGE );
461  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
462  vtkgl::CLAMP_TO_EDGE );
463 
464  glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
465  newImg[0], newImg[1], 0, glFormat,
466  GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
467  glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
468  glEnable(GL_ALPHA_TEST);
469  glMatrixMode(GL_TEXTURE);
470  glLoadIdentity();
471  glMatrixMode(GL_MODELVIEW);
472  glEnable(GL_TEXTURE_2D);
473  delete [] dataPtr;
474  return tmpIndex;
475  }
476 
478  {
479  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
480  {
481  cout << "Error = not an unsigned char..." << endl;
482  return 0;
483  }
484  int bytesPerPixel = image->GetNumberOfScalarComponents();
485  int size[3];
486  image->GetDimensions(size);
487 
488  unsigned char *dataPtr =
489  static_cast<unsigned char*>(image->GetScalarPointer());
490  GLuint tmpIndex(0);
491  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
492  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
493 
494  glGenTextures(1, &tmpIndex);
495  glBindTexture(GL_TEXTURE_2D, tmpIndex);
496 
497  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
498  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
499 
500  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
501  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
502  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
503  vtkgl::CLAMP_TO_EDGE );
504  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
505  vtkgl::CLAMP_TO_EDGE );
506 
507  glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
508  size[0], size[1], 0, glFormat,
509  GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
510  glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
511  glEnable(GL_ALPHA_TEST);
512  glMatrixMode(GL_TEXTURE);
513  glLoadIdentity();
514  glMatrixMode(GL_MODELVIEW);
515  glEnable(GL_TEXTURE_2D);
516  return tmpIndex;
517  }
518 
520  unsigned int TextureProperties;
522  // Store the previous GL state so that we can restore it when complete
523  GLboolean SavedLighting;
524  GLboolean SavedDepthTest;
525  GLboolean SavedAlphaTest;
526  GLboolean SavedStencilTest;
527  GLboolean SavedBlend;
529  GLfloat SavedClearColor[4];
530 
535  bool OpenGL15;
536  bool OpenGL20;
537  bool GLSL;
539 
541 
547 };
549 
550 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H
551 // VTK-HeaderTest-Exclude: vtkOpenGLContextDevice2DPrivate.h
std::list< CacheElement > Cache
List of a pair of key and cache data.
bool operator==(const CacheElement &other) const
void SetGLCapability(GLenum capability, GLboolean state)
double * GetBounds()
Return a pointer to the geometry bounding box in the form (xmin,xmax, ymin,ymax, zmin,zmax).
static int GetNumberOfScalarComponents(vtkInformation *meta_data)
Set/Get the number of scalar components for points.
GLuint TextureFromImage(vtkImageData *image, vtkVector2f &texCoords)
bool IsKeyInCache(const Key &key) const
Search the cache list to see if a given key already exists.
TextPropertyKey(vtkTextProperty *textProperty, const StringType &text, int dpi)
Creates a TextPropertyKey.
static vtkSmartPointer< T > New()
Create an instance of a VTK object.
CacheElement(const Key &key, const CacheData &cacheData)
void SetInputData(vtkDataObject *)
Assign a data object as input.
void ReleaseGraphicsResources(vtkWindow *window)
Release all the OpenGL Pixel Buffer Object(PBO) associated with the textures of the cache list...
vtkSmartPointer< vtkImageData > ImageData
bool operator==(const TextPropertyKey &other) const
Compares two TextPropertyKeys with each other.
TextPropertyKey< vtkStdString > UTF8TextPropertyKey
window superclass for vtkRenderWindow
Definition: vtkWindow.h:37
size_t MaxSize
Maximum size the cache list can be.
virtual int * GetDimensions()
Get dimensions of this structured points dataset.
static int GetScalarType(vtkInformation *meta_data)
topologically and geometrically regular array of data
Definition: vtkImageData.h:45
vtkImageData * GetInput()
Get the input as a vtkImageData object.
Some derived classes for the different vectors commonly used.
Definition: vtkVector.h:327
CacheData & GetCacheData(const Key &key)
Return the cache associated to a key.
void Set(const T &red, const T &green, const T &blue)
Set the red, green and blue components of the color.
Definition: vtkColor.h:129
handles properties associated with a texture map
Definition: vtkTexture.h:70
vtkTextureImageCache()
Construct a texture image cache with a maximum number of texture of 50.
virtual double GetOpacity()
Set/Get the text's opacity.
represent text properties.
static vtkFreeTypeTools * GetInstance()
Return the singleton instance with no reference counting.
vtkTextureImageCache< UTF16TextPropertyKey > TextTextureCache
Cache for text images.
static unsigned int GetIdFromTextProperty(vtkTextProperty *textProperty)
Transform a text property into an unsigned long.
virtual double * GetColor()
Set the color of the text.
#define VTK_UNSIGNED_CHAR
Definition: vtkType.h:51
virtual void * GetScalarPointer(int coordinates[3])
Access the native pointer for the scalar data.
void MapTextPropertyToId(vtkTextProperty *tprop, size_t *tprop_cache_id)
Given a text property 'tprop', get its unique ID in our cache framework.
CacheElement associates a unique key to some cache.
vtkVector2i FindPowerOfTwo(const vtkVector2i &size)
virtual int GetFontSize()
Set/Get the font size (in points).
TextPropertyKey< vtkUnicodeString > UTF16TextPropertyKey
CacheData & AddCacheData(const Key &key, const CacheData &cacheData)
Add a new cache entry into the cache list.
virtual void Delete()
Delete a VTK object.
vtkTextureImageCache< UTF8TextPropertyKey > MathTextTextureCache
Cache for text images.