From ddfd4501f051ee86a5a6f9edb8f9e4b38835d814 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Sat, 14 Jan 2023 14:18:04 +0100 Subject: [PATCH] visual tools: Add more tag get functions Add getters for alignment, outline, shadow, font size, and the raw extents of the text. Also handle overriding \xbord and \ybord correctly. --- src/visual_tool.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++- src/visual_tool.h | 10 +++++ 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/visual_tool.cpp b/src/visual_tool.cpp index 29f0579d5..27b5c4107 100644 --- a/src/visual_tool.cpp +++ b/src/visual_tool.cpp @@ -23,6 +23,7 @@ #include "ass_dialogue.h" #include "ass_file.h" #include "ass_style.h" +#include "auto4_base.h" #include "compat.h" #include "include/aegisub/context.h" #include "options.h" @@ -31,11 +32,15 @@ #include "video_display.h" #include "visual_tool_clip.h" #include "visual_tool_drag.h" +#include "visual_tool_perspective.h" #include "visual_tool_vector_clip.h" #include #include #include +#include + +#include #include @@ -475,6 +480,98 @@ void VisualToolBase::GetLineScale(AssDialogue *diag, Vector2D &scale) { scale = Vector2D(x, y); } +void VisualToolBase::GetLineOutline(AssDialogue *diag, Vector2D &outline) { + float x = 0.f, y = 0.f; + + if (AssStyle *style = c->ass->GetStyle(diag->Style)) { + x = style->outline_w; + y = style->outline_w; + } + + auto blocks = diag->ParseTags(); + + if (param_vec tag = find_tag(blocks, "\\bord")) { + x = tag->front().Get(x); + y = tag->front().Get(y); + } + if (param_vec tag = find_tag(blocks, "\\xbord")) + x = tag->front().Get(x); + if (param_vec tag = find_tag(blocks, "\\ybord")) + y = tag->front().Get(y); + + outline = Vector2D(x, y); +} + +void VisualToolBase::GetLineShadow(AssDialogue *diag, Vector2D &shadow) { + float x = 0.f, y = 0.f; + + if (AssStyle *style = c->ass->GetStyle(diag->Style)) { + x = style->shadow_w; + y = style->shadow_w; + } + + auto blocks = diag->ParseTags(); + + if (param_vec tag = find_tag(blocks, "\\shad")) { + x = tag->front().Get(x); + y = tag->front().Get(y); + } + if (param_vec tag = find_tag(blocks, "\\xshad")) + x = tag->front().Get(x); + if (param_vec tag = find_tag(blocks, "\\yshad")) + y = tag->front().Get(y); + + shadow = Vector2D(x, y); +} + +int VisualToolBase::GetLineAlignment(AssDialogue *diag) { + int an = 0; + + if (AssStyle *style = c->ass->GetStyle(diag->Style)) + an = style->alignment; + auto blocks = diag->ParseTags(); + if (param_vec tag = find_tag(blocks, "\\an")) + an = tag->front().Get(an); + + return an; +} + +void VisualToolBase::GetLineBaseExtents(AssDialogue *diag, double &width, double &height, double &descent, double &extlead) { + width = 0.; + height = 0.; + descent = 0.; + extlead = 0.; + + AssStyle style; + if (AssStyle *basestyle = c->ass->GetStyle(diag->Style)) { + style = AssStyle(basestyle->GetEntryData()); + style.scalex = 100.; + style.scaley = 100.; + } + + auto blocks = diag->ParseTags(); + if (param_vec tag = find_tag(blocks, "\\fs")) + style.fontsize = tag->front().Get(style.fontsize); + if (param_vec tag = find_tag(blocks, "\\fn")) + style.font = tag->front().Get(style.font); + + std::string text = diag->GetStrippedText(); + std::vector textlines; + boost::replace_all(text, "\\N", "\n"); + agi::Split(textlines, text, '\n'); + for (std::string line : textlines) { + double linewidth = 0; + double lineheight = 0; + if (!Automation4::CalculateTextExtents(&style, line, linewidth, lineheight, descent, extlead)) { + // meh... let's make some ballpark estimates + linewidth = style.fontsize * line.length(); + lineheight = style.fontsize; + } + width = std::max(width, linewidth); + height += lineheight; + } +} + void VisualToolBase::GetLineClip(AssDialogue *diag, Vector2D &p1, Vector2D &p2, bool &inverse) { inverse = false; @@ -545,12 +642,17 @@ void VisualToolBase::SetOverride(AssDialogue* line, std::string const& tag, std: if (!line) return; std::string removeTag; + std::string removeTag2; if (tag == "\\1c") removeTag = "\\c"; else if (tag == "\\frz") removeTag = "\\fr"; else if (tag == "\\pos") removeTag = "\\move"; else if (tag == "\\move") removeTag = "\\pos"; else if (tag == "\\clip") removeTag = "\\iclip"; else if (tag == "\\iclip") removeTag = "\\clip"; + else if (tag == "\\xbord" || tag == "\\ybord") removeTag = "\\bord"; + else if (tag == "\\xshad" || tag == "\\yshad") removeTag = "\\shad"; + else if (tag == "\\bord") { removeTag = "\\xbord"; removeTag2 = "\\ybord"; } + else if (tag == "\\shad") { removeTag = "\\xshad"; removeTag2 = "\\yshad"; } // Get block at start auto blocks = line->ParseTags(); @@ -561,7 +663,7 @@ void VisualToolBase::SetOverride(AssDialogue* line, std::string const& tag, std: // Remove old of same for (size_t i = 0; i < ovr->Tags.size(); i++) { std::string const& name = ovr->Tags[i].Name; - if (tag == name || removeTag == name) { + if (tag == name || removeTag == name || removeTag2 == name) { ovr->Tags.erase(ovr->Tags.begin() + i); i--; } diff --git a/src/visual_tool.h b/src/visual_tool.h index 1a3c1b1c4..e9e8770b9 100644 --- a/src/visual_tool.h +++ b/src/visual_tool.h @@ -127,6 +127,16 @@ protected: void GetLineRotation(AssDialogue *diag, float &rx, float &ry, float &rz); void GetLineShear(AssDialogue *diag, float& fax, float& fay); void GetLineScale(AssDialogue *diag, Vector2D &scale); + void GetLineOutline(AssDialogue *diag, Vector2D &outline); + void GetLineShadow(AssDialogue *diag, Vector2D &shadow); + float GetLineFontSize(AssDialogue *diag); + int GetLineAlignment(AssDialogue *diag); + /// @brief Compute text extents of the given line without any formatting + /// + /// Formatting tags are stripped and \fs tags are respected, but \fscx and \fscy are kept as 100 even if + /// they are different in the style. + /// Returns a rough estimate when getting the precise extents fails + void GetLineBaseExtents(AssDialogue *diag, double &width, double &height, double &descent, double &extlead); void GetLineClip(AssDialogue *diag, Vector2D &p1, Vector2D &p2, bool &inverse); std::string GetLineVectorClip(AssDialogue *diag, int &scale, bool &inverse);