Bug#893314: inkscape: please make the command-line PDF output reproducible
Chris Lamb
lamby at debian.org
Sat Mar 17 22:18:12 UTC 2018
Source: inkscape
Version: 0.92.3~pre0-1
Severity: wishlist
Tags: patch
User: reproducible-builds at lists.alioth.debian.org
Usertags: timestamps toolchain
X-Debbugs-Cc: reproducible-bugs at lists.alioth.debian.org
Hi,
Whilst working on the Reproducible Builds effort [0], we noticed
that inkscape generates output that is not reproducible:
$ cp /usr/share/icons/gnome/scalable/places/debian-swirl.svg .
$ inkscape -z debian-swirl.svg --export-width=25 --export-pdf=a.pdf
$ sleep 1
$ inkscape -z debian-swirl.svg --export-width=25 --export-pdf=b.pdf
$ sha1sum *.pdf
bee6f300a8fce628e94febd0700fa97f90aa7b37 a.pdf
32f26595ec1957c7e714174e007c452f6cb5dd79 b.pdf
This is affecting (at least) the "debian-astro" package:
│ │ │ ├── ./usr/share/pixmaps/Debian-Astro-logo.pdf
│ │ │ │ ├── pdftk {} output - uncompress
│ │ │ │ │ @@ -357,15 +357,15 @@
│ │ │ │ │ <<
│ │ │ │ │ /Type /Catalog
│ │ │ │ │ /Pages 1 0 R
│ │ │ │ │ >>
│ │ │ │ │ endobj
│ │ │ │ │ 6 0 obj
│ │ │ │ │ <<
│ │ │ │ │ -/CreationDate (D:20180315093948-12'00)
│ │ │ │ │ +/CreationDate (D:20190418180346+14'00)
│ │ │ │ │ /Producer (cairo 1.15.10 \(http://cairographics.org\))
│ │ │ │ │ >>
│ │ │ │ │ endobj xref
Patch attached. After applying:
$ export SOURCE_DATE_EPOCH=1521324801
[…]
$ sha1sum *.pdf
620bf8469600ab744ffa6fcc3eee4c6845f4f159 a.pdf
620bf8469600ab744ffa6fcc3eee4c6845f4f159 b.pdf
:)
[0] https://reproducible-builds.org/
Regards,
--
,''`.
: :' : Chris Lamb
`. `'` lamby at debian.org / chris-lamb.co.uk
`-
-------------- next part --------------
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index f606805..5c1479f 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -26,7 +26,10 @@
#include <signal.h>
+#include <limits.h>
#include <errno.h>
+#include <time.h>
+#include <stdlib.h>
#include <2geom/pathvector.h>
#include <glib.h>
@@ -796,6 +799,12 @@ CairoRenderContext::setupSurface(double width, double height)
cairo_surface_t *surface = NULL;
cairo_matrix_t ctm;
cairo_matrix_init_identity (&ctm);
+ char buffer[25];
+ char *endptr;
+ char *source_date_epoch;
+ time_t now;
+ struct tm *build_time;
+ unsigned long long epoch;
switch (_target) {
case CAIRO_SURFACE_TYPE_IMAGE:
surface = cairo_image_surface_create(_target_format, (int)ceil(width), (int)ceil(height));
@@ -804,6 +813,38 @@ CairoRenderContext::setupSurface(double width, double height)
case CAIRO_SURFACE_TYPE_PDF:
surface = cairo_pdf_surface_create_for_stream(Inkscape::Extension::Internal::_write_callback, _stream, width, height);
cairo_pdf_surface_restrict_to_version(surface, (cairo_pdf_version_t)_pdf_level);
+ source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+ if (source_date_epoch) {
+ errno = 0;
+ epoch = strtoull(source_date_epoch, &endptr, 10);
+ if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+ || (errno != 0 && epoch == 0)) {
+ g_printerr ("Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n",
+ strerror(errno));
+ exit (1);
+ }
+ if (endptr == source_date_epoch) {
+ g_printerr ("Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n",
+ endptr);
+ exit (1);
+ }
+ if (*endptr != '\0') {
+ g_printerr ("Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n",
+ endptr);
+ exit (1);
+ }
+ if (epoch > ULONG_MAX) {
+ g_printerr ("Environment variable $SOURCE_DATE_EPOCH: must be <= %lu but saw: %llu\n",
+ ULONG_MAX, epoch);
+ exit (1);
+ }
+ now = (time_t)epoch;
+ build_time = gmtime(&now);
+ strftime(buffer, 25, "%Y-%m-%dT%H:%M:%S%z", build_time);
+ cairo_pdf_surface_set_metadata (surface,
+ CAIRO_PDF_METADATA_CREATE_DATE,
+ buffer);
+ }
break;
#endif
#ifdef CAIRO_HAS_PS_SURFACE
More information about the Reproducible-bugs
mailing list