Commit cdb8e6f1 authored by Marcus D. Hanwell's avatar Marcus D. Hanwell
Browse files

ENH: Added unicode support to vtkContext2D.

Added support for rendering unicode text using the 2D API. Also added
two new tests, although the freetype version is disabled until freetype
correctly renders the unicode characters. Verified that the Qt version
works as expected.
parent 066d237d
......@@ -4,6 +4,7 @@ IF (VTK_USE_RENDERING AND VTK_USE_VIEWS)
# add tests that do not require data
SET(MyTests
TestContextScene.cxx
# TestContextUnicode.cxx # Disabled until Freetype unicode works
TestPieChart.cxx
TestPCPlot.cxx
TestDiagram.cxx
......@@ -39,6 +40,7 @@ IF (VTK_USE_RENDERING AND VTK_USE_VIEWS)
INCLUDE(${QT_USE_FILE})
SET(MyTests ${MyTests}
TestQtDiagram.cxx
TestQtContextUnicode.cxx
)
ENDIF(VTK_USE_QT)
CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx ${MyTests}
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestContext.cxx
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 "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkObjectFactory.h"
#include "vtkContext2D.h"
#include "vtkContextItem.h"
#include "vtkContextView.h"
#include "vtkContextScene.h"
#include "vtkPen.h"
#include "vtkBrush.h"
#include "vtkTextProperty.h"
#include "vtkUnicodeString.h"
#include "vtkRegressionTestImage.h"
//----------------------------------------------------------------------------
class ContextUnicode : public vtkContextItem
{
public:
static ContextUnicode *New();
vtkTypeMacro(ContextUnicode, vtkContextItem);
// Paint event for the chart, called whenever the chart needs to be drawn
virtual bool Paint(vtkContext2D *painter);
};
//----------------------------------------------------------------------------
int TestContextUnicode(int argc, char * argv [])
{
// Set up a 2D context view, context test object and add it to the scene
vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
view->GetRenderWindow()->SetSize(200, 100);
vtkSmartPointer<ContextUnicode> test = vtkSmartPointer<ContextUnicode>::New();
view->GetScene()->AddItem(test);
view->GetRenderWindow()->SetMultiSamples(0);
view->GetRenderWindow()->Render();
int retVal = vtkRegressionTestImage(view->GetRenderWindow());
if(retVal == vtkRegressionTester::DO_INTERACTOR)
{
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
}
return !retVal;
}
// Make our new derived class to draw a diagram
vtkStandardNewMacro(ContextUnicode);
// This function aims to test the primitives provided by the 2D API.
bool ContextUnicode::Paint(vtkContext2D *painter)
{
// Test the string drawing functionality of the context
painter->GetTextProp()->SetVerticalJustificationToCentered();
painter->GetTextProp()->SetJustificationToCentered();
painter->GetTextProp()->SetColor(0.0, 0.0, 0.0);
painter->GetTextProp()->SetFontSize(24);
painter->DrawString(70, 20, "Angstrom");
painter->DrawString(150, 20, vtkUnicodeString::from_utf8("\xe2\x84\xab"));
painter->DrawString(100, 80,
vtkUnicodeString::from_utf8("a\xce\xb1\xe0\xb8\x81\xf0\x90\x80\x80"));
painter->DrawString(100, 50,
vtkUnicodeString::from_utf8("\xce\xb1\xce\xb2\xce\xb3"));
return true;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestContext.cxx
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 "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkObjectFactory.h"
#include "vtkContext2D.h"
#include "vtkContextItem.h"
#include "vtkContextView.h"
#include "vtkContextScene.h"
#include "vtkPen.h"
#include "vtkBrush.h"
#include "vtkTextProperty.h"
#include "vtkUnicodeString.h"
#include "vtkRegressionTestImage.h"
#include <QApplication>
//----------------------------------------------------------------------------
class QtContextUnicode : public vtkContextItem
{
public:
static QtContextUnicode *New();
vtkTypeMacro(QtContextUnicode, vtkContextItem);
// Paint event for the chart, called whenever the chart needs to be drawn
virtual bool Paint(vtkContext2D *painter);
};
//----------------------------------------------------------------------------
int TestQtContextUnicode(int argc, char * argv [])
{
QApplication app (argc, argv);
// Set up a 2D context view, context test object and add it to the scene
vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
view->GetRenderWindow()->SetSize(200, 100);
vtkSmartPointer<QtContextUnicode> test = vtkSmartPointer<QtContextUnicode>::New();
view->GetScene()->AddItem(test);
view->GetRenderWindow()->SetMultiSamples(0);
view->GetRenderWindow()->Render();
int retVal = vtkRegressionTestImage(view->GetRenderWindow());
if(retVal == vtkRegressionTester::DO_INTERACTOR)
{
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
}
return !retVal;
}
// Make our new derived class to draw a diagram
vtkStandardNewMacro(QtContextUnicode);
// This function aims to test the primitives provided by the 2D API.
bool QtContextUnicode::Paint(vtkContext2D *painter)
{
// Test the string drawing functionality of the context
painter->GetTextProp()->SetVerticalJustificationToCentered();
painter->GetTextProp()->SetJustificationToCentered();
painter->GetTextProp()->SetColor(0.0, 0.0, 0.0);
painter->GetTextProp()->SetFontSize(24);
painter->DrawString(70, 20, "Angstrom");
painter->DrawString(150, 20, vtkUnicodeString::from_utf8("\xe2\x84\xab"));
painter->DrawString(100, 80,
vtkUnicodeString::from_utf8("a\xce\xb1\xe0\xb8\x81\xf0\x90\x80\x80"));
painter->DrawString(100, 50,
vtkUnicodeString::from_utf8("\xce\xb1\xce\xb2\xce\xb3"));
return true;
}
......@@ -16,6 +16,7 @@
#include "vtkContext2D.h"
#include "vtkPoints2D.h"
#include "vtkVector.h"
#include "vtkTransform2D.h"
#include "vtkContextDevice2D.h"
#include "vtkPen.h"
......@@ -433,56 +434,52 @@ void vtkContext2D::DrawEllipticArc(float x, float y, float rX, float rY,
//-----------------------------------------------------------------------------
void vtkContext2D::DrawStringRect(vtkPoints2D *rect, const vtkStdString &string)
{
// Draw the text at the appropriate point inside the rect for the alignment
// specified. This is a convenience when an area of the screen should have
// text drawn that is aligned to the entire area.
if (rect->GetNumberOfPoints() < 2)
{
return;
}
vtkVector2f p = this->CalculateTextPosition(rect);
this->DrawString(p.GetX(), p.GetY(), string);
}
float x = 0.0;
float y = 0.0;
float *f = vtkFloatArray::SafeDownCast(rect->GetData())->GetPointer(0);
//-----------------------------------------------------------------------------
void vtkContext2D::DrawStringRect(vtkPoints2D *rect,
const vtkUnicodeString &string)
{
vtkVector2f p = this->CalculateTextPosition(rect);
this->DrawString(p.GetX(), p.GetY(), string);
}
if (this->TextProp->GetJustification() == VTK_TEXT_LEFT)
{
x = f[0];
}
else if (this->TextProp->GetJustification() == VTK_TEXT_CENTERED)
{
x = f[0] + 0.5f*f[2];
}
else
{
x = f[0] + f[2];
}
//-----------------------------------------------------------------------------
void vtkContext2D::DrawStringRect(vtkPoints2D *rect, const char* string)
{
this->DrawStringRect(rect, vtkStdString(string));
}
if (this->TextProp->GetVerticalJustification() == VTK_TEXT_BOTTOM)
{
y = f[1];
}
else if (this->TextProp->GetVerticalJustification() == VTK_TEXT_CENTERED)
{
y = f[1] + 0.5f*f[3];
}
else
//-----------------------------------------------------------------------------
void vtkContext2D::DrawString(vtkPoints2D *point, const vtkStdString &string)
{
float *f = vtkFloatArray::SafeDownCast(point->GetData())->GetPointer(0);
this->DrawString(f[0], f[1], string);
}
//-----------------------------------------------------------------------------
void vtkContext2D::DrawString(float x, float y, const vtkStdString &string)
{
if (!this->Device)
{
y = f[1] + f[3];
vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D.");
return;
}
this->DrawString(x, y, string);
float f[] = { x, y };
this->Device->DrawString(f, this->TextProp, string);
}
//-----------------------------------------------------------------------------
void vtkContext2D::DrawString(vtkPoints2D *point, const vtkStdString &string)
void vtkContext2D::DrawString(vtkPoints2D *point, const vtkUnicodeString &string)
{
float *f = vtkFloatArray::SafeDownCast(point->GetData())->GetPointer(0);
this->DrawString(f[0], f[1], string);
}
//-----------------------------------------------------------------------------
void vtkContext2D::DrawString(float x, float y, const vtkStdString &string)
void vtkContext2D::DrawString(float x, float y, const vtkUnicodeString &string)
{
if (!this->Device)
{
......@@ -493,6 +490,19 @@ void vtkContext2D::DrawString(float x, float y, const vtkStdString &string)
this->Device->DrawString(&f[0], this->TextProp, string);
}
//-----------------------------------------------------------------------------
void vtkContext2D::DrawString(vtkPoints2D *point, const char* string)
{
float *f = vtkFloatArray::SafeDownCast(point->GetData())->GetPointer(0);
this->DrawString(f[0], f[1], vtkStdString(string));
}
//-----------------------------------------------------------------------------
void vtkContext2D::DrawString(float x, float y, const char* string)
{
this->DrawString(x, y, vtkStdString(string));
}
//-----------------------------------------------------------------------------
void vtkContext2D::ComputeStringBounds(const vtkStdString &string,
vtkPoints2D *bounds)
......@@ -514,6 +524,41 @@ void vtkContext2D::ComputeStringBounds(const vtkStdString &string,
this->Device->ComputeStringBounds(string, this->TextProp, bounds);
}
//-----------------------------------------------------------------------------
void vtkContext2D::ComputeStringBounds(const vtkUnicodeString &string,
vtkPoints2D *bounds)
{
bounds->SetNumberOfPoints(2);
float *f = vtkFloatArray::SafeDownCast(bounds->GetData())->GetPointer(0);
this->ComputeStringBounds(string, f);
}
//-----------------------------------------------------------------------------
void vtkContext2D::ComputeStringBounds(const vtkUnicodeString &string,
float bounds[4])
{
if (!this->Device)
{
vtkErrorMacro(<< "Attempted to paint with no active vtkContextDevice2D.");
return;
}
this->Device->ComputeStringBounds(string, this->TextProp, bounds);
}
//-----------------------------------------------------------------------------
void vtkContext2D::ComputeStringBounds(const char* string,
vtkPoints2D *bounds)
{
this->ComputeStringBounds(vtkStdString(string), bounds);
}
//-----------------------------------------------------------------------------
void vtkContext2D::ComputeStringBounds(const char* string,
float bounds[4])
{
this->ComputeStringBounds(vtkStdString(string), bounds);
}
//-----------------------------------------------------------------------------
void vtkContext2D::DrawImage(float x, float y, vtkImageData *image)
{
......@@ -629,8 +674,51 @@ inline void vtkContext2D::ApplyBrush()
if(!this->GetBufferIdMode())
{
this->Device->SetColor4(this->Brush->GetColor());
this->Device->SetTexture(this->Brush->GetTexture(), this->Brush->GetTextureProperties());
this->Device->SetTexture(this->Brush->GetTexture(),
this->Brush->GetTextureProperties());
}
}
//-----------------------------------------------------------------------------
vtkVector2f vtkContext2D::CalculateTextPosition(vtkPoints2D* rect)
{
// Draw the text at the appropriate point inside the rect for the alignment
// specified. This is a convenience when an area of the screen should have
// text drawn that is aligned to the entire area.
if (rect->GetNumberOfPoints() < 2)
{
return vtkVector2f();
}
vtkVector2f p;
float *f = vtkFloatArray::SafeDownCast(rect->GetData())->GetPointer(0);
if (this->TextProp->GetJustification() == VTK_TEXT_LEFT)
{
p.SetX(f[0]);
}
else if (this->TextProp->GetJustification() == VTK_TEXT_CENTERED)
{
p.SetX(f[0] + 0.5f*f[2]);
}
else
{
p.SetX(f[0] + f[2]);
}
if (this->TextProp->GetVerticalJustification() == VTK_TEXT_BOTTOM)
{
p.SetY(f[1]);
}
else if (this->TextProp->GetVerticalJustification() == VTK_TEXT_CENTERED)
{
p.SetY(f[1] + 0.5f*f[3]);
}
else
{
p.SetY(f[1] + f[3]);
}
return p;
}
//-----------------------------------------------------------------------------
......
......@@ -29,9 +29,11 @@
class vtkWindow;
class vtkStdString;
class vtkUnicodeString;
class vtkTextProperty;
class vtkPoints2D;
class vtkVector2f;
class vtkContextDevice2D;
class vtkPen;
class vtkBrush;
......@@ -228,11 +230,17 @@ public:
// of the text properties respecting the rectangle. The points should be
// supplied as bottom corner (x, y), width, height.
void DrawStringRect(vtkPoints2D *rect, const vtkStdString &string);
void DrawStringRect(vtkPoints2D *rect, const vtkUnicodeString &string);
void DrawStringRect(vtkPoints2D *rect, const char* string);
// Description:
// Draw some text to the screen.
void DrawString(vtkPoints2D *point, const vtkStdString &string);
void DrawString(float x, float y, const vtkStdString &string);
void DrawString(vtkPoints2D *point, const vtkUnicodeString &string);
void DrawString(float x, float y, const vtkUnicodeString &string);
void DrawString(vtkPoints2D *point, const char* string);
void DrawString(float x, float y, const char* string);
// Description:
// Compute the bounds of the supplied string. The bounds will be copied to the
......@@ -242,6 +250,10 @@ public:
// NOTE: This function does not take account of the text rotation.
void ComputeStringBounds(const vtkStdString &string, vtkPoints2D *bounds);
void ComputeStringBounds(const vtkStdString &string, float bounds[4]);
void ComputeStringBounds(const vtkUnicodeString &string, vtkPoints2D *bounds);
void ComputeStringBounds(const vtkUnicodeString &string, float bounds[4]);
void ComputeStringBounds(const char* string, vtkPoints2D *bounds);
void ComputeStringBounds(const char* string, float bounds[4]);
// Description:
// Apply the supplied pen which controls the outlines of shapes, as well as
......@@ -320,11 +332,18 @@ private:
vtkContext2D(const vtkContext2D &); // Not implemented.
void operator=(const vtkContext2D &); // Not implemented.
// Description:
// Apply the pen settings to the context
void ApplyPen();
// Description:
// Apply the brush settings to the context
void ApplyBrush();
// Description:
// Calculate position of text for rendering in a rectangle.
vtkVector2f CalculateTextPosition(vtkPoints2D* rect);
//ETX
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment