1 // Copyright (c) 2012 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.
5 #include "ui/gfx/color_profile.h"
10 #include "base/files/file_util.h"
11 #include "base/lazy_instance.h"
12 #include "base/synchronization/lock.h"
16 class ColorProfileCache
{
18 // A thread-safe cache of color profiles keyed by windows device name.
19 ColorProfileCache() {}
21 bool Find(const std::wstring
& device
, std::vector
<char>* profile
) {
22 base::AutoLock
lock(lock_
);
23 DeviceColorProfile::const_iterator it
= cache_
.find(device
);
24 if (it
== cache_
.end())
26 *profile
= it
->second
;
30 void Insert(const std::wstring
& device
, const std::vector
<char>& profile
) {
31 base::AutoLock
lock(lock_
);
32 cache_
[device
] = profile
;
35 bool Erase(const std::wstring
& device
) {
36 base::AutoLock
lock(lock_
);
37 DeviceColorProfile::iterator it
= cache_
.find(device
);
38 if (it
== cache_
.end())
45 base::AutoLock
lock(lock_
);
50 typedef std::map
<std::wstring
, std::vector
<char> > DeviceColorProfile
;
52 DeviceColorProfile cache_
;
55 DISALLOW_COPY_AND_ASSIGN(ColorProfileCache
);
58 base::LazyInstance
<ColorProfileCache
>::Leaky g_color_profile_cache
=
59 LAZY_INSTANCE_INITIALIZER
;
61 inline ColorProfileCache
& GetColorProfileCache() {
62 return g_color_profile_cache
.Get();
65 bool GetDisplayColorProfile(const gfx::Rect
& bounds
,
66 std::vector
<char>* profile
) {
67 DCHECK(profile
->empty());
69 RECT rect
= bounds
.ToRECT();
70 HMONITOR handle
= ::MonitorFromRect(&rect
, MONITOR_DEFAULTTONULL
);
71 if (bounds
.IsEmpty() || !handle
)
74 MONITORINFOEX monitor
;
75 monitor
.cbSize
= sizeof(MONITORINFOEX
);
76 CHECK(::GetMonitorInfo(handle
, &monitor
));
77 if (GetColorProfileCache().Find(monitor
.szDevice
, profile
))
80 HDC hdc
= ::CreateDC(monitor
.szDevice
, NULL
, NULL
, NULL
);
81 DWORD path_length
= MAX_PATH
;
82 WCHAR path
[MAX_PATH
+ 1];
83 BOOL result
= ::GetICMProfile(hdc
, &path_length
, path
);
88 base::FilePath file_name
= base::FilePath(path
).BaseName();
89 if (file_name
!= base::FilePath(L
"sRGB Color Space Profile.icm")) {
91 if (base::ReadFileToString(base::FilePath(path
), &data
))
92 profile
->assign(data
.data(), data
.data() + data
.size());
93 size_t length
= profile
->size();
94 if (gfx::InvalidColorProfileLength(length
))
98 GetColorProfileCache().Insert(monitor
.szDevice
, *profile
);
102 void ReadColorProfile(std::vector
<char>* profile
) {
103 // TODO: support multiple monitors.
104 HDC screen_dc
= GetDC(NULL
);
105 DWORD path_len
= MAX_PATH
;
106 WCHAR path
[MAX_PATH
+ 1];
108 BOOL result
= GetICMProfile(screen_dc
, &path_len
, path
);
109 ReleaseDC(NULL
, screen_dc
);
112 std::string profileData
;
113 if (!base::ReadFileToString(base::FilePath(path
), &profileData
))
115 size_t length
= profileData
.size();
116 if (gfx::InvalidColorProfileLength(length
))
118 profile
->assign(profileData
.data(), profileData
.data() + length
);