@shqld/canvas 3.2.2-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +654 -0
- package/binding.gyp +229 -0
- package/browser.js +31 -0
- package/index.d.ts +507 -0
- package/index.js +94 -0
- package/lib/DOMMatrix.js +678 -0
- package/lib/bindings.js +113 -0
- package/lib/canvas.js +113 -0
- package/lib/context2d.js +11 -0
- package/lib/image.js +97 -0
- package/lib/jpegstream.js +41 -0
- package/lib/pattern.js +15 -0
- package/lib/pdfstream.js +35 -0
- package/lib/pngstream.js +42 -0
- package/package.json +77 -0
- package/scripts/install.js +19 -0
- package/src/Backends.h +9 -0
- package/src/Canvas.cc +1026 -0
- package/src/Canvas.h +128 -0
- package/src/CanvasError.h +37 -0
- package/src/CanvasGradient.cc +113 -0
- package/src/CanvasGradient.h +20 -0
- package/src/CanvasPattern.cc +129 -0
- package/src/CanvasPattern.h +33 -0
- package/src/CanvasRenderingContext2d.cc +3527 -0
- package/src/CanvasRenderingContext2d.h +238 -0
- package/src/CharData.h +233 -0
- package/src/FontParser.cc +605 -0
- package/src/FontParser.h +115 -0
- package/src/Image.cc +1719 -0
- package/src/Image.h +146 -0
- package/src/ImageData.cc +138 -0
- package/src/ImageData.h +26 -0
- package/src/InstanceData.h +12 -0
- package/src/JPEGStream.h +157 -0
- package/src/PNG.h +292 -0
- package/src/Point.h +11 -0
- package/src/Util.h +9 -0
- package/src/bmp/BMPParser.cc +459 -0
- package/src/bmp/BMPParser.h +60 -0
- package/src/bmp/LICENSE.md +24 -0
- package/src/closure.cc +52 -0
- package/src/closure.h +98 -0
- package/src/color.cc +796 -0
- package/src/color.h +30 -0
- package/src/dll_visibility.h +20 -0
- package/src/init.cc +114 -0
- package/src/register_font.cc +352 -0
- package/src/register_font.h +7 -0
- package/util/has_lib.js +119 -0
- package/util/win_jpeg_lookup.js +21 -0
package/src/Canvas.h
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
struct Closure;
|
|
6
|
+
struct PdfSvgClosure;
|
|
7
|
+
|
|
8
|
+
#include "closure.h"
|
|
9
|
+
#include <cairo.h>
|
|
10
|
+
#include "dll_visibility.h"
|
|
11
|
+
#include <napi.h>
|
|
12
|
+
#include <pango/pangocairo.h>
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <cstddef>
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* Canvas types.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
typedef enum {
|
|
21
|
+
CANVAS_TYPE_IMAGE,
|
|
22
|
+
CANVAS_TYPE_PDF,
|
|
23
|
+
CANVAS_TYPE_SVG
|
|
24
|
+
} canvas_type_t;
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/*
|
|
28
|
+
* FontFace describes a font file in terms of one PangoFontDescription that
|
|
29
|
+
* will resolve to it and one that the user describes it as (like @font-face)
|
|
30
|
+
*/
|
|
31
|
+
class FontFace {
|
|
32
|
+
public:
|
|
33
|
+
PangoFontDescription *sys_desc = nullptr;
|
|
34
|
+
PangoFontDescription *user_desc = nullptr;
|
|
35
|
+
unsigned char file_path[1024];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
enum text_baseline_t : uint8_t {
|
|
39
|
+
TEXT_BASELINE_ALPHABETIC = 0,
|
|
40
|
+
TEXT_BASELINE_TOP = 1,
|
|
41
|
+
TEXT_BASELINE_BOTTOM = 2,
|
|
42
|
+
TEXT_BASELINE_MIDDLE = 3,
|
|
43
|
+
TEXT_BASELINE_IDEOGRAPHIC = 4,
|
|
44
|
+
TEXT_BASELINE_HANGING = 5
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
enum text_align_t : int8_t {
|
|
48
|
+
TEXT_ALIGNMENT_LEFT = -1,
|
|
49
|
+
TEXT_ALIGNMENT_CENTER = 0,
|
|
50
|
+
TEXT_ALIGNMENT_RIGHT = 1,
|
|
51
|
+
TEXT_ALIGNMENT_START = -2,
|
|
52
|
+
TEXT_ALIGNMENT_END = 2
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
enum canvas_draw_mode_t : uint8_t {
|
|
56
|
+
TEXT_DRAW_PATHS,
|
|
57
|
+
TEXT_DRAW_GLYPHS
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* Canvas.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
class Canvas : public Napi::ObjectWrap<Canvas> {
|
|
65
|
+
public:
|
|
66
|
+
Canvas(const Napi::CallbackInfo& info);
|
|
67
|
+
~Canvas();
|
|
68
|
+
static void Initialize(Napi::Env& env, Napi::Object& target);
|
|
69
|
+
|
|
70
|
+
Napi::Value ToBuffer(const Napi::CallbackInfo& info);
|
|
71
|
+
Napi::Value GetType(const Napi::CallbackInfo& info);
|
|
72
|
+
Napi::Value GetStride(const Napi::CallbackInfo& info);
|
|
73
|
+
Napi::Value GetWidth(const Napi::CallbackInfo& info);
|
|
74
|
+
Napi::Value GetHeight(const Napi::CallbackInfo& info);
|
|
75
|
+
void SetWidth(const Napi::CallbackInfo& info, const Napi::Value& value);
|
|
76
|
+
void SetHeight(const Napi::CallbackInfo& info, const Napi::Value& value);
|
|
77
|
+
void StreamPNGSync(const Napi::CallbackInfo& info);
|
|
78
|
+
void StreamPDFSync(const Napi::CallbackInfo& info);
|
|
79
|
+
void StreamJPEGSync(const Napi::CallbackInfo& info);
|
|
80
|
+
static void RegisterFont(const Napi::CallbackInfo& info);
|
|
81
|
+
static void DeregisterAllFonts(const Napi::CallbackInfo& info);
|
|
82
|
+
static Napi::Value ParseFont(const Napi::CallbackInfo& info);
|
|
83
|
+
Napi::Error CairoError(cairo_status_t status);
|
|
84
|
+
static void ToPngBufferAsync(Closure* closure);
|
|
85
|
+
static void ToJpegBufferAsync(Closure* closure);
|
|
86
|
+
static PangoWeight GetWeightFromCSSString(const char *weight);
|
|
87
|
+
static PangoStyle GetStyleFromCSSString(const char *style);
|
|
88
|
+
static PangoFontDescription *ResolveFontDescription(const PangoFontDescription *desc);
|
|
89
|
+
|
|
90
|
+
inline bool isPDF() { return type == CANVAS_TYPE_PDF; }
|
|
91
|
+
inline bool isSVG() { return type == CANVAS_TYPE_SVG; }
|
|
92
|
+
inline bool isImage() { return type == CANVAS_TYPE_IMAGE; }
|
|
93
|
+
inline void *closure() { return _closure; }
|
|
94
|
+
|
|
95
|
+
cairo_t* createCairoContext();
|
|
96
|
+
|
|
97
|
+
DLL_PUBLIC inline uint8_t *data() { return cairo_image_surface_get_data(ensureSurface()); }
|
|
98
|
+
DLL_PUBLIC inline int stride() { return cairo_image_surface_get_stride(ensureSurface()); }
|
|
99
|
+
DLL_PUBLIC inline std::size_t nBytes() {
|
|
100
|
+
return static_cast<std::size_t>(height) * stride();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
DLL_PUBLIC inline uint16_t getWidth() { return width; }
|
|
104
|
+
DLL_PUBLIC inline uint16_t getHeight() { return height; }
|
|
105
|
+
|
|
106
|
+
uint8_t approxBytesPerPixel();
|
|
107
|
+
void setFormat(cairo_format_t format);
|
|
108
|
+
cairo_format_t getFormat();
|
|
109
|
+
void resurface(Napi::Object This, uint16_t width, uint16_t height);
|
|
110
|
+
cairo_surface_t *ensureSurface();
|
|
111
|
+
void destroySurface();
|
|
112
|
+
|
|
113
|
+
Napi::Env env;
|
|
114
|
+
static int fontSerial;
|
|
115
|
+
|
|
116
|
+
private:
|
|
117
|
+
|
|
118
|
+
cairo_surface_t *_surface;
|
|
119
|
+
PdfSvgClosure *_closure;
|
|
120
|
+
|
|
121
|
+
Napi::FunctionReference ctor;
|
|
122
|
+
static std::vector<FontFace> font_face_list;
|
|
123
|
+
|
|
124
|
+
uint16_t width;
|
|
125
|
+
uint16_t height;
|
|
126
|
+
canvas_type_t type;
|
|
127
|
+
cairo_format_t format;
|
|
128
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
|
|
6
|
+
class CanvasError {
|
|
7
|
+
public:
|
|
8
|
+
std::string message;
|
|
9
|
+
std::string syscall;
|
|
10
|
+
std::string path;
|
|
11
|
+
int cerrno = 0;
|
|
12
|
+
void set(const char* iMessage = NULL, const char* iSyscall = NULL, int iErrno = 0, const char* iPath = NULL) {
|
|
13
|
+
if (iMessage) message.assign(iMessage);
|
|
14
|
+
if (iSyscall) syscall.assign(iSyscall);
|
|
15
|
+
cerrno = iErrno;
|
|
16
|
+
if (iPath) path.assign(iPath);
|
|
17
|
+
}
|
|
18
|
+
void reset() {
|
|
19
|
+
message.clear();
|
|
20
|
+
syscall.clear();
|
|
21
|
+
path.clear();
|
|
22
|
+
cerrno = 0;
|
|
23
|
+
}
|
|
24
|
+
bool empty() {
|
|
25
|
+
return cerrno == 0 && message.empty();
|
|
26
|
+
}
|
|
27
|
+
Napi::Error toError(Napi::Env env) {
|
|
28
|
+
if (cerrno) {
|
|
29
|
+
Napi::Error err = Napi::Error::New(env, strerror(cerrno));
|
|
30
|
+
if (!syscall.empty()) err.Value().Set("syscall", syscall);
|
|
31
|
+
if (!path.empty()) err.Value().Set("path", path);
|
|
32
|
+
return err;
|
|
33
|
+
} else {
|
|
34
|
+
return Napi::Error::New(env, message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|
2
|
+
|
|
3
|
+
#include "CanvasGradient.h"
|
|
4
|
+
#include "InstanceData.h"
|
|
5
|
+
|
|
6
|
+
#include "Canvas.h"
|
|
7
|
+
#include "color.h"
|
|
8
|
+
|
|
9
|
+
using namespace Napi;
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* Initialize CanvasGradient.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
void
|
|
16
|
+
Gradient::Initialize(Napi::Env& env, Napi::Object& exports) {
|
|
17
|
+
Napi::HandleScope scope(env);
|
|
18
|
+
InstanceData* data = env.GetInstanceData<InstanceData>();
|
|
19
|
+
|
|
20
|
+
Napi::Function ctor = DefineClass(env, "CanvasGradient", {
|
|
21
|
+
InstanceMethod<&Gradient::AddColorStop>("addColorStop", napi_default_method)
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
exports.Set("CanvasGradient", ctor);
|
|
25
|
+
data->CanvasGradientCtor = Napi::Persistent(ctor);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
* Initialize a new CanvasGradient.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
Gradient::Gradient(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Gradient>(info), env(info.Env()) {
|
|
33
|
+
// Linear
|
|
34
|
+
if (
|
|
35
|
+
4 == info.Length() &&
|
|
36
|
+
info[0].IsNumber() &&
|
|
37
|
+
info[1].IsNumber() &&
|
|
38
|
+
info[2].IsNumber() &&
|
|
39
|
+
info[3].IsNumber()
|
|
40
|
+
) {
|
|
41
|
+
double x0 = info[0].As<Napi::Number>().DoubleValue();
|
|
42
|
+
double y0 = info[1].As<Napi::Number>().DoubleValue();
|
|
43
|
+
double x1 = info[2].As<Napi::Number>().DoubleValue();
|
|
44
|
+
double y1 = info[3].As<Napi::Number>().DoubleValue();
|
|
45
|
+
_pattern = cairo_pattern_create_linear(x0, y0, x1, y1);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Radial
|
|
50
|
+
if (
|
|
51
|
+
6 == info.Length() &&
|
|
52
|
+
info[0].IsNumber() &&
|
|
53
|
+
info[1].IsNumber() &&
|
|
54
|
+
info[2].IsNumber() &&
|
|
55
|
+
info[3].IsNumber() &&
|
|
56
|
+
info[4].IsNumber() &&
|
|
57
|
+
info[5].IsNumber()
|
|
58
|
+
) {
|
|
59
|
+
double x0 = info[0].As<Napi::Number>().DoubleValue();
|
|
60
|
+
double y0 = info[1].As<Napi::Number>().DoubleValue();
|
|
61
|
+
double r0 = info[2].As<Napi::Number>().DoubleValue();
|
|
62
|
+
double x1 = info[3].As<Napi::Number>().DoubleValue();
|
|
63
|
+
double y1 = info[4].As<Napi::Number>().DoubleValue();
|
|
64
|
+
double r1 = info[5].As<Napi::Number>().DoubleValue();
|
|
65
|
+
_pattern = cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Napi::TypeError::New(env, "invalid arguments").ThrowAsJavaScriptException();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* Add color stop.
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
void
|
|
77
|
+
Gradient::AddColorStop(const Napi::CallbackInfo& info) {
|
|
78
|
+
if (!info[0].IsNumber()) {
|
|
79
|
+
Napi::TypeError::New(env, "offset required").ThrowAsJavaScriptException();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!info[1].IsString()) {
|
|
84
|
+
Napi::TypeError::New(env, "color string required").ThrowAsJavaScriptException();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
short ok;
|
|
89
|
+
std::string str = info[1].As<Napi::String>();
|
|
90
|
+
uint32_t rgba = rgba_from_string(str.c_str(), &ok);
|
|
91
|
+
|
|
92
|
+
if (ok) {
|
|
93
|
+
rgba_t color = rgba_create(rgba);
|
|
94
|
+
cairo_pattern_add_color_stop_rgba(
|
|
95
|
+
_pattern
|
|
96
|
+
, info[0].As<Napi::Number>().DoubleValue()
|
|
97
|
+
, color.r
|
|
98
|
+
, color.g
|
|
99
|
+
, color.b
|
|
100
|
+
, color.a);
|
|
101
|
+
} else {
|
|
102
|
+
Napi::TypeError::New(env, "parse color failed").ThrowAsJavaScriptException();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* Destroy the pattern.
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
Gradient::~Gradient() {
|
|
112
|
+
if (_pattern) cairo_pattern_destroy(_pattern);
|
|
113
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
#include <napi.h>
|
|
6
|
+
#include <cairo.h>
|
|
7
|
+
|
|
8
|
+
class Gradient : public Napi::ObjectWrap<Gradient> {
|
|
9
|
+
public:
|
|
10
|
+
static void Initialize(Napi::Env& env, Napi::Object& target);
|
|
11
|
+
Gradient(const Napi::CallbackInfo& info);
|
|
12
|
+
void AddColorStop(const Napi::CallbackInfo& info);
|
|
13
|
+
inline cairo_pattern_t *pattern(){ return _pattern; }
|
|
14
|
+
~Gradient();
|
|
15
|
+
|
|
16
|
+
Napi::Env env;
|
|
17
|
+
|
|
18
|
+
private:
|
|
19
|
+
cairo_pattern_t *_pattern;
|
|
20
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
|
|
2
|
+
|
|
3
|
+
#include "CanvasPattern.h"
|
|
4
|
+
|
|
5
|
+
#include "Canvas.h"
|
|
6
|
+
#include "Image.h"
|
|
7
|
+
#include "InstanceData.h"
|
|
8
|
+
|
|
9
|
+
using namespace Napi;
|
|
10
|
+
|
|
11
|
+
const cairo_user_data_key_t *pattern_repeat_key;
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* Initialize CanvasPattern.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
void
|
|
18
|
+
Pattern::Initialize(Napi::Env& env, Napi::Object& exports) {
|
|
19
|
+
Napi::HandleScope scope(env);
|
|
20
|
+
InstanceData* data = env.GetInstanceData<InstanceData>();
|
|
21
|
+
|
|
22
|
+
// Constructor
|
|
23
|
+
Napi::Function ctor = DefineClass(env, "CanvasPattern", {
|
|
24
|
+
InstanceMethod<&Pattern::setTransform>("setTransform", napi_default_method)
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Prototype
|
|
28
|
+
exports.Set("CanvasPattern", ctor);
|
|
29
|
+
data->CanvasPatternCtor = Napi::Persistent(ctor);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* Initialize a new CanvasPattern.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
Pattern::Pattern(const Napi::CallbackInfo& info) : ObjectWrap<Pattern>(info), env(info.Env()) {
|
|
37
|
+
if (!info[0].IsObject()) {
|
|
38
|
+
Napi::TypeError::New(env, "Image or Canvas expected").ThrowAsJavaScriptException();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
Napi::Object obj = info[0].As<Napi::Object>();
|
|
43
|
+
InstanceData* data = env.GetInstanceData<InstanceData>();
|
|
44
|
+
cairo_surface_t *surface;
|
|
45
|
+
|
|
46
|
+
// Image
|
|
47
|
+
if (obj.InstanceOf(data->ImageCtor.Value()).UnwrapOr(false)) {
|
|
48
|
+
Image *img = Image::Unwrap(obj);
|
|
49
|
+
if (!img->isComplete()) {
|
|
50
|
+
Napi::Error::New(env, "Image given has not completed loading").ThrowAsJavaScriptException();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
surface = img->surface();
|
|
54
|
+
|
|
55
|
+
// Canvas
|
|
56
|
+
} else if (obj.InstanceOf(data->CanvasCtor.Value()).UnwrapOr(false)) {
|
|
57
|
+
Canvas *canvas = Canvas::Unwrap(obj);
|
|
58
|
+
surface = canvas->ensureSurface();
|
|
59
|
+
// Invalid
|
|
60
|
+
} else {
|
|
61
|
+
if (!env.IsExceptionPending()) {
|
|
62
|
+
Napi::TypeError::New(env, "Image or Canvas expected").ThrowAsJavaScriptException();
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
_pattern = cairo_pattern_create_for_surface(surface);
|
|
67
|
+
|
|
68
|
+
if (info[1].IsString()) {
|
|
69
|
+
if ("no-repeat" == info[1].As<Napi::String>().Utf8Value()) {
|
|
70
|
+
_repeat = NO_REPEAT;
|
|
71
|
+
} else if ("repeat-x" == info[1].As<Napi::String>().Utf8Value()) {
|
|
72
|
+
_repeat = REPEAT_X;
|
|
73
|
+
} else if ("repeat-y" == info[1].As<Napi::String>().Utf8Value()) {
|
|
74
|
+
_repeat = REPEAT_Y;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
cairo_pattern_set_user_data(_pattern, pattern_repeat_key, &_repeat, NULL);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
* Set the pattern-space to user-space transform.
|
|
83
|
+
*/
|
|
84
|
+
void
|
|
85
|
+
Pattern::setTransform(const Napi::CallbackInfo& info) {
|
|
86
|
+
if (!info[0].IsObject()) {
|
|
87
|
+
Napi::TypeError::New(env, "Expected DOMMatrix").ThrowAsJavaScriptException();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
Napi::Object mat = info[0].As<Napi::Object>();
|
|
92
|
+
|
|
93
|
+
InstanceData* data = env.GetInstanceData<InstanceData>();
|
|
94
|
+
if (!mat.InstanceOf(data->DOMMatrixCtor.Value()).UnwrapOr(false)) {
|
|
95
|
+
if (!env.IsExceptionPending()) {
|
|
96
|
+
Napi::TypeError::New(env, "Expected DOMMatrix").ThrowAsJavaScriptException();
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
Napi::Value one = Napi::Number::New(env, 1);
|
|
102
|
+
Napi::Value zero = Napi::Number::New(env, 0);
|
|
103
|
+
|
|
104
|
+
cairo_matrix_t matrix;
|
|
105
|
+
cairo_matrix_init(&matrix,
|
|
106
|
+
mat.Get("a").UnwrapOr(one).As<Napi::Number>().DoubleValue(),
|
|
107
|
+
mat.Get("b").UnwrapOr(zero).As<Napi::Number>().DoubleValue(),
|
|
108
|
+
mat.Get("c").UnwrapOr(zero).As<Napi::Number>().DoubleValue(),
|
|
109
|
+
mat.Get("d").UnwrapOr(one).As<Napi::Number>().DoubleValue(),
|
|
110
|
+
mat.Get("e").UnwrapOr(zero).As<Napi::Number>().DoubleValue(),
|
|
111
|
+
mat.Get("f").UnwrapOr(zero).As<Napi::Number>().DoubleValue()
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
cairo_matrix_invert(&matrix);
|
|
115
|
+
cairo_pattern_set_matrix(_pattern, &matrix);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
repeat_type_t Pattern::get_repeat_type_for_cairo_pattern(cairo_pattern_t *pattern) {
|
|
119
|
+
void *ud = cairo_pattern_get_user_data(pattern, pattern_repeat_key);
|
|
120
|
+
return *reinterpret_cast<repeat_type_t*>(ud);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/*
|
|
124
|
+
* Destroy the pattern.
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
Pattern::~Pattern() {
|
|
128
|
+
if (_pattern) cairo_pattern_destroy(_pattern);
|
|
129
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright (c) 2011 LearnBoost <tj@learnboost.com>
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
#include <cairo.h>
|
|
6
|
+
#include <napi.h>
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Canvas types.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
typedef enum {
|
|
13
|
+
NO_REPEAT, // match CAIRO_EXTEND_NONE
|
|
14
|
+
REPEAT, // match CAIRO_EXTEND_REPEAT
|
|
15
|
+
REPEAT_X, // needs custom processing
|
|
16
|
+
REPEAT_Y // needs custom processing
|
|
17
|
+
} repeat_type_t;
|
|
18
|
+
|
|
19
|
+
extern const cairo_user_data_key_t *pattern_repeat_key;
|
|
20
|
+
|
|
21
|
+
class Pattern : public Napi::ObjectWrap<Pattern> {
|
|
22
|
+
public:
|
|
23
|
+
Pattern(const Napi::CallbackInfo& info);
|
|
24
|
+
static void Initialize(Napi::Env& env, Napi::Object& target);
|
|
25
|
+
void setTransform(const Napi::CallbackInfo& info);
|
|
26
|
+
static repeat_type_t get_repeat_type_for_cairo_pattern(cairo_pattern_t *pattern);
|
|
27
|
+
inline cairo_pattern_t *pattern(){ return _pattern; }
|
|
28
|
+
~Pattern();
|
|
29
|
+
Napi::Env env;
|
|
30
|
+
private:
|
|
31
|
+
cairo_pattern_t *_pattern;
|
|
32
|
+
repeat_type_t _repeat = REPEAT;
|
|
33
|
+
};
|