mirror of https://github.com/vitalif/openscad
Add implementation of text() module.
parent
9c9915a6f9
commit
bb45e7e52a
|
@ -13,3 +13,4 @@ include(eigen.pri)
|
|||
include(boost.pri)
|
||||
include(glib-2.0.pri)
|
||||
include(sparkle.pri)
|
||||
include(freetype.pri)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
freetype {
|
||||
QMAKE_CXXFLAGS += `pkg-config --cflags freetype2 harfbuzz fontconfig`
|
||||
LIBS += `pkg-config --libs freetype2 harfbuzz fontconfig`
|
||||
}
|
||||
|
|
@ -155,6 +155,7 @@ CONFIG += opencsg
|
|||
CONFIG += boost
|
||||
CONFIG += eigen
|
||||
CONFIG += glib-2.0
|
||||
CONFIG += freetype
|
||||
|
||||
#Uncomment the following line to enable QCodeEdit
|
||||
#CONFIG += qcodeedit
|
||||
|
@ -230,6 +231,7 @@ HEADERS += src/typedefs.h \
|
|||
src/transformnode.h \
|
||||
src/colornode.h \
|
||||
src/rendernode.h \
|
||||
src/textnode.h \
|
||||
src/openscad.h \
|
||||
src/handle_dep.h \
|
||||
src/Geometry.h \
|
||||
|
@ -252,6 +254,9 @@ HEADERS += src/typedefs.h \
|
|||
src/GeometryEvaluator.h \
|
||||
src/CSGTermEvaluator.h \
|
||||
src/Tree.h \
|
||||
src/DrawingCallback.h \
|
||||
src/FreetypeRenderer.h \
|
||||
src/FontCache.h \
|
||||
src/mathc99.h \
|
||||
src/memory.h \
|
||||
src/linalg.h \
|
||||
|
@ -303,6 +308,7 @@ SOURCES += src/version_check.cc \
|
|||
src/surface.cc \
|
||||
src/control.cc \
|
||||
src/render.cc \
|
||||
src/text.cc \
|
||||
src/dxfdata.cc \
|
||||
src/dxfdim.cc \
|
||||
src/linearextrude.cc \
|
||||
|
@ -321,6 +327,9 @@ SOURCES += src/version_check.cc \
|
|||
src/ModuleCache.cc \
|
||||
src/GeometryCache.cc \
|
||||
src/Tree.cc \
|
||||
src/DrawingCallback.cc \
|
||||
src/FreetypeRenderer.cc \
|
||||
src/FontCache.cc \
|
||||
\
|
||||
src/rendersettings.cc \
|
||||
src/highlighter.cc \
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <math.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "dxfdata.h"
|
||||
#include "dxftess.h"
|
||||
#include "polyset.h"
|
||||
#include "DrawingCallback.h"
|
||||
|
||||
DrawingCallback::DrawingCallback(unsigned long fn) : fn(fn),
|
||||
pen(Vector2d(0, 0)), offset(Vector2d(0, 0)), advance(Vector2d(0, 0))
|
||||
{
|
||||
}
|
||||
|
||||
DrawingCallback::~DrawingCallback()
|
||||
{
|
||||
}
|
||||
|
||||
void DrawingCallback::start_glyph()
|
||||
{
|
||||
data = new DxfData();
|
||||
}
|
||||
|
||||
void DrawingCallback::finish_glyph()
|
||||
{
|
||||
PolySet *p = new PolySet();
|
||||
p->is2d = true;
|
||||
dxf_tesselate(p, *data, 0, Vector2d(1,1), true, false, 0);
|
||||
dxf_border_to_ps(p, *data);
|
||||
result.push_back(p);
|
||||
|
||||
delete data;
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
std::vector<PolySet *> DrawingCallback::get_result()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
void DrawingCallback::set_glyph_offset(double offset_x, double offset_y)
|
||||
{
|
||||
offset = Vector2d(offset_x, offset_y);
|
||||
}
|
||||
|
||||
void DrawingCallback::add_glyph_advance(double advance_x, double advance_y)
|
||||
{
|
||||
advance += Vector2d(advance_x, advance_y);
|
||||
}
|
||||
|
||||
void DrawingCallback::add_vertex(Vector2d v)
|
||||
{
|
||||
double x = offset[0] + advance[0];
|
||||
double y = offset[1] + advance[1];
|
||||
data->paths.back().indices.push_back(data->addPoint(x + v[0], y + v[1]));
|
||||
}
|
||||
|
||||
void DrawingCallback::move_to(Vector2d to)
|
||||
{
|
||||
data->paths.push_back(DxfData::Path());
|
||||
data->paths.back().is_closed = true;
|
||||
add_vertex(to);
|
||||
pen = to;
|
||||
}
|
||||
|
||||
void DrawingCallback::line_to(Vector2d to)
|
||||
{
|
||||
add_vertex(to);
|
||||
pen = to;
|
||||
}
|
||||
|
||||
void DrawingCallback::curve_to(Vector2d c1, Vector2d to)
|
||||
{
|
||||
for (unsigned long idx = 1;idx <= fn;idx++) {
|
||||
const double a = idx * (1.0 / (double)fn);
|
||||
const double x = pen[0] * t(a, 2) + c1[0] * 2 * t(a, 1) * a + to[0] * a * a;
|
||||
const double y = pen[1] * t(a, 2) + c1[1] * 2 * t(a, 1) * a + to[1] * a * a;
|
||||
add_vertex(Vector2d(x, y));
|
||||
}
|
||||
pen = to;
|
||||
}
|
||||
|
||||
void DrawingCallback::curve_to(Vector2d c1, Vector2d c2, Vector2d to)
|
||||
{
|
||||
for (unsigned long idx = 1;idx <= fn;idx++) {
|
||||
const double a = idx * (1.0 / (double)fn);
|
||||
const double x = pen[0] * t(a, 3) + c1[0] * 3 * t(a, 2) * a + c2[0] * 3 * t(a, 1) * a * a + to[0] * a * a * a;
|
||||
const double y = pen[1] * t(a, 3) + c1[1] * 3 * t(a, 2) * a + c2[1] * 3 * t(a, 1) * a * a + to[1] * a * a * a;
|
||||
add_vertex(Vector2d(x, y));
|
||||
}
|
||||
pen = to;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef DRAWINGCALLBACK_H
|
||||
#define DRAWINGCALLBACK_H
|
||||
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include "dxfdata.h"
|
||||
#include "polyset.h"
|
||||
|
||||
class DrawingCallback {
|
||||
public:
|
||||
DrawingCallback(unsigned long fn);
|
||||
virtual ~DrawingCallback();
|
||||
|
||||
void start_glyph();
|
||||
void finish_glyph();
|
||||
void set_glyph_offset(double offset_x, double offset_y);
|
||||
void add_glyph_advance(double advance_x, double advance_y);
|
||||
std::vector<PolySet *> get_result();
|
||||
|
||||
void move_to(Vector2d to);
|
||||
void line_to(Vector2d to);
|
||||
void curve_to(Vector2d c1, Vector2d to);
|
||||
void curve_to(Vector2d c1, Vector2d c2, Vector2d to);
|
||||
private:
|
||||
unsigned long fn;
|
||||
Vector2d pen;
|
||||
Vector2d offset;
|
||||
Vector2d advance;
|
||||
|
||||
DxfData *data;
|
||||
std::vector<PolySet *> result;
|
||||
|
||||
void add_vertex(Vector2d v);
|
||||
|
||||
inline double t(double t, int exp) const {
|
||||
return pow(1.0 - t, exp);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DRAWINGCALLBACK_H */
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "boosty.h"
|
||||
#include "FontCache.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
FontCache * FontCache::self = NULL;
|
||||
|
||||
FontCache::FontCache()
|
||||
{
|
||||
init_ok = false;
|
||||
|
||||
config = FcInitLoadConfigAndFonts();
|
||||
if(!config) {
|
||||
PRINT("Can't initialize fontconfig library, text() objects will not be rendered");
|
||||
return;
|
||||
}
|
||||
|
||||
add_font_dir("/System/Library/Fonts");
|
||||
const char *home = getenv("HOME");
|
||||
if (home) {
|
||||
add_font_dir(std::string(home) + "/Library/Fonts");
|
||||
add_font_dir(std::string(home) + "/.fonts");
|
||||
}
|
||||
const char *windir = getenv("WinDir");
|
||||
if (windir) {
|
||||
add_font_dir(std::string(windir) + "\\Fonts");
|
||||
}
|
||||
|
||||
const FT_Error error = FT_Init_FreeType(&library);
|
||||
if (error) {
|
||||
PRINT("Can't initialize freetype library, text() objects will not be rendered");
|
||||
return;
|
||||
}
|
||||
|
||||
init_ok = true;
|
||||
}
|
||||
|
||||
FontCache::~FontCache()
|
||||
{
|
||||
}
|
||||
|
||||
FontCache * FontCache::instance()
|
||||
{
|
||||
if (!self) {
|
||||
self = new FontCache();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void FontCache::register_font_file(std::string path) {
|
||||
if (!FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8 *>(path.c_str()))) {
|
||||
PRINTB("Can't register font '%s'", path);
|
||||
}
|
||||
}
|
||||
|
||||
void FontCache::add_font_dir(std::string path) {
|
||||
if (!fs::is_directory(path)) {
|
||||
return;
|
||||
}
|
||||
if (!FcConfigAppFontAddDir(config, reinterpret_cast<const FcChar8 *>(path.c_str()))) {
|
||||
PRINTB("Can't register font directory '%s'", path);
|
||||
}
|
||||
}
|
||||
|
||||
bool FontCache::is_init_ok()
|
||||
{
|
||||
return init_ok;
|
||||
}
|
||||
|
||||
void FontCache::clear()
|
||||
{
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
void FontCache::dump_cache(std::string info)
|
||||
{
|
||||
std::cout << info << ":";
|
||||
for (cache_t::iterator it = cache.begin();it != cache.end();it++) {
|
||||
std::cout << " " << (*it).first << " (" << (*it).second.second << ")";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void FontCache::check_cleanup()
|
||||
{
|
||||
if (cache.size() < MAX_NR_OF_CACHE_ENTRIES) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache_t::iterator pos = cache.begin()++;
|
||||
for (cache_t::iterator it = cache.begin();it != cache.end();it++) {
|
||||
if ((*pos).second.second > (*it).second.second) {
|
||||
pos = it;
|
||||
}
|
||||
}
|
||||
FT_Done_Face((*pos).second.first);
|
||||
cache.erase(pos);
|
||||
}
|
||||
|
||||
FT_Face FontCache::get_font(std::string font)
|
||||
{
|
||||
FT_Face face;
|
||||
cache_t::iterator it = cache.find(font);
|
||||
if (it == cache.end()) {
|
||||
face = find_face(font);
|
||||
if (!face) {
|
||||
return NULL;
|
||||
}
|
||||
check_cleanup();
|
||||
} else {
|
||||
face = (*it).second.first;
|
||||
}
|
||||
cache[font] = cache_entry_t(face, time(NULL));
|
||||
return face;
|
||||
}
|
||||
|
||||
FT_Face FontCache::find_face(std::string font)
|
||||
{
|
||||
FT_Face face;
|
||||
|
||||
face = find_face_fontconfig(font);
|
||||
return face ? face : find_face_in_path_list(font);
|
||||
}
|
||||
|
||||
FT_Face FontCache::find_face_in_path_list(std::string font)
|
||||
{
|
||||
const char *env_font_path = getenv("OPENSCAD_FONT_PATH");
|
||||
|
||||
std::string paths = (env_font_path == NULL) ? "/usr/share/fonts/truetype" : env_font_path;
|
||||
typedef boost::split_iterator<std::string::iterator> string_split_iterator;
|
||||
for (string_split_iterator it = boost::make_split_iterator(paths, boost::first_finder(":", boost::is_iequal()));it != string_split_iterator();it++) {
|
||||
fs::path p(boost::copy_range<std::string>(*it));
|
||||
if (fs::exists(p)) {
|
||||
std::string path = boosty::absolute(p).string();
|
||||
FT_Face face = find_face_in_path(path, font);
|
||||
if (face) {
|
||||
return face;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FT_Face FontCache::find_face_fontconfig(std::string font)
|
||||
{
|
||||
FcResult result;
|
||||
|
||||
FcPattern *pattern = FcNameParse((unsigned char *)font.c_str());
|
||||
|
||||
FcValue true_value;
|
||||
true_value.type = FcTypeBool;
|
||||
true_value.u.b = true;
|
||||
|
||||
FcPatternAdd(pattern, FC_OUTLINE, true_value, true);
|
||||
FcPatternAdd(pattern, FC_SCALABLE, true_value, true);
|
||||
FcDefaultSubstitute(pattern);
|
||||
FcConfigSubstitute(config, pattern, FcMatchFont);
|
||||
FcPattern *match = FcFontMatch(config, pattern, &result);
|
||||
|
||||
FcValue file_value;
|
||||
FcPatternGet(match, FC_FILE, 0, &file_value);
|
||||
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Face(library, (const char *)file_value.u.s, 0, &face);
|
||||
|
||||
FcPatternDestroy(pattern);
|
||||
FcPatternDestroy(match);
|
||||
|
||||
return error ? NULL : face;
|
||||
}
|
||||
|
||||
FT_Face FontCache::find_face_in_path(std::string path, std::string font)
|
||||
{
|
||||
FT_Error error;
|
||||
|
||||
if (!fs::is_directory(path)) {
|
||||
PRINTB("Font path '%s' does not exist or is not a directory.", path);
|
||||
}
|
||||
|
||||
for (fs::recursive_directory_iterator it(path);it != fs::recursive_directory_iterator();it++) {
|
||||
fs::directory_entry entry = (*it);
|
||||
if (fs::is_regular(entry.path())) {
|
||||
FT_Face face;
|
||||
error = FT_New_Face(library, entry.path().c_str(), 0, &face);
|
||||
if (error) {
|
||||
continue;
|
||||
}
|
||||
const char *name = FT_Get_Postscript_Name(face);
|
||||
if (font == name) {
|
||||
return face;
|
||||
}
|
||||
FT_Done_Face(face);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef FONTCACHE_H
|
||||
#define FONTCACHE_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <hb.h>
|
||||
#include <hb-ft.h>
|
||||
|
||||
class FontCache {
|
||||
public:
|
||||
const static unsigned int MAX_NR_OF_CACHE_ENTRIES = 3;
|
||||
|
||||
FontCache();
|
||||
virtual ~FontCache();
|
||||
|
||||
bool is_init_ok();
|
||||
FT_Face get_font(std::string font);
|
||||
void register_font_file(std::string path);
|
||||
void clear();
|
||||
|
||||
static FontCache * instance();
|
||||
private:
|
||||
typedef std::pair<FT_Face, time_t> cache_entry_t;
|
||||
typedef std::map<std::string, cache_entry_t> cache_t;
|
||||
|
||||
static FontCache *self;
|
||||
|
||||
bool init_ok;
|
||||
cache_t cache;
|
||||
FcConfig *config;
|
||||
FT_Library library;
|
||||
|
||||
void check_cleanup();
|
||||
void dump_cache(std::string info);
|
||||
|
||||
void add_font_dir(std::string path);
|
||||
|
||||
FT_Face find_face(std::string font);
|
||||
FT_Face find_face_fontconfig(std::string font);
|
||||
FT_Face find_face_in_path_list(std::string font);
|
||||
FT_Face find_face_in_path(std::string path, std::string font);
|
||||
};
|
||||
|
||||
#endif /* FONTCACHE_H */
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include "printutils.h"
|
||||
|
||||
#include "FontCache.h"
|
||||
#include "DrawingCallback.h"
|
||||
#include "FreetypeRenderer.h"
|
||||
|
||||
#include FT_OUTLINE_H
|
||||
|
||||
static inline Vector2d get_scaled_vector(const FT_Vector *ft_vector, double scale) {
|
||||
return Vector2d(ft_vector->x / scale, ft_vector->y / scale);
|
||||
}
|
||||
|
||||
FreetypeRenderer::FreetypeRenderer()
|
||||
{
|
||||
funcs.move_to = outline_move_to_func;
|
||||
funcs.line_to = outline_line_to_func;
|
||||
funcs.conic_to = outline_conic_to_func;
|
||||
funcs.cubic_to = outline_cubic_to_func;
|
||||
funcs.delta = 0;
|
||||
funcs.shift = 0;
|
||||
}
|
||||
|
||||
FreetypeRenderer::~FreetypeRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
int FreetypeRenderer::outline_move_to_func(const FT_Vector *to, void *user)
|
||||
{
|
||||
DrawingCallback *cb = reinterpret_cast<DrawingCallback *>(user);
|
||||
|
||||
cb->move_to(get_scaled_vector(to, scale));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FreetypeRenderer::outline_line_to_func(const FT_Vector *to, void *user)
|
||||
{
|
||||
DrawingCallback *cb = reinterpret_cast<DrawingCallback *>(user);
|
||||
|
||||
cb->line_to(get_scaled_vector(to, scale));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FreetypeRenderer::outline_conic_to_func(const FT_Vector *c1, const FT_Vector *to, void *user)
|
||||
{
|
||||
DrawingCallback *cb = reinterpret_cast<DrawingCallback *>(user);
|
||||
|
||||
cb->curve_to(get_scaled_vector(c1, scale), get_scaled_vector(to, scale));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FreetypeRenderer::outline_cubic_to_func(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *to, void *user)
|
||||
{
|
||||
DrawingCallback *cb = reinterpret_cast<DrawingCallback *>(user);
|
||||
|
||||
cb->curve_to(get_scaled_vector(c1, scale), get_scaled_vector(c2, scale), get_scaled_vector(to, scale));
|
||||
return 0;
|
||||
}
|
||||
|
||||
double FreetypeRenderer::calc_x_offset(std::string halign, double width) const
|
||||
{
|
||||
if (halign == "right") {
|
||||
return -width;
|
||||
} else if (halign == "center") {
|
||||
return -width / 2.0;
|
||||
} else {
|
||||
if (halign != "left") {
|
||||
PRINTB("Unknown value for the halign parameter (use \"left\", \"right\" or \"center\"): '%s'", halign);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
double FreetypeRenderer::calc_y_offset(std::string valign, double ascend, double descend) const
|
||||
{
|
||||
if (valign == "top") {
|
||||
return -ascend;
|
||||
} else if (valign == "center") {
|
||||
return descend / 2.0 - ascend / 2.0;
|
||||
} else if (valign == "bottom") {
|
||||
return descend;
|
||||
} else {
|
||||
if (valign != "baseline") {
|
||||
PRINTB("Unknown value for the valign parameter (use \"baseline\", \"bottom\", \"top\" or \"center\"): '%s'", valign);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<PolySet *> FreetypeRenderer::render(const FreetypeRenderer::Params ¶ms) const
|
||||
{
|
||||
FT_Face face;
|
||||
FT_Error error;
|
||||
DrawingCallback callback(params.fn);
|
||||
|
||||
FontCache *cache = FontCache::instance();
|
||||
if (!cache->is_init_ok()) {
|
||||
return std::vector<PolySet *>();
|
||||
}
|
||||
|
||||
face = cache->get_font(params.font);
|
||||
if (face == NULL) {
|
||||
return std::vector<PolySet *>();
|
||||
}
|
||||
|
||||
error = FT_Set_Char_Size(face, 0, params.size * scale, 100, 100);
|
||||
if (error) {
|
||||
PRINTB("Can't set font size for font %s", params.font);
|
||||
return std::vector<PolySet *>();
|
||||
}
|
||||
|
||||
hb_font_t *hb_ft_font = hb_ft_font_create(face, NULL);
|
||||
|
||||
hb_buffer_t *hb_buf = hb_buffer_create();
|
||||
hb_buffer_set_direction(hb_buf, hb_direction_from_string(params.direction.c_str(), -1));
|
||||
hb_buffer_set_script(hb_buf, hb_script_from_string(params.script.c_str(), -1));
|
||||
hb_buffer_set_language(hb_buf, hb_language_from_string(params.language.c_str(), -1));
|
||||
hb_buffer_add_utf8(hb_buf, params.text.c_str(), strlen(params.text.c_str()), 0, strlen(params.text.c_str()));
|
||||
hb_shape(hb_ft_font, hb_buf, NULL, 0);
|
||||
|
||||
unsigned int glyph_count;
|
||||
hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(hb_buf, &glyph_count);
|
||||
hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(hb_buf, &glyph_count);
|
||||
|
||||
GlyphArray glyph_array;
|
||||
for (unsigned int idx = 0;idx < glyph_count;idx++) {
|
||||
FT_UInt glyph_index = glyph_info[idx].codepoint;
|
||||
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
PRINTB("Could not load glyph %u for char at index %u in text '%s'", glyph_index % idx % params.text);
|
||||
continue;
|
||||
}
|
||||
|
||||
FT_Glyph glyph;
|
||||
error = FT_Get_Glyph(face->glyph, &glyph);
|
||||
if (error) {
|
||||
PRINTB("Could not get glyph %u for char at index %u in text '%s'", glyph_index % idx % params.text);
|
||||
continue;
|
||||
}
|
||||
const GlyphData *glyph_data = new GlyphData(glyph, idx, &glyph_info[idx], &glyph_pos[idx]);
|
||||
glyph_array.push_back(glyph_data);
|
||||
}
|
||||
|
||||
double width = 0, ascend = 0, descend = 0;
|
||||
for (GlyphArray::iterator it = glyph_array.begin();it != glyph_array.end();it++) {
|
||||
const GlyphData *glyph = (*it);
|
||||
|
||||
FT_BBox bbox;
|
||||
FT_Glyph_Get_CBox(glyph->get_glyph(), FT_GLYPH_BBOX_GRIDFIT, &bbox);
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL(hb_buffer_get_direction(hb_buf))) {
|
||||
double asc = std::max(0.0, bbox.yMax / 64.0 / 16.0);
|
||||
double desc = std::max(0.0, -bbox.yMin / 64.0 / 16.0);
|
||||
width += glyph->get_x_advance() * params.spacing;
|
||||
ascend = std::max(ascend, asc);
|
||||
descend = std::max(descend, desc);
|
||||
} else {
|
||||
double w_bbox = (bbox.xMax - bbox.xMin) / 64.0 / 16.0;
|
||||
width = std::max(width, w_bbox);
|
||||
ascend += glyph->get_y_advance() * params.spacing;
|
||||
}
|
||||
}
|
||||
|
||||
double x_offset = calc_x_offset(params.halign, width);
|
||||
double y_offset = calc_y_offset(params.valign, ascend, descend);
|
||||
|
||||
for (GlyphArray::iterator it = glyph_array.begin();it != glyph_array.end();it++) {
|
||||
const GlyphData *glyph = (*it);
|
||||
|
||||
callback.start_glyph();
|
||||
callback.set_glyph_offset(x_offset + glyph->get_x_offset(), y_offset + glyph->get_y_offset());
|
||||
FT_Outline outline = reinterpret_cast<FT_OutlineGlyph>(glyph->get_glyph())->outline;
|
||||
FT_Outline_Decompose(&outline, &funcs, &callback);
|
||||
|
||||
double adv_x = glyph->get_x_advance() * params.spacing;
|
||||
double adv_y = glyph->get_y_advance() * params.spacing;
|
||||
callback.add_glyph_advance(adv_x, adv_y);
|
||||
callback.finish_glyph();
|
||||
}
|
||||
|
||||
hb_buffer_destroy(hb_buf);
|
||||
hb_font_destroy(hb_ft_font);
|
||||
|
||||
return callback.get_result();
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef FREETYPERENDERER_H
|
||||
#define FREETYPERENDERER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
|
||||
#include <hb.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
class FreetypeRenderer {
|
||||
public:
|
||||
class Params {
|
||||
public:
|
||||
void set_size(double size) {
|
||||
this->size = size;
|
||||
}
|
||||
void set_spacing(double spacing) {
|
||||
this->spacing = spacing;
|
||||
}
|
||||
void set_fn(double fn) {
|
||||
this->fn = fn;
|
||||
}
|
||||
void set_text(std::string text) {
|
||||
this->text = text;
|
||||
}
|
||||
void set_font(std::string font) {
|
||||
this->font = font;
|
||||
}
|
||||
void set_direction(std::string direction) {
|
||||
this->direction = direction;
|
||||
}
|
||||
void set_language(std::string language) {
|
||||
this->language = language;
|
||||
}
|
||||
void set_script(std::string script) {
|
||||
this->script = script;
|
||||
}
|
||||
void set_halign(std::string halign) {
|
||||
this->halign = halign;
|
||||
}
|
||||
void set_valign(std::string valign) {
|
||||
this->valign = valign;
|
||||
}
|
||||
friend std::ostream & operator << (std::ostream &stream, const FreetypeRenderer::Params ¶ms) {
|
||||
return stream
|
||||
<< "$fn = " << params.fn
|
||||
<< ", text = '" << params.text
|
||||
<< "', size = " << params.size
|
||||
<< ", spacing = " << params.spacing
|
||||
<< ", font = '" << params.font
|
||||
<< "', direction = '" << params.direction
|
||||
<< "', language = '" << params.language
|
||||
<< "', script = '" << params.script
|
||||
<< "', halign = '" << params.halign
|
||||
<< "', valign = '" << params.valign
|
||||
<< "'";
|
||||
}
|
||||
private:
|
||||
double size, spacing, fn;
|
||||
std::string text, font, direction, language, script, halign, valign;
|
||||
|
||||
friend FreetypeRenderer;
|
||||
};
|
||||
|
||||
FreetypeRenderer();
|
||||
virtual ~FreetypeRenderer();
|
||||
|
||||
std::vector<PolySet *> render(const FreetypeRenderer::Params ¶ms) const;
|
||||
private:
|
||||
const static double scale = 1000;
|
||||
FT_Outline_Funcs funcs;
|
||||
|
||||
class GlyphData {
|
||||
public:
|
||||
GlyphData(FT_Glyph glyph, unsigned int idx, hb_glyph_info_t *glyph_info, hb_glyph_position_t *glyph_pos) : glyph(glyph), idx(idx), glyph_pos(glyph_pos), glyph_info(glyph_info) {}
|
||||
unsigned int get_idx() const { return idx; };
|
||||
FT_Glyph get_glyph() const { return glyph; };
|
||||
double get_x_offset() const { return glyph_pos->x_offset / 64.0 / 16.0; };
|
||||
double get_y_offset() const { return glyph_pos->y_offset / 64.0 / 16.0; };
|
||||
double get_x_advance() const { return glyph_pos->x_advance / 64.0 / 16.0; };
|
||||
double get_y_advance() const { return glyph_pos->y_advance / 64.0 / 16.0; };
|
||||
private:
|
||||
FT_Glyph glyph;
|
||||
unsigned int idx;
|
||||
hb_glyph_position_t *glyph_pos;
|
||||
hb_glyph_info_t *glyph_info;
|
||||
};
|
||||
|
||||
struct done_glyph : public std::unary_function<const GlyphData *, void> {
|
||||
void operator() (const GlyphData *glyph_data) {
|
||||
FT_Done_Glyph(glyph_data->get_glyph());
|
||||
delete glyph_data;
|
||||
}
|
||||
};
|
||||
|
||||
class GlyphArray : public std::vector<const GlyphData *> {
|
||||
public:
|
||||
virtual ~GlyphArray() {
|
||||
std::for_each(begin(), end(), done_glyph());
|
||||
}
|
||||
};
|
||||
|
||||
double calc_x_offset(std::string halign, double width) const;
|
||||
double calc_y_offset(std::string valign, double ascend, double descend) const;
|
||||
|
||||
static int outline_move_to_func(const FT_Vector *to, void *user);
|
||||
static int outline_line_to_func(const FT_Vector *to, void *user);
|
||||
static int outline_conic_to_func(const FT_Vector *c1, const FT_Vector *to, void *user);
|
||||
static int outline_cubic_to_func(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *to, void *user);
|
||||
};
|
||||
|
||||
#endif /* FREETYPERENDERER_H */
|
||||
|
|
@ -37,6 +37,7 @@ extern void register_builtin_projection();
|
|||
extern void register_builtin_cgaladv();
|
||||
extern void register_builtin_dxf_linear_extrude();
|
||||
extern void register_builtin_dxf_rotate_extrude();
|
||||
extern void register_builtin_text();
|
||||
extern void initialize_builtin_dxf_dim();
|
||||
|
||||
/*!
|
||||
|
@ -62,6 +63,7 @@ void Builtins::initialize()
|
|||
register_builtin_cgaladv();
|
||||
register_builtin_dxf_linear_extrude();
|
||||
register_builtin_dxf_rotate_extrude();
|
||||
register_builtin_text();
|
||||
|
||||
this->deprecations["dxf_linear_extrude"] = "linear_extrude";
|
||||
this->deprecations["dxf_rotate_extrude"] = "rotate_extrude";
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
#endif // ENABLE_CGAL
|
||||
|
||||
#include "boosty.h"
|
||||
#include "FontCache.h"
|
||||
|
||||
// Global application state
|
||||
unsigned int GuiLocker::gui_locked = 0;
|
||||
|
@ -1699,6 +1700,7 @@ void MainWindow::actionFlushCaches()
|
|||
dxf_dim_cache.clear();
|
||||
dxf_cross_cache.clear();
|
||||
ModuleCache::instance()->clear();
|
||||
FontCache::instance()->clear();
|
||||
}
|
||||
|
||||
void MainWindow::viewModeActionsUncheck()
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <boost/filesystem.hpp>
|
||||
namespace fs = boost::filesystem;
|
||||
#include "boosty.h"
|
||||
#include "FontCache.h"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <sstream>
|
||||
#include <sys/stat.h>
|
||||
|
@ -56,6 +57,18 @@ AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstan
|
|||
return node;
|
||||
}
|
||||
|
||||
double AbstractModule::lookup_double_variable_with_default(Context &c, std::string variable, double def) const
|
||||
{
|
||||
const Value v = c.lookup_variable(variable, true);
|
||||
return (v.type() == Value::NUMBER) ? v.toDouble() : def;
|
||||
}
|
||||
|
||||
std::string AbstractModule::lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const
|
||||
{
|
||||
const Value v = c.lookup_variable(variable, true);
|
||||
return (v.type() == Value::STRING) ? v.toString() : def;
|
||||
}
|
||||
|
||||
std::string AbstractModule::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
|
@ -222,6 +235,21 @@ std::string Module::dump(const std::string &indent, const std::string &name) con
|
|||
return dump.str();
|
||||
}
|
||||
|
||||
void FileModule::registerUse(const std::string path) {
|
||||
std::string extraw = boosty::extension_str(fs::path(path));
|
||||
std::string ext = boost::algorithm::to_lower_copy(extraw);
|
||||
|
||||
if ((ext == ".otf") || (ext == ".ttf")) {
|
||||
if (fs::is_regular(path)) {
|
||||
FontCache::instance()->register_font_file(path);
|
||||
} else {
|
||||
PRINTB("ERROR: Can't read font with path '%s'", path);
|
||||
}
|
||||
} else {
|
||||
usedlibs.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
void FileModule::registerInclude(const std::string &localpath,
|
||||
const std::string &fullpath)
|
||||
{
|
||||
|
|
|
@ -70,6 +70,8 @@ public:
|
|||
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); };
|
||||
virtual class AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const class EvalContext *evalctx = NULL) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
virtual double lookup_double_variable_with_default(Context &c, std::string variable, double def) const;
|
||||
virtual std::string lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const;
|
||||
};
|
||||
|
||||
class Module : public AbstractModule
|
||||
|
@ -102,6 +104,7 @@ public:
|
|||
|
||||
void setModulePath(const std::string &path) { this->path = path; }
|
||||
const std::string &modulePath() const { return this->path; }
|
||||
void registerUse(const std::string path);
|
||||
void registerInclude(const std::string &localpath, const std::string &fullpath);
|
||||
bool includesChanged() const;
|
||||
bool handleDependencies();
|
||||
|
|
|
@ -129,7 +129,7 @@ std::string parser_source_path;
|
|||
|
||||
input: /* empty */
|
||||
| TOK_USE
|
||||
{ rootmodule->usedlibs.insert($1); }
|
||||
{ rootmodule->registerUse(std::string($1)); }
|
||||
input
|
||||
| statement input
|
||||
;
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "calc.h"
|
||||
#include "module.h"
|
||||
#include "evalcontext.h"
|
||||
#include "printutils.h"
|
||||
#include "builtin.h"
|
||||
#include "PolySetEvaluator.h"
|
||||
|
||||
#include "textnode.h"
|
||||
|
||||
#include <boost/assign/std/vector.hpp>
|
||||
using namespace boost::assign; // bring 'operator+=()' into scope
|
||||
|
||||
class TextModule : public AbstractModule
|
||||
{
|
||||
public:
|
||||
TextModule() { }
|
||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
||||
};
|
||||
|
||||
AbstractNode *TextModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
||||
{
|
||||
TextNode *node = new TextNode(inst);
|
||||
|
||||
AssignmentList args;
|
||||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
double fn = c.lookup_variable("$fn").toDouble();
|
||||
double fs = c.lookup_variable("$fs").toDouble();
|
||||
double fa = c.lookup_variable("$fa").toDouble();
|
||||
|
||||
double size = lookup_double_variable_with_default(c, "size", 10.0);
|
||||
int segments = Calc::get_fragments_from_r(size, fn, fs, fa);
|
||||
// The curved segments of most fonts are relatively short, so
|
||||
// by using a fraction of the number of full circle segments
|
||||
// the resolution will be better matching the detail level of
|
||||
// other objects.
|
||||
int text_segments = std::max(((int)floor(segments / 6)) + 2, 2);
|
||||
node->params.set_size(size);
|
||||
node->params.set_fn(text_segments);
|
||||
node->params.set_text(lookup_string_variable_with_default(c, "t", ""));
|
||||
node->params.set_spacing(lookup_double_variable_with_default(c, "spacing", 1.0));
|
||||
node->params.set_font(lookup_string_variable_with_default(c, "font", ""));
|
||||
node->params.set_direction(lookup_string_variable_with_default(c, "direction", "ltr"));
|
||||
node->params.set_language(lookup_string_variable_with_default(c, "language", "en"));
|
||||
node->params.set_script(lookup_string_variable_with_default(c, "script", "latin"));
|
||||
node->params.set_halign(lookup_string_variable_with_default(c, "halign", "left"));
|
||||
node->params.set_valign(lookup_string_variable_with_default(c, "valign", "baseline"));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
class PolySet *TextNode::evaluate_polyset(PolySetEvaluator *evaluator) const
|
||||
{
|
||||
if (!evaluator) {
|
||||
PRINTB("WARNING: No suitable PolySetEvaluator found for %s module!", this->name());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
print_messages_push();
|
||||
|
||||
PolySet *ps = evaluator->evaluatePolySet(*this);
|
||||
|
||||
print_messages_pop();
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
FreetypeRenderer::Params TextNode::get_params() const
|
||||
{
|
||||
return params;
|
||||
}
|
||||
|
||||
std::string TextNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "(" << this->params << ")";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
void register_builtin_text()
|
||||
{
|
||||
Builtins::init("text", new TextModule());
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef TEXTNODE_H_
|
||||
#define TEXTNODE_H_
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "FreetypeRenderer.h"
|
||||
|
||||
class TextModule;
|
||||
|
||||
class TextNode : public AbstractPolyNode
|
||||
{
|
||||
public:
|
||||
TextNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {}
|
||||
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "text"; }
|
||||
|
||||
virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const;
|
||||
|
||||
virtual FreetypeRenderer::Params get_params() const;
|
||||
private:
|
||||
FreetypeRenderer::Params params;
|
||||
friend TextModule;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -435,6 +435,20 @@ find_package(GLIB2 2.2.0 REQUIRED)
|
|||
add_definitions(${GLIB2_DEFINITIONS})
|
||||
inclusion(GLIB2_DIR GLIB2_INCLUDE_DIRS)
|
||||
|
||||
# find libraries using pkg-config
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_search_module(FONTCONFIG REQUIRED fontconfig>=2.11.0)
|
||||
message(STATUS "fontconfig found: ${FONTCONFIG_VERSION}")
|
||||
|
||||
pkg_search_module(FREETYPE REQUIRED freetype2>=2.4.9)
|
||||
message(STATUS "freetype2 found: ${FREETYPE_VERSION}")
|
||||
|
||||
pkg_search_module(HARFBUZZ REQUIRED harfbuzz>=0.9.19)
|
||||
message(STATUS "harfbuzz found: ${HARFBUZZ_VERSION}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FONTCONFIG_CFLAGS} ${FREETYPE_CFLAGS} ${HARFBUZZ_CFLAGS}")
|
||||
|
||||
# Imagemagick
|
||||
|
||||
if (SKIP_IMAGEMAGICK)
|
||||
|
@ -555,10 +569,14 @@ set(CORE_SOURCES
|
|||
../src/dxfdim.cc
|
||||
../src/linearextrude.cc
|
||||
../src/rotateextrude.cc
|
||||
../src/text.cc
|
||||
../src/printutils.cc
|
||||
../src/fileutils.cc
|
||||
../src/progress.cc
|
||||
../src/boost-utils.cc
|
||||
../src/FontCache.cc
|
||||
../src/DrawingCallback.cc
|
||||
../src/FreetypeRenderer.cc
|
||||
${FLEX_OpenSCADlexer_OUTPUTS}
|
||||
${BISON_OpenSCADparser_OUTPUTS})
|
||||
|
||||
|
@ -659,27 +677,51 @@ set_target_properties(tests-offscreen PROPERTIES COMPILE_FLAGS "${ENABLE_OPENCSG
|
|||
# modulecachetest
|
||||
#
|
||||
add_executable(modulecachetest modulecachetest.cc)
|
||||
target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES})
|
||||
target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES} ${Boost_LIBRARIES} ${FONTCONFIG_LDFLAGS} ${FREETYPE_LDFLAGS} ${HARFBUZZ_LDFLAGS})
|
||||
|
||||
#
|
||||
# csgtexttest
|
||||
#
|
||||
add_executable(csgtexttest csgtexttest.cc CSGTextRenderer.cc CSGTextCache.cc)
|
||||
target_link_libraries(csgtexttest tests-nocgal ${TESTS-NOCGAL-LIBRARIES})
|
||||
target_link_libraries(csgtexttest tests-nocgal ${TESTS-NOCGAL-LIBRARIES} ${FONTCONFIG_LDFLAGS} ${FREETYPE_LDFLAGS} ${HARFBUZZ_LDFLAGS})
|
||||
|
||||
#
|
||||
# cgalcachetest
|
||||
#
|
||||
add_executable(cgalcachetest cgalcachetest.cc)
|
||||
set_target_properties(cgalcachetest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
|
||||
target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${CLIPPER_LIBRARY} ${GLEW_LIBRARY} ${COCOA_LIBRARY})
|
||||
target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${COCOA_LIBRARY} ${FONTCONFIG_LDFLAGS} ${FREETYPE_LDFLAGS} ${HARFBUZZ_LDFLAGS})
|
||||
|
||||
#
|
||||
# openscad no-qt
|
||||
#
|
||||
add_executable(openscad_nogui ../src/openscad.cc)
|
||||
set_target_properties(openscad_nogui PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN -DENABLE_CGAL ${ENABLE_OPENCSG_FLAG} ${CGAL_CXX_FLAGS_INIT}")
|
||||
target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${Boost_LIBRARIES} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} ${APP_SERVICES_LIBRARY})
|
||||
set_target_properties(openscad_nogui PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN -DENABLE_CGAL -DENABLE_OPENCSG ${CGAL_CXX_FLAGS_INIT}")
|
||||
target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${Boost_LIBRARIES} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} ${APP_SERVICES_LIBRARY} ${FONTCONFIG_LDFLAGS} ${FREETYPE_LDFLAGS} ${HARFBUZZ_LDFLAGS})
|
||||
|
||||
#
|
||||
# GUI binary tests
|
||||
#
|
||||
#if(APPLE)
|
||||
# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../OpenSCAD.app/Contents/MacOS/OpenSCAD")
|
||||
#elseif (MINGW_CROSS_ENV_DIR)
|
||||
# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../mingw32/release/openscad.exe")
|
||||
#elseif(WIN32)
|
||||
# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../Release/openscad.exe")
|
||||
#else()
|
||||
# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../openscad")
|
||||
#endif()
|
||||
|
||||
#if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/openscad")
|
||||
# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_BINARY_DIR}/openscad")
|
||||
#endif()
|
||||
|
||||
#if(EXISTS "${OPENSCAD_BINPATH}")
|
||||
# message(STATUS "Found OpenSCAD binary: ${OPENSCAD_BINPATH}")
|
||||
#else()
|
||||
# message(STATUS "Couldn't find the OpenSCAD binary: ${OPENSCAD_BINPATH}")
|
||||
# message(FATAL_ERROR "Please build the OpenSCAD binary and place it here: ${OPENSCAD_BINPATH}" )
|
||||
#endif()
|
||||
|
||||
if(WIN32)
|
||||
set(OPENSCAD_BINPATH "${CMAKE_CURRENT_BINARY_DIR}/openscad_nogui.exe")
|
||||
|
|
Loading…
Reference in New Issue