mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 22:50:40 +08:00
Partialy fix align:
whitechar in center enters at begining enters at end Align
This commit is contained in:
parent
bf9bf2c626
commit
4be73de02f
@ -1271,32 +1271,30 @@ const int CANCEL_CHECK = 10;
|
|||||||
|
|
||||||
ExPolygons Emboss::text2shapes(FontFileWithCache &font_with_cache, const char *text, const FontProp &font_prop, const std::function<bool()>& was_canceled)
|
ExPolygons Emboss::text2shapes(FontFileWithCache &font_with_cache, const char *text, const FontProp &font_prop, const std::function<bool()>& was_canceled)
|
||||||
{
|
{
|
||||||
assert(font_with_cache.has_value());
|
std::wstring text_w = boost::nowide::widen(text);
|
||||||
const FontFile& font = *font_with_cache.font_file;
|
std::vector<ExPolygons> vshapes = text2vshapes(font_with_cache, text_w, font_prop, was_canceled);
|
||||||
unsigned int font_index = font_prop.collection_number.value_or(0);
|
// unify to one expolygon
|
||||||
if (!priv::is_valid(font, font_index)) return {};
|
|
||||||
|
|
||||||
unsigned counter = 0;
|
|
||||||
Point cursor(0, 0);
|
|
||||||
ExPolygons result;
|
ExPolygons result;
|
||||||
fontinfo_opt font_info_cache;
|
for (ExPolygons &shapes : vshapes) {
|
||||||
std::wstring ws = boost::nowide::widen(text);
|
if (shapes.empty())
|
||||||
for (wchar_t wc: ws){
|
|
||||||
if (++counter == CANCEL_CHECK) {
|
|
||||||
counter = 0;
|
|
||||||
if (was_canceled())
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
ExPolygons expolygons = letter2shapes(wc, cursor, font_with_cache, font_prop, font_info_cache);
|
|
||||||
if (expolygons.empty())
|
|
||||||
continue;
|
continue;
|
||||||
expolygons_append(result, std::move(expolygons));
|
expolygons_append(result, std::move(shapes));
|
||||||
}
|
}
|
||||||
result = Slic3r::union_ex(result);
|
result = Slic3r::union_ex(result);
|
||||||
heal_shape(result);
|
heal_shape(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// <summary>
|
||||||
|
/// Align expolygons by type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Type of alignement</param>
|
||||||
|
/// <param name="shape">shapes to align</param>
|
||||||
|
/// <param name="text">Same size as shape for align per line(detect of end line - '\n')</param>
|
||||||
|
void align_shape(FontProp::Align type, std::vector<ExPolygons> &shape, const std::wstring &text);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<ExPolygons> Emboss::text2vshapes(FontFileWithCache &font_with_cache, const std::wstring& text, const FontProp &font_prop, const std::function<bool()>& was_canceled){
|
std::vector<ExPolygons> Emboss::text2vshapes(FontFileWithCache &font_with_cache, const std::wstring& text, const FontProp &font_prop, const std::function<bool()>& was_canceled){
|
||||||
assert(font_with_cache.has_value());
|
assert(font_with_cache.has_value());
|
||||||
const FontFile &font = *font_with_cache.font_file;
|
const FontFile &font = *font_with_cache.font_file;
|
||||||
@ -1307,8 +1305,8 @@ std::vector<ExPolygons> Emboss::text2vshapes(FontFileWithCache &font_with_cache,
|
|||||||
unsigned counter = 0;
|
unsigned counter = 0;
|
||||||
Point cursor(0, 0);
|
Point cursor(0, 0);
|
||||||
|
|
||||||
std::vector<ExPolygons> result;
|
|
||||||
fontinfo_opt font_info_cache;
|
fontinfo_opt font_info_cache;
|
||||||
|
std::vector<ExPolygons> result;
|
||||||
result.reserve(text.size());
|
result.reserve(text.size());
|
||||||
for (wchar_t letter : text) {
|
for (wchar_t letter : text) {
|
||||||
if (++counter == CANCEL_CHECK) {
|
if (++counter == CANCEL_CHECK) {
|
||||||
@ -1318,6 +1316,8 @@ std::vector<ExPolygons> Emboss::text2vshapes(FontFileWithCache &font_with_cache,
|
|||||||
}
|
}
|
||||||
result.emplace_back(letter2shapes(letter, cursor, font_with_cache, font_prop, font_info_cache));
|
result.emplace_back(letter2shapes(letter, cursor, font_with_cache, font_prop, font_info_cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
align_shape(font_prop.align, result, text);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1326,26 +1326,27 @@ unsigned Emboss::get_count_lines(const std::wstring& ws)
|
|||||||
{
|
{
|
||||||
if (ws.empty())
|
if (ws.empty())
|
||||||
return 0;
|
return 0;
|
||||||
unsigned prev_count = 0;
|
|
||||||
for (wchar_t wc : ws)
|
|
||||||
if (wc == '\n')
|
|
||||||
++prev_count;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
unsigned post_count = 0;
|
|
||||||
for (wchar_t wc : boost::adaptors::reverse(ws))
|
|
||||||
if (wc == '\n')
|
|
||||||
++post_count;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
unsigned count = 1;
|
unsigned count = 1;
|
||||||
for (wchar_t wc : ws)
|
for (wchar_t wc : ws)
|
||||||
if (wc == '\n')
|
if (wc == '\n')
|
||||||
++count;
|
++count;
|
||||||
|
return count;
|
||||||
|
|
||||||
return count - prev_count - post_count;
|
// unsigned prev_count = 0;
|
||||||
|
// for (wchar_t wc : ws)
|
||||||
|
// if (wc == '\n')
|
||||||
|
// ++prev_count;
|
||||||
|
// else
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// unsigned post_count = 0;
|
||||||
|
// for (wchar_t wc : boost::adaptors::reverse(ws))
|
||||||
|
// if (wc == '\n')
|
||||||
|
// ++post_count;
|
||||||
|
// else
|
||||||
|
// break;
|
||||||
|
//return count - prev_count - post_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Emboss::get_count_lines(const std::string &text)
|
unsigned Emboss::get_count_lines(const std::string &text)
|
||||||
@ -1875,11 +1876,12 @@ PolygonPoints Emboss::sample_slice(const TextLine &slice, const BoundingBoxes &b
|
|||||||
// find BB in center of line
|
// find BB in center of line
|
||||||
size_t first_right_index = 0;
|
size_t first_right_index = 0;
|
||||||
for (const BoundingBox &bb : bbs)
|
for (const BoundingBox &bb : bbs)
|
||||||
if (bb.min.x() >= 0) {
|
if (!bb.defined) // white char do not have bb
|
||||||
break;
|
continue;
|
||||||
} else {
|
else if (bb.min.x() < 0)
|
||||||
++first_right_index;
|
++first_right_index;
|
||||||
}
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
PolygonPoints samples(bbs.size());
|
PolygonPoints samples(bbs.size());
|
||||||
int32_t shapes_x_cursor = 0;
|
int32_t shapes_x_cursor = 0;
|
||||||
@ -1925,71 +1927,76 @@ PolygonPoints Emboss::sample_slice(const TextLine &slice, const BoundingBoxes &b
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Point get_align_offset(FontProp::Align type, const BoundingBox &bb)
|
int32_t get_align_y_offset(FontProp::Align type, const BoundingBox &bb){
|
||||||
{
|
|
||||||
Point offset;
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// case Slic3r::FontProp::Align::start_first_line: break;
|
case Slic3r::FontProp::Align::first_line_left:
|
||||||
|
case Slic3r::FontProp::Align::first_line_right:
|
||||||
|
case Slic3r::FontProp::Align::first_line_center: break; // No change
|
||||||
case Slic3r::FontProp::Align::center_left:
|
case Slic3r::FontProp::Align::center_left:
|
||||||
case Slic3r::FontProp::Align::center_right:
|
case Slic3r::FontProp::Align::center_right:
|
||||||
case Slic3r::FontProp::Align::center_center: offset.y() = bb.center().y(); break;
|
case Slic3r::FontProp::Align::center_center: return -bb.center().y();
|
||||||
case Slic3r::FontProp::Align::top_left:
|
case Slic3r::FontProp::Align::top_left:
|
||||||
case Slic3r::FontProp::Align::top_right:
|
case Slic3r::FontProp::Align::top_right:
|
||||||
case Slic3r::FontProp::Align::top_center: offset.y() = bb.min.y(); break;
|
case Slic3r::FontProp::Align::top_center: return -bb.max.y(); break; // direction of Y in 2d is from top to bottom
|
||||||
case Slic3r::FontProp::Align::bottom_left:
|
case Slic3r::FontProp::Align::bottom_left:
|
||||||
case Slic3r::FontProp::Align::bottom_right:
|
case Slic3r::FontProp::Align::bottom_right:
|
||||||
case Slic3r::FontProp::Align::bottom_center: offset.y() = bb.max.y(); break;
|
case Slic3r::FontProp::Align::bottom_center: return -bb.min.y(); // direction of Y in 2d is from top to bottom
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int32_t get_align_x_offset(FontProp::Align type, const BoundingBox &shape_bb, const BoundingBox &line_bb)
|
||||||
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// case Slic3r::FontProp::Align::start_first_line: break;
|
case Slic3r::FontProp::Align::first_line_center:
|
||||||
case Slic3r::FontProp::Align::center_center:
|
case Slic3r::FontProp::Align::center_center:
|
||||||
case Slic3r::FontProp::Align::top_center:
|
case Slic3r::FontProp::Align::top_center:
|
||||||
case Slic3r::FontProp::Align::bottom_center: offset.x() = bb.center().x(); break;
|
case Slic3r::FontProp::Align::bottom_center: return -shape_bb.center().x() + (shape_bb.size().x() - line_bb.size().x())/2;
|
||||||
|
case Slic3r::FontProp::Align::first_line_left: break; // special case do not use offset
|
||||||
case Slic3r::FontProp::Align::center_left:
|
case Slic3r::FontProp::Align::center_left:
|
||||||
case Slic3r::FontProp::Align::top_left:
|
case Slic3r::FontProp::Align::top_left:
|
||||||
case Slic3r::FontProp::Align::bottom_left: offset.x() = bb.min.x(); break;
|
case Slic3r::FontProp::Align::bottom_left: return -shape_bb.min.x();
|
||||||
|
case Slic3r::FontProp::Align::first_line_right:
|
||||||
case Slic3r::FontProp::Align::center_right:
|
case Slic3r::FontProp::Align::center_right:
|
||||||
case Slic3r::FontProp::Align::top_right:
|
case Slic3r::FontProp::Align::top_right:
|
||||||
case Slic3r::FontProp::Align::bottom_right: offset.x() = bb.max.x(); break;
|
case Slic3r::FontProp::Align::bottom_right: return -shape_bb.max.x() + (shape_bb.size().x() - line_bb.size().x());
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return -offset;
|
return 0;
|
||||||
}
|
|
||||||
} // 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)
|
void align_shape(FontProp::Align type, std::vector<ExPolygons> &shapes, const std::wstring &text)
|
||||||
{
|
{
|
||||||
if (type == FontProp::Align::start_first_line)
|
if (type == FontProp::Align::first_line_left)
|
||||||
return; // no alignement
|
return; // no alignement
|
||||||
|
|
||||||
BoundingBox shape_bb_data;
|
BoundingBox shape_bb;
|
||||||
BoundingBox &shape_bb = (bb != nullptr) ? *bb : shape_bb_data;
|
for (const ExPolygons& shape: shapes)
|
||||||
if (!shape_bb.defined)
|
shape_bb.merge(get_extents(shape));
|
||||||
for (const ExPolygons& shape: shapes)
|
|
||||||
shape_bb.merge(get_extents(shape));
|
|
||||||
|
|
||||||
Point offset = get_align_offset(type, shape_bb);
|
auto get_line_bb = [&](size_t j) {
|
||||||
for (ExPolygons &shape : shapes)
|
BoundingBox line_bb;
|
||||||
|
for (; j < text.length() && text[j] != '\n'; ++j)
|
||||||
|
line_bb.merge(get_extents(shapes[j]));
|
||||||
|
return line_bb;
|
||||||
|
};
|
||||||
|
|
||||||
|
Point offset(
|
||||||
|
get_align_x_offset(type, shape_bb, get_line_bb(0)),
|
||||||
|
get_align_y_offset(type, shape_bb));
|
||||||
|
assert(shapes.size() == text.length());
|
||||||
|
for (size_t i = 0; i < shapes.size(); ++i) {
|
||||||
|
wchar_t letter = text[i];
|
||||||
|
if (letter == '\n'){
|
||||||
|
offset.x() = get_align_x_offset(type, shape_bb, get_line_bb(i+1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ExPolygons &shape = shapes[i];
|
||||||
for (ExPolygon &s : shape)
|
for (ExPolygon &s : shape)
|
||||||
s.translate(offset);
|
s.translate(offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
#ifdef REMOVE_SPIKES
|
#ifdef REMOVE_SPIKES
|
||||||
#include <Geometry.hpp>
|
#include <Geometry.hpp>
|
||||||
|
@ -441,15 +441,6 @@ 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_
|
||||||
|
@ -64,7 +64,9 @@ struct FontProp
|
|||||||
bool per_glyph;
|
bool per_glyph;
|
||||||
|
|
||||||
enum class Align {
|
enum class Align {
|
||||||
start_first_line, // it depends on position of zero for first letter
|
first_line_left, // it depends on position of zero for first letter (no shape move)
|
||||||
|
first_line_right, // use Y zero same as first letter
|
||||||
|
first_line_center, // use Y zero same as first letter
|
||||||
center_left,
|
center_left,
|
||||||
center_right,
|
center_right,
|
||||||
center_center,
|
center_center,
|
||||||
@ -77,7 +79,7 @@ struct FontProp
|
|||||||
};
|
};
|
||||||
// change pivot of text
|
// change pivot of text
|
||||||
// When not set, center is used and is not stored
|
// When not set, center is used and is not stored
|
||||||
Align align = Align::center_center;
|
Align align = Align::first_line_center;
|
||||||
|
|
||||||
//////
|
//////
|
||||||
// Duplicit data to wxFontDescriptor
|
// Duplicit data to wxFontDescriptor
|
||||||
|
@ -447,7 +447,7 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
if (gl_volume == nullptr || !m_style_manager.is_active_font())
|
if (gl_volume == nullptr || !m_style_manager.is_active_font())
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
m_style_manager.get_style().prop.angle = calc_up(gl_volume->world_matrix(), priv::up_limit);
|
m_style_manager.get_font_prop().angle = calc_up(gl_volume->world_matrix(), priv::up_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
volume_transformation_changing();
|
volume_transformation_changing();
|
||||||
@ -559,7 +559,7 @@ void GLGizmoEmboss::volume_transformation_changing()
|
|||||||
}
|
}
|
||||||
const FontProp &prop = m_volume->text_configuration->style.prop;
|
const FontProp &prop = m_volume->text_configuration->style.prop;
|
||||||
if (prop.per_glyph)
|
if (prop.per_glyph)
|
||||||
init_text_lines();
|
init_text_lines(m_text_lines.get_lines().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::volume_transformation_changed()
|
void GLGizmoEmboss::volume_transformation_changed()
|
||||||
@ -571,7 +571,7 @@ void GLGizmoEmboss::volume_transformation_changed()
|
|||||||
|
|
||||||
const FontProp &prop = m_volume->text_configuration->style.prop;
|
const FontProp &prop = m_volume->text_configuration->style.prop;
|
||||||
if (prop.per_glyph)
|
if (prop.per_glyph)
|
||||||
init_text_lines();
|
init_text_lines(m_text_lines.get_lines().size());
|
||||||
|
|
||||||
// Update surface by new position
|
// Update surface by new position
|
||||||
if (prop.use_surface || prop.per_glyph)
|
if (prop.use_surface || prop.per_glyph)
|
||||||
@ -1047,7 +1047,7 @@ EmbossStyles GLGizmoEmboss::create_default_styles()
|
|||||||
return styles;
|
return styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::init_text_lines(){
|
void GLGizmoEmboss::init_text_lines(unsigned count_lines){
|
||||||
assert(m_style_manager.is_active_font());
|
assert(m_style_manager.is_active_font());
|
||||||
if (!m_style_manager.is_active_font())
|
if (!m_style_manager.is_active_font())
|
||||||
return;
|
return;
|
||||||
@ -1067,7 +1067,7 @@ void GLGizmoEmboss::init_text_lines(){
|
|||||||
const FontFile &ff = *ff_ptr;
|
const FontFile &ff = *ff_ptr;
|
||||||
|
|
||||||
double line_height = TextLinesModel::calc_line_height(ff, fp);
|
double line_height = TextLinesModel::calc_line_height(ff, fp);
|
||||||
m_text_lines.init(m_parent.get_selection(), line_height);
|
m_text_lines.init(m_parent.get_selection(), line_height, count_lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::set_volume_by_selection()
|
void GLGizmoEmboss::set_volume_by_selection()
|
||||||
@ -1306,6 +1306,9 @@ bool GLGizmoEmboss::process()
|
|||||||
if (use_surface && is_object)
|
if (use_surface && is_object)
|
||||||
use_surface = false;
|
use_surface = false;
|
||||||
|
|
||||||
|
assert(!data.text_configuration.style.prop.per_glyph ||
|
||||||
|
get_count_lines(m_text) == m_text_lines.get_lines().size());
|
||||||
|
|
||||||
if (use_surface) {
|
if (use_surface) {
|
||||||
// Model to cut surface from.
|
// Model to cut surface from.
|
||||||
SurfaceVolumeData::ModelSources sources = create_volume_sources(m_volume);
|
SurfaceVolumeData::ModelSources sources = create_volume_sources(m_volume);
|
||||||
@ -1540,6 +1543,12 @@ void GLGizmoEmboss::draw_text_input()
|
|||||||
ImVec2 input_size(m_gui_cfg->text_size.x, m_gui_cfg->text_size.y + extra_height);
|
ImVec2 input_size(m_gui_cfg->text_size.x, m_gui_cfg->text_size.y + extra_height);
|
||||||
const ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_AutoSelectAll;
|
const ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_AutoSelectAll;
|
||||||
if (ImGui::InputTextMultiline("##Text", &m_text, input_size, flags)) {
|
if (ImGui::InputTextMultiline("##Text", &m_text, input_size, flags)) {
|
||||||
|
if (m_style_manager.get_font_prop().per_glyph) {
|
||||||
|
unsigned count_lines = get_count_lines(m_text);
|
||||||
|
if (count_lines != m_text_lines.get_lines().size())
|
||||||
|
// Necesarry to initialize count by given number (differ from stored in volume at the moment)
|
||||||
|
init_text_lines(count_lines);
|
||||||
|
}
|
||||||
process();
|
process();
|
||||||
range_text = create_range_text_prep();
|
range_text = create_range_text_prep();
|
||||||
}
|
}
|
||||||
@ -2801,7 +2810,7 @@ bool GLGizmoEmboss::rev_checkbox(const std::string &name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoEmboss::set_height() {
|
bool GLGizmoEmboss::set_height() {
|
||||||
float &value = m_style_manager.get_style().prop.size_in_mm;
|
float &value = m_style_manager.get_font_prop().size_in_mm;
|
||||||
|
|
||||||
// size can't be zero or negative
|
// size can't be zero or negative
|
||||||
priv::Limits::apply(value, priv::limits.size_in_mm);
|
priv::Limits::apply(value, priv::limits.size_in_mm);
|
||||||
@ -2829,7 +2838,7 @@ bool GLGizmoEmboss::set_height() {
|
|||||||
|
|
||||||
void GLGizmoEmboss::draw_height(bool use_inch)
|
void GLGizmoEmboss::draw_height(bool use_inch)
|
||||||
{
|
{
|
||||||
float &value = m_style_manager.get_style().prop.size_in_mm;
|
float &value = m_style_manager.get_font_prop().size_in_mm;
|
||||||
const EmbossStyle* stored_style = m_style_manager.get_stored_style();
|
const EmbossStyle* stored_style = m_style_manager.get_stored_style();
|
||||||
const float *stored = (stored_style != nullptr)? &stored_style->prop.size_in_mm : nullptr;
|
const float *stored = (stored_style != nullptr)? &stored_style->prop.size_in_mm : nullptr;
|
||||||
const char *size_format = use_inch ? "%.2f in" : "%.1f mm";
|
const char *size_format = use_inch ? "%.2f in" : "%.1f mm";
|
||||||
@ -2842,7 +2851,7 @@ void GLGizmoEmboss::draw_height(bool use_inch)
|
|||||||
|
|
||||||
bool GLGizmoEmboss::set_depth()
|
bool GLGizmoEmboss::set_depth()
|
||||||
{
|
{
|
||||||
float &value = m_style_manager.get_style().prop.emboss;
|
float &value = m_style_manager.get_font_prop().emboss;
|
||||||
|
|
||||||
// size can't be zero or negative
|
// size can't be zero or negative
|
||||||
priv::Limits::apply(value, priv::limits.emboss);
|
priv::Limits::apply(value, priv::limits.emboss);
|
||||||
@ -2853,7 +2862,7 @@ bool GLGizmoEmboss::set_depth()
|
|||||||
|
|
||||||
void GLGizmoEmboss::draw_depth(bool use_inch)
|
void GLGizmoEmboss::draw_depth(bool use_inch)
|
||||||
{
|
{
|
||||||
float &value = m_style_manager.get_style().prop.emboss;
|
float &value = m_style_manager.get_font_prop().emboss;
|
||||||
const EmbossStyle* stored_style = m_style_manager.get_stored_style();
|
const EmbossStyle* stored_style = m_style_manager.get_stored_style();
|
||||||
const float *stored = ((stored_style)? &stored_style->prop.emboss : nullptr);
|
const float *stored = ((stored_style)? &stored_style->prop.emboss : nullptr);
|
||||||
const std::string revert_emboss_depth = _u8L("Revert embossed depth.");
|
const std::string revert_emboss_depth = _u8L("Revert embossed depth.");
|
||||||
@ -2971,7 +2980,7 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FontProp &font_prop = m_style_manager.get_style().prop;
|
FontProp &font_prop = m_style_manager.get_font_prop();
|
||||||
const auto &cn = m_style_manager.get_font_prop().collection_number;
|
const auto &cn = m_style_manager.get_font_prop().collection_number;
|
||||||
unsigned int font_index = (cn.has_value()) ? *cn : 0;
|
unsigned int font_index = (cn.has_value()) ? *cn : 0;
|
||||||
const auto &font_info = ff.font_file->infos[font_index];
|
const auto &font_info = ff.font_file->infos[font_index];
|
||||||
@ -3210,7 +3219,7 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
if (ImGui::Button(_u8L("Set text to face camera").c_str())) {
|
if (ImGui::Button(_u8L("Set text to face camera").c_str())) {
|
||||||
assert(get_selected_volume(m_parent.get_selection()) == m_volume);
|
assert(get_selected_volume(m_parent.get_selection()) == m_volume);
|
||||||
const Camera &cam = wxGetApp().plater()->get_camera();
|
const Camera &cam = wxGetApp().plater()->get_camera();
|
||||||
bool use_surface = m_style_manager.get_style().prop.use_surface;
|
bool use_surface = m_style_manager.get_font_prop().use_surface;
|
||||||
if (priv::apply_camera_dir(cam, m_parent, m_keep_up) && use_surface)
|
if (priv::apply_camera_dir(cam, m_parent, m_keep_up) && use_surface)
|
||||||
process();
|
process();
|
||||||
} else if (ImGui::IsItemHovered()) {
|
} else if (ImGui::IsItemHovered()) {
|
||||||
@ -3239,24 +3248,24 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(100);
|
ImGui::SetNextItemWidth(100);
|
||||||
if (ImGui::SliderFloat("##base_line_y_offset", &m_text_lines.offset, -10.f, 10.f, "%f mm")) {
|
if (ImGui::SliderFloat("##base_line_y_offset", &m_text_lines.offset, -10.f, 10.f, "%f mm")) {
|
||||||
init_text_lines();
|
init_text_lines(m_text_lines.get_lines().size());
|
||||||
process();
|
process();
|
||||||
} else if (ImGui::IsItemHovered())
|
} else if (ImGui::IsItemHovered())
|
||||||
ImGui::SetTooltip("%s", _u8L("Move base line (up/down) for allign letters").c_str());
|
ImGui::SetTooltip("%s", _u8L("Move base line (up/down) for allign letters").c_str());
|
||||||
|
|
||||||
// order must match align enum
|
// order must match align enum
|
||||||
const char* align_names[] = {
|
const char* align_names[] = {"first_line_left",
|
||||||
"start_first_line",
|
"first_line_right",
|
||||||
"center_left",
|
"first_line_center",
|
||||||
"center_right",
|
"center_left",
|
||||||
"center_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"};
|
||||||
int selected_align = static_cast<int>(font_prop.align);
|
int selected_align = static_cast<int>(font_prop.align);
|
||||||
if (ImGui::Combo("align", &selected_align, align_names, IM_ARRAYSIZE(align_names))) {
|
if (ImGui::Combo("align", &selected_align, align_names, IM_ARRAYSIZE(align_names))) {
|
||||||
font_prop.align = static_cast<FontProp::Align>(selected_align);
|
font_prop.align = static_cast<FontProp::Align>(selected_align);
|
||||||
@ -3359,7 +3368,7 @@ bool GLGizmoEmboss::choose_font_by_wxdialog()
|
|||||||
const auto&ff = m_style_manager.get_font_file_with_cache();
|
const auto&ff = m_style_manager.get_font_file_with_cache();
|
||||||
if (WxFontUtils::is_italic(wx_font) &&
|
if (WxFontUtils::is_italic(wx_font) &&
|
||||||
!Emboss::is_italic(*ff.font_file, font_collection)) {
|
!Emboss::is_italic(*ff.font_file, font_collection)) {
|
||||||
m_style_manager.get_style().prop.skew = 0.2;
|
m_style_manager.get_font_prop().skew = 0.2;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3428,7 +3437,7 @@ bool GLGizmoEmboss::choose_svg_file()
|
|||||||
|
|
||||||
BoundingBox bb;
|
BoundingBox bb;
|
||||||
for (const auto &p : polys) bb.merge(p.contour.points);
|
for (const auto &p : polys) bb.merge(p.contour.points);
|
||||||
const FontProp &fp = m_style_manager.get_style().prop;
|
const FontProp &fp = m_style_manager.get_font_prop();
|
||||||
float scale = fp.size_in_mm / std::max(bb.max.x(), bb.max.y());
|
float scale = fp.size_in_mm / std::max(bb.max.x(), bb.max.y());
|
||||||
auto project = std::make_unique<ProjectScale>(
|
auto project = std::make_unique<ProjectScale>(
|
||||||
std::make_unique<ProjectZ>(fp.emboss / scale), scale);
|
std::make_unique<ProjectZ>(fp.emboss / scale), scale);
|
||||||
|
@ -317,7 +317,7 @@ private:
|
|||||||
|
|
||||||
// Keep information about curvature of text line around surface
|
// Keep information about curvature of text line around surface
|
||||||
TextLinesModel m_text_lines;
|
TextLinesModel m_text_lines;
|
||||||
void init_text_lines();
|
void init_text_lines(unsigned count_lines = 0);
|
||||||
|
|
||||||
// Rotation gizmo
|
// Rotation gizmo
|
||||||
GLGizmoRotate m_rotate_gizmo;
|
GLGizmoRotate m_rotate_gizmo;
|
||||||
|
@ -362,10 +362,15 @@ bool priv::check(const DataBase &input, bool check_fontfile, bool use_surface)
|
|||||||
res &= !input.text_configuration.text.empty();
|
res &= !input.text_configuration.text.empty();
|
||||||
assert(!input.volume_name.empty());
|
assert(!input.volume_name.empty());
|
||||||
res &= !input.volume_name.empty();
|
res &= !input.volume_name.empty();
|
||||||
assert(input.text_configuration.style.prop.use_surface == use_surface);
|
const FontProp& prop = input.text_configuration.style.prop;
|
||||||
res &= input.text_configuration.style.prop.use_surface == use_surface;
|
assert(prop.use_surface == use_surface);
|
||||||
assert(input.text_configuration.style.prop.per_glyph == !input.text_lines.empty());
|
res &= prop.use_surface == use_surface;
|
||||||
res &= input.text_configuration.style.prop.per_glyph == !input.text_lines.empty();
|
assert(prop.per_glyph == !input.text_lines.empty());
|
||||||
|
res &= prop.per_glyph == !input.text_lines.empty();
|
||||||
|
if (prop.per_glyph) {
|
||||||
|
assert(get_count_lines(input.text_configuration.text) == input.text_lines.size());
|
||||||
|
res &= get_count_lines(input.text_configuration.text) == input.text_lines.size();
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
bool priv::check(const DataCreateVolume &input, bool is_main_thread) {
|
bool priv::check(const DataCreateVolume &input, bool is_main_thread) {
|
||||||
@ -432,7 +437,6 @@ ExPolygons priv::create_shape(DataBase &input, Fnc was_canceled) {
|
|||||||
if (shapes.empty())
|
if (shapes.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
align_shape(input.text_configuration.style.prop.align, shapes);
|
|
||||||
return shapes;
|
return shapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,7 +456,6 @@ std::vector<ExPolygons> priv::create_shapes(DataBase &input, Fnc was_canceled) {
|
|||||||
if (shapes.empty())
|
if (shapes.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
align_shape(prop.align, shapes);
|
|
||||||
if (was_canceled())
|
if (was_canceled())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@ -591,8 +594,8 @@ TriangleMesh priv::try_create_mesh(DataBase &input, Fnc was_canceled)
|
|||||||
{
|
{
|
||||||
if (!input.text_lines.empty()) {
|
if (!input.text_lines.empty()) {
|
||||||
TriangleMesh tm = create_mesh_per_glyph(input, was_canceled);
|
TriangleMesh tm = create_mesh_per_glyph(input, was_canceled);
|
||||||
if (!tm.empty())
|
if (was_canceled()) return {};
|
||||||
return tm;
|
if (!tm.empty()) return tm;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons shapes = priv::create_shape(input, was_canceled);
|
ExPolygons shapes = priv::create_shape(input, was_canceled);
|
||||||
|
@ -251,7 +251,7 @@ GLModel::Geometry create_geometry(const TextLines &lines)
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void TextLinesModel::init(const Selection &selection, double line_height)
|
void TextLinesModel::init(const Selection &selection, double line_height, unsigned count_lines)
|
||||||
{
|
{
|
||||||
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)
|
||||||
@ -268,13 +268,15 @@ void TextLinesModel::init(const Selection &selection, double line_height)
|
|||||||
return;
|
return;
|
||||||
const ModelVolume &mv = *mv_ptr;
|
const ModelVolume &mv = *mv_ptr;
|
||||||
|
|
||||||
const std::optional<TextConfiguration> tc_opt = mv.text_configuration;
|
// calculate count lines when not set
|
||||||
if (!tc_opt.has_value())
|
if (count_lines == 0) {
|
||||||
return;
|
const std::optional<TextConfiguration> tc_opt = mv.text_configuration;
|
||||||
|
if (!tc_opt.has_value())
|
||||||
unsigned count_lines = Emboss::get_count_lines(tc_opt->text);
|
return;
|
||||||
if (count_lines == 0)
|
count_lines = Emboss::get_count_lines(tc_opt->text);
|
||||||
return;
|
if (count_lines == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
double first_line_center = 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);
|
||||||
|
@ -20,7 +20,8 @@ public:
|
|||||||
/// <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);
|
/// <param name="count_lines">[Optional] Count lines when not set it is calculated from vodel volume text</param>
|
||||||
|
void init(const Selection &selection, double line_height, unsigned count_lines = 0);
|
||||||
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