| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 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 #include "gfx/canvas_direct2d.h" | |
| 6 | |
| 7 #include "base/scoped_ptr.h" | |
| 8 #include "gfx/brush.h" | |
| 9 #include "gfx/rect.h" | |
| 10 | |
| 11 namespace { | |
| 12 | |
| 13 // Converts a SkColor to a ColorF. | |
| 14 D2D1_COLOR_F SkColorToColorF(SkColor color) { | |
| 15 return D2D1::ColorF(static_cast<float>(SkColorGetR(color)) / 0xFF, | |
| 16 static_cast<float>(SkColorGetG(color)) / 0xFF, | |
| 17 static_cast<float>(SkColorGetB(color)) / 0xFF, | |
| 18 static_cast<float>(SkColorGetA(color)) / 0xFF); | |
| 19 } | |
| 20 | |
| 21 D2D1_RECT_F RectToRectF(int x, int y, int w, int h) { | |
| 22 return D2D1::RectF(static_cast<float>(x), static_cast<float>(y), | |
| 23 static_cast<float>(x + w), static_cast<float>(y + h)); | |
| 24 } | |
| 25 | |
| 26 D2D1_RECT_F RectToRectF(const gfx::Rect& rect) { | |
| 27 return RectToRectF(rect.x(), rect.y(), rect.width(), rect.height()); | |
| 28 } | |
| 29 | |
| 30 D2D1_POINT_2F PointToPoint2F(int x, int y) { | |
| 31 return D2D1::Point2F(static_cast<float>(x), static_cast<float>(y)); | |
| 32 } | |
| 33 | |
| 34 D2D1_BITMAP_INTERPOLATION_MODE FilterToInterpolationMode(bool filter) { | |
| 35 return filter ? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR | |
| 36 : D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR; | |
| 37 } | |
| 38 | |
| 39 // Creates a Direct2D bitmap object from the contents of a SkBitmap. The caller | |
| 40 // is responsible for releasing this object. | |
| 41 ID2D1Bitmap* CreateD2D1BitmapFromSkBitmap(ID2D1RenderTarget* render_target, | |
| 42 const SkBitmap& bitmap) { | |
| 43 ID2D1Bitmap* d2d1_bitmap = NULL; | |
| 44 HRESULT hr = render_target->CreateBitmap( | |
| 45 D2D1::SizeU(bitmap.width(), bitmap.height()), | |
| 46 NULL, | |
| 47 NULL, | |
| 48 D2D1::BitmapProperties( | |
| 49 D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, | |
| 50 D2D1_ALPHA_MODE_IGNORE)), | |
| 51 &d2d1_bitmap); | |
| 52 if (FAILED(hr)) | |
| 53 return NULL; | |
| 54 bitmap.lockPixels(); | |
| 55 d2d1_bitmap->CopyFromMemory(NULL, bitmap.getPixels(), bitmap.rowBytes()); | |
| 56 bitmap.unlockPixels(); | |
| 57 return d2d1_bitmap; | |
| 58 } | |
| 59 | |
| 60 // Creates a Direct2D bitmap brush from the contents of a SkBitmap. The caller | |
| 61 // is responsible for releasing this object. | |
| 62 ID2D1Brush* CreateD2D1BrushFromSkBitmap(ID2D1RenderTarget* render_target, | |
| 63 const SkBitmap& bitmap, | |
| 64 D2D1_EXTEND_MODE extend_mode_x, | |
| 65 D2D1_EXTEND_MODE extend_mode_y) { | |
| 66 ScopedComPtr<ID2D1Bitmap> d2d1_bitmap( | |
| 67 CreateD2D1BitmapFromSkBitmap(render_target, bitmap)); | |
| 68 | |
| 69 ID2D1BitmapBrush* brush = NULL; | |
| 70 render_target->CreateBitmapBrush( | |
| 71 d2d1_bitmap, | |
| 72 D2D1::BitmapBrushProperties(extend_mode_x, extend_mode_y), | |
| 73 D2D1::BrushProperties(), | |
| 74 &brush); | |
| 75 return brush; | |
| 76 } | |
| 77 | |
| 78 // A platform wrapper for a Direct2D brush that makes sure the underlying | |
| 79 // ID2D1Brush COM object is released when this object is destroyed. | |
| 80 class Direct2DBrush : public gfx::Brush { | |
| 81 public: | |
| 82 explicit Direct2DBrush(ID2D1Brush* brush) : brush_(brush) { | |
| 83 } | |
| 84 | |
| 85 ID2D1Brush* brush() const { return brush_.get(); } | |
| 86 | |
| 87 private: | |
| 88 ScopedComPtr<ID2D1Brush> brush_; | |
| 89 | |
| 90 DISALLOW_COPY_AND_ASSIGN(Direct2DBrush); | |
| 91 }; | |
| 92 | |
| 93 | |
| 94 } // namespace | |
| 95 | |
| 96 namespace gfx { | |
| 97 | |
| 98 // static | |
| 99 ID2D1Factory* CanvasDirect2D::d2d1_factory_ = NULL; | |
| 100 | |
| 101 //////////////////////////////////////////////////////////////////////////////// | |
| 102 // CanvasDirect2D, public: | |
| 103 | |
| 104 CanvasDirect2D::CanvasDirect2D(ID2D1RenderTarget* rt) : rt_(rt) { | |
| 105 // A RenderState entry is pushed onto the stack to track the clip count prior | |
| 106 // to any calls to Save*(). | |
| 107 state_.push(RenderState()); | |
| 108 rt_->BeginDraw(); | |
| 109 } | |
| 110 | |
| 111 CanvasDirect2D::~CanvasDirect2D() { | |
| 112 // Unwind any clips that were pushed outside of any Save*()/Restore() pairs. | |
| 113 int clip_count = state_.top().clip_count; | |
| 114 for (int i = 0; i < clip_count; ++i) | |
| 115 rt_->PopAxisAlignedClip(); | |
| 116 rt_->EndDraw(); | |
| 117 } | |
| 118 | |
| 119 // static | |
| 120 ID2D1Factory* CanvasDirect2D::GetD2D1Factory() { | |
| 121 if (!d2d1_factory_) | |
| 122 D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2d1_factory_); | |
| 123 return d2d1_factory_; | |
| 124 } | |
| 125 | |
| 126 //////////////////////////////////////////////////////////////////////////////// | |
| 127 // CanvasDirect2D, Canvas implementation: | |
| 128 | |
| 129 void CanvasDirect2D::Save() { | |
| 130 SaveInternal(NULL); | |
| 131 } | |
| 132 | |
| 133 void CanvasDirect2D::SaveLayerAlpha(uint8 alpha) { | |
| 134 SaveLayerAlpha(alpha, gfx::Rect()); | |
| 135 } | |
| 136 | |
| 137 void CanvasDirect2D::SaveLayerAlpha(uint8 alpha, | |
| 138 const gfx::Rect& layer_bounds) { | |
| 139 D2D1_RECT_F bounds = D2D1::InfiniteRect(); | |
| 140 if (!layer_bounds.IsEmpty()) | |
| 141 bounds = RectToRectF(layer_bounds); | |
| 142 ID2D1Layer* layer = NULL; | |
| 143 HRESULT hr = rt_->CreateLayer(NULL, &layer); | |
| 144 if (SUCCEEDED(hr)) { | |
| 145 rt_->PushLayer(D2D1::LayerParameters(bounds, | |
| 146 NULL, | |
| 147 D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, | |
| 148 D2D1::IdentityMatrix(), | |
| 149 static_cast<float>(alpha) / 0xFF, | |
| 150 NULL, | |
| 151 D2D1_LAYER_OPTIONS_NONE), | |
| 152 layer); | |
| 153 } | |
| 154 SaveInternal(layer); | |
| 155 } | |
| 156 | |
| 157 void CanvasDirect2D::Restore() { | |
| 158 ID2D1Layer* layer = state_.top().layer; | |
| 159 if (layer) { | |
| 160 rt_->PopLayer(); | |
| 161 layer->Release(); | |
| 162 } | |
| 163 | |
| 164 int clip_count = state_.top().clip_count; | |
| 165 for (int i = 0; i < clip_count; ++i) | |
| 166 rt_->PopAxisAlignedClip(); | |
| 167 | |
| 168 state_.pop(); | |
| 169 // The state_ stack should never be empty - we should always have at least one | |
| 170 // entry to hold a clip count when there is no active save/restore entry. | |
| 171 CHECK(!state_.empty()) << "Called Restore() once too often!"; | |
| 172 | |
| 173 rt_->RestoreDrawingState(drawing_state_block_); | |
| 174 } | |
| 175 | |
| 176 bool CanvasDirect2D::ClipRectInt(int x, int y, int w, int h) { | |
| 177 rt_->PushAxisAlignedClip(RectToRectF(x, y, w, h), | |
| 178 D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); | |
| 179 // Increment the clip count so the call to PushAxisAlignedClip() can be | |
| 180 // balanced with a call to PopAxisAlignedClip in the next Restore(). | |
| 181 ++state_.top().clip_count; | |
| 182 return w > 0 && h > 0; | |
| 183 } | |
| 184 | |
| 185 void CanvasDirect2D::TranslateInt(int x, int y) { | |
| 186 D2D1_MATRIX_3X2_F raw; | |
| 187 rt_->GetTransform(&raw); | |
| 188 D2D1::Matrix3x2F transform(raw._11, raw._12, raw._21, raw._22, raw._31, | |
| 189 raw._32); | |
| 190 transform = D2D1::Matrix3x2F::Translation(static_cast<float>(x), | |
| 191 static_cast<float>(y)) * transform; | |
| 192 rt_->SetTransform(transform); | |
| 193 } | |
| 194 | |
| 195 void CanvasDirect2D::ScaleInt(int x, int y) { | |
| 196 D2D1_MATRIX_3X2_F raw; | |
| 197 rt_->GetTransform(&raw); | |
| 198 D2D1::Matrix3x2F transform(raw._11, raw._12, raw._21, raw._22, raw._31, | |
| 199 raw._32); | |
| 200 transform = D2D1::Matrix3x2F::Scale(static_cast<float>(x), | |
| 201 static_cast<float>(y)) * transform; | |
| 202 rt_->SetTransform(transform); | |
| 203 } | |
| 204 | |
| 205 void CanvasDirect2D::FillRectInt(const SkColor& color, | |
| 206 int x, int y, int w, int h) { | |
| 207 ScopedComPtr<ID2D1SolidColorBrush> solid_brush; | |
| 208 rt_->CreateSolidColorBrush(SkColorToColorF(color), solid_brush.Receive()); | |
| 209 rt_->FillRectangle(RectToRectF(x, y, w, h), solid_brush); | |
| 210 } | |
| 211 | |
| 212 void CanvasDirect2D::FillRectInt(const SkColor& color, | |
| 213 int x, int y, int w, int h, | |
| 214 SkXfermode::Mode mode) { | |
| 215 NOTIMPLEMENTED(); | |
| 216 } | |
| 217 | |
| 218 void CanvasDirect2D::FillRectInt(const gfx::Brush* brush, | |
| 219 int x, int y, int w, int h) { | |
| 220 const Direct2DBrush* d2d_brush = static_cast<const Direct2DBrush*>(brush); | |
| 221 rt_->FillRectangle(RectToRectF(x, y, w, h), d2d_brush->brush()); | |
| 222 } | |
| 223 | |
| 224 void CanvasDirect2D::DrawRectInt(const SkColor& color, | |
| 225 int x, int y, int w, int h) { | |
| 226 ScopedComPtr<ID2D1SolidColorBrush> solid_brush; | |
| 227 rt_->CreateSolidColorBrush(SkColorToColorF(color), solid_brush.Receive()); | |
| 228 rt_->DrawRectangle(RectToRectF(x, y, w, h), solid_brush); | |
| 229 } | |
| 230 | |
| 231 void CanvasDirect2D::DrawRectInt(const SkColor& color, | |
| 232 int x, int y, int w, int h, | |
| 233 SkXfermode::Mode mode) { | |
| 234 NOTIMPLEMENTED(); | |
| 235 } | |
| 236 | |
| 237 void CanvasDirect2D::DrawRectInt(int x, int y, int w, int h, | |
| 238 const SkPaint& paint) { | |
| 239 NOTIMPLEMENTED(); | |
| 240 } | |
| 241 | |
| 242 void CanvasDirect2D::DrawLineInt(const SkColor& color, | |
| 243 int x1, int y1, | |
| 244 int x2, int y2) { | |
| 245 ScopedComPtr<ID2D1SolidColorBrush> solid_brush; | |
| 246 rt_->CreateSolidColorBrush(SkColorToColorF(color), solid_brush.Receive()); | |
| 247 rt_->DrawLine(PointToPoint2F(x1, y1), PointToPoint2F(x2, y2), solid_brush); | |
| 248 } | |
| 249 | |
| 250 void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) { | |
| 251 ScopedComPtr<ID2D1Bitmap> d2d1_bitmap( | |
| 252 CreateD2D1BitmapFromSkBitmap(rt_, bitmap)); | |
| 253 rt_->DrawBitmap(d2d1_bitmap, | |
| 254 RectToRectF(x, y, bitmap.width(), bitmap.height()), | |
| 255 1.0f, | |
| 256 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, | |
| 257 RectToRectF(0, 0, bitmap.width(), bitmap.height())); | |
| 258 } | |
| 259 | |
| 260 void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, | |
| 261 int x, int y, | |
| 262 const SkPaint& paint) { | |
| 263 NOTIMPLEMENTED(); | |
| 264 } | |
| 265 | |
| 266 void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, | |
| 267 int src_x, int src_y, int src_w, int src_h, | |
| 268 int dest_x, int dest_y, | |
| 269 int dest_w, int dest_h, | |
| 270 bool filter) { | |
| 271 ScopedComPtr<ID2D1Bitmap> d2d1_bitmap( | |
| 272 CreateD2D1BitmapFromSkBitmap(rt_, bitmap)); | |
| 273 rt_->DrawBitmap(d2d1_bitmap, | |
| 274 RectToRectF(dest_x, dest_y, dest_w, dest_h), | |
| 275 1.0f, | |
| 276 FilterToInterpolationMode(filter), | |
| 277 RectToRectF(src_x, src_y, src_w, src_h)); | |
| 278 } | |
| 279 | |
| 280 void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, | |
| 281 int src_x, int src_y, int src_w, int src_h, | |
| 282 int dest_x, int dest_y, | |
| 283 int dest_w, int dest_h, | |
| 284 bool filter, | |
| 285 const SkPaint& paint) { | |
| 286 NOTIMPLEMENTED(); | |
| 287 } | |
| 288 | |
| 289 void CanvasDirect2D::DrawStringInt(const string16& text, | |
| 290 const gfx::Font& font, | |
| 291 const SkColor& color, | |
| 292 int x, int y, int w, int h) { | |
| 293 NOTIMPLEMENTED(); | |
| 294 } | |
| 295 | |
| 296 void CanvasDirect2D::DrawStringInt(const string16& text, | |
| 297 const gfx::Font& font, | |
| 298 const SkColor& color, | |
| 299 const gfx::Rect& display_rect) { | |
| 300 NOTIMPLEMENTED(); | |
| 301 } | |
| 302 | |
| 303 void CanvasDirect2D::DrawStringInt(const string16& text, | |
| 304 const gfx::Font& font, | |
| 305 const SkColor& color, | |
| 306 int x, int y, int w, int h, | |
| 307 int flags) { | |
| 308 NOTIMPLEMENTED(); | |
| 309 } | |
| 310 | |
| 311 void CanvasDirect2D::DrawFocusRect(int x, int y, int width, int height) { | |
| 312 NOTIMPLEMENTED(); | |
| 313 } | |
| 314 | |
| 315 void CanvasDirect2D::TileImageInt(const SkBitmap& bitmap, | |
| 316 int x, int y, int w, int h) { | |
| 317 ScopedComPtr<ID2D1Brush> brush( | |
| 318 CreateD2D1BrushFromSkBitmap(rt_, bitmap, D2D1_EXTEND_MODE_WRAP, | |
| 319 D2D1_EXTEND_MODE_WRAP)); | |
| 320 rt_->FillRectangle(RectToRectF(x, y, w, h), brush); | |
| 321 } | |
| 322 | |
| 323 void CanvasDirect2D::TileImageInt(const SkBitmap& bitmap, | |
| 324 int src_x, int src_y, | |
| 325 int dest_x, int dest_y, int w, int h) { | |
| 326 NOTIMPLEMENTED(); | |
| 327 } | |
| 328 | |
| 329 gfx::NativeDrawingContext CanvasDirect2D::BeginPlatformPaint() { | |
| 330 DCHECK(!interop_rt_.get()); | |
| 331 interop_rt_.QueryFrom(rt_); | |
| 332 HDC dc = NULL; | |
| 333 if (interop_rt_.get()) | |
| 334 interop_rt_->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &dc); | |
| 335 return dc; | |
| 336 } | |
| 337 | |
| 338 void CanvasDirect2D::EndPlatformPaint() { | |
| 339 DCHECK(interop_rt_.get()); | |
| 340 interop_rt_->ReleaseDC(NULL); | |
| 341 interop_rt_.release(); | |
| 342 } | |
| 343 | |
| 344 CanvasSkia* CanvasDirect2D::AsCanvasSkia() { | |
| 345 return NULL; | |
| 346 } | |
| 347 | |
| 348 const CanvasSkia* CanvasDirect2D::AsCanvasSkia() const { | |
| 349 return NULL; | |
| 350 } | |
| 351 | |
| 352 //////////////////////////////////////////////////////////////////////////////// | |
| 353 // CanvasDirect2D, private: | |
| 354 | |
| 355 void CanvasDirect2D::SaveInternal(ID2D1Layer* layer) { | |
| 356 if (!drawing_state_block_) | |
| 357 GetD2D1Factory()->CreateDrawingStateBlock(drawing_state_block_.Receive()); | |
| 358 rt_->SaveDrawingState(drawing_state_block_.get()); | |
| 359 state_.push(RenderState(layer)); | |
| 360 } | |
| 361 | |
| 362 } // namespace gfx | |
| OLD | NEW |