summaryrefslogtreecommitdiffstats
path: root/chromium/ui/gfx/color_profile_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/gfx/color_profile_win.cc')
-rw-r--r--chromium/ui/gfx/color_profile_win.cc98
1 files changed, 92 insertions, 6 deletions
diff --git a/chromium/ui/gfx/color_profile_win.cc b/chromium/ui/gfx/color_profile_win.cc
index 2e08a36d4b6..a22c3d96a18 100644
--- a/chromium/ui/gfx/color_profile_win.cc
+++ b/chromium/ui/gfx/color_profile_win.cc
@@ -4,32 +4,118 @@
#include "ui/gfx/color_profile.h"
+#include <map>
#include <windows.h>
#include "base/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/synchronization/lock.h"
namespace gfx {
+class ColorProfileCache {
+ public:
+ // A thread-safe cache of color profiles keyed by windows device name.
+ ColorProfileCache() {}
+
+ bool Find(const std::wstring& device, std::vector<char>* profile) {
+ base::AutoLock lock(lock_);
+ DeviceColorProfile::const_iterator it = cache_.find(device);
+ if (it == cache_.end())
+ return false;
+ *profile = it->second;
+ return true;
+ }
+
+ void Insert(const std::wstring& device, const std::vector<char>& profile) {
+ base::AutoLock lock(lock_);
+ cache_[device] = profile;
+ }
+
+ bool Erase(const std::wstring& device) {
+ base::AutoLock lock(lock_);
+ DeviceColorProfile::iterator it = cache_.find(device);
+ if (it == cache_.end())
+ return false;
+ cache_.erase(device);
+ return true;
+ }
+
+ void Clear() {
+ base::AutoLock lock(lock_);
+ cache_.clear();
+ }
+
+ private:
+ typedef std::map<std::wstring, std::vector<char> > DeviceColorProfile;
+
+ DeviceColorProfile cache_;
+ base::Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ColorProfileCache);
+};
+
+base::LazyInstance<ColorProfileCache>::Leaky g_color_profile_cache =
+ LAZY_INSTANCE_INITIALIZER;
+
+inline ColorProfileCache& GetColorProfileCache() {
+ return g_color_profile_cache.Get();
+}
+
+bool GetDisplayColorProfile(const gfx::Rect& bounds,
+ std::vector<char>* profile) {
+ DCHECK(profile->empty());
+
+ RECT rect = bounds.ToRECT();
+ HMONITOR handle = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONULL);
+ if (bounds.IsEmpty() || !handle)
+ return false;
+
+ MONITORINFOEX monitor;
+ monitor.cbSize = sizeof(MONITORINFOEX);
+ CHECK(::GetMonitorInfo(handle, &monitor));
+ if (GetColorProfileCache().Find(monitor.szDevice, profile))
+ return true;
+
+ HDC hdc = ::CreateDC(monitor.szDevice, NULL, NULL, NULL);
+ DWORD path_length = MAX_PATH;
+ WCHAR path[MAX_PATH + 1];
+ BOOL result = ::GetICMProfile(hdc, &path_length, path);
+ ::DeleteDC(hdc);
+ if (!result)
+ return false;
+
+ base::FilePath file_name = base::FilePath(path).BaseName();
+ if (file_name != base::FilePath(L"sRGB Color Space Profile.icm")) {
+ std::string data;
+ if (base::ReadFileToString(base::FilePath(path), &data))
+ profile->assign(data.data(), data.data() + data.size());
+ size_t length = profile->size();
+ if (gfx::InvalidColorProfileLength(length))
+ profile->clear();
+ }
+
+ GetColorProfileCache().Insert(monitor.szDevice, *profile);
+ return true;
+}
+
void ReadColorProfile(std::vector<char>* profile) {
// TODO: support multiple monitors.
HDC screen_dc = GetDC(NULL);
DWORD path_len = MAX_PATH;
WCHAR path[MAX_PATH + 1];
- BOOL res = GetICMProfile(screen_dc, &path_len, path);
+ BOOL result = GetICMProfile(screen_dc, &path_len, path);
ReleaseDC(NULL, screen_dc);
- if (!res)
+ if (!result)
return;
std::string profileData;
if (!base::ReadFileToString(base::FilePath(path), &profileData))
return;
size_t length = profileData.size();
- if (length > gfx::kMaxProfileLength)
- return;
- if (length < gfx::kMinProfileLength)
+ if (gfx::InvalidColorProfileLength(length))
return;
profile->assign(profileData.data(), profileData.data() + length);
}
} // namespace gfx
-