DialogVideoDetails::DialogVideoDetails(agi::Context *c) : wxDialog(c->parent , -1, _("Video Details")) { auto width = c->videoController->GetWidth(); auto height = c->videoController->GetHeight(); auto framecount = c->videoController->GetLength(); auto fps = c->videoController->FPS(); boost::rational<int> ar(width, height); auto fg = new wxFlexGridSizer(2, 5, 10); auto make_field = [&](wxString const& name, wxString const& value) { fg->Add(new wxStaticText(this, -1, name), 0, wxALIGN_CENTRE_VERTICAL); fg->Add(new wxTextCtrl(this, -1, value, wxDefaultPosition, wxSize(300,-1), wxTE_READONLY), 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND); }; make_field(_("File name:"), c->videoController->GetVideoName().wstring()); make_field(_("FPS:"), wxString::Format("%.3f", fps.FPS())); make_field(_("Resolution:"), wxString::Format("%dx%d (%d:%d)", width, height, ar.numerator(), ar.denominator())); make_field(_("Length:"), wxString::Format(_("%d frames (%s)"), framecount, to_wx(AssTime(fps.TimeAtFrame(framecount - 1)).GetAssFormated(true)))); make_field(_("Decoder:"), to_wx(c->videoController->GetProvider()->GetDecoderName())); wxStaticBoxSizer *video_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Video")); video_sizer->Add(fg); auto main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(video_sizer, 1, wxALL|wxEXPAND, 5); main_sizer->Add(CreateSeparatedButtonSizer(wxOK), 0, wxALL|wxEXPAND, 5); SetSizerAndFit(main_sizer); CenterOnParent(); }
void log(agi::log::SinkMessage *sm) override { #ifndef _WIN32 tm tmtime; localtime_r(&sm->tv.tv_sec, &tmtime); auto log = wxString::Format("%c %02d:%02d:%02d %-6ld <%-25s> [%s:%s:%d] %s\n", agi::log::Severity_ID[sm->severity], (int)tmtime.tm_hour, (int)tmtime.tm_min, (int)tmtime.tm_sec, (long)sm->tv.tv_usec, sm->section, sm->file, sm->func, sm->line, to_wx(sm->message)); #else auto log = wxString::Format("%c %-6ld <%-25s> [%s:%s:%d] %s\n", agi::log::Severity_ID[sm->severity], sm->tv.tv_usec, sm->section, sm->file, sm->func, sm->line, to_wx(sm->message)); #endif if (wxIsMainThread()) text_ctrl->AppendText(log); else agi::dispatch::Main().Async([=]{ text_ctrl->AppendText(log); }); }
void VideoBox::UpdateTimeBoxes() { if (!context->videoController->IsLoaded()) return; int frame = context->videoController->GetFrameN(); int time = context->videoController->TimeAtFrame(frame, agi::vfr::EXACT); // Set the text box for frame number and time VideoPosition->SetValue(wxString::Format("%s - %d", AssTime(time).GetAssFormated(true), frame)); if (boost::binary_search(context->videoController->GetKeyFrames(), frame)) { // Set the background color to indicate this is a keyframe VideoPosition->SetBackgroundColour(to_wx(OPT_GET("Colour/Subtitle Grid/Background/Selection")->GetColor())); VideoPosition->SetForegroundColour(to_wx(OPT_GET("Colour/Subtitle Grid/Selection")->GetColor())); } else { VideoPosition->SetBackgroundColour(wxNullColour); VideoPosition->SetForegroundColour(wxNullColour); } AssDialogue *active_line = context->selectionController->GetActiveLine(); if (!active_line) VideoSubsPos->SetValue(""); else { VideoSubsPos->SetValue(wxString::Format( "%+dms; %+dms", time - active_line->Start, time - active_line->End)); } }
bool execute( const std::vector<std::string>& args, execution_info& info) { bp::pipe out_pipe(bp::create_pipe()), err_pipe(bp::create_pipe()); { bio::file_descriptor_sink out_sink(out_pipe.sink, bio::close_handle), err_sink(err_pipe.sink, bio::close_handle); bp::child c = bp::execute( bpi::set_args(args), bpi::bind_stdout(out_sink), bpi::bind_stderr(err_sink), bpi::close_stdin() ); info.exitcode = bp::wait_for_exit(c); } bio::file_descriptor_source out_source(out_pipe.source, bio::close_handle), err_source(err_pipe.source, bio::close_handle); string_sink out, err; bio::copy(out_source, out); bio::copy(err_source, err); info.cmd = to_wx(args[0]); info.out = to_wx(out.get()); info.err = to_wx(err.get()); return info.exitcode == 0; }
static Optional<Size> deserialize_size(const utf8_string& str){ wxString wxStr(to_wx(str)); wxArrayString strs = wxSplit(to_wx(str), ',', '\0'); if (strs.GetCount() != 2){ return {}; } long width; if (!strs[0].ToLong(&width)){ return {}; } if (width <= 0){ return {}; } long height; if (!strs[1].ToLong(&height)){ return {}; } if (height <= 0){ return {}; } return {Size(static_cast<coord>(width), static_cast<coord>(height))}; }
wxString GetEncoding(wxString const& filename) { agi::charset::CharsetListDetected list; try { list = agi::charset::DetectAll(from_wx(filename)); } catch (const agi::charset::UnknownCharset&) { /// @todo If the charset is unknown we need to display a complete list of character sets. } if (list.size() == 1) { auto charset = list.begin(); LOG_I("charset/file") << filename << " (" << charset->second << ")"; return to_wx(charset->second); } wxArrayString choices; std::string log_choice; for (auto const& charset : list) { choices.push_back(to_wx(charset.second)); log_choice.append(" " + charset.second); } LOG_I("charset/file") << filename << " (" << log_choice << ")"; int choice = wxGetSingleChoiceIndex(_("Aegisub could not narrow down the character set to a single one.\nPlease pick one below:"),_("Choose character set"),choices); if (choice == -1) throw "Canceled"; return choices[choice]; }
void LatexPreviewWindow::OnAboutClick( wxCommandEvent& event ) { wxtk::AboutBox about(this); about.SetDescription( to_wx("Clever text describing the application. Not.") ); about.SetBigIcon( GetIconResource(wxT("icon1.xpm")) ); about.SetAppname( to_wx("wxLatexPreview\nVersion 1.2") ); about.SetTitle( to_wx("About wxLatexPreview") ); about.SetCopyright( to_wx("(C) 2010-2012 Thomas Gläßle") ); about.ShowModal(); }
bool StringBinder::TransferToWindow() { wxWindow *window = GetWindow(); if (wxTextCtrl *ctrl = dynamic_cast<wxTextCtrl*>(window)) ctrl->SetValue(to_wx(*value)); else if (wxComboBox *ctrl = dynamic_cast<wxComboBox*>(window)) ctrl->SetValue(to_wx(*value)); else throw agi::InternalError("Unsupported control type"); return true; }
void DialogSpellChecker::SetWord(std::string const& word) { orig_word->SetValue(to_wx(word)); wxArrayString suggestions = to_wx(spellchecker->GetSuggestions(word)); replace_word->SetValue(suggestions.size() ? suggestions[0] : to_wx(word)); suggest_list->Clear(); suggest_list->Append(suggestions); context->textSelectionController->SetSelection(word_start, word_start + word_len); context->textSelectionController->SetInsertionPoint(word_start + word_len); add_button->Enable(spellchecker->CanAddWord(word)); }
void DialogStyling::OnActiveLineChanged(AssDialogue *new_line) { if (!new_line) return; active_line = new_line; current_line_text->SetValue(to_wx(active_line->Text)); style_name->SetValue(to_wx(active_line->Style)); style_name->SetSelection(0, active_line->Style.get().size()); style_name->SetFocus(); style_list->SetStringSelection(to_wx(active_line->Style)); if (auto_seek->IsChecked() && IsActive()) c->videoController->JumpToTime(active_line->Start); }
void DialogAttachments::UpdateList() { listView->ClearAll(); listView->InsertColumn(0, _("Attachment name"), wxLIST_FORMAT_LEFT, 280); listView->InsertColumn(1, _("Size"), wxLIST_FORMAT_LEFT, 100); listView->InsertColumn(2, _("Group"), wxLIST_FORMAT_LEFT, 100); for (auto& attach : ass->Attachments) { int row = listView->GetItemCount(); listView->InsertItem(row, to_wx(attach.GetFileName(true))); listView->SetItem(row, 1, PrettySize(attach.GetSize())); listView->SetItem(row, 2, to_wx(attach.GroupHeader())); } }
void DialogAttachments::OnExtract(wxCommandEvent &) { int i = listView->GetFirstSelected(); if (i == -1) return; agi::fs::path path; bool fullPath = false; // Multiple or single? if (listView->GetNextSelected(i) != -1) path = wxDirSelector(_("Select the path to save the files to:"), to_wx(OPT_GET("Path/Fonts Collector Destination")->GetString())).c_str(); else { path = SaveFileSelector( _("Select the path to save the file to:"), "Path/Fonts Collector Destination", ass->Attachments[i].GetFileName(), ".ttf", "Font Files (*.ttf)|*.ttf", this); fullPath = true; } if (path.empty()) return; // Loop through items in list while (i != -1) { auto& attach = ass->Attachments[i]; attach.Extract(fullPath ? path : path/attach.GetFileName()); i = listView->GetNextSelected(i); } }
void OptionPage::OptionBrowse(wxFlexGridSizer *flex, const wxString &name, const char *opt_name, wxControl *enabler, bool do_enable) { parent->AddChangeableOption(opt_name); const auto opt = OPT_GET(opt_name); if (opt->GetType() != agi::OptionType::String) throw agi::InternalError("Option must be agi::OptionType::String for BrowseButton."); auto text = new wxTextCtrl(this, -1 , to_wx(opt->GetString())); text->SetMinSize(wxSize(160, -1)); text->Bind(wxEVT_TEXT, StringUpdater(opt_name, parent)); auto browse = new wxButton(this, -1, _("Browse...")); browse->Bind(wxEVT_BUTTON, std::bind(browse_button, text)); auto button_sizer = new wxBoxSizer(wxHORIZONTAL); button_sizer->Add(text, wxSizerFlags(1).Expand()); button_sizer->Add(browse, wxSizerFlags().Expand()); Add(flex, name, button_sizer); if (enabler) { if (do_enable) { EnableIfChecked(enabler, text); EnableIfChecked(enabler, browse); } else { DisableIfChecked(enabler, text); DisableIfChecked(enabler, browse); } } }
SubsController::SubsController(agi::Context *context) : context(context) , undo_connection(context->ass->AddUndoManager(&SubsController::OnCommit, this)) , commit_id(0) , saved_commit_id(0) , autosaved_commit_id(0) { autosave_timer_changed(&autosave_timer); OPT_SUB("App/Auto/Save", autosave_timer_changed, &autosave_timer); OPT_SUB("App/Auto/Save Every Seconds", autosave_timer_changed, &autosave_timer); autosave_timer.Bind(wxEVT_TIMER, [=](wxTimerEvent&) { try { auto fn = AutoSave(); if (!fn.empty()) StatusTimeout(wxString::Format(_("File backup saved as \"%s\"."), fn.wstring())); } catch (const agi::Exception& err) { StatusTimeout(to_wx("Exception when attempting to autosave file: " + err.GetMessage())); } catch (...) { StatusTimeout("Unhandled exception when attempting to autosave file."); } }); }
void DialogShiftTimes::OnHistoryClick(wxCommandEvent &evt) { size_t entry = evt.GetInt(); if (entry >= history->size()) return; json::Object& obj = (*history)[entry]; if (obj["is by time"]) { shift_time->SetTime(AssTime((std::string)obj["amount"])); shift_by_time->SetValue(true); OnByTime(evt); } else { shift_frames->SetValue(to_wx(obj["amount"])); if (shift_by_frames->IsEnabled()) { shift_by_frames->SetValue(true); OnByFrames(evt); } } if (obj["is backward"]) shift_backward->SetValue(true); else shift_forward->SetValue(true); selection_mode->SetSelection((int64_t)obj["mode"]); time_fields->SetSelection((int64_t)obj["fields"]); }
void TimeEdit::OnChar(wxKeyEvent &event) { event.Skip(); if (byFrame || insert) return; int key = event.GetUnicodeKey(); if ((key < '0' || key > '9') && key != ';' && key != '.' && key != ',') return; event.Skip(false); long start = GetInsertionPoint(); std::string text = from_wx(GetValue()); // Cursor is at the end so do nothing if (start >= (long)text.size()) return; // If the cursor is at punctuation, move it forward to the next digit if (text[start] == ':' || text[start] == '.' || text[start] == ',') ++start; // : and . hop over punctuation but never insert anything if (key == ':' || key == ';' || key == '.' || key == ',') { SetInsertionPoint(start); return; } // Overwrite the digit text[start] = (char)key; time = text; SetValue(to_wx(time.GetAssFormated())); SetInsertionPoint(start + 1); }
void OptionPage::OptionChoice(wxFlexGridSizer *flex, const wxString &name, const wxArrayString &choices, const char *opt_name) { parent->AddChangeableOption(opt_name); const auto opt = OPT_GET(opt_name); auto cb = new wxComboBox(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY | wxCB_DROPDOWN); Add(flex, name, cb); switch (opt->GetType()) { case agi::OptionType::Int: { int val = opt->GetInt(); cb->Select(val < (int)choices.size() ? val : 0); cb->Bind(wxEVT_COMBOBOX, IntCBUpdater(opt_name, parent)); break; } case agi::OptionType::String: { wxString val(to_wx(opt->GetString())); if (cb->FindString(val) != wxNOT_FOUND) cb->SetStringSelection(val); else if (!choices.empty()) cb->SetSelection(0); cb->Bind(wxEVT_COMBOBOX, StringUpdater(opt_name, parent)); break; } default: throw agi::InternalError("Unsupported type"); } }
void DialogSearchReplace::FindReplace(bool (SearchReplaceEngine::*func)()) { TransferDataFromWindow(); if (settings->find.empty()) return; c->search->Configure(*settings); try { (c->search->*func)(); } catch (std::exception const& e) { wxMessageBox(to_wx(e.what()), "Error", wxOK | wxICON_ERROR | wxCENTER, this); return; } config::mru->Add("Find", settings->find); if (has_replace) config::mru->Add("Replace", settings->replace_with); OPT_SET("Tool/Search Replace/Match Case")->SetBool(settings->match_case); OPT_SET("Tool/Search Replace/RegExp")->SetBool(settings->use_regex); OPT_SET("Tool/Search Replace/Skip Comments")->SetBool(settings->ignore_comments); OPT_SET("Tool/Search Replace/Skip Tags")->SetBool(settings->skip_tags); OPT_SET("Tool/Search Replace/Field")->SetInt(static_cast<int>(settings->field)); OPT_SET("Tool/Search Replace/Affect")->SetInt(static_cast<int>(settings->limit_to)); UpdateDropDowns(); }
void Project::DoLoadAudio(agi::fs::path const& path, bool quiet) { if (!progress) progress = new DialogProgress(context->parent); try { try { audio_provider = GetAudioProvider(path, *context->path, progress); } catch (agi::UserCancelException const&) { return; } catch (...) { config::mru->Remove("Audio", path); throw; } } catch (agi::fs::FileNotFound const& e) { return ShowError(_("The audio file was not found: ") + to_wx(e.GetMessage())); } catch (agi::AudioDataNotFound const& e) { if (quiet) { LOG_D("video/open/audio") << "File " << video_file << " has no audio data: " << e.GetMessage(); return; } else return ShowError(_("None of the available audio providers recognised the selected file as containing audio data.\n\nThe following providers were tried:\n") + to_wx(e.GetMessage())); } catch (agi::AudioProviderError const& e) { return ShowError(_("None of the available audio providers have a codec available to handle the selected file.\n\nThe following providers were tried:\n") + to_wx(e.GetMessage())); } catch (agi::Exception const& e) { return ShowError(e.GetMessage()); } SetPath(audio_file, "?audio", "Audio", path); AnnounceAudioProviderModified(audio_provider.get()); }
void DialogAttachments::OnAttachFont(wxCommandEvent &) { wxFileDialog diag(this, _("Choose file to be attached"), to_wx(OPT_GET("Path/Fonts Collector Destination")->GetString()), "", "Font Files (*.ttf)|*.ttf", wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE); AttachFile(diag, _("attach font file")); }
Optional<FilePath> make_absolute_file_path(const utf8_string& path){ wxFileName pathWX(to_wx(path)); if (!pathWX.IsOk()){ return no_option(); } pathWX = absoluted(pathWX); return option(FilePath::FromAbsoluteWx(pathWX)); }
void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, const AssDialogue *prev, const AssDialogue *line) const { // If it doesn't start at the end of previous, add blank if (prev && prev->End != line->Start) { wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample"); node->AddAttribute("sampleTime", to_wx("0" + prev->End.GetAssFormated(true))); node->AddAttribute("xml:space", "preserve"); root->AddChild(node); node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "", "")); } // Generate and insert node wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample"); node->AddAttribute("sampleTime", to_wx("0" + line->Start.GetAssFormated(true))); node->AddAttribute("xml:space", "preserve"); root->AddChild(node); node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "", to_wx(line->Text))); }
void AegisubLocale::Init(std::string const& language) { wxTranslations *translations = GetTranslations(); translations->SetLanguage(to_wx(language)); translations->AddCatalog(AEGISUB_CATALOG); translations->AddStdCatalog(); setlocale(LC_NUMERIC, "C"); setlocale(LC_CTYPE, "C"); active_language = language; }
bool Project::DoLoadVideo(agi::fs::path const& path) { if (!progress) progress = new DialogProgress(context->parent); try { auto old_matrix = context->ass->GetScriptInfo("YCbCr Matrix"); video_provider = agi::make_unique<AsyncVideoProvider>(path, old_matrix, context->videoController.get(), progress); } catch (agi::UserCancelException const&) { return false; } catch (agi::fs::FileSystemError const& err) { config::mru->Remove("Video", path); ShowError(to_wx(err.GetMessage())); return false; } catch (VideoProviderError const& err) { ShowError(to_wx(err.GetMessage())); return false; } AnnounceVideoProviderModified(video_provider.get()); UpdateVideoProperties(context->ass.get(), video_provider.get(), context->parent); video_provider->LoadSubtitles(context->ass.get()); timecodes = video_provider->GetFPS(); keyframes = video_provider->GetKeyFrames(); timecodes_file.clear(); keyframes_file.clear(); SetPath(video_file, "?video", "Video", path); std::string warning = video_provider->GetWarning(); if (!warning.empty()) wxMessageBox(to_wx(warning), "Warning", wxICON_WARNING | wxOK); video_has_subtitles = false; if (agi::fs::HasExtension(path, "mkv")) video_has_subtitles = MatroskaWrapper::HasSubtitles(path); AnnounceKeyframesModified(keyframes); AnnounceTimecodesModified(timecodes); return true; }
static wxString get_history_string(json::Object &obj) { wxString filename = to_wx(obj["filename"]); if (filename.empty()) filename = _("unsaved"); wxString shift_amount(to_wx(obj["amount"])); if (!obj["is by time"]) shift_amount = wxString::Format(_("%s frames"), shift_amount); wxString shift_direction = obj["is backward"] ? _("backward") : _("forward"); int64_t time_field = obj["fields"]; wxString fields = time_field == 0 ? _("s+e") : time_field == 1 ? _("s") : _("e") ; json::Array const& sel = obj["selection"]; wxString lines; int64_t sel_mode = obj["mode"]; if (sel_mode == 0) lines = _("all"); else if (sel_mode == 2) lines = wxString::Format(_("from %d onward"), (int)(int64_t)sel.front()["start"]); else { lines += _("sel "); for (auto it = sel.begin(); it != sel.end(); ++it) { int beg = (int64_t)(*it)["start"]; int end = (int64_t)(*it)["end"]; if (beg == end) lines += std::to_wstring(beg); else lines += wxString::Format("%d-%d", beg, end); if (it + 1 != sel.end()) lines += ";"; } } return wxString::Format("%s, %s %s, %s, %s", filename, shift_amount, shift_direction, fields, lines); }
void DialogSpellChecker::Replace() { AssDialogue *active_line = context->selectionController->GetActiveLine(); // Only replace if the user hasn't changed the selection to something else if (to_wx(active_line->Text.get().substr(word_start, word_len)) == orig_word->GetValue()) { std::string text = active_line->Text; text.replace(word_start, word_len, from_wx(replace_word->GetValue())); active_line->Text = text; context->ass->Commit(_("spell check replace"), AssFile::COMMIT_DIAG_TEXT); context->textSelectionController->SetInsertionPoint(word_start + replace_word->GetValue().size()); } }
void DialogStyling::OnActivate(wxActivateEvent &) { if (!IsActive()) return; play_video->Enable(c->videoController->IsLoaded()); play_audio->Enable(c->audioController->IsAudioOpen()); style_list->Set(to_wx(c->ass->GetStyles())); if (auto_seek->IsChecked()) c->videoController->JumpToTime(active_line->Start); style_name->SetFocus(); }
void DialogExport::OnProcess(wxCommandEvent &) { if (!TransferDataFromWindow()) return; auto filename = SaveFileSelector(_("Export subtitles file"), "", "", "", to_wx(SubtitleFormat::GetWildcards(1)), this); if (filename.empty()) return; for (size_t i = 0; i < filter_list->GetCount(); ++i) { if (filter_list->IsChecked(i)) exporter->AddFilter(from_wx(filter_list->GetString(i))); } try { wxBusyCursor busy; c->ass->SetScriptInfo("Export Encoding", from_wx(charset_list->GetStringSelection())); exporter->Export(filename, from_wx(charset_list->GetStringSelection()), this); } catch (agi::UserCancelException const&) { } catch (const char *error) { wxMessageBox(error, "Error exporting subtitles", wxOK | wxICON_ERROR | wxCENTER, this); } catch (wxString const& error) { wxMessageBox(error, "Error exporting subtitles", wxOK | wxICON_ERROR | wxCENTER, this); } catch (agi::Exception const& err) { wxMessageBox(to_wx(err.GetMessage()), "Error exporting subtitles", wxOK | wxICON_ERROR | wxCENTER, this); } catch (std::exception const& err) { wxMessageBox(to_wx(err.what()), "Error exporting subtitles", wxOK | wxICON_ERROR | wxCENTER, this); } catch (...) { wxMessageBox("Unknown error", "Error exporting subtitles", wxOK | wxICON_ERROR | wxCENTER, this); } EndModal(0); }
TimeEdit::TimeEdit(wxWindow* parent, wxWindowID id, agi::Context *c, const std::string& value, const wxSize& size, bool asEnd) : wxTextCtrl(parent, id, to_wx(value), wxDefaultPosition, size, wxTE_CENTRE | wxTE_PROCESS_ENTER) , c(c) , isEnd(asEnd) , insert(!OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool()) , insert_opt(OPT_SUB("Subtitle/Time Edit/Insert Mode", &TimeEdit::OnInsertChanged, this)) { // Set validator wxTextValidator val(wxFILTER_INCLUDE_CHAR_LIST); wxString includes[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", ":", ","}; val.SetIncludes(wxArrayString(countof(includes), includes)); SetValidator(val); // Other stuff if (value.empty()) SetValue(to_wx(time.GetAssFormated())); Bind(wxEVT_MENU, std::bind(&TimeEdit::CopyTime, this), Time_Edit_Copy); Bind(wxEVT_MENU, std::bind(&TimeEdit::PasteTime, this), Time_Edit_Paste); Bind(wxEVT_TEXT, &TimeEdit::OnModified, this); Bind(wxEVT_CONTEXT_MENU, &TimeEdit::OnContextMenu, this); Bind(wxEVT_CHAR_HOOK, &TimeEdit::OnKeyDown, this); Bind(wxEVT_CHAR, &TimeEdit::OnChar, this); Bind(wxEVT_KILL_FOCUS, &TimeEdit::OnFocusLost, this); }
void OpenGLText::SetFont(std::string const& face, int size, bool bold, bool italics) { // No change required if (size == fontSize && face == fontFace && bold == fontBold && italics == fontItalics) return; // Set font fontFace = face; fontSize = size; fontBold = bold; fontItalics = italics; font.SetFaceName(to_wx(fontFace)); font.SetPointSize(size); font.SetWeight(bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL); // Delete all old data textures.clear(); glyphs.clear(); }