Skip to content

Commit 0de7b93

Browse files
committed
Introduced settings and skeleton smoothing
1 parent 351bb8f commit 0de7b93

20 files changed

+741
-56
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
build/
33
mingw64/
44
build_mingw64/
5+
*.giv
6+
*.stl
7+
/src/giv-widget/gtk-image-viewer/gtk-image-viewer-fixed.*
8+
*.svg

src/main-input.cc

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,13 @@
11
#include "main-input.h"
22
#include "dov-mm-macros.h"
3+
#include "pomelo-widget-utils.h"
34
#include <math.h>
45
#include <fmt/core.h>
56

67
using namespace fmt;
78

89
constexpr double DEG2RAD = M_PI/180;
910

10-
static Gtk::Widget* mmLabelAligned(const gchar *markup, double xAlign)
11-
{
12-
auto w_label = mm<Gtk::Label>();
13-
w_label->set_markup(markup);
14-
w_label->set_alignment(xAlign,0.5);
15-
return w_label;
16-
}
17-
18-
// Make a left aligned managed label with markup
19-
static Gtk::Widget* mmLabelLeft(const gchar *markup)
20-
{
21-
return mmLabelAligned(markup, 0);
22-
}
23-
24-
// Make a left aligned managed label with markup
25-
static Gtk::Widget* mmLabelRight(const gchar *markup)
26-
{
27-
return mmLabelAligned(markup, 1);
28-
}
29-
30-
static Gtk::Frame* mmFrameWithBoldLabel(Glib::ustring label)
31-
{
32-
auto w_frame = mm<Gtk::Frame>();
33-
auto w_frame_label = mm<Gtk::Label>();
34-
w_frame_label->set_markup(Glib::ustring("<b>") + label + "</b>");
35-
w_frame->set_label_widget(*w_frame_label);
36-
return w_frame;
37-
}
38-
3911
MainInput::MainInput()
4012
: Gtk::Box(Gtk::ORIENTATION_VERTICAL)
4113
{

src/meson.build

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
engine_sources = ['pangocairo-to-contour.cc',
2+
'smooth-sharp-angles.cc',
3+
'svgpath-to-cairo.cc']
4+
15
sources = ['pomelo-main.cc',
26
'pomelo.cc',
37
'mesh-viewer.cc',
48
'trackball.cc',
59
'main-input.cc',
610
'mesh.cc',
7-
'pangocairo-to-contour.cc',
811
'worker-skeleton.cc',
912
'progress-dialog.cc',
1013
'skeleton-viewer.cc',
11-
'svgpath-to-cairo.cc',
14+
'settings-dialog.cc',
15+
'pomelo-widget-utils.cc',
16+
'pomelo-settings.cc'
1217
]
1318

1419
if host_machine.system() == 'windows'
@@ -32,6 +37,17 @@ gmp_dep = dependency('gmp')
3237
mpfr_dep = dependency('mpfr')
3338
nanosvg_dep = dependency('nanosvg')
3439

40+
subdir('giv-widget')
41+
42+
resources = gnome.compile_resources(
43+
'resources',
44+
'resources.xml',
45+
c_name :'resources',
46+
source_dir : ['.',
47+
'..',
48+
'../images',]
49+
)
50+
3551
deps = [gtkmm_dep,
3652
pangoft_dep,
3753
epoxy_dep,
@@ -43,17 +59,9 @@ deps = [gtkmm_dep,
4359
pthread_dep,
4460
nanosvg_dep]
4561

46-
47-
subdir('giv-widget')
48-
49-
resources = gnome.compile_resources(
50-
'resources',
51-
'resources.xml',
52-
c_name :'resources',
53-
source_dir : ['.',
54-
'..',
55-
'../images',]
56-
)
62+
lib_engine = static_library('engine',
63+
engine_sources,
64+
dependencies : deps)
5765

5866
incdir = ['giv-widget']
5967
exe = executable(name_cap,
@@ -65,13 +73,20 @@ exe = executable(name_cap,
6573
include_directories : incdir,
6674
link_with : [libgivwidget,
6775
libgtkimageviewer,
76+
lib_engine
6877
],
6978
install :true
7079
)
7180

7281

7382
# An example for converting an svg path to cairo
7483
executable('test-svgpath-to-cairo',
75-
['test-svgpath-to-cairo.cc',
76-
'svgpath-to-cairo.cc'],
84+
['test-svgpath-to-cairo.cc'],
85+
link_with : [lib_engine],
86+
dependencies : deps)
87+
88+
# An example for converting an svg path to cairo
89+
executable('test-svg-to-skeleton',
90+
['test-svg-to-skeleton.cc'],
91+
link_with : [lib_engine],
7792
dependencies : deps)

src/pangocairo-to-contour.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ vector<PHoleInfo> TeXtrusion::skeletonize(const std::vector<Polygon_with_holes>&
290290
vector<PHoleInfo> phole_infos;
291291

292292
for (int ph_idx=0; ph_idx < (int)polys_with_holes.size(); ph_idx++) {
293-
if (updater->info("skeletonize", 1.0*ph_idx/polys_with_holes.size()))
293+
if (updater &&
294+
updater->info("skeletonize", 1.0*ph_idx/polys_with_holes.size()))
294295
throw EAborted("Aborted!");
295296

296297
const auto& ph = polys_with_holes[ph_idx];
@@ -300,7 +301,7 @@ vector<PHoleInfo> TeXtrusion::skeletonize(const std::vector<Polygon_with_holes>&
300301
phi.divide_into_regions();
301302
phole_infos.push_back(phi);
302303
}
303-
if (updater->info("skeletonize", 1.0))
304+
if (updater && updater->info("skeletonize", 1.0))
304305
throw EAborted("Aborted!");
305306

306307
// Create a skeleton giv path. This is a replication of the code
@@ -364,7 +365,7 @@ Mesh TeXtrusion::skeleton_to_mesh(const vector<PHoleInfo>& phole_infos,
364365
// triangulation for both.
365366
double offset_thickness = 0.5;
366367
for (int ph_idx=0; ph_idx < (int)phole_infos.size(); ph_idx++) {
367-
if (updater->info("profile", 1.0*ph_idx/phole_infos.size()))
368+
if (updater && updater->info("profile", 1.0*ph_idx/phole_infos.size()))
368369
throw EAborted("Aborted!");
369370

370371
auto& phi = phole_infos[ph_idx];
@@ -498,7 +499,7 @@ Mesh TeXtrusion::skeleton_to_mesh(const vector<PHoleInfo>& phole_infos,
498499
of << giv_string;
499500
of.close();
500501
#endif
501-
if (updater->info("profile", 1.0))
502+
if (updater && updater->info("profile", 1.0))
502503
throw EAborted("Aborted!");
503504

504505
return mesh;

src/path-extractor.cc

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//======================================================================
2+
// path-extractor.cc - Extract the paths from an svg file
3+
//
4+
// Dov Grobgeld <[email protected]>
5+
// Fri Jan 29 12:38:42 2021
6+
//----------------------------------------------------------------------
7+
8+
#include "path-extractor.h"
9+
#include <fmt/core.h>
10+
#include "path-extractor.h"
11+
#include "svgpath.h"
12+
#include "cairocontext.h"
13+
#include "tinyxml2.h"
14+
15+
using namespace tinyxml2;
16+
using namespace std;
17+
using namespace fmt;
18+
19+
20+
PathExtractor::PathExtractor(const string& SvgFilename)
21+
{
22+
XMLDocument doc;
23+
doc.LoadFile(SvgFilename.c_str());
24+
25+
// Recursively look for paths
26+
Traverse(doc.FirstChildElement());
27+
}
28+
29+
// Recursive traverse the xml tree
30+
void PathExtractor::Traverse(XMLElement *element)
31+
{
32+
for (XMLElement* el = element->FirstChildElement(); el; el = el->NextSiblingElement())
33+
{
34+
XMLElement* el_save = el;
35+
36+
if (string(el->Name()) == "path")
37+
{
38+
const char *svg_path;
39+
el->QueryStringAttribute("d", &svg_path);
40+
this->paths.push_back({svg_path, cairo_matrix_t()});
41+
}
42+
43+
if (!el_save->NoChildren())
44+
Traverse(el_save);
45+
}
46+
}
47+

src/path-extractor.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//======================================================================
2+
// path-extractor.h - Extract the paths from an svg file
3+
//
4+
// Dov Grobgeld <[email protected]>
5+
// Fri Jan 29 12:38:42 2021
6+
//----------------------------------------------------------------------
7+
#ifndef PATH_EXTRACTOR_H
8+
#define PATH_EXTRACTOR_H
9+
10+
#include <cairo.h>
11+
#include <string>
12+
#include <vector>
13+
14+
namespace tinyxml2 {
15+
class XMLElement;
16+
}
17+
18+
// An svg path with its total concatenated cairo transformation
19+
struct PathTrans {
20+
std::string path;
21+
cairo_matrix_t trans;
22+
};
23+
24+
// The path extractor uses the tinyxml2 library to extract all paths
25+
// in the svg document. Currently it ignores surrounding transformations,
26+
// and thus assumes that the document has been fully ungrouped.
27+
class PathExtractor
28+
{
29+
public:
30+
PathExtractor(const std::string& SvgFilename);
31+
32+
std::vector<PathTrans> GetPaths() const { return paths; }
33+
34+
private:
35+
void ParseSvg();
36+
37+
// Traverse the xml tree
38+
void Traverse(tinyxml2::XMLElement * element);
39+
40+
std::vector<PathTrans> paths;
41+
};
42+
43+
#endif /* PATH-EXTRACTOR */

src/pomelo-main.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "pomelo.h"
22
#include "fmt/core.h"
33
#include "pangocairo-to-contour.h"
4+
#include "pomelo-settings.h"
45

56
using namespace std;
67
using namespace fmt;
@@ -9,6 +10,8 @@ int main(int argc, char *argv[])
910
{
1011
int argp = 1;
1112
string mesh_filename;
13+
string config_dir;
14+
auto pomelo_settings = make_shared<PomeloSettings>();
1215

1316
while(argp < argc && argv[argp][0]=='-')
1417
{
@@ -34,10 +37,10 @@ int main(int argc, char *argv[])
3437
}
3538

3639
auto app = Gtk::Application::create(); // argc, argv, "org.dov.pomelo");
37-
Pomelo pomelo;
40+
Pomelo pomelo(pomelo_settings);
3841
if (mesh_filename.size())
3942
pomelo.set_mesh(mesh_filename);
4043

41-
return app->run(pomelo);
44+
return app->run(pomelo, argc, argv);
4245
}
4346

src/pomelo-settings.cc

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// File to handle the pomelo settings through an glib ini file
2+
#include <stdlib.h>
3+
#include "pomelo-settings.h"
4+
#include <glib/gstdio.h>
5+
6+
using namespace std;
7+
8+
const char *GROUP_NAME = "pomelo";
9+
10+
static void rec_mkdir(std::string path)
11+
{
12+
size_t pos = 0;
13+
int mode = 0;
14+
#ifndef _WIN32
15+
mode = S_IRWXU | S_IRWXG | S_IRWXO;
16+
#endif
17+
18+
if (path[path.size()-1]!= '/')
19+
path += '/';
20+
21+
while((pos = path.find_first_of('/', pos+1)) != std::string::npos)
22+
g_mkdir(path.substr(0, pos).c_str(), mode);
23+
}
24+
25+
PomeloSettings::PomeloSettings()
26+
{
27+
string config_dir;
28+
const char *s;
29+
if ((s = getenv("LOCALAPPDATA"))) // Really only for windows
30+
config_dir = string(s);
31+
else
32+
config_dir = string(getenv("HOME"))+"/.config";
33+
34+
config_dir += "/pomelo";
35+
rec_mkdir(config_dir);
36+
m_settings_file = config_dir + "/pomelo.conf";
37+
try {
38+
load();
39+
}
40+
catch(...) {
41+
save();
42+
}
43+
}
44+
45+
void PomeloSettings::save()
46+
{
47+
save_to_file(m_settings_file);
48+
}
49+
50+
void PomeloSettings::load()
51+
{
52+
load_from_file(m_settings_file);
53+
}
54+
55+
// Convenience functions as we have only one group "pomelo"
56+
std::string PomeloSettings::get_string_default(const gchar *key, const char *default_value)
57+
{
58+
if (!has_key(GROUP_NAME, key))
59+
return default_value;
60+
return get_string(GROUP_NAME, key);
61+
}
62+
63+
int PomeloSettings::get_int_default(const gchar *key, int default_value)
64+
{
65+
if (!has_key(GROUP_NAME, key))
66+
return default_value;
67+
return get_integer(GROUP_NAME, key);
68+
}
69+
int PomeloSettings::get_double_default(const gchar *key, double default_value)
70+
{
71+
if (!has_key(GROUP_NAME, key))
72+
return default_value;
73+
return get_double(GROUP_NAME, key);
74+
}
75+
76+
void PomeloSettings::set_int(const char *key, int value)
77+
{
78+
set_integer(GROUP_NAME, key, value);
79+
}
80+
81+
void PomeloSettings::set_double(const char *key, double value)
82+
{
83+
KeyFile::set_double(GROUP_NAME, key, value);
84+
}
85+

0 commit comments

Comments
 (0)