Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::Emboss Namespace Reference

class with only static function add ability to engraved OR raised text OR polygons onto model surface More...

Classes

struct  FontFile
 keep information from file about font (store file data itself) More...
 
struct  FontFileWithCache
 Add caching for shape of glyphs. More...
 
struct  Glyph
 
class  IProject3d
 Project spatial point. More...
 
class  IProjection
 Project 2d point into space Could be plane, sphere, cylindric, ... More...
 
class  OrthoProject
 
class  OrthoProject3d
 
class  ProjectScale
 
class  ProjectZ
 

Typedefs

using Glyphs = std::map< int, Glyph >
 

Functions

EmbossStyles get_font_list ()
 Collect fonts registred inside OS.
 
std::optional< std::wstring > get_font_path (const std::wstring &font_face_name)
 OS dependent function to get location of font by its name descriptor.
 
std::unique_ptr< FontFilecreate_font_file (const char *file_path)
 Load font file into buffer.
 
std::unique_ptr< FontFilecreate_font_file (std::unique_ptr< std::vector< unsigned char > > data)
 
std::optional< Glyphletter2glyph (const FontFile &font, unsigned int font_index, int letter, float flatness)
 convert letter into polygons
 
ExPolygons text2shapes (FontFileWithCache &font, const char *text, const FontProp &font_prop, std::function< bool()> was_canceled=nullptr)
 Convert text into polygons.
 
ExPolygons heal_shape (const Polygons &shape)
 Fix duplicit points and self intersections in polygons. Also try to reduce amount of points and remove useless polygon parts.
 
bool heal_shape (ExPolygons &shape, unsigned max_iteration=10)
 NOTE: call Slic3r::union_ex before this call.
 
bool divide_segments_for_close_point (ExPolygons &expolygons, double distance)
 Divide line segments in place near to point (which could lead to self intersection due to preccision) Remove same neighbors Note: Possible part of heal shape.
 
void apply_transformation (const FontProp &font_prop, Transform3d &transformation)
 Use data from font property to modify transformation.
 
void apply_transformation (const std::optional< float > &angle, const std::optional< float > &distance, Transform3d &transformation)
 
bool is_italic (const FontFile &font, unsigned int font_index)
 Read information from naming table of font file search for italic (or oblique), bold italic (or bold oblique)
 
std::string create_range_text (const std::string &text, const FontFile &font, unsigned int font_index, bool *exist_unknown=nullptr)
 Create unique character set from string with filtered from text with only character from font.
 
double get_shape_scale (const FontProp &fp, const FontFile &ff)
 Calculate scale for glyph shape convert from shape points to mm.
 
indexed_triangle_set polygons2model (const ExPolygons &shape2d, const IProjection &projection)
 Create triangle model for text.
 
Vec3d suggest_up (const Vec3d normal, double up_limit=0.9)
 Suggest wanted up vector of embossed text by emboss direction.
 
std::optional< float > calc_up (const Transform3d &tr, double up_limit=0.9)
 By transformation calculate angle between suggested and actual up vector.
 
Transform3d create_transformation_onto_surface (const Vec3d &position, const Vec3d &normal, double up_limit=0.9)
 Create transformation for emboss text object to lay on surface point.
 

Variables

static constexpr double SHAPE_SCALE = 0.001
 

Detailed Description

class with only static function add ability to engraved OR raised text OR polygons onto model surface


Class Documentation

◆ Slic3r::Emboss::Glyph

struct Slic3r::Emboss::Glyph
+ Collaboration diagram for Slic3r::Emboss::Glyph:
Class Members
int advance_width =0
int left_side_bearing =0
ExPolygons shape

Typedef Documentation

◆ Glyphs

using Slic3r::Emboss::Glyphs = typedef std::map<int, Glyph>

Function Documentation

◆ apply_transformation() [1/2]

void Slic3r::Emboss::apply_transformation ( const FontProp font_prop,
Transform3d transformation 
)

Use data from font property to modify transformation.

Parameters
font_propZ-move as surface distance(FontProp::distance) Z-rotation as angle to Y axis(FontProp::angle)
transformationIn / Out transformation to modify by property
1268 {
1269 apply_transformation(font_prop.angle, font_prop.distance, transformation);
1270}
void apply_transformation(const FontProp &font_prop, Transform3d &transformation)
Use data from font property to modify transformation.
Definition Emboss.cpp:1268
std::optional< float > distance
Definition TextConfiguration.hpp:51
std::optional< float > angle
Definition TextConfiguration.hpp:57

References Slic3r::FontProp::angle, apply_transformation(), and Slic3r::FontProp::distance.

Referenced by apply_transformation(), Slic3r::GUI::on_mouse_surface_drag(), and priv::start_create_volume_on_surface_job().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_transformation() [2/2]

void Slic3r::Emboss::apply_transformation ( const std::optional< float > &  angle,
const std::optional< float > &  distance,
Transform3d transformation 
)
1272 {
1273 if (angle.has_value()) {
1274 double angle_z = *angle;
1275 transformation *= Eigen::AngleAxisd(angle_z, Vec3d::UnitZ());
1276 }
1277 if (distance.has_value()) {
1278 Vec3d translate = Vec3d::UnitZ() * (*distance);
1279 transformation.translate(translate);
1280 }
1281}
EIGEN_DEVICE_FUNC Transform & translate(const MatrixBase< OtherDerived > &other)
AngleAxis< double > AngleAxisd
Definition AngleAxis.h:160
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:112

References Slic3r::angle(), and Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::translate().

+ Here is the call graph for this function:

◆ calc_up()

std::optional< float > Slic3r::Emboss::calc_up ( const Transform3d tr,
double  up_limit = 0.9 
)

By transformation calculate angle between suggested and actual up vector.

Parameters
trTransformation of embossed volume in world
up_limitIs compared with normal.z to suggest up direction
Returns
Rotation of suggested up-vector[in rad] in the range [-Pi, Pi], When rotation is not zero
1566{
1567 auto tr_linear = tr.linear();
1568 // z base of transformation ( tr * UnitZ )
1569 Vec3d normal = tr_linear.col(2);
1570 // scaled matrix has base with different size
1571 normal.normalize();
1572 Vec3d suggested = suggest_up(normal);
1573 assert(is_approx(suggested.squaredNorm(), 1.));
1574
1575 Vec3d up = tr_linear.col(1); // tr * UnitY()
1576 up.normalize();
1577
1578 double dot = suggested.dot(up);
1579 if (dot >= 1. || dot <= -1.)
1580 return {}; // zero angle
1581
1582 Matrix3d m;
1583 m.row(0) = up;
1584 m.row(1) = suggested;
1585 m.row(2) = normal;
1586 double det = m.determinant();
1587
1588 return -atan2(det, dot);
1589}
EIGEN_DEVICE_FUNC ConstLinearPart linear() const
Definition Transform.h:400
Vec3d suggest_up(const Vec3d normal, double up_limit=0.9)
Suggest wanted up vector of embossed text by emboss direction.
Definition Emboss.cpp:1546
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:271
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:143

References Slic3r::dot(), Slic3r::is_approx(), Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::linear(), and suggest_up().

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_advanced(), Slic3r::GUI::GLGizmoEmboss::on_mouse_for_translate(), Slic3r::GUI::on_mouse_surface_drag(), Slic3r::GUI::GLGizmoEmboss::on_stop_dragging(), and Slic3r::GUI::GLGizmoEmboss::set_volume_by_selection().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_font_file() [1/2]

std::unique_ptr< FontFile > Slic3r::Emboss::create_font_file ( const char *  file_path)

Load font file into buffer.

Parameters
file_pathLocation of .ttf or .ttc font file
Returns
Font object when loaded.
1102{
1103 FILE *file = std::fopen(file_path, "rb");
1104 if (file == nullptr) {
1105 assert(false);
1106 BOOST_LOG_TRIVIAL(error) << "Couldn't open " << file_path << " for reading.";
1107 return nullptr;
1108 }
1109 ScopeGuard sg([&file]() { std::fclose(file); });
1110
1111 // find size of file
1112 if (fseek(file, 0L, SEEK_END) != 0) {
1113 assert(false);
1114 BOOST_LOG_TRIVIAL(error) << "Couldn't fseek file " << file_path << " for size measure.";
1115 return nullptr;
1116 }
1117 size_t size = ftell(file);
1118 if (size == 0) {
1119 assert(false);
1120 BOOST_LOG_TRIVIAL(error) << "Size of font file is zero. Can't read.";
1121 return nullptr;
1122 }
1123 rewind(file);
1124 auto buffer = std::make_unique<std::vector<unsigned char>>(size);
1125 size_t count_loaded_bytes = fread((void *) &buffer->front(), 1, size, file);
1126 if (count_loaded_bytes != size) {
1127 assert(false);
1128 BOOST_LOG_TRIVIAL(error) << "Different loaded(from file) data size.";
1129 return nullptr;
1130 }
1131 return create_font_file(std::move(buffer));
1132}
Definition Utils.hpp:282
std::unique_ptr< FontFile > create_font_file(const char *file_path)
Load font file into buffer.
Definition Emboss.cpp:1101
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183
#define L(s)
Definition I18N.hpp:18
static char error[256]
Definition tga.cpp:50

References create_font_file(), error, and L.

Referenced by create_font_file(), Slic3r::GUI::WxFontUtils::create_font_file(), and Slic3r::GUI::Emboss::StyleManager::load_style().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_font_file() [2/2]

std::unique_ptr< FontFile > Slic3r::Emboss::create_font_file ( std::unique_ptr< std::vector< unsigned char > >  data)
1071{
1072 int collection_size = stbtt_GetNumberOfFonts(data->data());
1073 // at least one font must be inside collection
1074 if (collection_size < 1) {
1075 assert(false);
1076 // There is no font collection inside font data
1077 return nullptr;
1078 }
1079
1080 unsigned int c_size = static_cast<unsigned int>(collection_size);
1081 std::vector<FontFile::Info> infos;
1082 infos.reserve(c_size);
1083 for (unsigned int i = 0; i < c_size; ++i) {
1084 auto font_info = priv::load_font_info(data->data(), i);
1085 if (!font_info.has_value()) return nullptr;
1086
1087 const stbtt_fontinfo *info = &(*font_info);
1088 // load information about line gap
1089 int ascent, descent, linegap;
1090 stbtt_GetFontVMetrics(info, &ascent, &descent, &linegap);
1091
1092 float pixels = 1000.; // value is irelevant
1093 float em_pixels = stbtt_ScaleForMappingEmToPixels(info, pixels);
1094 int units_per_em = static_cast<int>(std::round(pixels / em_pixels));
1095
1096 infos.emplace_back(FontFile::Info{ascent, descent, linegap, units_per_em});
1097 }
1098 return std::make_unique<FontFile>(std::move(data), std::move(infos));
1099}
STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
Definition imstb_truetype.h:715
fontinfo_opt load_font_info(const unsigned char *data, unsigned int index=0)
Definition Emboss.cpp:240
Definition Emboss.hpp:70

References priv::load_font_info(), stbtt_GetFontVMetrics(), stbtt_GetNumberOfFonts(), and stbtt_ScaleForMappingEmToPixels().

+ Here is the call graph for this function:

◆ create_range_text()

std::string Slic3r::Emboss::create_range_text ( const std::string &  text,
const FontFile font,
unsigned int  font_index,
bool *  exist_unknown = nullptr 
)

Create unique character set from string with filtered from text with only character from font.

Parameters
textSource vector of glyphs
fontFont descriptor
font_indexDefine font in collection
exist_unknownTrue when text contain glyph unknown in font
Returns
Unique set of character from text contained in font
1325{
1326 if (!priv::is_valid(font, font_index)) return {};
1327
1328 std::wstring ws = boost::nowide::widen(text);
1329
1330 // need remove symbols not contained in font
1331 std::sort(ws.begin(), ws.end());
1332
1333 auto font_info_opt = priv::load_font_info(font.data->data(), 0);
1334 if (!font_info_opt.has_value()) return {};
1335 const stbtt_fontinfo *font_info = &(*font_info_opt);
1336
1337 if (exist_unknown != nullptr) *exist_unknown = false;
1338 int prev_unicode = -1;
1339 ws.erase(std::remove_if(ws.begin(), ws.end(),
1340 [&prev_unicode, font_info, exist_unknown](wchar_t wc) -> bool {
1341 int unicode = static_cast<int>(wc);
1342
1343 // skip white spaces
1344 if (unicode == '\n' ||
1345 unicode == '\r' ||
1346 unicode == '\t') return true;
1347
1348 // is duplicit?
1349 if (prev_unicode == unicode) return true;
1350 prev_unicode = unicode;
1351
1352 // can find in font?
1353 bool is_unknown = !stbtt_FindGlyphIndex(font_info, unicode);
1354 if (is_unknown && exist_unknown != nullptr)
1355 *exist_unknown = true;
1356 return is_unknown;
1357 }), ws.end());
1358
1359 return boost::nowide::narrow(ws);
1360}
char * narrow(char *output, size_t output_size, wchar_t const *source)
Convert NULL terminated UTF source string to NULL terminated output string of size at most output_siz...
Definition convert.hpp:73
wchar_t * widen(wchar_t *output, size_t output_size, char const *source)
Convert NULL terminated UTF source string to NULL terminated output string of size at most output_siz...
Definition convert.hpp:95
bool is_valid(const FontFile &font, unsigned int index)
Definition Emboss.cpp:233
std::unique_ptr< std::vector< unsigned char > > data
Definition Emboss.hpp:67

References Slic3r::Emboss::FontFile::data, priv::is_valid(), priv::load_font_info(), boost::nowide::narrow(), and boost::nowide::widen().

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_text_input().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_transformation_onto_surface()

Transform3d Slic3r::Emboss::create_transformation_onto_surface ( const Vec3d position,
const Vec3d normal,
double  up_limit = 0.9 
)

Create transformation for emboss text object to lay on surface point.

Parameters
positionPosition of surface point
normalNormal of surface point
up_limitIs compared with normal.z to suggest up direction
Returns
Transformation onto surface point
1594{
1595 // is normalized ?
1596 assert(is_approx(normal.squaredNorm(), 1.));
1597
1598 // up and emboss direction for generated model
1599 Vec3d up_dir = Vec3d::UnitY();
1600 Vec3d emboss_dir = Vec3d::UnitZ();
1601
1602 // after cast from float it needs to be normalized again
1603 Vec3d wanted_up_dir = suggest_up(normal, up_limit);
1604
1605 // perpendicular to emboss vector of text and normal
1606 Vec3d axis_view;
1607 double angle_view;
1608 if (normal == -Vec3d::UnitZ()) {
1609 // text_emboss_dir has opposit direction to wanted_emboss_dir
1610 axis_view = Vec3d::UnitY();
1611 angle_view = M_PI;
1612 } else {
1613 axis_view = emboss_dir.cross(normal);
1614 angle_view = std::acos(emboss_dir.dot(normal)); // in rad
1615 axis_view.normalize();
1616 }
1617
1618 Eigen::AngleAxis view_rot(angle_view, axis_view);
1619 Vec3d wanterd_up_rotated = view_rot.matrix().inverse() * wanted_up_dir;
1620 wanterd_up_rotated.normalize();
1621 double angle_up = std::acos(up_dir.dot(wanterd_up_rotated));
1622
1623 Vec3d text_view = up_dir.cross(wanterd_up_rotated);
1624 Vec3d diff_view = emboss_dir - text_view;
1625 if (std::fabs(diff_view.x()) > 1. ||
1626 std::fabs(diff_view.y()) > 1. ||
1627 std::fabs(diff_view.z()) > 1.) // oposit direction
1628 angle_up *= -1.;
1629
1630 Eigen::AngleAxis up_rot(angle_up, emboss_dir);
1631
1633 transform.translate(position);
1634 transform.rotate(view_rot);
1635 transform.rotate(up_rot);
1636 return transform;
1637}
#define M_PI
Definition ExtrusionSimulator.cpp:20
static EIGEN_DEVICE_FUNC const Transform Identity()
Returns an identity transformation.
Definition Transform.h:539
Represents a 3D rotation as a rotation angle around an arbitrary 3D axis.
Definition AngleAxis.h:50
Linef3 transform(const Linef3 &line, const Transform3d &t)
Definition Line.cpp:10

References Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign >::Identity(), Slic3r::is_approx(), M_PI, Eigen::RotationBase< Derived, _Dim >::matrix(), suggest_up(), and Slic3r::transform().

Referenced by priv::start_create_volume_on_surface_job().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ divide_segments_for_close_point()

bool Slic3r::Emboss::divide_segments_for_close_point ( ExPolygons expolygons,
double  distance 
)

Divide line segments in place near to point (which could lead to self intersection due to preccision) Remove same neighbors Note: Possible part of heal shape.

Parameters
expolygonsExpolygon to edit
distance(epsilon)Euclidean distance from point to line which divide line
Returns
True when some division was made otherwise false
374{
375 if (expolygons.empty()) return false;
376 if (distance < 0.) return false;
377
378 // ExPolygons can't contain same neigbours
379 priv::remove_same_neighbor(expolygons);
380
381 // IMPROVE: use int(insted of double) lines and tree
382 const ExPolygonsIndices ids(expolygons);
383 const std::vector<Linef> lines = Slic3r::to_linesf(expolygons, ids.get_count());
385 using Div = std::pair<Point, size_t>;
386 std::vector<Div> divs;
387 size_t point_index = 0;
388 auto check_points = [&divs, &point_index, &lines, &tree, &distance, &ids, &expolygons](const Points &pts) {
389 for (const Point &p : pts) {
390 Vec2d p_d = p.cast<double>();
391 std::vector<size_t> close_lines = AABBTreeLines::all_lines_in_radius(lines, tree, p_d, distance);
392 for (size_t index : close_lines) {
393 // skip point neighbour lines indices
394 if (index == point_index) continue;
395 if (&p != &pts.front()) {
396 if (index == point_index - 1) continue;
397 } else if (index == (pts.size()-1)) continue;
398
399 // do not doubled side point of segment
400 const ExPolygonsIndex id = ids.cvt(index);
401 const ExPolygon &expoly = expolygons[id.expolygons_index];
402 const Polygon &poly = id.is_contour() ? expoly.contour : expoly.holes[id.hole_index()];
403 const Points &poly_pts = poly.points;
404 const Point &line_a = poly_pts[id.point_index];
405 const Point &line_b = (!ids.is_last_point(id)) ? poly_pts[id.point_index + 1] : poly_pts.front();
406 assert(line_a == lines[index].a.cast<int>());
407 assert(line_b == lines[index].b.cast<int>());
408 if (p == line_a || p == line_b) continue;
409
410 divs.emplace_back(p, index);
411 }
412 ++point_index;
413 }
414 };
415 for (const ExPolygon &expoly : expolygons) {
416 check_points(expoly.contour.points);
417 for (const Polygon &hole : expoly.holes)
418 check_points(hole.points);
419 }
420
421 // check if exist division
422 if (divs.empty()) return false;
423
424 // sort from biggest index to zero
425 // to be able add points and not interupt indices
426 std::sort(divs.begin(), divs.end(),
427 [](const Div &d1, const Div &d2) { return d1.second > d2.second; });
428
429 auto it = divs.begin();
430 // divide close line
431 while (it != divs.end()) {
432 // colect division of a line segmen
433 size_t index = it->second;
434 auto it2 = it+1;
435 while (it2 != divs.end() && it2->second == index) ++it2;
436
437 ExPolygonsIndex id = ids.cvt(index);
438 ExPolygon &expoly = expolygons[id.expolygons_index];
439 Polygon &poly = id.is_contour() ? expoly.contour : expoly.holes[id.hole_index()];
440 Points &pts = poly.points;
441 size_t count = it2 - it;
442
443 // add points into polygon to divide in place of near point
444 if (count == 1) {
445 pts.insert(pts.begin() + id.point_index + 1, it->first);
446 ++it;
447 } else {
448 // collect points to add into polygon
449 Points points;
450 points.reserve(count);
451 for (; it < it2; ++it)
452 points.push_back(it->first);
453
454 // need sort by line direction
455 const Linef &line = lines[index];
456 Vec2d dir = line.b - line.a;
457 // select mayorit direction
458 int axis = (abs(dir.x()) > abs(dir.y())) ? 0 : 1;
459 using Fnc = std::function<bool(const Point &, const Point &)>;
460 Fnc fnc = (dir[axis] < 0) ? Fnc([axis](const Point &p1, const Point &p2) { return p1[axis] > p2[axis]; }) :
461 Fnc([axis](const Point &p1, const Point &p2) { return p1[axis] < p2[axis]; }) ;
462 std::sort(points.begin(), points.end(), fnc);
463
464 // use only unique points
465 points.erase(std::unique(points.begin(), points.end()), points.end());
466
467 // divide line by adding points into polygon
468 pts.insert(pts.begin() + id.point_index + 1,
469 points.begin(), points.end());
470 }
471 assert(it == it2);
472 }
473 return true;
474}
Definition AABBTreeIndirect.hpp:40
Definition ExPolygon.hpp:16
Polygon contour
Definition ExPolygon.hpp:35
Polygons holes
Definition ExPolygon.hpp:36
Keep conversion from ExPolygonsIndex to Index and vice versa ExPolygonsIndex .. contour(or hole) poin...
Definition ExPolygonsIndex.hpp:38
Definition Line.hpp:243
Vec2d b
Definition Line.hpp:249
Vec2d a
Definition Line.hpp:248
Points points
Definition MultiPoint.hpp:18
Definition Point.hpp:158
Definition Polygon.hpp:24
#define const
Definition getopt.c:38
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half &a)
Definition Half.h:445
std::vector< size_t > all_lines_in_radius(const std::vector< LineType > &lines, const TreeType &tree, const VectorType &point, typename VectorType::Scalar max_distance_squared)
Definition AABBTreeLines.hpp:224
AABBTreeIndirect::Tree< LineType::Dim, typename LineType::Scalar > build_aabb_tree_over_indexed_lines(const std::vector< LineType > &lines)
Definition AABBTreeLines.hpp:168
Linesf to_linesf(const ExPolygons &src, uint32_t count_lines=0)
Definition ExPolygon.hpp:147
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:58
const Polygons & holes(const ExPolygon &p)
Definition AGGRaster.hpp:22
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12
Slic3r::Polygon & hole(Slic3r::ExPolygon &sh, unsigned long idx)
Definition geometries.hpp:200
bool remove_same_neighbor(Polygon &points)
Definition Emboss.cpp:275
Index into ExPolygons Identify expolygon, its contour (or hole) and point.
Definition ExPolygonsIndex.hpp:12

References Slic3r::Linef::a, Slic3r::AABBTreeLines::all_lines_in_radius(), Slic3r::Linef::b, Slic3r::AABBTreeLines::build_aabb_tree_over_indexed_lines(), Slic3r::ExPolygon::contour, Slic3r::ExPolygonsIndices::cvt(), Slic3r::ExPolygonsIndices::get_count(), Slic3r::ExPolygon::holes, Slic3r::ExPolygonsIndices::is_last_point(), Slic3r::MultiPoint::points, priv::remove_same_neighbor(), and Slic3r::to_linesf().

+ Here is the call graph for this function:

◆ get_font_list()

EmbossStyles Slic3r::Emboss::get_font_list ( )

Collect fonts registred inside OS.

Returns
OS registred TTF font files(full path) with names
1058 {
1059 // not implemented
1060 return {};
1061}

◆ get_font_path()

std::optional< std::wstring > Slic3r::Emboss::get_font_path ( const std::wstring &  font_face_name)

OS dependent function to get location of font by its name descriptor.

Parameters
font_face_nameUnique identificator for font
Returns
File path to font when found
1063 {
1064 // not implemented
1065 return {};
1066}

◆ get_shape_scale()

double Slic3r::Emboss::get_shape_scale ( const FontProp fp,
const FontFile ff 
)

Calculate scale for glyph shape convert from shape points to mm.

Parameters
fpProperty of font
ffFont data
Returns
Conversion to mm
1363{
1364 size_t font_index = fp.collection_number.value_or(0);
1365 const FontFile::Info &info = ff.infos[font_index];
1366 double scale = fp.size_in_mm / (double) info.unit_per_em;
1367 // Shape is scaled for store point coordinate as integer
1368 return scale * SHAPE_SCALE;
1369}
int scale(const int val)
Definition WipeTowerDialog.cpp:14
static constexpr double SHAPE_SCALE
Definition Emboss.hpp:23
std::vector< Info > infos
Definition Emboss.hpp:78
int unit_per_em
Definition Emboss.hpp:75
std::optional< unsigned int > collection_number
Definition TextConfiguration.hpp:61
float size_in_mm
Definition TextConfiguration.hpp:85

References Slic3r::FontProp::collection_number, Slic3r::Emboss::FontFile::infos, scale(), SHAPE_SCALE, Slic3r::FontProp::size_in_mm, and Slic3r::Emboss::FontFile::Info::unit_per_em.

Referenced by priv::cut_surface().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ heal_shape() [1/2]

ExPolygons Slic3r::Emboss::heal_shape ( const Polygons shape)

Fix duplicit points and self intersections in polygons. Also try to reduce amount of points and remove useless polygon parts.

Parameters
precisionDefine wanted precision of shape after heal
Returns
Healed shapes
533{
534 // When edit this code check that font 'ALIENATE.TTF' and glyph 'i' still work
535 // fix of self intersections
536 // http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Functions/SimplifyPolygon.htm
538 const double clean_distance = 1.415; // little grater than sqrt(2)
539 ClipperLib::CleanPolygons(paths, clean_distance);
540 Polygons polygons = to_polygons(paths);
541 polygons.erase(std::remove_if(polygons.begin(), polygons.end(), [](const Polygon &p) { return p.size() < 3; }), polygons.end());
542
543 // Do not remove all duplicates but do it better way
544 // Overlap all duplicit points by rectangle 3x3
545 Points duplicits = collect_duplicates(to_points(polygons));
546 if (!duplicits.empty()) {
547 polygons.reserve(polygons.size() + duplicits.size());
548 for (const Point &p : duplicits) {
549 Polygon rect_3x3(priv::pts_3x3);
550 rect_3x3.translate(p);
551 polygons.push_back(rect_3x3);
552 }
553 }
554
555 // TrueTypeFonts use non zero winding number
556 // https://docs.microsoft.com/en-us/typography/opentype/spec/ttch01
557 // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
559 heal_shape(res);
560 return res;
561}
Definition ClipperUtils.hpp:137
void CleanPolygons(const Paths &in_polys, Paths &out_polys, double distance)
Definition clipper.cpp:3972
@ pftNonZero
Definition clipper.hpp:81
Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType=pftNonZero, bool strictly_simple=true)
Definition clipper.hpp:592
std::vector< Path, Allocator< Path > > Paths
Definition clipper.hpp:122
ExPolygons heal_shape(const Polygons &shape)
Fix duplicit points and self intersections in polygons. Also try to reduce amount of points and remov...
Definition Emboss.cpp:532
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:15
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, ClipperLib::PolyFillType fill_type)
Definition ClipperUtils.cpp:774
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:13
Points collect_duplicates(Points pts)
Definition Point.cpp:69
Polygons to_polygons(const ExPolygon &src)
Definition ExPolygon.hpp:281
Points to_points(const ExPolygons &src)
Definition ExPolygon.hpp:196
const Points pts_3x3({Point(-1, -1), Point(1, -1), Point(1, 1), Point(-1, 1)})

References ClipperLib::CleanPolygons(), Slic3r::collect_duplicates(), heal_shape(), ClipperLib::pftNonZero, priv::pts_3x3(), ClipperLib::SimplifyPolygons(), Slic3r::to_points(), Slic3r::to_polygons(), Slic3r::MultiPoint::translate(), and Slic3r::union_ex().

Referenced by priv::get_glyph(), heal_shape(), and text2shapes().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ heal_shape() [2/2]

bool Slic3r::Emboss::heal_shape ( ExPolygons shape,
unsigned  max_iteration = 10 
)

NOTE: call Slic3r::union_ex before this call.

Heal (read: Fix) issues in expolygons:

  • self intersections
  • duplicit points
  • points close to line segments
Parameters
shapeIn/Out shape to heal
max_iterationHeal could create another issue, After healing it is checked again until shape is good or maximal count of iteration
Returns
True when shapes is good otherwise False
584{
585 return priv::heal_dupl_inter(shape, max_iteration);
586}
bool heal_dupl_inter(ExPolygons &shape, unsigned max_iteration)
Definition Emboss.cpp:589

References priv::heal_dupl_inter().

+ Here is the call graph for this function:

◆ is_italic()

bool Slic3r::Emboss::is_italic ( const FontFile font,
unsigned int  font_index 
)

Read information from naming table of font file search for italic (or oblique), bold italic (or bold oblique)

Parameters
fontSelector of font
font_indexIndex of font in collection
Returns
True when the font description contains italic/obligue otherwise False
1284{
1285 if (font_index >= font.infos.size()) return false;
1286 fontinfo_opt font_info_opt = priv::load_font_info(font.data->data(), font_index);
1287
1288 if (!font_info_opt.has_value()) return false;
1289 stbtt_fontinfo *info = &(*font_info_opt);
1290
1291 // https://docs.microsoft.com/cs-cz/typography/opentype/spec/name
1292 // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html
1293 // 2 ==> Style / Subfamily name
1294 int name_id = 2;
1295 int length;
1296 const char* value = stbtt_GetFontNameString(info, &length,
1300 name_id);
1301
1302 // value is big endian utf-16 i need extract only normal chars
1303 std::string value_str;
1304 value_str.reserve(length / 2);
1305 for (int i = 1; i < length; i += 2)
1306 value_str.push_back(value[i]);
1307
1308 // lower case
1309 std::transform(value_str.begin(), value_str.end(), value_str.begin(),
1310 [](unsigned char c) { return std::tolower(c); });
1311
1312 const std::vector<std::string> italics({"italic", "oblique"});
1313 for (const std::string &it : italics) {
1314 if (value_str.find(it) != std::string::npos) {
1315 return true;
1316 }
1317 }
1318 return false;
1319}
std::optional< stbtt_fontinfo > fontinfo_opt
Definition Emboss.cpp:24
@ STBTT_MS_LANG_ENGLISH
Definition imstb_truetype.h:1058
STBTT_DEF const char * stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
@ STBTT_MS_EID_UNICODE_BMP
Definition imstb_truetype.h:1044
@ STBTT_PLATFORM_ID_MICROSOFT
Definition imstb_truetype.h:1031
double length(const Points &pts)
Definition MultiPoint.hpp:116

References Slic3r::Emboss::FontFile::data, Slic3r::Emboss::FontFile::infos, Slic3r::length(), priv::load_font_info(), stbtt_GetFontNameString(), STBTT_MS_EID_UNICODE_BMP, STBTT_MS_LANG_ENGLISH, and STBTT_PLATFORM_ID_MICROSOFT.

Referenced by Slic3r::GUI::Emboss::StyleManager::is_font_changed().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ letter2glyph()

std::optional< Glyph > Slic3r::Emboss::letter2glyph ( const FontFile font,
unsigned int  font_index,
int  letter,
float  flatness 
)

convert letter into polygons

Parameters
fontDefine fonts
font_indexIndex of font in collection
letterOne character defined by unicode codepoint
flatnessPrecision of lettter outline curve in conversion to lines
Returns
inner polygon cw(outer ccw)
1203{
1204 if (!priv::is_valid(font, font_index)) return {};
1205 auto font_info_opt = priv::load_font_info(font.data->data(), font_index);
1206 if (!font_info_opt.has_value()) return {};
1207 return priv::get_glyph(*font_info_opt, letter, flatness);
1208}
std::optional< Glyph > get_glyph(const stbtt_fontinfo &font_info, int unicode_letter, float flatness)
Definition Emboss.cpp:724

References Slic3r::Emboss::FontFile::data, priv::get_glyph(), priv::is_valid(), and priv::load_font_info().

+ Here is the call graph for this function:

◆ polygons2model()

indexed_triangle_set Slic3r::Emboss::polygons2model ( const ExPolygons shape2d,
const IProjection projection 
)

Create triangle model for text.

Parameters
shape2dtext or image
projectionDefine transformation from 2d to 3d(orientation, position, scale, ...)
Returns
Projected shape into space
1516{
1517 Points points = to_points(shape2d);
1518 Points duplicits = collect_duplicates(points);
1519 return (duplicits.empty()) ?
1520 priv::polygons2model_unique(shape2d, projection, points) :
1521 priv::polygons2model_duplicit(shape2d, projection, points, duplicits);
1522}
Definition CutSurface.cpp:39
indexed_triangle_set polygons2model_unique(const ExPolygons &shape2d, const IProjection &projection, const Points &points)
Definition Emboss.cpp:1385

References Slic3r::collect_duplicates(), priv::polygons2model_duplicit(), priv::polygons2model_unique(), and Slic3r::to_points().

+ Here is the call graph for this function:

◆ suggest_up()

Vec3d Slic3r::Emboss::suggest_up ( const Vec3d  normal,
double  up_limit = 0.9 
)

Suggest wanted up vector of embossed text by emboss direction.

Parameters
normalNormalized vector of emboss direction in world
up_limitIs compared with normal.z to suggest up direction
Returns
Wanted up vector
1547{
1548 // Normal must be 1
1549 assert(is_approx(normal.squaredNorm(), 1.));
1550
1551 // wanted up direction of result
1552 Vec3d wanted_up_side =
1553 (std::fabs(normal.z()) > up_limit)?
1554 Vec3d::UnitY() : Vec3d::UnitZ();
1555
1556 // create perpendicular unit vector to surface triangle normal vector
1557 // lay on surface of triangle and define up vector for text
1558 Vec3d wanted_up_dir = normal.cross(wanted_up_side).cross(normal);
1559 // normal3d is NOT perpendicular to normal_up_dir
1560 wanted_up_dir.normalize();
1561
1562 return wanted_up_dir;
1563}

References Slic3r::is_approx().

Referenced by calc_up(), create_transformation_onto_surface(), and Slic3r::GUI::on_mouse_surface_drag().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ text2shapes()

ExPolygons Slic3r::Emboss::text2shapes ( FontFileWithCache font,
const char *  text,
const FontProp font_prop,
std::function< bool()>  was_canceled = nullptr 
)

Convert text into polygons.

Parameters
fontDefine fonts + cache, which could extend
textCharacters to convert
font_propUser defined property of the font
was_canceledWay to interupt processing
Returns
Inner polygon cw(outer ccw)
1214{
1215 assert(font_with_cache.has_value());
1216 fontinfo_opt font_info_opt;
1217 Point cursor(0, 0);
1218 ExPolygons result;
1219 const FontFile& font = *font_with_cache.font_file;
1220 unsigned int font_index = font_prop.collection_number.has_value()?
1221 *font_prop.collection_number : 0;
1222 if (!priv::is_valid(font, font_index)) return {};
1223 const FontFile::Info& info = font.infos[font_index];
1224 Glyphs& cache = *font_with_cache.cache;
1225 std::wstring ws = boost::nowide::widen(text);
1226 for (wchar_t wc: ws){
1227 if (wc == '\n') {
1228 int line_height = info.ascent - info.descent + info.linegap;
1229 if (font_prop.line_gap.has_value())
1230 line_height += *font_prop.line_gap;
1231 line_height = static_cast<int>(line_height / SHAPE_SCALE);
1232
1233 cursor.x() = 0;
1234 cursor.y() -= line_height;
1235 continue;
1236 }
1237 if (wc == '\t') {
1238 // '\t' = 4*space => same as imgui
1239 const int count_spaces = 4;
1240 const Glyph* space = priv::get_glyph(int(' '), font, font_prop, cache, font_info_opt);
1241 if (space == nullptr) continue;
1242 cursor.x() += count_spaces * space->advance_width;
1243 continue;
1244 }
1245 if (wc == '\r') continue;
1246
1247 int unicode = static_cast<int>(wc);
1248 // check cancelation only before unknown symbol - loading of symbol could be timeconsuming on slow computer and dificult fonts
1249 auto it = cache.find(unicode);
1250 if (it == cache.end() && was_canceled != nullptr && was_canceled()) return {};
1251 const Glyph *glyph_ptr = (it != cache.end())? &it->second :
1252 priv::get_glyph(unicode, font, font_prop, cache, font_info_opt);
1253 if (glyph_ptr == nullptr) continue;
1254
1255 // move glyph to cursor position
1256 ExPolygons expolygons = glyph_ptr->shape; // copy
1257 for (ExPolygon &expolygon : expolygons)
1258 expolygon.translate(cursor);
1259
1260 cursor.x() += glyph_ptr->advance_width;
1261 expolygons_append(result, std::move(expolygons));
1262 }
1263 result = Slic3r::union_ex(result);
1264 heal_shape(result);
1265 return result;
1266}
int advance_width
Definition Emboss.hpp:51
std::map< int, Glyph > Glyphs
Definition Emboss.hpp:54
ExPolygons shape
Definition Emboss.hpp:48
Definition Emboss.hpp:45
void expolygons_append(ExPolygons &dst, const ExPolygons &src)
Definition ExPolygon.hpp:411
void translate(Slic3r::ExPolygon &sh, const Slic3r::Point &offs)
Definition geometries.hpp:241
keep information from file about font (store file data itself)
Definition Emboss.hpp:62
int linegap
Definition Emboss.hpp:72
int ascent
Definition Emboss.hpp:72
int descent
Definition Emboss.hpp:72
std::shared_ptr< const FontFile > font_file
Definition Emboss.hpp:107
std::optional< int > line_gap
Definition TextConfiguration.hpp:27

References Slic3r::Emboss::Glyph::advance_width, Slic3r::Emboss::FontFile::Info::ascent, Slic3r::Emboss::FontFileWithCache::cache, Slic3r::FontProp::collection_number, Slic3r::Emboss::FontFile::Info::descent, Slic3r::expolygons_append(), Slic3r::Emboss::FontFileWithCache::font_file, priv::get_glyph(), Slic3r::Emboss::FontFileWithCache::has_value(), heal_shape(), Slic3r::Emboss::FontFile::infos, priv::is_valid(), Slic3r::FontProp::line_gap, Slic3r::Emboss::FontFile::Info::linegap, Slic3r::Emboss::Glyph::shape, SHAPE_SCALE, Slic3r::union_ex(), and boost::nowide::widen().

Referenced by Slic3r::GUI::CreateFontImageJob::process(), and Slic3r::GUI::Emboss::CreateFontStyleImagesJob::process().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ SHAPE_SCALE