1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_CAIRO_H_ 6 #define SKIA_EXT_BITMAP_PLATFORM_DEVICE_CAIRO_H_ 7 8 #include "base/basictypes.h" 9 #include "base/compiler_specific.h" 10 #include "base/memory/ref_counted.h" 11 #include "skia/ext/platform_device.h" 12 13 typedef struct _cairo_surface cairo_surface_t; 14 15 // ----------------------------------------------------------------------------- 16 // Image byte ordering on Linux: 17 // 18 // Pixels are packed into 32-bit words these days. Even for 24-bit images, 19 // often 8-bits will be left unused for alignment reasons. Thus, when you see 20 // ARGB as the byte order you have to wonder if that's in memory order or 21 // little-endian order. Here I'll write A.R.G.B to specifiy the memory order. 22 // 23 // GdkPixbuf's provide a nice backing store and defaults to R.G.B.A order. 24 // They'll do the needed byte swapping to match the X server when drawn. 25 // 26 // Skia can be controled in skia/include/corecg/SkUserConfig.h (see bits about 27 // SK_R32_SHIFT). For Linux we define it to be ARGB in registers. For little 28 // endian machines that means B.G.R.A in memory. 29 // 30 // The image loaders are controlled in 31 // webkit/port/platform/image-decoders/ImageDecoder.h (see setRGBA). These are 32 // also configured for ARGB in registers. 33 // 34 // Cairo's only 32-bit mode is ARGB in registers. 35 // 36 // X servers commonly have a 32-bit visual with xRGB in registers (since they 37 // typically don't do alpha blending of drawables at the user level. Composite 38 // extensions aside.) 39 // 40 // We don't use GdkPixbuf because its byte order differs from the rest. Most 41 // importantly, it differs from Cairo which, being a system library, is 42 // something that we can't easily change. 43 // ----------------------------------------------------------------------------- 44 45 namespace skia { 46 47 // ----------------------------------------------------------------------------- 48 // This is the Linux bitmap backing for Skia. We create a Cairo image surface 49 // to store the backing buffer. This buffer is BGRA in memory (on little-endian 50 // machines). 51 // 52 // For now we are also using Cairo to paint to the Drawables so we provide an 53 // accessor for getting the surface. 54 // 55 // This is all quite ok for test_shell. In the future we will want to use 56 // shared memory between the renderer and the main process at least. In this 57 // case we'll probably create the buffer from a precreated region of memory. 58 // ----------------------------------------------------------------------------- 59 class BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice { 60 public: 61 // Create a BitmapPlatformDeviceLinux from an already constructed bitmap; 62 // you should probably be using Create(). This may become private later if 63 // we ever have to share state between some native drawing UI and Skia, like 64 // the Windows and Mac versions of this class do. 65 // 66 // This object takes ownership of @data. 67 BitmapPlatformDevice(const SkBitmap& other, cairo_surface_t* surface); 68 virtual ~BitmapPlatformDevice(); 69 70 // Constructs a device with size |width| * |height| with contents initialized 71 // to zero. |is_opaque| should be set if the caller knows the bitmap will be 72 // completely opaque and allows some optimizations. 73 static BitmapPlatformDevice* Create(int width, int height, bool is_opaque); 74 75 // Performs the same construction as Create. 76 // Other ports require a separate construction routine because Create does not 77 // initialize the bitmap to 0. 78 static BitmapPlatformDevice* CreateAndClear(int width, int height, 79 bool is_opaque); 80 81 // This doesn't take ownership of |data|. If |data| is NULL, the contents 82 // of the device are initialized to 0. 83 static BitmapPlatformDevice* Create(int width, int height, bool is_opaque, 84 uint8_t* data); 85 86 // Overridden from SkBaseDevice: 87 virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region, 88 const SkClipStack&) OVERRIDE; 89 90 // Overridden from PlatformDevice: 91 virtual cairo_t* BeginPlatformPaint() OVERRIDE; 92 virtual void DrawToNativeContext(PlatformSurface surface, int x, int y, 93 const PlatformRect* src_rect) OVERRIDE; 94 95 protected: 96 virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config, int width, 97 int height, bool isOpaque, 98 Usage usage) OVERRIDE; 99 100 private: 101 static BitmapPlatformDevice* Create(int width, int height, bool is_opaque, 102 cairo_surface_t* surface); 103 104 // Sets the transform and clip operations. This will not update the Cairo 105 // context, but will mark the config as dirty. The next call of LoadConfig 106 // will pick up these changes. 107 void SetMatrixClip(const SkMatrix& transform, const SkRegion& region); 108 109 // Loads the current transform and clip into the context. 110 void LoadConfig(); 111 112 // Graphics context used to draw into the surface. 113 cairo_t* cairo_; 114 115 // True when there is a transform or clip that has not been set to the 116 // context. The context is retrieved for every text operation, and the 117 // transform and clip do not change as much. We can save time by not loading 118 // the clip and transform for every one. 119 bool config_dirty_; 120 121 // Translation assigned to the context: we need to keep track of this 122 // separately so it can be updated even if the context isn't created yet. 123 SkMatrix transform_; 124 125 // The current clipping 126 SkRegion clip_region_; 127 128 DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice); 129 }; 130 131 } // namespace skia 132 133 #endif // SKIA_EXT_BITMAP_PLATFORM_DEVICE_CAIRO_H_ 134