Skip to content

Commit 0526260

Browse files
authored
Merge pull request #9008 from The-OpenROAD-Project-staging/gui-multi-gif
gui: allow more than one animated gif to be generated at a time
2 parents f3cd476 + d225749 commit 0526260

File tree

8 files changed

+77
-51
lines changed

8 files changed

+77
-51
lines changed

src/gpl/src/graphicsImpl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -856,15 +856,16 @@ void GraphicsImpl::saveLabeledImageImpl(std::string_view path,
856856

857857
void GraphicsImpl::gifStart(std::string_view path)
858858
{
859-
gui::Gui::get()->gifStart(std::string(path));
859+
gif_key_ = gui::Gui::get()->gifStart(std::string(path));
860860
}
861861

862862
void GraphicsImpl::gifAddFrameImpl(const odb::Rect& region,
863863
int width_px,
864864
double dbu_per_pixel,
865865
std::optional<int> delay)
866866
{
867-
gui::Gui::get()->gifAddFrame(region, width_px, dbu_per_pixel, delay);
867+
gui::Gui::get()->gifAddFrame(
868+
gif_key_, region, width_px, dbu_per_pixel, delay);
868869
}
869870

870871
void GraphicsImpl::deleteLabel(std::string_view label_name)
@@ -874,7 +875,7 @@ void GraphicsImpl::deleteLabel(std::string_view label_name)
874875

875876
void GraphicsImpl::gifEnd()
876877
{
877-
gui::Gui::get()->gifEnd();
878+
gui::Gui::get()->gifEnd(gif_key_);
878879
}
879880

880881
} // namespace gpl

src/gpl/src/graphicsImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ class GraphicsImpl : public gpl::AbstractGraphics,
173173
gui::Chart* density_chart_{nullptr};
174174
gui::Chart* phi_chart_{nullptr};
175175
gui::Chart* stepLength_chart_{nullptr};
176-
bool debug_on_ = false;
176+
bool debug_on_{false};
177+
int gif_key_{0};
177178

178179
void initHeatmap();
179180
void drawNesterov(gui::Painter& painter);

src/gui/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,19 @@ save_histogram_image
165165

166166
This command can be used to generate an animated gif.
167167

168+
When used with -start this command returns an integer key that can be
169+
used to distinguish files if multiple are generated. That key can be
170+
provided when using -add or -end. If only a single file is being used
171+
the key can be ignored.
172+
168173
```tcl
169174
save_animated_gif
170175
-start|-add|-end
171176
[-resolution microns_per_pixel]
172177
[-area {x0 y0 x1 y1}]
173178
[-width width]
174179
[-delay delay]
180+
[-key key]
175181
[filename]
176182
```
177183

@@ -187,6 +193,7 @@ save_animated_gif
187193
| `-resolution`| resolution in microns per pixel to use when saving the image, default will match what the GUI has selected.|
188194
| `-width`| width of the output image in pixels, default will be computed from the resolution. Cannot be used with ``-resolution``.|
189195
| `-delay`| delay between frames in the GIF.|
196+
| `-key`| used to distinguish multiple GIF files (returned by -add).|
190197

191198
### Select Objects
192199

src/gui/include/gui/gui.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -824,12 +824,15 @@ class Gui
824824
const Selected& getInspectorSelection();
825825

826826
// GIF API
827-
void gifStart(const std::string& filename);
828-
void gifAddFrame(const odb::Rect& region = odb::Rect(),
827+
// Start returns the key for use by add and end. This allows multiple
828+
// gifs to be open at once.
829+
int gifStart(const std::string& filename);
830+
void gifAddFrame(int key,
831+
const odb::Rect& region = odb::Rect(),
829832
int width_px = 0,
830833
double dbu_per_pixel = 0,
831834
std::optional<int> delay = {});
832-
void gifEnd();
835+
void gifEnd(int key);
833836

834837
void setHeatMapSetting(const std::string& name,
835838
const std::string& option,
@@ -947,7 +950,7 @@ class Gui
947950
std::unique_ptr<PlacementDensityDataSource> placement_density_heat_map_;
948951
std::unique_ptr<PowerDensityDataSource> power_density_heat_map_;
949952

950-
std::unique_ptr<GIF> gif_;
953+
std::vector<std::unique_ptr<GIF>> gifs_;
951954
static constexpr int kDefaultGifDelay = 250;
952955

953956
std::string main_window_title_ = "OpenROAD";

src/gui/src/gui.cpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ bool Gui::TypeInfoComparator::operator()(const std::type_index& a,
14451445
#endif
14461446
}
14471447

1448-
void Gui::gifStart(const std::string& filename)
1448+
int Gui::gifStart(const std::string& filename)
14491449
{
14501450
if (!enabled()) {
14511451
logger_->error(utl::GUI, 49, "Cannot generate GIF without GUI enabled");
@@ -1455,24 +1455,29 @@ void Gui::gifStart(const std::string& filename)
14551455
logger_->error(utl::GUI, 81, "Filename is required to save a GIF.");
14561456
}
14571457

1458-
gif_ = std::make_unique<GIF>();
1459-
gif_->filename = filename;
1460-
gif_->writer = nullptr;
1458+
auto gif = std::make_unique<GIF>();
1459+
gif->filename = filename;
1460+
gifs_.emplace_back(std::move(gif));
1461+
return gifs_.size() - 1;
14611462
}
14621463

1463-
void Gui::gifAddFrame(const odb::Rect& region,
1464+
void Gui::gifAddFrame(const int key,
1465+
const odb::Rect& region,
14641466
int width_px,
14651467
double dbu_per_pixel,
14661468
std::optional<int> delay)
14671469
{
1468-
if (gif_ == nullptr) {
1470+
if (key >= gifs_.size() || gifs_[key] == nullptr) {
14691471
logger_->warn(utl::GUI, 51, "GIF not active");
14701472
return;
14711473
}
14721474

14731475
if (db_ == nullptr) {
14741476
logger_->error(utl::GUI, 50, "No design loaded.");
14751477
}
1478+
1479+
auto& gif = gifs_[key];
1480+
14761481
odb::Rect save_region = region;
14771482
const bool use_die_area = region.dx() == 0 || region.dy() == 0;
14781483
const bool is_offscreen
@@ -1504,64 +1509,65 @@ void Gui::gifAddFrame(const odb::Rect& region,
15041509
QImage img = main_window->getLayoutViewer()->createImage(
15051510
save_region, width_px, dbu_per_pixel);
15061511

1507-
if (gif_->writer == nullptr) {
1508-
gif_->writer = std::make_unique<GifWriter>();
1509-
gif_->width = img.width();
1510-
gif_->height = img.height();
1511-
GifBegin(gif_->writer.get(),
1512-
gif_->filename.c_str(),
1513-
gif_->width,
1514-
gif_->height,
1512+
if (gif->writer == nullptr) {
1513+
gif->writer = std::make_unique<GifWriter>();
1514+
gif->width = img.width();
1515+
gif->height = img.height();
1516+
GifBegin(gif->writer.get(),
1517+
gif->filename.c_str(),
1518+
gif->width,
1519+
gif->height,
15151520
delay.value_or(kDefaultGifDelay));
15161521
} else {
15171522
// scale IMG if not matched
1518-
img = img.scaled(gif_->width, gif_->height, Qt::KeepAspectRatio);
1523+
img = img.scaled(gif->width, gif->height, Qt::KeepAspectRatio);
15191524
}
15201525

1521-
std::vector<uint8_t> frame(gif_->width * gif_->height * 4, 0);
1526+
std::vector<uint8_t> frame(gif->width * gif->height * 4, 0);
15221527
for (int x = 0; x < img.width(); x++) {
1523-
if (x >= gif_->width) {
1528+
if (x >= gif->width) {
15241529
continue;
15251530
}
15261531
for (int y = 0; y < img.height(); y++) {
1527-
if (y >= gif_->height) {
1532+
if (y >= gif->height) {
15281533
continue;
15291534
}
15301535

15311536
const QRgb pixel = img.pixel(x, y);
1532-
const int frame_offset = (y * gif_->width + x) * 4;
1537+
const int frame_offset = (y * gif->width + x) * 4;
15331538
frame[frame_offset + 0] = qRed(pixel);
15341539
frame[frame_offset + 1] = qGreen(pixel);
15351540
frame[frame_offset + 2] = qBlue(pixel);
15361541
frame[frame_offset + 3] = qAlpha(pixel);
15371542
}
15381543
}
15391544

1540-
GifWriteFrame(gif_->writer.get(),
1545+
GifWriteFrame(gif->writer.get(),
15411546
frame.data(),
1542-
gif_->width,
1543-
gif_->height,
1547+
gif->width,
1548+
gif->height,
15441549
delay.value_or(kDefaultGifDelay));
15451550
}
15461551

1547-
void Gui::gifEnd()
1552+
void Gui::gifEnd(const int key)
15481553
{
1549-
if (gif_ == nullptr) {
1554+
if (key >= gifs_.size() || gifs_[key] == nullptr) {
15501555
logger_->warn(utl::GUI, 58, "GIF not active");
15511556
return;
15521557
}
15531558

1554-
if (gif_->writer == nullptr) {
1559+
auto& gif = gifs_[key];
1560+
if (gif->writer == nullptr) {
15551561
logger_->warn(utl::GUI,
15561562
107,
15571563
"Nothing to save to {}. No frames added to gif.",
1558-
gif_->filename);
1559-
gif_ = nullptr;
1564+
gif->filename);
1565+
gif = nullptr;
15601566
return;
15611567
}
15621568

1563-
GifEnd(gif_->writer.get());
1564-
gif_ = nullptr;
1569+
GifEnd(gif->writer.get());
1570+
gifs_[key] = nullptr;
15651571
}
15661572

15671573
class SafeApplication : public QApplication

src/gui/src/gui.i

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -817,16 +817,16 @@ void set_title(std::string title)
817817
gui->setMainWindowTitle(title);
818818
}
819819

820-
void gif_start(const char* filename)
820+
int gif_start(const char* filename)
821821
{
822822
if (!check_gui("gif_start")) {
823-
return;
823+
return 0;
824824
}
825825
auto gui = gui::Gui::get();
826-
gui->gifStart(filename);
826+
return gui->gifStart(filename);
827827
}
828828

829-
void gif_add(double xlo, double ylo, double xhi, double yhi, int width_px = 0, double dbu_per_pixel = 0, int delay = 0)
829+
void gif_add(int key, double xlo, double ylo, double xhi, double yhi, int width_px = 0, double dbu_per_pixel = 0, int delay = 0)
830830
{
831831
if (!check_gui("gif_add")) {
832832
return;
@@ -836,16 +836,16 @@ void gif_add(double xlo, double ylo, double xhi, double yhi, int width_px = 0, d
836836
if (delay > 0) {
837837
delay_pass = delay;
838838
}
839-
gui->gifAddFrame(make_rect(xlo, ylo, xhi, yhi), width_px, dbu_per_pixel, delay_pass);
839+
gui->gifAddFrame(key, make_rect(xlo, ylo, xhi, yhi), width_px, dbu_per_pixel, delay_pass);
840840
}
841841

842-
void gif_end()
842+
void gif_end(int key)
843843
{
844844
if (!check_gui("gif_end")) {
845845
return;
846846
}
847847
auto gui = gui::Gui::get();
848-
gui->gifEnd();
848+
gui->gifEnd(key);
849849
}
850850

851851
%} // inline

src/gui/src/gui.tcl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ sta::define_cmd_args "save_animated_gif" {-start|-add|-end \
142142
[-width width] \
143143
[-resolution microns_per_pixel] \
144144
[-delay delay] \
145+
[-key key] \
145146
[path]
146147
}
147148

148149
proc save_animated_gif { args } {
149150
sta::parse_key_args "save_animated_gif" args \
150-
keys {-area -width -resolution -delay} flags {-start -end -add}
151+
keys {-area -width -resolution -delay -key} flags {-start -end -add}
151152

152153
set resolution 0
153154
if { [info exists keys(-resolution)] } {
@@ -189,19 +190,24 @@ proc save_animated_gif { args } {
189190
set delay $keys(-delay)
190191
}
191192

193+
set key 0
194+
if { [info exists keys(-key)] } {
195+
set key $keys(-key)
196+
}
197+
192198
if { [info exists flags(-start)] } {
193199
sta::check_argc_eq1 "save_animated_gif" $args
194200
set path [lindex $args 0]
195201

196-
gui::gif_start $path
202+
return [gui::gif_start $path]
197203
} elseif { [info exists flags(-add)] } {
198204
sta::check_argc_eq0 "save_animated_gif" $args
199205

200-
gui::gif_add {*}$area $width $resolution $delay
206+
gui::gif_add $key {*}$area $width $resolution $delay
201207
} elseif { [info exists flags(-end)] } {
202208
sta::check_argc_eq0 "save_animated_gif" $args
203209

204-
gui::gif_end
210+
gui::gif_end $key
205211
} else {
206212
utl::error GUI 106 "-start, -end, or -add is required"
207213
}

src/gui/src/stub.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,17 @@ void initGui(Tcl_Interp* interp,
204204
Tcl_Eval(interp, enabled_supported.c_str());
205205
}
206206

207-
void Gui::gifStart(const std::string& filename)
207+
int Gui::gifStart(const std::string& filename)
208208
{
209+
return 0;
209210
}
210211

211-
void Gui::gifEnd()
212+
void Gui::gifEnd(const int key)
212213
{
213214
}
214215

215-
void Gui::gifAddFrame(const odb::Rect& region,
216+
void Gui::gifAddFrame(const int key,
217+
const odb::Rect& region,
216218
int width_px,
217219
double dbu_per_pixel,
218220
std::optional<int> delay)

0 commit comments

Comments
 (0)