1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file.
4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/themes/browser_theme_pack.h"
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/stl_util-inl.h"
8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_util.h"
93f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h"
10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/utf_string_conversions.h"
11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/values.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/themes/theme_service.h"
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/app_resources.h"
15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/theme_resources.h"
16bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/base/file_stream.h"
17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/base/net_errors.h"
18bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "third_party/skia/include/core/SkCanvas.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/data_pack.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/codec/png_codec.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skbitmap_operations.h"
23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace {
25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Version number of the current theme pack. We just throw out and rebuild
27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// theme packs that aren't int-equal to this.
28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kThemePackVersion = 15;
29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// IDs that are in the DataPack won't clash with the positive integer
31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// int32_t. kHeaderID should always have the maximum value because we want the
32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// "header" to be written last. That way we can detect whether the pack was
33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// successfully written and ignore and regenerate if it was only partially
34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// written (i.e. chrome crashed on a different thread while writing the pack).
35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kHeaderID = UINT_MAX - 1;
36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kTintsID = UINT_MAX - 2;
37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kColorsID = UINT_MAX - 3;
38bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kDisplayPropertiesID = UINT_MAX - 4;
39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kSourceImagesID = UINT_MAX - 5;
40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Static size of the tint/color/display property arrays that are mmapped.
42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kTintArraySize = 6;
43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kColorArraySize = 19;
44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kDisplayPropertySize = 3;
45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// The sum of kFrameBorderThickness and kNonClientRestoredExtraThickness from
47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// OpaqueBrowserFrameView.
48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kRestoredTabVerticalOffset = 15;
49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Persistent constants for the main images that we need. These have the same
51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// names as their IDR_* counterparts but these values will always stay the
52bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// same.
53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_FRAME = 1;
54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_FRAME_INACTIVE = 2;
55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_FRAME_INCOGNITO = 3;
56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_FRAME_INCOGNITO_INACTIVE = 4;
57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_TOOLBAR = 5;
58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_TAB_BACKGROUND = 6;
59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_TAB_BACKGROUND_INCOGNITO = 7;
60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_TAB_BACKGROUND_V = 8;
61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_NTP_BACKGROUND = 9;
62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_FRAME_OVERLAY = 10;
63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_FRAME_OVERLAY_INACTIVE = 11;
64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_BUTTON_BACKGROUND = 12;
65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_NTP_ATTRIBUTION = 13;
66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int PRS_THEME_WINDOW_CONTROL_BACKGROUND = 14;
67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstruct PersistingImagesTable {
69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // A non-changing integer ID meant to be saved in theme packs. This ID must
70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // not change between versions of chrome.
71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int persistent_id;
72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // The IDR that depends on the whims of GRIT and therefore changes whenever
74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // someone adds a new resource.
75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int idr_id;
76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // String to check for when parsing theme manifests or NULL if this isn't
78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // supposed to be changeable by the user.
79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  const char* key;
80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
81bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// IDR_* resource names change whenever new resources are added; use persistent
83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// IDs when storing to a cached pack.
84bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenPersistingImagesTable kPersistingImages[] = {
85bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME, IDR_THEME_FRAME,
86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_frame" },
87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME_INACTIVE, IDR_THEME_FRAME_INACTIVE,
88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_frame_inactive" },
89bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME_INCOGNITO, IDR_THEME_FRAME_INCOGNITO,
90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_frame_incognito" },
91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME_INCOGNITO_INACTIVE, IDR_THEME_FRAME_INCOGNITO_INACTIVE,
92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_frame_incognito_inactive" },
93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_TOOLBAR, IDR_THEME_TOOLBAR,
94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_toolbar" },
95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_TAB_BACKGROUND, IDR_THEME_TAB_BACKGROUND,
96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_tab_background" },
97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_TAB_BACKGROUND_INCOGNITO, IDR_THEME_TAB_BACKGROUND_INCOGNITO,
98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_tab_background_incognito" },
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_TAB_BACKGROUND_V, IDR_THEME_TAB_BACKGROUND_V,
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_tab_background_v"},
101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_NTP_BACKGROUND, IDR_THEME_NTP_BACKGROUND,
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_ntp_background" },
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME_OVERLAY, IDR_THEME_FRAME_OVERLAY,
104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_frame_overlay" },
105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME_OVERLAY_INACTIVE, IDR_THEME_FRAME_OVERLAY_INACTIVE,
106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_frame_overlay_inactive" },
107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_BUTTON_BACKGROUND, IDR_THEME_BUTTON_BACKGROUND,
108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_button_background" },
109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_NTP_ATTRIBUTION, IDR_THEME_NTP_ATTRIBUTION,
110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_ntp_attribution" },
111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_WINDOW_CONTROL_BACKGROUND, IDR_THEME_WINDOW_CONTROL_BACKGROUND,
112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "theme_window_control_background"},
113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // The rest of these entries have no key because they can't be overridden
115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // from the json manifest.
116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 15, IDR_BACK, NULL },
117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 16, IDR_BACK_D, NULL },
118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 17, IDR_BACK_H, NULL },
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 18, IDR_BACK_P, NULL },
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 19, IDR_FORWARD, NULL },
121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 20, IDR_FORWARD_D, NULL },
122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 21, IDR_FORWARD_H, NULL },
123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 22, IDR_FORWARD_P, NULL },
124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 23, IDR_HOME, NULL },
125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 24, IDR_HOME_H, NULL },
126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 25, IDR_HOME_P, NULL },
127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 26, IDR_RELOAD, NULL },
128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 27, IDR_RELOAD_H, NULL },
129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 28, IDR_RELOAD_P, NULL },
130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 29, IDR_STOP, NULL },
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 30, IDR_STOP_D, NULL },
132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 31, IDR_STOP_H, NULL },
133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 32, IDR_STOP_P, NULL },
134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 33, IDR_LOCATIONBG_C, NULL },
135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 34, IDR_LOCATIONBG_L, NULL },
136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 35, IDR_LOCATIONBG_R, NULL },
137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 36, IDR_BROWSER_ACTIONS_OVERFLOW, NULL },
138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 37, IDR_BROWSER_ACTIONS_OVERFLOW_H, NULL },
139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 38, IDR_BROWSER_ACTIONS_OVERFLOW_P, NULL },
140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 39, IDR_TOOLS, NULL },
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 40, IDR_TOOLS_H, NULL },
142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 41, IDR_TOOLS_P, NULL },
143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 42, IDR_MENU_DROPARROW, NULL },
144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 43, IDR_THROBBER, NULL },
145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 44, IDR_THROBBER_WAITING, NULL },
146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { 45, IDR_THROBBER_LIGHT, NULL },
147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
148bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
149bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenint GetPersistentIDByName(const std::string& key) {
150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (size_t i = 0; i < arraysize(kPersistingImages); ++i) {
151bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (kPersistingImages[i].key != NULL &&
152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        base::strcasecmp(key.c_str(), kPersistingImages[i].key) == 0) {
153bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return kPersistingImages[i].persistent_id;
154bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
155bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
156bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
157bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return -1;
158bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
159bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenint GetPersistentIDByIDR(int idr) {
161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (size_t i = 0; i < arraysize(kPersistingImages); ++i) {
162bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (kPersistingImages[i].idr_id == idr) {
163bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return kPersistingImages[i].persistent_id;
164bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
165bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
166bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
167bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return -1;
168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
169bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
170bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstruct StringToIntTable {
171bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  const char* key;
172bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int id;
173bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
174bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
175bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Strings used by themes to identify tints in the JSON.
176bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenStringToIntTable kTintTable[] = {
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "buttons", ThemeService::TINT_BUTTONS },
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "frame", ThemeService::TINT_FRAME },
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "frame_inactive", ThemeService::TINT_FRAME_INACTIVE },
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "frame_incognito", ThemeService::TINT_FRAME_INCOGNITO },
181bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { "frame_incognito_inactive",
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ThemeService::TINT_FRAME_INCOGNITO_INACTIVE },
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "background_tab", ThemeService::TINT_BACKGROUND_TAB },
184bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { NULL, 0 }
185bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
186bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
187bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Strings used by themes to identify colors in the JSON.
188bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenStringToIntTable kColorTable[] = {
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "frame", ThemeService::COLOR_FRAME },
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "frame_inactive", ThemeService::COLOR_FRAME_INACTIVE },
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "frame_incognito", ThemeService::COLOR_FRAME_INCOGNITO },
192bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { "frame_incognito_inactive",
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE },
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "toolbar", ThemeService::COLOR_TOOLBAR },
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "tab_text", ThemeService::COLOR_TAB_TEXT },
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "tab_background_text", ThemeService::COLOR_BACKGROUND_TAB_TEXT },
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "bookmark_text", ThemeService::COLOR_BOOKMARK_TEXT },
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_background", ThemeService::COLOR_NTP_BACKGROUND },
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_text", ThemeService::COLOR_NTP_TEXT },
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_link", ThemeService::COLOR_NTP_LINK },
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_link_underline", ThemeService::COLOR_NTP_LINK_UNDERLINE },
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_header", ThemeService::COLOR_NTP_HEADER },
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_section", ThemeService::COLOR_NTP_SECTION },
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_section_text", ThemeService::COLOR_NTP_SECTION_TEXT },
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_section_link", ThemeService::COLOR_NTP_SECTION_LINK },
206bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { "ntp_section_link_underline",
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE },
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "control_background", ThemeService::COLOR_CONTROL_BACKGROUND },
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "button_background", ThemeService::COLOR_BUTTON_BACKGROUND },
210bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { NULL, 0 }
211bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
212bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
213bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Strings used by themes to identify display properties keys in JSON.
214bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenStringToIntTable kDisplayProperties[] = {
215bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { "ntp_background_alignment",
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ThemeService::NTP_BACKGROUND_ALIGNMENT },
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_background_repeat", ThemeService::NTP_BACKGROUND_TILING },
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "ntp_logo_alternate", ThemeService::NTP_LOGO_ALTERNATE },
219bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { NULL, 0 }
220bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
221bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
222bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Strings used by the tiling values in JSON.
223bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenStringToIntTable kTilingStrings[] = {
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "no-repeat", ThemeService::NO_REPEAT },
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "repeat-x", ThemeService::REPEAT_X },
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "repeat-y", ThemeService::REPEAT_Y },
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "repeat", ThemeService::REPEAT },
228bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { NULL, 0 }
229bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
230bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
231bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenint GetIntForString(const std::string& key, StringToIntTable* table) {
232bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (int i = 0; table[i].key != NULL; ++i) {
233bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (base::strcasecmp(key.c_str(), table[i].key) == 0) {
234bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return table[i].id;
235bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
236bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
237bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
238bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return -1;
239bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
240bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
241bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstruct IntToIntTable {
242bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int key;
243bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int value;
244bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
245bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
246bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Mapping used in GenerateFrameImages() to associate frame images with the
247bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// tint ID that should maybe be applied to it.
248bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenIntToIntTable kFrameTintMap[] = {
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { PRS_THEME_FRAME, ThemeService::TINT_FRAME },
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { PRS_THEME_FRAME_INACTIVE, ThemeService::TINT_FRAME_INACTIVE },
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { PRS_THEME_FRAME_OVERLAY, ThemeService::TINT_FRAME },
252bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME_OVERLAY_INACTIVE,
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ThemeService::TINT_FRAME_INACTIVE },
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { PRS_THEME_FRAME_INCOGNITO, ThemeService::TINT_FRAME_INCOGNITO },
255bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_FRAME_INCOGNITO_INACTIVE,
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ThemeService::TINT_FRAME_INCOGNITO_INACTIVE }
257bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
258bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
259bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Mapping used in GenerateTabBackgroundImages() to associate what frame image
260bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// goes with which tab background.
261bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenIntToIntTable kTabBackgroundMap[] = {
262bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_TAB_BACKGROUND, PRS_THEME_FRAME },
263bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  { PRS_THEME_TAB_BACKGROUND_INCOGNITO, PRS_THEME_FRAME_INCOGNITO }
264bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
265bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
266bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// A list of images that don't need tinting or any other modification and can
267bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// be byte-copied directly into the finished DataPack. This should contain the
268bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// persistent IDs for all themeable image IDs that aren't in kFrameTintMap or
269bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// kTabBackgroundMap.
270bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kPreloadIDs[] = {
271bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PRS_THEME_TOOLBAR,
272bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PRS_THEME_NTP_BACKGROUND,
273bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PRS_THEME_BUTTON_BACKGROUND,
274bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PRS_THEME_NTP_ATTRIBUTION,
275bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  PRS_THEME_WINDOW_CONTROL_BACKGROUND
276bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
277bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
278bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Returns a piece of memory with the contents of the file |path|.
279bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenRefCountedMemory* ReadFileData(const FilePath& path) {
280bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!path.empty()) {
281bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    net::FileStream file;
282bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
283bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (file.Open(path, flags) == net::OK) {
284bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      int64 avail = file.Available();
285bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (avail > 0 && avail < INT_MAX) {
286bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        size_t size = static_cast<size_t>(avail);
287bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        std::vector<unsigned char> raw_data;
288bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        raw_data.resize(size);
289bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        char* data = reinterpret_cast<char*>(&(raw_data.front()));
290bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        if (file.ReadUntilComplete(data, size) == avail)
291bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          return RefCountedBytes::TakeVector(&raw_data);
292bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
293bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
294bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
295bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
296bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return NULL;
297bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
298bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
299bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Does error checking for invalid incoming data while trying to read an
300bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// floating point value.
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ValidDoubleValue(ListValue* tint_list, int index, double* out) {
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (tint_list->GetDouble(index, out))
303bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
304bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
305bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int value = 0;
306bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (tint_list->GetInteger(index, &value)) {
307bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    *out = value;
308bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
309bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
310bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
311bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return false;
312bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
313bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
314bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace
315bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
316bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBrowserThemePack::~BrowserThemePack() {
317bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!data_pack_.get()) {
318bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    delete header_;
319bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    delete [] tints_;
320bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    delete [] colors_;
321bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    delete [] display_properties_;
322bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    delete [] source_images_;
323bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
324bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
325bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  STLDeleteValues(&prepared_images_);
326bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  STLDeleteValues(&loaded_images_);
327bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
328bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
329bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static
330513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBrowserThemePack* BrowserThemePack::BuildFromExtension(
331513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const Extension* extension) {
332731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
333bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DCHECK(extension);
334bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DCHECK(extension->is_theme());
335bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
336bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  BrowserThemePack* pack = new BrowserThemePack;
337bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->BuildHeader(extension);
338bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->BuildTintsFromJSON(extension->GetThemeTints());
339bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->BuildColorsFromJSON(extension->GetThemeColors());
340bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->BuildDisplayPropertiesFromJSON(extension->GetThemeDisplayProperties());
341bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
342bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Builds the images. (Image building is dependent on tints).
343bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  FilePathMap file_paths;
344bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->ParseImageNamesFromJSON(extension->GetThemeImages(),
345bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                extension->path(),
346bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                &file_paths);
347bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->BuildSourceImagesArray(file_paths);
348bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
349bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!pack->LoadRawBitmapsTo(file_paths, &pack->prepared_images_))
350bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
351bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
352bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->GenerateFrameImages(&pack->prepared_images_);
353bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
354bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if !defined(OS_MACOSX)
355bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // OSX uses its own special buttons that are PDFs that do odd sorts of vector
356bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // graphics tricks. Other platforms use bitmaps and we must pre-tint them.
357bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->GenerateTintedButtons(
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pack->GetTintInternal(ThemeService::TINT_BUTTONS),
359bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      &pack->prepared_images_);
360bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
361bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
362bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->GenerateTabBackgroundImages(&pack->prepared_images_);
363bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
364bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // The BrowserThemePack is now in a consistent state.
365bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return pack;
366bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
367bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
368bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static
369bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenscoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromDataPack(
370bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    FilePath path, const std::string& expected_id) {
371731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
372513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<BrowserThemePack> pack(new BrowserThemePack);
37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  pack->data_pack_.reset(new ui::DataPack);
374bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
375bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!pack->data_pack_->Load(path)) {
376bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    LOG(ERROR) << "Failed to load theme data pack.";
377bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
378bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
379bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
380bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  base::StringPiece pointer;
381bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!pack->data_pack_->GetStringPiece(kHeaderID, &pointer))
382bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
383bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->header_ = reinterpret_cast<BrowserThemePackHeader*>(const_cast<char*>(
384bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      pointer.data()));
385bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
386bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (pack->header_->version != kThemePackVersion) {
387bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    DLOG(ERROR) << "BuildFromDataPack failure! Version mismatch!";
388bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
389bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
390bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // TODO(erg): Check endianess once DataPack works on the other endian.
391bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::string theme_id(reinterpret_cast<char*>(pack->header_->theme_id),
392bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                       Extension::kIdSize);
393bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::string truncated_id = expected_id.substr(0, Extension::kIdSize);
394bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (theme_id != truncated_id) {
395bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    DLOG(ERROR) << "Wrong id: " << theme_id << " vs " << expected_id;
396bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
397bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
398bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
399bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!pack->data_pack_->GetStringPiece(kTintsID, &pointer))
400bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
401bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->tints_ = reinterpret_cast<TintEntry*>(const_cast<char*>(
402bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      pointer.data()));
403bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
404bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!pack->data_pack_->GetStringPiece(kColorsID, &pointer))
405bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
406bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->colors_ =
407bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      reinterpret_cast<ColorPair*>(const_cast<char*>(pointer.data()));
408bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
409bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!pack->data_pack_->GetStringPiece(kDisplayPropertiesID, &pointer))
410bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
411bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->display_properties_ = reinterpret_cast<DisplayPropertyPair*>(
412bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      const_cast<char*>(pointer.data()));
413bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
414bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!pack->data_pack_->GetStringPiece(kSourceImagesID, &pointer))
415bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
416bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  pack->source_images_ = reinterpret_cast<int*>(
417bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      const_cast<char*>(pointer.data()));
418bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
419bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return pack;
420bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
421bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
422bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BrowserThemePack::WriteToDisk(FilePath path) const {
423731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
424bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Add resources for each of the property arrays.
425bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  RawDataForWriting resources;
426bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  resources[kHeaderID] = base::StringPiece(
427bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      reinterpret_cast<const char*>(header_), sizeof(BrowserThemePackHeader));
428bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  resources[kTintsID] = base::StringPiece(
429bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      reinterpret_cast<const char*>(tints_), sizeof(TintEntry[kTintArraySize]));
430bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  resources[kColorsID] = base::StringPiece(
431bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      reinterpret_cast<const char*>(colors_),
432bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      sizeof(ColorPair[kColorArraySize]));
433bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  resources[kDisplayPropertiesID] = base::StringPiece(
434bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      reinterpret_cast<const char*>(display_properties_),
435bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      sizeof(DisplayPropertyPair[kDisplayPropertySize]));
436bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
437bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int source_count = 1;
438bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int* end = source_images_;
439bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (; *end != -1 ; end++)
440bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    source_count++;
441bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  resources[kSourceImagesID] = base::StringPiece(
442bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      reinterpret_cast<const char*>(source_images_),
443bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      source_count * sizeof(*source_images_));
444bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
445bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  AddRawImagesTo(image_memory_, &resources);
446bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
447bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  RawImages reencoded_images;
448bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  RepackImages(prepared_images_, &reencoded_images);
449bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  AddRawImagesTo(reencoded_images, &resources);
450bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::DataPack::WritePack(path, resources);
452bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
453bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
454bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BrowserThemePack::GetTint(int id, color_utils::HSL* hsl) const {
455bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (tints_) {
456bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    for (int i = 0; i < kTintArraySize; ++i) {
457bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (tints_[i].id == id) {
458bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        hsl->h = tints_[i].h;
459bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        hsl->s = tints_[i].s;
460bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        hsl->l = tints_[i].l;
461bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        return true;
462bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
463bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
464bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
465bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
466bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return false;
467bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
468bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
469bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BrowserThemePack::GetColor(int id, SkColor* color) const {
470bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (colors_) {
471bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    for (int i = 0; i < kColorArraySize; ++i) {
472bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (colors_[i].id == id) {
473bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        *color = colors_[i].color;
474bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        return true;
475bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
476bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
477bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
478bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
479bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return false;
480bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
481bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
482bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BrowserThemePack::GetDisplayProperty(int id, int* result) const {
483bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (display_properties_) {
484bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    for (int i = 0; i < kDisplayPropertySize; ++i) {
485bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (display_properties_[i].id == id) {
486bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        *result = display_properties_[i].property;
487bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        return true;
488bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
489bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
490bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
491bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
492bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return false;
493bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
494bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
495bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenSkBitmap* BrowserThemePack::GetBitmapNamed(int idr_id) const {
496bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int prs_id = GetPersistentIDByIDR(idr_id);
497bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (prs_id == -1)
498bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return NULL;
499bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
500bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Check our cache of prepared images, first.
501bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ImageCache::const_iterator image_iter = prepared_images_.find(prs_id);
502bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (image_iter != prepared_images_.end())
503bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return image_iter->second;
504bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
505bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Check if we've already loaded this image.
506bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  image_iter = loaded_images_.find(prs_id);
507bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (image_iter != loaded_images_.end())
508bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return image_iter->second;
509bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
510bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  scoped_refptr<RefCountedMemory> memory;
511bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (data_pack_.get()) {
512bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    memory = data_pack_->GetStaticMemory(prs_id);
513bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  } else {
514bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    RawImages::const_iterator it = image_memory_.find(prs_id);
515bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (it != image_memory_.end()) {
516bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      memory = it->second;
517bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
518bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
519bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
520bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (memory.get()) {
521bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // Decode the PNG.
522bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    SkBitmap bitmap;
523bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (!gfx::PNGCodec::Decode(memory->front(), memory->size(),
524bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                               &bitmap)) {
525bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NOTREACHED() << "Unable to decode theme image resource " << idr_id
526bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                   << " from saved DataPack.";
527bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return NULL;
528bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
529bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
530bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    SkBitmap* ret = new SkBitmap(bitmap);
531bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    loaded_images_[prs_id] = ret;
532bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
533bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return ret;
534bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
535bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
536bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return NULL;
537bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
538bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
539bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenRefCountedMemory* BrowserThemePack::GetRawData(int idr_id) const {
540bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  RefCountedMemory* memory = NULL;
541bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int prs_id = GetPersistentIDByIDR(idr_id);
542bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
543bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (prs_id != -1) {
544bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (data_pack_.get()) {
545bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      memory = data_pack_->GetStaticMemory(prs_id);
546bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
547bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      RawImages::const_iterator it = image_memory_.find(prs_id);
548bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (it != image_memory_.end()) {
549bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        memory = it->second;
550bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
551bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
552bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
553bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
554bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return memory;
555bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
556bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
557bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BrowserThemePack::HasCustomImage(int idr_id) const {
558bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int prs_id = GetPersistentIDByIDR(idr_id);
559bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (prs_id == -1)
560bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
561bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
562bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int* img = source_images_;
563bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (; *img != -1; ++img) {
564bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (*img == prs_id)
565bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return true;
566bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
567bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
568bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return false;
569bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
570bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
571bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// private:
572bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
573bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBrowserThemePack::BrowserThemePack()
574bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    : header_(NULL),
575bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      tints_(NULL),
576bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      colors_(NULL),
577bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      display_properties_(NULL),
578bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      source_images_(NULL) {
579bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
580bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
581513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserThemePack::BuildHeader(const Extension* extension) {
582bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  header_ = new BrowserThemePackHeader;
583bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  header_->version = kThemePackVersion;
584bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
585bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // TODO(erg): Need to make this endian safe on other computers. Prerequisite
58672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // is that ui::DataPack removes this same check.
587bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(__BYTE_ORDER)
588bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Linux check
589bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN,
590bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                 datapack_assumes_little_endian);
591bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#elif defined(__BIG_ENDIAN__)
592bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Mac check
593bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  #error DataPack assumes little endian
594bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
595bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  header_->little_endian = 1;
596bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
597bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  const std::string& id = extension->id();
598bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  memcpy(header_->theme_id, id.c_str(), Extension::kIdSize);
599bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
600bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
601bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::BuildTintsFromJSON(DictionaryValue* tints_value) {
602bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  tints_ = new TintEntry[kTintArraySize];
603bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (int i = 0; i < kTintArraySize; ++i) {
604bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[i].id = -1;
605bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[i].h = -1;
606bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[i].s = -1;
607bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[i].l = -1;
608bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
609bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
610bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!tints_value)
611bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return;
612bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
613bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Parse the incoming data from |tints_value| into an intermediary structure.
614bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::map<int, color_utils::HSL> temp_tints;
615bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (DictionaryValue::key_iterator iter(tints_value->begin_keys());
616bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       iter != tints_value->end_keys(); ++iter) {
617bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ListValue* tint_list;
618bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (tints_value->GetList(*iter, &tint_list) &&
619bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        (tint_list->GetSize() == 3)) {
620bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      color_utils::HSL hsl = { -1, -1, -1 };
621bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
62272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (ValidDoubleValue(tint_list, 0, &hsl.h) &&
62372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          ValidDoubleValue(tint_list, 1, &hsl.s) &&
62472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          ValidDoubleValue(tint_list, 2, &hsl.l)) {
625bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        int id = GetIntForString(*iter, kTintTable);
626bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        if (id != -1) {
627bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          temp_tints[id] = hsl;
628bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        }
629bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
630bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
631bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
632bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
633bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Copy data from the intermediary data structure to the array.
634bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int count = 0;
635bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (std::map<int, color_utils::HSL>::const_iterator it =
636bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen           temp_tints.begin(); it != temp_tints.end() && count < kTintArraySize;
637bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       ++it, ++count) {
638bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[count].id = it->first;
639bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[count].h = it->second.h;
640bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[count].s = it->second.s;
641bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    tints_[count].l = it->second.l;
642bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
643bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
644bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
645bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::BuildColorsFromJSON(DictionaryValue* colors_value) {
646bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  colors_ = new ColorPair[kColorArraySize];
647bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (int i = 0; i < kColorArraySize; ++i) {
648bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    colors_[i].id = -1;
649bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    colors_[i].color = SkColorSetRGB(0, 0, 0);
650bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
651bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
652bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::map<int, SkColor> temp_colors;
653bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (colors_value)
654bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ReadColorsFromJSON(colors_value, &temp_colors);
655bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  GenerateMissingColors(&temp_colors);
656bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
657bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Copy data from the intermediary data structure to the array.
658bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int count = 0;
659bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (std::map<int, SkColor>::const_iterator it = temp_colors.begin();
660bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       it != temp_colors.end() && count < kColorArraySize; ++it, ++count) {
661bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    colors_[count].id = it->first;
662bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    colors_[count].color = it->second;
663bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
664bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
665bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
666bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::ReadColorsFromJSON(
667bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    DictionaryValue* colors_value,
668bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    std::map<int, SkColor>* temp_colors) {
669bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Parse the incoming data from |colors_value| into an intermediary structure.
670bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (DictionaryValue::key_iterator iter(colors_value->begin_keys());
671bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       iter != colors_value->end_keys(); ++iter) {
672bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ListValue* color_list;
673bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (colors_value->GetList(*iter, &color_list) &&
674bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        ((color_list->GetSize() == 3) || (color_list->GetSize() == 4))) {
675bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      SkColor color = SK_ColorWHITE;
676bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      int r, g, b;
677bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (color_list->GetInteger(0, &r) &&
678bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          color_list->GetInteger(1, &g) &&
679bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          color_list->GetInteger(2, &b)) {
680bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        if (color_list->GetSize() == 4) {
681bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          double alpha;
682bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          int alpha_int;
68372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          if (color_list->GetDouble(3, &alpha)) {
684bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen            color = SkColorSetARGB(static_cast<int>(alpha * 255), r, g, b);
685bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          } else if (color_list->GetInteger(3, &alpha_int) &&
686bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                     (alpha_int == 0 || alpha_int == 1)) {
687bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen            color = SkColorSetARGB(alpha_int ? 255 : 0, r, g, b);
688bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          } else {
689bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen            // Invalid entry for part 4.
690bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen            continue;
691bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          }
692bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        } else {
693bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          color = SkColorSetRGB(r, g, b);
694bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        }
695bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
696bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        int id = GetIntForString(*iter, kColorTable);
697bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        if (id != -1) {
698bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          (*temp_colors)[id] = color;
699bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        }
700bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
701bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
702bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
703bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
704bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
705bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::GenerateMissingColors(
706bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    std::map<int, SkColor>* colors) {
707bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Generate link colors, if missing. (See GetColor()).
708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!colors->count(ThemeService::COLOR_NTP_HEADER) &&
709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      colors->count(ThemeService::COLOR_NTP_SECTION)) {
710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*colors)[ThemeService::COLOR_NTP_HEADER] =
711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        (*colors)[ThemeService::COLOR_NTP_SECTION];
712bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
713bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!colors->count(ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE) &&
715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      colors->count(ThemeService::COLOR_NTP_SECTION_LINK)) {
716bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    SkColor color_section_link =
717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        (*colors)[ThemeService::COLOR_NTP_SECTION_LINK];
718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*colors)[ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE] =
719bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        SkColorSetA(color_section_link, SkColorGetA(color_section_link) / 3);
720bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
721bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!colors->count(ThemeService::COLOR_NTP_LINK_UNDERLINE) &&
723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      colors->count(ThemeService::COLOR_NTP_LINK)) {
724ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SkColor color_link = (*colors)[ThemeService::COLOR_NTP_LINK];
725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*colors)[ThemeService::COLOR_NTP_LINK_UNDERLINE] =
726bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        SkColorSetA(color_link, SkColorGetA(color_link) / 3);
727bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
728bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
729bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Generate frame colors, if missing. (See GenerateFrameColors()).
730bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  SkColor frame;
731bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::map<int, SkColor>::const_iterator it =
732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      colors->find(ThemeService::COLOR_FRAME);
733bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (it != colors->end()) {
734bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    frame = it->second;
735bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  } else {
736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    frame = ThemeService::GetDefaultColor(
737ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ThemeService::COLOR_FRAME);
738bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
739bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!colors->count(ThemeService::COLOR_FRAME)) {
741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*colors)[ThemeService::COLOR_FRAME] =
742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        HSLShift(frame, GetTintInternal(ThemeService::TINT_FRAME));
743bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!colors->count(ThemeService::COLOR_FRAME_INACTIVE)) {
745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*colors)[ThemeService::COLOR_FRAME_INACTIVE] =
746bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        HSLShift(frame, GetTintInternal(
747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            ThemeService::TINT_FRAME_INACTIVE));
748bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!colors->count(ThemeService::COLOR_FRAME_INCOGNITO)) {
750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*colors)[ThemeService::COLOR_FRAME_INCOGNITO] =
751bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        HSLShift(frame, GetTintInternal(
752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            ThemeService::TINT_FRAME_INCOGNITO));
753bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!colors->count(ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE)) {
755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*colors)[ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE] =
756bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        HSLShift(frame, GetTintInternal(
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            ThemeService::TINT_FRAME_INCOGNITO_INACTIVE));
758bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
759bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
760bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
761bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::BuildDisplayPropertiesFromJSON(
762bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    DictionaryValue* display_properties_value) {
763bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  display_properties_ = new DisplayPropertyPair[kDisplayPropertySize];
764bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (int i = 0; i < kDisplayPropertySize; ++i) {
765bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    display_properties_[i].id = -1;
766bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    display_properties_[i].property = 0;
767bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
768bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
769bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!display_properties_value)
770bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return;
771bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
772bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::map<int, int> temp_properties;
773bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (DictionaryValue::key_iterator iter(
774bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       display_properties_value->begin_keys());
775bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       iter != display_properties_value->end_keys(); ++iter) {
776bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    int property_id = GetIntForString(*iter, kDisplayProperties);
777bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    switch (property_id) {
778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case ThemeService::NTP_BACKGROUND_ALIGNMENT: {
779bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        std::string val;
780bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        if (display_properties_value->GetString(*iter, &val)) {
781ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          temp_properties[ThemeService::NTP_BACKGROUND_ALIGNMENT] =
782ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              ThemeService::StringToAlignment(val);
783bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        }
784bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        break;
785bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case ThemeService::NTP_BACKGROUND_TILING: {
787bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        std::string val;
788bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        if (display_properties_value->GetString(*iter, &val)) {
789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          temp_properties[ThemeService::NTP_BACKGROUND_TILING] =
790bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen              GetIntForString(val, kTilingStrings);
791bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        }
792bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        break;
793bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case ThemeService::NTP_LOGO_ALTERNATE: {
795bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        int val = 0;
796bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        if (display_properties_value->GetInteger(*iter, &val))
797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          temp_properties[ThemeService::NTP_LOGO_ALTERNATE] = val;
798bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        break;
799bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
800bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
801bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
802bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
803bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Copy data from the intermediary data structure to the array.
804bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  int count = 0;
805bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (std::map<int, int>::const_iterator it = temp_properties.begin();
806bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       it != temp_properties.end() && count < kDisplayPropertySize;
807bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       ++it, ++count) {
808bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    display_properties_[count].id = it->first;
809bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    display_properties_[count].property = it->second;
810bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
811bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
812bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
813bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::ParseImageNamesFromJSON(
814bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    DictionaryValue* images_value,
815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const FilePath& images_path,
816bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    FilePathMap* file_paths) const {
817bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!images_value)
818bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return;
819bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
820bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (DictionaryValue::key_iterator iter(images_value->begin_keys());
821bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       iter != images_value->end_keys(); ++iter) {
822bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    std::string val;
823bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (images_value->GetString(*iter, &val)) {
824bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      int id = GetPersistentIDByName(*iter);
825bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (id != -1)
826bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        (*file_paths)[id] = images_path.AppendASCII(val);
827bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
828bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
829bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
830bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
831bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::BuildSourceImagesArray(const FilePathMap& file_paths) {
832bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::vector<int> ids;
833bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (FilePathMap::const_iterator it = file_paths.begin();
834bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       it != file_paths.end(); ++it) {
835bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ids.push_back(it->first);
836bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
837bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
838bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  source_images_ = new int[ids.size() + 1];
839bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::copy(ids.begin(), ids.end(), source_images_);
840bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  source_images_[ids.size()] = -1;
841bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
842bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
843bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BrowserThemePack::LoadRawBitmapsTo(
844bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const FilePathMap& file_paths,
845bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ImageCache* raw_bitmaps) {
846513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Themes should be loaded on the file thread, not the UI thread.
847513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // http://crbug.com/61838
848513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  base::ThreadRestrictions::ScopedAllowIO allow_io;
849513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
850bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (FilePathMap::const_iterator it = file_paths.begin();
851bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       it != file_paths.end(); ++it) {
852bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    scoped_refptr<RefCountedMemory> raw_data(ReadFileData(it->second));
853bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (!raw_data.get()) {
854bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      LOG(ERROR) << "Could not load theme image";
855bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return false;
856bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
857bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
858bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    int id = it->first;
859bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
860bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // Some images need to go directly into |image_memory_|. No modification is
861bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // necessary or desirable.
862bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    bool is_copyable = false;
863bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    for (size_t i = 0; i < arraysize(kPreloadIDs); ++i) {
864bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (kPreloadIDs[i] == id) {
865bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        is_copyable = true;
866bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        break;
867bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
868bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
869bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
870bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (is_copyable) {
871bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      image_memory_[id] = raw_data;
872bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else if (raw_data.get() && raw_data->size()) {
873bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // Decode the PNG.
874bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      SkBitmap bitmap;
875bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(),
876bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                &bitmap)) {
877bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        (*raw_bitmaps)[it->first] = new SkBitmap(bitmap);
878bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      } else {
879bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        NOTREACHED() << "Unable to decode theme image resource " << it->first;
880bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
881bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
882bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
883bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
884bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
885bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
886bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
887bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::GenerateFrameImages(ImageCache* bitmaps) const {
888bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
889bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
890bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Create all the output bitmaps in a separate cache and move them back into
891bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // the input bitmaps because there can be name collisions.
892bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ImageCache temp_output;
893bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
894bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (size_t i = 0; i < arraysize(kFrameTintMap); ++i) {
895bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    int prs_id = kFrameTintMap[i].key;
896bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    scoped_ptr<SkBitmap> frame;
897bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // If there's no frame image provided for the specified id, then load
898bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // the default provided frame. If that's not provided, skip this whole
899bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // thing and just use the default images.
900bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    int prs_base_id;
901bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
902bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (prs_id == PRS_THEME_FRAME_INCOGNITO_INACTIVE) {
903bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      prs_base_id = bitmaps->count(PRS_THEME_FRAME_INCOGNITO) ?
904bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                    PRS_THEME_FRAME_INCOGNITO : PRS_THEME_FRAME;
905bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else if (prs_id == PRS_THEME_FRAME_OVERLAY_INACTIVE) {
906bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      prs_base_id = PRS_THEME_FRAME_OVERLAY;
907bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else if (prs_id == PRS_THEME_FRAME_INACTIVE) {
908bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      prs_base_id = PRS_THEME_FRAME;
909bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else if (prs_id == PRS_THEME_FRAME_INCOGNITO &&
910bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen               !bitmaps->count(PRS_THEME_FRAME_INCOGNITO)) {
911bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      prs_base_id = PRS_THEME_FRAME;
912bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
913bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      prs_base_id = prs_id;
914bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
915bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
916bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (bitmaps->count(prs_id)) {
917bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      frame.reset(new SkBitmap(*(*bitmaps)[prs_id]));
918bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else if (prs_base_id != prs_id && bitmaps->count(prs_base_id)) {
919bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      frame.reset(new SkBitmap(*(*bitmaps)[prs_base_id]));
920bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else if (prs_base_id == PRS_THEME_FRAME_OVERLAY &&
921bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen               bitmaps->count(PRS_THEME_FRAME)) {
922bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // If there is no theme overlay, don't tint the default frame,
923bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // because it will overwrite the custom frame image when we cache and
924bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // reload from disk.
925bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      frame.reset(NULL);
926bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
927bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // If the theme doesn't specify an image, then apply the tint to
928bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // the default frame.
929bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      frame.reset(new SkBitmap(*rb.GetBitmapNamed(IDR_THEME_FRAME)));
930bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
931bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
932bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (frame.get()) {
933bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      temp_output[prs_id] = new SkBitmap(
934bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          SkBitmapOperations::CreateHSLShiftedBitmap(
935bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen              *frame, GetTintInternal(kFrameTintMap[i].value)));
936bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
937bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
938bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
939bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  MergeImageCaches(temp_output, bitmaps);
940bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
941bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
942bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::GenerateTintedButtons(
943513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const color_utils::HSL& button_tint,
944bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ImageCache* processed_bitmaps) const {
945bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (button_tint.h != -1 || button_tint.s != -1 || button_tint.l != -1) {
946bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
947bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const std::set<int>& idr_ids =
948ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ThemeService::GetTintableToolbarButtons();
949bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    for (std::set<int>::const_iterator it = idr_ids.begin();
950bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen         it != idr_ids.end(); ++it) {
951bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      int prs_id = GetPersistentIDByIDR(*it);
952bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      DCHECK(prs_id > 0);
953bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
954bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // Fetch the image by IDR...
955bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      scoped_ptr<SkBitmap> button(new SkBitmap(*rb.GetBitmapNamed(*it)));
956bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
957bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // but save a version with the persistent ID.
958bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      (*processed_bitmaps)[prs_id] = new SkBitmap(
959bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          SkBitmapOperations::CreateHSLShiftedBitmap(*button, button_tint));
960bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
961bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
962bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
963bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
964bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::GenerateTabBackgroundImages(ImageCache* bitmaps) const {
965bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ImageCache temp_output;
966bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (size_t i = 0; i < arraysize(kTabBackgroundMap); ++i) {
967bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    int prs_id = kTabBackgroundMap[i].key;
968bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    int prs_base_id = kTabBackgroundMap[i].value;
969bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
970bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // We only need to generate the background tab images if we were provided
971bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // with a PRS_THEME_FRAME.
972bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ImageCache::const_iterator it = bitmaps->find(prs_base_id);
973bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (it != bitmaps->end()) {
974bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      SkBitmap bg_tint = SkBitmapOperations::CreateHSLShiftedBitmap(
975bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          *(it->second), GetTintInternal(
976ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              ThemeService::TINT_BACKGROUND_TAB));
977bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      int vertical_offset = bitmaps->count(prs_id)
978bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                            ? kRestoredTabVerticalOffset : 0;
979bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      SkBitmap* bg_tab = new SkBitmap(SkBitmapOperations::CreateTiledBitmap(
980bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          bg_tint, 0, vertical_offset, bg_tint.width(), bg_tint.height()));
981bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
982bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // If they've provided a custom image, overlay it.
983bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      ImageCache::const_iterator overlay_it = bitmaps->find(prs_id);
984bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (overlay_it != bitmaps->end()) {
985bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        SkBitmap* overlay = overlay_it->second;
986bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        SkCanvas canvas(*bg_tab);
987bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        for (int x = 0; x < bg_tab->width(); x += overlay->width())
988bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          canvas.drawBitmap(*overlay, static_cast<SkScalar>(x), 0, NULL);
989bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
990bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
991bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      temp_output[prs_id] = bg_tab;
992bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
993bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
994bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
995bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  MergeImageCaches(temp_output, bitmaps);
996bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
997bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
998bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::RepackImages(const ImageCache& images,
999bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                    RawImages* reencoded_images) const {
1000731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1001bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (ImageCache::const_iterator it = images.begin();
1002bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       it != images.end(); ++it) {
1003bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    std::vector<unsigned char> image_data;
1004bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (!gfx::PNGCodec::EncodeBGRASkBitmap(*(it->second), false, &image_data)) {
1005bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NOTREACHED() << "Image file for resource " << it->first
1006bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                   << " could not be encoded.";
1007bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
1008bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      (*reencoded_images)[it->first] = RefCountedBytes::TakeVector(&image_data);
1009bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
1010bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
1011bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
1012bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
1013bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::MergeImageCaches(
1014bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const ImageCache& source, ImageCache* destination) const {
1015bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
1016bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (ImageCache::const_iterator it = source.begin(); it != source.end();
1017bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       ++it) {
1018bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    ImageCache::const_iterator bitmap_it = destination->find(it->first);
1019bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (bitmap_it != destination->end())
1020bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      delete bitmap_it->second;
1021bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
1022bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    (*destination)[it->first] = it->second;
1023bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
1024bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
1025bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
1026bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BrowserThemePack::AddRawImagesTo(const RawImages& images,
1027bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                      RawDataForWriting* out) const {
1028731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1029bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (RawImages::const_iterator it = images.begin(); it != images.end();
1030bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen       ++it) {
1031bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    (*out)[it->first] = base::StringPiece(
1032bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        reinterpret_cast<const char*>(it->second->front()), it->second->size());
1033bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
1034bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
1035bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
1036bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsencolor_utils::HSL BrowserThemePack::GetTintInternal(int id) const {
1037bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (tints_) {
1038bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    for (int i = 0; i < kTintArraySize; ++i) {
1039bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (tints_[i].id == id) {
1040bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        color_utils::HSL hsl;
1041bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        hsl.h = tints_[i].h;
1042bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        hsl.s = tints_[i].s;
1043bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        hsl.l = tints_[i].l;
1044bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        return hsl;
1045bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
1046bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
1047bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
1048bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
1049ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ThemeService::GetDefaultTint(id);
1050bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
1051