From 878d25e91eac68605b5a90b22a3274f3655301b6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 14:31:51 +0800 Subject: [PATCH 01/21] Enable converting gfx::Image to Buffer --- .../native_mate_converters/image_converter.cc | 16 +++++++++++++--- .../native_mate_converters/image_converter.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/atom/common/native_mate_converters/image_converter.cc b/atom/common/native_mate_converters/image_converter.cc index 8de73db306dd..2c991b9236c0 100644 --- a/atom/common/native_mate_converters/image_converter.cc +++ b/atom/common/native_mate_converters/image_converter.cc @@ -16,10 +16,12 @@ #include "ui/gfx/image/image_skia.h" #include "ui/base/layout.h" -#if !defined(OS_MACOSX) +#include "atom/common/node_includes.h" namespace mate { +#if !defined(OS_MACOSX) + namespace { struct ScaleFactorPair { @@ -122,6 +124,14 @@ bool Converter::FromV8(v8::Isolate* isolate, return true; } -} // namespace mate - #endif // !defined(OS_MACOSX) + +v8::Handle Converter::ToV8(v8::Isolate* isolate, + const gfx::Image& val) { + scoped_refptr png = val.As1xPNGBytes(); + return node::Buffer::New(isolate, + reinterpret_cast(png->front()), + png->size()); +} + +} // namespace mate diff --git a/atom/common/native_mate_converters/image_converter.h b/atom/common/native_mate_converters/image_converter.h index 738b50ad7416..1b1a12c3ae02 100644 --- a/atom/common/native_mate_converters/image_converter.h +++ b/atom/common/native_mate_converters/image_converter.h @@ -26,6 +26,8 @@ struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, gfx::Image* out); + static v8::Handle ToV8(v8::Isolate* isolate, + const gfx::Image& val); }; } // namespace mate From b76615f3e71399289473d59784d6fb7ef7ee81d0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 14:55:44 +0800 Subject: [PATCH 02/21] Add clipboard.readImage method --- atom/common/api/atom_api_clipboard.cc | 12 ++++++++++-- atom/common/api/lib/clipboard.coffee | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/atom/common/api/atom_api_clipboard.cc b/atom/common/api/atom_api_clipboard.cc index 36b8cecb7c86..645e6a68b2d5 100644 --- a/atom/common/api/atom_api_clipboard.cc +++ b/atom/common/api/atom_api_clipboard.cc @@ -5,10 +5,13 @@ #include #include +#include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "native_mate/dictionary.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" +#include "ui/gfx/image/image.h" #include "atom/common/node_includes.h" @@ -16,8 +19,7 @@ namespace mate { template<> struct Converter { - static bool FromV8(v8::Isolate* isolate, - v8::Handle val, + static bool FromV8(v8::Isolate* isolate, v8::Handle val, ui::ClipboardType* out) { std::string type; if (!Converter::FromV8(isolate, val, &type)) @@ -62,6 +64,11 @@ void WriteText(const base::string16& text, ui::ClipboardType type) { writer.WriteText(text); } +gfx::Image ReadImage(ui::ClipboardType type) { + SkBitmap bitmap = ui::Clipboard::GetForCurrentThread()->ReadImage(type); + return gfx::Image::CreateFrom1xBitmap(bitmap); +} + void Clear(ui::ClipboardType type) { ui::Clipboard::GetForCurrentThread()->Clear(type); } @@ -73,6 +80,7 @@ void Initialize(v8::Handle exports, v8::Handle unused, dict.SetMethod("_read", &Read); dict.SetMethod("_readText", &ReadText); dict.SetMethod("_writeText", &WriteText); + dict.SetMethod("_readImage", &ReadImage); dict.SetMethod("_clear", &Clear); } diff --git a/atom/common/api/lib/clipboard.coffee b/atom/common/api/lib/clipboard.coffee index 6438207a96a6..17b98e4aa176 100644 --- a/atom/common/api/lib/clipboard.coffee +++ b/atom/common/api/lib/clipboard.coffee @@ -9,4 +9,5 @@ else read: (format, type='standard') -> binding._read format, type readText: (type='standard') -> binding._readText type writeText: (text, type='standard') -> binding._writeText text, type + readImage: (type='standard') -> binding._readImage type clear: (type='standard') -> binding._clear type From aae576b48434385185902cdfb6777eab502aadbd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 16:03:19 +0800 Subject: [PATCH 03/21] Convert gfx::Image to NativeImage instance --- atom.gyp | 2 + atom/common/api/atom_api_native_image.cc | 65 +++++++++++++++++++ atom/common/api/atom_api_native_image.h | 41 ++++++++++++ .../native_mate_converters/image_converter.cc | 6 +- atom/common/node_bindings.cc | 1 + 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 atom/common/api/atom_api_native_image.cc create mode 100644 atom/common/api/atom_api_native_image.h diff --git a/atom.gyp b/atom.gyp index c83529a5d211..3c161b45d119 100644 --- a/atom.gyp +++ b/atom.gyp @@ -204,6 +204,8 @@ 'atom/common/api/atom_api_crash_reporter.cc', 'atom/common/api/atom_api_id_weak_map.cc', '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_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 new file mode 100644 index 000000000000..def6d0917577 --- /dev/null +++ b/atom/common/api/atom_api_native_image.cc @@ -0,0 +1,65 @@ +// 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" + +#include "atom/common/native_mate_converters/image_converter.h" +#include "native_mate/constructor.h" +#include "native_mate/dictionary.h" +#include "native_mate/object_template_builder.h" + +#include "atom/common/node_includes.h" + +namespace atom { + +namespace api { + +namespace { + +v8::Persistent template_; + +} // namespace + +NativeImage::NativeImage(const gfx::Image& image) : image_(image) {} + +NativeImage::~NativeImage() {} + +mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + if (template_.IsEmpty()) + template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) + .SetMethod("toPng", &NativeImage::ToPNG) + .Build()); + + return mate::ObjectTemplateBuilder( + isolate, v8::Local::New(isolate, template_)); +} + +v8::Handle NativeImage::ToPNG(v8::Isolate* isolate) { + scoped_refptr png = image_.As1xPNGBytes(); + return node::Buffer::New(isolate, + reinterpret_cast(png->front()), + png->size()); +} + +// static +mate::Handle NativeImage::Create(v8::Isolate* isolate, + const gfx::Image& image) { + return mate::CreateHandle(isolate, new NativeImage(image)); +} + +} // namespace api + +} // namespace atom + + +namespace { + +void Initialize(v8::Handle exports, v8::Handle unused, + v8::Handle context, void* priv) { +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_native_image, Initialize) diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h new file mode 100644 index 000000000000..4d1978e69e49 --- /dev/null +++ b/atom/common/api/atom_api_native_image.h @@ -0,0 +1,41 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_API_ATOM_API_NATIVE_IMAGE_H_ +#define ATOM_COMMON_API_ATOM_API_NATIVE_IMAGE_H_ + +#include "native_mate/handle.h" +#include "native_mate/wrappable.h" +#include "ui/gfx/image/image.h" + +namespace atom { + +namespace api { + +class NativeImage : public mate::Wrappable { + public: + static mate::Handle Create(v8::Isolate* isolate, + const gfx::Image& image); + + protected: + NativeImage(const gfx::Image& image); + virtual ~NativeImage(); + + // mate::Wrappable: + mate::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + + private: + v8::Handle ToPNG(v8::Isolate* isolate); + + gfx::Image image_; + + DISALLOW_COPY_AND_ASSIGN(NativeImage); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_COMMON_API_ATOM_API_NATIVE_IMAGE_H_ diff --git a/atom/common/native_mate_converters/image_converter.cc b/atom/common/native_mate_converters/image_converter.cc index 2c991b9236c0..baa79055b8b5 100644 --- a/atom/common/native_mate_converters/image_converter.cc +++ b/atom/common/native_mate_converters/image_converter.cc @@ -7,6 +7,7 @@ #include #include +#include "atom/common/api/atom_api_native_image.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "base/files/file_util.h" #include "base/strings/string_util.h" @@ -128,10 +129,7 @@ bool Converter::FromV8(v8::Isolate* isolate, v8::Handle Converter::ToV8(v8::Isolate* isolate, const gfx::Image& val) { - scoped_refptr png = val.As1xPNGBytes(); - return node::Buffer::New(isolate, - reinterpret_cast(png->front()), - png->size()); + return ConvertToV8(isolate, atom::api::NativeImage::Create(isolate, val)); } } // namespace mate diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 20ac2b3d434d..7e9c8ffdc6bc 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -72,6 +72,7 @@ REFERENCE_MODULE(atom_common_asar); REFERENCE_MODULE(atom_common_clipboard); REFERENCE_MODULE(atom_common_crash_reporter); REFERENCE_MODULE(atom_common_id_weak_map); +REFERENCE_MODULE(atom_common_native_image); REFERENCE_MODULE(atom_common_screen); REFERENCE_MODULE(atom_common_shell); REFERENCE_MODULE(atom_common_v8_util); From 549df36f00d8bbb48f16a0dc6e4cb1199c79272b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 16:49:43 +0800 Subject: [PATCH 04/21] Add a few more methods for NativeImage --- atom/common/api/atom_api_native_image.cc | 12 ++++++++++++ atom/common/api/atom_api_native_image.h | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index def6d0917577..dc4b73771280 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -4,10 +4,12 @@ #include "atom/common/api/atom_api_native_image.h" +#include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/image_converter.h" #include "native_mate/constructor.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" +#include "ui/gfx/geometry/size.h" #include "atom/common/node_includes.h" @@ -30,6 +32,8 @@ mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder( if (template_.IsEmpty()) template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) .SetMethod("toPng", &NativeImage::ToPNG) + .SetMethod("isEmpty", &NativeImage::IsEmpty) + .SetMethod("getSize", &NativeImage::GetSize) .Build()); return mate::ObjectTemplateBuilder( @@ -43,6 +47,14 @@ v8::Handle NativeImage::ToPNG(v8::Isolate* isolate) { png->size()); } +bool NativeImage::IsEmpty() { + return image_.IsEmpty(); +} + +gfx::Size NativeImage::GetSize() { + return image_.Size(); +} + // static mate::Handle NativeImage::Create(v8::Isolate* isolate, const gfx::Image& image) { diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 4d1978e69e49..44bfbb784d4e 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 gfx { +class Size; +} + namespace atom { namespace api { @@ -28,6 +32,8 @@ class NativeImage : public mate::Wrappable { private: v8::Handle ToPNG(v8::Isolate* isolate); + bool IsEmpty(); + gfx::Size GetSize(); gfx::Image image_; From 53fca43d89a3cc0fdf8daa6cdc271a286dee228a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 17:47:54 +0800 Subject: [PATCH 05/21] Add NativeImage.ToJPEG --- atom/common/api/atom_api_native_image.cc | 10 ++++++++++ atom/common/api/atom_api_native_image.h | 1 + 2 files changed, 11 insertions(+) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index dc4b73771280..354e8a8fa8b4 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -10,6 +10,7 @@ #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image_util.h" #include "atom/common/node_includes.h" @@ -32,6 +33,7 @@ mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder( if (template_.IsEmpty()) template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) .SetMethod("toPng", &NativeImage::ToPNG) + .SetMethod("toJpeg", &NativeImage::ToJPEG) .SetMethod("isEmpty", &NativeImage::IsEmpty) .SetMethod("getSize", &NativeImage::GetSize) .Build()); @@ -47,6 +49,14 @@ v8::Handle NativeImage::ToPNG(v8::Isolate* isolate) { png->size()); } +v8::Handle NativeImage::ToJPEG(v8::Isolate* isolate, int quality) { + std::vector output; + gfx::JPEG1xEncodedDataFromImage(image_, quality, &output); + return node::Buffer::New(isolate, + reinterpret_cast(&output.front()), + output.size()); +} + bool NativeImage::IsEmpty() { return image_.IsEmpty(); } diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 44bfbb784d4e..3eea50d523f7 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -32,6 +32,7 @@ class NativeImage : public mate::Wrappable { private: v8::Handle ToPNG(v8::Isolate* isolate); + v8::Handle ToJPEG(v8::Isolate* isolate, int quality); bool IsEmpty(); gfx::Size GetSize(); From 85f5ef2ab1a7a0d1cde25ba93af8452bb2032416 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 18:02:59 +0800 Subject: [PATCH 06/21] Enable creating NativeImage from PNG and JPEG --- atom/common/api/atom_api_native_image.cc | 22 ++++++++++++++++++++-- atom/common/api/atom_api_native_image.h | 10 +++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 354e8a8fa8b4..22db4b8e22c6 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -66,11 +66,29 @@ gfx::Size NativeImage::GetSize() { } // static -mate::Handle NativeImage::Create(v8::Isolate* isolate, - const gfx::Image& image) { +mate::Handle NativeImage::Create( + v8::Isolate* isolate, const gfx::Image& image) { return mate::CreateHandle(isolate, new NativeImage(image)); } +// static +mate::Handle NativeImage::CreateFromPNG( + v8::Isolate* isolate, v8::Handle buffer) { + gfx::Image image = gfx::Image::CreateFrom1xPNGBytes( + reinterpret_cast(node::Buffer::Data(buffer)), + node::Buffer::Length(buffer)); + return Create(isolate, image); +} + +// static +mate::Handle NativeImage::CreateFromJPEG( + v8::Isolate* isolate, v8::Handle buffer) { + gfx::Image image = gfx::ImageFrom1xJPEGEncodedData( + reinterpret_cast(node::Buffer::Data(buffer)), + node::Buffer::Length(buffer)); + return Create(isolate, image); +} + } // namespace api } // namespace atom diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 3eea50d523f7..55d2686227a0 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -19,11 +19,15 @@ namespace api { class NativeImage : public mate::Wrappable { public: - static mate::Handle Create(v8::Isolate* isolate, - const gfx::Image& image); + static mate::Handle Create( + v8::Isolate* isolate, const gfx::Image& image); + static mate::Handle CreateFromPNG( + v8::Isolate* isolate, v8::Handle buffer); + static mate::Handle CreateFromJPEG( + v8::Isolate* isolate, v8::Handle buffer); protected: - NativeImage(const gfx::Image& image); + explicit NativeImage(const gfx::Image& image); virtual ~NativeImage(); // mate::Wrappable: From 2876f1506376e69582534ef7d3ba830bad7acc58 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 18:09:51 +0800 Subject: [PATCH 07/21] Enable creating NativeImage with native-image module --- atom.gyp | 1 + atom/common/api/atom_api_native_image.cc | 3 +++ atom/common/api/lib/native-image.coffee | 1 + 3 files changed, 5 insertions(+) create mode 100644 atom/common/api/lib/native-image.coffee diff --git a/atom.gyp b/atom.gyp index 3c161b45d119..75aedb4fac4a 100644 --- a/atom.gyp +++ b/atom.gyp @@ -38,6 +38,7 @@ 'atom/common/api/lib/clipboard.coffee', 'atom/common/api/lib/crash-reporter.coffee', 'atom/common/api/lib/id-weak-map.coffee', + 'atom/common/api/lib/native-image.coffee', 'atom/common/api/lib/original-fs.coffee', 'atom/common/api/lib/shell.coffee', 'atom/common/lib/init.coffee', diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 22db4b8e22c6..bb657335ced5 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -98,6 +98,9 @@ namespace { void Initialize(v8::Handle exports, v8::Handle unused, v8::Handle context, void* priv) { + mate::Dictionary dict(context->GetIsolate(), exports); + dict.SetMethod("createFromPng", &atom::api::NativeImage::CreateFromPNG); + dict.SetMethod("createFromJpeg", &atom::api::NativeImage::CreateFromJPEG); } } // namespace diff --git a/atom/common/api/lib/native-image.coffee b/atom/common/api/lib/native-image.coffee new file mode 100644 index 000000000000..c3cbb60ef030 --- /dev/null +++ b/atom/common/api/lib/native-image.coffee @@ -0,0 +1 @@ +module.exports = process.atomBinding 'native_image' From 6556602bdc008d1fb0d87b191f330f0b8a570b93 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 18:41:06 +0800 Subject: [PATCH 08/21] 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 From 054b6a98170ecdab5255943e6258bff7c4701dcb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 19:22:41 +0800 Subject: [PATCH 09/21] Use NativeImage when converting images from V8 --- atom.gyp | 1 - atom/common/api/atom_api_native_image.cc | 2 + atom/common/api/atom_api_native_image.h | 5 + .../native_mate_converters/image_converter.cc | 122 +++--------------- .../native_mate_converters/image_converter.h | 3 +- .../image_converter_mac.mm | 60 --------- 6 files changed, 27 insertions(+), 166 deletions(-) delete mode 100644 atom/common/native_mate_converters/image_converter_mac.mm diff --git a/atom.gyp b/atom.gyp index 9df90ef44a7b..a01d89fa9c7d 100644 --- a/atom.gyp +++ b/atom.gyp @@ -246,7 +246,6 @@ 'atom/common/native_mate_converters/gurl_converter.h', 'atom/common/native_mate_converters/image_converter.cc', 'atom/common/native_mate_converters/image_converter.h', - 'atom/common/native_mate_converters/image_converter_mac.mm', 'atom/common/native_mate_converters/string16_converter.h', 'atom/common/native_mate_converters/v8_value_converter.cc', 'atom/common/native_mate_converters/v8_value_converter.h', diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 955bfe7a84b8..84208e9ab62e 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -106,6 +106,8 @@ v8::Persistent template_; } // namespace +NativeImage::NativeImage() {} + NativeImage::NativeImage(const gfx::Image& image) : image_(image) {} NativeImage::~NativeImage() {} diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 7096ad93e0ef..e4417611aedc 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -32,6 +32,11 @@ class NativeImage : public mate::Wrappable { static mate::Handle CreateFromPath( v8::Isolate* isolate, const base::FilePath& path); + // The default constructor should only be used by image_converter.cc. + NativeImage(); + + const gfx::Image& image() const { return image_; } + protected: explicit NativeImage(const gfx::Image& image); virtual ~NativeImage(); diff --git a/atom/common/native_mate_converters/image_converter.cc b/atom/common/native_mate_converters/image_converter.cc index baa79055b8b5..ec5c50f31564 100644 --- a/atom/common/native_mate_converters/image_converter.cc +++ b/atom/common/native_mate_converters/image_converter.cc @@ -4,129 +4,45 @@ #include "atom/common/native_mate_converters/image_converter.h" -#include -#include - #include "atom/common/api/atom_api_native_image.h" #include "atom/common/native_mate_converters/file_path_converter.h" -#include "base/files/file_util.h" -#include "base/strings/string_util.h" -#include "ui/gfx/codec/jpeg_codec.h" -#include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" -#include "ui/base/layout.h" - -#include "atom/common/node_includes.h" namespace mate { -#if !defined(OS_MACOSX) - -namespace { - -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; -} - -} // namespace - bool Converter::FromV8(v8::Isolate* isolate, v8::Handle val, gfx::ImageSkia* out) { - if (val->IsNull()) - return true; - - base::FilePath path; - if (!Converter::FromV8(isolate, val, &path)) + gfx::Image image; + if (!ConvertFromV8(isolate, val, &image)) return false; - return PopulateImageSkiaRepsFromPath(out, path); + *out = image.AsImageSkia(); + return true; } bool Converter::FromV8(v8::Isolate* isolate, v8::Handle val, gfx::Image* out) { - gfx::ImageSkia image; - if (!ConvertFromV8(isolate, val, &image)) - return false; + if (val->IsNull()) + return true; - *out = gfx::Image(image); + Handle native_image; + if (!ConvertFromV8(isolate, val, &native_image)) { + // Try converting from file path. + base::FilePath path; + if (!Converter::FromV8(isolate, val, &path)) + return false; + + native_image = atom::api::NativeImage::CreateFromPath(isolate, path); + if (native_image->image().IsEmpty()) + return false; + } + + *out = native_image->image(); return true; } -#endif // !defined(OS_MACOSX) - v8::Handle Converter::ToV8(v8::Isolate* isolate, const gfx::Image& val) { return ConvertToV8(isolate, atom::api::NativeImage::Create(isolate, val)); diff --git a/atom/common/native_mate_converters/image_converter.h b/atom/common/native_mate_converters/image_converter.h index 1b1a12c3ae02..b19af32b4dea 100644 --- a/atom/common/native_mate_converters/image_converter.h +++ b/atom/common/native_mate_converters/image_converter.h @@ -26,8 +26,7 @@ struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, gfx::Image* out); - static v8::Handle ToV8(v8::Isolate* isolate, - const gfx::Image& val); + static v8::Handle ToV8(v8::Isolate* isolate, const gfx::Image& val); }; } // namespace mate diff --git a/atom/common/native_mate_converters/image_converter_mac.mm b/atom/common/native_mate_converters/image_converter_mac.mm deleted file mode 100644 index 67871ee32f30..000000000000 --- a/atom/common/native_mate_converters/image_converter_mac.mm +++ /dev/null @@ -1,60 +0,0 @@ -// 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/native_mate_converters/image_converter.h" - -#import - -#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 { - -bool IsTemplateImage(const std::string& path) { - return (MatchPattern(path, "*Template.*") || - MatchPattern(path, "*Template@*x.*")); -} - -} // namespace - -namespace mate { - -bool Converter::FromV8(v8::Isolate* isolate, - v8::Handle val, - gfx::ImageSkia* out) { - gfx::Image image; - if (!ConvertFromV8(isolate, val, &image)) - return false; - - *out = image.AsImageSkia(); - return true; -} - -bool Converter::FromV8(v8::Isolate* isolate, - v8::Handle val, - gfx::Image* out) { - if (val->IsNull()) - return true; - - std::string path; - if (!ConvertFromV8(isolate, val, &path)) - return false; - - base::scoped_nsobject image([[NSImage alloc] - initByReferencingFile:base::SysUTF8ToNSString(path)]); - if (![image isValid]) - return false; - - if (IsTemplateImage(path)) - [image setTemplate:YES]; - - *out = gfx::Image(image.release()); - return true; -} - -} // namespace mate From 2ca6be69e21b26b6796721da35dc31175d2e8529 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 21:59:08 +0800 Subject: [PATCH 10/21] Fix cpplint warnings --- atom/common/api/atom_api_native_image.cc | 4 +++- atom/common/native_mate_converters/image_converter.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 84208e9ab62e..32b8823fc88c 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -4,11 +4,13 @@ #include "atom/common/api/atom_api_native_image.h" +#include +#include + #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gfx_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" diff --git a/atom/common/native_mate_converters/image_converter.h b/atom/common/native_mate_converters/image_converter.h index b19af32b4dea..1b1a12c3ae02 100644 --- a/atom/common/native_mate_converters/image_converter.h +++ b/atom/common/native_mate_converters/image_converter.h @@ -26,7 +26,8 @@ struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, gfx::Image* out); - static v8::Handle ToV8(v8::Isolate* isolate, const gfx::Image& val); + static v8::Handle ToV8(v8::Isolate* isolate, + const gfx::Image& val); }; } // namespace mate From 903ff0b61a6b07b67ff9009e82fdb309f69edeec Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Feb 2015 22:10:09 +0800 Subject: [PATCH 11/21] Upgrade native_mate for security check --- vendor/native_mate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/native_mate b/vendor/native_mate index 1116a36c15ac..3387f33a8e7b 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 1116a36c15ac3e65720cf12d38a3308f40f7ea58 +Subproject commit 3387f33a8e7b4107f4268dec2a72a3fa943d706c From 509ce0d5cb80d7ec46357c56536665f24e253839 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 12:24:18 +0800 Subject: [PATCH 12/21] mac: Don't rely on NSImage to read file It doesn't work with asar. --- atom/common/api/atom_api_native_image.cc | 18 ++++++++++---- atom/common/api/atom_api_native_image.h | 5 ++++ atom/common/api/atom_api_native_image_mac.mm | 26 ++------------------ 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 32b8823fc88c..821417d524c1 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -28,7 +28,6 @@ namespace api { namespace { -#if !defined(OS_MACOSX) struct ScaleFactorPair { const char* name; float scale; @@ -102,7 +101,13 @@ bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image, pair.scale); return succeed; } -#endif // !defined(OS_MACOSX) + +#if defined(OS_MACOSX) +bool IsTemplateImage(const base::FilePath& path) { + return (MatchPattern(path.value(), "*Template.*") || + MatchPattern(path.value(), "*Template@*x.*")); +} +#endif v8::Persistent template_; @@ -175,15 +180,18 @@ 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)); + gfx::Image image(image_skia); +#if defined(OS_MACOSX) + if (IsTemplateImage(path)) + MakeTemplateImage(&image); +#endif + return Create(isolate, image); } -#endif // !defined(OS_MACOSX) } // namespace api diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index e4417611aedc..615ac0762fb1 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -46,6 +46,11 @@ class NativeImage : public mate::Wrappable { v8::Isolate* isolate) override; private: +#if defined(OS_MACOSX) + // Mark the image as template image if possible. + static void MakeTemplateImage(gfx::Image* image); +#endif + v8::Handle ToPNG(v8::Isolate* isolate); v8::Handle ToJPEG(v8::Isolate* isolate, int quality); bool IsEmpty(); diff --git a/atom/common/api/atom_api_native_image_mac.mm b/atom/common/api/atom_api_native_image_mac.mm index f4d7e7d496ae..67d16d2e820b 100644 --- a/atom/common/api/atom_api_native_image_mac.mm +++ b/atom/common/api/atom_api_native_image_mac.mm @@ -6,35 +6,13 @@ #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())); +void NativeImage::MakeTemplateImage(gfx::Image* image) { + [image->AsNSImage() setTemplate:YES]; } } // namespace api From 443a4b8f2f379690dfb3e63d7e8bb50646aa826e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 12:29:21 +0800 Subject: [PATCH 13/21] mac: Use AsNSImage instead of ToNSImage It can get rid of the empty check. --- atom/browser/ui/tray_icon_cocoa.mm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 408ba29a14e0..db2508ecc6a4 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -54,13 +54,11 @@ TrayIconCocoa::~TrayIconCocoa() { } void TrayIconCocoa::SetImage(const gfx::Image& image) { - if (!image.IsEmpty()) - [item_ setImage:image.ToNSImage()]; + [item_ setImage:image.AsNSImage()]; } void TrayIconCocoa::SetPressedImage(const gfx::Image& image) { - if (!image.IsEmpty()) - [item_ setAlternateImage:image.ToNSImage()]; + [item_ setAlternateImage:image.AsNSImage()]; } void TrayIconCocoa::SetToolTip(const std::string& tool_tip) { From da407200d2b2ac73122f41fa74ddedb0665801de Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 12:58:11 +0800 Subject: [PATCH 14/21] Return NativeImage in BrowserWindow.capturePage --- atom/browser/api/atom_api_window.cc | 10 +++------- vendor/native_mate | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 81a2d37305ff..4dd7803178e3 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -52,15 +52,11 @@ namespace { void OnCapturePageDone( v8::Isolate* isolate, - const base::Callback)>& callback, + const base::Callback& callback, const std::vector& data) { v8::Locker locker(isolate); v8::HandleScope handle_scope(isolate); - - v8::Local buffer = node::Buffer::New( - reinterpret_cast(data.data()), - data.size()); - callback.Run(buffer); + callback.Run(gfx::Image::CreateFrom1xPNGBytes(&data.front(), data.size())); } } // namespace @@ -374,7 +370,7 @@ bool Window::IsDocumentEdited() { void Window::CapturePage(mate::Arguments* args) { gfx::Rect rect; - base::Callback)> callback; + base::Callback callback; if (!(args->Length() == 1 && args->GetNext(&callback)) && !(args->Length() == 2 && args->GetNext(&rect) diff --git a/vendor/native_mate b/vendor/native_mate index 3387f33a8e7b..8d537ee2b6da 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 3387f33a8e7b4107f4268dec2a72a3fa943d706c +Subproject commit 8d537ee2b6da29c1aa38928590d4c56700e1c69b From 8093300a439f1aaf7890ae1f70324a8150e35a1f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 13:52:28 +0800 Subject: [PATCH 15/21] docs: Use NativeImage to replace Image --- docs/README.md | 1 + docs/api/browser-window.md | 15 ++++--- docs/api/dialog.md | 2 +- docs/api/{image.md => native-image.md} | 60 +++++++++++++++++++++++--- docs/api/tray.md | 8 ++-- 5 files changed, 68 insertions(+), 18 deletions(-) rename docs/api/{image.md => native-image.md} (56%) diff --git a/docs/README.md b/docs/README.md index 0d00200def5c..474883f9ef35 100644 --- a/docs/README.md +++ b/docs/README.md @@ -46,6 +46,7 @@ Modules for both sides: * [clipboard](api/clipboard.md) * [crash-reporter](api/crash-reporter.md) +* [native-image](api/native-image.md) * [screen](api/screen.md) * [shell](api/shell.md) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 24865e25c229..74452282ce24 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -43,13 +43,13 @@ You can also create a window without chrome by using other windows * `fullscreen` Boolean - Whether the window should show in fullscreen, when set to `false` the fullscreen button would also be hidden on OS X - * `skip-taskbar` Boolean - Do not show window in taskbar + * `skip-taskbar` Boolean - Do not show window in Taskbar * `zoom-factor` Number - The default zoom factor of the page, zoom factor is zoom percent / 100, so `3.0` represents `300%` * `kiosk` Boolean - The kiosk mode * `title` String - Default window title - * `icon` [Image](image.md) - The window icon, when omitted on Windows the - executable's icon would be used as window icon + * `icon` [NativeImage](native-image.md) - The window icon, when omitted on + Windows the executable's icon would be used as window icon * `show` Boolean - Whether window should be shown when created * `frame` Boolean - Specify `false` to create a [Frameless Window](frameless-window.md) @@ -415,7 +415,7 @@ Starts or stops flashing the window to attract user's attention. * `skip` Boolean -Makes the window do not show in taskbar. +Makes the window do not show in Taskbar. ### BrowserWindow.setKiosk(flag) @@ -545,8 +545,11 @@ it will assume `app.getName().desktop`. ### BrowserWindow.setOverlayIcon(overlay, description) -* `overlay` [Image](image.md) - the icon to display on the bottom right corner of the Taskbar icon. If this parameter is `null`, the overlay is cleared. -* `description` String - a description that will be provided to Accessibility screenreaders +* `overlay` [NativeImage](native-image.md) - the icon to display on the bottom +right corner of the Taskbar icon. If this parameter is `null`, the overlay is +cleared +* `description` String - a description that will be provided to Accessibility +screen readers Sets a 16px overlay onto the current Taskbar icon, usually used to convey some sort of application status or to passively notify the user. diff --git a/docs/api/dialog.md b/docs/api/dialog.md index a0e29f4fd9a1..f7ba10245204 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -76,7 +76,7 @@ would be passed via `callback(filename)` * `title` String - Title of the message box, some platforms will not show it * `message` String - Content of the message box * `detail` String - Extra information of the message - * `icon` [Image](image.md) + * `icon` [NativeImage](native-image.md) * `callback` Function Shows a message box, it will block until the message box is closed. It returns diff --git a/docs/api/image.md b/docs/api/native-image.md similarity index 56% rename from docs/api/image.md rename to docs/api/native-image.md index d7cf8aeea733..6ce260e89932 100644 --- a/docs/api/image.md +++ b/docs/api/native-image.md @@ -1,7 +1,7 @@ -# Image +# NativeImage -In atom-shell images are represented by their file paths, we currently do not -support in-memory images or remote images. +In atom-shell for the APIs that take images, you can pass either file paths or +`NativeImage` instances. When passing `null`, an empty image will be used. For example when creating tray or setting window's icon, you can pass image's file path as `String` to represent an image: @@ -11,12 +11,18 @@ var appIcon = new Tray('/Users/somebody/images/icon.png'); var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'}); ``` +Or read the image from clipboard: + +```javascript +var clipboard = require('clipboard'); +var image = clipboard.readImage(); +var appIcon = new Tray(image); +``` + ## Supported formats -On Mac all formats supported by the system can be used, while on Linux and -Windows only `PNG` and `JPG` formats are supported. - -So it is recommended to use `PNG` images for all cases. +Currently `PNG` and `JPEG` are supported, and it is recommended to use `PNG` +because it supports alpha channel and image is usually not compressed. ## High resolution image @@ -73,3 +79,43 @@ To mark an image as template image, its filename should end with the word * `xxxTemplate.png` * `xxxTemplate@2x.png` + +## nativeImage.createFromPng(buffer) + +* `buffer` [Buffer][buffer] + +Creates a new `NativeImage` instance from `buffer` with `PNG` format. + +## nativeImage.createFromPng(buffer) + +* `buffer` [Buffer][buffer] + +Creates a new `NativeImage` instance from `buffer` with `JPEG` format. + +## nativeImage.createFromPath(path) + +* `path` String + +Creates a new `NativeImage` instance from file located at `path`. + +## Class: NativeImage + +This class is used to represent an image. + +### NativeImage.toPng() + +Returns a [Buffer][buffer] that contains image's `PNG` encoded data. + +### NativeImage.isJpeg() + +Returns a [Buffer][buffer] that contains image's `JPEG` encoded data. + +### NativeImage.isEmpty() + +Returns whether the image is empty. + +### NativeImage.getSize() + +Returns the size of the image. + +[buffer]: https://iojs.org/api/buffer.html#buffer_class_buffer diff --git a/docs/api/tray.md b/docs/api/tray.md index d18b3b8ff1a2..64193d7ad05f 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -40,7 +40,7 @@ rely on `clicked` event and always attach a context menu to the tray icon. ### new Tray(image) -* `image` [Image](image.md) +* `image` [NativeImage](native-image.md) Creates a new tray icon associated with the `image`. @@ -79,13 +79,13 @@ Destroys the tray icon immediately. ### Tray.setImage(image) -* `image` [Image](image.md) +* `image` [NativeImage](native-image.md) Sets the `image` associated with this tray icon. ### Tray.setPressedImage(image) -* `image` [Image](image.md) +* `image` [NativeImage](native-image.md) Sets the `image` associated with this tray icon when pressed. @@ -114,7 +114,7 @@ This is only implmented on OS X. ### Tray.displayBalloon(options) * `options` Object - * `icon` [Image](image.md) + * `icon` [NativeImage](native-image.md) * `title` String * `content` String From b9f6d6dffc75b20d6d660a02b3908f0ae174124a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 13:55:45 +0800 Subject: [PATCH 16/21] Add nativeImage.createEmpty() --- atom/common/api/atom_api_native_image.cc | 6 ++++++ atom/common/api/atom_api_native_image.h | 1 + docs/api/native-image.md | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 821417d524c1..e74d681cc0b8 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -156,6 +156,11 @@ gfx::Size NativeImage::GetSize() { return image_.Size(); } +// static +mate::Handle NativeImage::CreateEmpty(v8::Isolate* isolate) { + return mate::CreateHandle(isolate, new NativeImage); +} + // static mate::Handle NativeImage::Create( v8::Isolate* isolate, const gfx::Image& image) { @@ -203,6 +208,7 @@ namespace { void Initialize(v8::Handle exports, v8::Handle unused, v8::Handle context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); + dict.SetMethod("createEmpty", &atom::api::NativeImage::CreateEmpty); dict.SetMethod("createFromPng", &atom::api::NativeImage::CreateFromPNG); dict.SetMethod("createFromJpeg", &atom::api::NativeImage::CreateFromJPEG); dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath); diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 615ac0762fb1..33c020f21ad2 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -23,6 +23,7 @@ namespace api { class NativeImage : public mate::Wrappable { public: + static mate::Handle CreateEmpty(v8::Isolate* isolate); static mate::Handle Create( v8::Isolate* isolate, const gfx::Image& image); static mate::Handle CreateFromPNG( diff --git a/docs/api/native-image.md b/docs/api/native-image.md index 6ce260e89932..e38f9abd35be 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -80,6 +80,10 @@ To mark an image as template image, its filename should end with the word * `xxxTemplate.png` * `xxxTemplate@2x.png` +## nativeImage.createEmpty() + +Creates a new `NativeImage` instance that contains empty image. + ## nativeImage.createFromPng(buffer) * `buffer` [Buffer][buffer] From 8e94856cc88bcb86cc8adc335eee5bcdf5a3d0f2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 14:27:53 +0800 Subject: [PATCH 17/21] Add nativeImage.createFromDataUrl() --- atom/common/api/atom_api_native_image.cc | 30 +++++++++++++++++------- atom/common/api/atom_api_native_image.h | 8 +++++-- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index e74d681cc0b8..44c0ae309df5 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -9,10 +9,12 @@ #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/gurl_converter.h" #include "base/files/file_util.h" #include "base/strings/string_util.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" +#include "net/base/data_url.h" #include "ui/base/layout.h" #include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/codec/png_codec.h" @@ -169,19 +171,17 @@ mate::Handle NativeImage::Create( // static mate::Handle NativeImage::CreateFromPNG( - v8::Isolate* isolate, v8::Handle buffer) { + v8::Isolate* isolate, const char* buffer, size_t length) { gfx::Image image = gfx::Image::CreateFrom1xPNGBytes( - reinterpret_cast(node::Buffer::Data(buffer)), - node::Buffer::Length(buffer)); + reinterpret_cast(buffer), length); return Create(isolate, image); } // static mate::Handle NativeImage::CreateFromJPEG( - v8::Isolate* isolate, v8::Handle buffer) { + v8::Isolate* isolate, const char* buffer, size_t length) { gfx::Image image = gfx::ImageFrom1xJPEGEncodedData( - reinterpret_cast(node::Buffer::Data(buffer)), - node::Buffer::Length(buffer)); + reinterpret_cast(buffer), length); return Create(isolate, image); } @@ -198,6 +198,20 @@ mate::Handle NativeImage::CreateFromPath( return Create(isolate, image); } +// static +mate::Handle NativeImage::CreateFromDataURL( + v8::Isolate* isolate, const GURL& url) { + std::string mime_type, charset, data; + if (net::DataURL::Parse(url, &mime_type, &charset, &data)) { + if (mime_type == "image/png") + return CreateFromPNG(isolate, data.c_str(), data.size()); + else if (mime_type == "image/jpeg") + return CreateFromJPEG(isolate, data.c_str(), data.size()); + } + + return CreateEmpty(isolate); +} + } // namespace api } // namespace atom @@ -209,9 +223,9 @@ void Initialize(v8::Handle exports, v8::Handle unused, v8::Handle context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("createEmpty", &atom::api::NativeImage::CreateEmpty); - dict.SetMethod("createFromPng", &atom::api::NativeImage::CreateFromPNG); - dict.SetMethod("createFromJpeg", &atom::api::NativeImage::CreateFromJPEG); dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath); + dict.SetMethod("createFromDataUrl", + &atom::api::NativeImage::CreateFromDataURL); } } // namespace diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 33c020f21ad2..2104a305f032 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -9,6 +9,8 @@ #include "native_mate/wrappable.h" #include "ui/gfx/image/image.h" +class GURL; + namespace base { class FilePath; } @@ -27,11 +29,13 @@ class NativeImage : public mate::Wrappable { static mate::Handle Create( v8::Isolate* isolate, const gfx::Image& image); static mate::Handle CreateFromPNG( - v8::Isolate* isolate, v8::Handle buffer); + v8::Isolate* isolate, const char* buffer, size_t length); static mate::Handle CreateFromJPEG( - v8::Isolate* isolate, v8::Handle buffer); + v8::Isolate* isolate, const char* buffer, size_t length); static mate::Handle CreateFromPath( v8::Isolate* isolate, const base::FilePath& path); + static mate::Handle CreateFromDataURL( + v8::Isolate* isolate, const GURL& url); // The default constructor should only be used by image_converter.cc. NativeImage(); From 353b4852025bbf4a8e00538ddb7f9e4ab719862d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 14:32:51 +0800 Subject: [PATCH 18/21] Add NativeImage.toDataUrl() --- atom/common/api/atom_api_native_image.cc | 11 +++++++++++ atom/common/api/atom_api_native_image.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 44c0ae309df5..38bff3a6ade7 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -10,6 +10,7 @@ #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/gurl_converter.h" +#include "base/base64.h" #include "base/files/file_util.h" #include "base/strings/string_util.h" #include "native_mate/dictionary.h" @@ -127,6 +128,7 @@ mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder( template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) .SetMethod("toPng", &NativeImage::ToPNG) .SetMethod("toJpeg", &NativeImage::ToJPEG) + .SetMethod("toDataUrl", &NativeImage::ToDataURL) .SetMethod("isEmpty", &NativeImage::IsEmpty) .SetMethod("getSize", &NativeImage::GetSize) .Build()); @@ -150,6 +152,15 @@ v8::Handle NativeImage::ToJPEG(v8::Isolate* isolate, int quality) { output.size()); } +std::string NativeImage::ToDataURL() { + scoped_refptr png = image_.As1xPNGBytes(); + std::string data_url; + data_url.insert(data_url.end(), png->front(), png->front() + png->size()); + base::Base64Encode(data_url, &data_url); + data_url.insert(0, "data:image/png;base64,"); + return data_url; +} + bool NativeImage::IsEmpty() { return image_.IsEmpty(); } diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 2104a305f032..3c669004ef46 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -5,6 +5,8 @@ #ifndef ATOM_COMMON_API_ATOM_API_NATIVE_IMAGE_H_ #define ATOM_COMMON_API_ATOM_API_NATIVE_IMAGE_H_ +#include + #include "native_mate/handle.h" #include "native_mate/wrappable.h" #include "ui/gfx/image/image.h" @@ -58,6 +60,7 @@ class NativeImage : public mate::Wrappable { v8::Handle ToPNG(v8::Isolate* isolate); v8::Handle ToJPEG(v8::Isolate* isolate, int quality); + std::string ToDataURL(); bool IsEmpty(); gfx::Size GetSize(); From faf40457c58c9d9c8e98f5ab67490bbfedf8f163 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 14:37:32 +0800 Subject: [PATCH 19/21] spec: Fix BrowserWindow.capturePage --- spec/api-browser-window-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index fa4432b8df35..caf23b96e660 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -78,7 +78,7 @@ describe 'browser-window module', -> describe 'BrowserWindow.capturePage(rect, callback)', -> it 'calls the callback with a Buffer', (done) -> w.capturePage {x: 0, y: 0, width: 100, height: 100}, (image) -> - assert.equal image.constructor.name, 'Buffer' + assert.equal image.isEmpty(), true done() describe 'BrowserWindow.setSize(width, height)', -> From c8738a88a41ed6a0f07d415e742e6e186b432e5d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 15:19:05 +0800 Subject: [PATCH 20/21] Add nativeImage.createFromBuffer() --- atom/common/api/atom_api_native_image.cc | 38 +++++++++++++++++++----- atom/common/api/atom_api_native_image.h | 6 ++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 38bff3a6ade7..6b873fa7f55a 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -65,15 +65,9 @@ float GetScaleFactorFromPath(const base::FilePath& path) { } bool AddImageSkiaRep(gfx::ImageSkia* image, - const base::FilePath& path, + const unsigned char* data, + size_t size, 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. @@ -88,6 +82,19 @@ bool AddImageSkiaRep(gfx::ImageSkia* image, return true; } +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(); + return AddImageSkiaRep(image, data, size, scale_factor); +} + bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image, const base::FilePath& path) { bool succeed = false; @@ -209,6 +216,20 @@ mate::Handle NativeImage::CreateFromPath( return Create(isolate, image); } +// static +mate::Handle NativeImage::CreateFromBuffer( + mate::Arguments* args, v8::Handle buffer) { + double scale_factor = 1.; + args->GetNext(&scale_factor); + + gfx::ImageSkia image_skia; + AddImageSkiaRep(&image_skia, + reinterpret_cast(node::Buffer::Data(buffer)), + node::Buffer::Length(buffer), + scale_factor); + return Create(args->isolate(), gfx::Image(image_skia)); +} + // static mate::Handle NativeImage::CreateFromDataURL( v8::Isolate* isolate, const GURL& url) { @@ -235,6 +256,7 @@ void Initialize(v8::Handle exports, v8::Handle unused, mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("createEmpty", &atom::api::NativeImage::CreateEmpty); dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath); + dict.SetMethod("createFromBuffer", &atom::api::NativeImage::CreateFromBuffer); dict.SetMethod("createFromDataUrl", &atom::api::NativeImage::CreateFromDataURL); } diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 3c669004ef46..fab93efc7021 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -21,6 +21,10 @@ namespace gfx { class Size; } +namespace mate { +class Arguments; +} + namespace atom { namespace api { @@ -36,6 +40,8 @@ class NativeImage : public mate::Wrappable { v8::Isolate* isolate, const char* buffer, size_t length); static mate::Handle CreateFromPath( v8::Isolate* isolate, const base::FilePath& path); + static mate::Handle CreateFromBuffer( + mate::Arguments* args, v8::Handle buffer); static mate::Handle CreateFromDataURL( v8::Isolate* isolate, const GURL& url); From 06d681c66ad41699e3b3503f9743ba015bd9bbf9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Feb 2015 15:38:16 +0800 Subject: [PATCH 21/21] docs: Update NativeImage --- docs/api/native-image.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/api/native-image.md b/docs/api/native-image.md index e38f9abd35be..de46ad1c4c4d 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -82,19 +82,7 @@ To mark an image as template image, its filename should end with the word ## nativeImage.createEmpty() -Creates a new `NativeImage` instance that contains empty image. - -## nativeImage.createFromPng(buffer) - -* `buffer` [Buffer][buffer] - -Creates a new `NativeImage` instance from `buffer` with `PNG` format. - -## nativeImage.createFromPng(buffer) - -* `buffer` [Buffer][buffer] - -Creates a new `NativeImage` instance from `buffer` with `JPEG` format. +Creates an empty `NativeImage` instance. ## nativeImage.createFromPath(path) @@ -102,6 +90,20 @@ Creates a new `NativeImage` instance from `buffer` with `JPEG` format. Creates a new `NativeImage` instance from file located at `path`. +## nativeImage.createFromBuffer(buffer[, scaleFactor]) + +* `buffer` [Buffer][buffer] +* `scaleFactor` Double + +Creates a new `NativeImage` instance from `buffer`. The `scaleFactor` is 1.0 by +default. + +## nativeImage.createFromDataUrl(dataUrl) + +* `dataUrl` String + +Creates a new `NativeImage` instance from `dataUrl`. + ## Class: NativeImage This class is used to represent an image. @@ -110,10 +112,16 @@ This class is used to represent an image. Returns a [Buffer][buffer] that contains image's `PNG` encoded data. -### NativeImage.isJpeg() +### NativeImage.toJpeg(quality) + +* `quality` Integer Returns a [Buffer][buffer] that contains image's `JPEG` encoded data. +### NativeImage.toDataUrl() + +Returns the data URL of image. + ### NativeImage.isEmpty() Returns whether the image is empty.