diff options
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 31 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 20 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 10 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.cc | 52 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.h | 10 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper.cc | 28 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper.h | 20 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_linux.cc | 107 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_mac.cc | 6 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_win.cc | 34 | ||||
-rw-r--r-- | skia/ext/vector_canvas.h | 19 | ||||
-rw-r--r-- | skia/ext/vector_canvas_linux.cc | 22 | ||||
-rw-r--r-- | skia/ext/vector_platform_device_linux.cc | 35 | ||||
-rw-r--r-- | skia/ext/vector_platform_device_linux.h | 23 |
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&); |