Add support for multiple DPI images, fixes #541.

This commit is contained in:
Cheng Zhao 2014-08-06 11:20:00 +08:00
parent a76ae8cd35
commit dfe111b95a
2 changed files with 114 additions and 22 deletions

View file

@ -5,6 +5,7 @@
#include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/image_converter.h"
#include <string> #include <string>
#include <vector>
#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h"
#include "base/file_util.h" #include "base/file_util.h"
@ -18,21 +19,62 @@ namespace mate {
namespace { namespace {
ui::ScaleFactor GetScaleFactorFromFileName(const base::FilePath& path) { struct ScaleFactorPair {
const char* name;
float scale;
};
ScaleFactorPair kScaleFactorPairs[] = {
// The "@2x" is put as first one to make scale matching faster.
{ "@2x" , 2.0f },
{ "@3x" , 3.0f },
{ "@1x" , 1.0f },
{ "@1.25x" , 1.25f },
{ "@1.33x" , 1.33f },
{ "@1.4x" , 1.4f },
{ "@1.5x" , 1.5f },
{ "@1.8x" , 1.8f },
{ "@2.5x" , 2.5f },
};
float GetScaleFactorFromPath(const base::FilePath& path) {
std::string filename(path.BaseName().RemoveExtension().AsUTF8Unsafe()); std::string filename(path.BaseName().RemoveExtension().AsUTF8Unsafe());
if (EndsWith(filename, "@2x", true))
return ui::SCALE_FACTOR_200P; // There is no scale info in the file path.
else if (!EndsWith(filename, "x", true))
return ui::SCALE_FACTOR_100P; return 1.0f;
// We don't try to convert string to float here because it is very very
// expensive.
for (unsigned i = 0; i < arraysize(kScaleFactorPairs); ++i) {
if (EndsWith(filename, kScaleFactorPairs[i].name, true))
return kScaleFactorPairs[i].scale;
} }
} // namespace return 1.0f;
}
bool Converter<gfx::ImageSkia>::FromV8(v8::Isolate* isolate, void AppendIfExists(std::vector<base::FilePath>* paths,
v8::Handle<v8::Value> val, const base::FilePath& path) {
gfx::ImageSkia* out) { if (base::PathExists(path))
base::FilePath path; paths->push_back(path);
if (Converter<base::FilePath>::FromV8(isolate, val, &path)) { }
void PopulatePossibleFilePaths(std::vector<base::FilePath>* paths,
const base::FilePath& path) {
AppendIfExists(paths, path);
std::string filename(path.BaseName().RemoveExtension().AsUTF8Unsafe());
if (MatchPattern(filename, "*@*x"))
return;
for (unsigned i = 0; i < arraysize(kScaleFactorPairs); ++i)
AppendIfExists(paths,
path.InsertBeforeExtensionASCII(kScaleFactorPairs[i].name));
}
bool AddImageSkiaRepFromPath(gfx::ImageSkia* image,
const base::FilePath& path) {
std::string file_contents; std::string file_contents;
if (!base::ReadFileToString(path, &file_contents)) if (!base::ReadFileToString(path, &file_contents))
return false; return false;
@ -48,10 +90,31 @@ bool Converter<gfx::ImageSkia>::FromV8(v8::Isolate* isolate,
decoded.reset(gfx::JPEGCodec::Decode(data, size)); decoded.reset(gfx::JPEGCodec::Decode(data, size));
if (decoded) { if (decoded) {
*out = gfx::ImageSkia(gfx::ImageSkiaRep(*decoded.release(), image->AddRepresentation(gfx::ImageSkiaRep(
GetScaleFactorFromFileName(path))); *decoded.release(), GetScaleFactorFromPath(path)));
return true; return true;
} }
return false;
}
} // namespace
bool Converter<gfx::ImageSkia>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::ImageSkia* out) {
base::FilePath path;
if (Converter<base::FilePath>::FromV8(isolate, val, &path)) {
std::vector<base::FilePath> paths;
PopulatePossibleFilePaths(&paths, path);
if (paths.empty())
return false;
for (size_t i = 0; i < paths.size(); ++i) {
if (!AddImageSkiaRepFromPath(out, paths[i]))
return false;
}
return true;
} }
return false; return false;

View file

@ -7,7 +7,7 @@ For example when creating tray or setting window's icon, you can pass image's
file path as `String` to represent an image: file path as `String` to represent an image:
```javascript ```javascript
var appIcon = new Tray('/Users/somebody/images/icon@2x.png'); var appIcon = new Tray('/Users/somebody/images/icon.png');
var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'}); var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'});
``` ```
@ -23,3 +23,32 @@ file name's base name to mark it as a high resolution image.
For example if `icon.png` is a normal image that has standard resolution, the For example if `icon.png` is a normal image that has standard resolution, the
`icon@2x.png` would be treated as a high resolution image that has double DPI `icon@2x.png` would be treated as a high resolution image that has double DPI
dense. dense.
If you want to support displays with different DPI denses at the same time, you
can put images with different sizes in the same folder, and use the filename
without DPI suffixes, like this:
```text
images/
├── icon.png
├── icon@2x.png
└── icon@3x.png
```
```javascript
var appIcon = new Tray('/Users/somebody/images/icon.png');
```
Following suffixes as DPI denses are also supported:
* `@1x`
* `@1.25x`
* `@1.33x`
* `@1.4x`
* `@1.5x`
* `@1.8x`
* `@2x`
* `@2.5x`
* `@3x`