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:
parent
c172cf4faa
commit
147adb10f7
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user