1
0
mirror of synced 2024-09-25 12:08:26 +02:00

sys: Drastically improve highlighting performance

This commit is contained in:
WerWolv 2022-02-04 00:29:47 +01:00
parent ba68f463e5
commit 618eead341
6 changed files with 95 additions and 52 deletions

View File

@ -104,7 +104,7 @@ namespace hex {
EVENT_DEF(EventFileLoaded, fs::path);
EVENT_DEF(EventFileUnloaded);
EVENT_DEF(EventDataChanged);
EVENT_DEF(EventPatternChanged, std::vector<pl::PatternData *> &);
EVENT_DEF(EventHighlightingChanged);
EVENT_DEF(EventWindowClosing, GLFWwindow *);
EVENT_DEF(EventRegionSelected, Region);
EVENT_DEF(EventProjectFileStore);

View File

@ -39,11 +39,15 @@ namespace hex {
id, Highlighting {region, color, tooltip}
});
EventManager::post<EventHighlightingChanged>();
return id;
}
void removeHighlight(u32 id) {
s_highlights.erase(id);
EventManager::post<EventHighlightingChanged>();
}
std::map<u32, Highlighting> &getHighlights() {

View File

@ -14,12 +14,22 @@ namespace hex::prv {
class Provider;
}
namespace hex::plugin::builtin {
using SearchFunction = std::vector<std::pair<u64, u64>> (*)(prv::Provider *&provider, std::string string);
struct HighlightBlock {
struct Highlight {
color_t color;
std::vector<std::string> tooltips;
};
constexpr static size_t Size = 0x2000;
u64 base;
std::array<Highlight, Size> highlight;
};
class ViewHexEditor : public View {
public:
ViewHexEditor();
@ -54,6 +64,8 @@ namespace hex::plugin::builtin {
hex::EncodingFile m_currEncodingFile;
u8 m_highlightAlpha = 0x80;
std::list<HighlightBlock> m_highlights;
bool m_processingImportExport = false;
bool m_advancedDecodingEnabled = false;

View File

@ -59,45 +59,72 @@ namespace hex::plugin::builtin {
};
this->m_memoryEditor.HighlightFn = [](const ImU8 *data, size_t off, bool next) -> bool {
auto _this = (ViewHexEditor *)(data);
std::optional<u32> currColor, prevColor;
bool firstByte = off == 0x00;
auto _this = (ViewHexEditor *)(data);
auto provider = ImHexApi::Provider::get();
off += provider->getBaseAddress() + provider->getCurrentPageAddress();
u32 alpha = static_cast<u32>(_this->m_highlightAlpha) << 24;
for (const auto &[id, highlight] : ImHexApi::HexEditor::getHighlights()) {
auto &region = highlight.getRegion();
auto &color = highlight.getColor();
std::optional<color_t> currColor, prevColor;
if (off >= region.address && off < (region.address + region.size))
currColor = (color & 0x00FFFFFF) | alpha;
if ((off - 1) >= region.address && (off - 1) < (region.address + region.size))
prevColor = (color & 0x00FFFFFF) | alpha;
for (auto &highlightBlock : _this->m_highlights) {
if (off >= highlightBlock.base && off < (highlightBlock.base + HighlightBlock::Size)) {
currColor = highlightBlock.highlight[off - highlightBlock.base].color;
}
if ((off - 1) >= highlightBlock.base && (off - 1) < (highlightBlock.base + HighlightBlock::Size)) {
prevColor = highlightBlock.highlight[(off - 1) - highlightBlock.base].color;
}
if (currColor && prevColor) break;
if (firstByte)
prevColor = 0x00;
}
{
auto patterns = provider->getPatternLanguageRuntime().getPatterns();
for (const auto &pattern : patterns) {
auto child = pattern->getPattern(off);
if (child != nullptr) {
auto color = (child->getColor() & 0x00FFFFFF) | alpha;
currColor = currColor.has_value() ? ImAlphaBlendColors(color, currColor.value()) : color;
break;
if (!currColor || !prevColor) {
if (_this->m_highlights.size() > 0x10)
_this->m_highlights.pop_front();
auto blockStartOffset = off - (off % HighlightBlock::Size);
HighlightBlock newBlock = {
blockStartOffset,
{}
};
for (u32 i = 0; i < HighlightBlock::Size; i++) {
std::optional<color_t> highlightColor;
std::string highlightTooltip;
for (const auto &[id, highlight] : ImHexApi::HexEditor::getHighlights()) {
auto &region = highlight.getRegion();
auto &color = highlight.getColor();
auto &tooltip = highlight.getTooltip();
if (blockStartOffset + i >= region.address && blockStartOffset + i < (region.address + region.size)) {
highlightColor = (color & 0x00FFFFFF) | alpha;
highlightTooltip = tooltip;
}
}
auto patterns = provider->getPatternLanguageRuntime().getPatterns();
for (const auto &pattern : patterns) {
auto child = pattern->getPattern(blockStartOffset + i);
if (child != nullptr) {
auto color = (child->getColor() & 0x00FFFFFF) | alpha;
highlightColor = highlightColor.has_value() ? ImAlphaBlendColors(color, highlightColor.value()) : color;
break;
}
}
auto &currHighlight = newBlock.highlight[i];
currHighlight.color = highlightColor.value_or(0x00);
if (!highlightTooltip.empty())
currHighlight.tooltips.push_back(highlightTooltip);
}
for (const auto &pattern : patterns) {
auto child = pattern->getPattern(off - 1);
if (child != nullptr) {
auto color = (child->getColor() & 0x00FFFFFF) | alpha;
prevColor = prevColor.has_value() ? ImAlphaBlendColors(color, currColor.value()) : color;
break;
}
}
_this->m_highlights.push_back(std::move(newBlock));
}
if (next && prevColor != currColor) {
@ -114,24 +141,26 @@ namespace hex::plugin::builtin {
};
this->m_memoryEditor.HoverFn = [](const ImU8 *data, size_t off) {
auto _this = (ViewHexEditor *)(data);
bool tooltipShown = false;
auto provider = ImHexApi::Provider::get();
off += provider->getBaseAddress() + provider->getCurrentPageAddress();
for (const auto &[id, highlight] : ImHexApi::HexEditor::getHighlights()) {
auto &region = highlight.getRegion();
auto &color = highlight.getColor();
auto &tooltip = highlight.getTooltip();
if (off >= region.address && off < (region.address + region.size)) {
if (!tooltipShown && !tooltip.empty()) {
for (auto &highlightBlock : _this->m_highlights) {
if (off >= highlightBlock.base && off < (highlightBlock.base + HighlightBlock::Size)) {
auto &highlight = highlightBlock.highlight[off - highlightBlock.base];
if (!tooltipShown && !highlight.tooltips.empty()) {
ImGui::BeginTooltip();
tooltipShown = true;
}
ImGui::ColorButton(tooltip.c_str(), ImColor(color).Value);
ImGui::SameLine(0, 10);
ImGui::TextUnformatted(tooltip.c_str());
for (const auto &tooltip : highlight.tooltips) {
ImGui::ColorButton(tooltip.c_str(), ImColor(highlight.color).Value);
ImGui::SameLine(0, 10);
ImGui::TextUnformatted(tooltip.c_str());
}
}
}
@ -175,6 +204,7 @@ namespace hex::plugin::builtin {
EventManager::unsubscribe<EventWindowClosing>(this);
EventManager::unsubscribe<RequestOpenWindow>(this);
EventManager::unsubscribe<EventSettingsChanged>(this);
EventManager::unsubscribe<EventHighlightingChanged>(this);
}
void ViewHexEditor::drawContent() {
@ -384,11 +414,7 @@ namespace hex::plugin::builtin {
EventManager::post<EventFileLoaded>(path);
EventManager::post<EventDataChanged>();
{
std::vector<pl::PatternData *> patterns;
EventManager::post<EventPatternChanged>(patterns);
}
EventManager::post<EventHighlightingChanged>();
}
void ViewHexEditor::copyBytes() const {
@ -908,6 +934,10 @@ namespace hex::plugin::builtin {
region = Region { address, size };
});
EventManager::subscribe<EventHighlightingChanged>(this, [this] {
this->m_highlights.clear();
});
}
void ViewHexEditor::registerShortcuts() {

View File

@ -7,7 +7,7 @@ namespace hex::plugin::builtin {
ViewPatternData::ViewPatternData() : View("hex.builtin.view.pattern_data.name") {
EventManager::subscribe<EventPatternChanged>(this, [this](auto &) {
EventManager::subscribe<EventHighlightingChanged>(this, [this]() {
if (!ImHexApi::Provider::isValid()) return;
this->m_sortedPatterns[ImHexApi::Provider::get()].clear();
@ -15,7 +15,7 @@ namespace hex::plugin::builtin {
}
ViewPatternData::~ViewPatternData() {
EventManager::unsubscribe<EventPatternChanged>(this);
EventManager::unsubscribe<EventHighlightingChanged>(this);
}
static bool beginPatternDataTable(prv::Provider *&provider, const std::vector<pl::PatternData *> &patterns, std::vector<pl::PatternData *> &sortedPatterns) {

View File

@ -624,10 +624,7 @@ namespace hex::plugin::builtin {
this->m_console.clear();
this->clearPatternData();
{
std::vector<pl::PatternData *> patterns;
EventManager::post<EventPatternChanged>(patterns);
}
EventManager::post<EventHighlightingChanged>();
std::thread([this, code] {
std::map<std::string, pl::Token::Literal> envVars;
@ -663,7 +660,7 @@ namespace hex::plugin::builtin {
}
if (result) {
EventManager::post<EventPatternChanged>(runtime.getPatterns());
EventManager::post<EventHighlightingChanged>();
}
this->m_runningEvaluators--;