Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add rendering to stdout and stderr.

This feature renders PDF, GIF and other format supported by Qt to
stdout or stderr.

*NOTE*
"/dev/stdout" and "/dev/stderr" are converted to System::stdout and
System::stderr on Windows.

Issue: https://code.google.com/p/phantomjs/issues/detail?id=973
  • Loading branch information...
commit 0734811514a88f5c5f16fbd0df19a0eafd285d15 1 parent 6d81933
@bongole bongole authored committed
View
108 src/webpage.cpp
@@ -54,6 +54,7 @@
#include <QBuffer>
#include <QDebug>
#include <QImageWriter>
+#include <QUuid>
#include <gifwriter.h>
@@ -64,6 +65,12 @@
#include "consts.h"
#include "callback.h"
#include "cookiejar.h"
+#include "system.h"
+
+#ifdef Q_OS_WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif
// Ensure we have at least head and body.
#define BLANK_HTML "<html><head></head><body></body></html>"
@@ -72,6 +79,9 @@
#define CALLBACKS_OBJECT_INJECTION INPAGE_CALL_NAME" = function() { return window."CALLBACKS_OBJECT_NAME".call.call(_phantom, Array.prototype.splice.call(arguments, 0)); };"
#define CALLBACKS_OBJECT_PRESENT "typeof(window."CALLBACKS_OBJECT_NAME") !== \"undefined\";"
+#define STDOUT_FILENAME "/dev/stdout"
+#define STDERR_FILENAME "/dev/stderr"
+
/**
* @class CustomPage
@@ -819,24 +829,102 @@ void WebPage::close() {
deleteLater();
}
-bool WebPage::render(const QString &fileName)
+bool WebPage::render(const QString &fileName, const QVariantMap &option)
{
if (m_mainFrame->contentsSize().isEmpty())
return false;
- QFileInfo fileInfo(fileName);
- QDir dir;
- dir.mkpath(fileInfo.absolutePath());
+ QString outFileName = fileName;
+ QString tempFileName = "";
+
+ QString format = "";
+ int quality = -1; // QImage#save default
+
+ if( fileName == STDOUT_FILENAME || fileName == STDERR_FILENAME ){
+ if( !QFile::exists(fileName) ){
+ // create temporary file for OS that have no /dev/stdout or /dev/stderr. (ex. windows)
+ tempFileName = QDir::tempPath() + "/phantomjstemp" + QUuid::createUuid().toString();
+ outFileName = tempFileName;
+ }
+
+ format = "png"; // default format for stdout and stderr
+ }
+ else{
+ QFileInfo fileInfo(outFileName);
+ QDir dir;
+ dir.mkpath(fileInfo.absolutePath());
+ }
+
+ if( option.contains("format") ){
+ format = option.value("format").toString();
+ }
+ else if (fileName.endsWith(".pdf", Qt::CaseInsensitive) ){
+ format = "pdf";
+ }
+ else if (fileName.endsWith(".gif", Qt::CaseInsensitive) ){
+ format = "gif";
+ }
+
+ if( option.contains("quality") ){
+ quality = option.value("quality").toInt();
+ }
+
+ bool retval = true;
+ if ( format == "pdf" ){
+ retval = renderPdf(outFileName);
+ }
+ else if ( format == "gif" ) {
+ QImage rawPageRendering = renderImage();
+ retval = exportGif(rawPageRendering, outFileName);
+ }
+ else{
+ QImage rawPageRendering = renderImage();
+
+ const char *f = 0; // 0 is QImage#save default
+ if( format != "" ){
+ f = format.toUtf8().constData();
+ }
+
+ retval = rawPageRendering.save(outFileName, f, quality);
+ }
+
+ if( tempFileName != "" ){
+ // cleanup temporary file and render to stdout or stderr
+ QFile i(tempFileName);
+ i.open(QIODevice::ReadOnly);
+
+ QByteArray ba = i.readAll();
+
+ System *system = (System*)Phantom::instance()->createSystem();
+ if( fileName == STDOUT_FILENAME ){
+#ifdef Q_OS_WIN32
+ _setmode(_fileno(stdout), O_BINARY);
+#endif
+
+ ((File *)system->_stdout())->write(QString::fromAscii(ba.constData(), ba.size()));
+
+#ifdef Q_OS_WIN32
+ _setmode(_fileno(stdout), O_TEXT);
+#endif
+ }
+ else if( fileName == STDERR_FILENAME ){
+#ifdef Q_OS_WIN32
+ _setmode(_fileno(stderr), O_BINARY);
+#endif
+
+ ((File *)system->_stderr())->write(QString::fromAscii(ba.constData(), ba.size()));
+
+#ifdef Q_OS_WIN32
+ _setmode(_fileno(stderr), O_TEXT);
+#endif
+ }
- if (fileName.endsWith(".pdf", Qt::CaseInsensitive))
- return renderPdf(fileName);
+ i.close();
- QImage buffer = renderImage();
- if (fileName.toLower().endsWith(".gif")) {
- return exportGif(buffer, fileName);
+ QFile::remove(tempFileName);
}
- return buffer.save(fileName);
+ return retval;
}
QString WebPage::renderBase64(const QByteArray &format)
View
2  src/webpage.h
@@ -233,7 +233,7 @@ public slots:
void close();
QVariant evaluateJavaScript(const QString &code);
- bool render(const QString &fileName);
+ bool render(const QString &fileName, const QVariantMap &map = QVariantMap());
/**
* Render the page as base-64 encoded string.
* Default image format is "png".
View
BIN  test/webpage-spec-renders/image.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
15 test/webpage-spec-renders/index.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title></title>
+ <style>
+ body {
+ background-color: #000;
+ }
+ </style>
+</head>
+<body>
+ <img src="image.jpg">
+</body>
+</html>
View
BIN  test/webpage-spec-renders/test.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  test/webpage-spec-renders/test.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  test/webpage-spec-renders/test.pdf
Binary file not shown
View
BIN  test/webpage-spec-renders/test.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  test/webpage-spec-renders/test50.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
82 test/webpage-spec.js
@@ -1718,3 +1718,85 @@ describe('WebPage navigation events', function() {
});
});
});
+
+describe("WebPage render image", function(){
+ var TEST_FILE_DIR = "webpage-spec-renders/";
+
+ var p = require("webpage").create();
+ p.paperSize = { width: '300px', height: '300px', border: '0px' };
+ p.clipRect = { top: 0, left: 0, width: 300, height: 300};
+ p.viewportSize = { width: 300, height: 300};
+
+ p.open( TEST_FILE_DIR + "index.html");
+ waits(50);
+
+ function render_test( format, option ){
+ var opt = option || {};
+ var content, expect_content;
+ try {
+ var FILE_EXTENSION = format;
+ var FILE_NAME = "test";
+ var EXPECT_FILE;
+ if( opt.quality ){
+ EXPECT_FILE = TEST_FILE_DIR + FILE_NAME + opt.quality + "." + FILE_EXTENSION;
+ }
+ else{
+ EXPECT_FILE = TEST_FILE_DIR + FILE_NAME + "." + FILE_EXTENSION;
+ }
+
+ var TEST_FILE;
+ if( opt.format ){
+ TEST_FILE = TEST_FILE_DIR + "temp_" + FILE_NAME;
+ }
+ else{
+ TEST_FILE = TEST_FILE_DIR + "temp_" + FILE_NAME + "." + FILE_EXTENSION;
+ }
+
+ p.render(TEST_FILE, opt);
+
+ expect_content = fs.read(EXPECT_FILE, "b");
+ content = fs.read(TEST_FILE, "b");
+
+ fs.remove(TEST_FILE);
+ } catch (e) { console.log(e) }
+
+ // for PDF test
+ content = content.replace(/CreationDate \(D:\d+\)Z\)/,'');
+ expect_content = expect_content.replace(/CreationDate \(D:\d+\)Z\)/,'');
+
+ expect(content).toEqual(expect_content);
+ }
+
+ it("should render PDF file", function(){
+ render_test("pdf");
+ });
+
+ it("should render PDF file with format option", function(){
+ render_test("pdf", { format: "pdf" });
+ });
+
+ it("should render GIF file", function(){
+ render_test("gif");
+ });
+
+ it("should render GIF file with format option", function(){
+ render_test("gif", { format: "gif" });
+ });
+
+ it("should render PNG file", function(){
+ render_test("png");
+ });
+
+ it("should render PNG file with format option", function(){
+ render_test("png", { format: "png" });
+ });
+
+ it("should render JPEG file with quality option", function(){
+ render_test("jpg", { quality: 50 });
+ });
+
+ it("should render JPEG file with format and quality option", function(){
+ render_test("jpg", { format: 'jpg', quality: 50 });
+ });
+
+});
Please sign in to comment.
Something went wrong with that request. Please try again.