OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/base/resource/resource_bundle.h" | 5 #include "ui/base/resource/resource_bundle.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 | 42 |
43 ResourceBundle* g_shared_instance_ = NULL; | 43 ResourceBundle* g_shared_instance_ = NULL; |
44 | 44 |
45 bool ShouldHighlightMissingScaledResources() { | 45 bool ShouldHighlightMissingScaledResources() { |
46 return CommandLine::ForCurrentProcess()->HasSwitch( | 46 return CommandLine::ForCurrentProcess()->HasSwitch( |
47 switches::kHighlightMissingScaledResources); | 47 switches::kHighlightMissingScaledResources); |
48 } | 48 } |
49 | 49 |
50 } // namespace | 50 } // namespace |
51 | 51 |
52 // An ImageSkiaSource that loads bitmaps for requested scale factor from | 52 // An ImageSkiaSource that loads bitmaps for the requested scale factor from |
53 // ResourceBundle on demand for given resource_id. It falls back | 53 // ResourceBundle on demand for a given |resource_id|. If the bitmap for the |
54 // to the 1x bitmap if the bitmap for the requested scale factor does not | 54 // requested scale factor does not exist, it will return the 1x bitmap scaled |
55 // exist. If the resource for the requested scale factor is not exactly | 55 // by the scale factor. This may lead to broken UI if the correct size of the |
56 // |scale_factor| * the size of the 1x resource, it will end up with | 56 // scaled image is not exactly |scale_factor| * the size of the 1x resource. |
57 // broken UI because it will be drawn as if the bitmap was the correct size. | 57 // When --highlight-missing-scaled-resources flag is specified, scaled 1x images |
58 // When --highlight-missing-scaled-resources flag is specified, it | 58 // are higlighted by blending them with red. |
59 // will show the scaled image blended with red instead. | |
60 class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource { | 59 class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource { |
61 public: | 60 public: |
62 ResourceBundleImageSource(ResourceBundle* rb, | 61 ResourceBundleImageSource(ResourceBundle* rb, int resource_id) |
63 int resource_id, | 62 : rb_(rb), resource_id_(resource_id) {} |
64 const gfx::Size& size_in_dip) | |
65 : rb_(rb), | |
66 resource_id_(resource_id), | |
67 size_in_dip_(size_in_dip) { | |
68 } | |
69 virtual ~ResourceBundleImageSource() {} | 63 virtual ~ResourceBundleImageSource() {} |
70 | 64 |
71 // gfx::ImageSkiaSource overrides: | 65 // gfx::ImageSkiaSource overrides: |
72 virtual gfx::ImageSkiaRep GetImageForScale( | 66 virtual gfx::ImageSkiaRep GetImageForScale( |
73 ui::ScaleFactor scale_factor) OVERRIDE { | 67 ui::ScaleFactor scale_factor) OVERRIDE { |
74 scoped_ptr<SkBitmap> result(rb_->LoadBitmap(resource_id_, scale_factor)); | 68 SkBitmap image; |
75 float scale = ui::GetScaleFactorScale(scale_factor); | 69 bool scale_fallback = false; |
sail
2012/10/09 22:01:37
same, naming could be better
benrg
2012/10/10 02:18:13
Done.
| |
76 gfx::Size size_in_pixel = size_in_dip_.Scale(scale); | 70 bool found = rb_->LoadBitmap(resource_id_, scale_factor, |
71 &image, &scale_fallback); | |
77 | 72 |
78 if (scale_factor != SCALE_FACTOR_100P && | 73 if (!found) { |
79 (!result.get() || | 74 // Some images (e.g. wallpapers) exist only at 100%. Return the unscaled |
80 result->width() != size_in_pixel.width() || | 75 // image with the correct scale factor. |
81 result->height() != size_in_pixel.height())) { | 76 DCHECK_NE(scale_factor, SCALE_FACTOR_100P); |
sail
2012/10/09 22:01:37
This DCHECK says that we shouldn't be missing imag
benrg
2012/10/10 02:18:13
You're right; rewritten.
| |
77 if (!rb_->LoadBitmap(resource_id_, SCALE_FACTOR_100P, &image, NULL)) | |
78 return gfx::ImageSkiaRep(); | |
79 return gfx::ImageSkiaRep(image, SCALE_FACTOR_100P); | |
80 } | |
82 | 81 |
83 // If non 1x resource is missing from |image| or is the incorrect | 82 if (scale_fallback) { |
84 // size and --highlight-missing-scaled-resources is specified, logs | 83 // GRIT fell back to the 100% image, so rescale it to the correct size. |
85 // the resource id and creates a version of the resource at the correct | 84 float scale = GetScaleFactorScale(scale_factor); |
86 // size. Blends the created resource with red to make it | 85 image = skia::ImageOperations::Resize( |
87 // distinguishable from bitmaps in the resource pak. | 86 image, |
87 skia::ImageOperations::RESIZE_LANCZOS3, | |
88 static_cast<int>(image.width() * scale + 0.5f), | |
sail
2012/10/09 22:01:37
the cast and + 0.5 is for rounding right? can you
benrg
2012/10/10 02:18:13
I'm not sure I even want to make a helper function
sail
2012/10/10 03:09:55
This is still a rounding function. Duplicated.
Eve
benrg
2012/10/10 21:03:56
Done.
| |
89 static_cast<int>(image.height() * scale + 0.5f)); | |
90 // If --highlight-missing-scaled-resources is specified, log the resource | |
91 // id and blend the created resource with red. | |
88 if (ShouldHighlightMissingScaledResources()) { | 92 if (ShouldHighlightMissingScaledResources()) { |
89 if (!result.get()) { | 93 LOG(ERROR) << "Missing " << scale << "x scaled resource. id=" |
90 LOG(ERROR) << "Missing " << scale << "x resource. id=" | 94 << resource_id_; |
91 << resource_id_; | |
92 } else { | |
93 LOG(ERROR) << "Incorrectly sized " << scale << "x resource. id=" | |
94 << resource_id_; | |
95 } | |
96 | |
97 scoped_ptr<SkBitmap> bitmap1x( | |
98 rb_->LoadBitmap(resource_id_, SCALE_FACTOR_100P)); | |
99 DCHECK(bitmap1x.get()); | |
100 SkBitmap bitmap_scaled = skia::ImageOperations::Resize( | |
101 *bitmap1x, | |
102 skia::ImageOperations::RESIZE_LANCZOS3, | |
103 size_in_pixel.width(), | |
104 size_in_pixel.height()); | |
105 | 95 |
106 SkBitmap mask; | 96 SkBitmap mask; |
107 mask.setConfig(SkBitmap::kARGB_8888_Config, | 97 mask.setConfig(SkBitmap::kARGB_8888_Config, |
108 bitmap_scaled.width(), | 98 image.width(), image.height()); |
109 bitmap_scaled.height()); | |
110 mask.allocPixels(); | 99 mask.allocPixels(); |
111 mask.eraseColor(SK_ColorRED); | 100 mask.eraseColor(SK_ColorRED); |
112 result.reset(new SkBitmap()); | 101 image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2); |
113 *result.get() = SkBitmapOperations::CreateBlendedBitmap( | |
114 bitmap_scaled, mask, 0.2); | |
115 } else if (!result.get() || result->width() == size_in_dip_.width()) { | |
116 // The scaled resource pack may have the 1x image if its grd file | |
117 // points to 1x image. Fallback to 1x by returning empty image | |
118 // in this case. This 1x image will be scaled when drawn. | |
119 return gfx::ImageSkiaRep(); | |
120 } | 102 } |
121 // If the size of scaled image isn't exactly |scale| * 1x version, | |
122 // create ImageSkia as usual. This will end up with | |
123 // corrupted visual representation as the size of image doesn't | |
124 // match the expected size. | |
125 } | 103 } |
126 DCHECK(result.get()); | 104 |
127 return gfx::ImageSkiaRep(*result.get(), scale_factor); | 105 return gfx::ImageSkiaRep(image, scale_factor); |
128 } | 106 } |
129 | 107 |
130 private: | 108 private: |
131 ResourceBundle* rb_; | 109 ResourceBundle* rb_; |
132 const int resource_id_; | 110 const int resource_id_; |
133 const gfx::Size size_in_dip_; | |
134 | 111 |
135 DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource); | 112 DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource); |
136 }; | 113 }; |
137 | 114 |
138 // static | 115 // static |
139 std::string ResourceBundle::InitSharedInstanceWithLocale( | 116 std::string ResourceBundle::InitSharedInstanceWithLocale( |
140 const std::string& pref_locale, Delegate* delegate) { | 117 const std::string& pref_locale, Delegate* delegate) { |
141 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 118 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; |
142 g_shared_instance_ = new ResourceBundle(delegate); | 119 g_shared_instance_ = new ResourceBundle(delegate); |
143 | 120 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 } | 314 } |
338 | 315 |
339 gfx::Image image; | 316 gfx::Image image; |
340 if (delegate_) | 317 if (delegate_) |
341 image = delegate_->GetImageNamed(resource_id); | 318 image = delegate_->GetImageNamed(resource_id); |
342 | 319 |
343 if (image.IsEmpty()) { | 320 if (image.IsEmpty()) { |
344 DCHECK(!delegate_ && !data_packs_.empty()) << | 321 DCHECK(!delegate_ && !data_packs_.empty()) << |
345 "Missing call to SetResourcesDataDLL?"; | 322 "Missing call to SetResourcesDataDLL?"; |
346 | 323 |
347 // TODO(oshima): Pick the scale factor from currently used scale factors. | 324 // TODO(benrg/oshima): GetPrimaryDisplay() crashes at startup. |
348 scoped_ptr<SkBitmap> bitmap(LoadBitmap(resource_id, SCALE_FACTOR_100P)); | 325 // ScaleFactor primary_scale_factor = GetScaleFactorFromScale( |
sail
2012/10/09 22:01:37
there's no point leaving commented out code here.
benrg
2012/10/10 02:18:13
Fixed by fixing the crash (courtesy Oshima).
| |
349 if (!bitmap.get()) { | 326 // gfx::Screen::GetPrimaryDisplay().device_scale_factor()); |
327 ScaleFactor primary_scale_factor = SCALE_FACTOR_100P; | |
328 scoped_ptr<ResourceBundleImageSource> image_source( | |
329 new ResourceBundleImageSource(this, resource_id)); | |
330 gfx::ImageSkiaRep scaled_image = | |
331 image_source->GetImageForScale(primary_scale_factor); | |
332 if (scaled_image.is_null()) { | |
350 LOG(WARNING) << "Unable to load image with id " << resource_id; | 333 LOG(WARNING) << "Unable to load image with id " << resource_id; |
351 NOTREACHED(); // Want to assert in debug mode. | 334 NOTREACHED(); // Want to assert in debug mode. |
352 // The load failed to retrieve the image; show a debugging red square. | 335 // The load failed to retrieve the image; show a debugging red square. |
353 return GetEmptyImage(); | 336 return GetEmptyImage(); |
354 } | 337 } |
338 gfx::Size size_in_dip(scaled_image.GetWidth(), scaled_image.GetHeight()); | |
355 | 339 |
356 // ResourceBundle::GetSharedInstance() is destroyed after the | 340 // ResourceBundle::GetSharedInstance() is destroyed after the |
357 // BrowserMainLoop has finished running. |image_skia| is guaranteed to be | 341 // BrowserMainLoop has finished running. |image_skia| is guaranteed to be |
358 // destroyed before the resource bundle is destroyed. | 342 // destroyed before the resource bundle is destroyed. |
359 gfx::Size size_in_dip(bitmap->width(), bitmap->height()); | 343 gfx::ImageSkia image_skia(image_source.release(), size_in_dip); |
360 gfx::ImageSkia image_skia( | 344 image_skia.AddRepresentation(scaled_image); |
361 new ResourceBundleImageSource(this, resource_id, size_in_dip), | |
362 size_in_dip); | |
363 image_skia.AddRepresentation(gfx::ImageSkiaRep(*bitmap.get(), | |
364 SCALE_FACTOR_100P)); | |
365 image_skia.SetReadOnly(); | 345 image_skia.SetReadOnly(); |
366 image = gfx::Image(image_skia); | 346 image = gfx::Image(image_skia); |
367 } | 347 } |
368 | 348 |
369 // The load was successful, so cache the image. | 349 // The load was successful, so cache the image. |
370 base::AutoLock lock_scope(*images_and_fonts_lock_); | 350 base::AutoLock lock_scope(*images_and_fonts_lock_); |
371 | 351 |
372 // Another thread raced the load and has already cached the image. | 352 // Another thread raced the load and has already cached the image. |
373 if (images_.count(resource_id)) | 353 if (images_.count(resource_id)) |
374 return images_[resource_id]; | 354 return images_[resource_id]; |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
582 | 562 |
583 if (!large_bold_font_.get()) { | 563 if (!large_bold_font_.get()) { |
584 large_bold_font_.reset(new gfx::Font()); | 564 large_bold_font_.reset(new gfx::Font()); |
585 *large_bold_font_ = | 565 *large_bold_font_ = |
586 base_font_->DeriveFont(kLargeFontSizeDelta, | 566 base_font_->DeriveFont(kLargeFontSizeDelta, |
587 base_font_->GetStyle() | gfx::Font::BOLD); | 567 base_font_->GetStyle() | gfx::Font::BOLD); |
588 } | 568 } |
589 } | 569 } |
590 } | 570 } |
591 | 571 |
592 SkBitmap* ResourceBundle::LoadBitmap(const ResourceHandle& data_handle, | 572 bool ResourceBundle::LoadBitmap(const ResourceHandle& data_handle, |
593 int resource_id) const { | 573 int resource_id, |
574 SkBitmap* bitmap, | |
575 bool* scale_fallback) const { | |
594 scoped_refptr<base::RefCountedMemory> memory( | 576 scoped_refptr<base::RefCountedMemory> memory( |
595 data_handle.GetStaticMemory(resource_id)); | 577 data_handle.GetStaticMemory(resource_id)); |
596 if (!memory) | 578 if (!memory) |
597 return NULL; | 579 return false; |
598 | 580 |
599 SkBitmap bitmap; | 581 if (gfx::PNGCodec::Decode(memory->front(), memory->size(), |
600 if (gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) | 582 bitmap, scale_fallback)) { |
601 return new SkBitmap(bitmap); | 583 return true; |
584 } | |
602 | 585 |
603 // 99% of our assets are PNGs, however fallback to JPEG. | 586 // 99% of our assets are PNGs, however fallback to JPEG. |
604 SkBitmap* allocated_bitmap = | 587 scoped_ptr<SkBitmap> jpeg_bitmap( |
605 gfx::JPEGCodec::Decode(memory->front(), memory->size()); | 588 gfx::JPEGCodec::Decode(memory->front(), memory->size())); |
606 if (allocated_bitmap) | 589 if (jpeg_bitmap.get()) { |
607 return allocated_bitmap; | 590 bitmap->swap(*jpeg_bitmap.get()); |
591 return true; | |
592 } | |
608 | 593 |
609 NOTREACHED() << "Unable to decode theme image resource " << resource_id; | 594 NOTREACHED() << "Unable to decode theme image resource " << resource_id; |
610 return NULL; | 595 return false; |
611 } | 596 } |
612 | 597 |
613 SkBitmap* ResourceBundle::LoadBitmap(int resource_id, | 598 bool ResourceBundle::LoadBitmap(int resource_id, |
614 ScaleFactor scale_factor) const { | 599 ScaleFactor scale_factor, |
600 SkBitmap* bitmap, | |
601 bool* scale_fallback) const { | |
615 for (size_t i = 0; i < data_packs_.size(); ++i) { | 602 for (size_t i = 0; i < data_packs_.size(); ++i) { |
616 if (data_packs_[i]->GetScaleFactor() == scale_factor) { | 603 if (data_packs_[i]->GetScaleFactor() == scale_factor) { |
617 SkBitmap* bitmap = LoadBitmap(*data_packs_[i], resource_id); | 604 if (LoadBitmap(*data_packs_[i], resource_id, bitmap, scale_fallback)) |
618 if (bitmap) | 605 return true; |
619 return bitmap; | |
620 } | 606 } |
621 } | 607 } |
622 return NULL; | 608 return false; |
623 } | 609 } |
624 | 610 |
625 gfx::Image& ResourceBundle::GetEmptyImage() { | 611 gfx::Image& ResourceBundle::GetEmptyImage() { |
626 base::AutoLock lock(*images_and_fonts_lock_); | 612 base::AutoLock lock(*images_and_fonts_lock_); |
627 | 613 |
628 if (empty_image_.IsEmpty()) { | 614 if (empty_image_.IsEmpty()) { |
629 // The placeholder bitmap is bright red so people notice the problem. | 615 // The placeholder bitmap is bright red so people notice the problem. |
630 SkBitmap bitmap; | 616 SkBitmap bitmap; |
631 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32, 32); | 617 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32, 32); |
632 bitmap.allocPixels(); | 618 bitmap.allocPixels(); |
633 bitmap.eraseARGB(255, 255, 0, 0); | 619 bitmap.eraseARGB(255, 255, 0, 0); |
634 empty_image_ = gfx::Image(bitmap); | 620 empty_image_ = gfx::Image(bitmap); |
635 } | 621 } |
636 return empty_image_; | 622 return empty_image_; |
637 } | 623 } |
638 | 624 |
639 } // namespace ui | 625 } // namespace ui |
OLD | NEW |