From 6556602bdc008d1fb0d87b191f330f0b8a570b93 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 18:41:06 +0800 Subject: [PATCH] Enable creating NativeImage from file path --- atom.gyp | 1 + atom/common/api/atom_api_native_image.cc | 95 +++++++++++++++++++- atom/common/api/atom_api_native_image.h | 6 ++ atom/common/api/atom_api_native_image_mac.mm | 42 +++++++++ 4 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 atom/common/api/atom_api_native_image_mac.mm diff --git a/atom.gyp b/atom.gyp index 75aedb4fac4a..9df90ef44a7b 100644 --- a/atom.gyp +++ b/atom.gyp @@ -207,6 +207,7 @@ 'atom/common/api/atom_api_id_weak_map.h', 'atom/common/api/atom_api_native_image.cc', 'atom/common/api/atom_api_native_image.h', + 'atom/common/api/atom_api_native_image_mac.mm', 'atom/common/api/atom_api_shell.cc', 'atom/common/api/atom_api_v8_util.cc', 'atom/common/api/atom_bindings.cc', diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index bb657335ced5..955bfe7a84b8 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -4,12 +4,18 @@ #include "atom/common/api/atom_api_native_image.h" +#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gfx_converter.h" -#include "atom/common/native_mate_converters/image_converter.h" +#include "base/files/file_util.h" +#include "base/strings/string_util.h" #include "native_mate/constructor.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" +#include "ui/base/layout.h" +#include "ui/gfx/codec/jpeg_codec.h" +#include "ui/gfx/codec/png_codec.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_util.h" #include "atom/common/node_includes.h" @@ -20,6 +26,82 @@ namespace api { namespace { +#if !defined(OS_MACOSX) +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 }, + { "@4x" , 4.0f }, + { "@5x" , 5.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()); + + // 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; + } + + return 1.0f; +} + +bool AddImageSkiaRep(gfx::ImageSkia* image, + const base::FilePath& path, + double scale_factor) { + std::string file_contents; + if (!base::ReadFileToString(path, &file_contents)) + return false; + + const unsigned char* data = + reinterpret_cast(file_contents.data()); + size_t size = file_contents.size(); + scoped_ptr decoded(new SkBitmap()); + + // Try PNG first. + if (!gfx::PNGCodec::Decode(data, size, decoded.get())) + // Try JPEG. + decoded.reset(gfx::JPEGCodec::Decode(data, size)); + + if (!decoded) + return false; + + image->AddRepresentation(gfx::ImageSkiaRep(*decoded.release(), scale_factor)); + return true; +} + +bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image, + const base::FilePath& path) { + bool succeed = false; + std::string filename(path.BaseName().RemoveExtension().AsUTF8Unsafe()); + if (MatchPattern(filename, "*@*x")) + // Don't search for other representations if the DPI has been specified. + return AddImageSkiaRep(image, path, GetScaleFactorFromPath(path)); + else + succeed |= AddImageSkiaRep(image, path, 1.0f); + + for (const ScaleFactorPair& pair : kScaleFactorPairs) + succeed |= AddImageSkiaRep(image, + path.InsertBeforeExtensionASCII(pair.name), + pair.scale); + return succeed; +} +#endif // !defined(OS_MACOSX) + v8::Persistent template_; } // namespace @@ -89,6 +171,16 @@ mate::Handle NativeImage::CreateFromJPEG( return Create(isolate, image); } +#if !defined(OS_MACOSX) +// static +mate::Handle NativeImage::CreateFromPath( + v8::Isolate* isolate, const base::FilePath& path) { + gfx::ImageSkia image_skia; + PopulateImageSkiaRepsFromPath(&image_skia, path); + return Create(isolate, gfx::Image(image_skia)); +} +#endif // !defined(OS_MACOSX) + } // namespace api } // namespace atom @@ -101,6 +193,7 @@ void Initialize(v8::Handle exports, v8::Handle unused, mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("createFromPng", &atom::api::NativeImage::CreateFromPNG); dict.SetMethod("createFromJpeg", &atom::api::NativeImage::CreateFromJPEG); + dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath); } } // namespace diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 55d2686227a0..7096ad93e0ef 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -9,6 +9,10 @@ #include "native_mate/wrappable.h" #include "ui/gfx/image/image.h" +namespace base { +class FilePath; +} + namespace gfx { class Size; } @@ -25,6 +29,8 @@ class NativeImage : public mate::Wrappable { v8::Isolate* isolate, v8::Handle buffer); static mate::Handle CreateFromJPEG( v8::Isolate* isolate, v8::Handle buffer); + static mate::Handle CreateFromPath( + v8::Isolate* isolate, const base::FilePath& path); protected: explicit NativeImage(const gfx::Image& image); diff --git a/atom/common/api/atom_api_native_image_mac.mm b/atom/common/api/atom_api_native_image_mac.mm new file mode 100644 index 000000000000..f4d7e7d496ae --- /dev/null +++ b/atom/common/api/atom_api_native_image_mac.mm @@ -0,0 +1,42 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/api/atom_api_native_image.h" + +#import + +#include "base/files/file_path.h" +#include "base/mac/foundation_util.h" +#include "base/mac/scoped_nsobject.h" +#include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia.h" + +namespace atom { + +namespace api { + +namespace { + +bool IsTemplateImage(const base::FilePath& path) { + return (MatchPattern(path.value(), "*Template.*") || + MatchPattern(path.value(), "*Template@*x.*")); +} + +} // namespace + +// static +mate::Handle NativeImage::CreateFromPath( + v8::Isolate* isolate, const base::FilePath& path) { + base::scoped_nsobject image([[NSImage alloc] + initByReferencingFile:base::mac::FilePathToNSString(path)]); + if (IsTemplateImage(path)) + [image setTemplate:YES]; + return Create(isolate, gfx::Image(image.release())); +} + +} // namespace api + +} // namespace atom