summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc31
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h20
-rw-r--r--chrome/common/render_messages_internal.h10
-rw-r--r--chrome/common/temp_scaffolding_stubs.cc52
-rw-r--r--chrome/common/temp_scaffolding_stubs.h10
-rw-r--r--chrome/renderer/print_web_view_helper.cc28
-rw-r--r--chrome/renderer/print_web_view_helper.h20
-rw-r--r--chrome/renderer/print_web_view_helper_linux.cc107
-rw-r--r--chrome/renderer/print_web_view_helper_mac.cc6
-rw-r--r--chrome/renderer/print_web_view_helper_win.cc34
-rw-r--r--skia/ext/vector_canvas.h19
-rw-r--r--skia/ext/vector_canvas_linux.cc22
-rw-r--r--skia/ext/vector_platform_device_linux.cc35
-rw-r--r--skia/ext/vector_platform_device_linux.h23
14 files changed, 308 insertions, 109 deletions
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index b460814..059f2af 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -323,7 +323,13 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
OnGetPreferredExtensionForMimeType)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPBrowsingContext,
OnGetCPBrowsingContext)
+#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection)
+#endif
+#if defined(OS_LINUX)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateShareMemory,
+ OnAllocateShareMemory)
+#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings,
@@ -675,6 +681,7 @@ void ResourceMessageFilter::OnGetCPBrowsingContext(uint32* context) {
CPBrowsingContextManager::Instance()->Allocate(request_context_.get());
}
+#if defined(OS_WIN)
void ResourceMessageFilter::OnDuplicateSection(
base::SharedMemoryHandle renderer_handle,
base::SharedMemoryHandle* browser_handle) {
@@ -683,6 +690,30 @@ void ResourceMessageFilter::OnDuplicateSection(
base::SharedMemory shared_buf(renderer_handle, true, handle());
shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle);
}
+#endif
+
+#if defined(OS_LINUX)
+void ResourceMessageFilter::OnAllocateShareMemory(
+ size_t buffer_size,
+ base::SharedMemoryHandle* browser_handle) {
+ // We don't want to allocate a super big chunk of memory.
+ // 32MB should be large enough for printing on Linux.
+ if (buffer_size > 32 * 1024 * 1024) {
+ *browser_handle = base::SharedMemory::NULLHandle();
+ NOTREACHED() << "Buffer too large: " << buffer_size;
+ return;
+ }
+ base::SharedMemory shared_buf;
+ shared_buf.Create(L"", false, false, buffer_size);
+ if (shared_buf.Map(buffer_size)) {
+ shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle);
+ } else {
+ *browser_handle = base::SharedMemory::NULLHandle();
+ NOTREACHED() << "Cannot map buffer";
+ return;
+ }
+}
+#endif
void ResourceMessageFilter::OnResourceTypeStats(
const WebCache::ResourceTypeStats& stats) {
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 825422b..7fd7979 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -5,6 +5,10 @@
#ifndef CHROME_BROWSER_RENDERER_HOST_RESOURCE_MSG_FILTER_H_
#define CHROME_BROWSER_RENDERER_HOST_RESOURCE_MSG_FILTER_H_
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
#include <string>
#include <vector>
@@ -26,10 +30,6 @@
#include "ipc/ipc_channel_proxy.h"
#include "webkit/api/public/WebCache.h"
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
class AppCacheDispatcherHost;
class AudioRendererHost;
class Clipboard;
@@ -190,8 +190,20 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnGetPreferredExtensionForMimeType(const std::string& mime_type,
FilePath::StringType* ext);
void OnGetCPBrowsingContext(uint32* context);
+
+#if defined(OS_WIN)
+ // Used to pass resulting EMF from renderer to browser in printing.
void OnDuplicateSection(base::SharedMemoryHandle renderer_handle,
base::SharedMemoryHandle* browser_handle);
+#endif
+
+#if defined(OS_LINUX)
+ // Used to ask the browser allocate a block of shared memory for the renderer
+ // to fill in resulting PDF in renderer.
+ void OnAllocateShareMemory(size_t buffer_size,
+ base::SharedMemoryHandle* browser_handle);
+#endif
+
void OnResourceTypeStats(const WebKit::WebCache::ResourceTypeStats& stats);
void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 293ce43..43b2b9c 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1338,11 +1338,21 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_UploadProgress_ACK,
int /* request_id */)
+#if defined(OS_WIN)
// Duplicates a shared memory handle from the renderer to the browser. Then
// the renderer can flush the handle.
IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_DuplicateSection,
base::SharedMemoryHandle /* renderer handle */,
base::SharedMemoryHandle /* browser handle */)
+#endif
+
+#if defined(OS_LINUX)
+ // Asks the browser create a block of shared memory for the renderer to fill
+ // in resulting NativeMetafile in printing.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_AllocateShareMemory,
+ size_t /* buffer size */,
+ base::SharedMemoryHandle /* browser handle */)
+#endif
// Provide the browser process with information about the WebCore resource
// cache.
diff --git a/chrome/common/temp_scaffolding_stubs.cc b/chrome/common/temp_scaffolding_stubs.cc
index f2d8afb..4357d99 100644
--- a/chrome/common/temp_scaffolding_stubs.cc
+++ b/chrome/common/temp_scaffolding_stubs.cc
@@ -4,8 +4,6 @@
#include "chrome/common/temp_scaffolding_stubs.h"
-#include "build/build_config.h"
-
#include <vector>
#include "base/gfx/rect.h"
@@ -15,7 +13,12 @@
#include "chrome/browser/rlz/rlz.h"
#if defined(OS_LINUX)
+#include "base/path_service.h"
#include "chrome/browser/dock_info.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/render_messages.h"
+#include "printing/native_metafile.h"
#endif
#if defined(OS_MACOSX)
@@ -322,3 +325,48 @@ void BookmarkManager::Show(Profile* profile) {
}
#endif
+
+//------------------------------------------------------------------------------
+
+#if defined(OS_LINUX)
+// TODO(myhuang): This is a quick hack for testing purpose. We should implement
+// PrintViewManager and other related classes later on Linux.
+namespace printing {
+
+void PrintViewManager::DidPrintPage(
+ const ViewHostMsg_DidPrintPage_Params& params) {
+ base::SharedMemory shared_buf(params.metafile_data_handle, true);
+ if (!shared_buf.Map(params.data_size)) {
+ NOTREACHED() << "couldn't map";
+ owner_.Stop();
+ return;
+ }
+
+ // The only format we can use now is PDF since Cairo needs to create a
+ // temporary file for a PostScript surface. We do not allow disk I/O in the
+ // renderer.
+ scoped_ptr<NativeMetafile> metafile(
+ new NativeMetafile(printing::NativeMetafile::PDF));
+
+ if (!metafile->Init(shared_buf.memory(), params.data_size)) {
+ NOTREACHED() << "Invalid metafile header";
+ shared_buf.Unmap();
+ owner_.Stop();
+ return;
+ }
+
+ // Save the PDF file to default download location.
+ // NOTE: Existing file will be overwritten.
+ FilePath default_save_path;
+ if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &default_save_path)) {
+ NOTREACHED();
+ }
+ FilePath save_filename =
+ default_save_path.Append(FilePath("chromium_printing_test.pdf"));
+ metafile->SaveTo(save_filename);
+ shared_buf.Unmap();
+}
+
+} // namespace printing
+
+#endif
diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h
index 2ed3181..7b01f31 100644
--- a/chrome/common/temp_scaffolding_stubs.h
+++ b/chrome/common/temp_scaffolding_stubs.h
@@ -54,7 +54,7 @@ namespace printing {
class PrintViewManager : public RenderViewHostDelegate::Printing {
public:
- PrintViewManager(TabContents&) { }
+ PrintViewManager(TabContents& owner) : owner_(owner) { }
void Stop() { NOTIMPLEMENTED(); }
void Destroy() { }
bool OnRenderViewGone(RenderViewHost*) {
@@ -66,9 +66,17 @@ class PrintViewManager : public RenderViewHostDelegate::Printing {
virtual void DidGetPrintedPagesCount(int cookie, int number_pages) {
NOTIMPLEMENTED();
}
+
+#if defined(OS_LINUX)
+ virtual void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params);
+#else
virtual void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params) {
NOTIMPLEMENTED();
}
+#endif
+
+ private:
+ TabContents& owner_;
};
class PrintingContext {
diff --git a/chrome/renderer/print_web_view_helper.cc b/chrome/renderer/print_web_view_helper.cc
index d23bef2..9de27a8 100644
--- a/chrome/renderer/print_web_view_helper.cc
+++ b/chrome/renderer/print_web_view_helper.cc
@@ -29,7 +29,6 @@ PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint(
WebFrame* frame,
WebView* web_view)
: frame_(frame), web_view_(web_view), expected_pages_count_(0) {
-
print_canvas_size_.set_width(
printing::ConvertUnit(print_params.printable_size.width(),
static_cast<int>(print_params.dpi),
@@ -114,33 +113,6 @@ bool PrintWebViewHelper::CopyAndPrint(const ViewMsg_PrintPages_Params& params,
return true;
}
-void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params,
- WebFrame* frame) {
- PrepareFrameAndViewForPrint prep_frame_view(params.params,
- frame,
- frame->view());
- int page_count = prep_frame_view.GetExpectedPageCount();
-
- Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id(),
- params.params.document_cookie,
- page_count));
- if (page_count) {
- ViewMsg_PrintPage_Params page_params;
- page_params.params = params.params;
- if (params.pages.empty()) {
- for (int i = 0; i < page_count; ++i) {
- page_params.page_number = i;
- PrintPage(page_params, prep_frame_view.GetPrintCanvasSize(), frame);
- }
- } else {
- for (size_t i = 0; i < params.pages.size(); ++i) {
- page_params.page_number = params.pages[i];
- PrintPage(page_params, prep_frame_view.GetPrintCanvasSize(), frame);
- }
- }
- }
-}
-
void PrintWebViewHelper::PrintPageAsJPEG(
const ViewMsg_PrintPage_Params& params,
WebFrame* frame,
diff --git a/chrome/renderer/print_web_view_helper.h b/chrome/renderer/print_web_view_helper.h
index 406c807..63a973b 100644
--- a/chrome/renderer/print_web_view_helper.h
+++ b/chrome/renderer/print_web_view_helper.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_RENDERER_PRINT_WEB_VIEW_DELEGATE_H_
-#define CHROME_RENDERER_PRINT_WEB_VIEW_DELEGATE_H_
+#ifndef CHROME_RENDERER_PRINT_WEB_VIEW_HELPER_H_
+#define CHROME_RENDERER_PRINT_WEB_VIEW_HELPER_H_
#include <vector>
@@ -20,6 +20,13 @@ namespace IPC {
class Message;
}
+#if defined(OS_LINUX)
+namespace printing {
+class PdfPsMetafile;
+typedef PdfPsMetafile NativeMetafile;
+}
+#endif
+
class RenderView;
class WebView;
struct ViewMsg_Print_Params;
@@ -88,9 +95,16 @@ class PrintWebViewHelper : public WebViewDelegate {
WebKit::WebFrame* web_frame);
// Prints the page listed in |params|.
+#if defined(OS_LINUX)
+ void PrintPage(const ViewMsg_PrintPage_Params& params,
+ const gfx::Size& canvas_size,
+ WebKit::WebFrame* frame,
+ printing::NativeMetafile* metafile);
+#else
void PrintPage(const ViewMsg_PrintPage_Params& params,
const gfx::Size& canvas_size,
WebKit::WebFrame* frame);
+#endif
// Prints all the pages listed in |params|.
// It will implicitly revert the document to display CSS media type.
@@ -129,4 +143,4 @@ class PrintWebViewHelper : public WebViewDelegate {
DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelper);
};
-#endif // CHROME_RENDERER_PRINT_WEB_VIEW_DELEGATE_H_
+#endif // CHROME_RENDERER_PRINT_WEB_VIEW_HELPER_H_
diff --git a/chrome/renderer/print_web_view_helper_linux.cc b/chrome/renderer/print_web_view_helper_linux.cc
index 0fb7ffc..b16b05e 100644
--- a/chrome/renderer/print_web_view_helper_linux.cc
+++ b/chrome/renderer/print_web_view_helper_linux.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "chrome/common/render_messages.h"
+#include "printing/native_metafile.h"
#include "skia/ext/vector_canvas.h"
#include "webkit/api/public/WebFrame.h"
@@ -37,30 +38,85 @@ void PrintWebViewHelper::Print(WebFrame* frame, bool script_initiated) {
default_settings.document_cookie = NULL;
default_settings.selection_only = false;
- // Calculate the estimated page count.
- PrepareFrameAndViewForPrint prep_frame_view(default_settings,
+ ViewMsg_PrintPages_Params print_settings;
+ print_settings.params = default_settings;
+
+ PrintPages(print_settings, frame);
+}
+
+void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params,
+ WebFrame* frame) {
+ PrepareFrameAndViewForPrint prep_frame_view(params.params,
frame,
frame->view());
- int expected_pages_count = prep_frame_view.GetExpectedPageCount();
- DCHECK(expected_pages_count);
+ int page_count = prep_frame_view.GetExpectedPageCount();
+
+ // TODO(myhuang): Send ViewHostMsg_DidGetPrintedPagesCount.
+
+ if (page_count) {
+ // We only can use PDF in the renderer because Cairo needs to create a
+ // temporary file for a PostScript surface.
+ printing::NativeMetafile metafile(printing::NativeMetafile::PDF);
+ metafile.Init();
+
+ ViewMsg_PrintPage_Params print_page_params;
+ print_page_params.params = params.params;
+ const gfx::Size& canvas_size = prep_frame_view.GetPrintCanvasSize();
+ if (params.pages.empty()) {
+ for (int i = 0; i < page_count; ++i) {
+ print_page_params.page_number = i;
+ PrintPage(print_page_params, canvas_size, frame, &metafile);
+ }
+ } else {
+ for (size_t i = 0; i < params.pages.size(); ++i) {
+ print_page_params.page_number = params.pages[i];
+ PrintPage(print_page_params, canvas_size, frame, &metafile);
+ }
+ }
+
+ metafile.Close();
- ViewMsg_PrintPage_Params page_params;
- page_params.params = default_settings;
+ // Get the size of the resulting metafile.
+ unsigned int buf_size = metafile.GetDataSize();
+ DCHECK_GT(buf_size, 0u);
- // TODO(myhuang): Get final printing settings via IPC.
- // For testing purpose, we hard-coded printing settings here.
+ ViewHostMsg_DidPrintPage_Params did_page_params;
- // Print the first page only.
- expected_pages_count = 1;
- for (int i = 0; i < expected_pages_count; ++i) {
- page_params.page_number = i;
- PrintPage(page_params, prep_frame_view.GetPrintCanvasSize(), frame);
+ // Ask the browser create the shared memory for us.
+ if (Send(new ViewHostMsg_AllocateShareMemory(
+ routing_id(),
+ buf_size,
+ &did_page_params.metafile_data_handle))) {
+ if (did_page_params.metafile_data_handle.fd > -1) {
+ base::SharedMemory shared_buf(did_page_params.metafile_data_handle,
+ false);
+ if (shared_buf.Map(buf_size)) {
+ if (metafile.GetData(shared_buf.memory(), buf_size)) {
+ // FIXME(myhuang): This is for testing purpose at this moment.
+ // We use this message to pass the resulting PDF to the browser,
+ // and the browser will save this PDF on the disk.
+ did_page_params.data_size = buf_size;
+ Send(new ViewHostMsg_DidPrintPage(routing_id(), did_page_params));
+ } else {
+ NOTREACHED() << "GetData() failed";
+ }
+ shared_buf.Unmap();
+ } else {
+ NOTREACHED() << "Buffer mapping failed";
+ }
+ } else {
+ NOTREACHED() << "Buffer allocation failed";
+ }
+ } else {
+ NOTREACHED() << "Buffer allocation failed";
+ }
}
}
void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
const gfx::Size& canvas_size,
- WebFrame* frame) {
+ WebFrame* frame,
+ printing::NativeMetafile* metafile) {
// Since WebKit extends the page width depending on the magical shrink
// factor we make sure the canvas covers the worst case scenario
// (x2.0 currently). PrintContext will then set the correct clipping region.
@@ -71,16 +127,29 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
float shrink = static_cast<float>(canvas_size.width()) /
params.params.printable_size.width();
- // TODO(myhuang): We now use VectorCanvas to generate a PS/PDF file for
- // each page in printing. We might also need to create a metafile class
- // on Linux.
- skia::VectorCanvas canvas(size_x, size_y);
+ cairo_t* cairo_context = metafile->StartPage(size_x, size_y);
+ if (!cairo_context) {
+ // TODO(myhuang): We should handle such kind of error further!
+ // We already have had DLOG(ERROR) in NativeMetafile::StartPage(),
+ // log the error here, too?
+ return;
+ }
+
+ skia::VectorCanvas canvas(cairo_context, size_x, size_y);
float webkit_shrink = frame->printPage(params.page_number, &canvas);
- if (shrink <= 0) {
+ if (webkit_shrink <= 0) {
NOTREACHED() << "Printing page " << params.page_number << " failed.";
} else {
// Update the dpi adjustment with the "page shrink" calculated in webkit.
shrink /= webkit_shrink;
}
+
+ // TODO(myhuang): We should handle transformation for paper margins.
+ // TODO(myhuang): We should render the header and the footer.
+
+ // Done printing. Close the device context to retrieve the compiled metafile.
+ if (!metafile->FinishPage(shrink)) {
+ NOTREACHED() << "metafile failed";
+ }
}
diff --git a/chrome/renderer/print_web_view_helper_mac.cc b/chrome/renderer/print_web_view_helper_mac.cc
index 87a5517..fdb61419e 100644
--- a/chrome/renderer/print_web_view_helper_mac.cc
+++ b/chrome/renderer/print_web_view_helper_mac.cc
@@ -13,6 +13,12 @@ void PrintWebViewHelper::Print(WebFrame* frame, bool script_initiated) {
NOTIMPLEMENTED();
}
+void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params,
+ WebKit::WebFrame* frame) {
+ // TODO(port) implement printing
+ NOTIMPLEMENTED();
+}
+
void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
const gfx::Size& canvas_size,
WebFrame* frame) {
diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc
index 625a66d..dba857e 100644
--- a/chrome/renderer/print_web_view_helper_win.cc
+++ b/chrome/renderer/print_web_view_helper_win.cc
@@ -11,6 +11,7 @@
#include "chrome/renderer/render_view.h"
#include "grit/generated_resources.h"
#include "printing/native_metafile.h"
+#include "skia/ext/vector_canvas.h"
#include "webkit/api/public/WebConsoleMessage.h"
#include "webkit/api/public/WebFrame.h"
@@ -18,8 +19,6 @@ using WebKit::WebConsoleMessage;
using WebKit::WebFrame;
using WebKit::WebString;
-#include "skia/ext/vector_canvas.h"
-
void PrintWebViewHelper::Print(WebFrame* frame, bool script_initiated) {
const int kMinSecondsToIgnoreJavascriptInitiatedPrint = 2;
const int kMaxSecondsToIgnoreJavascriptInitiatedPrint = 2 * 60; // 2 Minutes.
@@ -149,6 +148,33 @@ void PrintWebViewHelper::Print(WebFrame* frame, bool script_initiated) {
DidFinishPrinting(user_cancelled_print);
}
+void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params,
+ WebFrame* frame) {
+ PrepareFrameAndViewForPrint prep_frame_view(params.params,
+ frame,
+ frame->view());
+ int page_count = prep_frame_view.GetExpectedPageCount();
+
+ Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id(),
+ params.params.document_cookie,
+ page_count));
+ if (page_count) {
+ ViewMsg_PrintPage_Params page_params;
+ page_params.params = params.params;
+ if (params.pages.empty()) {
+ for (int i = 0; i < page_count; ++i) {
+ page_params.page_number = i;
+ PrintPage(page_params, prep_frame_view.GetPrintCanvasSize(), frame);
+ }
+ } else {
+ for (size_t i = 0; i < params.pages.size(); ++i) {
+ page_params.page_number = params.pages[i];
+ PrintPage(page_params, prep_frame_view.GetPrintCanvasSize(), frame);
+ }
+ }
+ }
+}
+
void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
const gfx::Size& canvas_size,
WebFrame* frame) {
@@ -177,7 +203,7 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
skia::PlatformCanvas canvas(size_x, size_y, true);
canvas.drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
- if (shrink <= 0) {
+ if (shrink <= 0 || webkit_shrink <= 0) {
NOTREACHED() << "Printing page " << params.page_number << " failed.";
} else {
// Update the dpi adjustment with the "page shrink" calculated in webkit.
@@ -204,7 +230,7 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
// 100% GDI based.
skia::VectorCanvas canvas(hdc, size_x, size_y);
float webkit_shrink = frame->printPage(params.page_number, &canvas);
- if (shrink <= 0) {
+ if (shrink <= 0 || webkit_shrink <= 0) {
NOTREACHED() << "Printing page " << params.page_number << " failed.";
} else {
// Update the dpi adjustment with the "page shrink" calculated in webkit.
diff --git a/skia/ext/vector_canvas.h b/skia/ext/vector_canvas.h
index 27f7598..d4f76f8 100644
--- a/skia/ext/vector_canvas.h
+++ b/skia/ext/vector_canvas.h
@@ -8,6 +8,10 @@
#include "skia/ext/platform_canvas.h"
#include "skia/ext/vector_platform_device.h"
+#if defined(__linux__)
+typedef struct _cairo cairo_t;
+#endif
+
namespace skia {
// This class is a specialization of the regular PlatformCanvas. It is designed
@@ -20,7 +24,8 @@ class VectorCanvas : public PlatformCanvas {
#if defined(WIN32)
VectorCanvas(HDC dc, int width, int height);
#elif defined(__linux__)
- VectorCanvas(int width, int height);
+ // Caller owns |context|. Ownership is not transferred.
+ VectorCanvas(cairo_t* context, int width, int height);
#endif
virtual ~VectorCanvas();
@@ -28,10 +33,11 @@ class VectorCanvas : public PlatformCanvas {
#if defined(WIN32)
bool initialize(HDC context, int width, int height);
#elif defined(__linux__)
- bool initialize(int width, int height);
+ // Ownership of |context| is not transferred.
+ bool initialize(cairo_t* context, int width, int height);
#endif
- virtual SkBounder* setBounder(SkBounder*);
+ virtual SkBounder* setBounder(SkBounder* bounder);
#if defined(WIN32) || defined(__linux__)
virtual SkDevice* createDevice(SkBitmap::Config config,
int width, int height,
@@ -40,12 +46,15 @@ class VectorCanvas : public PlatformCanvas {
virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
private:
- // |is_opaque| is unused. |shared_section| is in fact the HDC used for output.
#if defined(WIN32)
+ // |shared_section| is in fact the HDC used for output. |is_opaque| is unused.
virtual SkDevice* createPlatformDevice(int width, int height, bool is_opaque,
HANDLE shared_section);
#elif defined(__linux__)
- virtual SkDevice* createPlatformDevice(int width, int height, bool is_opaque);
+ // Ownership of |context| is not transferred. |is_opaque| is unused.
+ virtual SkDevice* createPlatformDevice(cairo_t* context,
+ int width, int height,
+ bool is_opaque);
#endif
// Returns true if the top device is vector based and not bitmap based.
diff --git a/skia/ext/vector_canvas_linux.cc b/skia/ext/vector_canvas_linux.cc
index 95722c9..c3024f3 100644
--- a/skia/ext/vector_canvas_linux.cc
+++ b/skia/ext/vector_canvas_linux.cc
@@ -9,14 +9,14 @@
namespace skia {
-VectorCanvas::VectorCanvas(int width, int height) {
- bool initialized = initialize(width, height);
+VectorCanvas::VectorCanvas(cairo_t* context, int width, int height) {
+ bool initialized = initialize(context, width, height);
SkASSERT(initialized);
}
-bool VectorCanvas::initialize(int width, int height) {
- SkDevice* device = createPlatformDevice(width, height, true);
+bool VectorCanvas::initialize(cairo_t* context, int width, int height) {
+ SkDevice* device = createPlatformDevice(context, width, height, true);
if (!device)
return false;
@@ -29,19 +29,23 @@ SkDevice* VectorCanvas::createDevice(SkBitmap::Config config,
int width, int height,
bool is_opaque, bool isForLayer) {
SkASSERT(config == SkBitmap::kARGB_8888_Config);
- return createPlatformDevice(width, height, is_opaque);
+ return createPlatformDevice(NULL, width, height, is_opaque);
}
-SkDevice* VectorCanvas::createPlatformDevice(int width,
- int height, bool is_opaque) {
+SkDevice* VectorCanvas::createPlatformDevice(cairo_t* context,
+ int width,
+ int height,
+ bool is_opaque) {
// TODO(myhuang): Here we might also have similar issues as those on Windows
// (vector_canvas_win.cc, http://crbug.com/18382 & http://crbug.com/18383).
// Please note that is_opaque is true when we use this class for printing.
- if (!is_opaque) {
+ // Fallback to bitmap when context is NULL.
+ if (!is_opaque || NULL == context) {
return BitmapPlatformDevice::Create(width, height, is_opaque);
}
- PlatformDevice* device = VectorPlatformDevice::create(width, height);
+ PlatformDevice* device =
+ VectorPlatformDevice::create(context, width, height);
return device;
}
diff --git a/skia/ext/vector_platform_device_linux.cc b/skia/ext/vector_platform_device_linux.cc
index dde60f9..3b30ddf 100644
--- a/skia/ext/vector_platform_device_linux.cc
+++ b/skia/ext/vector_platform_device_linux.cc
@@ -4,48 +4,41 @@
#include "skia/ext/vector_platform_device.h"
-// TODO(myhuang): We have to decide or allow the user the choose the type
-// of the surface in the future.
-#include <cairo-pdf.h>
+#include <cairo.h>
#include "third_party/skia/include/core/SkTypeface.h"
namespace skia {
-VectorPlatformDevice* VectorPlatformDevice::create(int width, int height) {
+VectorPlatformDevice* VectorPlatformDevice::create(PlatformSurface context,
+ int width, int height) {
+ SkASSERT(cairo_status(context) == CAIRO_STATUS_SUCCESS);
SkASSERT(width > 0);
SkASSERT(height > 0);
- // TODO(myhuang): Can we get rid of the bitmap? In this vetorial device,
- // the content of this bitmap is meaningless. However, it does occupy
+ // TODO(myhuang): Can we get rid of the bitmap? In this vectorial device,
+ // the content of this bitmap might be meaningless. However, it does occupy
// lots of memory space.
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- return new VectorPlatformDevice(bitmap);
+ return new VectorPlatformDevice(context, bitmap);
}
-VectorPlatformDevice::VectorPlatformDevice(const SkBitmap& bitmap)
- : PlatformDevice(bitmap) {
+VectorPlatformDevice::VectorPlatformDevice(PlatformSurface context,
+ const SkBitmap& bitmap)
+ : PlatformDevice(bitmap), context_(context) {
SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
- // FIXME(myhuang): At this moment, we write the PDF file to the disk
- // for testing when we run chromium without sanboxing.
- surface_ = cairo_pdf_surface_create("chrome_printing_test.pdf",
- width(), height());
- SkASSERT(surface_);
- context_ = cairo_create(surface_);
- SkASSERT(context_);
+ // Increase the reference count to keep the context alive.
+ cairo_reference(context_);
transform_.reset();
}
VectorPlatformDevice::~VectorPlatformDevice() {
- SkASSERT(surface_);
- SkASSERT(context_);
-
+ // Un-ref |context_| since we referenced it in the constructor.
cairo_destroy(context_);
- cairo_surface_destroy(surface_);
}
void VectorPlatformDevice::drawBitmap(const SkDraw& draw,
@@ -163,7 +156,7 @@ void VectorPlatformDevice::drawPath(const SkDraw& draw,
current_points[3].fX, current_points[3].fY);
} break;
- case SkPath::kClose_Verb: { // iter.next returns 1 point (the last point)
+ case SkPath::kClose_Verb: { // iter.next returns 1 point (the last pt).
cairo_close_path(context_);
} break;
diff --git a/skia/ext/vector_platform_device_linux.h b/skia/ext/vector_platform_device_linux.h
index 0cd9512..67f1c48 100644
--- a/skia/ext/vector_platform_device_linux.h
+++ b/skia/ext/vector_platform_device_linux.h
@@ -9,20 +9,18 @@
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkRegion.h"
-typedef struct _cairo_surface cairo_surface_t;
-
namespace skia {
// This device is basically a wrapper that provides a surface for SkCanvas
// to draw into. It is basically an adaptor which converts skia APIs into
-// cooresponding Cairo APIs and outputs to a Cairo PDF surface. Please NOTE
-// that since it is completely vectorial, the bitmap content in it is thus
+// cooresponding Cairo APIs and outputs to a Cairo surface. Please NOTE that
+// since it is completely vectorial, the bitmap content in it is thus
// meaningless.
class VectorPlatformDevice : public PlatformDevice {
public:
- // Factory function.
- static VectorPlatformDevice* create(int width, int height);
-
+ // Factory function. Ownership of |context| is not transferred.
+ static VectorPlatformDevice* create(PlatformSurface context,
+ int width, int height);
virtual ~VectorPlatformDevice();
virtual bool IsVectorial() { return true; }
@@ -56,10 +54,12 @@ class VectorPlatformDevice : public PlatformDevice {
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint);
- virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region);
+ virtual void setMatrixClip(const SkMatrix& transform,
+ const SkRegion& region);
protected:
- explicit VectorPlatformDevice(const SkBitmap& bitmap);
+ explicit VectorPlatformDevice(PlatformSurface context,
+ const SkBitmap& bitmap);
private:
// Apply paint's color in the context.
@@ -95,11 +95,8 @@ class VectorPlatformDevice : public PlatformDevice {
// The current clipping region.
SkRegion clip_region_;
- // Context's target surface. It is a PS/PDF surface.
- cairo_surface_t* surface_;
-
// Device context.
- cairo_t* context_;
+ PlatformSurface context_;
// Copy & assign are not supported.
VectorPlatformDevice(const VectorPlatformDevice&);