summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/extension/internal/cairo-render-context.cpp49
-rw-r--r--src/extension/internal/cairo-renderer.cpp11
-rw-r--r--src/include/source_date_epoch.h68
3 files changed, 83 insertions, 45 deletions
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index 2b4072336..4464742dd 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -27,10 +27,7 @@
#include <csignal>
-#include <climits>
#include <cerrno>
-#include <ctime>
-#include <cstdlib>
#include <2geom/pathvector.h>
#include <glib.h>
@@ -814,12 +811,6 @@ CairoRenderContext::setupSurface(double width, double height)
cairo_surface_t *surface = nullptr;
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));
@@ -828,40 +819,6 @@ 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);
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 4)
- 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);
- }
-#endif
break;
#endif
#ifdef CAIRO_HAS_PS_SURFACE
@@ -957,6 +914,12 @@ CairoRenderContext::_setSurfaceMetadata(cairo_surface_t *surface)
if (!_metadata.creator.empty()) {
cairo_pdf_surface_set_metadata(surface, CAIRO_PDF_METADATA_CREATOR, _metadata.creator.c_str());
}
+ if (!_metadata.cdate.empty()) {
+ cairo_pdf_surface_set_metadata(surface, CAIRO_PDF_METADATA_CREATE_DATE, _metadata.cdate.c_str());
+ }
+ if (!_metadata.mdate.empty()) {
+ cairo_pdf_surface_set_metadata(surface, CAIRO_PDF_METADATA_MOD_DATE, _metadata.mdate.c_str());
+ }
break;
#endif
#if defined CAIRO_HAS_PS_SURFACE
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index 35531cb04..170abe9a7 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -61,6 +61,8 @@
#include "io/sys.h"
+#include "include/source_date_epoch.h"
+
#include "libnrtype/Layout-TNG.h"
#include "object/sp-anchor.h"
@@ -697,8 +699,13 @@ void CairoRenderer::setMetadata(CairoRenderContext *ctx, SPDocument *doc) {
ctx->_metadata.creator = Glib::ustring::compose("Inkscape %1 (https://inkscape.org)",
Inkscape::version_string_without_revision);
- // cdate / mdate
- // (currently unused)
+ // cdate (only used for for reproducible builds hack)
+ Glib::ustring cdate = ReproducibleBuilds::now_iso_8601();
+ if (!cdate.empty()) {
+ ctx->_metadata.cdate = cdate;
+ }
+
+ // mdate (currently unused)
}
bool
diff --git a/src/include/source_date_epoch.h b/src/include/source_date_epoch.h
new file mode 100644
index 000000000..9080526f7
--- /dev/null
+++ b/src/include/source_date_epoch.h
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/** @file
+ * Functions to parse the "SOURCE_DATE_EPOCH" environment variable for reproducible build hacks, see
+ * https://reproducible-builds.org/docs/source-date-epoch/
+ *//*
+ * Authors:
+ * Patrick Storz <eduard.braun2@gmx.de>
+ *
+ * Copyright (C) 2019 Authors
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#ifndef SEEN_SOURCE_DATE_EPOCH
+#define SEEN_SOURCE_DATE_EPOCH
+
+#include <sstream>
+#include <iostream>
+#include <cstdlib>
+#include <ctime>
+
+namespace ReproducibleBuilds {
+
+/** parse current time from SOURCE_DATE_EPOCH environment variable
+ *
+ * \return current time (or zero if SOURCE_DATE_EPOCH unset)
+ */
+time_t now()
+{
+ time_t now = 0;
+
+ char *source_date_epoch = std::getenv("SOURCE_DATE_EPOCH");
+ if (source_date_epoch) {
+ std::istringstream iss(source_date_epoch);
+ iss >> now;
+ if (iss.fail() || !iss.eof()) {
+ std::cerr << "Error: Cannot parse SOURCE_DATE_EPOCH as integer\n";
+ exit(27);
+ }
+ }
+
+ return now;
+}
+
+/** like ReproducibleBuilds::now() but returns a ISO 8601 formatted string
+ *
+ * \return current time as ISO 8601 formatted string (or empty string if SOURCE_DATE_EPOCH unset)
+ */
+Glib::ustring now_iso_8601()
+{
+ Glib::ustring now_formatted;
+
+ time_t now = ReproducibleBuilds::now();
+ if (now) {
+ const tm *now_struct;
+ char buffer[25];
+
+ now_struct = gmtime(&now);
+ if (strftime(buffer, 25, "%Y-%m-%dT%H:%M:%S", now_struct)) {
+ now_formatted = buffer;
+ }
+ }
+
+ return now_formatted;
+}
+
+} // namespace ReproducibleBuilds
+
+#endif // SEEN_SOURCE_DATE_EPOCH