Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

339 lines
9.5 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkTextActor3D.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkTextActor3D.h"
#include "vtkObjectFactory.h"
#include "vtkCamera.h"
#include "vtkImageActor.h"
#include "vtkImageData.h"
#include "vtkTransform.h"
#include "vtkTextProperty.h"
#include "vtkRenderer.h"
#include "vtkWindow.h"
#include "vtkFreeTypeUtilities.h"
#include "vtkMatrix4x4.h"
#include "vtkMath.h"
vtkCxxRevisionMacro(vtkTextActor3D, "$Revision: 1.5 $");
vtkStandardNewMacro(vtkTextActor3D);
vtkCxxSetObjectMacro(vtkTextActor3D, TextProperty, vtkTextProperty);
// ----------------------------------------------------------------------------
vtkTextActor3D::vtkTextActor3D()
{
this->Input = NULL;
this->ImageActor = vtkImageActor::New();
this->ImageData = NULL;
this->TextProperty = NULL;
this->BuildTime.Modified();
this->SetTextProperty(vtkTextProperty::New());
this->TextProperty->Delete();
this->ImageActor->InterpolateOn();
}
// --------------------------------------------------------------------------
vtkTextActor3D::~vtkTextActor3D()
{
this->SetTextProperty(NULL);
this->SetInput(NULL);
if (this->ImageActor)
{
this->ImageActor->Delete();
this->ImageActor = NULL;
}
if (this->ImageData)
{
this->ImageData->Delete();
this->ImageData = NULL;
}
}
// --------------------------------------------------------------------------
void vtkTextActor3D::ShallowCopy(vtkProp *prop)
{
vtkTextActor3D *a = vtkTextActor3D::SafeDownCast(prop);
if (a != NULL)
{
this->SetInput(a->GetInput());
this->SetTextProperty(a->GetTextProperty());
}
this->Superclass::ShallowCopy(prop);
}
// --------------------------------------------------------------------------
double* vtkTextActor3D::GetBounds()
{
if (this->ImageActor)
{
return this->ImageActor->GetBounds();
}
return NULL;
}
// --------------------------------------------------------------------------
void vtkTextActor3D::ReleaseGraphicsResources(vtkWindow *win)
{
if (this->ImageActor)
{
this->ImageActor->ReleaseGraphicsResources(win);
}
this->Superclass::ReleaseGraphicsResources(win);
}
// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOverlay(vtkViewport *viewport)
{
int rendered_something = 0;
if (this->UpdateImageActor() && this->ImageActor)
{
rendered_something += this->ImageActor->RenderOverlay(viewport);
}
return rendered_something;
}
// --------------------------------------------------------------------------
int vtkTextActor3D::RenderTranslucentGeometry(vtkViewport *viewport)
{
int rendered_something = 0;
if (this->UpdateImageActor() && this->ImageActor)
{
rendered_something +=
this->ImageActor->RenderTranslucentGeometry(viewport);
}
return rendered_something;
}
// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOpaqueGeometry(vtkViewport *viewport)
{
int rendered_something = 0;
if (this->UpdateImageActor() && this->ImageActor)
{
rendered_something +=
this->ImageActor->RenderOpaqueGeometry(viewport);
}
return rendered_something;
}
// --------------------------------------------------------------------------
int vtkTextActor3D::UpdateImageActor()
{
// Need text prop
if (!this->TextProperty)
{
vtkErrorMacro(<<"Need a text property to render text actor");
return 0;
}
// No input, the assign the image actor a zilch input
if (!this->Input || !*this->Input)
{
if (this->ImageActor)
{
this->ImageActor->SetInput(NULL);
}
return 1;
}
// Do we need to (re-)render the text ?
// Yes if:
// - instance has been modified since last build
// - text prop has been modified since last build
// - ImageData ivar has not been allocated yet
if (this->GetMTime() > this->BuildTime ||
this->TextProperty->GetMTime() > this->BuildTime ||
!this->ImageData)
{
//cout << "Need to re-render " << this->GetMTime() << ", " << this->TextProperty->GetMTime() << ", " << this->BuildTime << endl;
this->BuildTime.Modified();
// Get the bounding box of the text to render
// If the bounding box is invalid, then there is nothing to render
// assign the image actor a nada input
vtkFreeTypeUtilities *fu = vtkFreeTypeUtilities::GetInstance();
if (!fu)
{
vtkErrorMacro(<<"Failed getting the FreeType utilities instance");
return 0;
}
int text_bbox[4];
fu->GetBoundingBox(this->TextProperty, this->Input, text_bbox);
if (!fu->IsBoundingBoxValid(text_bbox))
{
if (this->ImageActor)
{
this->ImageActor->SetInput(NULL);
}
return 1;
}
// The bounding box was the area that is going to be filled with pixels
// given a text origin of (0, 0). Now get the real size we need, i.e.
// the full extent from the origin to the bounding box.
int text_size[2];
text_size[0] = (text_bbox[1] - text_bbox[0] + 1) + abs(text_bbox[0]);
text_size[1] = (text_bbox[3] - text_bbox[2] + 1) + abs(text_bbox[2]);
// If the RGBA image data is too small, resize it to the next power of 2
// WARNING: at this point, since this image is going to be a texture
// we should limit its size or query the hardware
if (!this->ImageData)
{
this->ImageData = vtkImageData::New();
this->ImageData->SetScalarTypeToUnsignedChar();
this->ImageData->SetNumberOfScalarComponents(4);
this->ImageData->SetSpacing(1.0, 1.0, 1.0);
}
// If the current image data is too small to render the text,
// or more than twice as big (too hungry), then resize
int img_dims[3], new_img_dims[3];
this->ImageData->GetDimensions(img_dims);
if (img_dims[0] < text_size[0] || img_dims[1] < text_size[1] ||
text_size[0] * 2 < img_dims[0] || text_size[1] * 2 < img_dims[0])
{
new_img_dims[0] = 1 << (int)ceil(log((double)text_size[0]) / log(2.0));
new_img_dims[1] = 1 << (int)ceil(log((double)text_size[1]) / log(2.0));
new_img_dims[2] = 1;
if (new_img_dims[0] != img_dims[0] ||
new_img_dims[1] != img_dims[1] ||
new_img_dims[2] != img_dims[2])
{
//cout << "I need: " << text_size[0] << "x" << text_size[1] << ", I resize to: " << new_img_dims[0] << "x" << new_img_dims[1] << endl;
this->ImageData->SetDimensions(new_img_dims);
this->ImageData->AllocateScalars();
this->ImageData->UpdateInformation();
this->ImageData->SetUpdateExtent(this->ImageData->GetWholeExtent());
this->ImageData->PropagateUpdateExtent();
if (this->ImageActor)
{
this->ImageActor->SetDisplayExtent(
this->ImageData->GetWholeExtent());
}
}
}
// Render inside the image data
int x = (text_bbox[0] < 0 ? -text_bbox[0] : 0);
int y = (text_bbox[2] < 0 ? -text_bbox[2] : 0);
#if 0
char *ptr = (char*)this->ImageData->GetScalarPointer();
int nb_comp = this->ImageData->GetNumberOfScalarComponents();
char *ptr_end = ptr + this->ImageData->GetNumberOfPoints() * nb_comp;
memset(ptr, 0, ptr_end - ptr);
ptr += nb_comp - 1;
while (ptr < ptr_end)
{
*ptr = 255.0;
ptr += nb_comp;
}
#else
memset(this->ImageData->GetScalarPointer(),
0,
(this->ImageData->GetNumberOfPoints() *
this->ImageData->GetNumberOfScalarComponents()));
#endif
if (!fu->RenderString(
this->TextProperty, this->Input, x, y, this->ImageData))
{
vtkErrorMacro(<<"Failed rendering text to buffer");
return 0;
}
// Set the image data origin so that oriented text is placed properly
// Also take shadow into account, we want the text to be on the baseline
if (this->TextProperty->GetShadow())
{
// this is wrong
//x += this->TextProperty->GetShadowOffset()[0];
//y += this->TextProperty->GetShadowOffset()[1];
}
this->ImageData->SetOrigin(-x, -y, 0);
// Associate the image data (should be up to date now) to the image actor
if (this->ImageActor)
{
this->ImageActor->SetInput(this->ImageData);
}
}
// Position the actor
if (this->ImageActor)
{
// Which one is faster ?
#if 1
vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
this->GetMatrix(matrix);
this->ImageActor->SetUserMatrix(matrix);
matrix->Delete();
#else
this->ImageActor->SetPosition(this->GetPosition());
this->ImageActor->SetScale(this->GetScale());
this->ImageActor->SetOrientation(this->GetOrientation());
#endif
}
return 1;
}
// --------------------------------------------------------------------------
void vtkTextActor3D::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Input: " << (this->Input ? this->Input : "(none)") << "\n";
if (this->TextProperty)
{
os << indent << "Text Property:\n";
this->TextProperty->PrintSelf(os, indent.GetNextIndent());
}
else
{
os << indent << "Text Property: (none)\n";
}
}