diff --git a/src/libslic3r/Emboss.cpp b/src/libslic3r/Emboss.cpp index 7352516633..3a2bb6802e 100644 --- a/src/libslic3r/Emboss.cpp +++ b/src/libslic3r/Emboss.cpp @@ -1929,22 +1929,22 @@ PolygonPoints Emboss::sample_slice(const TextLine &slice, const BoundingBoxes &b } namespace { -int32_t get_align_y_offset(FontProp::VerticalAlign align, int count_lines, int line_height) +template T get_align_y_offset(FontProp::VerticalAlign align, unsigned count_lines, T line_height) { + if (count_lines == 0) + return 0; + // direction of Y in 2d is from top to bottom // zero is on base line of first line switch (align) { - case FontProp::VerticalAlign::center: - return ((count_lines-1) / 2) * line_height - + ((count_lines % 2 == 0) ? (line_height / 2) : 0); - case FontProp::VerticalAlign::bottom: - return (count_lines-1) * line_height; + case FontProp::VerticalAlign::center: return ((count_lines - 1) / 2) * line_height + ((count_lines % 2 == 0) ? (line_height / 2) : 0); + case FontProp::VerticalAlign::bottom: return (count_lines - 1) * line_height; case FontProp::VerticalAlign::top: // no change - default: - break; + default: break; } return 0; } + int32_t get_align_x_offset(FontProp::HorizontalAlign align, const BoundingBox &shape_bb, const BoundingBox &line_bb) { switch (align) { @@ -1990,6 +1990,10 @@ void align_shape(FontProp::Align type, std::vector &shapes, const st } } // namespace +double Emboss::get_align_y_offset(FontProp::VerticalAlign align, unsigned count_lines, double line_height){ + return ::get_align_y_offset(align, count_lines, line_height); +} + #ifdef REMOVE_SPIKES #include void priv::remove_spikes(Polygon &polygon, const SpikeDesc &spike_desc) diff --git a/src/libslic3r/Emboss.hpp b/src/libslic3r/Emboss.hpp index cb6aac8df9..bef95735b1 100644 --- a/src/libslic3r/Emboss.hpp +++ b/src/libslic3r/Emboss.hpp @@ -236,6 +236,16 @@ namespace Emboss /// Line height with spacing in ExPolygon size int get_line_height(const FontFile &font, const FontProp &prop); + /// + /// Calculate Vertical align + /// + /// double for mm + /// type + /// + /// + /// In same unit as line height + double get_align_y_offset(FontProp::VerticalAlign align, unsigned count_lines, double line_height); + /// /// Project spatial point /// diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index bd78b66193..e1d28882c2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -264,26 +264,7 @@ namespace { // for existing volume which is selected(could init different(to volume text) lines count when edit text) void init_text_lines(TextLinesModel &text_lines, const Selection& selection, /* const*/ StyleManager &style_manager, unsigned count_lines=0); // before text volume is created -void init_new_text_line(TextLinesModel &text_lines, const Transform3d& new_text_tr, const ModelObject& mo, /* const*/ StyleManager &style_manager) -{ - // prepare volumes to slice - ModelVolumePtrs volumes; - volumes.reserve(mo.volumes.size()); - for (ModelVolume *volume : mo.volumes) { - // only part could be surface for volumes - if (!volume->is_model_part()) - continue; - volumes.push_back(volume); - } - - double line_height = style_manager.get_line_height(); - if (line_height < 0) - return; - - FontProp::Align align = style_manager.get_font_prop().align; - unsigned count_lines = 1; - text_lines.init(new_text_tr, volumes, align, line_height, count_lines); -} +void init_new_text_line(TextLinesModel &text_lines, const Transform3d& new_text_tr, const ModelObject& mo, /* const*/ StyleManager &style_manager); } void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos) @@ -1098,12 +1079,42 @@ EmbossStyles GLGizmoEmboss::create_default_styles() } namespace { -void init_text_lines(TextLinesModel &text_lines, const Selection& selection, /* const*/ StyleManager &style_manager, unsigned count_lines) + +bool get_line_height_offset(/* const*/ StyleManager &style_manager, double &line_height_mm, double &line_offset_mm) { - double line_height = style_manager.get_line_height(); - if (line_height < 0) - return; - + assert(style_manager.is_active_font()); + if (!style_manager.is_active_font()) + return false; + const auto &ffc = style_manager.get_font_file_with_cache(); + assert(ffc.has_value()); + if (!ffc.has_value()) + return false; + const auto &ff_ptr = ffc.font_file; + assert(ff_ptr != nullptr); + if (ff_ptr == nullptr) + return false; + const FontProp &fp = style_manager.get_font_prop(); + const FontFile &ff = *ff_ptr; + + double half_ascent_shape_size = ff.infos[fp.collection_number.value_or(0)].ascent / 2.; + int line_height_shape_size = get_line_height(ff, fp); // In shape size + + double scale = get_shape_scale(fp, ff); + line_offset_mm = half_ascent_shape_size * scale / SHAPE_SCALE; + line_height_mm = line_height_shape_size * scale; + + if (line_height_mm < 0) + return false; + + // fix for bad filled ascent in font file + if (line_offset_mm <= 0) + line_offset_mm = line_height_mm / 3; + + return true; +} + +void init_text_lines(TextLinesModel &text_lines, const Selection& selection, /* const*/ StyleManager &style_manager, unsigned count_lines) +{ const GLVolume *gl_volume_ptr = selection.get_first_volume(); if (gl_volume_ptr == nullptr) return; @@ -1149,10 +1160,35 @@ void init_text_lines(TextLinesModel &text_lines, const Selection& selection, /* } // For interactivity during drag over surface it must be from gl_volume not volume. - const Transform3d &mv_trafo = gl_volume.get_volume_transformation().get_matrix(); - const FontProp &fp = style_manager.get_font_prop(); - text_lines.init(mv_trafo, volumes, fp.align, line_height, count_lines); + const Transform3d &mv_trafo = gl_volume.get_volume_transformation().get_matrix(); + FontProp::VerticalAlign align = style_manager.get_font_prop().align.second; + double line_height_mm, line_offset_mm; + if (!get_line_height_offset(style_manager, line_height_mm, line_offset_mm)) + return; + + text_lines.init(mv_trafo, volumes, align, line_height_mm, line_offset_mm, count_lines); } + +void init_new_text_line(TextLinesModel &text_lines, const Transform3d& new_text_tr, const ModelObject& mo, /* const*/ StyleManager &style_manager) +{ + // prepare volumes to slice + ModelVolumePtrs volumes; + volumes.reserve(mo.volumes.size()); + for (ModelVolume *volume : mo.volumes) { + // only part could be surface for volumes + if (!volume->is_model_part()) + continue; + volumes.push_back(volume); + } + + FontProp::VerticalAlign align = style_manager.get_font_prop().align.second; + double line_height_mm, line_offset_mm; + if (!get_line_height_offset(style_manager, line_height_mm, line_offset_mm)) + return; + unsigned count_lines = 1; + text_lines.init(new_text_tr, volumes, align, line_height_mm, line_offset_mm, count_lines); +} + } void GLGizmoEmboss::reinit_text_lines(unsigned count_lines) { @@ -1617,6 +1653,8 @@ void GLGizmoEmboss::draw_text_input() append_warning(_u8L("Too tall, diminished font height inside text input.")); if (imgui_size < StyleManager::min_imgui_font_size) append_warning(_u8L("Too small, enlarged font height inside text input.")); + if (prop.align.first == FontProp::HorizontalAlign::center || prop.align.first == FontProp::HorizontalAlign::right) + append_warning(_u8L("Text doesn't show current horizontal alignment.")); } // flag for extend font ranges if neccessary diff --git a/src/slic3r/GUI/TextLines.cpp b/src/slic3r/GUI/TextLines.cpp index 7e6e71a580..55002fcf63 100644 --- a/src/slic3r/GUI/TextLines.cpp +++ b/src/slic3r/GUI/TextLines.cpp @@ -251,12 +251,17 @@ GLModel::Geometry create_geometry(const TextLines &lines) } } // namespace -void TextLinesModel::init(const Transform3d &text_tr, const ModelVolumePtrs &volumes_to_slice, FontProp::Align align, double line_height, unsigned count_lines) +void TextLinesModel::init(const Transform3d &text_tr, + const ModelVolumePtrs &volumes_to_slice, + FontProp::VerticalAlign align, + double line_height, + double offset, + unsigned count_lines) { m_model.reset(); m_lines.clear(); - double first_line_center = offset + (count_lines / 2) * line_height - ((count_lines % 2 == 0) ? line_height / 2. : 0.); + double first_line_center = offset + this->offset + get_align_y_offset(align, count_lines, line_height); std::vector line_centers(count_lines); for (size_t i = 0; i < count_lines; ++i) line_centers[i] = static_cast(first_line_center - i * line_height); diff --git a/src/slic3r/GUI/TextLines.hpp b/src/slic3r/GUI/TextLines.hpp index bef7e2262f..2a5f8ca8fa 100644 --- a/src/slic3r/GUI/TextLines.hpp +++ b/src/slic3r/GUI/TextLines.hpp @@ -26,8 +26,9 @@ public: /// Vector of volumes to be sliced /// Vertical (Y) align of the text /// Distance between lines [in mm] + /// Offset from baseline [in mm] /// Count lines(slices over volumes) - void init(const Transform3d &text_tr, const ModelVolumePtrs& volumes_to_slice, FontProp::Align align, double line_height, unsigned count_lines); + void init(const Transform3d &text_tr, const ModelVolumePtrs& volumes_to_slice, FontProp::VerticalAlign align, double line_height, double offset, unsigned count_lines); void render(const Transform3d &text_world);