Add text alignement

This commit is contained in:
Filip Sykala - NTB T15p 2023-05-04 19:13:13 +02:00
parent af0ef21ce3
commit 28b526167a
7 changed files with 138 additions and 29 deletions

View File

@ -1918,6 +1918,73 @@ PolygonPoints Emboss::sample_slice(const TextLine &slice, const BoundingBoxes &b
return samples; return samples;
} }
namespace {
Point get_align_offset(FontProp::Align type, const BoundingBox &bb)
{
Point offset;
switch (type) {
// case Slic3r::FontProp::Align::start_first_line: break;
case Slic3r::FontProp::Align::center_left:
case Slic3r::FontProp::Align::center_right:
case Slic3r::FontProp::Align::center_center: offset.y() = bb.center().y(); break;
case Slic3r::FontProp::Align::top_left:
case Slic3r::FontProp::Align::top_right:
case Slic3r::FontProp::Align::top_center: offset.y() = bb.min.y(); break;
case Slic3r::FontProp::Align::bottom_left:
case Slic3r::FontProp::Align::bottom_right:
case Slic3r::FontProp::Align::bottom_center: offset.y() = bb.max.y(); break;
default: break;
}
switch (type) {
// case Slic3r::FontProp::Align::start_first_line: break;
case Slic3r::FontProp::Align::center_center:
case Slic3r::FontProp::Align::top_center:
case Slic3r::FontProp::Align::bottom_center: offset.x() = bb.center().x(); break;
case Slic3r::FontProp::Align::center_left:
case Slic3r::FontProp::Align::top_left:
case Slic3r::FontProp::Align::bottom_left: offset.x() = bb.min.x(); break;
case Slic3r::FontProp::Align::center_right:
case Slic3r::FontProp::Align::top_right:
case Slic3r::FontProp::Align::bottom_right: offset.x() = bb.max.x(); break;
default: break;
}
return -offset;
}
} // namespace
void Emboss::align_shape(FontProp::Align type, ExPolygons &shape, BoundingBox *bb)
{
if (type == FontProp::Align::start_first_line)
return; // no alignement
BoundingBox shape_bb_data;
BoundingBox &shape_bb = (bb != nullptr) ? *bb : shape_bb_data;
if (!shape_bb.defined)
shape_bb = get_extents(shape);
Point offset = get_align_offset(type, shape_bb);
for (ExPolygon &s : shape)
s.translate(offset);
}
void Emboss::align_shape(FontProp::Align type, std::vector<ExPolygons> &shapes, BoundingBox *bb)
{
if (type == FontProp::Align::start_first_line)
return; // no alignement
BoundingBox shape_bb_data;
BoundingBox &shape_bb = (bb != nullptr) ? *bb : shape_bb_data;
if (!shape_bb.defined)
for (const ExPolygons& shape: shapes)
shape_bb.merge(get_extents(shape));
Point offset = get_align_offset(type, shape_bb);
for (ExPolygons &shape : shapes)
for (ExPolygon &s : shape)
s.translate(offset);
}
#ifdef REMOVE_SPIKES #ifdef REMOVE_SPIKES
#include <Geometry.hpp> #include <Geometry.hpp>
void priv::remove_spikes(Polygon &polygon, const SpikeDesc &spike_desc) void priv::remove_spikes(Polygon &polygon, const SpikeDesc &spike_desc)

View File

@ -442,6 +442,15 @@ namespace Emboss
double calculate_angle(int32_t distance, PolygonPoint polygon_point, const Polygon &polygon); double calculate_angle(int32_t distance, PolygonPoint polygon_point, const Polygon &polygon);
std::vector<double> calculate_angles(int32_t distance, const PolygonPoints& polygon_points, const Polygon &polygon); std::vector<double> calculate_angles(int32_t distance, const PolygonPoints& polygon_points, const Polygon &polygon);
/// <summary>
/// Align expolygons by type
/// </summary>
/// <param name="type">Type of alignement</param>
/// <param name="shape">shapes to align</param>
/// <param name="bb">extents of shape</param>
void align_shape(FontProp::Align type, ExPolygons& shape, BoundingBox* bb = nullptr);
void align_shape(FontProp::Align type, std::vector<ExPolygons> &shape, BoundingBox *bb = nullptr);
} // namespace Emboss } // namespace Emboss
} // namespace Slic3r } // namespace Slic3r
#endif // slic3r_Emboss_hpp_ #endif // slic3r_Emboss_hpp_

View File

@ -63,20 +63,21 @@ struct FontProp
// Distiguish projection per glyph // Distiguish projection per glyph
bool per_glyph; bool per_glyph;
//enum class Align { enum class Align {
// left, start_first_line, // it depends on position of zero for first letter
// right, center_left,
// center, center_right,
// top_left, center_center,
// top_right, top_left,
// top_center, top_right,
// bottom_left, top_center,
// bottom_right, bottom_left,
// bottom_center bottom_right,
//}; bottom_center
//// change pivot of text };
//// When not set, center is used and is not stored // change pivot of text
//std::optional<Align> align; // When not set, center is used and is not stored
Align align = Align::center_center;
////// //////
// Duplicit data to wxFontDescriptor // Duplicit data to wxFontDescriptor

View File

@ -1059,6 +1059,9 @@ void GLGizmoEmboss::init_text_lines(){
if (ff_ptr == nullptr) if (ff_ptr == nullptr)
return; return;
if (m_volume->is_the_only_one_part())
return;
const FontProp& fp = m_style_manager.get_font_prop(); const FontProp& fp = m_style_manager.get_font_prop();
const FontFile &ff = *ff_ptr; const FontFile &ff = *ff_ptr;
@ -3226,6 +3229,32 @@ void GLGizmoEmboss::draw_advanced()
} }
} else if (!*per_glyph && m_text_lines.is_init()) } else if (!*per_glyph && m_text_lines.is_init())
m_text_lines.reset(); m_text_lines.reset();
ImGui::SameLine();
ImGui::SetNextItemWidth(100);
if (ImGui::SliderFloat("##base_line_y_offset", &m_text_lines.offset, -10.f, 10.f, "%f mm")) {
init_text_lines();
} else if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", _u8L("Move base line (up/down) for allign letters").c_str());
// order must match align enum
const char* align_names[] = {
"start_first_line",
"center_left",
"center_right",
"center_center",
"top_left",
"top_right",
"top_center",
"bottom_left",
"bottom_right",
"bottom_center"
};
int selected_align = static_cast<int>(font_prop.align);
if (ImGui::Combo("align", &selected_align, align_names, IM_ARRAYSIZE(align_names))) {
font_prop.align = static_cast<FontProp::Align>(selected_align);
}
if (exist_change) { if (exist_change) {
m_style_manager.clear_glyphs_cache(); m_style_manager.clear_glyphs_cache();

View File

@ -427,7 +427,12 @@ ExPolygons priv::create_shape(DataBase &input, Fnc was_canceled) {
if (!font.has_value()) if (!font.has_value())
return {}; return {};
return text2shapes(font, text, prop, was_canceled); ExPolygons shapes = text2shapes(font, text, prop, was_canceled);
if (shapes.empty())
return {};
align_shape(input.text_configuration.style.prop.align, shapes);
return shapes;
} }
#define STORE_SAMPLING #define STORE_SAMPLING
@ -563,15 +568,16 @@ TriangleMesh priv::try_create_mesh(DataBase &input, Fnc was_canceled)
ExPolygons shapes = priv::create_shape(input, was_canceled); ExPolygons shapes = priv::create_shape(input, was_canceled);
if (shapes.empty()) return {}; if (shapes.empty()) return {};
if (was_canceled()) return {}; if (was_canceled()) return {};
const FontProp &prop = input.text_configuration.style.prop; const FontProp &prop = input.text_configuration.style.prop;
const FontFile &ff = *input.font_file.font_file; const FontFile &ff = *input.font_file.font_file;
// NOTE: SHAPE_SCALE is applied in ProjectZ // NOTE: SHAPE_SCALE is applied in ProjectZ
double scale = get_shape_scale(prop, ff) / SHAPE_SCALE; double scale = get_shape_scale(prop, ff) / SHAPE_SCALE;
double depth = prop.emboss / scale; double depth = prop.emboss / scale;
auto projectZ = std::make_unique<ProjectZ>(depth); auto projectZ = std::make_unique<ProjectZ>(depth);
ProjectScale project(std::move(projectZ), scale); //auto scaled = std::make_unique<ProjectScale>(std::move(projectZ), scale);
ProjectTransform project(std::move(projectZ), Eigen::Translation<double, 3>(0., 0., -prop.emboss / 2) * Eigen::Scaling(scale));
if (was_canceled()) return {}; if (was_canceled()) return {};
return TriangleMesh(polygons2model(shapes, project)); return TriangleMesh(polygons2model(shapes, project));
} }
@ -867,12 +873,7 @@ TriangleMesh priv::cut_surface(DataBase& input1, const SurfaceVolumeData& input2
if (was_canceled()) return {}; if (was_canceled()) return {};
// Define alignment of text - left, right, center, top bottom, .... BoundingBox bb = get_extents(shapes);
BoundingBox bb = get_extents(shapes);
Point projection_center = bb.center();
for (ExPolygon &shape : shapes) shape.translate(-projection_center);
bb.translate(-projection_center);
const FontFile &ff = *input1.font_file.font_file; const FontFile &ff = *input1.font_file.font_file;
const FontProp &fp = input1.text_configuration.style.prop; const FontProp &fp = input1.text_configuration.style.prop;
double shape_scale = get_shape_scale(fp, ff); double shape_scale = get_shape_scale(fp, ff);

View File

@ -223,7 +223,7 @@ indexed_triangle_set create_its(const TextLines &lines)
if (polygon.empty()) continue; if (polygon.empty()) continue;
indexed_triangle_set line_its = its_create_belt(polygon, model_half_width); indexed_triangle_set line_its = its_create_belt(polygon, model_half_width);
//indexed_triangle_set line_its = its_create_torus(polygon, model_half_width); //indexed_triangle_set line_its = its_create_torus(polygon, model_half_width);
auto transl = Eigen::Translation3d(0., -line.y, 0.); auto transl = Eigen::Translation3d(0., line.y, 0.);
Transform3d tr = transl * get_rotation(); Transform3d tr = transl * get_rotation();
its_transform(line_its, tr); its_transform(line_its, tr);
its_merge(its, line_its); its_merge(its, line_its);
@ -251,7 +251,7 @@ GLModel::Geometry create_geometry(const TextLines &lines)
} }
} // namespace } // namespace
void TextLinesModel::init(const Selection &selection, double line_height, double line_offset) void TextLinesModel::init(const Selection &selection, double line_height)
{ {
const GLVolume *gl_volume_ptr = selection.get_first_volume(); const GLVolume *gl_volume_ptr = selection.get_first_volume();
if (gl_volume_ptr == nullptr) if (gl_volume_ptr == nullptr)
@ -276,7 +276,7 @@ void TextLinesModel::init(const Selection &selection, double line_height, double
if (count_lines == 0) if (count_lines == 0)
return; return;
double first_line_center = line_offset + (count_lines / 2) * line_height - ((count_lines % 2 == 0) ? line_height / 2. : 0.); double first_line_center = offset + (count_lines / 2) * line_height - ((count_lines % 2 == 0) ? line_height / 2. : 0.);
std::vector<float> line_centers(count_lines); std::vector<float> line_centers(count_lines);
for (size_t i = 0; i < count_lines; ++i) for (size_t i = 0; i < count_lines; ++i)
line_centers[i] = static_cast<float>(first_line_center - i * line_height); line_centers[i] = static_cast<float>(first_line_center - i * line_height);

View File

@ -12,13 +12,15 @@ class Selection;
class TextLinesModel class TextLinesModel
{ {
public: public:
// line offset in y direction (up/down)
float offset = 0;
/// <summary> /// <summary>
/// Initialize model and lines /// Initialize model and lines
/// </summary> /// </summary>
/// <param name="selection">Must be selected text volume</param> /// <param name="selection">Must be selected text volume</param>
/// <param name="line_height">Height of text line with spacing [in mm]</param> /// <param name="line_height">Height of text line with spacing [in mm]</param>
/// <param name="line_offset">Offset of base line from center [in mm]</param> /// <param name="line_offset">Offset of base line from center [in mm]</param>
void init(const Selection &selection, double line_height, double line_offset = 0.); void init(const Selection &selection, double line_height);
void render(const Transform3d &text_world); void render(const Transform3d &text_world);
bool is_init() const { return m_model.is_initialized(); } bool is_init() const { return m_model.is_initialized(); }