4 * Copyright (C) 2012 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcdisplayinfo.h"
26 #include "edlsession.h"
29 #include "motionscan.h"
30 #include "motionwindow.h"
32 #include "pluginserver.h"
34 MotionWindow::MotionWindow(MotionMain *plugin)
35 : PluginClientWindow(plugin, 800, 640, 800, 640, 0)
37 this->plugin = plugin;
40 MotionWindow::~MotionWindow()
44 void MotionWindow::create_objects()
47 int x1 = x, x2 = get_w() / 2;
50 add_subwindow(global = new MotionGlobal(plugin, this, x1, y));
51 add_subwindow(rotate = new MotionRotate(plugin, this, x2, y));
54 add_subwindow(title = new BC_Title(x1, y,
55 _("Translation search radius:\n(W/H Percent of image)")));
56 add_subwindow(global_range_w = new GlobalRange(plugin,
57 x1 + title->get_w() + 10, y,
58 &plugin->config.global_range_w));
59 add_subwindow(global_range_h = new GlobalRange(plugin,
60 x1 + title->get_w() + 10 + global_range_w->get_w(), y,
61 &plugin->config.global_range_h));
63 add_subwindow(title = new BC_Title(x2, y,
64 _("Rotation search radius:\n(Degrees)")));
65 add_subwindow(rotation_range = new RotationRange(plugin,
66 x2 + title->get_w() + 10, y));
69 add_subwindow(title = new BC_Title(x1, y,
70 _("Translation block size:\n(W/H Percent of image)")));
71 add_subwindow(global_block_w =
72 new BlockSize(plugin, x1 + title->get_w() + 10, y,
73 &plugin->config.global_block_w));
74 add_subwindow(global_block_h =
75 new BlockSize(plugin, x1 + title->get_w() + 10 +
76 global_block_w->get_w(), y,
77 &plugin->config.global_block_h));
79 // add_subwindow(title = new BC_Title(x2,
81 // _("Rotation block size:\n(W/H Percent of image)")));
82 // add_subwindow(rotation_block_w = new BlockSize(plugin,
83 // x2 + title->get_w() + 10,
85 // &plugin->config.rotation_block_w));
86 // add_subwindow(rotation_block_h = new BlockSize(plugin,
87 // x2 + title->get_w() + 10 + rotation_block_w->get_w(),
89 // &plugin->config.rotation_block_h));
92 add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:")));
93 add_subwindow(global_search_positions =
94 new GlobalSearchPositions(plugin, x1 + title->get_w() + 10, y, 80));
95 global_search_positions->create_objects();
97 add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:")));
98 add_subwindow(rotation_search_positions =
99 new RotationSearchPositions(plugin, x2 + title->get_w() + 10, y, 80));
100 rotation_search_positions->create_objects();
103 add_subwindow(title = new BC_Title(x, y, _("Translation direction:")));
104 add_subwindow(track_direction = new TrackDirection(plugin,
106 x + title->get_w() + 10,
108 track_direction->create_objects();
111 add_subwindow(title = new BC_Title(x2, y, _("Tracking file:")));
112 add_subwindow(tracking_file = new MotionTrackingFile(plugin,
113 plugin->config.tracking_file, this, x2+title->get_w() + 20, y));
116 add_subwindow(title = new BC_Title(x, y + 10, _("Block X:")));
117 add_subwindow(block_x =
118 new MotionBlockX(plugin, this, x + title->get_w() + 10, y));
119 add_subwindow(block_x_text =
120 new MotionBlockXText(plugin, this,
121 x + title->get_w() + 10 + block_x->get_w() + 10, y + 10));
124 add_subwindow(title = new BC_Title(x2, y, _("Rotation center:")));
125 add_subwindow(rotation_center =
126 new RotationCenter(plugin, x2 + title->get_w() + 10, y));
129 add_subwindow(title = new BC_Title(x2, y + 10, _("Maximum angle offset:")));
130 add_subwindow(rotate_magnitude =
131 new MotionRMagnitude(plugin, x2 + title->get_w() + 10, y));
134 add_subwindow(title = new BC_Title(x2, y + 10, _("Rotation settling speed:")));
135 add_subwindow(rotate_return_speed =
136 new MotionRReturnSpeed(plugin, x2 + title->get_w() + 10, y));
138 add_subwindow(vectors = new MotionDrawVectors(plugin, this, x2, y));
141 add_subwindow(title = new BC_Title(x, y + 10, _("Block Y:")));
142 add_subwindow(block_y =
143 new MotionBlockY(plugin, this, x + title->get_w() + 10, y));
144 add_subwindow(block_y_text =
145 new MotionBlockYText(plugin, this,
146 x + title->get_w() + 10 + block_y->get_w() + 10, y + 10));
149 add_subwindow(title = new BC_Title(x, y + 10, _("Maximum absolute offset:")));
150 add_subwindow(magnitude = new MotionMagnitude(plugin,
151 x + title->get_w() + 10,
155 add_subwindow(title = new BC_Title(x, y + 10, _("Motion settling speed:")));
156 add_subwindow(return_speed =
157 new MotionReturnSpeed(plugin, x + title->get_w() + 10, y));
160 add_subwindow(track_single =
161 new TrackSingleFrame(plugin, this, x, y));
163 add_subwindow(track_previous =
164 new TrackPreviousFrame(plugin, this, x, y));
166 add_subwindow(previous_same =
167 new PreviousFrameSameBlock(plugin, this, x, y));
171 add_subwindow(title =
172 new BC_Title(x1=x2, y1, _("Frame number:")));
173 add_subwindow(track_frame_number =
174 new TrackFrameNumber(plugin, this, x1 += title->get_w(), y1));
175 if(plugin->config.tracking_object != MotionScan::TRACK_SINGLE)
176 track_frame_number->disable();
178 add_subwindow(addtrackedframeoffset =
179 new AddTrackedFrameOffset(plugin, this, x1=x2, y1+=track_frame_number->get_h()));
180 int pef = client->server->mwindow->edl->session->video_every_frame;
181 add_subwindow(pef_title = new BC_Title(x1=x2+50, y1+=addtrackedframeoffset->get_h() + 5,
182 !pef ? _("For best results\n"
183 " Set: Play every frame\n"
184 " Preferences-> Playback-> Video Out") :
185 _("Currently using: Play every frame"), MEDIUMFONT,
186 !pef ? RED : GREEN));
188 add_subwindow(title = new BC_Title(x, y, _("Master layer:")));
189 add_subwindow(master_layer = new MasterLayer(plugin,
190 this, x + title->get_w() + 10, y));
191 master_layer->create_objects();
194 add_subwindow(title = new BC_Title(x, y, _("Action:")));
195 add_subwindow(action_type = new ActionType(plugin,
196 this, x + title->get_w() + 10, y));
197 action_type->create_objects();
200 add_subwindow(title = new BC_Title(x, y, _("Calculation:")));
201 add_subwindow(tracking_type = new TrackingType(plugin,
202 this, x + title->get_w() + 10, y));
203 tracking_type->create_objects();
208 void MotionWindow::update_mode()
210 global_range_w->update(plugin->config.global_range_w,
211 MIN_RADIUS, MAX_RADIUS);
212 global_range_h->update(plugin->config.global_range_h,
213 MIN_RADIUS, MAX_RADIUS);
214 rotation_range->update(plugin->config.rotation_range,
215 MIN_ROTATION, MAX_ROTATION);
216 vectors->update(plugin->config.draw_vectors);
217 tracking_file->update(plugin->config.tracking_file);
218 global->update(plugin->config.global);
219 rotate->update(plugin->config.rotate);
220 addtrackedframeoffset->update(plugin->config.addtrackedframeoffset);
223 MotionTrackingFile::MotionTrackingFile(MotionMain *plugin,
224 const char *filename, MotionWindow *gui, int x, int y)
225 : BC_TextBox(x, y, 150, 1, filename)
227 this->plugin = plugin;
231 int MotionTrackingFile::handle_event()
233 strcpy(plugin->config.tracking_file, get_text());
234 plugin->send_configure_change();
239 GlobalRange::GlobalRange(MotionMain *plugin,
240 int x, int y, int *value)
241 : BC_IPot(x, y, (int64_t)*value,
242 (int64_t)MIN_RADIUS, (int64_t)MAX_RADIUS)
244 this->plugin = plugin;
249 int GlobalRange::handle_event()
251 *value = (int)get_value();
252 plugin->send_configure_change();
259 RotationRange::RotationRange(MotionMain *plugin, int x, int y)
260 : BC_IPot(x, y, (int64_t)plugin->config.rotation_range,
261 (int64_t)MIN_ROTATION, (int64_t)MAX_ROTATION)
263 this->plugin = plugin;
267 int RotationRange::handle_event()
269 plugin->config.rotation_range = (int)get_value();
270 plugin->send_configure_change();
275 RotationCenter::RotationCenter(MotionMain *plugin, int x, int y)
276 : BC_IPot(x, y, (int64_t)plugin->config.rotation_center,
277 (int64_t)-MAX_ROTATION, (int64_t)MAX_ROTATION)
279 this->plugin = plugin;
283 int RotationCenter::handle_event()
285 plugin->config.rotation_center = (int)get_value();
286 plugin->send_configure_change();
291 BlockSize::BlockSize(MotionMain *plugin,
301 this->plugin = plugin;
306 int BlockSize::handle_event()
308 *value = (int)get_value();
309 plugin->send_configure_change();
314 GlobalSearchPositions::GlobalSearchPositions(MotionMain *plugin,
316 : BC_PopupMenu(x, y, w, "", 1)
318 this->plugin = plugin;
320 void GlobalSearchPositions::create_objects()
322 add_item(new BC_MenuItem("16"));
323 add_item(new BC_MenuItem("32"));
324 add_item(new BC_MenuItem("64"));
325 add_item(new BC_MenuItem("128"));
326 add_item(new BC_MenuItem("256"));
327 add_item(new BC_MenuItem("512"));
328 add_item(new BC_MenuItem("1024"));
329 add_item(new BC_MenuItem("2048"));
330 add_item(new BC_MenuItem("4096"));
331 add_item(new BC_MenuItem("8192"));
332 add_item(new BC_MenuItem("16384"));
333 add_item(new BC_MenuItem("32768"));
334 add_item(new BC_MenuItem("65536"));
335 add_item(new BC_MenuItem("131072"));
336 char string[BCTEXTLEN];
337 sprintf(string, "%d", plugin->config.global_positions);
341 int GlobalSearchPositions::handle_event()
343 plugin->config.global_positions = atoi(get_text());
344 plugin->send_configure_change();
349 RotationSearchPositions::RotationSearchPositions(MotionMain *plugin,
351 : BC_PopupMenu(x, y, w, "", 1)
353 this->plugin = plugin;
355 void RotationSearchPositions::create_objects()
357 add_item(new BC_MenuItem("4"));
358 add_item(new BC_MenuItem("8"));
359 add_item(new BC_MenuItem("16"));
360 add_item(new BC_MenuItem("32"));
361 char string[BCTEXTLEN];
362 sprintf(string, "%d", plugin->config.rotate_positions);
366 int RotationSearchPositions::handle_event()
368 plugin->config.rotate_positions = atoi(get_text());
369 plugin->send_configure_change();
374 MotionMagnitude::MotionMagnitude(MotionMain *plugin, int x, int y)
376 (int64_t)plugin->config.magnitude, (int64_t)0, (int64_t)100)
378 this->plugin = plugin;
381 int MotionMagnitude::handle_event()
383 plugin->config.magnitude = (int)get_value();
384 plugin->send_configure_change();
389 MotionReturnSpeed::MotionReturnSpeed(MotionMain *plugin, int x, int y)
391 (int64_t)plugin->config.return_speed, (int64_t)0, (int64_t)100)
393 this->plugin = plugin;
396 int MotionReturnSpeed::handle_event()
398 plugin->config.return_speed = (int)get_value();
399 plugin->send_configure_change();
405 AddTrackedFrameOffset::AddTrackedFrameOffset(MotionMain *plugin,
406 MotionWindow *gui, int x, int y)
407 : BC_CheckBox(x, y, plugin->config.addtrackedframeoffset,
408 _("Add (loaded) offset from tracked frame"))
410 this->plugin = plugin;
414 int AddTrackedFrameOffset::handle_event()
416 plugin->config.addtrackedframeoffset = get_value();
417 plugin->send_configure_change();
422 MotionRMagnitude::MotionRMagnitude(MotionMain *plugin, int x, int y)
424 (int64_t)plugin->config.rotate_magnitude, (int64_t)0, (int64_t)90)
426 this->plugin = plugin;
429 int MotionRMagnitude::handle_event()
431 plugin->config.rotate_magnitude = (int)get_value();
432 plugin->send_configure_change();
438 MotionRReturnSpeed::MotionRReturnSpeed(MotionMain *plugin, int x, int y)
440 (int64_t)plugin->config.rotate_return_speed, (int64_t)0, (int64_t)100)
442 this->plugin = plugin;
445 int MotionRReturnSpeed::handle_event()
447 plugin->config.rotate_return_speed = (int)get_value();
448 plugin->send_configure_change();
453 MotionGlobal::MotionGlobal(MotionMain *plugin,
454 MotionWindow *gui, int x, int y)
455 : BC_CheckBox(x, y, plugin->config.global, _("Track translation"))
457 this->plugin = plugin;
461 int MotionGlobal::handle_event()
463 plugin->config.global = get_value();
464 plugin->send_configure_change();
468 MotionRotate::MotionRotate(MotionMain *plugin,
469 MotionWindow *gui, int x, int y)
470 : BC_CheckBox(x, y, plugin->config.rotate, _("Track rotation"))
472 this->plugin = plugin;
476 int MotionRotate::handle_event()
478 plugin->config.rotate = get_value();
479 plugin->send_configure_change();
484 MotionBlockX::MotionBlockX(MotionMain *plugin,
485 MotionWindow *gui, int x, int y)
486 : BC_FPot(x, y, plugin->config.block_x, (float)0, (float)100)
488 this->plugin = plugin;
492 int MotionBlockX::handle_event()
494 plugin->config.block_x = get_value();
495 gui->block_x_text->update((float)plugin->config.block_x);
496 plugin->send_configure_change();
501 MotionBlockY::MotionBlockY(MotionMain *plugin,
507 (float)plugin->config.block_y,
511 this->plugin = plugin;
515 int MotionBlockY::handle_event()
517 plugin->config.block_y = get_value();
518 gui->block_y_text->update((float)plugin->config.block_y);
519 plugin->send_configure_change();
523 MotionBlockXText::MotionBlockXText(MotionMain *plugin,
524 MotionWindow *gui, int x, int y)
525 : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_x)
527 this->plugin = plugin;
532 int MotionBlockXText::handle_event()
534 plugin->config.block_x = atof(get_text());
535 gui->block_x->update(plugin->config.block_x);
536 plugin->send_configure_change();
543 MotionBlockYText::MotionBlockYText(MotionMain *plugin,
544 MotionWindow *gui, int x, int y)
545 : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_y)
547 this->plugin = plugin;
552 int MotionBlockYText::handle_event()
554 plugin->config.block_y = atof(get_text());
555 gui->block_y->update(plugin->config.block_y);
556 plugin->send_configure_change();
561 MotionDrawVectors::MotionDrawVectors(MotionMain *plugin,
562 MotionWindow *gui, int x, int y)
565 plugin->config.draw_vectors,
569 this->plugin = plugin;
572 int MotionDrawVectors::handle_event()
574 plugin->config.draw_vectors = get_value();
575 plugin->send_configure_change();
580 TrackSingleFrame::TrackSingleFrame(MotionMain *plugin,
586 plugin->config.tracking_object == MotionScan::TRACK_SINGLE,
587 _("Track single frame"))
589 this->plugin = plugin;
593 int TrackSingleFrame::handle_event()
595 plugin->config.tracking_object = MotionScan::TRACK_SINGLE;
596 gui->track_previous->update(0);
597 gui->previous_same->update(0);
598 gui->track_frame_number->enable();
599 plugin->send_configure_change();
603 TrackFrameNumber::TrackFrameNumber(MotionMain *plugin,
607 : BC_TextBox(x, y, 100, 1, plugin->config.track_frame)
609 this->plugin = plugin;
613 int TrackFrameNumber::handle_event()
615 plugin->config.track_frame = atol(get_text());
616 plugin->send_configure_change();
621 TrackPreviousFrame::TrackPreviousFrame(MotionMain *plugin,
627 plugin->config.tracking_object == MotionScan::TRACK_PREVIOUS,
628 _("Track previous frame"))
630 this->plugin = plugin;
633 int TrackPreviousFrame::handle_event()
635 plugin->config.tracking_object = MotionScan::TRACK_PREVIOUS;
636 gui->track_single->update(0);
637 gui->previous_same->update(0);
638 gui->track_frame_number->disable();
639 plugin->send_configure_change();
644 PreviousFrameSameBlock::PreviousFrameSameBlock(MotionMain *plugin,
650 plugin->config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK,
651 _("Previous frame same block"))
653 this->plugin = plugin;
656 int PreviousFrameSameBlock::handle_event()
658 plugin->config.tracking_object = MotionScan::PREVIOUS_SAME_BLOCK;
659 gui->track_single->update(0);
660 gui->track_previous->update(0);
661 gui->track_frame_number->disable();
662 plugin->send_configure_change();
667 MasterLayer::MasterLayer(MotionMain *plugin, MotionWindow *gui, int x, int y)
671 to_text(plugin->config.bottom_is_master))
673 this->plugin = plugin;
677 int MasterLayer::handle_event()
679 plugin->config.bottom_is_master = from_text(get_text());
680 plugin->send_configure_change();
684 void MasterLayer::create_objects()
686 add_item(new BC_MenuItem(to_text(0)));
687 add_item(new BC_MenuItem(to_text(1)));
690 int MasterLayer::from_text(char *text)
692 if(!strcmp(text, _("Top"))) return 0;
696 char* MasterLayer::to_text(int mode)
698 return mode ? _("Bottom") : _("Top");
701 int MasterLayer::calculate_w(MotionWindow *gui)
704 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0)));
705 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1)));
710 ActionType::ActionType(MotionMain *plugin, MotionWindow *gui, int x, int y)
714 to_text(plugin->config.action_type))
716 this->plugin = plugin;
720 int ActionType::handle_event()
722 plugin->config.action_type = from_text(get_text());
723 plugin->send_configure_change();
727 void ActionType::create_objects()
729 add_item(new BC_MenuItem(to_text(MotionScan::TRACK)));
730 add_item(new BC_MenuItem(to_text(MotionScan::TRACK_PIXEL)));
731 add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE)));
732 add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE_PIXEL)));
733 add_item(new BC_MenuItem(to_text(MotionScan::NOTHING)));
736 int ActionType::from_text(char *text)
738 if(!strcmp(text, _("Track Subpixel"))) return MotionScan::TRACK;
739 if(!strcmp(text, _("Track Pixel"))) return MotionScan::TRACK_PIXEL;
740 if(!strcmp(text, _("Stabilize Subpixel"))) return MotionScan::STABILIZE;
741 if(!strcmp(text, _("Stabilize Pixel"))) return MotionScan::STABILIZE_PIXEL;
742 //if(!strcmp(text, _("Do Nothing"))) return MotionScan::NOTHING;
743 return MotionScan::NOTHING;
746 char* ActionType::to_text(int mode)
750 case MotionScan::TRACK:
751 return _("Track Subpixel");
752 case MotionScan::TRACK_PIXEL:
753 return _("Track Pixel");
754 case MotionScan::STABILIZE:
755 return _("Stabilize Subpixel");
756 case MotionScan::STABILIZE_PIXEL:
757 return _("Stabilize Pixel");
759 case MotionScan::NOTHING:
760 return _("Do Nothing");
764 int ActionType::calculate_w(MotionWindow *gui)
767 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK)));
768 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK_PIXEL)));
769 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE)));
770 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE_PIXEL)));
771 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NOTHING)));
776 TrackingType::TrackingType(MotionMain *plugin, MotionWindow *gui, int x, int y)
780 to_text(plugin->config.tracking_type))
782 this->plugin = plugin;
786 int TrackingType::handle_event()
788 plugin->config.tracking_type = from_text(get_text());
789 plugin->send_configure_change();
793 void TrackingType::create_objects()
795 add_item(new BC_MenuItem(to_text(MotionScan::SAVE)));
796 add_item(new BC_MenuItem(to_text(MotionScan::LOAD)));
797 add_item(new BC_MenuItem(to_text(MotionScan::CALCULATE)));
798 add_item(new BC_MenuItem(to_text(MotionScan::NO_CALCULATE)));
801 int TrackingType::from_text(char *text)
803 if(!strcmp(text, _("Save coords to tracking file"))) return MotionScan::SAVE;
804 if(!strcmp(text, _("Load coords from tracking file"))) return MotionScan::LOAD;
805 if(!strcmp(text, _("Recalculate"))) return MotionScan::CALCULATE;
806 //if(!strcmp(text, _("Don't Calculate"))) return MotionScan::NO_CALCULATE;
807 return MotionScan::NO_CALCULATE;
810 char* TrackingType::to_text(int mode)
814 case MotionScan::SAVE: return _("Save coords to tracking file");
815 case MotionScan::LOAD: return _("Load coords from tracking file");
816 case MotionScan::CALCULATE: return _("Recalculate");
818 case MotionScan::NO_CALCULATE: return _("Don't Calculate");
822 int TrackingType::calculate_w(MotionWindow *gui)
825 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NO_CALCULATE)));
826 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::CALCULATE)));
827 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::SAVE)));
828 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::LOAD)));
833 TrackDirection::TrackDirection(MotionMain *plugin, MotionWindow *gui, int x, int y)
837 to_text(plugin->config.horizontal_only, plugin->config.vertical_only))
839 this->plugin = plugin;
843 int TrackDirection::handle_event()
845 from_text(&plugin->config.horizontal_only, &plugin->config.vertical_only, get_text());
846 plugin->send_configure_change();
850 void TrackDirection::create_objects()
852 add_item(new BC_MenuItem(to_text(1, 0)));
853 add_item(new BC_MenuItem(to_text(0, 1)));
854 add_item(new BC_MenuItem(to_text(0, 0)));
857 void TrackDirection::from_text(int *horizontal_only, int *vertical_only, char *text)
859 *horizontal_only = 0;
861 if(!strcmp(text, to_text(1, 0))) *horizontal_only = 1;
862 if(!strcmp(text, to_text(0, 1))) *vertical_only = 1;
865 char* TrackDirection::to_text(int horizontal_only, int vertical_only)
867 if(horizontal_only) return _("Horizontal only");
868 if(vertical_only) return _("Vertical only");
872 int TrackDirection::calculate_w(MotionWindow *gui)
875 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0)));
876 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1)));
877 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0)));