contrek 1.2.8 → 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +11 -0
- data/CHANGELOG.md +7 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/contrek.gemspec +2 -0
- data/ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt +2 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +108 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.h +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +0 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +70 -297
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +6 -6
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +3 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp +114 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h +41 -0
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +52 -2
- data/ext/cpp_polygon_finder/extconf.rb +2 -0
- data/lib/contrek/bitmaps/bitmap.rb +2 -0
- data/lib/contrek/bitmaps/chunky_bitmap.rb +2 -0
- data/lib/contrek/bitmaps/painting.rb +2 -0
- data/lib/contrek/bitmaps/png_bitmap.rb +2 -0
- data/lib/contrek/bitmaps/raw_bitmap.rb +2 -0
- data/lib/contrek/bitmaps/rgb_color.rb +2 -0
- data/lib/contrek/bitmaps/rgb_cpp_color.rb +2 -0
- data/lib/contrek/bitmaps/sample_generator.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_finder.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_horizontal_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_streaming_merger.rb +11 -0
- data/lib/contrek/cpp/cpp_concurrent_vertical_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_result.rb +2 -0
- data/lib/contrek/cpp/cpp_tempfile.rb +28 -0
- data/lib/contrek/finder/bounds.rb +2 -0
- data/lib/contrek/finder/concurrent/clipped_polygon_finder.rb +2 -0
- data/lib/contrek/finder/concurrent/cluster.rb +2 -0
- data/lib/contrek/finder/concurrent/cursor.rb +2 -0
- data/lib/contrek/finder/concurrent/end_point.rb +2 -0
- data/lib/contrek/finder/concurrent/fake_cluster.rb +2 -0
- data/lib/contrek/finder/concurrent/finder.rb +2 -0
- data/lib/contrek/finder/concurrent/horizontal_merger.rb +2 -0
- data/lib/contrek/finder/concurrent/hub.rb +2 -0
- data/lib/contrek/finder/concurrent/inner_polyline.rb +2 -0
- data/lib/contrek/finder/concurrent/listable.rb +2 -0
- data/lib/contrek/finder/concurrent/merger.rb +3 -0
- data/lib/contrek/finder/concurrent/part.rb +2 -0
- data/lib/contrek/finder/concurrent/partitionable.rb +2 -0
- data/lib/contrek/finder/concurrent/polyline.rb +2 -0
- data/lib/contrek/finder/concurrent/poolable.rb +2 -0
- data/lib/contrek/finder/concurrent/position.rb +2 -0
- data/lib/contrek/finder/concurrent/queueable.rb +2 -0
- data/lib/contrek/finder/concurrent/sequence.rb +2 -0
- data/lib/contrek/finder/concurrent/shape.rb +2 -0
- data/lib/contrek/finder/concurrent/streaming_merger.rb +89 -0
- data/lib/contrek/finder/concurrent/tile.rb +2 -0
- data/lib/contrek/finder/concurrent/vertical_merger.rb +4 -2
- data/lib/contrek/finder/list.rb +2 -0
- data/lib/contrek/finder/list_entry.rb +2 -0
- data/lib/contrek/finder/listable.rb +2 -0
- data/lib/contrek/finder/lists.rb +2 -0
- data/lib/contrek/finder/node.rb +2 -0
- data/lib/contrek/finder/node_cluster.rb +3 -1
- data/lib/contrek/finder/polygon_finder.rb +2 -0
- data/lib/contrek/finder/result.rb +2 -0
- data/lib/contrek/map/mercator_projection.rb +2 -0
- data/lib/contrek/matchers/matcher.rb +2 -0
- data/lib/contrek/matchers/matcher_hsb.rb +2 -0
- data/lib/contrek/matchers/value_not_matcher.rb +2 -0
- data/lib/contrek/reducers/linear_reducer.rb +2 -0
- data/lib/contrek/reducers/reducer.rb +2 -0
- data/lib/contrek/reducers/uniq_reducer.rb +2 -0
- data/lib/contrek/reducers/visvalingam_reducer.rb +2 -0
- data/lib/contrek/shared/result.rb +2 -0
- data/lib/contrek/version.rb +3 -1
- data/lib/contrek.rb +5 -0
- metadata +11 -5
|
@@ -21,7 +21,7 @@ Polyline::Polyline(Tile* tile, const std::vector<Point*>& polygon, const std::op
|
|
|
21
21
|
tile(tile)
|
|
22
22
|
{ if (bounds.has_value()) {
|
|
23
23
|
min_x = bounds->min_x;
|
|
24
|
-
|
|
24
|
+
max_x_ = bounds->max_x;
|
|
25
25
|
min_y_ = bounds->min_y;
|
|
26
26
|
max_y_ = bounds->max_y;
|
|
27
27
|
} else {
|
|
@@ -32,17 +32,17 @@ Polyline::Polyline(Tile* tile, const std::vector<Point*>& polygon, const std::op
|
|
|
32
32
|
|
|
33
33
|
int Polyline::width() {
|
|
34
34
|
if (raw_.empty()) return 0;
|
|
35
|
-
return(
|
|
35
|
+
return(max_x_ - min_x);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
bool Polyline::boundary() {
|
|
39
|
-
return( tile->tg_border(Point{min_x, 0}) || tile->tg_border(Point{
|
|
39
|
+
return( tile->tg_border(Point{min_x, 0}) || tile->tg_border(Point{max_x_, 0}));
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
void Polyline::find_boundary() {
|
|
43
43
|
if (raw_.empty()) return;
|
|
44
44
|
min_x = std::numeric_limits<int>::max();
|
|
45
|
-
|
|
45
|
+
max_x_ = -std::numeric_limits<int>::max();
|
|
46
46
|
min_y_ = std::numeric_limits<int>::max();
|
|
47
47
|
max_y_ = -std::numeric_limits<int>::max();
|
|
48
48
|
for (Point* p : raw_) {
|
|
@@ -50,7 +50,7 @@ void Polyline::find_boundary() {
|
|
|
50
50
|
int x = p->x;
|
|
51
51
|
int y = p->y;
|
|
52
52
|
if (x < min_x) min_x = x;
|
|
53
|
-
if (x >
|
|
53
|
+
if (x > max_x_) max_x_ = x;
|
|
54
54
|
if (y < min_y_) min_y_ = y;
|
|
55
55
|
if (y > max_y_) max_y_ = y;
|
|
56
56
|
}
|
|
@@ -98,7 +98,7 @@ std::string Polyline::named() {
|
|
|
98
98
|
|
|
99
99
|
void Polyline::fill_bounds(RectBounds& target_bounds) const {
|
|
100
100
|
target_bounds.min_x = this->min_x;
|
|
101
|
-
target_bounds.max_x = this->
|
|
101
|
+
target_bounds.max_x = this->max_x_;
|
|
102
102
|
target_bounds.min_y = this->min_y_;
|
|
103
103
|
target_bounds.max_y = this->max_y_;
|
|
104
104
|
}
|
|
@@ -40,10 +40,11 @@ class Polyline : public Partitionable {
|
|
|
40
40
|
int width();
|
|
41
41
|
Tile *tile = nullptr;
|
|
42
42
|
Shape* shape = nullptr;
|
|
43
|
-
std::vector<Point
|
|
43
|
+
const std::vector<Point*>& raw() const { return raw_; }
|
|
44
44
|
const std::vector<Part*>& parts() const { return parts_; }
|
|
45
45
|
const int max_y() const { return max_y_; }
|
|
46
46
|
const int min_y() const { return min_y_; }
|
|
47
|
+
const int max_x() const { return max_x_; }
|
|
47
48
|
void clear();
|
|
48
49
|
bool is_empty();
|
|
49
50
|
bool any_ancients = false;
|
|
@@ -56,7 +57,7 @@ class Polyline : public Partitionable {
|
|
|
56
57
|
|
|
57
58
|
private:
|
|
58
59
|
std::vector<Point*> raw_;
|
|
59
|
-
int min_x,
|
|
60
|
+
int min_x, max_x_, min_y_, max_y_;
|
|
60
61
|
void find_boundary();
|
|
61
62
|
uint32_t flags_ = 0;
|
|
62
63
|
std::string named_;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* StreamingMerger.cpp
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025-2026 Emanuele Cesaroni
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the GNU Affero General Public License v3 (AGPLv3).
|
|
7
|
+
* See the LICENSE file in this directory for the full license text.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#include "StreamingMerger.h"
|
|
11
|
+
#include <sstream>
|
|
12
|
+
#include <algorithm>
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <string>
|
|
15
|
+
|
|
16
|
+
StreamingMerger::StreamingMerger(int number_of_threads,
|
|
17
|
+
std::vector<std::string>* options,
|
|
18
|
+
std::ofstream* stream_to,
|
|
19
|
+
int total_width, int total_height)
|
|
20
|
+
: VerticalMerger(number_of_threads, options), stream(stream_to), total_width(total_width), total_height(total_height) {
|
|
21
|
+
if (!stream) {
|
|
22
|
+
throw std::invalid_argument("Streaming requires a valid destination output. stream_to cannot be null.");
|
|
23
|
+
}
|
|
24
|
+
if (total_width <= 0 || total_height <= 0) {
|
|
25
|
+
throw std::invalid_argument("Streaming requires valid canvas dimensions (width and height must be > 0).");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void StreamingMerger::add_tile(ProcessResult& result, bool flush)
|
|
30
|
+
{ VerticalMerger::add_tile(result);
|
|
31
|
+
if (tiles_.size() == 2) {
|
|
32
|
+
this->process_tiles();
|
|
33
|
+
this->tiles_.queue_push(this->whole_tile);
|
|
34
|
+
this->stream_polygons(this->whole_tile, flush);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
ProcessResult* StreamingMerger::process_info() {
|
|
39
|
+
ProcessResult *pr = VerticalMerger::process_info();
|
|
40
|
+
pr->groups = this->moved;
|
|
41
|
+
return(pr);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void StreamingMerger::stream_polygons(Tile* tile, bool flush) {
|
|
45
|
+
ensure_header();
|
|
46
|
+
if (int tile_end_x = tile->end_x(); true) {
|
|
47
|
+
tile->shapes().erase(
|
|
48
|
+
std::remove_if(tile->shapes().begin(), tile->shapes().end(), [this, flush, tile_end_x](const Shape* shape) {
|
|
49
|
+
if (flush || shape->outer_polyline->max_x() < (tile_end_x - 1)) {
|
|
50
|
+
this->moved++;
|
|
51
|
+
this->stream_raw_polygon(shape);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}),
|
|
56
|
+
tile->shapes().end());
|
|
57
|
+
}
|
|
58
|
+
if (flush) {
|
|
59
|
+
ensure_footer();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void StreamingMerger::stream_raw_polygon(const Shape* shape) {
|
|
64
|
+
std::ostringstream outer_oss;
|
|
65
|
+
const std::vector<Point*> points = shape->outer_polyline->raw();
|
|
66
|
+
for (size_t i = 0; i < points.size(); ++i) {
|
|
67
|
+
outer_oss << points[i]->y << "," << points[i]->x;
|
|
68
|
+
if (i < points.size() - 1) outer_oss << " ";
|
|
69
|
+
}
|
|
70
|
+
*stream << svg_outer_polygon_string(outer_oss.str());
|
|
71
|
+
|
|
72
|
+
for (const auto& inner_polyline : shape->inner_polylines) {
|
|
73
|
+
std::ostringstream inner_oss;
|
|
74
|
+
const std::vector<Point*> inner_points = inner_polyline->raw();
|
|
75
|
+
for (size_t i = 0; i < inner_points.size(); ++i) {
|
|
76
|
+
inner_oss << inner_points[i]->y << "," << inner_points[i]->x;
|
|
77
|
+
if (i < inner_points.size() - 1) inner_oss << " ";
|
|
78
|
+
}
|
|
79
|
+
*stream << svg_inner_polygon_string(inner_oss.str());
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void StreamingMerger::ensure_header() {
|
|
84
|
+
if (stream && stream->tellp() == 0) {
|
|
85
|
+
*stream << svg_header_string();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
void StreamingMerger::ensure_footer() {
|
|
90
|
+
if (stream) {
|
|
91
|
+
*stream << svg_footer_string();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
std::string StreamingMerger::svg_css() {
|
|
96
|
+
return ".out{fill:none;stroke:red;stroke-width:1;}.in{fill:none;stroke:green;stroke-width:1;}.out:hover{stroke:yellow;}";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
std::string StreamingMerger::svg_header_string() {
|
|
100
|
+
return "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"" + std::to_string(total_width) +
|
|
101
|
+
"\" height=\"" + std::to_string(total_height) + "\"><style>" + svg_css() + "</style>";
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
std::string StreamingMerger::svg_footer_string() {
|
|
105
|
+
return "</svg>";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
std::string StreamingMerger::svg_outer_polygon_string(std::string_view points) {
|
|
109
|
+
return "<polygon points=\"" + std::string(points) + "\" class=\"out\"/>";
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
std::string StreamingMerger::svg_inner_polygon_string(std::string_view points) {
|
|
113
|
+
return "<polygon points=\"" + std::string(points) + "\" class=\"in\"/>";
|
|
114
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* StreamingMerger.h
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025-2026 Emanuele Cesaroni
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the GNU Affero General Public License v3 (AGPLv3).
|
|
7
|
+
* See the LICENSE file in this directory for the full license text.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#pragma once
|
|
11
|
+
#include "VerticalMerger.h"
|
|
12
|
+
#include <fstream>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <string_view>
|
|
15
|
+
#include <stdexcept>
|
|
16
|
+
#include <vector>
|
|
17
|
+
|
|
18
|
+
class StreamingMerger : public VerticalMerger {
|
|
19
|
+
private:
|
|
20
|
+
std::ofstream* stream;
|
|
21
|
+
int total_width;
|
|
22
|
+
int total_height;
|
|
23
|
+
int moved = 0;
|
|
24
|
+
void ensure_header();
|
|
25
|
+
void ensure_footer();
|
|
26
|
+
void stream_polygons(Tile* tile, bool flush = false);
|
|
27
|
+
void stream_raw_polygon(const Shape* shape);
|
|
28
|
+
virtual std::string svg_css();
|
|
29
|
+
virtual std::string svg_header_string();
|
|
30
|
+
virtual std::string svg_footer_string();
|
|
31
|
+
virtual std::string svg_outer_polygon_string(std::string_view points);
|
|
32
|
+
virtual std::string svg_inner_polygon_string(std::string_view points);
|
|
33
|
+
|
|
34
|
+
public:
|
|
35
|
+
StreamingMerger(int number_of_threads,
|
|
36
|
+
std::vector<std::string>* options,
|
|
37
|
+
std::ofstream* stream_to,
|
|
38
|
+
int total_width, int total_height);
|
|
39
|
+
void add_tile(ProcessResult& result, bool flush = false);
|
|
40
|
+
ProcessResult* process_info() override;
|
|
41
|
+
};
|
|
@@ -96,6 +96,8 @@
|
|
|
96
96
|
#include "PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.cpp"
|
|
97
97
|
#include "PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h"
|
|
98
98
|
#include "PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp"
|
|
99
|
+
#include "PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h"
|
|
100
|
+
#include "PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp"
|
|
99
101
|
#include "PolygonFinder/src/polygon/finder/concurrent/ShapePool.h"
|
|
100
102
|
#include "PolygonFinder/src/polygon/finder/concurrent/ShapePool.cpp"
|
|
101
103
|
extern "C" {
|
|
@@ -290,6 +292,36 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
|
|
|
290
292
|
|
|
291
293
|
} // namespace Rice::detail
|
|
292
294
|
|
|
295
|
+
struct OfstreamWrapper {
|
|
296
|
+
std::string path;
|
|
297
|
+
std::ofstream stream;
|
|
298
|
+
OfstreamWrapper(std::string p) : path(p), stream(p, std::ios::out) {}
|
|
299
|
+
void close() { stream.close(); }
|
|
300
|
+
bool closed() { return !stream.is_open(); }
|
|
301
|
+
void rewind() { /* noop */ }
|
|
302
|
+
std::string read() {
|
|
303
|
+
stream.flush();
|
|
304
|
+
std::ifstream in(path);
|
|
305
|
+
return std::string((std::istreambuf_iterator<char>(in)),
|
|
306
|
+
std::istreambuf_iterator<char>());
|
|
307
|
+
}
|
|
308
|
+
std::ofstream& get_stream() { return stream; }
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
StreamingMerger* create_streaming_merger(Object self,
|
|
312
|
+
int number_of_threads,
|
|
313
|
+
std::vector<std::string>* options,
|
|
314
|
+
Object stream_obj,
|
|
315
|
+
int total_width,
|
|
316
|
+
int total_height) {
|
|
317
|
+
OfstreamWrapper* wrapper = Rice::detail::From_Ruby<OfstreamWrapper*>().convert(stream_obj.value());
|
|
318
|
+
return new StreamingMerger(number_of_threads, options, &wrapper->get_stream(), total_width, total_height);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
OfstreamWrapper* create_ofstream(Object self, std::string path) {
|
|
322
|
+
return new OfstreamWrapper(path);
|
|
323
|
+
}
|
|
324
|
+
|
|
293
325
|
extern "C"
|
|
294
326
|
void Init_cpp_polygon_finder() {
|
|
295
327
|
#ifdef HAVE_TCMALLOC
|
|
@@ -384,9 +416,27 @@ void Init_cpp_polygon_finder() {
|
|
|
384
416
|
define_class<HorizontalMerger, Merger>("CPPHorizontalMerger")
|
|
385
417
|
.define_constructor(Constructor<HorizontalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true);
|
|
386
418
|
|
|
387
|
-
|
|
419
|
+
Data_Type<VerticalMerger> rb_cVerticalMerger =
|
|
388
420
|
define_class<VerticalMerger, Merger>("CPPVerticalMerger")
|
|
389
|
-
.define_constructor(Constructor<VerticalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true)
|
|
421
|
+
.define_constructor(Constructor<VerticalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true)
|
|
422
|
+
.define_method("add_tile", [](VerticalMerger& self, Object rb_result) {
|
|
423
|
+
ProcessResult pr = Rice::detail::ruby_result_to_process_result(rb_result);
|
|
424
|
+
self.add_tile(pr);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
Data_Type<OfstreamWrapper> rb_cstd_ofstream = define_class<OfstreamWrapper>("CPPOfstream");
|
|
428
|
+
rb_cstd_ofstream.define_singleton_method("new", &create_ofstream);
|
|
429
|
+
rb_cstd_ofstream.define_method("close", [](OfstreamWrapper& self) { self.close(); });
|
|
430
|
+
rb_cstd_ofstream.define_method("closed?", [](OfstreamWrapper& self) { return self.closed(); });
|
|
431
|
+
rb_cstd_ofstream.define_method("rewind", [](OfstreamWrapper& self) { self.rewind(); });
|
|
432
|
+
rb_cstd_ofstream.define_method("read", [](OfstreamWrapper& self) { return self.read(); });
|
|
433
|
+
|
|
434
|
+
Data_Type<StreamingMerger> rb_cstreaming_merger = define_class<StreamingMerger, VerticalMerger>("CPPStreamingMerger");
|
|
435
|
+
rb_cstreaming_merger.define_method("add_tile", [](StreamingMerger& self, Object rb_result, bool flush) {
|
|
436
|
+
ProcessResult pr = Rice::detail::ruby_result_to_process_result(rb_result);
|
|
437
|
+
self.add_tile(pr, flush);
|
|
438
|
+
});
|
|
439
|
+
rb_cstreaming_merger.define_singleton_method("new", &create_streaming_merger);
|
|
390
440
|
|
|
391
441
|
Module mContrek = define_module("Contrek");
|
|
392
442
|
Module mCpp = define_module_under(mContrek, "Cpp");
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Contrek
|
|
4
|
+
module Cpp
|
|
5
|
+
class CPPConcurrentStreamingMerger < CPPStreamingMerger
|
|
6
|
+
def self.new(stream_to:, total_width:, total_height:, number_of_threads: 0, options: nil)
|
|
7
|
+
super(number_of_threads, options, stream_to, total_width, total_height)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Contrek
|
|
4
|
+
module Cpp
|
|
5
|
+
class CPPTempfile < CPPOfstream
|
|
6
|
+
def self.new(name)
|
|
7
|
+
require "tempfile"
|
|
8
|
+
tempfile = Tempfile.new(name)
|
|
9
|
+
instance = super(tempfile.path)
|
|
10
|
+
instance.instance_variable_set(:@tempfile, tempfile)
|
|
11
|
+
instance
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def path
|
|
15
|
+
@tempfile.path
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def close
|
|
19
|
+
super
|
|
20
|
+
@tempfile.close
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def unlink
|
|
24
|
+
@tempfile.unlink
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|