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