Skip to content

Instantly share code, notes, and snippets.

@iamtekeste
Created April 12, 2020 03:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamtekeste/847f91ee46317ab8fb7ca523f8fdf049 to your computer and use it in GitHub Desktop.
Save iamtekeste/847f91ee46317ab8fb7ca523f8fdf049 to your computer and use it in GitHub Desktop.
#include "config.h"
#include <poppler-config.h>
#include <cstdint>
#include <cstdio>
#include <cmath>
#include <cstring>
#include "goo/gmem.h"
#include "goo/GooString.h"
#include "GlobalParams.h"
#include "Object.h"
#include "PDFDoc.h"
#include "PDFDocFactory.h"
#include "CairoOutputDev.h"
#include "numberofcharacters.h"
#include <cairo.h>
#include <cairo-svg.h>
static bool useMediaBox = true;
static bool printing = true;
static double resolution = 0.0;
static double x_resolution = 150.0;
static double y_resolution = 150.0;
static int scaleTo = 0;
static int x_scaleTo = 0;
static int y_scaleTo = 0;
static int crop_x = 0;
static int crop_y = 0;
static int crop_w = 0;
static int crop_h = 0;
static int sz = 0;
static cairo_surface_t *surface;
static FILE *output_file;
static void getCropSize(double page_w, double page_h, double *width, double *height)
{
int w = crop_w;
int h = crop_h;
if (w == 0)
w = (int)ceil(page_w);
if (h == 0)
h = (int)ceil(page_h);
*width = (crop_x + w > page_w ? (int)ceil(page_w - crop_x) : w);
*height = (crop_y + h > page_h ? (int)ceil(page_h - crop_y) : h);
}
static void getOutputSize(double page_w, double page_h, double *width, double *height)
{
*width = page_w;
*height = page_h;
}
static void getFitToPageTransform(double page_w, double page_h,
double paper_w, double paper_h,
cairo_matrix_t *m)
{
double x_scale, y_scale, scale;
x_scale = paper_w / page_w;
y_scale = paper_h / page_h;
if (x_scale < y_scale)
scale = x_scale;
else
scale = y_scale;
if (scale > 1.0 && !expand)
scale = 1.0;
if (scale < 1.0 && noShrink)
scale = 1.0;
cairo_matrix_init_identity (m);
if (!noCenter) {
// centre page
cairo_matrix_translate (m, (paper_w - page_w*scale)/2, (paper_h - page_h*scale)/2);
} else if (!svg) {
// move to PostScript origin
cairo_matrix_translate (m, 0, (paper_h - page_h*scale));
}
cairo_matrix_scale (m, scale, scale);
}
static cairo_status_t writeStream(void *closure, const unsigned char *data, unsigned int length)
{
FILE *file = (FILE *)closure;
if (fwrite(data, length, 1, file) == 1)
return CAIRO_STATUS_SUCCESS;
else
return CAIRO_STATUS_WRITE_ERROR;
}
static void beginDocument(GooString *outputFileName, double w, double h)
{
output_file = fopen(outputFileName->c_str(), "wb");
if (!output_file) {
fprintf(stderr, "Error opening output file %s\n", outputFileName->c_str());
exit(2);
}
surface = cairo_svg_surface_create_for_stream(writeStream, output_file, w, h);
cairo_svg_surface_restrict_to_version (surface, CAIRO_SVG_VERSION_1_2);
}
static void beginPage(double *w, double *h)
{
cairo_surface_set_fallback_resolution (surface, x_resolution, y_resolution);
}
static void renderPage(PDFDoc *doc, CairoOutputDev *cairoOut, int pg,
double page_w, double page_h,
double output_w, double output_h)
{
cairo_t *cr;
cairo_status_t status;
cairo_matrix_t m;
cr = cairo_create(surface);
cairoOut->setCairo(cr);
cairoOut->setPrinting(printing);
cairo_save(cr);
cairo_translate (cr, -crop_x, -crop_y);
double cropped_w, cropped_h;
getCropSize(page_w, page_h, &cropped_w, &cropped_h);
getFitToPageTransform(cropped_w, cropped_h, output_w, output_h, &m);
cairo_transform (cr, &m);
cairo_rectangle(cr, crop_x, crop_y, cropped_w, cropped_h);
cairo_clip(cr);
doc->displayPageSlice(cairoOut,
pg,
72.0, 72.0,
0, /* rotate */
useMediaBox, /* useMediaBox */
false, /* Crop */
printing,
-1, -1, -1, -1);
cairo_restore(cr);
cairoOut->setCairo(nullptr);
status = cairo_status(cr);
if (status)
fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
cairo_destroy (cr);
}
static void endPage()
{
cairo_surface_show_page(surface);
}
static void endDocument()
{
cairo_status_t status;
if (printing) {
cairo_surface_finish(surface);
status = cairo_surface_status(surface);
if (status)
fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
cairo_surface_destroy(surface);
if (output_file)
fclose(output_file);
}
}
int getNumberOfPages (char *inputFileName) {
PDFDoc *doc;
GooString *fileName = new GooString(inputFileName);
doc = PDFDocFactory().createPDFDoc(*fileName, nullptr, nullptr);
if (!doc->isOk()) {
fprintf(stderr, "Error opening PDF file.\n");
exit(1);
}
return doc->getNumPages();
}
int myConverter(int pageNumber, char *inputFileName, char *outputFileName) {
PDFDoc *doc;
GooString *fileName = new GooString(inputFileName);
GooString *outputName = new GooString(outputFileName);;
CairoOutputDev *cairoOut;
int pg, pg_num_len;
double pg_w, pg_h, tmp, output_w, output_h;
doc = PDFDocFactory().createPDFDoc(*fileName, nullptr, nullptr);
if (!doc->isOk()) {
fprintf(stderr, "Error opening PDF file.\n");
exit(1);
}
cairoOut = new CairoOutputDev();
cairoOut->startDoc(doc);
pg_w = doc->getPageMediaWidth(pageNumber);
pg_h = doc->getPageMediaHeight(pageNumber);
if ((doc->getPageRotate(pageNumber) == 90) || (doc->getPageRotate(pageNumber) == 270)) {
tmp = pg_w;
pg_w = pg_h;
pg_h = tmp;
}
getOutputSize(pg_w, pg_h, &output_w, &output_h);
beginDocument(outputName, output_w, output_h);
beginPage(&output_w, &output_h);
renderPage(doc, cairoOut, pg, pg_w, pg_h, output_w, output_h);
endPage();
endDocument();
// clean up
delete cairoOut;
delete doc;
if (fileName)
delete fileName;
if (outputName)
delete outputName;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment