mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 01:25:59 +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;
|
||||
}
|
||||
|
||||
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
|
||||
#include <Geometry.hpp>
|
||||
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);
|
||||
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 Slic3r
|
||||
#endif // slic3r_Emboss_hpp_
|
||||
|
@ -63,20 +63,21 @@ struct FontProp
|
||||
// Distiguish projection per glyph
|
||||
bool per_glyph;
|
||||
|
||||
//enum class Align {
|
||||
// left,
|
||||
// right,
|
||||
// center,
|
||||
// top_left,
|
||||
// top_right,
|
||||
// top_center,
|
||||
// bottom_left,
|
||||
// bottom_right,
|
||||
// bottom_center
|
||||
//};
|
||||
//// change pivot of text
|
||||
//// When not set, center is used and is not stored
|
||||
//std::optional<Align> align;
|
||||
enum class Align {
|
||||
start_first_line, // it depends on position of zero for first letter
|
||||
center_left,
|
||||
center_right,
|
||||
center_center,
|
||||
top_left,
|
||||
top_right,
|
||||
top_center,
|
||||
bottom_left,
|
||||
bottom_right,
|
||||
bottom_center
|
||||
};
|
||||
// change pivot of text
|
||||
// When not set, center is used and is not stored
|
||||
Align align = Align::center_center;
|
||||
|
||||
//////
|
||||
// Duplicit data to wxFontDescriptor
|
||||
|
@ -1059,6 +1059,9 @@ void GLGizmoEmboss::init_text_lines(){
|
||||
if (ff_ptr == nullptr)
|
||||
return;
|
||||
|
||||
if (m_volume->is_the_only_one_part())
|
||||
return;
|
||||
|
||||
const FontProp& fp = m_style_manager.get_font_prop();
|
||||
const FontFile &ff = *ff_ptr;
|
||||
|
||||
@ -3226,6 +3229,32 @@ void GLGizmoEmboss::draw_advanced()
|
||||
}
|
||||
} else if (!*per_glyph && m_text_lines.is_init())
|
||||
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) {
|
||||
m_style_manager.clear_glyphs_cache();
|
||||
|
@ -427,7 +427,12 @@ ExPolygons priv::create_shape(DataBase &input, Fnc was_canceled) {
|
||||
if (!font.has_value())
|
||||
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
|
||||
@ -563,15 +568,16 @@ TriangleMesh priv::try_create_mesh(DataBase &input, Fnc was_canceled)
|
||||
|
||||
ExPolygons shapes = priv::create_shape(input, was_canceled);
|
||||
if (shapes.empty()) return {};
|
||||
if (was_canceled()) return {};
|
||||
|
||||
if (was_canceled()) return {};
|
||||
|
||||
const FontProp &prop = input.text_configuration.style.prop;
|
||||
const FontFile &ff = *input.font_file.font_file;
|
||||
// NOTE: SHAPE_SCALE is applied in ProjectZ
|
||||
double scale = get_shape_scale(prop, ff) / SHAPE_SCALE;
|
||||
double depth = prop.emboss / scale;
|
||||
auto projectZ = std::make_unique<ProjectZ>(depth);
|
||||
ProjectScale project(std::move(projectZ), scale);
|
||||
auto projectZ = std::make_unique<ProjectZ>(depth);
|
||||
//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 {};
|
||||
return TriangleMesh(polygons2model(shapes, project));
|
||||
}
|
||||
@ -867,12 +873,7 @@ TriangleMesh priv::cut_surface(DataBase& input1, const SurfaceVolumeData& input2
|
||||
|
||||
if (was_canceled()) return {};
|
||||
|
||||
// Define alignment of text - left, right, center, top bottom, ....
|
||||
BoundingBox bb = get_extents(shapes);
|
||||
Point projection_center = bb.center();
|
||||
for (ExPolygon &shape : shapes) shape.translate(-projection_center);
|
||||
bb.translate(-projection_center);
|
||||
|
||||
BoundingBox bb = get_extents(shapes);
|
||||
const FontFile &ff = *input1.font_file.font_file;
|
||||
const FontProp &fp = input1.text_configuration.style.prop;
|
||||
double shape_scale = get_shape_scale(fp, ff);
|
||||
|
@ -223,7 +223,7 @@ indexed_triangle_set create_its(const TextLines &lines)
|
||||
if (polygon.empty()) continue;
|
||||
indexed_triangle_set line_its = its_create_belt(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();
|
||||
its_transform(line_its, tr);
|
||||
its_merge(its, line_its);
|
||||
@ -251,7 +251,7 @@ GLModel::Geometry create_geometry(const TextLines &lines)
|
||||
}
|
||||
} // 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();
|
||||
if (gl_volume_ptr == nullptr)
|
||||
@ -276,7 +276,7 @@ void TextLinesModel::init(const Selection &selection, double line_height, double
|
||||
if (count_lines == 0)
|
||||
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);
|
||||
for (size_t i = 0; i < count_lines; ++i)
|
||||
line_centers[i] = static_cast<float>(first_line_center - i * line_height);
|
||||
|
@ -12,13 +12,15 @@ class Selection;
|
||||
class TextLinesModel
|
||||
{
|
||||
public:
|
||||
// line offset in y direction (up/down)
|
||||
float offset = 0;
|
||||
/// <summary>
|
||||
/// Initialize model and lines
|
||||
/// </summary>
|
||||
/// <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_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);
|
||||
|
||||
bool is_init() const { return m_model.is_initialized(); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user