mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 05:26:02 +08:00
Add text alignement
This commit is contained in:
parent
af0ef21ce3
commit
28b526167a
@ -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)
|
||||||
|
@ -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_
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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(); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user