Commit 5c14d896 authored by David C. Lonie's avatar David C. Lonie
Browse files

Add GetConstrainedFontSize to FTTools and MTUtilities.

Add a method to compute the font size needed to make text rendered
by FreeTypeTools or MathTextUtilities fill a specified rectangle.
The documentation of vtkTextMapper::GetConstrainedFontSize is
clarified, too.

Change-Id: I39de26b5173153eaec9e8f5f2857fe9964bad768

s constrained -- add note about updated docs for tmapper

Change-Id: Ib8c042285aabc719fe57825c05d85b6ab2b59c4b
parent 37a9af50
......@@ -75,14 +75,16 @@ public:
vtkGetMacro(NumberOfLines,int);
// Description:
// Set and return the font size required to make this mapper fit in a given
// Set and return the font size (in points) required to make this mapper fit
// in a given
// target rectangle (width x height, in pixels). A static version of the method
// is also available for convenience to other classes (e.g., widgets).
virtual int SetConstrainedFontSize(vtkViewport*, int targetWidth, int targetHeight);
static int SetConstrainedFontSize(vtkTextMapper*, vtkViewport*, int targetWidth, int targetHeight);
// Description:
// Set and return the font size required to make each element of an array
// Set and return the font size (in points) required to make each element of
// an array
// of mappers fit in a given rectangle (width x height, in pixels). This
// font size is the smallest size that was required to fit the largest
// mapper in this constraint.
......
......@@ -463,6 +463,24 @@ bool vtkFreeTypeTools::StringToPath(vtkTextProperty *tprop,
return this->PopulatePath<vtkUnicodeString>(tprop, str, 0, 0, path);
}
//----------------------------------------------------------------------------
int vtkFreeTypeTools::GetConstrainedFontSize(const vtkStdString &str,
vtkTextProperty *tprop,
int targetWidth, int targetHeight)
{
return this->FitStringToBBox<vtkStdString>(str, tprop, targetWidth,
targetHeight);
}
//----------------------------------------------------------------------------
int vtkFreeTypeTools::GetConstrainedFontSize(const vtkUnicodeString &str,
vtkTextProperty *tprop,
int targetWidth, int targetHeight)
{
return this->FitStringToBBox<vtkUnicodeString>(str, tprop, targetWidth,
targetHeight);
}
//----------------------------------------------------------------------------
vtkTypeUInt16 vtkFreeTypeTools::HashString(const char *str)
{
......@@ -1520,6 +1538,84 @@ bool vtkFreeTypeTools::PopulatePath(vtkTextProperty *tprop,
return true;
}
//----------------------------------------------------------------------------
// Similar to implementations in vtkFreeTypeUtilities and vtkTextMapper.
template <typename T>
int vtkFreeTypeTools::FitStringToBBox(const T &str, vtkTextProperty *tprop,
int targetWidth, int targetHeight)
{
if (str.empty() || targetWidth == 0 || targetHeight == 0 || tprop == NULL)
{
return 0;
}
// sin, cos of orientation
double angle = vtkMath::RadiansFromDegrees(tprop->GetOrientation());
double c = cos(angle);
double s = sin(angle);
// Use the current font size as a first guess
int bbox[4];
int size[2];
int fontSize = tprop->GetFontSize();
if (!this->CalculateBoundingBox(tprop, str, bbox))
{
return -1;
}
int width = bbox[1] - bbox[0];
int height = bbox[3] - bbox[2];
size[0] = vtkMath::Floor(c * width - s * height + 0.5);
size[1] = vtkMath::Floor(s * width + c * height + 0.5);
// Bad assumption but better than nothing -- assume the bbox grows linearly
// with the font size:
if (size[0] != 0 && size[1] != 0)
{
fontSize *= std::min(
static_cast<double>(targetWidth) / static_cast<double>(size[0]),
static_cast<double>(targetHeight) / static_cast<double>(size[1]));
tprop->SetFontSize(fontSize);
if (!this->CalculateBoundingBox(tprop, str, bbox))
{
return -1;
}
width = bbox[1] - bbox[0];
height = bbox[3] - bbox[2];
size[0] = vtkMath::Floor(c * width - s * height + 0.5);
size[1] = vtkMath::Floor(s * width + c * height + 0.5);
}
// Now just step up/down until the bbox matches the target.
while ((size[0] < targetWidth || size[1] < targetHeight) && fontSize < 200)
{
tprop->SetFontSize(++fontSize);
if (!this->CalculateBoundingBox(tprop, str, bbox))
{
return -1;
}
width = bbox[1] - bbox[0];
height = bbox[3] - bbox[2];
size[0] = vtkMath::Floor(c * width - s * height + 0.5);
size[1] = vtkMath::Floor(s * width + c * height + 0.5);
}
while ((size[0] > targetWidth || size[1] > targetHeight) && fontSize > 0)
{
tprop->SetFontSize(--fontSize);
if (!this->CalculateBoundingBox(tprop, str, bbox))
{
return -1;
}
width = bbox[1] - bbox[0];
height = bbox[3] - bbox[2];
size[0] = vtkMath::Floor(c * width - s * height + 0.5);
size[1] = vtkMath::Floor(s * width + c * height + 0.5);
}
return fontSize;
}
//----------------------------------------------------------------------------
inline bool vtkFreeTypeTools::GetFace(vtkTextProperty *prop,
unsigned long &prop_cache_id,
FT_Face &face, bool &face_has_kerning)
......
......@@ -118,6 +118,16 @@ public:
bool StringToPath(vtkTextProperty *tprop, const vtkUnicodeString& str,
vtkPath *path);
// Description:
// This function returns the font size (in points) required to fit the string
// in the target rectangle. The font size of tprop is updated to the computed
// value as well. If an error occurs, -1 is returned.
int GetConstrainedFontSize(const vtkStdString &str, vtkTextProperty *tprop,
int targetWidth, int targetHeight);
int GetConstrainedFontSize(const vtkUnicodeString &str,
vtkTextProperty *tprop,
int targetWidth, int targetHeight);
// Description:
// Turn a string into a hash. This is not a general purpose hash
// function, and is only used to generate identifiers for cached fonts.
......@@ -190,6 +200,14 @@ protected:
bool PopulatePath(vtkTextProperty *tprop, const T& str,
int x, int y, vtkPath *path);
// Description:
// Internal helper method called by GetConstrainedFontSize. Returns the
// fontsize (in points) that will fit the return string @a str into the @a
// targetWidth and @a targetHeight.
template <typename T>
int FitStringToBBox(const T &str, vtkTextProperty *tprop, int targetWidth,
int targetHeight);
// Description:
// Given a text property, get the corresponding FreeType size object
// (a structure storing both a face and a specific size metric).
......
......@@ -236,8 +236,8 @@ public:
int *x, int *y);
// Description:
// This function returns the font size required to fit the string in the
// target rectangle
// This function returns the font size (in points) required to fit the string
// in the target rectangle
int GetConstrainedFontSize(const char *str, vtkTextProperty *tprop,
double orientation, int targetWidth,
int targetHeight);
......
......@@ -15,7 +15,9 @@
#include "vtkMathTextUtilities.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkTextProperty.h"
#ifdef VTK_DEBUG_LEAKS
#include "vtkDebugLeaks.h"
......@@ -85,6 +87,71 @@ void vtkMathTextUtilities::SetInstance(vtkMathTextUtilities* instance)
}
}
//----------------------------------------------------------------------------
int vtkMathTextUtilities::GetConstrainedFontSize(const char *str,
vtkTextProperty *tprop,
int targetWidth,
int targetHeight,
unsigned int dpi)
{
if (str == NULL || str[0] == '\0' || targetWidth == 0 || targetHeight == 0 ||
tprop == NULL)
{
return 0;
}
// Use the current font size as a first guess
int bbox[4];
int fontSize = tprop->GetFontSize();
if (!this->GetBoundingBox(tprop, str, dpi, bbox))
{
return -1;
}
int width = bbox[1] - bbox[0];
int height = bbox[3] - bbox[2];
// Bad assumption but better than nothing -- assume the bbox grows linearly
// with the font size:
if (width != 0 && height != 0)
{
fontSize *= std::min(
static_cast<double>(targetWidth) / static_cast<double>(width),
static_cast<double>(targetHeight) / static_cast<double>(height));
tprop->SetFontSize(fontSize);
if (!this->GetBoundingBox(tprop, str, dpi, bbox))
{
return -1;
}
width = bbox[1] - bbox[0];
height = bbox[3] - bbox[2];
}
// Now just step up/down until the bbox matches the target.
while ((width < targetWidth || height < targetHeight) && fontSize < 200)
{
tprop->SetFontSize(++fontSize);
if (!this->GetBoundingBox(tprop, str, dpi, bbox))
{
return -1;
}
width = bbox[1] - bbox[0];
height = bbox[3] - bbox[2];
}
while ((width > targetWidth || height > targetHeight) && fontSize > 0)
{
tprop->SetFontSize(--fontSize);
if (!this->GetBoundingBox(tprop, str, dpi, bbox))
{
return -1;
}
width = bbox[1] - bbox[0];
height = bbox[3] - bbox[2];
}
return fontSize;
}
//----------------------------------------------------------------------------
vtkMathTextUtilities* vtkMathTextUtilities::New()
{
......
......@@ -80,6 +80,16 @@ public:
virtual bool StringToPath(const char *str, vtkPath *path,
vtkTextProperty *tprop) = 0;
// Description:
// This function returns the font size (in points) required to fit the string
// in the target rectangle. The font size of tprop is updated to the computed
// value as well. If an error occurs (e.g. an improperly formatted MathText
// string), -1 is returned.
virtual int GetConstrainedFontSize(const char *str,
vtkTextProperty *tprop,
int targetWidth, int targetHeight,
unsigned int dpi);
protected:
vtkMathTextUtilities();
virtual ~vtkMathTextUtilities();
......
......@@ -383,10 +383,10 @@ bool vtkMatplotlibMathTextUtilities::GetBoundingBox(
double bboxd[4];
this->RotateCorners(angleDeg, corners, bboxd);
bbox[0] = vtkMath::Round(bboxd[0]);
bbox[1] = vtkMath::Round(bboxd[1]);
bbox[2] = vtkMath::Round(bboxd[2]);
bbox[3] = vtkMath::Round(bboxd[3]);
bbox[0] = vtkMath::Ceil(bboxd[0]);
bbox[1] = vtkMath::Ceil(bboxd[1]);
bbox[2] = vtkMath::Ceil(bboxd[2]);
bbox[3] = vtkMath::Ceil(bboxd[3]);
return true;
}
......
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