Merge branch 'vector_clip_actions' into feature

This commit is contained in:
arch1t3cht 2023-04-29 01:16:08 +02:00
commit ff20805ae6
10 changed files with 107 additions and 49 deletions

View File

@ -178,7 +178,7 @@ namespace {
STR_HELP("When the surrounding plane is also visible, switches which quad is locked. If inactive, the inner quad can only be resized without changing the perspective plane. If active, this holds for the outer quad instead.")
bool Validate(const agi::Context *c) override {
return c->videoDisplay->ToolIsType(typeid(VisualToolPerspective)) && c->videoDisplay->GetSubTool() | PERSP_OUTER;
return c->videoDisplay->ToolIsType(typeid(VisualToolPerspective)) && c->videoDisplay->GetSubTool() & PERSP_OUTER;
}
};

View File

@ -41,17 +41,22 @@
#include <limits>
Spline::Spline(const VisualToolBase &tl)
Spline::Spline(const VisualToolBase *tl)
: coord_translator(tl)
{
}
Vector2D Spline::ToScript(Vector2D vec) const {
return coord_translator.ToScriptCoords(vec) * scale;
if (coord_translator)
vec = coord_translator->ToScriptCoords(vec);
return vec * scale;
}
Vector2D Spline::FromScript(Vector2D vec) const {
return coord_translator.FromScriptCoords(vec / scale);
vec = vec / scale;
if (coord_translator)
vec = coord_translator->FromScriptCoords(vec);
return vec;
}
void Spline::SetScale(int new_scale) {

View File

@ -36,7 +36,7 @@ class VisualToolBase;
class Spline final : private std::vector<SplineCurve> {
/// Visual tool to do the conversion between script and video pixels
const VisualToolBase &coord_translator;
const VisualToolBase *coord_translator = nullptr;
/// Spline scale
int scale = 0;
int raw_scale = 0;
@ -47,7 +47,8 @@ class Spline final : private std::vector<SplineCurve> {
/// Script coordinates -> Video coordinates
Vector2D FromScript(Vector2D vec) const;
public:
Spline(const VisualToolBase &scale);
Spline() {};
Spline(const VisualToolBase *scale);
/// Encode to an ASS vector drawing
std::string EncodeToAss() const;

View File

@ -115,6 +115,15 @@ Vector2D& SplineCurve::EndPoint() {
}
}
std::vector<Vector2D> SplineCurve::AnchorPoints() {
switch (type) {
case POINT: return std::vector<Vector2D>({p1});
case LINE: return std::vector<Vector2D>({p1, p2});
case BICUBIC: return std::vector<Vector2D>({p1, p2, p3, p4});
default: return std::vector<Vector2D>();
}
}
Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const {
return GetPoint(GetClosestParam(ref));
}

View File

@ -73,6 +73,7 @@ public:
Vector2D GetPoint(float t) const;
Vector2D& EndPoint();
std::vector<Vector2D> AnchorPoints();
/// Get point on the curve closest to reference
Vector2D GetClosestPoint(Vector2D ref) const;
/// Get t value for the closest point to reference

View File

@ -40,6 +40,8 @@
#include <libaegisub/of_type_adaptor.h>
#include <libaegisub/split.h>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <algorithm>
@ -540,11 +542,9 @@ int VisualToolBase::GetLineAlignment(AssDialogue *diag) {
return an;
}
void VisualToolBase::GetLineBaseExtents(AssDialogue *diag, double &width, double &height, double &descent, double &extlead) {
width = 0.;
height = 0.;
descent = 0.;
extlead = 0.;
std::pair<Vector2D, Vector2D> VisualToolBase::GetLineBaseExtents(AssDialogue *diag) {
double width = 0.;
double height = 0.;
AssStyle style;
if (AssStyle *basestyle = c->ass->GetStyle(diag->Style)) {
@ -554,25 +554,57 @@ void VisualToolBase::GetLineBaseExtents(AssDialogue *diag, double &width, double
}
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);
param_vec ptag = find_tag(blocks, "\\p");
std::string text = diag->GetStrippedText();
std::vector<std::string> 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;
if (ptag && ptag->front().Get(0)) { // A drawing
Spline spline;
spline.SetScale(ptag->front().Get(1));
std::string drawing_text = join(blocks | agi::of_type<AssDialogueBlockDrawing>() | boost::adaptors::transformed([&](AssDialogueBlock *d) { return d->GetText(); }), "");
spline.DecodeFromAss(drawing_text);
if (!spline.size())
return std::make_pair(Vector2D(0, 0), Vector2D(0, 0));
float left = FLT_MAX;
float top = FLT_MAX;
float right = -FLT_MAX;
float bot = -FLT_MAX;
for (SplineCurve curve : spline) {
for (Vector2D pt : curve.AnchorPoints()) {
left = std::min(left, pt.X());
top = std::min(top, pt.Y());
right = std::max(right, pt.X());
bot = std::max(bot, pt.Y());
}
}
width = std::max(width, linewidth);
height += lineheight;
return std::make_pair(Vector2D(left, top), Vector2D(right, bot));
} else {
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<std::string> textlines;
boost::replace_all(text, "\\N", "\n");
agi::Split(textlines, text, '\n');
for (std::string line : textlines) {
double linewidth = 0;
double lineheight = 0;
double descent;
double extlead;
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;
}
return std::make_pair(Vector2D(0, 0), Vector2D(width, height));
}
}

View File

@ -133,11 +133,18 @@ protected:
float GetLineFontSize(AssDialogue *diag);
int GetLineAlignment(AssDialogue *diag);
/// @brief Compute text extents of the given line without any formatting
/// @param diag The dialogue line
/// @return The top left and bottom right corners of the line's bounding box respectively.
///
/// 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.
/// For text the top left corner of the bounding box will always be at the origin, but this needn't be
/// the case for drawings. The width and height of the bounding box are the shifts used for text alignment.
///
/// This function works for most common line formats, but can be inaccurate for more complex cases such as lines
/// containing both text and drawings.
/// Returns a rough estimate when getting the precise extents fails
void GetLineBaseExtents(AssDialogue *diag, double &width, double &height, double &descent, double &extlead);
std::pair<Vector2D, Vector2D> GetLineBaseExtents(AssDialogue *diag);
void GetLineClip(AssDialogue *diag, Vector2D &p1, Vector2D &p2, bool &inverse);
std::string GetLineVectorClip(AssDialogue *diag, int &scale, bool &inverse);

View File

@ -35,6 +35,8 @@
#include <libaegisub/split.h>
#include <libaegisub/util.h>
#include <libaegisub/log.h>
#include <cmath>
#include <wx/colour.h>
@ -332,7 +334,7 @@ void VisualToolPerspective::Draw() {
gl.SetRotation(angle_x, angle_y, angle_z);
gl.SetScale(fsc);
gl.SetShear(fax, fay);
Vector2D glScale = textheight * Vector2D(1, 1) / spacing / 4;
Vector2D glScale = (bbox.second.Y() - bbox.first.Y()) * Vector2D(1, 1) / spacing / 4;
gl.SetScale(100 * glScale);
// Draw grid
@ -678,17 +680,18 @@ bool VisualToolPerspective::InnerToText() {
float quadwidth = ab.Len();
float quadheight = abs(ad.Y());
float scalex = quadwidth / textwidth;
float scaley = quadheight / textheight;
float scalex = quadwidth / std::max(bbox.second.X() - bbox.first.X(), 1.0f);
float scaley = quadheight / std::max(bbox.second.Y() - bbox.first.Y(), 1.0f);
Vector2D scale = Vector2D(scalex, scaley);
float shiftv = align <= 3 ? 1 : (align <= 6 ? 0.5 : 0);
float shifth = align % 3 == 0 ? 1 : (align % 3 == 2 ? 0.5 : 0);
pos = org + r[0].XY() + Vector2D(quadwidth * shifth, quadheight * shiftv);
pos = org + r[0].XY() - bbox.first * scale + Vector2D(quadwidth * shifth, quadheight * shiftv);
angle_x = rotx * rad2deg;
angle_y = -roty * rad2deg;
angle_z = -rotz * rad2deg;
Vector2D oldfsc = fsc;
fsc = 100 * Vector2D(scalex, scaley);
fsc = 100 * scale;
fax = rawfax * scaley / scalex;
fay = 0;
@ -779,40 +782,39 @@ void VisualToolPerspective::TextToPersp() {
align = GetLineAlignment(active_line);
double descend, extlead;
GetLineBaseExtents(active_line, textwidth, textheight, descend, extlead);
textwidth = std::max(textwidth, 1.);
textheight = std::max(textheight, 1.);
double textleft, texttop = 0.;
bbox = GetLineBaseExtents(active_line);
float textwidth = std::max(bbox.second.X() - bbox.first.X(), 1.f);
float textheight = std::max(bbox.second.Y() - bbox.first.Y(), 1.f);
double shiftx = 0., shifty = 0.;
switch ((align - 1) % 3) {
case 1:
textleft = -textwidth / 2;
shiftx = -textwidth / 2;
break;
case 2:
textleft = -textwidth;
shiftx = -textwidth;
break;
default:
break;
}
switch ((align - 1) / 3) {
case 0:
texttop = -textheight;
shifty = -textheight;
break;
case 1:
texttop = -textheight / 2;
shifty = -textheight / 2;
break;
default:
break;
}
std::vector<Vector2D> textrect = MakeRect(Vector2D(0, 0), Vector2D(textwidth, textheight));
std::vector<Vector2D> textrect = MakeRect(bbox.first, bbox.second);
for (int i = 0; i < 4; i++) {
Vector2D p = textrect[i];
// Apply \fax and \fay
p = Vector2D(p.X() + p.Y() * fax, p.X() * fay + p.Y());
// Translate to alignment point
p = p + Vector2D(textleft, texttop);
p = p + Vector2D(shiftx, shifty);
// Apply scaling
p = Vector2D(p.X() * fsc.X() / 100., p.Y() * fsc.Y() / 100.);
// Translate relative to origin

View File

@ -52,7 +52,7 @@ public:
class VisualToolPerspective final : public VisualTool<VisualToolPerspectiveDraggableFeature> {
wxToolBar *toolBar = nullptr; /// The subtoolbar
int settings = 0;
int settings = 0;
agi::OptionValue* optOuter;
agi::OptionValue* optOuterLocked;
@ -69,8 +69,9 @@ class VisualToolPerspective final : public VisualTool<VisualToolPerspectiveDragg
int align = 0;
double textwidth = 0.f;
double textheight = 0.f;
// Corners of the bounding box of the event without any formatting.
// The top left corner is the zero vector for text but might not be for drawings.
std::pair<Vector2D, Vector2D> bbox;
Vector2D fsc;

View File

@ -34,7 +34,7 @@ int BUTTON_ID_BASE = 1300;
VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, agi::Context *context)
: VisualTool<VisualToolVectorClipDraggableFeature>(parent, context)
, spline(*this)
, spline(this)
{
}