15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <limits>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/big_endian.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted_memory.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "grit/app_locale_settings.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/layout.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/data_pack.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_base_paths.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_base_switches.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/jpeg_codec.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_source.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/safe_integer_conversions.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size_conversions.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
390c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#if defined(OS_ANDROID)
400c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#include "ui/base/resource/resource_bundle_android.h"
410c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#endif
420c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(OS_CHROMEOS)
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/platform_font_pango.h"
46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_WIN)
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/win/dpi_setup.h"
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/win/dpi.h"
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_MACOSX) && !defined(OS_IOS)
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/mac/mac_util.h"
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Font sizes relative to base font.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSmallFontSizeDelta = -1;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMediumFontSizeDelta = 3;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLargeFontSizeDelta = 8;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PNG-related constants.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned char kPngMagic[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kPngChunkMetadataSize = 12;  // length, type, crc32
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned char kPngScaleChunkType[4] = { 'c', 's', 'C', 'l' };
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned char kPngDataChunkType[4] = { 'I', 'D', 'A', 'T' };
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
720c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#if !defined(OS_MACOSX)
730c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdochconst char kPakFileSuffix[] = ".pak";
740c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#endif
750c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceBundle* g_shared_instance_ = NULL;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void InitDefaultFontList() {
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(OS_CHROMEOS)
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string font_family = base::UTF16ToUTF8(
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      rb.GetLocalizedString(IDS_UI_FONT_FAMILY_CROS));
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::FontList::SetDefaultFontDescription(font_family);
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(yukishiino): Remove SetDefaultFontDescription() once the migration to
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // the font list is done.  We will no longer need SetDefaultFontDescription()
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // after every client gets started using a FontList instead of a Font.
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::PlatformFontPango::SetDefaultFontDescription(font_family);
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#else
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Use a single default font as the default font list.
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::FontList::SetDefaultFontDescription(std::string());
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_ANDROID)
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns the scale factor closest to |scale| from the full list of factors.
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Note that it does NOT rely on the list of supported scale factors.
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Finding the closest match is inefficient and shouldn't be done frequently.
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ScaleFactor FindClosestScaleFactorUnsafe(float scale) {
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  float smallest_diff =  std::numeric_limits<float>::max();
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScaleFactor closest_match = SCALE_FACTOR_100P;
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int i = SCALE_FACTOR_100P; i < NUM_SCALE_FACTORS; ++i) {
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ScaleFactor scale_factor = static_cast<ScaleFactor>(i);
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    float diff = std::abs(GetScaleForScaleFactor(scale_factor) - scale);
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (diff < smallest_diff) {
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      closest_match = scale_factor;
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      smallest_diff = diff;
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return closest_match;
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  // OS_ANDROID
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An ImageSkiaSource that loads bitmaps for the requested scale factor from
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ResourceBundle on demand for a given |resource_id|. If the bitmap for the
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// requested scale factor does not exist, it will return the 1x bitmap scaled
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by the scale factor. This may lead to broken UI if the correct size of the
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scaled image is not exactly |scale_factor| * the size of the 1x resource.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When --highlight-missing-scaled-resources flag is specified, scaled 1x images
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are higlighted by blending them with red.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceBundleImageSource(ResourceBundle* rb, int resource_id)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : rb_(rb), resource_id_(resource_id) {}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ResourceBundleImageSource() {}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // gfx::ImageSkiaSource overrides:
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkBitmap image;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool fell_back_to_1x = false;
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScaleFactor scale_factor = GetSupportedScaleFactor(scale);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool found = rb_->LoadBitmap(resource_id_, &scale_factor,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 &image, &fell_back_to_1x);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return gfx::ImageSkiaRep();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If the resource is in the package with SCALE_FACTOR_NONE, it
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // can be used in any scale factor. The image is maked as "unscaled"
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // so that the ImageSkia do not automatically scale.
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (scale_factor == ui::SCALE_FACTOR_NONE)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return gfx::ImageSkiaRep(image, 0.0f);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fell_back_to_1x) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // GRIT fell back to the 100% image, so rescale it to the correct size.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image = skia::ImageOperations::Resize(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          image,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          skia::ImageOperations::RESIZE_LANCZOS3,
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          gfx::ToCeiledInt(image.width() * scale),
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          gfx::ToCeiledInt(image.height() * scale));
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    } else {
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scale = GetScaleForScaleFactor(scale_factor);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return gfx::ImageSkiaRep(image, scale);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceBundle* rb_;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int resource_id_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ResourceBundle::InitSharedInstanceWithLocale(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& pref_locale, Delegate* delegate) {
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  InitSharedInstance(delegate);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_shared_instance_->LoadCommonResources();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result = g_shared_instance_->LoadLocaleResources(pref_locale);
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitDefaultFontList();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ResourceBundle::InitSharedInstanceLocaleOnly(
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& pref_locale, Delegate* delegate) {
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  InitSharedInstance(delegate);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result = g_shared_instance_->LoadLocaleResources(pref_locale);
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitDefaultFontList();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1858d8c7bbf2600bb117d324f0708e6a6a9e0ec3ebaBen Murdochvoid ResourceBundle::InitSharedInstanceWithPakFileRegion(
1868d8c7bbf2600bb117d324f0708e6a6a9e0ec3ebaBen Murdoch    base::File pak_file,
1878d8c7bbf2600bb117d324f0708e6a6a9e0ec3ebaBen Murdoch    const base::MemoryMappedFile::Region& region,
1888d8c7bbf2600bb117d324f0708e6a6a9e0ec3ebaBen Murdoch    bool should_load_common_resources) {
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  InitSharedInstance(NULL);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_load_common_resources)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_shared_instance_->LoadCommonResources();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DataPack> data_pack(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DataPack(SCALE_FACTOR_100P));
1958d8c7bbf2600bb117d324f0708e6a6a9e0ec3ebaBen Murdoch  if (!data_pack->LoadFromFileRegion(pak_file.Pass(), region)) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "failed to load pak file";
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_shared_instance_->locale_resources_data_.reset(data_pack.release());
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitDefaultFontList();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceBundle::InitSharedInstanceWithPakPath(const base::FilePath& path) {
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  InitSharedInstance(NULL);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_shared_instance_->LoadTestResources(path, path);
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitDefaultFontList();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceBundle::CleanupSharedInstance() {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_shared_instance_) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete g_shared_instance_;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_shared_instance_ = NULL;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ResourceBundle::HasSharedInstance() {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_shared_instance_ != NULL;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceBundle& ResourceBundle::GetSharedInstance() {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must call InitSharedInstance before this function.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(g_shared_instance_ != NULL);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *g_shared_instance_;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
2320c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  bool locale_file_path_exists = !GetLocaleFilePath(locale, true).empty();
2330c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#if defined(OS_ANDROID)
2340c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  // TODO(mkosiba,primiano): Chrome should mmap the .pak files too, in which
2350c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  // case we'd not need to check if locale_file_path_exists here.
2360c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  // http://crbug.com/394502.
2370c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  return locale_file_path_exists ||
2380c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch      AssetContainedInApk(locale + kPakFileSuffix);
2390c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#else
2400c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  return locale_file_path_exists;
2410c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch#endif
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceBundle::AddDataPackFromPath(const base::FilePath& path,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         ScaleFactor scale_factor) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddDataPackFromPathInternal(path, scale_factor, false);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceBundle::AddOptionalDataPackFromPath(const base::FilePath& path,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         ScaleFactor scale_factor) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddDataPackFromPathInternal(path, scale_factor, true);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ResourceBundle::AddDataPackFromFile(base::File file,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         ScaleFactor scale_factor) {
256adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch  AddDataPackFromFileRegion(
257adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch      file.Pass(), base::MemoryMappedFile::Region::kWholeFile, scale_factor);
258adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch}
259adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch
260adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdochvoid ResourceBundle::AddDataPackFromFileRegion(
261adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch    base::File file,
262adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch    const base::MemoryMappedFile::Region& region,
263adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch    ScaleFactor scale_factor) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DataPack> data_pack(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DataPack(scale_factor));
266adf47cdafabb7eed9d3d806ce331c2b810a7acd1Ben Murdoch  if (data_pack->LoadFromFileRegion(file.Pass(), region)) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddDataPack(data_pack.release());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to load data pack from file."
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "\nSome features may not be available.";
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 bool test_file_exists) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (app_locale.empty())
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath locale_file_path;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(ui::DIR_LOCALES, &locale_file_path);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2840c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  if (!locale_file_path.empty()) {
2850c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch    locale_file_path =
2860c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch        locale_file_path.AppendASCII(app_locale + kPakFileSuffix);
2870c426db9e857768f27c4cb499a787b80ddc080f5Ben Murdoch  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    locale_file_path =
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->GetPathForLocalePack(locale_file_path, app_locale);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't try to load empty values or values that are not absolute paths.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (locale_file_path.empty() || !locale_file_path.IsAbsolute())
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (test_file_exists && !base::PathExists(locale_file_path))
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return locale_file_path;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ResourceBundle::LoadLocaleResources(
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& pref_locale) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded";
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath locale_file_path = GetOverriddenPakPath();
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (locale_file_path.empty())
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    locale_file_path = GetLocaleFilePath(app_locale, true);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (locale_file_path.empty()) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's possible that there is no locale.pak.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "locale_file_path.empty()";
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DataPack> data_pack(
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DataPack(SCALE_FACTOR_100P));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data_pack->LoadFromPath(locale_file_path)) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("ResourceBundle.LoadLocaleResourcesError",
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              logging::GetLastSystemErrorCode(), 16000);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "failed to load locale.pak";
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  locale_resources_data_.reset(data_pack.release());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_locale;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceBundle::LoadTestResources(const base::FilePath& path,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const base::FilePath& locale_path) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the given resource pak for both common and localized resources.
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!path.empty() && data_pack->LoadFromPath(path))
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddDataPack(data_pack.release());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_pack.reset(new DataPack(ui::SCALE_FACTOR_NONE));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!locale_path.empty() && data_pack->LoadFromPath(locale_path)) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    locale_resources_data_.reset(data_pack.release());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    locale_resources_data_.reset(new DataPack(ui::SCALE_FACTOR_NONE));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceBundle::UnloadLocaleResources() {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  locale_resources_data_.reset();
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceBundle::OverrideLocalePakForTest(const base::FilePath& pak_path) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overridden_pak_path_ = pak_path;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath& ResourceBundle::GetOverriddenPakPath() {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return overridden_pak_path_;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ResourceBundle::ReloadLocaleResources(
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& pref_locale) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock_scope(*locale_resources_data_lock_);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnloadLocaleResources();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LoadLocaleResources(pref_locale);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia* ResourceBundle::GetImageSkiaNamed(int resource_id) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkia* image = GetImageNamed(resource_id).ToImageSkia();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return const_cast<gfx::ImageSkia*>(image);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image& ResourceBundle::GetImageNamed(int resource_id) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if the image is already in the cache.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock_scope(*images_and_fonts_lock_);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (images_.count(resource_id))
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return images_[resource_id];
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image image;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image = delegate_->GetImageNamed(resource_id);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (image.IsEmpty()) {
3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK(!data_packs_.empty()) <<
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Missing call to SetResourcesDataDLL?";
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_CHROMEOS) || defined(OS_WIN)
389effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ui::ScaleFactor scale_factor_to_load = GetMaxScaleFactor();
39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#else
391effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P;
39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(oshima): Consider reading the image size from png IHDR chunk and
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // skip decoding here and remove #ifdef below.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ResourceBundle::GetSharedInstance() is destroyed after the
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // BrowserMainLoop has finished running. |image_skia| is guaranteed to be
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // destroyed before the resource bundle is destroyed.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::ImageSkia image_skia(new ResourceBundleImageSource(this, resource_id),
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              GetScaleForScaleFactor(scale_factor_to_load));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (image_skia.isNull()) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unable to load image with id " << resource_id;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();  // Want to assert in debug mode.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The load failed to retrieve the image; show a debugging red square.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetEmptyImage();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_skia.SetReadOnly();
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image = gfx::Image(image_skia);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The load was successful, so cache the image.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock_scope(*images_and_fonts_lock_);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Another thread raced the load and has already cached the image.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (images_.count(resource_id))
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return images_[resource_id];
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  images_[resource_id] = image;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return images_[resource_id];
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetNativeImageNamed(resource_id, RTL_DISABLED);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes(
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int resource_id) const {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LoadDataResourceBytesForScale(resource_id, ui::SCALE_FACTOR_NONE);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytesForScale(
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int resource_id,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScaleFactor scale_factor) const {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RefCountedStaticMemory* bytes = NULL;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes = delegate_->LoadDataResourceBytes(resource_id, scale_factor);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bytes) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece data =
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetRawDataResourceForScale(resource_id, scale_factor);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data.empty()) {
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bytes = new base::RefCountedStaticMemory(data.data(), data.length());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bytes;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::StringPiece ResourceBundle::GetRawDataResource(int resource_id) const {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetRawDataResourceForScale(resource_id, ui::SCALE_FACTOR_NONE);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::StringPiece ResourceBundle::GetRawDataResourceForScale(
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int resource_id,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScaleFactor scale_factor) const {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece data;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ &&
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->GetRawDataResource(resource_id, scale_factor, &data))
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scale_factor != ui::SCALE_FACTOR_100P) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < data_packs_.size(); i++) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (data_packs_[i]->GetScaleFactor() == scale_factor &&
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          data_packs_[i]->GetStringPiece(resource_id, &data))
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return data;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < data_packs_.size(); i++) {
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_100P ||
470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_200P ||
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_NONE) &&
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data_packs_[i]->GetStringPiece(resource_id, &data))
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return data;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPiece();
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 ResourceBundle::GetLocalizedString(int message_id) {
480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 string;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ && delegate_->GetLocalizedString(message_id, &string))
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return string;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that ReloadLocaleResources() doesn't drop the resources while
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we're using them.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock_scope(*locale_resources_data_lock_);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If for some reason we were unable to load the resources , return an empty
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string (better than crashing).
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!locale_resources_data_.get()) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "locale resources are not loaded";
492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece data;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!locale_resources_data_->GetStringPiece(message_id, &data)) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fall back on the main data pack (shouldn't be any strings here except in
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // unittests).
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data = GetRawDataResource(message_id);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data.empty()) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "unable to find resource: " << message_id;
502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return base::string16();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strings should not be loaded from a data pack that contains binary data.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceHandle::TextEncodingType encoding =
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      locale_resources_data_->GetTextEncodingType();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(encoding == ResourceHandle::UTF16 || encoding == ResourceHandle::UTF8)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "requested localized string from binary pack file";
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Data pack encodes strings as either UTF8 or UTF16.
513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 msg;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (encoding == ResourceHandle::UTF16) {
515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    msg = base::string16(reinterpret_cast<const base::char16*>(data.data()),
516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         data.length() / 2);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (encoding == ResourceHandle::UTF8) {
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    msg = base::UTF8ToUTF16(data);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return msg;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const gfx::FontList& ResourceBundle::GetFontList(FontStyle style) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock_scope(*images_and_fonts_lock_);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadFontsIfNecessary();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (style) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BoldFont:
530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *bold_font_list_;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SmallFont:
532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *small_font_list_;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MediumFont:
534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *medium_font_list_;
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SmallBoldFont:
536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *small_bold_font_list_;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MediumBoldFont:
538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *medium_bold_font_list_;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LargeFont:
540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *large_font_list_;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LargeBoldFont:
542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *large_bold_font_list_;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *base_font_list_;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
549a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return GetFontList(style).GetPrimaryFont();
550a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
551a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceBundle::ReloadFonts() {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock_scope(*images_and_fonts_lock_);
554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base_font_list_.reset();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadFontsIfNecessary();
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ScaleFactor ResourceBundle::GetMaxScaleFactor() const {
559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_CHROMEOS) || defined(OS_WIN)
56068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return max_scale_factor_;
56168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#else
56268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetSupportedScaleFactors().back();
56368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
56468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
56568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ResourceBundle::IsScaleFactorSupported(ScaleFactor scale_factor) {
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const std::vector<ScaleFactor>& supported_scale_factors =
568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ui::GetSupportedScaleFactors();
569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return std::find(supported_scale_factors.begin(),
570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   supported_scale_factors.end(),
571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   scale_factor) != supported_scale_factors.end();
572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceBundle::ResourceBundle(Delegate* delegate)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(delegate),
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      images_and_fonts_lock_(new base::Lock),
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      locale_resources_data_lock_(new base::Lock),
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_scale_factor_(SCALE_FACTOR_100P) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceBundle::~ResourceBundle() {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeImages();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnloadLocaleResources();
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// static
58768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ResourceBundle::InitSharedInstance(Delegate* delegate) {
58868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
58968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  g_shared_instance_ = new ResourceBundle(delegate);
59068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  static std::vector<ScaleFactor> supported_scale_factors;
591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(OS_IOS) && !defined(OS_WIN)
59268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // On platforms other than iOS, 100P is always a supported scale factor.
593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // For Windows we have a separate case in this function.
59468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  supported_scale_factors.push_back(SCALE_FACTOR_100P);
59568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
59668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_ANDROID)
59768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const gfx::Display display =
59868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
59968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const float display_density = display.device_scale_factor();
60068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const ScaleFactor closest = FindClosestScaleFactorUnsafe(display_density);
60168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (closest != SCALE_FACTOR_100P)
60268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    supported_scale_factors.push_back(closest);
60368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#elif defined(OS_IOS)
60468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
60568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (display.device_scale_factor() > 1.0) {
60668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(2.0, display.device_scale_factor());
60768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    supported_scale_factors.push_back(SCALE_FACTOR_200P);
60868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
60968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    supported_scale_factors.push_back(SCALE_FACTOR_100P);
61068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
61168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#elif defined(OS_MACOSX)
61268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (base::mac::IsOSLionOrLater())
61368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    supported_scale_factors.push_back(SCALE_FACTOR_200P);
61468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#elif defined(OS_CHROMEOS)
61568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // TODO(oshima): Include 200P only if the device support 200P
61668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  supported_scale_factors.push_back(SCALE_FACTOR_200P);
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#elif defined(OS_LINUX) && defined(ENABLE_HIDPI)
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  supported_scale_factors.push_back(SCALE_FACTOR_200P);
619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_WIN)
620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool default_to_100P = true;
621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (gfx::IsHighDPIEnabled()) {
622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // On Windows if the dpi scale is greater than 1.25 on high dpi machines
623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // downscaling from 200 percent looks better than scaling up from 100
624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // percent.
625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (gfx::GetDPIScale() > 1.25) {
626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      supported_scale_factors.push_back(SCALE_FACTOR_200P);
627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      default_to_100P = false;
628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (default_to_100P)
631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    supported_scale_factors.push_back(SCALE_FACTOR_100P);
63268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
63368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ui::SetSupportedScaleFactors(supported_scale_factors);
6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(OS_WIN)
6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Must be called _after_ supported scale factors are set since it
6364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // uses them.
63746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Don't initialize the device scale factor if it has already been
63846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // initialized.
63946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!gfx::win::IsDeviceScaleFactorSet())
64046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ui::win::InitDeviceScaleFactor();
6414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
64268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
64368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceBundle::FreeImages() {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  images_.clear();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceBundle::AddDataPackFromPathInternal(const base::FilePath& path,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 ScaleFactor scale_factor,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 bool optional) {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not pass an empty |path| value to this method. If the absolute path is
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unknown pass just the pack file name.
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!path.empty());
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath pack_path = path;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pack_path = delegate_->GetPathForResourcePack(pack_path, scale_factor);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't try to load empty values or values that are not absolute paths.
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pack_path.empty() || !pack_path.IsAbsolute())
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DataPack> data_pack(
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DataPack(scale_factor));
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data_pack->LoadFromPath(pack_path)) {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddDataPack(data_pack.release());
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!optional) {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to load " << pack_path.value()
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "\nSome features may not be available.";
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceBundle::AddDataPack(DataPack* data_pack) {
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_packs_.push_back(data_pack);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (GetScaleForScaleFactor(data_pack->GetScaleFactor()) >
6770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetScaleForScaleFactor(max_scale_factor_))
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_scale_factor_ = data_pack->GetScaleFactor();
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceBundle::LoadFontsIfNecessary() {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  images_and_fonts_lock_->AssertAcquired();
683a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!base_font_list_.get()) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_) {
685a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base_font_list_ = GetFontListFromDelegate(BaseFont);
686a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      bold_font_list_ = GetFontListFromDelegate(BoldFont);
687a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      small_font_list_ = GetFontListFromDelegate(SmallFont);
688a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      small_bold_font_list_ = GetFontListFromDelegate(SmallBoldFont);
689a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      medium_font_list_ = GetFontListFromDelegate(MediumFont);
690a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      medium_bold_font_list_ = GetFontListFromDelegate(MediumBoldFont);
691a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      large_font_list_ = GetFontListFromDelegate(LargeFont);
692a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      large_bold_font_list_ = GetFontListFromDelegate(LargeBoldFont);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!base_font_list_.get())
696a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base_font_list_.reset(new gfx::FontList());
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
698a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!bold_font_list_.get()) {
699a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      bold_font_list_.reset(new gfx::FontList());
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *bold_font_list_ = base_font_list_->DeriveWithStyle(
701a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          base_font_list_->GetFontStyle() | gfx::Font::BOLD);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
704a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!small_font_list_.get()) {
705a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      small_font_list_.reset(new gfx::FontList());
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *small_font_list_ =
7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base_font_list_->DeriveWithSizeDelta(kSmallFontSizeDelta);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
710a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!small_bold_font_list_.get()) {
711a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      small_bold_font_list_.reset(new gfx::FontList());
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *small_bold_font_list_ = small_font_list_->DeriveWithStyle(
713a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          small_font_list_->GetFontStyle() | gfx::Font::BOLD);
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
716a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!medium_font_list_.get()) {
717a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      medium_font_list_.reset(new gfx::FontList());
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *medium_font_list_ =
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base_font_list_->DeriveWithSizeDelta(kMediumFontSizeDelta);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
722a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!medium_bold_font_list_.get()) {
723a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      medium_bold_font_list_.reset(new gfx::FontList());
7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *medium_bold_font_list_ = medium_font_list_->DeriveWithStyle(
725a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          medium_font_list_->GetFontStyle() | gfx::Font::BOLD);
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
728a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!large_font_list_.get()) {
729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      large_font_list_.reset(new gfx::FontList());
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *large_font_list_ =
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base_font_list_->DeriveWithSizeDelta(kLargeFontSizeDelta);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
734a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!large_bold_font_list_.get()) {
735a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      large_bold_font_list_.reset(new gfx::FontList());
7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *large_bold_font_list_ = large_font_list_->DeriveWithStyle(
737a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          large_font_list_->GetFontStyle() | gfx::Font::BOLD);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)scoped_ptr<gfx::FontList> ResourceBundle::GetFontListFromDelegate(
743a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    FontStyle style) {
744a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(delegate_);
745a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<gfx::Font> font = delegate_->GetFont(style);
746a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (font.get())
747a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return scoped_ptr<gfx::FontList>(new gfx::FontList(*font));
748a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return scoped_ptr<gfx::FontList>();
749a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
750a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ResourceBundle::LoadBitmap(const ResourceHandle& data_handle,
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int resource_id,
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                SkBitmap* bitmap,
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool* fell_back_to_1x) const {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fell_back_to_1x);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::RefCountedMemory> memory(
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_handle.GetStaticMemory(resource_id));
758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!memory.get())
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (DecodePNG(memory->front(), memory->size(), bitmap, fell_back_to_1x))
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_IOS)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // iOS does not compile or use the JPEG codec.  On other platforms,
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 99% of our assets are PNGs, however fallback to JPEG.
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SkBitmap> jpeg_bitmap(
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::JPEGCodec::Decode(memory->front(), memory->size()));
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (jpeg_bitmap.get()) {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap->swap(*jpeg_bitmap.get());
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *fell_back_to_1x = false;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Unable to decode theme image resource " << resource_id;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ResourceBundle::LoadBitmap(int resource_id,
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                ScaleFactor* scale_factor,
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                SkBitmap* bitmap,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool* fell_back_to_1x) const {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fell_back_to_1x);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < data_packs_.size(); ++i) {
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_NONE &&
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LoadBitmap(*data_packs_[i], resource_id, bitmap, fell_back_to_1x)) {
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!*fell_back_to_1x);
789cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *scale_factor = ui::SCALE_FACTOR_NONE;
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (data_packs_[i]->GetScaleFactor() == *scale_factor &&
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LoadBitmap(*data_packs_[i], resource_id, bitmap, fell_back_to_1x)) {
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image& ResourceBundle::GetEmptyImage() {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(*images_and_fonts_lock_);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (empty_image_.IsEmpty()) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The placeholder bitmap is bright red so people notice the problem.
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkBitmap bitmap;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32, 32);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.allocPixels();
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.eraseARGB(255, 255, 0, 0);
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    empty_image_ = gfx::Image::CreateFrom1xBitmap(bitmap);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return empty_image_;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ResourceBundle::PNGContainsFallbackMarker(const unsigned char* buf,
816a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                               size_t size) {
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size < arraysize(kPngMagic) ||
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      memcmp(buf, kPngMagic, arraysize(kPngMagic)) != 0) {
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Data invalid or a JPEG.
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t pos = arraysize(kPngMagic);
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Scan for custom chunks until we find one, find the IDAT chunk, or run out
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of chunks.
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (;;) {
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (size - pos < kPngChunkMetadataSize)
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 length = 0;
830a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::ReadBigEndian(reinterpret_cast<const char*>(buf + pos), &length);
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (size - pos - kPngChunkMetadataSize < length)
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (length == 0 && memcmp(buf + pos + sizeof(uint32), kPngScaleChunkType,
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              arraysize(kPngScaleChunkType)) == 0) {
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (memcmp(buf + pos + sizeof(uint32), kPngDataChunkType,
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               arraysize(kPngDataChunkType)) == 0) {
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Stop looking for custom chunks, any custom chunks should be before an
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // IDAT chunk.
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pos += length + kPngChunkMetadataSize;
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ResourceBundle::DecodePNG(const unsigned char* buf,
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               size_t size,
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               SkBitmap* bitmap,
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               bool* fell_back_to_1x) {
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *fell_back_to_1x = PNGContainsFallbackMarker(buf, size);
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::PNGCodec::Decode(buf, size, bitmap);
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
858