Skip to content

Commit

Permalink
Update ReadSVG
Browse files Browse the repository at this point in the history
Transforms seems to work ...

Only tested on Ubuntu with the Natron logo.

* #25
* NatronGitHub/Natron#970
  • Loading branch information
rodlie committed Jun 12, 2024
1 parent 106aa7f commit 8112cea
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 151 deletions.
197 changes: 76 additions & 121 deletions Extra/ReadSVG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@
#include "ofxsMultiPlane.h"
#include "ofxsImageEffect.h"

// cairo helper functions
// transform helper
#include "ofxsTransform3x3.h"
#include "ofxsTransformInteract.h"

// cairo helper
#include "CairoHelper.h"

#define kPluginName "ReadSVG"
Expand All @@ -54,30 +58,10 @@
#define kParamDpiHint "Dots-per-inch (90 is default)"
#define kParamDpiDefault 90

#define kParamPivot "pivot"
#define kParamPivotLabel "Pivot"
#define kParamPivotHint "Apply origin on transform, else center of image."
#define kParamPivotDefault false

#define kParamOrigin "origin"
#define kParamOriginLabel "Origin"
#define kParamOriginHint "Origin for transform."
#define kParamOriginDefault 0.

#define kParamScale "scale"
#define kParamScaleLabel "Scale"
#define kParamScaleHint "Transform scale."
#define kParamScaleDefault 1.

#define kParamSkew "skew"
#define kParamSkewLabel "Skew"
#define kParamSkewHint "Transform skew."
#define kParamSkewDefault 0.

#define kParamRotate "rotate"
#define kParamRotateLabel "Rotate"
#define kParamRotateHint "Rotate the surface."
#define kParamRotateDefault 0.
#define kParamTranslateEnabled "translateEnabled"
#define kParamTranslateEnabledLabel "Translate"
#define kParamTranslateEnabledHint "Enable translate."
#define kParamTranslateEnabledDefault false

#define kSupportsRGBA true
#define kSupportsRGB false
Expand Down Expand Up @@ -179,12 +163,16 @@ class ReadSVGPlugin : public GenericReaderPlugin
int *componentCount) OVERRIDE FINAL;
virtual void changedFilename(const OFX::InstanceChangedArgs &args) OVERRIDE FINAL;
void getLayers(xmlNode *node, std::vector<std::string> *layers);
OFX::IntParam *_dpi;
OFX::BooleanParam *_pivot;
OFX::Double2DParam *_origin;
OFX::Double2DParam *_scale;
OFX::Double2DParam *_skew;
OFX::DoubleParam *_rotate;
IntParam *_dpi;
BooleanParam *_translateEnabled;
Double2DParam* _translate;
DoubleParam* _rotate;
Double2DParam* _scale;
BooleanParam* _scaleUniform;
DoubleParam* _skewX;
DoubleParam* _skewY;
ChoiceParam* _skewOrder;
Double2DParam* _center;
std::vector<std::string> imageLayers;
};

Expand All @@ -203,20 +191,29 @@ ReadSVGPlugin::ReadSVGPlugin(OfxImageEffectHandle handle,
false
#endif
)
,_dpi(nullptr)
, _pivot(nullptr)
, _origin(nullptr)
, _scale(nullptr)
, _skew(nullptr)
, _dpi(nullptr)
, _translateEnabled(nullptr)
, _translate(nullptr)
, _rotate(nullptr)
, _scale(nullptr)
, _scaleUniform(nullptr)
, _skewX(nullptr)
, _skewY(nullptr)
, _skewOrder(nullptr)
, _center(nullptr)
{
_dpi = fetchIntParam(kParamDpi);
_pivot = fetchBooleanParam(kParamPivot);
_origin = fetchDouble2DParam(kParamOrigin);
_scale = fetchDouble2DParam(kParamScale);
_skew = fetchDouble2DParam(kParamSkew);
_rotate = fetchDoubleParam(kParamRotate);
assert(_dpi && _pivot && _origin && _scale && _skew && _rotate);
_translateEnabled = fetchBooleanParam(kParamTranslateEnabled);
assert(_dpi && _translateEnabled);

_translate = fetchDouble2DParam(kParamTransformTranslateOld);
_rotate = fetchDoubleParam(kParamTransformRotateOld);
_scale = fetchDouble2DParam(kParamTransformScaleOld);
_scaleUniform = fetchBooleanParam(kParamTransformScaleUniformOld);
_skewX = fetchDoubleParam(kParamTransformSkewXOld);
_skewY = fetchDoubleParam(kParamTransformSkewYOld);
_skewOrder = fetchChoiceParam(kParamTransformSkewOrderOld);
_center = fetchDouble2DParam(kParamTransformCenterOld);
}

ReadSVGPlugin::~ReadSVGPlugin()
Expand Down Expand Up @@ -353,19 +350,22 @@ ReadSVGPlugin::decodePlane(const std::string& filename,
cairo_surface_t *surface;
cairo_t *cr;
cairo_status_t status;
double imageWidth, imageHeight, scaleWidth, scaleHeight, originX, originY, scaleX, scaleY, skewX, skewY, rotate;
int dpi, width, height, renderWidth, renderHeight;
bool pivot;
double imageWidth, imageHeight, scaleWidth, scaleHeight;
double translateX, translateY, rotate, scaleX, scaleY, skewX, skewY, centerX, centerY;
int dpi, width, height, renderWidth, renderHeight, skewO;
bool scaleUniform, translateEnabled;

_dpi->getValueAtTime(time, dpi);
_pivot->getValueAtTime(time, pivot);
_origin->getValueAtTime(time, originX, originY);
_scale->getValueAtTime(time, scaleX, scaleY);
_skew->getValueAtTime(time, skewX, skewY);
_rotate->getValueAtTime(time, rotate);
_translateEnabled->getValueAtTime(time, translateEnabled);

bool hasTransform = (pivot || scaleX != 1. || scaleY != 1. || skewX != 0. || skewY != 0. || rotate != 0.);
bool hasDpi = (dpi != kParamDpiDefault);
_translate->getValueAtTime(time, translateX, translateY);
_rotate->getValueAtTime(time, rotate);
_scale->getValueAtTime(time, scaleX, scaleY);
_scaleUniform->getValueAtTime(time, scaleUniform);
_skewX->getValueAtTime(time, skewX);
_skewY->getValueAtTime(time, skewY);;
_skewOrder->getValueAtTime(time, skewO);
_center->getValueAtTime(time, centerX, centerY);

// load svg
handle = rsvg_handle_new_from_file(filename.c_str(), &error);
Expand All @@ -384,15 +384,14 @@ ReadSVGPlugin::decodePlane(const std::string& filename,
renderWidth= renderWindow.x2 - renderWindow.x1;
renderHeight= renderWindow.y2 - renderWindow.y1;

if (hasDpi) {
if (dpi != kParamDpiDefault) {
width = imageWidth * dpi / kParamDpiDefault;
height = imageHeight * dpi / kParamDpiDefault;
}
else {
width = imageWidth;
height = imageHeight;
}

if (width != renderWidth || height != renderHeight) {
setPersistentMessage(OFX::Message::eMessageError, "", "Image don't match RenderWindow");
OFX::throwSuiteStatusException(kOfxStatErrFormat);
Expand All @@ -410,19 +409,14 @@ ReadSVGPlugin::decodePlane(const std::string& filename,
CairoHelper::applyScale(cr, {scaleWidth, scaleHeight});

// transform
if (hasTransform) {
if (!pivot) {
originX = hasDpi ? width / scaleWidth / 2. : width / 2.;
originY = hasDpi ? height / scaleHeight / 2. : height / 2.;
} else {
// TODO
}
CairoHelper::applyTransform(cr, {{originX, originY},
{scaleX, scaleY},
{skewX, skewY},
rotate,
pivot});
}
CairoHelper::applyTransform(cr, {{translateX, translateY},
{(translateEnabled ? translateX : centerX),
(translateEnabled ? translateY : centerY)},
{scaleX, scaleY},
{(skewO == 1 ? skewY : skewX),
(skewO == 1 ? skewX : skewY)},
rotate,
translateEnabled});

// render svg
if (layerID.empty()) {
Expand Down Expand Up @@ -629,6 +623,9 @@ ReadSVGPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
kIsMultiPlanar);
desc.setLabel(kPluginName);
desc.setPluginDescription(kPluginDescription);

Transform3x3Describe(desc, true);
desc.setOverlayInteractDescriptor(new TransformOverlayDescriptorOldParams);
}

/** @brief The describe in context function, passed a plugin descriptor and a context */
Expand All @@ -655,67 +652,25 @@ ReadSVGPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc,
param->setDisplayRange(1, 500);
param->setDefault(kParamDpiDefault);
param->setAnimates(false);
param->setLayoutHint(OFX::eLayoutHintDivider);
if (page) { page->addChild(*param); }
}
{
BooleanParamDescriptor* param = desc.defineBooleanParam(kParamPivot);
param->setLabel(kParamPivotLabel);
param->setHint(kParamPivotHint);
param->setDefault(kParamPivotDefault);
param->setAnimates(false);
param->setLayoutHint(OFX::eLayoutHintNoNewLine);
if (page) { page->addChild(*param); }
}
{
Double2DParamDescriptor* param = desc.defineDouble2DParam(kParamOrigin);
param->setLabel(kParamOriginLabel);
param->setHint(kParamOriginHint);
param->setRange(INT_MIN, INT_MIN,
INT_MAX, INT_MAX);
param->setDisplayRange(-1000, -1000,
1000, 1000);
param->setDefault(kParamOriginDefault,
kParamOriginDefault);
param->setAnimates(true);
if (page) { page->addChild(*param); }
}
{
Double2DParamDescriptor* param = desc.defineDouble2DParam(kParamScale);
param->setLabel(kParamScaleLabel);
param->setHint(kParamScaleHint);
param->setRange(INT_MIN, INT_MIN,
INT_MAX, INT_MAX);
param->setDisplayRange(-5, -5,
5, 5);
param->setDefault(kParamScaleDefault,
kParamScaleDefault);
param->setAnimates(true);
if (page) { page->addChild(*param); }
}
{
Double2DParamDescriptor* param = desc.defineDouble2DParam(kParamSkew);
param->setLabel(kParamSkewLabel);
param->setHint(kParamSkewHint);
param->setRange(INT_MIN, INT_MIN,
INT_MAX, INT_MAX);
param->setDisplayRange(-5, -5,
5, 5);
param->setDefault(kParamSkewDefault,
kParamSkewDefault);
param->setAnimates(true);
if (page) { page->addChild(*param); }
}
{
DoubleParamDescriptor* param = desc.defineDoubleParam(kParamRotate);
param->setLabel(kParamRotateLabel);
param->setHint(kParamRotateHint);
param->setRange(-360., 360.);
param->setDefault(kParamRotateDefault);
param->setAnimates(true);
BooleanParamDescriptor* param = desc.defineBooleanParam(kParamTranslateEnabled);
param->setLabel(kParamTranslateEnabledLabel);
param->setHint(kParamTranslateEnabledHint);
param->setDefault(kParamTranslateEnabledDefault);
param->setAnimates(false);
param->setLayoutHint(OFX::eLayoutHintDivider);
if (page) { page->addChild(*param); }
}
ofxsTransformDescribeParams(desc,
page,
NULL,
true,
true,
false,
false);
GenericReaderDescribeInContextEnd(desc,
context,
page,
Expand Down
62 changes: 36 additions & 26 deletions Helpers/CairoHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,17 @@

#include <cmath>

void
CairoHelper::applyFlip(cairo_t *cr,
const int &height)
{
if (!cr || height < 1) { return; }
cairo_scale(cr, 1.0f, -1.0f);
cairo_translate(cr, 0.0f, -height);
}

void
CairoHelper::applyPosition(cairo_t *cr,
const _XY &position)
const _XY &position,
const bool translate)
{
if (!cr) { return; }
cairo_move_to(cr, position.x, position.y);
if (translate) {
cairo_translate(cr, position.x, position.y);
} else {
cairo_move_to(cr, position.x, position.y);
}
}

void
Expand Down Expand Up @@ -62,17 +58,23 @@ CairoHelper::applySkew(cairo_t *cr,
const _XY &origin)
{
if (!cr || (skew.x == 0. && skew.y == 0.)) { return; }
double x = skew.x;
double y = skew.y;
if (x != 0.) { x = -x; }
if (y != 0.) { y = -y; }
cairo_matrix_t matrix = {
1.0, y,
x , 1.0,
0.0, 0.0
};
cairo_translate(cr, origin.x, origin.y);
cairo_transform(cr, &matrix);
if (skew.x != 0.) {
cairo_matrix_t matrix = {
1.0, 0.0,
skew.x, 1.0,
0.0, 0.0
};
cairo_transform(cr, &matrix);
}
if (skew.y != 0.) {
cairo_matrix_t matrix = {
1.0, skew.y,
0.0, 1.0,
0.0, 0.0
};
cairo_transform(cr, &matrix);
}
cairo_translate(cr, -origin.x, -origin.y);
}

Expand All @@ -83,7 +85,7 @@ CairoHelper::applyRotate(cairo_t *cr,
{
if (!cr || rotate == 0.) { return; }
cairo_translate(cr, origin.x, origin.y);
cairo_rotate(cr, -rotate * (M_PI / 180.0));
cairo_rotate(cr, rotate * (M_PI / 180.0));
cairo_translate(cr, -origin.x, -origin.y);
}

Expand All @@ -92,8 +94,16 @@ CairoHelper::applyTransform(cairo_t *cr,
const _Transform &transform)
{
if (!cr) { return; }
if (transform.position) { applyPosition(cr, transform.origin); }
applyScale(cr, transform.scale, transform.origin);
applySkew(cr, transform.skew, transform.origin);
applyRotate(cr, transform.rotate, transform.origin);
if (transform.position) { applyPosition(cr,
transform.translate,
true); }
applyScale(cr,
transform.scale,
transform.origin);
applySkew(cr,
transform.skew,
transform.origin);
applyRotate(cr,
transform.rotate,
transform.origin);
}
7 changes: 3 additions & 4 deletions Helpers/CairoHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,17 @@ class CairoHelper
};
struct _Transform
{
_XY translate;
_XY origin;
_XY scale;
_XY skew;
double rotate;
bool position;
};
/** @brief apply flip */
static void applyFlip(cairo_t *cr,
const int &height);
/** @brief apply position */
static void applyPosition(cairo_t *cr,
const _XY &position);
const _XY &position,
const bool translate = false);
/** @brief apply scale */
static void applyScale(cairo_t *cr,
const _XY &scale);
Expand Down

0 comments on commit 8112cea

Please sign in to comment.