Port Emboss & SVG gizmo from PrusaSlicer (#2819)

* Rework UI jobs to make them more understandable and flexible.

* Update Orca specific jobs

* Fix progress issue

* Fix dark mode and window radius

* Update cereal version from 1.2.2 to 1.3.0

(cherry picked from commit prusa3d/PrusaSlicer@057232a275)

* Initial port of Emboss gizmo

* Bump up CGAL version to 5.4

(cherry picked from commit prusa3d/PrusaSlicer@1bf9dee3e7)

* Fix text rotation

* Fix test dragging

* Add text gizmo to right click menu

* Initial port of SVG gizmo

* Fix text rotation

* Fix Linux build

* Fix "from surface"

* Fix -90 rotation

* Fix icon path

* Fix loading font with non-ascii name

* Fix storing non-utf8 font descriptor in 3mf file

* Fix filtering with non-utf8 characters

* Emboss: Use Orca style input dialog

* Fix build on macOS

* Fix tooltip color in light mode

* InputText: fixed incorrect padding when FrameBorder > 0. (ocornut/imgui#4794, ocornut/imgui#3781)
InputTextMultiline: fixed vertical tracking with large values of FramePadding.y. (ocornut/imgui#3781, ocornut/imgui#4794)

(cherry picked from commit ocornut/imgui@072caa4a90)
(cherry picked from commit ocornut/imgui@bdd2a94315)

* SVG: Use Orca style input dialog

* Fix job progress update

* Fix crash when select editing text in preview screen

* Use Orca checkbox style

* Fix issue that toolbar icons are kept regenerated

* Emboss: Fix text & icon alignment

* SVG: Fix text & icon alignment

* Emboss: fix toolbar icon mouse hover state

* Add a simple subtle outline effect by drawing back faces using wireframe mode

* Disable selection outlines

* Show outline in white if the model color is too dark

* Make the outline algorithm more reliable

* Enable cull face, which fix render on Linux

* Fix `disable_cullface`

* Post merge fix

* Optimize selection rendering

* Fix scale gizmo

* Emboss: Fix text rotation if base object is scaled

* Fix volume synchronize

* Fix emboss rotation

* Emboss: Fix advance toggle

* Fix text position after reopened the project

* Make font style preview darker

* Make font style preview selector height shorter

---------

Co-authored-by: tamasmeszaros <meszaros.q@gmail.com>
Co-authored-by: ocornut <omarcornut@gmail.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Noisyfox 2023-12-09 22:46:18 +08:00 committed by GitHub
parent 7a8e1929ee
commit 933aa3050b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
197 changed files with 27190 additions and 2454 deletions

View file

@ -0,0 +1,157 @@
///|/ Copyright (c) Prusa Research 2022 Filip Sykala @Jony01
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "CreateFontStyleImagesJob.hpp"
// rasterization of ExPoly
#include "libslic3r/SLA/AGGRaster.hpp"
#include "slic3r/GUI/3DScene.hpp" // ::glsafe
// ability to request new frame after finish rendering
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
using namespace Slic3r;
using namespace Slic3r::Emboss;
using namespace Slic3r::GUI;
using namespace Slic3r::GUI::Emboss;
CreateFontStyleImagesJob::CreateFontStyleImagesJob(StyleManager::StyleImagesData &&input)
: m_input(std::move(input)), m_width(0), m_height(0)
{
assert(m_input.result != nullptr);
assert(!m_input.styles.empty());
assert(!m_input.text.empty());
assert(m_input.max_size.x() > 1);
assert(m_input.max_size.y() > 1);
assert(m_input.ppm > 1e-5);
}
void CreateFontStyleImagesJob::process(Ctl &ctl)
{
// create shapes and calc size (bounding boxes)
std::vector<ExPolygons> name_shapes(m_input.styles.size());
std::vector<double> scales(m_input.styles.size());
m_images = std::vector<StyleManager::StyleImage>(m_input.styles.size());
auto was_canceled = []() { return false; };
for (auto &item : m_input.styles) {
size_t index = &item - &m_input.styles.front();
ExPolygons &shapes = name_shapes[index];
shapes = text2shapes(item.font, m_input.text.c_str(), item.prop, was_canceled);
// create image description
StyleManager::StyleImage &image = m_images[index];
BoundingBox &bounding_box = image.bounding_box;
for (ExPolygon &shape : shapes)
bounding_box.merge(BoundingBox(shape.contour.points));
for (ExPolygon &shape : shapes) shape.translate(-bounding_box.min);
// calculate conversion from FontPoint to screen pixels by size of font
double scale = get_text_shape_scale(item.prop, *item.font.font_file);
scales[index] = scale;
//double scale = font_prop.size_in_mm * SCALING_FACTOR;
BoundingBoxf bb2(bounding_box.min.cast<double>(),
bounding_box.max.cast<double>());
bb2.scale(scale);
image.tex_size.x = std::ceil(bb2.max.x() - bb2.min.x());
image.tex_size.y = std::ceil(bb2.max.y() - bb2.min.y());
// crop image width
if (image.tex_size.x > m_input.max_size.x())
image.tex_size.x = m_input.max_size.x();
// crop image height
if (image.tex_size.y > m_input.max_size.y())
image.tex_size.y = m_input.max_size.y();
}
// arrange bounding boxes
int offset_y = 0;
m_width = 0;
for (StyleManager::StyleImage &image : m_images) {
image.offset.y() = offset_y;
offset_y += image.tex_size.y+1;
if (m_width < image.tex_size.x)
m_width = image.tex_size.x;
}
m_height = offset_y;
for (StyleManager::StyleImage &image : m_images) {
const Point &o = image.offset;
const ImVec2 &s = image.tex_size;
image.uv0 = ImVec2(o.x() / (double) m_width,
o.y() / (double) m_height);
image.uv1 = ImVec2((o.x() + s.x) / (double) m_width,
(o.y() + s.y) / (double) m_height);
}
// Set up result
m_pixels = std::vector<unsigned char>(4 * m_width * m_height, {255});
// upload sub textures
for (StyleManager::StyleImage &image : m_images) {
sla::Resolution resolution(image.tex_size.x, image.tex_size.y);
size_t index = &image - &m_images.front();
double pixel_dim = SCALING_FACTOR / scales[index];
sla::PixelDim dim(pixel_dim, pixel_dim);
double gamma = 1.;
std::unique_ptr<sla::RasterBase> r =
sla::create_raster_grayscale_aa(resolution, dim, gamma);
for (const ExPolygon &shape : name_shapes[index]) r->draw(shape);
// copy rastered data to pixels
sla::RasterEncoder encoder = [&offset = image.offset, &pix = m_pixels, w=m_width,h=m_height]
(const void *ptr, size_t width, size_t height, size_t num_components) {
// bigger value create darker image
unsigned char gray_level = 1;
size_t size {static_cast<size_t>(w*h)};
assert((offset.x() + width) <= (size_t)w);
assert((offset.y() + height) <= (size_t)h);
const unsigned char *ptr2 = (const unsigned char *) ptr;
for (size_t x = 0; x < width; ++x)
for (size_t y = 0; y < height; ++y) {
size_t index = (offset.y() + y)*w + offset.x() + x;
assert(index < size);
if (index >= size) continue;
pix[4*index+3] = ptr2[y * width + x] / gray_level;
}
return sla::EncodedRaster();
};
r->encode(encoder);
}
}
void CreateFontStyleImagesJob::finalize(bool canceled, std::exception_ptr &)
{
if (canceled) return;
// upload texture on GPU
GLuint tex_id;
GLenum target = GL_TEXTURE_2D, format = GL_RGBA, type = GL_UNSIGNED_BYTE;
GLint level = 0, border = 0;
glsafe(::glGenTextures(1, &tex_id));
glsafe(::glBindTexture(target, tex_id));
glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
GLint w = m_width, h = m_height;
glsafe(::glTexImage2D(target, level, GL_RGBA, w, h, border, format, type,
(const void *) m_pixels.data()));
// set up texture id
void *texture_id = (void *) (intptr_t) tex_id;
for (StyleManager::StyleImage &image : m_images)
image.texture_id = texture_id;
// move to result
m_input.result->styles = std::move(m_input.styles);
m_input.result->images = std::move(m_images);
// bind default texture
GLuint no_texture_id = 0;
glsafe(::glBindTexture(target, no_texture_id));
// show rendered texture
wxGetApp().plater()->canvas3D()->schedule_extra_frame(0);
}