Skip to content

Commit 12a1b50

Browse files
committed
allow registerFont after a canvas has been created
Fixes 1921
1 parent a0c8031 commit 12a1b50

File tree

5 files changed

+30
-9
lines changed

5 files changed

+30
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
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

src/Canvas.cc

Lines changed: 6 additions & 1 deletion
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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,11 @@ class Canvas : public Napi::ObjectWrap<Canvas> {
9292
void resurface(Napi::Object This);
9393

9494
Napi::Env env;
95+
static int fontSerial;
9596

9697
private:
9798
Backend* _backend;
9899
Napi::ObjectReference _jsBackend;
99100
Napi::FunctionReference ctor;
101+
static std::vector<FontFace> font_face_list;
100102
};

src/CanvasRenderingContext2d.cc

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,18 @@ Context2d::Initialize(Napi::Env& env, Napi::Object& exports) {
168168
data->Context2dCtor = Napi::Persistent(ctor);
169169
}
170170

171+
void
172+
Context2d::recreateLayout() {
173+
if (_layout) g_object_unref(_layout);
174+
_layout = pango_cairo_create_layout(_context);
175+
// As of January 2023, Pango rounds glyph positions which renders text wider
176+
// or narrower than the browser. See #2184 for more information
177+
#if PANGO_VERSION_CHECK(1, 44, 0)
178+
pango_context_set_round_glyph_positions(pango_layout_get_context(_layout), FALSE);
179+
#endif
180+
pango_layout_set_font_description(_layout, state->fontDescription);
181+
}
182+
171183
/*
172184
* Create a cairo context.
173185
*/
@@ -222,17 +234,10 @@ Context2d::Context2d(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Context2
222234
}
223235

224236
_context = _canvas->createCairoContext();
225-
_layout = pango_cairo_create_layout(_context);
226-
227-
// As of January 2023, Pango rounds glyph positions which renders text wider
228-
// or narrower than the browser. See #2184 for more information
229-
#if PANGO_VERSION_CHECK(1, 44, 0)
230-
pango_context_set_round_glyph_positions(pango_layout_get_context(_layout), FALSE);
231-
#endif
232237

233238
states.emplace();
234239
state = &states.top();
235-
pango_layout_set_font_description(_layout, state->fontDescription);
240+
recreateLayout();
236241
}
237242

238243
/*
@@ -2446,6 +2451,12 @@ Context2d::paintText(const Napi::CallbackInfo&info, bool stroke) {
24462451
double y = args[1];
24472452
double scaled_by = 1;
24482453

2454+
// If fonts have been registered, the PangoLayout is using an outdated FontMap
2455+
if (canvas()->fontSerial != fontSerial) {
2456+
recreateLayout();
2457+
fontSerial = canvas()->fontSerial;
2458+
}
2459+
24492460
PangoLayout *layout = this->layout();
24502461

24512462
pango_layout_set_text(layout, str.c_str(), -1);

src/CanvasRenderingContext2d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class Context2d : public Napi::ObjectWrap<Context2d> {
205205
void setFontFromState();
206206
void resetState();
207207
inline PangoLayout *layout(){ return _layout; }
208+
void recreateLayout();
208209
~Context2d();
209210
Napi::Env env;
210211

@@ -224,4 +225,5 @@ class Context2d : public Napi::ObjectWrap<Context2d> {
224225
cairo_t *_context = nullptr;
225226
cairo_path_t *_path;
226227
PangoLayout *_layout = nullptr;
228+
int fontSerial = 0;
227229
};

0 commit comments

Comments
 (0)