Commit 16838f7c authored by David C. Lonie's avatar David C. Lonie

Move FontConfig font lookup to its own module.

This removes the VTK_USE_FONTCONFIG option and is more consistent
with the modular approach.

Change-Id: Iaa7383667b116a0e9b596f9467b824710e865b5f
parent a83a346c
......@@ -4,7 +4,6 @@
TestContextScene.cxx
TestControlPointsItem.cxx
TestControlPointsItemEvents.cxx
TestSimpleFontRendering.cxx
)
if(VTK_DATA_ROOT)
......
find_package(FontConfig QUIET)
option(VTK_USE_FONTCONFIG
"Enable system font support through FontConfig"
${FONTCONFIG_FOUND}
)
if (VTK_USE_FONTCONFIG AND NOT FONTCONFIG_FOUND)
message(SEND_ERROR "VTK_USE_FONTCONFIG is enabled but FontConfig was not found. Please set FONTCONFIG_INCLUDE_DIR and FONTCONFIG_LIBRARY.")
endif()
if(VTK_USE_FONTCONFIG)
include_directories(${FONTCONFIG_INCLUDE_DIR})
endif()
set(Module_SRCS
vtkFreeTypeStringToImage.cxx
vtkFreeTypeUtilities.cxx
......@@ -54,15 +39,4 @@ set_source_files_properties(
WRAP_EXCLUDE
)
if(VTK_USE_FONTCONFIG)
set_property(SOURCE vtkFreeTypeTools.cxx
PROPERTY COMPILE_DEFINITIONS FONTCONFIG_FOUND)
endif()
vtk_module_library(${vtk-module} ${Module_SRCS})
if(VTK_USE_FONTCONFIG)
target_link_libraries(${vtk-module} ${FONTCONFIG_LIBRARIES})
endif()
mark_as_advanced(VTK_USE_FONTCONFIG)
......@@ -31,11 +31,6 @@
// The embedded fonts
#include "fonts/vtkEmbeddedFonts.h"
// Font config
#ifdef FONTCONFIG_FOUND
#include <fontconfig/fontconfig.h>
#endif
#ifndef _MSC_VER
# include <stdint.h>
#endif
......@@ -156,8 +151,7 @@ vtkFreeTypeTools::vtkFreeTypeTools()
#if VTK_FTFC_DEBUG_CD
printf("vtkFreeTypeTools::vtkFreeTypeTools\n");
#endif
// Skip FontConfig lookup by default.
// Force use of compiled fonts by default.
this->ForceCompiledFonts = true;
this->MaximumNumberOfFaces = 30; // combinations of family+bold+italic
this->MaximumNumberOfSizes = this->MaximumNumberOfFaces * 20; // sizes
......@@ -248,18 +242,12 @@ vtkFreeTypeToolsFaceRequester(FTC_FaceID face_id,
vtkSmartPointer<vtkTextProperty>::New();
self->MapIdToTextProperty(reinterpret_cast<intptr_t>(face_id), tprop);
bool faceIsSet = false;
#ifdef FONTCONFIG_FOUND
if (!self->GetForceCompiledFonts())
{
faceIsSet = self->LookupFaceFontConfig(tprop, lib, face);
}
#endif
if (!faceIsSet)
faceIsSet = self->LookupFaceCompiledFonts(tprop, lib, face);
bool faceIsSet = self->LookupFace(tprop, lib, face);
if (!faceIsSet)
{
return static_cast<FT_Error>(1);
}
if ( tprop->GetOrientation() != 0.0 )
{
......@@ -292,13 +280,7 @@ void vtkFreeTypeTools::InitializeCacheManager()
// Create the cache manager itself
this->CacheManager = new FTC_Manager;
error = FTC_Manager_New(*this->GetLibrary(),
this->MaximumNumberOfFaces,
this->MaximumNumberOfSizes,
this->MaximumNumberOfBytes,
vtkFreeTypeToolsFaceRequester,
static_cast<FT_Pointer>(this),
this->CacheManager);
error = this->CreateFTCManager();
if (error)
{
......@@ -754,99 +736,8 @@ bool vtkFreeTypeTools::GetGlyph(unsigned long tprop_cache_id,
return error ? false : true;
}
#ifdef FONTCONFIG_FOUND
bool vtkFreeTypeTools::LookupFaceFontConfig(vtkTextProperty *tprop,
FT_Library lib, FT_Face *face)
{
if (!FcInit())
{
return false;
}
// Query tprop
const FcChar8 *family = reinterpret_cast<const FcChar8*>(
tprop->GetFontFamilyAsString());
const double pointSize = static_cast<double>(tprop->GetFontSize());
const int weight = tprop->GetBold() ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM;
const int slant = tprop->GetItalic() ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
// Build pattern
FcPattern *pattern = FcPatternCreate();
FcPatternAddString(pattern, FC_FAMILY, family);
FcPatternAddDouble(pattern, FC_SIZE, pointSize);
FcPatternAddInteger(pattern, FC_WEIGHT, weight);
FcPatternAddInteger(pattern, FC_SLANT, slant);
FcPatternAddBool(pattern, FC_SCALABLE, true);
// Replace common font names, e.g. arial, times, etc -> sans, serif, etc
FcConfigSubstitute(NULL, pattern, FcMatchPattern);
// Fill in any missing defaults:
FcDefaultSubstitute(pattern);
// Match pattern
FcResult result;
FcFontSet *fontMatches = FcFontSort(NULL, pattern, false, NULL, &result);
FcPatternDestroy(pattern);
pattern = NULL;
if (!fontMatches || fontMatches->nfont == 0)
{
if (fontMatches)
FcFontSetDestroy(fontMatches);
return false;
}
// Grab the first match that is scalable -- even though we've requested
// scalable fonts in the match, FC seems to not weigh that option very heavily
FcPattern *match = NULL;
for (int i = 0; i < fontMatches->nfont; ++i)
{
match = fontMatches->fonts[i];
FcBool isScalable;
FcPatternGetBool(match, FC_SCALABLE, 0, &isScalable);
if (!isScalable)
continue;
else
break;
}
if (!match)
{
FcFontSetDestroy(fontMatches);
return false;
}
// Get filename. Do not free the filename string -- it is owned by FcPattern
// "match". Likewise, do not use the filename after match is freed.
FcChar8 *filename;
result = FcPatternGetString(match, FC_FILE, 0, &filename);
cout << "Loading a font from disk: " << filename << endl;
FT_Error error = FT_New_Face(lib, reinterpret_cast<const char*>(filename), 0,
face);
if (error)
{
FcFontSetDestroy(fontMatches);
return false;
}
FcFontSetDestroy(fontMatches);
fontMatches = NULL;
return true;
}
#else // FONTCONFIG_FOUND
bool vtkFreeTypeTools::LookupFaceFontConfig(vtkTextProperty *vtkNotUsed(tprop),
FT_Library vtkNotUsed(lib), FT_Face *vtkNotUsed(face))
{
return false;
}
#endif
bool vtkFreeTypeTools::LookupFaceCompiledFonts(vtkTextProperty *tprop,
FT_Library lib, FT_Face *face)
bool vtkFreeTypeTools::LookupFace(vtkTextProperty *tprop, FT_Library lib,
FT_Face *face)
{
// Fonts, organized by [Family][Bold][Italic]
static EmbeddedFontStruct EmbeddedFonts[3][2][2] =
......@@ -999,6 +890,18 @@ void vtkFreeTypeTools::PrintSelf(ostream& os, vtkIndent indent)
<< this->ScaleToPowerTwo << endl;
}
//----------------------------------------------------------------------------
FT_Error vtkFreeTypeTools::CreateFTCManager()
{
return FTC_Manager_New(*this->GetLibrary(),
this->MaximumNumberOfFaces,
this->MaximumNumberOfSizes,
this->MaximumNumberOfBytes,
vtkFreeTypeToolsFaceRequester,
static_cast<FT_Pointer>(this),
this->CacheManager);
}
//----------------------------------------------------------------------------
template <typename T>
bool vtkFreeTypeTools::CalculateBoundingBox(vtkTextProperty *tprop,
......
......@@ -138,27 +138,23 @@ public:
// Description:
// Force use of the fonts compiled into VTK, ignoring any FontConfig or
// embedded fonts. Useful for generating test images consistently across
// platforms.
// platforms. This flag is on by default.
vtkSetMacro(ForceCompiledFonts, bool);
vtkGetMacro(ForceCompiledFonts, bool);
vtkBooleanMacro(ForceCompiledFonts, bool);
// Description:
// Lookup and set the FreeType font face @a face best matching the text
// property @a tprop using FontConfig to query the installed system fonts.
// Returns true if the face is set, false otherwise.
static bool LookupFaceFontConfig(vtkTextProperty *tprop, FT_Library lib,
FT_Face *face);
// Description:
// Lookup and set the FreeType font face @a face best matching the text
// property @a tprop using the compiled Arial, Times, and Courier fonts. If
// an unrecognized font family is requested, Arial will be substituted.
// Returns true if the face is set, false otherwise.
static bool LookupFaceCompiledFonts(vtkTextProperty *tprop, FT_Library lib,
FT_Face *face);
static bool LookupFace(vtkTextProperty *tprop, FT_Library lib, FT_Face *face);
protected:
// Description:
// Create the FreeType Cache manager instance and set this->CacheManager
virtual FT_Error CreateFTCManager();
// Description:
// This function initializes calculates the size of the required bounding box.
template <typename T>
......@@ -238,10 +234,6 @@ protected:
vtkFreeTypeTools();
virtual ~vtkFreeTypeTools();
private:
vtkFreeTypeTools(const vtkFreeTypeTools&); // Not implemented.
void operator=(const vtkFreeTypeTools&); // Not implemented.
// Description:
// Attempt to get the typeface of the specified font.
bool GetFace(vtkTextProperty *prop, unsigned long &prop_cache_id,
......@@ -282,6 +274,10 @@ private:
void InitializeCacheManager();
void ReleaseCacheManager();
private:
vtkFreeTypeTools(const vtkFreeTypeTools&); // Not implemented.
void operator=(const vtkFreeTypeTools&); // Not implemented.
};
#endif
find_package(FontConfig REQUIRED)
include_directories(${FONTCONFIG_INCLUDE_DIR})
set(Module_SRCS
vtkFontConfigFreeTypeTools.cxx
${CMAKE_CURRENT_BINARY_DIR}/vtkRenderingFreeTypeFontConfigObjectFactory.cxx
)
set_source_files_properties(
vtkFontConfigFreeTypeTools
vtkRenderingFreeTypeFontConfigObjectFactory
WRAP_EXCLUDE
)
# Setup overrides
list(APPEND vtk_module_overrides "vtkFreeTypeTools")
set(vtk_module_vtkFreeTypeTools_override "vtkFontConfigFreeTypeTools")
# Now we iterate and create that class file...
foreach(_class ${vtk_module_overrides})
set(_override ${vtk_module_${_class}_override})
set(_vtk_override_includes "${_vtk_override_includes}
#include \"${_override}.h\"")
set(_vtk_override_creates "${_vtk_override_creates}
VTK_CREATE_CREATE_FUNCTION(${_override})")
set(_vtk_override_do "${_vtk_override_do}
this->RegisterOverride(\"${_class}\",
\"${_override}\",
\"Override for ${vtk-module} module\", 1,
vtkObjectFactoryCreate${_override});")
endforeach()
# Now lets create the object factory classes
string(TOUPPER ${vtk-module} VTK-MODULE)
configure_file(${VTK_CMAKE_DIR}/vtkObjectFactory.h.in
${CMAKE_CURRENT_BINARY_DIR}/${vtk-module}ObjectFactory.h)
configure_file(${VTK_CMAKE_DIR}/vtkObjectFactory.cxx.in
${CMAKE_CURRENT_BINARY_DIR}/${vtk-module}ObjectFactory.cxx)
vtk_module_library(${vtk-module} ${Module_SRCS})
target_link_libraries(${vtk-module} ${FONTCONFIG_LIBRARIES})
# add tests that do not require data
set(MyTests
TestSystemFontRendering
)
# Use the testing object factory, to reduce boilerplate code in tests.
include("${vtkTestingRendering_SOURCE_DIR}/vtkTestingObjectFactory.cmake")
vtk_module_test_executable(${vtk-module}CxxTests ${Tests})
set(TestsToRun ${Tests})
remove(TestsToRun CxxTests.cxx)
# Add all the executables
foreach(test ${TestsToRun})
get_filename_component(TName ${test} NAME_WE)
if(VTK_DATA_ROOT)
if(${${TName}Error})
set(_error_threshold ${${TName}Error})
else()
set(_error_threshold 10)
endif()
add_test(NAME Charts-${TName}
COMMAND ${vtk-module}CxxTests ${TName}
-D ${VTK_DATA_ROOT}
-T ${VTK_TEST_OUTPUT_DIR}
-V Baseline/Rendering/${TName}.png
-E ${_error_threshold})
else()
add_test(NAME Charts-${TName}
COMMAND ${vtk-module}CxxTests ${TName})
endif()
endforeach()
/*=========================================================================
Program: Visualization Toolkit
Module: TestContext.cxx
Module: TestSimpleFontRendering.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
......@@ -29,30 +29,30 @@
#include "vtkRegressionTestImage.h"
//----------------------------------------------------------------------------
class SimpleFontRenderTest : public vtkContextItem
class SystemFontRenderTest : public vtkContextItem
{
public:
static SimpleFontRenderTest *New();
vtkTypeMacro(SimpleFontRenderTest, vtkContextItem);
static SystemFontRenderTest *New();
vtkTypeMacro(SystemFontRenderTest, vtkContextItem);
// Paint event for the chart, called whenever the chart needs to be drawn
virtual bool Paint(vtkContext2D *painter);
};
//----------------------------------------------------------------------------
int TestSimpleFontRendering( int, char * [] )
int TestSystemFontRendering( int, char * [] )
{
// Set up a 2D context view, context test object and add it to the scene
vtkNew<vtkContextView> view;
view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
view->GetRenderWindow()->SetSize(520, 360);
vtkNew<SimpleFontRenderTest> test;
vtkNew<SystemFontRenderTest> test;
view->GetScene()->AddItem(test.GetPointer());
// Force the use of the freetype based rendering strategy
vtkOpenGLContextDevice2D::SafeDownCast(view->GetContext()->GetDevice())
->SetStringRendererToFreeType();
// Use the new FontConfig font lookup
// Use the FontConfig font lookup
vtkFreeTypeTools::GetInstance()->ForceCompiledFontsOff();
view->GetRenderWindow()->SetMultiSamples(0);
......@@ -62,8 +62,8 @@ int TestSimpleFontRendering( int, char * [] )
}
// Make our new derived class to draw a diagram
vtkStandardNewMacro(SimpleFontRenderTest);
bool SimpleFontRenderTest::Paint(vtkContext2D *painter)
vtkStandardNewMacro(SystemFontRenderTest);
bool SystemFontRenderTest::Paint(vtkContext2D *painter)
{
painter->GetTextProp()->SetColor(0.0, 0.0, 0.0);
painter->GetTextProp()->SetFontSize(24);
......
vtk_module(vtkRenderingFreeTypeFontConfig
IMPLEMENTS
vtkRenderingFreeType
TEST_DEPENDS
vtkChartsCore
vtkTestingRendering
vtkViewsContext2D
)
/*=========================================================================
Program: Visualization Toolkit
Module: vtkFontConfigFreeTypeTools.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 "vtkFontConfigFreeTypeTools.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
#include "vtkTextProperty.h"
#ifndef _MSC_VER
# include <stdint.h>
#endif
#include <fontconfig/fontconfig.h>
vtkStandardNewMacro(vtkFontConfigFreeTypeTools)
namespace
{
// The FreeType face requester callback:
FT_CALLBACK_DEF(FT_Error)
vtkFontConfigFreeTypeToolsFaceRequester(FTC_FaceID face_id,
FT_Library lib,
FT_Pointer request_data,
FT_Face* face)
{
// Get a pointer to the current vtkFontConfigFreeTypeTools object
vtkFontConfigFreeTypeTools *self =
reinterpret_cast<vtkFontConfigFreeTypeTools*>(request_data);
// Map the ID to a text property
vtkSmartPointer<vtkTextProperty> tprop =
vtkSmartPointer<vtkTextProperty>::New();
self->MapIdToTextProperty(reinterpret_cast<intptr_t>(face_id), tprop);
bool faceIsSet = self->GetForceCompiledFonts() ?
false : self->LookupFaceFontConfig(tprop, lib, face);
// Fall back to compiled fonts if lookup fails/compiled fonts are forced:
if (!faceIsSet)
{
faceIsSet = self->Superclass::LookupFace(tprop, lib, face);
}
if (!faceIsSet)
{
return static_cast<FT_Error>(1);
}
if ( tprop->GetOrientation() != 0.0 )
{
// FreeType documentation says that the transform should not be set
// but we cache faces also by transform, so that there is a unique
// (face, orientation) cache entry
FT_Matrix matrix;
float angle = vtkMath::RadiansFromDegrees( tprop->GetOrientation() );
matrix.xx = (FT_Fixed)( cos(angle) * 0x10000L);
matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
matrix.yx = (FT_Fixed)( sin(angle) * 0x10000L);
matrix.yy = (FT_Fixed)( cos(angle) * 0x10000L);
FT_Set_Transform(*face, &matrix, NULL);
}
return static_cast<FT_Error>(0);
}
} // end anon namespace
void vtkFontConfigFreeTypeTools::PrintSelf(ostream &os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
vtkFontConfigFreeTypeTools::vtkFontConfigFreeTypeTools()
{
}
vtkFontConfigFreeTypeTools::~vtkFontConfigFreeTypeTools()
{
}
FT_Error vtkFontConfigFreeTypeTools::CreateFTCManager()
{
return FTC_Manager_New(*this->GetLibrary(),
this->MaximumNumberOfFaces,
this->MaximumNumberOfSizes,
this->MaximumNumberOfBytes,
vtkFontConfigFreeTypeToolsFaceRequester,
static_cast<FT_Pointer>(this),
this->CacheManager);
}
bool vtkFontConfigFreeTypeTools::LookupFaceFontConfig(vtkTextProperty *tprop,
FT_Library lib,
FT_Face *face)
{
if (!FcInit())
{
return false;
}
// Query tprop
const FcChar8 *family = reinterpret_cast<const FcChar8*>(
tprop->GetFontFamilyAsString());
const double pointSize = static_cast<double>(tprop->GetFontSize());
const int weight = tprop->GetBold() ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM;
const int slant = tprop->GetItalic() ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
// Build pattern
FcPattern *pattern = FcPatternCreate();
FcPatternAddString(pattern, FC_FAMILY, family);
FcPatternAddDouble(pattern, FC_SIZE, pointSize);
FcPatternAddInteger(pattern, FC_WEIGHT, weight);
FcPatternAddInteger(pattern, FC_SLANT, slant);
FcPatternAddBool(pattern, FC_SCALABLE, true);
// Replace common font names, e.g. arial, times, etc -> sans, serif, etc
FcConfigSubstitute(NULL, pattern, FcMatchPattern);
// Fill in any missing defaults:
FcDefaultSubstitute(pattern);
// Match pattern
FcResult result;
FcFontSet *fontMatches = FcFontSort(NULL, pattern, false, NULL, &result);
FcPatternDestroy(pattern);
pattern = NULL;
if (!fontMatches || fontMatches->nfont == 0)
{
if (fontMatches)
FcFontSetDestroy(fontMatches);
return false;
}
// Grab the first match that is scalable -- even though we've requested
// scalable fonts in the match, FC seems to not weigh that option very heavily
FcPattern *match = NULL;
for (int i = 0; i < fontMatches->nfont; ++i)
{
match = fontMatches->fonts[i];
FcBool isScalable;
FcPatternGetBool(match, FC_SCALABLE, 0, &isScalable);
if (!isScalable)
continue;
else
break;
}
if (!match)
{
FcFontSetDestroy(fontMatches);
return false;
}
// Get filename. Do not free the filename string -- it is owned by FcPattern
// "match". Likewise, do not use the filename after match is freed.
FcChar8 *filename;
result = FcPatternGetString(match, FC_FILE, 0, &filename);
FT_Error error = FT_New_Face(lib, reinterpret_cast<const char*>(filename), 0,
face);
if (error)
{
FcFontSetDestroy(fontMatches);
return false;
}
FcFontSetDestroy(fontMatches);
fontMatches = NULL;
return true;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkFontConfigFreeTypeTools.h
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.
=========================================================================*/
// .NAME vtkFontConfigFreeTypeTools - Subclass of vtkFreeTypeTools that uses
// system installed fonts.
//
// .SECTION Description
// vtkFontConfigFreeTypeTools defers to vtkFreeTypeTools for rendering and
// rasterization, but sources fonts from a FontConfig system lookup. If the
// lookup fails, the compiled fonts of vtkFreeType are used instead.
//
// .SECTION Caveats
// Do not instantiate this class directly. Rather, call
// vtkFreeTypeTools::GetInstance() to ensure that the singleton design is
// correctly applied.
// Be aware that FontConfig lookup is disabled by default. To enable, call
// vtkFreeTypeTools::GetInstance()->ForceCompiledFontsOff();
#ifndef __vtkFontConfigFreeTypeTools_h
#define __vtkFontConfigFreeTypeTools_h
#include "vtkRenderingFreeTypeFontConfigModule.h" // For export macro
#include "vtkFreeTypeTools.h"
class VTKRENDERINGFREETYPEFONTCONFIG_EXPORT vtkFontConfigFreeTypeTools:
public vtkFreeTypeTools
{
public:
vtkTypeMacro(vtkFontConfigFreeTypeTools, vtkFreeTypeTools);
virtual void PrintSelf(ostream &os, vtkIndent indent);
// Description:
// Creates a new object of this type, but it is not preferred to use this
// method directly. Instead, call vtkFreeTypeTools::GetInstance() and let
// the object factory create a new instance. In this way the singleton
// pattern of vtkFreeTypeTools is preserved.
static vtkFontConfigFreeTypeTools *New();
// Description:
// Modified version of vtkFreeTypeTools::LookupFace that locates FontConfig
// faces. Falls back to the Superclass method for compiled fonts if the
// FontConfig lookup fails.
static bool LookupFaceFontConfig(vtkTextProperty *tprop, FT_Library lib,
FT_Face *face);
protected:
vtkFontConfigFreeTypeTools();
~vtkFontConfigFreeTypeTools();
// Description:
// Reimplemented from Superclass to use the FontConfig face lookup callback.
FT_Error CreateFTCManager();
private:
vtkFontConfigFreeTypeTools(const vtkFontConfigFreeTypeTools &); // Not implemented.
void operator=(const vtkFontConfigFreeTypeTools &); // Not implemented.
};
#endif //__vtkFontConfigFreeTypeTools_h
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