* (c) 2018 Martin Mares <mj@ucw.cz>
*/
-#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <iconv.h>
-using namespace std;
-
-#include "pdf-tools.h"
+#include "jam.h"
#include <qpdf/QUtil.hh>
#include <qpdf/Pl_Concatenate.hh>
-/*** Messages ***/
-
-int debug_mode;
-int debug_indent;
-
-void debug(const char *msg, ...)
-{
- if (!debug_mode)
- return;
- va_list args;
- va_start(args, msg);
- fprintf(stderr, "%*s", debug_indent, "");
- vfprintf(stderr, msg, args);
- fputc('\n', stderr);
- va_end(args);
-}
-
-void warn(const char *msg, ...)
-{
- va_list args;
- va_start(args, msg);
- fprintf(stderr, "WARNING: ");
- vfprintf(stderr, msg, args);
- fputc('\n', stderr);
- va_end(args);
-}
-
-void die(const char *msg, ...)
-{
- va_list args;
- va_start(args, msg);
- fprintf(stderr, "ERROR: ");
- vfprintf(stderr, msg, args);
- fputc('\n', stderr);
- va_end(args);
- exit(1);
-}
-
-void bad(const char *msg, ...)
-{
- va_list args;
- va_start(args, msg);
- char buf[1024];
- vsnprintf(buf, sizeof(buf), msg, args);
- va_end(args);
-
- printf("error: %s\n", buf);
- die("BAD: %s", buf);
-}
-
/*** Transformation matrices ***/
// Construct string representation of a transformation matrix
for (int i=0; i<6; i++) {
if (i)
s += " ";
- char buf[16];
- snprintf(buf, sizeof(buf), "%.3f", m[i]);
- s += buf;
+ s += pdf_coord(m[i], 6);
}
return s;
}
string BBox::to_rect()
{
- char buf[64];
- snprintf(buf, sizeof(buf), "%.1f %.1f %.1f %.1f", x_min, y_min, width(), height());
- return string(buf);
+ return
+ pdf_coord(x_min) + " " +
+ pdf_coord(y_min) + " " +
+ pdf_coord(width()) + " " +
+ pdf_coord(height());
}
bool BBox::parse(QPDFObjectHandle h)
return true;
}
+BBox::BBox(QPDFObjectHandle box) {
+ if (!parse(box)) {
+ warn("Invalid bounding box, falling back to A4");
+ x_min = 0, x_max = A4_WIDTH;
+ y_min = 0, y_max = A4_HEIGHT;
+ }
+}
+
void BBox::transform(pdf_matrix &m)
{
m.apply(&x_min, &y_min);
swap(y_min, y_max);
}
+BBox BBox::transformed(pdf_matrix &m)
+{
+ BBox b = *this;
+ b.transform(m);
+ return b;
+}
+
+void BBox::join(BBox &with)
+{
+ x_min = min(x_min, with.x_min);
+ x_max = max(x_max, with.x_max);
+ y_min = min(y_min, with.y_min);
+ y_max = max(y_max, with.y_max);
+}
+
+static double clamp(double x, double min, double max)
+{
+ if (x < min)
+ return min;
+ if (x > max)
+ return max;
+ return x;
+}
+
+void BBox::intersect(BBox &with)
+{
+ x_min = clamp(x_min, with.x_min, with.x_max);
+ x_max = clamp(x_max, with.x_min, with.x_max);
+ y_min = clamp(y_min, with.y_min, with.y_max);
+ y_max = clamp(y_max, with.y_min, with.y_max);
+}
+
+void BBox::enlarge(double by)
+{
+ x_min -= by;
+ x_max += by;
+ y_min -= by;
+ y_max += by;
+}
+
+BBox BBox::enlarged(double by)
+{
+ BBox b = *this;
+ b.enlarge(by);
+ return b;
+}
+
/*** Unicode strings ***/
// Construct PDF representation of a UTF-8 string
xo_stream.replaceStreamData(ph, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
return xo_stream;
}
+
+/*** Formatting of coordinates ***/
+
+string pdf_coord(double x, uint digits)
+{
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%.*f", digits, x);
+ int n = strlen(buf);
+ while (n > 0 && buf[n-1] == '0')
+ buf[--n] = 0;
+ if (n > 0 && buf[n-1] == '.')
+ buf[--n] = 0;
+ return buf;
+}