15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SKIA_EXT_PLATFORM_CANVAS_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SKIA_EXT_PLATFORM_CANVAS_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The platform-specific device will include the necessary platform headers 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to get the surface type. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_device.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "skia/ext/refptr.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkPixelRef.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace skia { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef SkCanvas PlatformCanvas; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note about error handling. 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Creating a canvas can fail at times, most often because we fail to allocate 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the backing-store (pixels). This can be from out-of-memory, or something 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// more opaque, like GDI or cairo reported a failure. 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To allow the caller to handle the failure, every Create... factory takes an 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// enum as its last parameter. The default value is kCrashOnFailure. If the 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// caller passes kReturnNullOnFailure, then the caller is responsible to check 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the return result. 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)enum OnFailureType { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CRASH_ON_FAILURE, 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RETURN_NULL_ON_FAILURE 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(WIN32) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The shared_section parameter is passed to gfx::PlatformDevice::create. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See it for details. 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SK_API SkCanvas* CreatePlatformCanvas(int width, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height, 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_opaque, 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HANDLE shared_section, 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnFailureType failure_type); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__APPLE__) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SK_API SkCanvas* CreatePlatformCanvas(CGContextRef context, 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int width, 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height, 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_opaque, 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnFailureType failure_type); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SK_API SkCanvas* CreatePlatformCanvas(int width, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_opaque, 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8_t* context, 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnFailureType failure_type); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) defined(__sun) || defined(ANDROID) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Linux --------------------------------------------------------------------- 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct a canvas from the given memory region. The memory is not cleared 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first. @data must be, at least, @height * StrideForWidth(@width) bytes. 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SK_API SkCanvas* CreatePlatformCanvas(int width, 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height, 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_opaque, 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8_t* data, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnFailureType failure_type); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline SkCanvas* CreatePlatformCanvas(int width, 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height, 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_opaque) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CreatePlatformCanvas(width, height, is_opaque, 0, CRASH_ON_FAILURE); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SK_API SkCanvas* CreateCanvas(const skia::RefPtr<SkBaseDevice>& device, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnFailureType failure_type); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline SkCanvas* CreateBitmapCanvas(int width, 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height, 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_opaque) { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CreatePlatformCanvas(width, height, is_opaque, 0, CRASH_ON_FAILURE); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline SkCanvas* TryCreateBitmapCanvas(int width, 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height, 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_opaque) { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CreatePlatformCanvas(width, height, is_opaque, 0, 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RETURN_NULL_ON_FAILURE); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Return the stride (length of a line in bytes) for the given width. Because 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// we use 32-bits per pixel, this will be roughly 4*width. However, for 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// alignment reasons we may wish to increase that. 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SK_API size_t PlatformCanvasStrideForWidth(unsigned width); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Returns the SkBaseDevice pointer of the topmost rect with a non-empty 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// clip. In practice, this is usually either the top layer or nothing, since 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we usually set the clip to new layers when we make them. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// This may return NULL, so callers need to check. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is different than SkCanvas' getDevice, because that returns the 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bottommost device. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Danger: the resulting device should not be saved. It will be invalidated 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by the next call to save() or restore(). 109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SK_API SkBaseDevice* GetTopDevice(const SkCanvas& canvas); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if native platform routines can be used to draw on the 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// given canvas. If this function returns false, BeginPlatformPaint will 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return NULL PlatformSurface. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SK_API bool SupportsPlatformPaint(const SkCanvas* canvas); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Draws into the a native platform surface, |context|. Forwards to 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DrawToNativeContext on a PlatformDevice instance bound to the top device. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If no PlatformDevice instance is bound, is a no-operation. 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SK_API void DrawToNativeContext(SkCanvas* canvas, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PlatformSurface context, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int x, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int y, 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const PlatformRect* src_rect); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sets the opacity of each pixel in the specified region to be opaque. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SK_API void MakeOpaque(SkCanvas* canvas, int x, int y, int width, int height); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These calls should surround calls to platform drawing routines, the 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// surface returned here can be used with the native platform routines. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Call EndPlatformPaint when you are done and want to use skia operations 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after calling the platform-specific BeginPlatformPaint; this will 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// synchronize the bitmap to OS if necessary. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SK_API PlatformSurface BeginPlatformPaint(SkCanvas* canvas); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SK_API void EndPlatformPaint(SkCanvas* canvas); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class for pairing calls to BeginPlatformPaint and EndPlatformPaint. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Upon construction invokes BeginPlatformPaint, and upon destruction invokes 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// EndPlatformPaint. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SK_API ScopedPlatformPaint { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ScopedPlatformPaint(SkCanvas* canvas) : canvas_(canvas) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_surface_ = BeginPlatformPaint(canvas); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ScopedPlatformPaint() { EndPlatformPaint(canvas_); } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the PlatformSurface to use for native platform drawing calls. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PlatformSurface GetPlatformSurface() { return platform_surface_; } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkCanvas* canvas_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PlatformSurface platform_surface_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disallow copy and assign 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedPlatformPaint(const ScopedPlatformPaint&); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedPlatformPaint& operator=(const ScopedPlatformPaint&); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// PlatformBitmap holds a PlatformSurface that can also be used as an SkBitmap. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SK_API PlatformBitmap { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PlatformBitmap(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~PlatformBitmap(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the bitmap was able to allocate its surface. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Allocate(int width, int height, bool is_opaque); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the platform surface, or 0 if Allocate() did not return true. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PlatformSurface GetSurface() { return surface_; } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the skia bitmap, which will be empty if Allocate() did not 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return true. 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The resulting SkBitmap holds a refcount on the underlying platform surface, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so the surface will remain allocated so long as the SkBitmap or its copies 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay around. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& GetBitmap() { return bitmap_; } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap bitmap_; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PlatformSurface surface_; // initialized to 0 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) intptr_t platform_extra_; // platform specific, initialized to 0 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(PlatformBitmap); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace skia 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SKIA_EXT_PLATFORM_CANVAS_H_ 189