| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef SKIA_EXT_PLATFORM_CANVAS_WIN_H_ | |
| 6 #define SKIA_EXT_PLATFORM_CANVAS_WIN_H_ | |
| 7 | 5 |
| 8 #include <windows.h> | 6 // TODO(brettw) erase this file. This file is necessary because |
| 7 // FontChromiumWin.cpp in WebKit includes it, and I want to avoid having to |
| 8 // synchronize the checkins to Chromium and WebKit. |
| 9 | 9 |
| 10 #include "skia/ext/platform_device_win.h" | 10 #include "skia/ext/platform_canvas.h" |
| 11 | |
| 12 #include "third_party/skia/include/core/SkCanvas.h" | |
| 13 | |
| 14 namespace skia { | |
| 15 | |
| 16 // This class is a specialization of the regular SkCanvas that is designed to | |
| 17 // work with a PlatformDevice to manage platform-specific drawing. It allows | |
| 18 // using both Skia operations and platform-specific operations. | |
| 19 class PlatformCanvasWin : public SkCanvas { | |
| 20 public: | |
| 21 // Set is_opaque if you are going to erase the bitmap and not use | |
| 22 // transparency: this will enable some optimizations. The shared_section | |
| 23 // parameter is passed to gfx::PlatformDevice::create. See it for details. | |
| 24 // | |
| 25 // If you use the version with no arguments, you MUST call initialize() | |
| 26 PlatformCanvasWin(); | |
| 27 PlatformCanvasWin(int width, int height, bool is_opaque); | |
| 28 PlatformCanvasWin(int width, int height, bool is_opaque, | |
| 29 HANDLE shared_section); | |
| 30 virtual ~PlatformCanvasWin(); | |
| 31 | |
| 32 // For two-part init, call if you use the no-argument constructor above. Note | |
| 33 // that we want this to optionally match the Linux initialize if you only | |
| 34 // pass 3 arguments, hence the evil default argument. | |
| 35 bool initialize(int width, int height, bool is_opaque, | |
| 36 HANDLE shared_section = NULL); | |
| 37 | |
| 38 // These calls should surround calls to platform drawing routines, the DC | |
| 39 // returned by beginPlatformPaint is the DC that can be used to draw into. | |
| 40 // Call endPlatformPaint when you are done and want to use Skia operations | |
| 41 // again; this will synchronize the bitmap to Windows. | |
| 42 virtual HDC beginPlatformPaint(); | |
| 43 virtual void endPlatformPaint(); | |
| 44 | |
| 45 // Returns the platform device pointer of the topmost rect with a non-empty | |
| 46 // clip. In practice, this is usually either the top layer or nothing, since | |
| 47 // we usually set the clip to new layers when we make them. | |
| 48 // | |
| 49 // If there is no layer that is not all clipped out, this will return a | |
| 50 // dummy device so callers do not have to check. If you are concerned about | |
| 51 // performance, check the clip before doing any painting. | |
| 52 // | |
| 53 // This is different than SkCanvas' getDevice, because that returns the | |
| 54 // bottommost device. | |
| 55 // | |
| 56 // Danger: the resulting device should not be saved. It will be invalidated | |
| 57 // by the next call to save() or restore(). | |
| 58 PlatformDeviceWin& getTopPlatformDevice() const; | |
| 59 | |
| 60 static size_t StrideForWidth(unsigned width); | |
| 61 | |
| 62 protected: | |
| 63 // Creates a device store for use by the canvas. We override this so that | |
| 64 // the device is always our own so we know that we can use GDI operations | |
| 65 // on it. Simply calls into createPlatformDevice(). | |
| 66 virtual SkDevice* createDevice(SkBitmap::Config, int width, int height, | |
| 67 bool is_opaque, bool isForLayer); | |
| 68 | |
| 69 // Creates a device store for use by the canvas. By default, it creates a | |
| 70 // BitmapPlatformDeviceWin. Can be overridden to change the object type. | |
| 71 virtual SkDevice* createPlatformDevice(int width, int height, bool is_opaque, | |
| 72 HANDLE shared_section); | |
| 73 | |
| 74 private: | |
| 75 // Unimplemented. | |
| 76 virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap); | |
| 77 | |
| 78 // Disallow copy and assign. | |
| 79 PlatformCanvasWin(const PlatformCanvasWin&); | |
| 80 PlatformCanvasWin& operator=(const PlatformCanvasWin&); | |
| 81 }; | |
| 82 | |
| 83 // A class designed to help with WM_PAINT operations on Windows. It will | |
| 84 // do BeginPaint/EndPaint on init/destruction, and will create the bitmap and | |
| 85 // canvas with the correct size and transform for the dirty rect. The bitmap | |
| 86 // will be automatically painted to the screen on destruction. | |
| 87 // | |
| 88 // You MUST call isEmpty before painting to determine if anything needs | |
| 89 // painting. Sometimes the dirty rect can actually be empty, and this makes | |
| 90 // the bitmap functions we call unhappy. The caller should not paint in this | |
| 91 // case. | |
| 92 // | |
| 93 // Therefore, all you need to do is: | |
| 94 // case WM_PAINT: { | |
| 95 // gfx::PlatformCanvasWinPaint canvas(hwnd); | |
| 96 // if (!canvas.isEmpty()) { | |
| 97 // ... paint to the canvas ... | |
| 98 // } | |
| 99 // return 0; | |
| 100 // } | |
| 101 template <class T> | |
| 102 class CanvasPaintT : public T { | |
| 103 public: | |
| 104 explicit CanvasPaintT(HWND hwnd) : hwnd_(hwnd), paint_dc_(NULL), | |
| 105 for_paint_(true) { | |
| 106 memset(&ps_, 0, sizeof(ps_)); | |
| 107 initPaint(true); | |
| 108 } | |
| 109 | |
| 110 CanvasPaintT(HWND hwnd, bool opaque) : hwnd_(hwnd), paint_dc_(NULL), | |
| 111 for_paint_(true) { | |
| 112 memset(&ps_, 0, sizeof(ps_)); | |
| 113 initPaint(opaque); | |
| 114 } | |
| 115 | |
| 116 // Creates a CanvasPaintT for the specified region that paints to the | |
| 117 // specified dc. This does NOT do BeginPaint/EndPaint. | |
| 118 CanvasPaintT(HDC dc, bool opaque, int x, int y, int w, int h) | |
| 119 : hwnd_(NULL), | |
| 120 paint_dc_(dc), | |
| 121 for_paint_(false) { | |
| 122 memset(&ps_, 0, sizeof(ps_)); | |
| 123 ps_.rcPaint.left = x; | |
| 124 ps_.rcPaint.right = x + w; | |
| 125 ps_.rcPaint.top = y; | |
| 126 ps_.rcPaint.bottom = y + h; | |
| 127 init(opaque); | |
| 128 } | |
| 129 | |
| 130 | |
| 131 virtual ~CanvasPaintT() { | |
| 132 if (!isEmpty()) { | |
| 133 restoreToCount(1); | |
| 134 // Commit the drawing to the screen | |
| 135 getTopPlatformDevice().drawToHDC(paint_dc_, | |
| 136 ps_.rcPaint.left, ps_.rcPaint.top, | |
| 137 NULL); | |
| 138 } | |
| 139 if (for_paint_) | |
| 140 EndPaint(hwnd_, &ps_); | |
| 141 } | |
| 142 | |
| 143 // Returns true if the invalid region is empty. The caller should call this | |
| 144 // function to determine if anything needs painting. | |
| 145 bool isEmpty() const { | |
| 146 return ps_.rcPaint.right - ps_.rcPaint.left == 0 || | |
| 147 ps_.rcPaint.bottom - ps_.rcPaint.top == 0; | |
| 148 } | |
| 149 | |
| 150 // Use to access the Windows painting parameters, especially useful for | |
| 151 // getting the bounding rect for painting: paintstruct().rcPaint | |
| 152 const PAINTSTRUCT& paintStruct() const { | |
| 153 return ps_; | |
| 154 } | |
| 155 | |
| 156 // Returns the DC that will be painted to | |
| 157 HDC paintDC() const { | |
| 158 return paint_dc_; | |
| 159 } | |
| 160 | |
| 161 protected: | |
| 162 HWND hwnd_; | |
| 163 HDC paint_dc_; | |
| 164 PAINTSTRUCT ps_; | |
| 165 | |
| 166 private: | |
| 167 void initPaint(bool opaque) { | |
| 168 paint_dc_ = BeginPaint(hwnd_, &ps_); | |
| 169 | |
| 170 init(opaque); | |
| 171 } | |
| 172 | |
| 173 void init(bool opaque) { | |
| 174 // FIXME(brettw) for ClearType, we probably want to expand the bounds of | |
| 175 // painting by one pixel so that the boundaries will be correct (ClearType | |
| 176 // text can depend on the adjacent pixel). Then we would paint just the | |
| 177 // inset pixels to the screen. | |
| 178 const int width = ps_.rcPaint.right - ps_.rcPaint.left; | |
| 179 const int height = ps_.rcPaint.bottom - ps_.rcPaint.top; | |
| 180 if (!initialize(width, height, opaque, NULL)) { | |
| 181 // Cause a deliberate crash; | |
| 182 *(char*) 0 = 0; | |
| 183 } | |
| 184 | |
| 185 // This will bring the canvas into the screen coordinate system for the | |
| 186 // dirty rect | |
| 187 translate(SkIntToScalar(-ps_.rcPaint.left), | |
| 188 SkIntToScalar(-ps_.rcPaint.top)); | |
| 189 } | |
| 190 | |
| 191 // If true, this canvas was created for a BeginPaint. | |
| 192 const bool for_paint_; | |
| 193 | |
| 194 // Disallow copy and assign. | |
| 195 CanvasPaintT(const CanvasPaintT&); | |
| 196 CanvasPaintT& operator=(const CanvasPaintT&); | |
| 197 }; | |
| 198 | |
| 199 typedef CanvasPaintT<PlatformCanvasWin> PlatformCanvasWinPaint; | |
| 200 | |
| 201 } // namespace skia | |
| 202 | |
| 203 #endif // SKIA_EXT_PLATFORM_CANVAS_WIN_H_ | |
| OLD | NEW |