Skip to content

Commit 88e9657

Browse files
authored
allow registerFont after a canvas has been created (#2483)
Fixes #1921
1 parent 52330b8 commit 88e9657

6 files changed

+31
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ project adheres to [Semantic Versioning](http://semver.org/).
1010
### Changed
1111
* Replaced `simple-get ` with ` Node.js builtin` `fetch` (#2309)
1212
* `ctx.font` has a new C++ parser and is 2x-400x faster. Please file an issue if you experience different results, as caching has been removed.
13+
* The restriction of registering fonts before a canvas is created has been removed. You can now register a font as late as right before the `fillText` call ([#1921](https://github.com/Automattic/node-canvas/issues/1921))
1314

1415
### Added
1516
* Support for accessibility and links in PDFs

Readme.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ const myimg = await loadImage('http://server.com/image.png')
163163
> registerFont(path: string, { family: string, weight?: string, style?: string }) => void
164164
> ```
165165
166-
To use a font file that is not installed as a system font, use `registerFont()` to register the font with Canvas. *This must be done before the Canvas is created.*
166+
To use a font file that is not installed as a system font, use `registerFont()` to register the font with Canvas.
167167
168168
```js
169169
const { registerFont, createCanvas } = require('canvas')

src/Canvas.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@
3838

3939
using namespace std;
4040

41-
std::vector<FontFace> font_face_list;
41+
std::vector<FontFace> Canvas::font_face_list;
42+
43+
// Increases each time a font is (de)registered
44+
int Canvas::fontSerial = 1;
4245

4346
/*
4447
* Initialize Canvas.
@@ -734,6 +737,7 @@ Canvas::RegisterFont(const Napi::CallbackInfo& info) {
734737
free(family);
735738
free(weight);
736739
free(style);
740+
fontSerial++;
737741
}
738742

739743
void
@@ -749,6 +753,7 @@ Canvas::DeregisterAllFonts(const Napi::CallbackInfo& info) {
749753
});
750754

751755
font_face_list.clear();
756+
fontSerial++;
752757
if (!success) Napi::Error::New(env, "Could not deregister one or more fonts").ThrowAsJavaScriptException();
753758
}
754759

src/Canvas.h

+2
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,11 @@ class Canvas : public Napi::ObjectWrap<Canvas> {
9191
void resurface(Napi::Object This);
9292

9393
Napi::Env env;
94+
static int fontSerial;
9495

9596
private:
9697
Backend* _backend;
9798
Napi::ObjectReference _jsBackend;
9899
Napi::FunctionReference ctor;
100+
static std::vector<FontFace> font_face_list;
99101
};

src/CanvasRenderingContext2d.cc

+19-1
Original file line numberDiff line numberDiff line change
@@ -2450,8 +2450,24 @@ get_text_scale(PangoLayout *layout, double maxWidth) {
24502450
}
24512451
}
24522452

2453+
/*
2454+
* Make sure the layout's font list is up-to-date
2455+
*/
2456+
void
2457+
Context2d::checkFonts() {
2458+
// If fonts have been registered, the PangoContext is using an outdated FontMap
2459+
if (canvas()->fontSerial != fontSerial) {
2460+
pango_context_set_font_map(
2461+
pango_layout_get_context(_layout),
2462+
pango_cairo_font_map_get_default()
2463+
);
2464+
2465+
fontSerial = canvas()->fontSerial;
2466+
}
2467+
}
2468+
24532469
void
2454-
Context2d::paintText(const Napi::CallbackInfo&info, bool stroke) {
2470+
Context2d::paintText(const Napi::CallbackInfo& info, bool stroke) {
24552471
int argsNum = info.Length() >= 4 ? 3 : 2;
24562472

24572473
if (argsNum == 3 && info[3].IsUndefined())
@@ -2472,6 +2488,7 @@ Context2d::paintText(const Napi::CallbackInfo&info, bool stroke) {
24722488

24732489
PangoLayout *layout = this->layout();
24742490

2491+
checkFonts();
24752492
pango_layout_set_text(layout, str.c_str(), -1);
24762493
pango_cairo_update_layout(context(), layout);
24772494

@@ -2775,6 +2792,7 @@ Context2d::MeasureText(const Napi::CallbackInfo& info) {
27752792
PangoFontMetrics *metrics;
27762793
PangoLayout *layout = this->layout();
27772794

2795+
checkFonts();
27782796
pango_layout_set_text(layout, str.Utf8Value().c_str(), -1);
27792797
pango_cairo_update_layout(ctx, layout);
27802798

src/CanvasRenderingContext2d.h

+2
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,13 @@ class Context2d : public Napi::ObjectWrap<Context2d> {
220220
void _setFillPattern(Napi::Value arg);
221221
void _setStrokeColor(Napi::Value arg);
222222
void _setStrokePattern(Napi::Value arg);
223+
void checkFonts();
223224
void paintText(const Napi::CallbackInfo&, bool);
224225
Napi::Reference<Napi::Value> _fillStyle;
225226
Napi::Reference<Napi::Value> _strokeStyle;
226227
Canvas *_canvas;
227228
cairo_t *_context = nullptr;
228229
cairo_path_t *_path;
229230
PangoLayout *_layout = nullptr;
231+
int fontSerial = 1;
230232
};

0 commit comments

Comments
 (0)