mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-31 14:01:59 +00:00
Transformation matrix
This commit is contained in:
parent
3440ea7d3c
commit
daeb5a85b6
90
libqpdf/QPDFMatrix.cc
Normal file
90
libqpdf/QPDFMatrix.cc
Normal file
@ -0,0 +1,90 @@
|
||||
#include <qpdf/QPDFMatrix.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
QPDFMatrix::QPDFMatrix() :
|
||||
a(1.0),
|
||||
b(0.0),
|
||||
c(0.0),
|
||||
d(1.0),
|
||||
e(0.0),
|
||||
f(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
QPDFMatrix::QPDFMatrix(double a, double b, double c,
|
||||
double d, double e, double f) :
|
||||
a(a),
|
||||
b(b),
|
||||
c(c),
|
||||
d(d),
|
||||
e(e),
|
||||
f(f)
|
||||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFMatrix::unparse() const
|
||||
{
|
||||
return (QUtil::double_to_string(a, 5) + " " +
|
||||
QUtil::double_to_string(b, 5) + " " +
|
||||
QUtil::double_to_string(c, 5) + " " +
|
||||
QUtil::double_to_string(d, 5) + " " +
|
||||
QUtil::double_to_string(e, 5) + " " +
|
||||
QUtil::double_to_string(f, 5));
|
||||
}
|
||||
|
||||
void
|
||||
QPDFMatrix::concat(QPDFMatrix const& other)
|
||||
{
|
||||
double ap = (this->a * other.a) + (this->c * other.b);
|
||||
double bp = (this->b * other.a) + (this->d * other.b);
|
||||
double cp = (this->a * other.c) + (this->c * other.d);
|
||||
double dp = (this->b * other.c) + (this->d * other.d);
|
||||
double ep = (this->a * other.e) + (this->c * other.f) + this->e;
|
||||
double fp = (this->b * other.e) + (this->d * other.f) + this->f;
|
||||
this-> a = ap;
|
||||
this-> b = bp;
|
||||
this-> c = cp;
|
||||
this-> d = dp;
|
||||
this-> e = ep;
|
||||
this-> f = fp;
|
||||
}
|
||||
|
||||
void
|
||||
QPDFMatrix::scale(double sx, double sy)
|
||||
{
|
||||
concat(QPDFMatrix(sx, 0, 0, sy, 0, 0));
|
||||
}
|
||||
|
||||
void
|
||||
QPDFMatrix::translate(double tx, double ty)
|
||||
{
|
||||
concat(QPDFMatrix(1, 0, 0, 1, tx, ty));
|
||||
}
|
||||
|
||||
void
|
||||
QPDFMatrix::rotatex90(int angle)
|
||||
{
|
||||
switch (angle)
|
||||
{
|
||||
case 90:
|
||||
concat(QPDFMatrix(0, 1, -1, 0, 0, 0));
|
||||
break;
|
||||
case 180:
|
||||
concat(QPDFMatrix(-1, 0, 0, -1, 0, 0));
|
||||
break;
|
||||
case 270:
|
||||
concat(QPDFMatrix(0, -1, 1, 0, 0, 0));
|
||||
break;
|
||||
default:
|
||||
// ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFMatrix::transform(double x, double y, double& xp, double& yp)
|
||||
{
|
||||
xp = (this->a * x) + (this->c * y) + this->e;
|
||||
yp = (this->b * x) + (this->d * y) + this->f;
|
||||
}
|
@ -41,6 +41,7 @@ SRCS_libqpdf = \
|
||||
libqpdf/QPDFAnnotationObjectHelper.cc \
|
||||
libqpdf/QPDFExc.cc \
|
||||
libqpdf/QPDFFormFieldObjectHelper.cc \
|
||||
libqpdf/QPDFMatrix.cc \
|
||||
libqpdf/QPDFNameTreeObjectHelper.cc \
|
||||
libqpdf/QPDFNumberTreeObjectHelper.cc \
|
||||
libqpdf/QPDFObjGen.cc \
|
||||
|
43
libqpdf/qpdf/QPDFMatrix.hh
Normal file
43
libqpdf/qpdf/QPDFMatrix.hh
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef QPDFMATRIX_HH
|
||||
#define QPDFMATRIX_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <string>
|
||||
|
||||
class QPDFMatrix
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFMatrix();
|
||||
QPDF_DLL
|
||||
QPDFMatrix(double a, double b, double c,
|
||||
double d, double e, double f);
|
||||
|
||||
QPDF_DLL
|
||||
std::string unparse() const;
|
||||
|
||||
// This is not part of the public API. Just provide the methods we
|
||||
// need as we need them.
|
||||
QPDF_DLL
|
||||
void concat(QPDFMatrix const& other);
|
||||
QPDF_DLL
|
||||
void scale(double sx, double sy);
|
||||
QPDF_DLL
|
||||
void translate(double tx, double ty);
|
||||
// Any value other than 90, 180, or 270 is ignored
|
||||
QPDF_DLL
|
||||
void rotatex90(int angle);
|
||||
|
||||
QPDF_DLL
|
||||
void transform(double x, double y, double& xp, double& yp);
|
||||
|
||||
private:
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double e;
|
||||
double f;
|
||||
};
|
||||
|
||||
#endif // QPDFMATRIX_HH
|
@ -12,6 +12,7 @@ BINS_libtests = \
|
||||
input_source \
|
||||
json \
|
||||
lzw \
|
||||
matrix \
|
||||
md5 \
|
||||
numrange \
|
||||
pointer_holder \
|
||||
|
55
libtests/matrix.cc
Normal file
55
libtests/matrix.cc
Normal file
@ -0,0 +1,55 @@
|
||||
#include <qpdf/QPDFMatrix.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
static void check(QPDFMatrix const& m, std::string const& exp)
|
||||
{
|
||||
std::string u = m.unparse();
|
||||
if (u != exp)
|
||||
{
|
||||
std::cout << "got " << u << ", wanted " << exp << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void check_xy(double x, double y, std::string const& exp)
|
||||
{
|
||||
std::string u = (QUtil::double_to_string(x, 2) + " " +
|
||||
QUtil::double_to_string(y, 2));
|
||||
if (u != exp)
|
||||
{
|
||||
std::cout << "got " << u << ", wanted " << exp << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
QPDFMatrix m;
|
||||
check(m, "1.00000 0.00000 0.00000 1.00000 0.00000 0.00000");
|
||||
m.translate(10, 20);
|
||||
check(m, "1.00000 0.00000 0.00000 1.00000 10.00000 20.00000");
|
||||
m.scale(1.5, 2);
|
||||
check(m, "1.50000 0.00000 0.00000 2.00000 10.00000 20.00000");
|
||||
m.translate(30, 40);
|
||||
check(m, "1.50000 0.00000 0.00000 2.00000 55.00000 100.00000");
|
||||
m.concat(QPDFMatrix(1, 2, 3, 4, 5, 6));
|
||||
check(m, "1.50000 4.00000 4.50000 8.00000 62.50000 112.00000");
|
||||
m.rotatex90(90);
|
||||
check(m, "4.50000 8.00000 -1.50000 -4.00000 62.50000 112.00000");
|
||||
m.rotatex90(180);
|
||||
check(m, "-4.50000 -8.00000 1.50000 4.00000 62.50000 112.00000");
|
||||
m.rotatex90(270);
|
||||
check(m, "-1.50000 -4.00000 -4.50000 -8.00000 62.50000 112.00000");
|
||||
m.rotatex90(180);
|
||||
check(m, "1.50000 4.00000 4.50000 8.00000 62.50000 112.00000");
|
||||
m.rotatex90(12345);
|
||||
check(m, "1.50000 4.00000 4.50000 8.00000 62.50000 112.00000");
|
||||
|
||||
double xp = 0;
|
||||
double yp = 0;
|
||||
m.transform(240, 480, xp, yp);
|
||||
check_xy(xp, yp, "2582.50 4912.00");
|
||||
|
||||
std::cout << "matrix tests done" << std::endl;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user