diff options
Diffstat (limited to 'ui/gfx')
-rw-r--r-- | ui/gfx/render_text_win.cc | 14 | ||||
-rw-r--r-- | ui/gfx/screen_compatible_dc_win.cc | 122 | ||||
-rw-r--r-- | ui/gfx/screen_compatible_dc_win.h | 32 |
3 files changed, 161 insertions, 7 deletions
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc index 28dcce8..87fa314 100644 --- a/ui/gfx/render_text_win.cc +++ b/ui/gfx/render_text_win.cc @@ -11,7 +11,7 @@ #include "base/stl_util.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "base/win/scoped_hdc.h" +#include "ui/gfx/screen_compatible_dc_win.h" #include "ui/gfx/canvas.h" #include "ui/gfx/canvas_skia.h" #include "ui/gfx/platform_font.h" @@ -595,7 +595,7 @@ void RenderTextWin::ItemizeLogicalText() { void RenderTextWin::LayoutVisualText() { HRESULT hr = E_FAIL; - base::win::ScopedCreateDC hdc(CreateCompatibleDC(NULL)); + ScopedTemporaryScreenCompatibleDC hdc; std::vector<internal::TextRun*>::const_iterator run_iter; for (run_iter = runs_.begin(); run_iter < runs_.end(); ++run_iter) { internal::TextRun* run = *run_iter; @@ -604,7 +604,7 @@ void RenderTextWin::LayoutVisualText() { bool tried_fallback = false; // Select the font desired for glyph generation. - SelectObject(hdc, run->font.GetNativeFont()); + SelectObject(hdc.get(), run->font.GetNativeFont()); run->logical_clusters.reset(new WORD[run_length]); run->glyph_count = 0; @@ -613,7 +613,7 @@ void RenderTextWin::LayoutVisualText() { while (max_glyphs < kMaxGlyphs) { run->glyphs.reset(new WORD[max_glyphs]); run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]); - hr = ScriptShape(hdc, + hr = ScriptShape(hdc.get(), &run->script_cache, run_text, run_length, @@ -644,10 +644,10 @@ void RenderTextWin::LayoutVisualText() { // The run's font doesn't contain the required glyphs, use an alternate. // TODO(msw): support RenderText's font_list(). - if (ChooseFallbackFont(hdc, run->font, run_text, run_length, + if (ChooseFallbackFont(hdc.get(), run->font, run_text, run_length, &run->font)) { ScriptFreeCache(&run->script_cache); - SelectObject(hdc, run->font.GetNativeFont()); + SelectObject(hdc.get(), run->font.GetNativeFont()); } tried_fallback = true; @@ -660,7 +660,7 @@ void RenderTextWin::LayoutVisualText() { if (run->glyph_count > 0) { run->advance_widths.reset(new int[run->glyph_count]); run->offsets.reset(new GOFFSET[run->glyph_count]); - hr = ScriptPlace(hdc, + hr = ScriptPlace(hdc.get(), &run->script_cache, run->glyphs.get(), run->glyph_count, diff --git a/ui/gfx/screen_compatible_dc_win.cc b/ui/gfx/screen_compatible_dc_win.cc new file mode 100644 index 0000000..7e3a33b --- /dev/null +++ b/ui/gfx/screen_compatible_dc_win.cc @@ -0,0 +1,122 @@ +// 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/screen_compatible_dc_win.h" + +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "base/win/wrapped_window_proc.h" +#include "ui/base/win/hwnd_util.h" + +namespace { + +// Windows class name to use for the listener window. +const wchar_t kWindowClassName[] = L"CachedCompatibleDC_Invalidator"; + +class CachedCompatibleDC { + public: + // Singleton getter. + static CachedCompatibleDC* GetInstance(); + + // Returns the cached screen compatible DC or creates one if needed. + HDC GetOrCreateCompatibleDC(); + + // Deletes the cached DC, called on WM_DISPLAYCHANGE notifications. + void DeleteCachedCompatibleDC(); + + private: + // Cached device context compatible with the screen. + HDC compatible_dc_; + + // HWND for listening to WM_DISPLAYCHANGE notifications. + HWND listener_window_; + + CachedCompatibleDC(); + ~CachedCompatibleDC(); + + friend struct DefaultSingletonTraits<CachedCompatibleDC>; + + DISALLOW_COPY_AND_ASSIGN(CachedCompatibleDC); +}; + +// Windows callback for listening for WM_DISPLAYCHANGE messages. +LRESULT CALLBACK ListenerWindowProc(HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) { + if (message == WM_DISPLAYCHANGE) + CachedCompatibleDC::GetInstance()->DeleteCachedCompatibleDC(); + + return ::DefWindowProc(hwnd, message, wparam, lparam); +} + +// Creates a listener window to handle WM_DISPLAYCHANGE messages. +HWND CreateListenerWindow() { + HINSTANCE hinst = 0; + if (!::GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + reinterpret_cast<char*>(&ListenerWindowProc), + &hinst)) { + NOTREACHED(); + } + + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(wc); + wc.lpfnWndProc = base::win::WrappedWindowProc<ListenerWindowProc>; + wc.hInstance = hinst; + wc.lpszClassName = kWindowClassName; + ATOM clazz = ::RegisterClassEx(&wc); + DCHECK(clazz); + + return ::CreateWindow(MAKEINTATOM(clazz), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, + hinst, 0); +} + +CachedCompatibleDC::CachedCompatibleDC() + : compatible_dc_(NULL), + listener_window_(NULL) { +} + +CachedCompatibleDC::~CachedCompatibleDC() { + DeleteCachedCompatibleDC(); + if (listener_window_) { + ::DestroyWindow(listener_window_); + ::UnregisterClass(kWindowClassName, GetModuleHandle(NULL)); + } +} + +// static +CachedCompatibleDC* CachedCompatibleDC::GetInstance() { + return Singleton<CachedCompatibleDC>::get(); +} + +HDC CachedCompatibleDC::GetOrCreateCompatibleDC() { + if (!compatible_dc_) { + compatible_dc_ = ::CreateCompatibleDC(NULL); + if (!listener_window_) { + listener_window_ = CreateListenerWindow(); + ui::CheckWindowCreated(listener_window_); + } + } + return compatible_dc_; +} + +void CachedCompatibleDC::DeleteCachedCompatibleDC() { + if (compatible_dc_) { + ::DeleteDC(compatible_dc_); + compatible_dc_ = NULL; + } +} + +} // namespace + +namespace gfx { + +ScopedTemporaryScreenCompatibleDC::ScopedTemporaryScreenCompatibleDC() + : hdc_(CachedCompatibleDC::GetInstance()->GetOrCreateCompatibleDC()) { +} + +ScopedTemporaryScreenCompatibleDC::~ScopedTemporaryScreenCompatibleDC() { +} + +} // namespace gfx diff --git a/ui/gfx/screen_compatible_dc_win.h b/ui/gfx/screen_compatible_dc_win.h new file mode 100644 index 0000000..d20c93a --- /dev/null +++ b/ui/gfx/screen_compatible_dc_win.h @@ -0,0 +1,32 @@ +// 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_SCREEN_COMPATIBLE_DC_WIN_H_ +#define UI_GFX_SCREEN_COMPATIBLE_DC_WIN_H_ +#pragma once + +#include <windows.h> + +#include "base/basictypes.h" + +namespace gfx { + +// Temporary device context that is compatible with the screen. Can be used for +// short-lived operations on the UI threads. +class ScopedTemporaryScreenCompatibleDC { + public: + ScopedTemporaryScreenCompatibleDC(); + ~ScopedTemporaryScreenCompatibleDC(); + + HDC get() const { return hdc_; } + + private: + HDC hdc_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTemporaryScreenCompatibleDC); +}; + +} // namespace gfx + +#endif // UI_GFX_SCREEN_COMPATIBLE_DC_WIN_H_ |