@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.
Files changed (51) hide show
  1. package/Readme.md +654 -0
  2. package/binding.gyp +229 -0
  3. package/browser.js +31 -0
  4. package/index.d.ts +507 -0
  5. package/index.js +94 -0
  6. package/lib/DOMMatrix.js +678 -0
  7. package/lib/bindings.js +113 -0
  8. package/lib/canvas.js +113 -0
  9. package/lib/context2d.js +11 -0
  10. package/lib/image.js +97 -0
  11. package/lib/jpegstream.js +41 -0
  12. package/lib/pattern.js +15 -0
  13. package/lib/pdfstream.js +35 -0
  14. package/lib/pngstream.js +42 -0
  15. package/package.json +77 -0
  16. package/scripts/install.js +19 -0
  17. package/src/Backends.h +9 -0
  18. package/src/Canvas.cc +1026 -0
  19. package/src/Canvas.h +128 -0
  20. package/src/CanvasError.h +37 -0
  21. package/src/CanvasGradient.cc +113 -0
  22. package/src/CanvasGradient.h +20 -0
  23. package/src/CanvasPattern.cc +129 -0
  24. package/src/CanvasPattern.h +33 -0
  25. package/src/CanvasRenderingContext2d.cc +3527 -0
  26. package/src/CanvasRenderingContext2d.h +238 -0
  27. package/src/CharData.h +233 -0
  28. package/src/FontParser.cc +605 -0
  29. package/src/FontParser.h +115 -0
  30. package/src/Image.cc +1719 -0
  31. package/src/Image.h +146 -0
  32. package/src/ImageData.cc +138 -0
  33. package/src/ImageData.h +26 -0
  34. package/src/InstanceData.h +12 -0
  35. package/src/JPEGStream.h +157 -0
  36. package/src/PNG.h +292 -0
  37. package/src/Point.h +11 -0
  38. package/src/Util.h +9 -0
  39. package/src/bmp/BMPParser.cc +459 -0
  40. package/src/bmp/BMPParser.h +60 -0
  41. package/src/bmp/LICENSE.md +24 -0
  42. package/src/closure.cc +52 -0
  43. package/src/closure.h +98 -0
  44. package/src/color.cc +796 -0
  45. package/src/color.h +30 -0
  46. package/src/dll_visibility.h +20 -0
  47. package/src/init.cc +114 -0
  48. package/src/register_font.cc +352 -0
  49. package/src/register_font.h +7 -0
  50. package/util/has_lib.js +119 -0
  51. package/util/win_jpeg_lookup.js +21 -0
package/src/color.h ADDED
@@ -0,0 +1,30 @@
1
+ // Copyright (c) 2010 LearnBoost <tj@learnboost.com>
2
+
3
+ #pragma once
4
+
5
+ #include <stdint.h> // node < 7 uses libstdc++ on macOS which lacks complete c++11
6
+ #include <cstdlib>
7
+
8
+ /*
9
+ * RGBA struct.
10
+ */
11
+
12
+ typedef struct {
13
+ double r, g, b, a;
14
+ } rgba_t;
15
+
16
+ /*
17
+ * Prototypes.
18
+ */
19
+
20
+ rgba_t
21
+ rgba_create(uint32_t rgba);
22
+
23
+ int32_t
24
+ rgba_from_string(const char *str, short *ok);
25
+
26
+ void
27
+ rgba_to_string(rgba_t rgba, char *buf, size_t len);
28
+
29
+ void
30
+ rgba_inspect(int32_t rgba);
@@ -0,0 +1,20 @@
1
+ #ifndef DLL_PUBLIC
2
+
3
+ #if defined _WIN32
4
+ #ifdef __GNUC__
5
+ #define DLL_PUBLIC __attribute__ ((dllexport))
6
+ #else
7
+ #define DLL_PUBLIC __declspec(dllexport)
8
+ #endif
9
+ #define DLL_LOCAL
10
+ #else
11
+ #if __GNUC__ >= 4
12
+ #define DLL_PUBLIC __attribute__ ((visibility ("default")))
13
+ #define DLL_LOCAL __attribute__ ((visibility ("hidden")))
14
+ #else
15
+ #define DLL_PUBLIC
16
+ #define DLL_LOCAL
17
+ #endif
18
+ #endif
19
+
20
+ #endif
package/src/init.cc ADDED
@@ -0,0 +1,114 @@
1
+ // Copyright (c) 2010 LearnBoost <tj@learnboost.com>
2
+
3
+ #include <cstdio>
4
+ #include <pango/pango.h>
5
+
6
+ #include <cairo.h>
7
+ #if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 10, 0)
8
+ // CAIRO_FORMAT_RGB16_565: undeprecated in v1.10.0
9
+ // CAIRO_STATUS_INVALID_SIZE: v1.10.0
10
+ // CAIRO_FORMAT_INVALID: v1.10.0
11
+ // Lots of the compositing operators: v1.10.0
12
+ // JPEG MIME tracking: v1.10.0
13
+ // Note: CAIRO_FORMAT_RGB30 is v1.12.0 and still optional
14
+ #error("cairo v1.10.0 or later is required")
15
+ #endif
16
+
17
+ #include "Canvas.h"
18
+ #include "CanvasGradient.h"
19
+ #include "CanvasPattern.h"
20
+ #include "CanvasRenderingContext2d.h"
21
+ #include "Image.h"
22
+ #include "ImageData.h"
23
+ #include "InstanceData.h"
24
+
25
+ #include <ft2build.h>
26
+ #include FT_FREETYPE_H
27
+
28
+ /*
29
+ * Save some external modules as private references.
30
+ */
31
+
32
+ static void
33
+ setDOMMatrix(const Napi::CallbackInfo& info) {
34
+ InstanceData* data = info.Env().GetInstanceData<InstanceData>();
35
+ data->DOMMatrixCtor = Napi::Persistent(info[0].As<Napi::Function>());
36
+ }
37
+
38
+ static void
39
+ setParseFont(const Napi::CallbackInfo& info) {
40
+ InstanceData* data = info.Env().GetInstanceData<InstanceData>();
41
+ data->parseFont = Napi::Persistent(info[0].As<Napi::Function>());
42
+ }
43
+
44
+ // Compatibility with Visual Studio versions prior to VS2015
45
+ #if defined(_MSC_VER) && _MSC_VER < 1900
46
+ #define snprintf _snprintf
47
+ #endif
48
+
49
+ Napi::Object init(Napi::Env env, Napi::Object exports) {
50
+ env.SetInstanceData(new InstanceData());
51
+
52
+ Canvas::Initialize(env, exports);
53
+ Image::Initialize(env, exports);
54
+ ImageData::Initialize(env, exports);
55
+ Context2d::Initialize(env, exports);
56
+ Gradient::Initialize(env, exports);
57
+ Pattern::Initialize(env, exports);
58
+
59
+ exports.Set("setDOMMatrix", Napi::Function::New(env, &setDOMMatrix));
60
+ exports.Set("setParseFont", Napi::Function::New(env, &setParseFont));
61
+
62
+ exports.Set("cairoVersion", Napi::String::New(env, cairo_version_string()));
63
+ #ifdef HAVE_JPEG
64
+
65
+ #ifndef JPEG_LIB_VERSION_MAJOR
66
+ #ifdef JPEG_LIB_VERSION
67
+ #define JPEG_LIB_VERSION_MAJOR (JPEG_LIB_VERSION / 10)
68
+ #else
69
+ #define JPEG_LIB_VERSION_MAJOR 0
70
+ #endif
71
+ #endif
72
+
73
+ #ifndef JPEG_LIB_VERSION_MINOR
74
+ #ifdef JPEG_LIB_VERSION
75
+ #define JPEG_LIB_VERSION_MINOR (JPEG_LIB_VERSION % 10)
76
+ #else
77
+ #define JPEG_LIB_VERSION_MINOR 0
78
+ #endif
79
+ #endif
80
+
81
+ char jpeg_version[10];
82
+ static bool minor_gt_0 = JPEG_LIB_VERSION_MINOR > 0;
83
+ if (minor_gt_0) {
84
+ snprintf(jpeg_version, 10, "%d%c", JPEG_LIB_VERSION_MAJOR, JPEG_LIB_VERSION_MINOR + 'a' - 1);
85
+ } else {
86
+ snprintf(jpeg_version, 10, "%d", JPEG_LIB_VERSION_MAJOR);
87
+ }
88
+ exports.Set("jpegVersion", Napi::String::New(env, jpeg_version));
89
+ #endif
90
+
91
+ #ifdef HAVE_GIF
92
+ #ifndef GIF_LIB_VERSION
93
+ char gif_version[10];
94
+ snprintf(gif_version, 10, "%d.%d.%d", GIFLIB_MAJOR, GIFLIB_MINOR, GIFLIB_RELEASE);
95
+ exports.Set("gifVersion", Napi::String::New(env, gif_version));
96
+ #else
97
+ exports.Set("gifVersion", Napi::String::New(env, GIF_LIB_VERSION));
98
+ #endif
99
+ #endif
100
+
101
+ #ifdef HAVE_RSVG
102
+ exports.Set("rsvgVersion", Napi::String::New(env, LIBRSVG_VERSION));
103
+ #endif
104
+
105
+ exports.Set("pangoVersion", Napi::String::New(env, PANGO_VERSION_STRING));
106
+
107
+ char freetype_version[10];
108
+ snprintf(freetype_version, 10, "%d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
109
+ exports.Set("freetypeVersion", Napi::String::New(env, freetype_version));
110
+
111
+ return exports;
112
+ }
113
+
114
+ NODE_API_MODULE(canvas, init);
@@ -0,0 +1,352 @@
1
+ #include "register_font.h"
2
+
3
+ #include <pango/pangocairo.h>
4
+ #include <pango/pango-fontmap.h>
5
+ #include <pango/pango.h>
6
+
7
+ #ifdef __APPLE__
8
+ #include <CoreText/CoreText.h>
9
+ #elif defined(_WIN32)
10
+ #include <windows.h>
11
+ #include <memory>
12
+ #else
13
+ #include <fontconfig/fontconfig.h>
14
+ #endif
15
+
16
+ #include <ft2build.h>
17
+ #include FT_FREETYPE_H
18
+ #include FT_TRUETYPE_TABLES_H
19
+ #include FT_SFNT_NAMES_H
20
+ #include FT_TRUETYPE_IDS_H
21
+ #ifndef FT_SFNT_OS2
22
+ #define FT_SFNT_OS2 ft_sfnt_os2
23
+ #endif
24
+
25
+ // OSX seems to read the strings in MacRoman encoding and ignore Unicode entries.
26
+ // You can verify this by opening a TTF with both Unicode and Macroman on OSX.
27
+ // It uses the MacRoman name, while Fontconfig and Windows use Unicode
28
+ #ifdef __APPLE__
29
+ #define PREFERRED_PLATFORM_ID TT_PLATFORM_MACINTOSH
30
+ #define PREFERRED_ENCODING_ID TT_MAC_ID_ROMAN
31
+ #else
32
+ #define PREFERRED_PLATFORM_ID TT_PLATFORM_MICROSOFT
33
+ #define PREFERRED_ENCODING_ID TT_MS_ID_UNICODE_CS
34
+ #endif
35
+
36
+ #define IS_PREFERRED_ENC(X) \
37
+ X.platform_id == PREFERRED_PLATFORM_ID && X.encoding_id == PREFERRED_ENCODING_ID
38
+
39
+ #define GET_NAME_RANK(X) \
40
+ (IS_PREFERRED_ENC(X) ? 1 : 0) + (X.name_id == TT_NAME_ID_PREFERRED_FAMILY ? 1 : 0)
41
+
42
+ /*
43
+ * Return a UTF-8 encoded string given a TrueType name buf+len
44
+ * and its platform and encoding
45
+ */
46
+
47
+ char *
48
+ to_utf8(FT_Byte* buf, FT_UInt len, FT_UShort pid, FT_UShort eid) {
49
+ size_t ret_len = len * 4; // max chars in a utf8 string
50
+ char *ret = (char*)malloc(ret_len + 1); // utf8 string + null
51
+
52
+ if (!ret) return NULL;
53
+
54
+ // In my testing of hundreds of fonts from the Google Font repo, the two types
55
+ // of fonts are TT_PLATFORM_MICROSOFT with TT_MS_ID_UNICODE_CS encoding, or
56
+ // TT_PLATFORM_MACINTOSH with TT_MAC_ID_ROMAN encoding. Usually both, never neither
57
+
58
+ char const *fromcode;
59
+
60
+ if (pid == TT_PLATFORM_MACINTOSH && eid == TT_MAC_ID_ROMAN) {
61
+ fromcode = "MAC";
62
+ } else if (pid == TT_PLATFORM_MICROSOFT && eid == TT_MS_ID_UNICODE_CS) {
63
+ fromcode = "UTF-16BE";
64
+ } else {
65
+ free(ret);
66
+ return NULL;
67
+ }
68
+
69
+ GIConv cd = g_iconv_open("UTF-8", fromcode);
70
+
71
+ if (cd == (GIConv)-1) {
72
+ free(ret);
73
+ return NULL;
74
+ }
75
+
76
+ size_t inbytesleft = len;
77
+ size_t outbytesleft = ret_len;
78
+
79
+ size_t n_converted = g_iconv(cd, (char**)&buf, &inbytesleft, &ret, &outbytesleft);
80
+
81
+ ret -= ret_len - outbytesleft; // rewind the pointers to their
82
+ buf -= len - inbytesleft; // original starting positions
83
+
84
+ if (n_converted == (size_t)-1) {
85
+ free(ret);
86
+ return NULL;
87
+ } else {
88
+ ret[ret_len - outbytesleft] = '\0';
89
+ return ret;
90
+ }
91
+ }
92
+
93
+ /*
94
+ * Find a family name in the face's name table, preferring the one the
95
+ * system, fall back to the other
96
+ */
97
+
98
+ char *
99
+ get_family_name(FT_Face face) {
100
+ FT_SfntName name;
101
+
102
+ int best_rank = -1;
103
+ char* best_buf = NULL;
104
+
105
+ for (unsigned i = 0; i < FT_Get_Sfnt_Name_Count(face); ++i) {
106
+ FT_Get_Sfnt_Name(face, i, &name);
107
+
108
+ if (name.name_id == TT_NAME_ID_FONT_FAMILY || name.name_id == TT_NAME_ID_PREFERRED_FAMILY) {
109
+ char *buf = to_utf8(name.string, name.string_len, name.platform_id, name.encoding_id);
110
+
111
+ if (buf) {
112
+ int rank = GET_NAME_RANK(name);
113
+ if (rank > best_rank) {
114
+ best_rank = rank;
115
+ if (best_buf) free(best_buf);
116
+ best_buf = buf;
117
+ } else {
118
+ free(buf);
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ return best_buf;
125
+ }
126
+
127
+ PangoWeight
128
+ get_pango_weight(FT_UShort weight) {
129
+ switch (weight) {
130
+ case 100: return PANGO_WEIGHT_THIN;
131
+ case 200: return PANGO_WEIGHT_ULTRALIGHT;
132
+ case 300: return PANGO_WEIGHT_LIGHT;
133
+ #if PANGO_VERSION >= PANGO_VERSION_ENCODE(1, 36, 7)
134
+ case 350: return PANGO_WEIGHT_SEMILIGHT;
135
+ #endif
136
+ case 380: return PANGO_WEIGHT_BOOK;
137
+ case 400: return PANGO_WEIGHT_NORMAL;
138
+ case 500: return PANGO_WEIGHT_MEDIUM;
139
+ case 600: return PANGO_WEIGHT_SEMIBOLD;
140
+ case 700: return PANGO_WEIGHT_BOLD;
141
+ case 800: return PANGO_WEIGHT_ULTRABOLD;
142
+ case 900: return PANGO_WEIGHT_HEAVY;
143
+ case 1000: return PANGO_WEIGHT_ULTRAHEAVY;
144
+ default: return PANGO_WEIGHT_NORMAL;
145
+ }
146
+ }
147
+
148
+ PangoStretch
149
+ get_pango_stretch(FT_UShort width) {
150
+ switch (width) {
151
+ case 1: return PANGO_STRETCH_ULTRA_CONDENSED;
152
+ case 2: return PANGO_STRETCH_EXTRA_CONDENSED;
153
+ case 3: return PANGO_STRETCH_CONDENSED;
154
+ case 4: return PANGO_STRETCH_SEMI_CONDENSED;
155
+ case 5: return PANGO_STRETCH_NORMAL;
156
+ case 6: return PANGO_STRETCH_SEMI_EXPANDED;
157
+ case 7: return PANGO_STRETCH_EXPANDED;
158
+ case 8: return PANGO_STRETCH_EXTRA_EXPANDED;
159
+ case 9: return PANGO_STRETCH_ULTRA_EXPANDED;
160
+ default: return PANGO_STRETCH_NORMAL;
161
+ }
162
+ }
163
+
164
+ PangoStyle
165
+ get_pango_style(FT_Long flags) {
166
+ if (flags & FT_STYLE_FLAG_ITALIC) {
167
+ return PANGO_STYLE_ITALIC;
168
+ } else {
169
+ return PANGO_STYLE_NORMAL;
170
+ }
171
+ }
172
+
173
+ #ifdef _WIN32
174
+ std::unique_ptr<wchar_t[]>
175
+ u8ToWide(const char* str) {
176
+ int iBufferSize = MultiByteToWideChar(CP_UTF8, 0, str, -1, (wchar_t*)NULL, 0);
177
+ if(!iBufferSize){
178
+ return nullptr;
179
+ }
180
+ std::unique_ptr<wchar_t[]> wpBufWString = std::unique_ptr<wchar_t[]>{ new wchar_t[static_cast<size_t>(iBufferSize)] };
181
+ if(!MultiByteToWideChar(CP_UTF8, 0, str, -1, wpBufWString.get(), iBufferSize)){
182
+ return nullptr;
183
+ }
184
+ return wpBufWString;
185
+ }
186
+
187
+ static unsigned long
188
+ stream_read_func(FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count){
189
+ HANDLE hFile = reinterpret_cast<HANDLE>(stream->descriptor.pointer);
190
+ DWORD numberOfBytesRead;
191
+ OVERLAPPED overlapped;
192
+ overlapped.Offset = offset;
193
+ overlapped.OffsetHigh = 0;
194
+ overlapped.hEvent = NULL;
195
+ if(!ReadFile(hFile, buffer, count, &numberOfBytesRead, &overlapped)){
196
+ return 0;
197
+ }
198
+ return numberOfBytesRead;
199
+ };
200
+
201
+ static void
202
+ stream_close_func(FT_Stream stream){
203
+ HANDLE hFile = reinterpret_cast<HANDLE>(stream->descriptor.pointer);
204
+ CloseHandle(hFile);
205
+ }
206
+ #endif
207
+
208
+ /*
209
+ * Return a PangoFontDescription that will resolve to the font file
210
+ */
211
+
212
+ PangoFontDescription *
213
+ get_pango_font_description(unsigned char* filepath) {
214
+ FT_Library library;
215
+ FT_Face face;
216
+ PangoFontDescription *desc = pango_font_description_new();
217
+ #ifdef _WIN32
218
+ // FT_New_Face use fopen.
219
+ // Unable to find the file when supplied the multibyte string path on the Windows platform and throw error "Could not parse font file".
220
+ // This workaround fixes this by reading the font file uses win32 wide character API.
221
+ std::unique_ptr<wchar_t[]> wFilepath = u8ToWide((char*)filepath);
222
+ if(!wFilepath){
223
+ return NULL;
224
+ }
225
+ HANDLE hFile = CreateFileW(
226
+ wFilepath.get(),
227
+ GENERIC_READ,
228
+ FILE_SHARE_READ,
229
+ NULL,
230
+ OPEN_EXISTING,
231
+ FILE_ATTRIBUTE_NORMAL,
232
+ NULL
233
+ );
234
+ if(!hFile){
235
+ return NULL;
236
+ }
237
+ LARGE_INTEGER liSize;
238
+ if(!GetFileSizeEx(hFile, &liSize)) {
239
+ CloseHandle(hFile);
240
+ return NULL;
241
+ }
242
+ FT_Open_Args args;
243
+ args.flags = FT_OPEN_STREAM;
244
+ FT_StreamRec stream;
245
+ stream.base = NULL;
246
+ stream.size = liSize.QuadPart;
247
+ stream.pos = 0;
248
+ stream.descriptor.pointer = hFile;
249
+ stream.read = stream_read_func;
250
+ stream.close = stream_close_func;
251
+ args.stream = &stream;
252
+ if (
253
+ !FT_Init_FreeType(&library) &&
254
+ !FT_Open_Face(library, &args, 0, &face)) {
255
+ #else
256
+ if (!FT_Init_FreeType(&library) && !FT_New_Face(library, (const char*)filepath, 0, &face)) {
257
+ #endif
258
+ TT_OS2 *table = (TT_OS2*)FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
259
+ if (table) {
260
+ char *family = get_family_name(face);
261
+
262
+ if (!family) {
263
+ pango_font_description_free(desc);
264
+ FT_Done_Face(face);
265
+ FT_Done_FreeType(library);
266
+
267
+ return NULL;
268
+ }
269
+
270
+ pango_font_description_set_family(desc, family);
271
+ free(family);
272
+ pango_font_description_set_weight(desc, get_pango_weight(table->usWeightClass));
273
+ pango_font_description_set_stretch(desc, get_pango_stretch(table->usWidthClass));
274
+ pango_font_description_set_style(desc, get_pango_style(face->style_flags));
275
+
276
+ FT_Done_Face(face);
277
+ FT_Done_FreeType(library);
278
+
279
+ return desc;
280
+ }
281
+ }
282
+ pango_font_description_free(desc);
283
+
284
+ return NULL;
285
+ }
286
+
287
+ /*
288
+ * Register font with the OS
289
+ */
290
+
291
+ bool
292
+ register_font(unsigned char *filepath) {
293
+ bool success;
294
+
295
+ #ifdef __APPLE__
296
+ CFURLRef filepathUrl = CFURLCreateFromFileSystemRepresentation(NULL, filepath, strlen((char*)filepath), false);
297
+ success = CTFontManagerRegisterFontsForURL(filepathUrl, kCTFontManagerScopeProcess, NULL);
298
+ #elif defined(_WIN32)
299
+ std::unique_ptr<wchar_t[]> wFilepath = u8ToWide((char*)filepath);
300
+ if(wFilepath){
301
+ success = AddFontResourceExW(wFilepath.get(), FR_PRIVATE, 0) != 0;
302
+ }else{
303
+ success = false;
304
+ }
305
+
306
+ #else
307
+ success = FcConfigAppFontAddFile(FcConfigGetCurrent(), (FcChar8 *)(filepath));
308
+ #endif
309
+
310
+ if (!success) return false;
311
+
312
+ // Tell Pango to throw away the current FontMap and create a new one. This
313
+ // has the effect of registering the new font in Pango by re-looking up all
314
+ // font families.
315
+ pango_cairo_font_map_set_default(NULL);
316
+
317
+ return true;
318
+ }
319
+
320
+ /*
321
+ * Deregister font from the OS
322
+ * Note that Linux (FontConfig) can only dereregister ALL fonts at once.
323
+ */
324
+
325
+ bool
326
+ deregister_font(unsigned char *filepath) {
327
+ bool success;
328
+
329
+ #ifdef __APPLE__
330
+ CFURLRef filepathUrl = CFURLCreateFromFileSystemRepresentation(NULL, filepath, strlen((char*)filepath), false);
331
+ success = CTFontManagerUnregisterFontsForURL(filepathUrl, kCTFontManagerScopeProcess, NULL);
332
+ #elif defined(_WIN32)
333
+ std::unique_ptr<wchar_t[]> wFilepath = u8ToWide((char*)filepath);
334
+ if(wFilepath){
335
+ success = RemoveFontResourceExW(wFilepath.get(), FR_PRIVATE, 0) != 0;
336
+ }else{
337
+ success = false;
338
+ }
339
+ #else
340
+ FcConfigAppFontClear(FcConfigGetCurrent());
341
+ success = true;
342
+ #endif
343
+
344
+ if (!success) return false;
345
+
346
+ // Tell Pango to throw away the current FontMap and create a new one. This
347
+ // has the effect of deregistering the font in Pango by re-looking up all
348
+ // font families.
349
+ pango_cairo_font_map_set_default(NULL);
350
+
351
+ return true;
352
+ }
@@ -0,0 +1,7 @@
1
+ #pragma once
2
+
3
+ #include <pango/pango.h>
4
+
5
+ PangoFontDescription *get_pango_font_description(unsigned char *filepath);
6
+ bool register_font(unsigned char *filepath);
7
+ bool deregister_font(unsigned char *filepath);
@@ -0,0 +1,119 @@
1
+ const query = process.argv[2]
2
+ const fs = require('fs')
3
+ const childProcess = require('child_process')
4
+
5
+ const SYSTEM_PATHS = [
6
+ '/lib',
7
+ '/usr/lib',
8
+ '/usr/lib64',
9
+ '/usr/local/lib',
10
+ '/opt/local/lib',
11
+ '/opt/homebrew/lib',
12
+ '/usr/lib/x86_64-linux-gnu',
13
+ '/usr/lib/i386-linux-gnu',
14
+ '/usr/lib/arm-linux-gnueabihf',
15
+ '/usr/lib/arm-linux-gnueabi',
16
+ '/usr/lib/aarch64-linux-gnu'
17
+ ]
18
+
19
+ /**
20
+ * Checks for lib using ldconfig if present, or searching SYSTEM_PATHS
21
+ * otherwise.
22
+ * @param {string} lib - library name, e.g. 'jpeg' in 'libjpeg64.so' (see first line)
23
+ * @return {boolean} exists
24
+ */
25
+ function hasSystemLib (lib) {
26
+ const libName = 'lib' + lib + '.+(so|dylib)'
27
+ const libNameRegex = new RegExp(libName)
28
+
29
+ // Try using ldconfig on linux systems
30
+ if (hasLdconfig()) {
31
+ try {
32
+ if (childProcess.execSync('ldconfig -p 2>/dev/null | grep -E "' + libName + '"').length) {
33
+ return true
34
+ }
35
+ } catch (err) {
36
+ // noop -- proceed to other search methods
37
+ }
38
+ }
39
+
40
+ // Try checking common library locations
41
+ return SYSTEM_PATHS.some(function (systemPath) {
42
+ try {
43
+ const dirListing = fs.readdirSync(systemPath)
44
+ return dirListing.some(function (file) {
45
+ return libNameRegex.test(file)
46
+ })
47
+ } catch (err) {
48
+ return false
49
+ }
50
+ })
51
+ }
52
+
53
+ /**
54
+ * Checks for ldconfig on the path and /sbin
55
+ * @return {boolean} exists
56
+ */
57
+ function hasLdconfig () {
58
+ try {
59
+ // Add /sbin to path as ldconfig is located there on some systems -- e.g.
60
+ // Debian (and it can still be used by unprivileged users):
61
+ childProcess.execSync('export PATH="$PATH:/sbin"')
62
+ process.env.PATH = '...'
63
+ // execSync throws on nonzero exit
64
+ childProcess.execSync('hash ldconfig 2>/dev/null')
65
+ return true
66
+ } catch (err) {
67
+ return false
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Checks for freetype2 with --cflags-only-I
73
+ * @return Boolean exists
74
+ */
75
+ function hasFreetype () {
76
+ try {
77
+ if (childProcess.execSync('pkg-config cairo --cflags-only-I 2>/dev/null | grep freetype2').length) {
78
+ return true
79
+ }
80
+ } catch (err) {
81
+ // noop
82
+ }
83
+ return false
84
+ }
85
+
86
+ /**
87
+ * Checks for lib using pkg-config.
88
+ * @param {string} lib - library name
89
+ * @return {boolean} exists
90
+ */
91
+ function hasPkgconfigLib (lib) {
92
+ try {
93
+ // execSync throws on nonzero exit
94
+ childProcess.execSync('pkg-config --exists "' + lib + '" 2>/dev/null')
95
+ return true
96
+ } catch (err) {
97
+ return false
98
+ }
99
+ }
100
+
101
+ function main (query) {
102
+ switch (query) {
103
+ case 'gif':
104
+ case 'cairo':
105
+ return hasSystemLib(query)
106
+ case 'pango':
107
+ return hasPkgconfigLib(query)
108
+ case 'freetype':
109
+ return hasFreetype()
110
+ case 'jpeg':
111
+ return hasPkgconfigLib('libjpeg')
112
+ case 'rsvg':
113
+ return hasPkgconfigLib('librsvg-2.0')
114
+ default:
115
+ throw new Error('Unknown library: ' + query)
116
+ }
117
+ }
118
+
119
+ process.stdout.write(main(query).toString())
@@ -0,0 +1,21 @@
1
+ const fs = require('fs')
2
+ const paths = ['C:/libjpeg-turbo']
3
+
4
+ if (process.arch === 'x64') {
5
+ paths.unshift('C:/libjpeg-turbo64')
6
+ }
7
+
8
+ paths.forEach(function (path) {
9
+ if (exists(path)) {
10
+ process.stdout.write(path)
11
+ process.exit()
12
+ }
13
+ })
14
+
15
+ function exists (path) {
16
+ try {
17
+ return fs.lstatSync(path).isDirectory()
18
+ } catch (e) {
19
+ return false
20
+ }
21
+ }