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 "vtkFreeTypeTools.h"
40 #include "vtkTextProperty.h"
41 #include "vtkTextRenderer.h"
42 #include "vtkTexture.h"
43 #include "vtkStdString.h"
44 #include "vtkUnicodeString.h"
45 
46 #include <algorithm>
47 #include <list>
48 #include <utility>
49 
50 // .NAME vtkTextureImageCache - store vtkTexture and vtkImageData identified by
51 // a unique key.
52 // .SECTION Description
53 // Creating and initializing a texture can be time consuming,
54 // vtkTextureImageCache offers the ability to reuse them as much as possible.
55 template <class Key>
57 {
58 public:
59  struct CacheData
60  {
63  // Use to generate texture coordinates. Computing this is as expensive as
64  // rendering the texture, so we cache it.
66  };
67 
69 
72  struct CacheElement: public std::pair<Key, CacheData>
73  {
74  // Default constructor
76  : std::pair<Key, CacheData>(Key(), CacheData()){}
77  // Construct a partial CacheElement with no CacheData
78  // This can be used for temporary CacheElement used to search a given
79  // key into the cache list.
80  CacheElement(const Key& key)
81  : std::pair<Key, CacheData>(key, CacheData()){}
82  // Standard constructor of CacheElement
83  CacheElement(const Key& key, const CacheData& cacheData)
84  : std::pair<Key, CacheData>(key, cacheData){}
85  // Operator tuned to be used when searching into the cache list using
86  // std::find()
87  bool operator==(const CacheElement& other)const
88  {
89  // Here we cheat and make the comparison only on the key, this allows
90  // us to use std::find() to search for a given key.
91  return this->first == other.first;
92  }
93  };
95 
100  {
101  this->MaxSize = 50;
102  }
103 
108  bool IsKeyInCache(const Key& key)const
109  {
110  return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end();
111  }
112 
119  CacheData& GetCacheData(const Key& key);
120 
122 
127  {
128  typename std::list<CacheElement >::iterator it;
129  for (it = this->Cache.begin(); it != this->Cache.end(); ++it)
130  {
131  it->second.Texture->ReleaseGraphicsResources(window);
132  }
133  }
135 
136 protected:
138 
142  CacheData& AddCacheData(const Key& key, const CacheData& cacheData)
143  {
144  assert(!this->IsKeyInCache(key));
145  if (this->Cache.size() >= this->MaxSize)
146  {
147  this->Cache.pop_back();
148  }
149  this->Cache.push_front(CacheElement(key, cacheData));
150  return this->Cache.begin()->second;
151  }
153 
157  std::list<CacheElement > Cache;
159 
162  size_t MaxSize;
163 };
165 
166 template<class Key>
168 ::GetCacheData(const Key& key)
169 {
170  typename std::list<CacheElement>::iterator it =
171  std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key));
172  if (it != this->Cache.end())
173  {
174  return it->second;
175  }
176  CacheData cacheData;
179  cacheData.Texture->SetInputData(cacheData.ImageData);
180  return this->AddCacheData(key, cacheData);
181 }
182 
183 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text
184 // .SECTION Description
185 // Uniquely describe a pair of vtkTextProperty and text.
186 template <class StringType>
188 {
190 
193  static vtkTypeUInt32 GetIdFromTextProperty(vtkTextProperty* tprop)
194  {
195  size_t id;
196 
198  ftt->MapTextPropertyToId(tprop, &id);
199 
200  // The hash is really a uint32 that gets cast to a size_t in
201  // MapTextPropertyToId, so this possible truncation is safe.
202  // Yay legacy APIs.
203  vtkTypeUInt32 hash = static_cast<vtkTypeUInt32>(id);
204 
205  // Ensure that the above implementation assumption still holds. If it
206  // doesn't we'll need to rework this cache class a bit.
207  assert("Hash is really a uint32" && static_cast<size_t>(hash) == id);
208 
209  // Since we cache the text metrics (which includes orientation and alignment
210  // info), we'll need to store the alignment options, since
211  // MapTextPropertyToId intentionally ignores these:
212  int tmp = tprop->GetJustification();
213  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
214  tmp = tprop->GetVerticalJustification();
215  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
216 
217  return hash;
218  }
220 
222 
225  TextPropertyKey(vtkTextProperty* textProperty, const StringType& text,
226  int dpi)
227  {
228  this->TextPropertyId = GetIdFromTextProperty(textProperty);
229  this->FontSize = textProperty->GetFontSize();
230  double color[3];
231  textProperty->GetColor(color);
232  this->Color.Set(static_cast<unsigned char>(color[0] * 255),
233  static_cast<unsigned char>(color[1] * 255),
234  static_cast<unsigned char>(color[2] * 255),
235  static_cast<unsigned char>(textProperty->GetOpacity() * 255));
236  this->Text = text;
237  this->DPI = dpi;
238  }
240 
245  bool operator==(const TextPropertyKey& other)const
246  {
247  return this->TextPropertyId == other.TextPropertyId &&
248  this->FontSize == other.FontSize &&
249  this->Text == other.Text &&
250  this->Color[0] == other.Color[0] &&
251  this->Color[1] == other.Color[1] &&
252  this->Color[2] == other.Color[2] &&
253  this->Color[3] == other.Color[3] &&
254  this->DPI == other.DPI;
255  }
256 
257  unsigned short FontSize;
259  // States in the function not to use more than 32 bits - int works fine here.
260  vtkTypeUInt32 TextPropertyId;
261  StringType Text;
262  int DPI;
263 };
264 
267 
269 {
270 public:
272  {
273  this->Texture = NULL;
276  this->SpriteTexture = NULL;
277  this->SavedLighting = GL_TRUE;
278  this->SavedDepthTest = GL_TRUE;
279  this->SavedAlphaTest = GL_TRUE;
280  this->SavedStencilTest = GL_TRUE;
281  this->SavedBlend = GL_TRUE;
282  this->SavedDrawBuffer = 0;
283  this->SavedClearColor[0] = this->SavedClearColor[1] =
284  this->SavedClearColor[2] =
285  this->SavedClearColor[3] = 0.0f;
286  this->TextCounter = 0;
287  this->GLExtensionsLoaded = false;
288  this->OpenGL15 = false;
289  this->OpenGL20 = false;
290  this->GLSL = false;
291  this->PowerOfTwoTextures = true;
292  }
293 
295  {
296  if (this->Texture)
297  {
298  this->Texture->Delete();
299  this->Texture = NULL;
300  }
301  if (this->SpriteTexture)
302  {
303  this->SpriteTexture->Delete();
304  this->SpriteTexture = NULL;
305  }
306  }
307 
308  void SaveGLState(bool colorBuffer = false)
309  {
310  this->SavedLighting = glIsEnabled(GL_LIGHTING);
311  this->SavedDepthTest = glIsEnabled(GL_DEPTH_TEST);
312 
313  if (colorBuffer)
314  {
315  this->SavedAlphaTest = glIsEnabled(GL_ALPHA_TEST);
316  this->SavedStencilTest = glIsEnabled(GL_STENCIL_TEST);
317  this->SavedBlend = glIsEnabled(GL_BLEND);
318  glGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor);
319  glGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer);
320  }
321  }
322 
323  void RestoreGLState(bool colorBuffer = false)
324  {
325  this->SetGLCapability(GL_LIGHTING, this->SavedLighting);
326  this->SetGLCapability(GL_DEPTH_TEST, this->SavedDepthTest);
327 
328  if (colorBuffer)
329  {
330  this->SetGLCapability(GL_ALPHA_TEST, this->SavedAlphaTest);
331  this->SetGLCapability(GL_STENCIL_TEST, this->SavedStencilTest);
332  this->SetGLCapability(GL_BLEND, this->SavedBlend);
333 
334  if(this->SavedDrawBuffer != GL_BACK_LEFT)
335  {
336  glDrawBuffer(this->SavedDrawBuffer);
337  }
338 
339  int i = 0;
340  bool colorDiffer = false;
341  while(!colorDiffer && i < 4)
342  {
343  colorDiffer=this->SavedClearColor[i++] != 0.0;
344  }
345  if(colorDiffer)
346  {
347  glClearColor(this->SavedClearColor[0],
348  this->SavedClearColor[1],
349  this->SavedClearColor[2],
350  this->SavedClearColor[3]);
351  }
352  }
353  }
354 
355  void SetGLCapability(GLenum capability, GLboolean state)
356  {
357  if (state)
358  {
359  glEnable(capability);
360  }
361  else
362  {
363  glDisable(capability);
364  }
365  }
366 
367  float* TexCoords(float* f, int n)
368  {
369  float* texCoord = new float[2*n];
370  float minX = f[0]; float minY = f[1];
371  float maxX = f[0]; float maxY = f[1];
372  float* fptr = f;
373  for(int i = 0; i < n; ++i)
374  {
375  minX = fptr[0] < minX ? fptr[0] : minX;
376  maxX = fptr[0] > maxX ? fptr[0] : maxX;
377  minY = fptr[1] < minY ? fptr[1] : minY;
378  maxY = fptr[1] > maxY ? fptr[1] : maxY;
379  fptr+=2;
380  }
381  fptr = f;
383  {
384  const double* textureBounds = this->Texture->GetInput()->GetBounds();
385  float rangeX = (textureBounds[1] - textureBounds[0]) ?
386  textureBounds[1] - textureBounds[0] : 1.;
387  float rangeY = (textureBounds[3] - textureBounds[2]) ?
388  textureBounds[3] - textureBounds[2] : 1.;
389  for (int i = 0; i < n; ++i)
390  {
391  texCoord[i*2] = (fptr[0]-minX) / rangeX;
392  texCoord[i*2+1] = (fptr[1]-minY) / rangeY;
393  fptr+=2;
394  }
395  }
396  else // this->TextureProperties & vtkContextDevice2D::Stretch
397  {
398  float rangeX = (maxX - minX)? maxX - minX : 1.f;
399  float rangeY = (maxY - minY)? maxY - minY : 1.f;
400  for (int i = 0; i < n; ++i)
401  {
402  texCoord[i*2] = (fptr[0]-minX)/rangeX;
403  texCoord[i*2+1] = (fptr[1]-minY)/rangeY;
404  fptr+=2;
405  }
406  }
407  return texCoord;
408  }
409 
411  {
412  vtkVector2i pow2(1, 1);
413  for (int i = 0; i < 2; ++i)
414  {
415  while (pow2[i] < size[i])
416  {
417  pow2[i] *= 2;
418  }
419  }
420  return pow2;
421  }
422 
424  {
425  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
426  {
427  cout << "Error = not an unsigned char..." << endl;
428  return 0;
429  }
430  int bytesPerPixel = image->GetNumberOfScalarComponents();
431  int size[3];
432  image->GetDimensions(size);
433  vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1]));
434 
435  for (int i = 0; i < 2; ++i)
436  {
437  texCoords[i] = size[i] / float(newImg[i]);
438  }
439 
440  unsigned char *dataPtr =
441  new unsigned char[newImg[0] * newImg[1] * bytesPerPixel];
442  unsigned char *origPtr =
443  static_cast<unsigned char*>(image->GetScalarPointer());
444 
445  for (int i = 0; i < newImg[0]; ++i)
446  {
447  for (int j = 0; j < newImg[1]; ++j)
448  {
449  for (int k = 0; k < bytesPerPixel; ++k)
450  {
451  if (i < size[0] && j < size[1])
452  {
453  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] =
454  origPtr[i * bytesPerPixel + j * size[0] * bytesPerPixel + k];
455  }
456  else
457  {
458  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] =
459  k == 3 ? 0 : 255;
460  }
461  }
462  }
463  }
464 
465  GLuint tmpIndex(0);
466  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
467  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
468 
469  glGenTextures(1, &tmpIndex);
470  glBindTexture(GL_TEXTURE_2D, tmpIndex);
471 
472  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
473  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
474 
475  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
476  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
477  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
478  vtkgl::CLAMP_TO_EDGE );
479  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
480  vtkgl::CLAMP_TO_EDGE );
481 
482  glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
483  newImg[0], newImg[1], 0, glFormat,
484  GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
485  glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
486  glEnable(GL_ALPHA_TEST);
487  glMatrixMode(GL_TEXTURE);
488  glLoadIdentity();
489  glMatrixMode(GL_MODELVIEW);
490  glEnable(GL_TEXTURE_2D);
491  delete [] dataPtr;
492  return tmpIndex;
493  }
494 
496  {
497  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
498  {
499  cout << "Error = not an unsigned char..." << endl;
500  return 0;
501  }
502  int bytesPerPixel = image->GetNumberOfScalarComponents();
503  int size[3];
504  image->GetDimensions(size);
505 
506  unsigned char *dataPtr =
507  static_cast<unsigned char*>(image->GetScalarPointer());
508  GLuint tmpIndex(0);
509  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
510  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
511 
512  glGenTextures(1, &tmpIndex);
513  glBindTexture(GL_TEXTURE_2D, tmpIndex);
514 
515  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
516  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
517 
518  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
519  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
520  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
521  vtkgl::CLAMP_TO_EDGE );
522  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
523  vtkgl::CLAMP_TO_EDGE );
524 
525  glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
526  size[0], size[1], 0, glFormat,
527  GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
528  glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
529  glEnable(GL_ALPHA_TEST);
530  glMatrixMode(GL_TEXTURE);
531  glLoadIdentity();
532  glMatrixMode(GL_MODELVIEW);
533  glEnable(GL_TEXTURE_2D);
534  return tmpIndex;
535  }
536 
538  unsigned int TextureProperties;
540  // Store the previous GL state so that we can restore it when complete
541  GLboolean SavedLighting;
542  GLboolean SavedDepthTest;
543  GLboolean SavedAlphaTest;
544  GLboolean SavedStencilTest;
545  GLboolean SavedBlend;
547  GLfloat SavedClearColor[4];
548 
553  bool OpenGL15;
554  bool OpenGL20;
555  bool GLSL;
557 
559 
565 };
567 
568 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H
569 // VTK-HeaderTest-Exclude: vtkOpenGLContextDevice2DPrivate.h
std::list< CacheElement > Cache
List of a pair of key and cache data.
bool operator==(const CacheElement &other) const
virtual int GetJustification()
Set/Get the horizontal justification to left (default), centered, or right.
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:34
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:39
vtkImageData * GetInput()
Get the input as a vtkImageData object.
Some derived classes for the different vectors commonly used.
Definition: vtkVector.h:324
virtual int GetVerticalJustification()
Set/Get the vertical justification to bottom (default), middle, or top.
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:64
vtkTextureImageCache()
Construct a texture image cache with a maximum number of texture of 50.
virtual double GetOpacity()
Set/Get the text&#39;s opacity.
represent text properties.
static vtkFreeTypeTools * GetInstance()
Return the singleton instance with no reference counting.
vtkTextureImageCache< UTF16TextPropertyKey > TextTextureCache
Cache for text images.
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 &#39;tprop&#39;, 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
static vtkTypeUInt32 GetIdFromTextProperty(vtkTextProperty *tprop)
Transform a text property into an unsigned long.
static vtkTypeUInt32 HashBuffer(const void *str, size_t n, vtkTypeUInt32 hash=0)
Hash a string of a given length.
FreeType library support.
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.