Commit deb96689 authored by Marcus D. Hanwell's avatar Marcus D. Hanwell Committed by Code Review
Browse files

Merge topic 'unicode-charts-master' into master

597cfab0 Use the std::string API from vtkContextUnicode
dff00e9e Add tests for unicode chart rendering.
5ff4f80b Add unicode text support to charts and context2D.
parents f604df1a 597cfab0
......@@ -5,6 +5,9 @@ vtk_add_test_cxx(NO_DATA NO_VALID
TestControlPointsItemEvents.cxx
)
set(TestChartUnicode_ARGS DATA{../Data/Fonts/DejaVuSans.ttf})
set(TestContextUnicode_ARGS DATA{../Data/Fonts/DejaVuSans.ttf})
# add tests that require data
vtk_add_test_cxx(
TestAxes.cxx
......@@ -12,10 +15,12 @@ vtk_add_test_cxx(
TestBarGraphHorizontal.cxx
TestColorTransferFunction.cxx,-E80
TestChartMatrix.cxx
TestChartUnicode.cxx,-E25
TestChartsOn3D.cxx,-E16
TestChartXYZ.cxx
TestContext.cxx
TestContextImage.cxx
TestContextUnicode.cxx
TestControlPointsHandleItem.cxx,-E30
TestDiagram.cxx
TestHistogram2D.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestLinePlot.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 "vtkAxis.h"
#include "vtkChartXY.h"
#include "vtkContextScene.h"
#include "vtkContextView.h"
#include "vtkFloatArray.h"
#include "vtkNew.h"
#include "vtkPlot.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkTable.h"
#include "vtkTextProperty.h"
#include <string>
//----------------------------------------------------------------------------
int TestChartUnicode(int argc, char *argv[])
{
if (argc < 2)
{
cout << "Missing font filename." << endl;
return EXIT_FAILURE;
}
std::string fontFile(argv[1]);
// Set up a 2D scene, add an XY chart to it
vtkNew<vtkContextView> view;
view->GetRenderWindow()->SetSize(400, 300);
vtkNew<vtkChartXY> chart;
view->GetScene()->AddItem(chart.GetPointer());
// Exercise the support for extended characters using UTF8 encoded strings.
chart->GetTitleProperties()->SetFontFamily(VTK_FONT_FILE);
chart->GetTitleProperties()->SetFontFile(fontFile.c_str());
chart->SetTitle("\xcf\x85\xcf\x84\xce\xba");
vtkAxis *axis1 = chart->GetAxis(0);
axis1->GetTitleProperties()->SetFontFamily(VTK_FONT_FILE);
axis1->GetTitleProperties()->SetFontFile(fontFile.c_str());
axis1->SetTitle("\xcf\x87(m)");
vtkAxis *axis2 = chart->GetAxis(1);
axis2->GetTitleProperties()->SetFontFamily(VTK_FONT_FILE);
axis2->GetTitleProperties()->SetFontFile(fontFile.c_str());
axis2->SetTitle("\xcf\x80\xcf\x86");
// Create a table with some points in it...
vtkNew<vtkTable> table;
vtkNew<vtkFloatArray> arrX;
arrX->SetName("X Axis");
table->AddColumn(arrX.GetPointer());
vtkNew<vtkFloatArray> arrC;
arrC->SetName("Cosine");
table->AddColumn(arrC.GetPointer());
int numPoints = 69;
float inc = 7.5 / (numPoints - 1);
table->SetNumberOfRows(numPoints);
for (int i = 0; i < numPoints; ++i)
{
table->SetValue(i, 0, i * inc);
table->SetValue(i, 1, cos(i * inc) + sin(i * (inc - 3.14)));
}
// Add multiple line plots, setting the colors etc
vtkPlot *line = chart->AddPlot(vtkChart::LINE);
line->SetInputData(table.GetPointer(), 0, 1);
line->SetColor(42, 55, 69, 255);
// Render the scene and compare the image to a reference image
view->GetRenderWindow()->SetMultiSamples(0);
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
return EXIT_SUCCESS;
}
......@@ -23,12 +23,15 @@
#include "vtkContextScene.h"
#include "vtkPen.h"
#include "vtkBrush.h"
#include "vtkTestUtilities.h"
#include "vtkTextProperty.h"
#include "vtkUnicodeString.h"
#include "vtkRegressionTestImage.h"
#include <string>
//----------------------------------------------------------------------------
class ContextUnicode : public vtkContextItem
{
......@@ -37,15 +40,25 @@ public:
vtkTypeMacro(ContextUnicode, vtkContextItem);
// Paint event for the chart, called whenever the chart needs to be drawn
virtual bool Paint(vtkContext2D *painter);
std::string FontFile;
};
//----------------------------------------------------------------------------
int TestContextUnicode(int argc, char * argv [])
{
if (argc < 2)
{
cout << "Missing font filename." << endl;
return EXIT_FAILURE;
}
std::string fontFile(argv[1]);
// 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();
test->FontFile = fontFile;
view->GetScene()->AddItem(test);
view->GetRenderWindow()->SetMultiSamples(0);
......@@ -70,10 +83,12 @@ bool ContextUnicode::Paint(vtkContext2D *painter)
painter->GetTextProp()->SetJustificationToCentered();
painter->GetTextProp()->SetColor(0.0, 0.0, 0.0);
painter->GetTextProp()->SetFontSize(24);
painter->GetTextProp()->SetFontFamily(VTK_FONT_FILE);
painter->GetTextProp()->SetFontFile(this->FontFile.c_str());
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"));
vtkUnicodeString::from_utf8("a\xce\xb1"));
painter->DrawString(100, 50,
vtkUnicodeString::from_utf8("\xce\xb1\xce\xb2\xce\xb3"));
return true;
......
......@@ -75,6 +75,7 @@
#define VTK_COURIER 1
#define VTK_TIMES 2
#define VTK_UNKNOWN_FONT 3
#define VTK_FONT_FILE 4
#define VTK_TEXT_LEFT 0
#define VTK_TEXT_CENTERED 1
......
......@@ -798,6 +798,20 @@ void vtkOpenGLContextDevice2D::AlignText(double orientation, float width,
//-----------------------------------------------------------------------------
void vtkOpenGLContextDevice2D::DrawString(float *point,
const vtkStdString &string)
{
this->DrawString(point, vtkUnicodeString::from_utf8(string));
}
//-----------------------------------------------------------------------------
void vtkOpenGLContextDevice2D::ComputeStringBounds(const vtkStdString &string,
float bounds[4])
{
this->ComputeStringBounds(vtkUnicodeString::from_utf8(string), bounds);
}
//-----------------------------------------------------------------------------
void vtkOpenGLContextDevice2D::DrawString(float *point,
const vtkUnicodeString &string)
{
vtkOpenGLClearErrorMacro();
......@@ -810,9 +824,9 @@ void vtkOpenGLContextDevice2D::DrawString(float *point,
std::floor(point[1] * yScale) / yScale };
// Cache rendered text strings
vtkTextureImageCache<TextPropertyKey>::CacheData &cache =
this->Storage->TextTextureCache.GetCacheData(
TextPropertyKey(this->TextProp, string));
vtkTextureImageCache<UTF16TextPropertyKey>::CacheData &cache =
this->Storage->TextTextureCache.GetCacheData(
UTF16TextPropertyKey(this->TextProp, string));
vtkImageData* image = cache.ImageData;
if (image->GetNumberOfPoints() == 0 && image->GetNumberOfCells() == 0)
{
......@@ -864,47 +878,6 @@ void vtkOpenGLContextDevice2D::DrawString(float *point,
vtkOpenGLCheckErrorMacro("failed after DrawString");
}
//-----------------------------------------------------------------------------
void vtkOpenGLContextDevice2D::ComputeStringBounds(const vtkStdString &string,
float bounds[4])
{
vtkVector2i box = this->TextRenderer->GetBounds(this->TextProp, string);
// Check for invalid bounding box
if (box[0] == VTK_INT_MIN || box[0] == VTK_INT_MAX ||
box[1] == VTK_INT_MIN || box[1] == VTK_INT_MAX)
{
bounds[0] = static_cast<float>(0);
bounds[1] = static_cast<float>(0);
bounds[2] = static_cast<float>(0);
bounds[3] = static_cast<float>(0);
return;
}
GLfloat mv[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
float xScale = mv[0];
float yScale = mv[5];
bounds[0] = static_cast<float>(0);
bounds[1] = static_cast<float>(0);
bounds[2] = static_cast<float>(box.GetX() / xScale);
bounds[3] = static_cast<float>(box.GetY() / yScale);
}
//-----------------------------------------------------------------------------
void vtkOpenGLContextDevice2D::DrawString(float *point,
const vtkUnicodeString &string)
{
int p[] = { static_cast<int>(point[0]),
static_cast<int>(point[1]) };
//TextRenderer draws in window, not viewport coords
p[0]+=this->Storage->Offset.GetX();
p[1]+=this->Storage->Offset.GetY();
vtkImageData *data = vtkImageData::New();
this->TextRenderer->RenderString(this->TextProp, string, data);
this->DrawImage(point, 1.0, data);
data->Delete();
}
//-----------------------------------------------------------------------------
void vtkOpenGLContextDevice2D::ComputeStringBounds(const vtkUnicodeString &string,
float bounds[4])
......@@ -948,9 +921,9 @@ void vtkOpenGLContextDevice2D::DrawMathTextString(float point[2],
float p[] = { std::floor(point[0]), std::floor(point[1]) };
// Cache rendered text strings
vtkTextureImageCache<TextPropertyKey>::CacheData &cache =
vtkTextureImageCache<UTF8TextPropertyKey>::CacheData &cache =
this->Storage->MathTextTextureCache.GetCacheData(
TextPropertyKey(this->TextProp, string));
UTF8TextPropertyKey(this->TextProp, string));
vtkImageData* image = cache.ImageData;
if (image->GetNumberOfPoints() == 0 && image->GetNumberOfCells() == 0)
{
......
......@@ -35,6 +35,9 @@
#include "vtkColor.h"
#include "vtkTextProperty.h"
#include "vtkFreeTypeTools.h"
#include "vtkStdString.h"
#include "vtkUnicodeString.h"
#include <algorithm>
#include <list>
#include <utility>
......@@ -162,6 +165,7 @@ typename vtkTextureImageCache<Key>::CacheData& vtkTextureImageCache<Key>
// .NAME TextPropertyKey - unique key for a vtkTextProperty and text
// .SECTION Description
// Uniquely describe a pair of vtkTextProperty and text.
template <class StringType>
struct TextPropertyKey
{
// Description:
......@@ -175,7 +179,7 @@ struct TextPropertyKey
// Description:
// Creates a TextPropertyKey.
TextPropertyKey(vtkTextProperty* textProperty, const vtkStdString& text)
TextPropertyKey(vtkTextProperty* textProperty, const StringType& text)
{
this->TextPropertyId = GetIdFromTextProperty(textProperty);
this->FontSize = textProperty->GetFontSize();
......@@ -206,9 +210,12 @@ struct TextPropertyKey
vtkColor4ub Color;
// States in the function not to use more than 32 bits - int works fine here.
unsigned int TextPropertyId;
vtkStdString Text;
StringType Text;
};
typedef TextPropertyKey<vtkStdString> UTF8TextPropertyKey;
typedef TextPropertyKey<vtkUnicodeString> UTF16TextPropertyKey;
class vtkOpenGLContextDevice2D::Private
{
public:
......@@ -502,8 +509,8 @@ public:
// Description:
// Cache for text images. Generating texture for strings is expensive,
// we cache the textures here for a faster reuse.
mutable vtkTextureImageCache<TextPropertyKey> TextTextureCache;
mutable vtkTextureImageCache<TextPropertyKey> MathTextTextureCache;
mutable vtkTextureImageCache<UTF16TextPropertyKey> TextTextureCache;
mutable vtkTextureImageCache<UTF8TextPropertyKey> MathTextTextureCache;
};
#endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H
......
......@@ -27,6 +27,7 @@ vtkTextProperty::vtkTextProperty()
this->Opacity = 1.0;
this->FontFamilyAsString = 0;
this->FontFile = NULL;
this->SetFontFamilyAsString( "Arial" );
this->FontSize = 12;
......@@ -48,6 +49,7 @@ vtkTextProperty::vtkTextProperty()
vtkTextProperty::~vtkTextProperty()
{
this->SetFontFamilyAsString(NULL);
this->SetFontFile(NULL);
}
//----------------------------------------------------------------------------
......@@ -62,6 +64,7 @@ void vtkTextProperty::ShallowCopy(vtkTextProperty *tprop)
this->SetOpacity(tprop->GetOpacity());
this->SetFontFamilyAsString(tprop->GetFontFamilyAsString());
this->SetFontFile(tprop->GetFontFile());
this->SetFontSize(tprop->GetFontSize());
this->SetBold(tprop->GetBold());
......@@ -105,6 +108,8 @@ void vtkTextProperty::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "FontFamilyAsString: "
<< (this->FontFamilyAsString ? this->FontFamilyAsString : "(null)") << endl;
os << indent << "FontFile: "
<< (this->FontFile ? this->FontFile : "(null)") << endl;
os << indent << "FontSize: " << this->FontSize << "\n";
os << indent << "Bold: " << (this->Bold ? "On\n" : "Off\n");
......
......@@ -51,6 +51,9 @@ public:
// Description:
// Set/Get the font family. Supports legacy three font family system.
// If the symbolic constant VTK_FONT_FILE is returned by GetFontFamily(), the
// string returned by GetFontFile() must be an absolute filepath
// to a local FreeType compatible font.
vtkGetStringMacro(FontFamilyAsString);
vtkSetStringMacro(FontFamilyAsString);
void SetFontFamily(int t);
......@@ -62,6 +65,13 @@ public:
static int GetFontFamilyFromString( const char *f );
static const char *GetFontFamilyAsString( int f );
// Description:
// The absolute filepath to a local file containing a freetype-readable font
// if GetFontFamily() return VTK_FONT_FILE. The result is undefined for other
// values of GetFontFamily().
vtkGetStringMacro(FontFile)
vtkSetStringMacro(FontFile)
// Description:
// Set/Get the font size (in points).
vtkSetClampMacro(FontSize,int,0,VTK_INT_MAX);
......@@ -148,6 +158,7 @@ protected:
double Color[3];
double Opacity;
char* FontFamilyAsString;
char* FontFile;
int FontSize;
int Bold;
int Italic;
......@@ -178,6 +189,10 @@ inline const char *vtkTextProperty::GetFontFamilyAsString( int f )
{
return "Times";
}
else if ( f == VTK_FONT_FILE )
{
return "File";
}
return "Unknown";
}
......@@ -215,6 +230,10 @@ inline int vtkTextProperty::GetFontFamilyFromString( const char *f )
{
return VTK_TIMES;
}
else if ( strcmp( f, GetFontFamilyAsString( VTK_FONT_FILE) ) == 0 )
{
return VTK_FONT_FILE;
}
return VTK_UNKNOWN_FONT;
}
......
......@@ -536,7 +536,11 @@ void vtkFreeTypeTools::MapTextPropertyToId(vtkTextProperty *tprop,
int bits = 1;
// The font family is hashed into 16 bits (= 17 bits so far)
*id |= vtkFreeTypeTools::HashString(tprop->GetFontFamilyAsString()) << bits;
vtkTypeUInt16 familyHash =
vtkFreeTypeTools::HashString(tprop->GetFontFamily() != VTK_FONT_FILE
? tprop->GetFontFamilyAsString()
: tprop->GetFontFile());
*id |= familyHash << bits;
bits += 16;
// Bold is in 1 bit (= 18 bits so far)
......@@ -862,6 +866,23 @@ bool vtkFreeTypeTools::LookupFace(vtkTextProperty *tprop, FT_Library lib,
" unavailable. Substituting Arial.");
family = VTK_ARIAL;
}
else if (family == VTK_FONT_FILE)
{
vtkDebugWithObjectMacro(tprop,
<< "Attempting to load font from file: "
<< tprop->GetFontFile());
if (FT_New_Face(lib, tprop->GetFontFile(), 0, face) == 0)
{
return true;
}
vtkDebugWithObjectMacro(
tprop,
<< "Error loading font from file '" << tprop->GetFontFile()
<< "'. Falling back to arial.");
family = VTK_ARIAL;
}
FT_Long length = EmbeddedFonts
[family][tprop->GetBold()][tprop->GetItalic()].length;
......@@ -1938,6 +1959,7 @@ void vtkFreeTypeTools::GetLineMetrics(T begin, T end, MetaData &metaData,
{
// FIXME: do something more elegant here.
// We should render an empty rectangle to adhere to the specs...
vtkDebugMacro(<<"Unrecognized character: " << *begin);
continue;
}
......
......@@ -46,8 +46,9 @@ vtkFontConfigFreeTypeToolsFaceRequester(FTC_FaceID face_id,
vtkSmartPointer<vtkTextProperty>::New();
self->MapIdToTextProperty(reinterpret_cast<intptr_t>(face_id), tprop);
bool faceIsSet = self->GetForceCompiledFonts() ?
false : self->LookupFaceFontConfig(tprop, lib, face);
bool faceIsSet =
self->GetForceCompiledFonts() || tprop->GetFontFamily() == VTK_FONT_FILE
? false : self->LookupFaceFontConfig(tprop, lib, face);
// Fall back to compiled fonts if lookup fails/compiled fonts are forced:
if (!faceIsSet)
......
Markdown is supported
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