Merge pull request #1128 from atom/native-image

Introduce NativeImage
This commit is contained in:
Cheng Zhao 2015-02-12 16:48:42 +08:00
commit 64622ceae3
20 changed files with 499 additions and 195 deletions

View file

@ -38,6 +38,7 @@
'atom/common/api/lib/clipboard.coffee', 'atom/common/api/lib/clipboard.coffee',
'atom/common/api/lib/crash-reporter.coffee', 'atom/common/api/lib/crash-reporter.coffee',
'atom/common/api/lib/id-weak-map.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/original-fs.coffee',
'atom/common/api/lib/shell.coffee', 'atom/common/api/lib/shell.coffee',
'atom/common/lib/init.coffee', 'atom/common/lib/init.coffee',
@ -204,6 +205,9 @@
'atom/common/api/atom_api_crash_reporter.cc', '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.cc',
'atom/common/api/atom_api_id_weak_map.h', '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_shell.cc',
'atom/common/api/atom_api_v8_util.cc', 'atom/common/api/atom_api_v8_util.cc',
'atom/common/api/atom_bindings.cc', 'atom/common/api/atom_bindings.cc',
@ -242,7 +246,6 @@
'atom/common/native_mate_converters/gurl_converter.h', 'atom/common/native_mate_converters/gurl_converter.h',
'atom/common/native_mate_converters/image_converter.cc', 'atom/common/native_mate_converters/image_converter.cc',
'atom/common/native_mate_converters/image_converter.h', '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/string16_converter.h',
'atom/common/native_mate_converters/v8_value_converter.cc', 'atom/common/native_mate_converters/v8_value_converter.cc',
'atom/common/native_mate_converters/v8_value_converter.h', 'atom/common/native_mate_converters/v8_value_converter.h',

View file

@ -52,15 +52,11 @@ namespace {
void OnCapturePageDone( void OnCapturePageDone(
v8::Isolate* isolate, v8::Isolate* isolate,
const base::Callback<void(v8::Handle<v8::Value>)>& callback, const base::Callback<void(const gfx::Image&)>& callback,
const std::vector<unsigned char>& data) { const std::vector<unsigned char>& data) {
v8::Locker locker(isolate); v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
callback.Run(gfx::Image::CreateFrom1xPNGBytes(&data.front(), data.size()));
v8::Local<v8::Value> buffer = node::Buffer::New(
reinterpret_cast<const char*>(data.data()),
data.size());
callback.Run(buffer);
} }
} // namespace } // namespace
@ -374,7 +370,7 @@ bool Window::IsDocumentEdited() {
void Window::CapturePage(mate::Arguments* args) { void Window::CapturePage(mate::Arguments* args) {
gfx::Rect rect; gfx::Rect rect;
base::Callback<void(v8::Handle<v8::Value>)> callback; base::Callback<void(const gfx::Image&)> callback;
if (!(args->Length() == 1 && args->GetNext(&callback)) && if (!(args->Length() == 1 && args->GetNext(&callback)) &&
!(args->Length() == 2 && args->GetNext(&rect) !(args->Length() == 2 && args->GetNext(&rect)

View file

@ -54,13 +54,11 @@ TrayIconCocoa::~TrayIconCocoa() {
} }
void TrayIconCocoa::SetImage(const gfx::Image& image) { void TrayIconCocoa::SetImage(const gfx::Image& image) {
if (!image.IsEmpty()) [item_ setImage:image.AsNSImage()];
[item_ setImage:image.ToNSImage()];
} }
void TrayIconCocoa::SetPressedImage(const gfx::Image& image) { void TrayIconCocoa::SetPressedImage(const gfx::Image& image) {
if (!image.IsEmpty()) [item_ setAlternateImage:image.AsNSImage()];
[item_ setAlternateImage:image.ToNSImage()];
} }
void TrayIconCocoa::SetToolTip(const std::string& tool_tip) { void TrayIconCocoa::SetToolTip(const std::string& tool_tip) {

View file

@ -5,10 +5,13 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/string16_converter.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/gfx/image/image.h"
#include "atom/common/node_includes.h" #include "atom/common/node_includes.h"
@ -16,8 +19,7 @@ namespace mate {
template<> template<>
struct Converter<ui::ClipboardType> { struct Converter<ui::ClipboardType> {
static bool FromV8(v8::Isolate* isolate, static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
v8::Handle<v8::Value> val,
ui::ClipboardType* out) { ui::ClipboardType* out) {
std::string type; std::string type;
if (!Converter<std::string>::FromV8(isolate, val, &type)) if (!Converter<std::string>::FromV8(isolate, val, &type))
@ -62,6 +64,11 @@ void WriteText(const base::string16& text, ui::ClipboardType type) {
writer.WriteText(text); 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) { void Clear(ui::ClipboardType type) {
ui::Clipboard::GetForCurrentThread()->Clear(type); ui::Clipboard::GetForCurrentThread()->Clear(type);
} }
@ -73,6 +80,7 @@ void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
dict.SetMethod("_read", &Read); dict.SetMethod("_read", &Read);
dict.SetMethod("_readText", &ReadText); dict.SetMethod("_readText", &ReadText);
dict.SetMethod("_writeText", &WriteText); dict.SetMethod("_writeText", &WriteText);
dict.SetMethod("_readImage", &ReadImage);
dict.SetMethod("_clear", &Clear); dict.SetMethod("_clear", &Clear);
} }

View file

@ -0,0 +1,266 @@
// 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 <string>
#include <vector>
#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"
#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"
#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"
namespace atom {
namespace api {
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 unsigned char* data,
size_t size,
double scale_factor) {
scoped_ptr<SkBitmap> 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 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<const unsigned char*>(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;
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;
}
#if defined(OS_MACOSX)
bool IsTemplateImage(const base::FilePath& path) {
return (MatchPattern(path.value(), "*Template.*") ||
MatchPattern(path.value(), "*Template@*x.*"));
}
#endif
v8::Persistent<v8::ObjectTemplate> template_;
} // namespace
NativeImage::NativeImage() {}
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)
.SetMethod("toJpeg", &NativeImage::ToJPEG)
.SetMethod("toDataUrl", &NativeImage::ToDataURL)
.SetMethod("isEmpty", &NativeImage::IsEmpty)
.SetMethod("getSize", &NativeImage::GetSize)
.Build());
return mate::ObjectTemplateBuilder(
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
}
v8::Handle<v8::Value> NativeImage::ToPNG(v8::Isolate* isolate) {
scoped_refptr<base::RefCountedMemory> png = image_.As1xPNGBytes();
return node::Buffer::New(isolate,
reinterpret_cast<const char*>(png->front()),
png->size());
}
v8::Handle<v8::Value> NativeImage::ToJPEG(v8::Isolate* isolate, int quality) {
std::vector<unsigned char> output;
gfx::JPEG1xEncodedDataFromImage(image_, quality, &output);
return node::Buffer::New(isolate,
reinterpret_cast<const char*>(&output.front()),
output.size());
}
std::string NativeImage::ToDataURL() {
scoped_refptr<base::RefCountedMemory> 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();
}
gfx::Size NativeImage::GetSize() {
return image_.Size();
}
// static
mate::Handle<NativeImage> NativeImage::CreateEmpty(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new NativeImage);
}
// static
mate::Handle<NativeImage> NativeImage::Create(
v8::Isolate* isolate, const gfx::Image& image) {
return mate::CreateHandle(isolate, new NativeImage(image));
}
// static
mate::Handle<NativeImage> NativeImage::CreateFromPNG(
v8::Isolate* isolate, const char* buffer, size_t length) {
gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
reinterpret_cast<const unsigned char*>(buffer), length);
return Create(isolate, image);
}
// static
mate::Handle<NativeImage> NativeImage::CreateFromJPEG(
v8::Isolate* isolate, const char* buffer, size_t length) {
gfx::Image image = gfx::ImageFrom1xJPEGEncodedData(
reinterpret_cast<const unsigned char*>(buffer), length);
return Create(isolate, image);
}
// static
mate::Handle<NativeImage> NativeImage::CreateFromPath(
v8::Isolate* isolate, const base::FilePath& path) {
gfx::ImageSkia image_skia;
PopulateImageSkiaRepsFromPath(&image_skia, path);
gfx::Image image(image_skia);
#if defined(OS_MACOSX)
if (IsTemplateImage(path))
MakeTemplateImage(&image);
#endif
return Create(isolate, image);
}
// static
mate::Handle<NativeImage> NativeImage::CreateFromBuffer(
mate::Arguments* args, v8::Handle<v8::Value> buffer) {
double scale_factor = 1.;
args->GetNext(&scale_factor);
gfx::ImageSkia image_skia;
AddImageSkiaRep(&image_skia,
reinterpret_cast<unsigned char*>(node::Buffer::Data(buffer)),
node::Buffer::Length(buffer),
scale_factor);
return Create(args->isolate(), gfx::Image(image_skia));
}
// static
mate::Handle<NativeImage> 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
namespace {
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context, void* priv) {
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);
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_native_image, Initialize)

View file

@ -0,0 +1,82 @@
// 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 <string>
#include "native_mate/handle.h"
#include "native_mate/wrappable.h"
#include "ui/gfx/image/image.h"
class GURL;
namespace base {
class FilePath;
}
namespace gfx {
class Size;
}
namespace mate {
class Arguments;
}
namespace atom {
namespace api {
class NativeImage : public mate::Wrappable {
public:
static mate::Handle<NativeImage> CreateEmpty(v8::Isolate* isolate);
static mate::Handle<NativeImage> Create(
v8::Isolate* isolate, const gfx::Image& image);
static mate::Handle<NativeImage> CreateFromPNG(
v8::Isolate* isolate, const char* buffer, size_t length);
static mate::Handle<NativeImage> CreateFromJPEG(
v8::Isolate* isolate, const char* buffer, size_t length);
static mate::Handle<NativeImage> CreateFromPath(
v8::Isolate* isolate, const base::FilePath& path);
static mate::Handle<NativeImage> CreateFromBuffer(
mate::Arguments* args, v8::Handle<v8::Value> buffer);
static mate::Handle<NativeImage> CreateFromDataURL(
v8::Isolate* isolate, const GURL& url);
// 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();
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
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<v8::Value> ToPNG(v8::Isolate* isolate);
v8::Handle<v8::Value> ToJPEG(v8::Isolate* isolate, int quality);
std::string ToDataURL();
bool IsEmpty();
gfx::Size GetSize();
gfx::Image image_;
DISALLOW_COPY_AND_ASSIGN(NativeImage);
};
} // namespace api
} // namespace atom
#endif // ATOM_COMMON_API_ATOM_API_NATIVE_IMAGE_H_

View file

@ -0,0 +1,20 @@
// 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 <Cocoa/Cocoa.h>
namespace atom {
namespace api {
// static
void NativeImage::MakeTemplateImage(gfx::Image* image) {
[image->AsNSImage() setTemplate:YES];
}
} // namespace api
} // namespace atom

View file

@ -9,4 +9,5 @@ else
read: (format, type='standard') -> binding._read format, type read: (format, type='standard') -> binding._read format, type
readText: (type='standard') -> binding._readText type readText: (type='standard') -> binding._readText type
writeText: (text, type='standard') -> binding._writeText text, type writeText: (text, type='standard') -> binding._writeText text, type
readImage: (type='standard') -> binding._readImage type
clear: (type='standard') -> binding._clear type clear: (type='standard') -> binding._clear type

View file

@ -0,0 +1 @@
module.exports = process.atomBinding 'native_image'

View file

@ -4,124 +4,48 @@
#include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/image_converter.h"
#include <string> #include "atom/common/api/atom_api_native_image.h"
#include <vector>
#include "atom/common/native_mate_converters/file_path_converter.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/gfx/image/image_skia.h"
#include "ui/base/layout.h"
#if !defined(OS_MACOSX)
namespace mate { namespace mate {
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<const unsigned char*>(file_contents.data());
size_t size = file_contents.size();
scoped_ptr<SkBitmap> 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<gfx::ImageSkia>::FromV8(v8::Isolate* isolate, bool Converter<gfx::ImageSkia>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val, v8::Handle<v8::Value> val,
gfx::ImageSkia* out) { gfx::ImageSkia* out) {
if (val->IsNull()) gfx::Image image;
return true; if (!ConvertFromV8(isolate, val, &image))
base::FilePath path;
if (!Converter<base::FilePath>::FromV8(isolate, val, &path))
return false; return false;
return PopulateImageSkiaRepsFromPath(out, path); *out = image.AsImageSkia();
return true;
} }
bool Converter<gfx::Image>::FromV8(v8::Isolate* isolate, bool Converter<gfx::Image>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val, v8::Handle<v8::Value> val,
gfx::Image* out) { gfx::Image* out) {
gfx::ImageSkia image; if (val->IsNull())
if (!ConvertFromV8(isolate, val, &image)) return true;
return false;
*out = gfx::Image(image); Handle<atom::api::NativeImage> native_image;
if (!ConvertFromV8(isolate, val, &native_image)) {
// Try converting from file path.
base::FilePath path;
if (!Converter<base::FilePath>::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; return true;
} }
} // namespace mate v8::Handle<v8::Value> Converter<gfx::Image>::ToV8(v8::Isolate* isolate,
const gfx::Image& val) {
return ConvertToV8(isolate, atom::api::NativeImage::Create(isolate, val));
}
#endif // !defined(OS_MACOSX) } // namespace mate

View file

@ -26,6 +26,8 @@ struct Converter<gfx::Image> {
static bool FromV8(v8::Isolate* isolate, static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val, v8::Handle<v8::Value> val,
gfx::Image* out); gfx::Image* out);
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::Image& val);
}; };
} // namespace mate } // namespace mate

View file

@ -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 <Cocoa/Cocoa.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 {
bool IsTemplateImage(const std::string& path) {
return (MatchPattern(path, "*Template.*") ||
MatchPattern(path, "*Template@*x.*"));
}
} // namespace
namespace mate {
bool Converter<gfx::ImageSkia>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::ImageSkia* out) {
gfx::Image image;
if (!ConvertFromV8(isolate, val, &image))
return false;
*out = image.AsImageSkia();
return true;
}
bool Converter<gfx::Image>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Image* out) {
if (val->IsNull())
return true;
std::string path;
if (!ConvertFromV8(isolate, val, &path))
return false;
base::scoped_nsobject<NSImage> 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

View file

@ -72,6 +72,7 @@ REFERENCE_MODULE(atom_common_asar);
REFERENCE_MODULE(atom_common_clipboard); REFERENCE_MODULE(atom_common_clipboard);
REFERENCE_MODULE(atom_common_crash_reporter); REFERENCE_MODULE(atom_common_crash_reporter);
REFERENCE_MODULE(atom_common_id_weak_map); REFERENCE_MODULE(atom_common_id_weak_map);
REFERENCE_MODULE(atom_common_native_image);
REFERENCE_MODULE(atom_common_screen); REFERENCE_MODULE(atom_common_screen);
REFERENCE_MODULE(atom_common_shell); REFERENCE_MODULE(atom_common_shell);
REFERENCE_MODULE(atom_common_v8_util); REFERENCE_MODULE(atom_common_v8_util);

View file

@ -46,6 +46,7 @@ Modules for both sides:
* [clipboard](api/clipboard.md) * [clipboard](api/clipboard.md)
* [crash-reporter](api/crash-reporter.md) * [crash-reporter](api/crash-reporter.md)
* [native-image](api/native-image.md)
* [screen](api/screen.md) * [screen](api/screen.md)
* [shell](api/shell.md) * [shell](api/shell.md)

View file

@ -43,13 +43,13 @@ You can also create a window without chrome by using
other windows other windows
* `fullscreen` Boolean - Whether the window should show in fullscreen, when * `fullscreen` Boolean - Whether the window should show in fullscreen, when
set to `false` the fullscreen button would also be hidden on OS X 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-factor` Number - The default zoom factor of the page, zoom factor is
zoom percent / 100, so `3.0` represents `300%` zoom percent / 100, so `3.0` represents `300%`
* `kiosk` Boolean - The kiosk mode * `kiosk` Boolean - The kiosk mode
* `title` String - Default window title * `title` String - Default window title
* `icon` [Image](image.md) - The window icon, when omitted on Windows the * `icon` [NativeImage](native-image.md) - The window icon, when omitted on
executable's icon would be used as window icon Windows the executable's icon would be used as window icon
* `show` Boolean - Whether window should be shown when created * `show` Boolean - Whether window should be shown when created
* `frame` Boolean - Specify `false` to create a * `frame` Boolean - Specify `false` to create a
[Frameless Window](frameless-window.md) [Frameless Window](frameless-window.md)
@ -415,7 +415,7 @@ Starts or stops flashing the window to attract user's attention.
* `skip` Boolean * `skip` Boolean
Makes the window do not show in taskbar. Makes the window do not show in Taskbar.
### BrowserWindow.setKiosk(flag) ### BrowserWindow.setKiosk(flag)
@ -545,8 +545,11 @@ it will assume `app.getName().desktop`.
### BrowserWindow.setOverlayIcon(overlay, description) ### 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. * `overlay` [NativeImage](native-image.md) - the icon to display on the bottom
* `description` String - a description that will be provided to Accessibility screenreaders 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. Sets a 16px overlay onto the current Taskbar icon, usually used to convey some sort of application status or to passively notify the user.

View file

@ -76,7 +76,7 @@ would be passed via `callback(filename)`
* `title` String - Title of the message box, some platforms will not show it * `title` String - Title of the message box, some platforms will not show it
* `message` String - Content of the message box * `message` String - Content of the message box
* `detail` String - Extra information of the message * `detail` String - Extra information of the message
* `icon` [Image](image.md) * `icon` [NativeImage](native-image.md)
* `callback` Function * `callback` Function
Shows a message box, it will block until the message box is closed. It returns Shows a message box, it will block until the message box is closed. It returns

View file

@ -1,7 +1,7 @@
# Image # NativeImage
In atom-shell images are represented by their file paths, we currently do not In atom-shell for the APIs that take images, you can pass either file paths or
support in-memory images or remote images. `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 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:
@ -11,12 +11,18 @@ 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'});
``` ```
Or read the image from clipboard:
```javascript
var clipboard = require('clipboard');
var image = clipboard.readImage();
var appIcon = new Tray(image);
```
## Supported formats ## Supported formats
On Mac all formats supported by the system can be used, while on Linux and Currently `PNG` and `JPEG` are supported, and it is recommended to use `PNG`
Windows only `PNG` and `JPG` formats are supported. because it supports alpha channel and image is usually not compressed.
So it is recommended to use `PNG` images for all cases.
## High resolution image ## High resolution image
@ -73,3 +79,55 @@ To mark an image as template image, its filename should end with the word
* `xxxTemplate.png` * `xxxTemplate.png`
* `xxxTemplate@2x.png` * `xxxTemplate@2x.png`
## nativeImage.createEmpty()
Creates an empty `NativeImage` instance.
## nativeImage.createFromPath(path)
* `path` String
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.
### NativeImage.toPng()
Returns a [Buffer][buffer] that contains image's `PNG` encoded data.
### 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.
### NativeImage.getSize()
Returns the size of the image.
[buffer]: https://iojs.org/api/buffer.html#buffer_class_buffer

View file

@ -40,7 +40,7 @@ rely on `clicked` event and always attach a context menu to the tray icon.
### new Tray(image) ### new Tray(image)
* `image` [Image](image.md) * `image` [NativeImage](native-image.md)
Creates a new tray icon associated with the `image`. Creates a new tray icon associated with the `image`.
@ -79,13 +79,13 @@ Destroys the tray icon immediately.
### Tray.setImage(image) ### Tray.setImage(image)
* `image` [Image](image.md) * `image` [NativeImage](native-image.md)
Sets the `image` associated with this tray icon. Sets the `image` associated with this tray icon.
### Tray.setPressedImage(image) ### Tray.setPressedImage(image)
* `image` [Image](image.md) * `image` [NativeImage](native-image.md)
Sets the `image` associated with this tray icon when pressed. Sets the `image` associated with this tray icon when pressed.
@ -114,7 +114,7 @@ This is only implmented on OS X.
### Tray.displayBalloon(options) ### Tray.displayBalloon(options)
* `options` Object * `options` Object
* `icon` [Image](image.md) * `icon` [NativeImage](native-image.md)
* `title` String * `title` String
* `content` String * `content` String

View file

@ -78,7 +78,7 @@ describe 'browser-window module', ->
describe 'BrowserWindow.capturePage(rect, callback)', -> describe 'BrowserWindow.capturePage(rect, callback)', ->
it 'calls the callback with a Buffer', (done) -> it 'calls the callback with a Buffer', (done) ->
w.capturePage {x: 0, y: 0, width: 100, height: 100}, (image) -> w.capturePage {x: 0, y: 0, width: 100, height: 100}, (image) ->
assert.equal image.constructor.name, 'Buffer' assert.equal image.isEmpty(), true
done() done()
describe 'BrowserWindow.setSize(width, height)', -> describe 'BrowserWindow.setSize(width, height)', ->

2
vendor/native_mate vendored

@ -1 +1 @@
Subproject commit 1116a36c15ac3e65720cf12d38a3308f40f7ea58 Subproject commit 8d537ee2b6da29c1aa38928590d4c56700e1c69b