pdfviewer: remove dependency on picture_utils. add utility function to render SkStream into bitmap.

Review URL: https://codereview.chromium.org/20087003

git-svn-id: http://skia.googlecode.com/svn/trunk@10314 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
edisonn@google.com 2013-07-24 15:56:19 +00:00
parent c172cf4faa
commit 147adb10f7
6 changed files with 146 additions and 17 deletions

View File

@ -2030,6 +2030,20 @@ bool SkPdfRenderer::load(const SkString inputFileName) {
return fPdfDoc != NULL;
}
bool SkPdfRenderer::load(SkStream* stream) {
unload();
// TODO(edisonn): create static function that could return NULL if there are errors
fPdfDoc = new SkNativeParsedPDF(stream);
if (fPdfDoc->pages() == 0) {
delete fPdfDoc;
fPdfDoc = NULL;
}
return fPdfDoc != NULL;
}
int SkPdfRenderer::pages() const {
return fPdfDoc != NULL ? fPdfDoc->pages() : 0;
}
@ -2047,3 +2061,30 @@ SkRect SkPdfRenderer::MediaBox(int page) const {
size_t SkPdfRenderer::bytesUsed() const {
return fPdfDoc ? fPdfDoc->bytesUsed() : 0;
}
bool SkPDFNativeRenderToBitmap(SkStream* stream,
SkBitmap* output,
int page,
SkPdfContent content,
double dpi) {
SkASSERT(page >= 0);
SkPdfRenderer renderer;
renderer.load(stream);
if (!renderer.loaded() || page >= renderer.pages() || page < 0) {
return false;
}
SkRect rect = renderer.MediaBox(page < 0 ? 0 :page);
SkScalar width = SkScalarMul(rect.width(), SkDoubleToScalar(sqrt(dpi / 72.0)));
SkScalar height = SkScalarMul(rect.height(), SkDoubleToScalar(sqrt(dpi / 72.0)));
rect = SkRect::MakeWH(width, height);
setup_bitmap(output, (int)SkScalarToDouble(width), (int)SkScalarToDouble(height));
SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (*output)));
SkCanvas canvas(device);
return renderer.renderPage(page, &canvas, rect);
}

View File

@ -9,9 +9,16 @@
#ifndef SkPdfRenderer_DEFINED
#define SkPdfRenderer_DEFINED
class SkBitmap;
class SkCanvas;
class SkNativeParsedPDF;
class SkRect;
class SkStream;
enum SkPdfContent {
kNoForms_SkPdfContent,
kAll_SkPdfContent,
};
// TODO(edisonn): move in another file
class SkPdfRenderer : public SkRefCnt {
@ -24,6 +31,7 @@ public:
bool renderPage(int page, SkCanvas* canvas, const SkRect& dst) const;
bool load(const SkString inputFileName);
bool load(SkStream* stream);
bool loaded() const {return fPdfDoc != NULL;}
int pages() const;
void unload();
@ -33,4 +41,10 @@ public:
void reportPdfRenderStats();
bool SkPDFNativeRenderToBitmap(SkStream* stream,
SkBitmap* output,
int page = 0,
SkPdfContent content = kAll_SkPdfContent,
double dpi = 72.0);
#endif // SkPdfRenderer_DEFINED

View File

@ -9,7 +9,6 @@
#include "SkStream.h"
#include "SkTypeface.h"
#include "SkTArray.h"
#include "picture_utils.h"
#include "SkNulCanvas.h"
#include "SkPdfRenderer.h"
@ -74,6 +73,56 @@ static bool add_page_and_replace_filename_extension(SkString* path, int page,
return false;
}
void make_filepath(SkString* path, const SkString& dir, const SkString& name) {
size_t len = dir.size();
path->set(dir);
if (0 < len && '/' != dir[len - 1]) {
path->append("/");
}
path->append(name);
}
bool is_path_seperator(const char chr) {
#if defined(SK_BUILD_FOR_WIN)
return chr == '\\' || chr == '/';
#else
return chr == '/';
#endif
}
void get_basename(SkString* basename, const SkString& path) {
if (path.size() == 0) {
basename->reset();
return;
}
size_t end = path.size() - 1;
// Paths pointing to directories often have a trailing slash,
// we remove it so the name is not empty
if (is_path_seperator(path[end])) {
if (end == 0) {
basename->reset();
return;
}
end -= 1;
}
size_t i = end;
do {
--i;
if (is_path_seperator(path[i])) {
const char* basenameStart = path.c_str() + i + 1;
size_t basenameLength = end - i;
basename->set(basenameStart, basenameLength);
return;
}
} while (i > 0);
basename->set(path.c_str(), end + 1);
}
/** Builds the output filename. path = dir/name, and it replaces expected
* .skp extension with .pdf extention.
* @param path Output filename.
@ -81,12 +130,10 @@ static bool add_page_and_replace_filename_extension(SkString* path, int page,
* @returns false if the file did not has the expected extension.
* if false is returned, contents of path are undefined.
*/
static bool make_output_filepath(SkString* path, const SkString& dir,
const SkString& name,
int page) {
sk_tools::make_filepath(path, dir, name);
make_filepath(path, dir, name);
return add_page_and_replace_filename_extension(path, page,
PDF_FILE_EXTENSION,
PNG_FILE_EXTENSION);
@ -167,7 +214,7 @@ static bool process_pdf(const SkString& inputPath, const SkString& outputDir,
SkDebugf("Loading PDF: %s\n", inputPath.c_str());
SkString inputFilename;
sk_tools::get_basename(&inputFilename, inputPath);
get_basename(&inputFilename, inputPath);
SkFILEStream inputStream;
inputStream.setPath(inputPath.c_str());
@ -241,7 +288,7 @@ static int process_input(const char* input, const SkString& outputDir,
SkString inputPath;
SkString _input;
_input.append(input);
sk_tools::make_filepath(&inputPath, _input, inputFilename);
make_filepath(&inputPath, _input, inputFilename);
if (!process_pdf(inputPath, outputDir, renderer)) {
++failures;
}

View File

@ -14,6 +14,7 @@
#include "SkPdfPageTreeNodeDictionary_autogen.h"
#include "SkPdfMapper_autogen.h"
#include "SkStream.h"
static long getFileSize(const char* filename)
@ -67,25 +68,48 @@ SkNativeParsedPDF* gDoc = NULL;
// 1) run on a lot of file
// 2) recoverable corupt file: remove endobj, endsteam, remove other keywords, use other white spaces, insert comments randomly, ...
// 3) irrecoverable corrupt file
SkNativeParsedPDF::SkNativeParsedPDF(SkStream* stream)
: fAllocator(new SkPdfAllocator())
, fFileContent(NULL)
, fContentLength(0)
, fRootCatalogRef(NULL)
, fRootCatalog(NULL) {
size_t size = stream->getLength();
void* ptr = sk_malloc_throw(size);
stream->read(ptr, size);
init(ptr, size);
}
SkNativeParsedPDF::SkNativeParsedPDF(const char* path)
: fAllocator(new SkPdfAllocator())
, fFileContent(NULL)
, fContentLength(0)
, fRootCatalogRef(NULL)
, fRootCatalog(NULL) {
gDoc = this;
FILE* file = fopen(path, "r");
fContentLength = getFileSize(path);
unsigned char* content = new unsigned char[fContentLength + 1];
bool ok = (0 != fread(content, fContentLength, 1, file));
content[fContentLength] = '\0';
fFileContent = content;
size_t size = getFileSize(path);
void* content = sk_malloc_throw(size);
bool ok = (0 != fread(content, size, 1, file));
fclose(file);
file = NULL;
if (!ok) {
sk_free(content);
// TODO(edisonn): report read error
// TODO(edisonn): not nice to return like this from constructor, create a static
// function that can report NULL for failures.
return; // Doc will have 0 pages
}
init(content, size);
}
void SkNativeParsedPDF::init(const void* bytes, size_t length) {
fFileContent = (const unsigned char*)bytes;
fContentLength = length;
const unsigned char* eofLine = lineHome(fFileContent, fFileContent + fContentLength - 1);
const unsigned char* xrefByteOffsetLine = previousLineHome(fFileContent, eofLine);
const unsigned char* xrefstartKeywordLine = previousLineHome(fFileContent, xrefByteOffsetLine);
@ -126,7 +150,7 @@ SkNativeParsedPDF::SkNativeParsedPDF(const char* path)
// TODO(edisonn): NYI
SkNativeParsedPDF::~SkNativeParsedPDF() {
delete[] fFileContent;
sk_free((void*)fFileContent);
delete fAllocator;
}

View File

@ -19,6 +19,8 @@ class SkPdfPageTreeNodeDictionary;
class SkPdfNativeTokenizer;
class SkStream;
class SkNativeParsedPDF {
private:
struct PublicObjectEntry {
@ -35,7 +37,10 @@ public:
// TODO(edisonn): read page N asap, read all file
// TODO(edisonn): allow corruptions of file (e.g. missing endobj, missing stream length, ...)
// TODO(edisonn): encryption
SkNativeParsedPDF(const char* path);
SkNativeParsedPDF(SkStream* stream);
~SkNativeParsedPDF();
int pages() const;
@ -65,6 +70,9 @@ public:
private:
// Takes ownership of bytes.
void init(const void* bytes, size_t length);
const unsigned char* readCrossReferenceSection(const unsigned char* xrefStart, const unsigned char* trailerEnd);
long readTrailer(const unsigned char* trailerStart, const unsigned char* trailerEnd, bool storeCatalog);

View File

@ -11,10 +11,6 @@
{
'target_name': 'libpdfviewer',
'type': 'static_library',
'cflags': ['-fexceptions'],
'cflags_cc': ['-fexceptions'],
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ],
'sources': [
'../experimental/PdfViewer/SkPdfBasics.cpp',
'../experimental/PdfViewer/SkPdfFont.cpp',
@ -91,7 +87,6 @@
'core.gyp:core',
'flags.gyp:flags',
'libpdfviewer',
'tools.gyp:picture_utils',
],
},
],