diff options
author | reed@google.com <reed@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-30 13:46:12 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-30 13:46:12 +0000 |
commit | 263fc7a4101301195c888664c013eab179e57ff5 (patch) | |
tree | 626fdefbdf2f5703fc872a932bc1ddf85eb13a37 /ui/gfx | |
parent | 03e09f16f1a65030e6ea566b005c3885b23dca6e (diff) | |
download | chromium_src-263fc7a4101301195c888664c013eab179e57ff5.zip chromium_src-263fc7a4101301195c888664c013eab179e57ff5.tar.gz chromium_src-263fc7a4101301195c888664c013eab179e57ff5.tar.bz2 |
reapply 164660 w/ fix to add UI_EXPORT to new classes, so we can link in component build.
https://codereview.chromium.org/11193037/
Review URL: https://codereview.chromium.org/11338013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164905 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r-- | ui/gfx/canvas_paint_gtk.cc | 72 | ||||
-rw-r--r-- | ui/gfx/canvas_paint_gtk.h | 62 | ||||
-rw-r--r-- | ui/gfx/canvas_paint_mac.h | 59 | ||||
-rw-r--r-- | ui/gfx/canvas_paint_mac.mm | 77 | ||||
-rw-r--r-- | ui/gfx/canvas_paint_win.cc | 1 | ||||
-rw-r--r-- | ui/gfx/canvas_paint_win.h | 135 | ||||
-rw-r--r-- | ui/gfx/canvas_skia_paint.h | 46 |
7 files changed, 419 insertions, 33 deletions
diff --git a/ui/gfx/canvas_paint_gtk.cc b/ui/gfx/canvas_paint_gtk.cc new file mode 100644 index 0000000..ded981b --- /dev/null +++ b/ui/gfx/canvas_paint_gtk.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/canvas_skia_paint.h" +#include "ui/gfx/rect.h" + +namespace gfx { + +CanvasSkiaPaint::CanvasSkiaPaint(GdkEventExpose* event) + : context_(NULL), + window_(event->window), + region_(gdk_region_copy(event->region)), + composite_alpha_(false) { + Init(true); +} + +CanvasSkiaPaint::CanvasSkiaPaint(GdkEventExpose* event, bool opaque) + : context_(NULL), + window_(event->window), + region_(gdk_region_copy(event->region)), + composite_alpha_(false) { + Init(opaque); +} + +CanvasSkiaPaint::~CanvasSkiaPaint() { + if (!is_empty()) { + platform_canvas()->restoreToCount(1); + + // Blit the dirty rect to the window. + CHECK(window_); + cairo_t* cr = gdk_cairo_create(window_); + CHECK(cr); + if (composite_alpha_) + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_surface_t* source_surface = cairo_get_target(context_); + CHECK(source_surface); + // Flush cairo's cache of the surface. + cairo_surface_mark_dirty(source_surface); + GdkRectangle bounds = rectangle(); + cairo_set_source_surface(cr, source_surface, bounds.x, bounds.y); + gdk_cairo_region(cr, region_); + cairo_fill(cr); + cairo_destroy(cr); + } + + gdk_region_destroy(region_); +} + +void CanvasSkiaPaint::Init(bool opaque) { + GdkRectangle bounds = rectangle(); + skia::PlatformCanvas* canvas = platform_canvas(); + if (!canvas->initialize(bounds.width, bounds.height, opaque, NULL)) { + // Cause a deliberate crash; + CHECK(false); + } + // No need to clear the canvas, because cairo automatically performs the + // clear. + + // Need to translate so that the dirty region appears at the origin of the + // surface. + canvas->translate(-SkIntToScalar(bounds.x), -SkIntToScalar(bounds.y)); + + context_ = skia::BeginPlatformPaint(canvas); +} + +} // namespace gfx + + diff --git a/ui/gfx/canvas_paint_gtk.h b/ui/gfx/canvas_paint_gtk.h new file mode 100644 index 0000000..889f308 --- /dev/null +++ b/ui/gfx/canvas_paint_gtk.h @@ -0,0 +1,62 @@ + +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_CANVAS_PAINT_LINUX_H_ +#define UI_GFX_CANVAS_PAINT_LINUX_H_ + +#include "base/logging.h" +#include "skia/ext/platform_canvas.h" +#include "ui/gfx/canvas.h" +#include <gdk/gdk.h> + +namespace gfx { + +// A class designed to translate skia painting into a region in a GdkWindow. +// On construction, it will set up a context for painting into, and on +// destruction, it will commit it to the GdkWindow. +// Note: The created context is always inialized to (0, 0, 0, 0). +class UI_EXPORT CanvasSkiaPaint : public Canvas { + public: + // This constructor assumes the result is opaque. + explicit CanvasSkiaPaint(GdkEventExpose* event); + CanvasSkiaPaint(GdkEventExpose* event, bool opaque); + virtual ~CanvasSkiaPaint(); + + // Sets whether the bitmap is composited in such a way that the alpha channel + // is honored. This is only useful if you've enabled an RGBA colormap on the + // widget. The default is false. + void set_composite_alpha(bool composite_alpha) { + composite_alpha_ = composite_alpha; + } + + // Returns true if the invalid region is empty. The caller should call this + // function to determine if anything needs painting. + bool is_empty() const { + return gdk_region_empty(region_); + } + + GdkRectangle rectangle() const { + GdkRectangle bounds; + gdk_region_get_clipbox(region_, &bounds); + return bounds; + } + + private: + void Init(bool opaque); + + cairo_t* context_; + GdkWindow* window_; + GdkRegion* region_; + // See description above setter. + bool composite_alpha_; + + // Disallow copy and assign. + CanvasSkiaPaint(const CanvasSkiaPaint&); + CanvasSkiaPaint& operator=(const CanvasSkiaPaint&); +}; + +} // namespace gfx + +#endif // UI_GFX_CANVAS_PAINT_LINUX_H_ diff --git a/ui/gfx/canvas_paint_mac.h b/ui/gfx/canvas_paint_mac.h new file mode 100644 index 0000000..16d7410 --- /dev/null +++ b/ui/gfx/canvas_paint_mac.h @@ -0,0 +1,59 @@ + +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_CANVAS_PAINT_MAC_H_ +#define UI_GFX_CANVAS_PAINT_MAC_H_ + +#include "skia/ext/platform_canvas.h" +#include "ui/gfx/canvas.h" + +#import <Cocoa/Cocoa.h> + +namespace gfx { + +// A class designed to translate skia painting into a region to the current +// graphics context. On construction, it will set up a context for painting +// into, and on destruction, it will commit it to the current context. +// Note: The created context is always inialized to (0, 0, 0, 0). +class UI_EXPORT CanvasSkiaPaint : public Canvas { + public: + // This constructor assumes the result is opaque. + explicit CanvasSkiaPaint(NSRect dirtyRect); + CanvasSkiaPaint(NSRect dirtyRect, bool opaque); + virtual ~CanvasSkiaPaint(); + + // If true, the data painted into the CanvasSkiaPaint is blended onto the + // current context, else it is copied. + void set_composite_alpha(bool composite_alpha) { + composite_alpha_ = composite_alpha; + } + + // Returns true if the invalid region is empty. The caller should call this + // function to determine if anything needs painting. + bool is_empty() const { + return NSIsEmptyRect(rectangle_); + } + + const NSRect& rectangle() const { + return rectangle_; + } + + private: + void Init(bool opaque); + + CGContext* context_; + NSRect rectangle_; + // See description above setter. + bool composite_alpha_; + + // Disallow copy and assign. + CanvasSkiaPaint(const CanvasSkiaPaint&); + CanvasSkiaPaint& operator=(const CanvasSkiaPaint&); +}; + +} // namespace gfx + + +#endif // UI_GFX_CANVAS_PAINT_MAC_H_ diff --git a/ui/gfx/canvas_paint_mac.mm b/ui/gfx/canvas_paint_mac.mm new file mode 100644 index 0000000..391436f --- /dev/null +++ b/ui/gfx/canvas_paint_mac.mm @@ -0,0 +1,77 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gfx/canvas_paint_mac.h" +#include "ui/gfx/size.h" + +namespace gfx { + +CanvasSkiaPaint::CanvasSkiaPaint(NSRect dirtyRect) + : context_(NULL), + rectangle_(dirtyRect), + composite_alpha_(false) { + Init(true); +} + +CanvasSkiaPaint::CanvasSkiaPaint(NSRect dirtyRect, bool opaque) + : context_(NULL), + rectangle_(dirtyRect), + composite_alpha_(false) { + Init(opaque); +} + +CanvasSkiaPaint::~CanvasSkiaPaint() { + if (!is_empty()) { + platform_canvas()->restoreToCount(1); + + // Blit the dirty rect to the current context. + CGImageRef image = CGBitmapContextCreateImage(context_); + CGRect dest_rect = NSRectToCGRect(rectangle_); + + CGContextRef destination_context = + (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(destination_context); + CGContextSetBlendMode( + destination_context, + composite_alpha_ ? kCGBlendModeNormal : kCGBlendModeCopy); + + if ([[NSGraphicsContext currentContext] isFlipped]) { + // Mirror context on the target's rect middle scanline. + CGContextTranslateCTM(destination_context, 0.0, NSMidY(rectangle_)); + CGContextScaleCTM(destination_context, 1.0, -1.0); + CGContextTranslateCTM(destination_context, 0.0, -NSMidY(rectangle_)); + } + + CGContextDrawImage(destination_context, dest_rect, image); + CGContextRestoreGState(destination_context); + + CFRelease(image); + } +} + +void CanvasSkiaPaint::Init(bool opaque) { + CGContextRef destination_context = + (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGRect scaled_unit_rect = CGContextConvertRectToDeviceSpace( + destination_context, CGRectMake(0, 0, 1, 1)); + // Assume that the x scale and the y scale are the same. + CGFloat scale = scaled_unit_rect.size.width; + + ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale); + gfx::Size size(NSWidth(rectangle_), NSHeight(rectangle_)); + this->RecreateBackingCanvas(size, scale_factor, opaque); + skia::PlatformCanvas* canvas = platform_canvas(); + canvas->clear(SkColorSetARGB(0, 0, 0, 0)); + + // Need to translate so that the dirty region appears at the origin of the + // surface. + canvas->translate(-SkDoubleToScalar(NSMinX(rectangle_)), + -SkDoubleToScalar(NSMinY(rectangle_))); + + context_ = skia::GetBitmapContext(skia::GetTopDevice(*canvas)); +} + +} // namespace skia + + diff --git a/ui/gfx/canvas_paint_win.cc b/ui/gfx/canvas_paint_win.cc index 87ba3f6..27898fc 100644 --- a/ui/gfx/canvas_paint_win.cc +++ b/ui/gfx/canvas_paint_win.cc @@ -5,7 +5,6 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/canvas_paint.h" #include "ui/gfx/canvas_skia_paint.h" #include "ui/gfx/rect.h" diff --git a/ui/gfx/canvas_paint_win.h b/ui/gfx/canvas_paint_win.h new file mode 100644 index 0000000..8a146e1 --- /dev/null +++ b/ui/gfx/canvas_paint_win.h @@ -0,0 +1,135 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_CANVAS_PAINT_WIN_H_ +#define UI_GFX_CANVAS_PAINT_WIN_H_ + +#include "skia/ext/platform_canvas.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/canvas_paint.h" + +namespace gfx { + +// A class designed to help with WM_PAINT operations on Windows. It will +// do BeginPaint/EndPaint on init/destruction, and will create the bitmap and +// canvas with the correct size and transform for the dirty rect. The bitmap +// will be automatically painted to the screen on destruction. +// +// You MUST call isEmpty before painting to determine if anything needs +// painting. Sometimes the dirty rect can actually be empty, and this makes +// the bitmap functions we call unhappy. The caller should not paint in this +// case. +// +// Therefore, all you need to do is: +// case WM_PAINT: { +// gfx::PlatformCanvasPaint canvas(hwnd); +// if (!canvas.isEmpty()) { +// ... paint to the canvas ... +// } +// return 0; +// } +// Note: The created context is always inialized to (0, 0, 0, 0). +class UI_EXPORT CanvasSkiaPaint : public Canvas { + public: + // This constructor assumes the canvas is opaque. + explicit CanvasSkiaPaint(HWND hwnd) : hwnd_(hwnd), paint_dc_(NULL), + for_paint_(true) { + memset(&ps_, 0, sizeof(ps_)); + initPaint(true); + } + + CanvasSkiaPaint(HWND hwnd, bool opaque) : hwnd_(hwnd), paint_dc_(NULL), + for_paint_(true) { + memset(&ps_, 0, sizeof(ps_)); + initPaint(opaque); + } + + // Creates a CanvasSkiaPaint for the specified region that paints to the + // specified dc. This does NOT do BeginPaint/EndPaint. + CanvasSkiaPaint(HDC dc, bool opaque, int x, int y, int w, int h) + : hwnd_(NULL), + paint_dc_(dc), + for_paint_(false) { + memset(&ps_, 0, sizeof(ps_)); + ps_.rcPaint.left = x; + ps_.rcPaint.right = x + w; + ps_.rcPaint.top = y; + ps_.rcPaint.bottom = y + h; + init(opaque); + } + + virtual ~CanvasSkiaPaint() { + if (!isEmpty()) { + skia::PlatformCanvas* canvas = platform_canvas(); + canvas->restoreToCount(1); + // Commit the drawing to the screen + skia::DrawToNativeContext(canvas, paint_dc_, ps_.rcPaint.left, + ps_.rcPaint.top, NULL); + } + if (for_paint_) + EndPaint(hwnd_, &ps_); + } + + // Returns true if the invalid region is empty. The caller should call this + // function to determine if anything needs painting. + bool isEmpty() const { + return ps_.rcPaint.right - ps_.rcPaint.left == 0 || + ps_.rcPaint.bottom - ps_.rcPaint.top == 0; + } + + // Use to access the Windows painting parameters, especially useful for + // getting the bounding rect for painting: paintstruct().rcPaint + const PAINTSTRUCT& paintStruct() const { + return ps_; + } + + // Returns the DC that will be painted to + HDC paintDC() const { + return paint_dc_; + } + + protected: + HWND hwnd_; + HDC paint_dc_; + PAINTSTRUCT ps_; + + private: + void initPaint(bool opaque) { + paint_dc_ = BeginPaint(hwnd_, &ps_); + + init(opaque); + } + + void init(bool opaque) { + skia::PlatformCanvas* canvas = platform_canvas(); + // FIXME(brettw) for ClearType, we probably want to expand the bounds of + // painting by one pixel so that the boundaries will be correct (ClearType + // text can depend on the adjacent pixel). Then we would paint just the + // inset pixels to the screen. + const int width = ps_.rcPaint.right - ps_.rcPaint.left; + const int height = ps_.rcPaint.bottom - ps_.rcPaint.top; + if (!canvas->initialize(width, height, opaque, NULL)) { + // Cause a deliberate crash; + __debugbreak(); + _exit(1); + } + canvas->clear(SkColorSetARGB(0, 0, 0, 0)); + + // This will bring the canvas into the screen coordinate system for the + // dirty rect + canvas->translate(SkIntToScalar(-ps_.rcPaint.left), + SkIntToScalar(-ps_.rcPaint.top)); + } + + // If true, this canvas was created for a BeginPaint. + const bool for_paint_; + + // Disallow copy and assign. + CanvasSkiaPaint(const CanvasSkiaPaint&); + CanvasSkiaPaint& operator=(const CanvasSkiaPaint&); +}; + +} // namespace gfx + +#endif // UI_GFX_CANVAS_PAINT_WIN_H_ diff --git a/ui/gfx/canvas_skia_paint.h b/ui/gfx/canvas_skia_paint.h index ad92d94..3f21f5c 100644 --- a/ui/gfx/canvas_skia_paint.h +++ b/ui/gfx/canvas_skia_paint.h @@ -5,37 +5,19 @@ #ifndef UI_GFX_CANVAS_SKIA_PAINT_H_ #define UI_GFX_CANVAS_SKIA_PAINT_H_ -#include "base/logging.h" -#include "skia/ext/canvas_paint.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/size.h" - -// Define a gfx::CanvasSkiaPaint type that wraps our gfx::Canvas like the -// skia::PlatformCanvasPaint wraps PlatformCanvas. - -namespace skia { - -template<> inline -PlatformCanvas* GetPlatformCanvas(skia::CanvasPaintT<gfx::Canvas>* canvas) { - PlatformCanvas* platform_canvas = canvas->platform_canvas(); - DCHECK(platform_canvas); - return platform_canvas; -} - -template<> inline -void RecreateBackingCanvas(skia::CanvasPaintT<gfx::Canvas>* canvas, - int width, int height, float scale, bool opaque) { - ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale); - canvas->RecreateBackingCanvas(gfx::Size(width, height), scale_factor, - opaque); -} - -} // namespace skia - -namespace gfx { - -typedef skia::CanvasPaintT<Canvas> CanvasSkiaPaint; - -} // namespace gfx +// This file provides an easy way to include the appropriate CanvasPaint +// header file on your platform. + +#if defined(WIN32) +#include "ui/gfx/canvas_paint_win.h" +#elif defined(__APPLE__) +#include "ui/gfx/canvas_paint_mac.h" +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) +#if defined(TOOLKIT_GTK) +#include "ui/gfx/canvas_paint_gtk.h" +#else +#error "No canvas paint for this platform" +#endif +#endif #endif // UI_GFX_CANVAS_SKIA_PAINT_H_ |