diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aa4a39e4..33c2b1cd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ project adheres to [Semantic Versioning](http://semver.org/). ### Changed * Replaced `simple-get ` with ` Node.js builtin` `fetch` (#2309) * `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. +* 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)) ### Added * Support for accessibility and links in PDFs diff --git a/Readme.md b/Readme.md index 4cb17701c..d0429c520 100644 --- a/Readme.md +++ b/Readme.md @@ -163,7 +163,7 @@ const myimg = await loadImage('http://server.com/image.png') > registerFont(path: string, { family: string, weight?: string, style?: string }) => void > ``` -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.* +To use a font file that is not installed as a system font, use `registerFont()` to register the font with Canvas. ```js const { registerFont, createCanvas } = require('canvas') diff --git a/src/Canvas.cc b/src/Canvas.cc index 7b208bec2..b4fe25120 100644 --- a/src/Canvas.cc +++ b/src/Canvas.cc @@ -38,7 +38,10 @@ using namespace std; -std::vector font_face_list; +std::vector Canvas::font_face_list; + +// Increases each time a font is (de)registered +int Canvas::fontSerial = 1; /* * Initialize Canvas. @@ -734,6 +737,7 @@ Canvas::RegisterFont(const Napi::CallbackInfo& info) { free(family); free(weight); free(style); + fontSerial++; } void @@ -749,6 +753,7 @@ Canvas::DeregisterAllFonts(const Napi::CallbackInfo& info) { }); font_face_list.clear(); + fontSerial++; if (!success) Napi::Error::New(env, "Could not deregister one or more fonts").ThrowAsJavaScriptException(); } diff --git a/src/Canvas.h b/src/Canvas.h index eb19843e5..3883c5137 100644 --- a/src/Canvas.h +++ b/src/Canvas.h @@ -91,9 +91,11 @@ class Canvas : public Napi::ObjectWrap { void resurface(Napi::Object This); Napi::Env env; + static int fontSerial; private: Backend* _backend; Napi::ObjectReference _jsBackend; Napi::FunctionReference ctor; + static std::vector font_face_list; }; diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index d294a4b35..449f5c07f 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -2450,8 +2450,24 @@ get_text_scale(PangoLayout *layout, double maxWidth) { } } +/* + * Make sure the layout's font list is up-to-date + */ +void +Context2d::checkFonts() { + // If fonts have been registered, the PangoContext is using an outdated FontMap + if (canvas()->fontSerial != fontSerial) { + pango_context_set_font_map( + pango_layout_get_context(_layout), + pango_cairo_font_map_get_default() + ); + + fontSerial = canvas()->fontSerial; + } +} + void -Context2d::paintText(const Napi::CallbackInfo&info, bool stroke) { +Context2d::paintText(const Napi::CallbackInfo& info, bool stroke) { int argsNum = info.Length() >= 4 ? 3 : 2; if (argsNum == 3 && info[3].IsUndefined()) @@ -2472,6 +2488,7 @@ Context2d::paintText(const Napi::CallbackInfo&info, bool stroke) { PangoLayout *layout = this->layout(); + checkFonts(); pango_layout_set_text(layout, str.c_str(), -1); pango_cairo_update_layout(context(), layout); @@ -2775,6 +2792,7 @@ Context2d::MeasureText(const Napi::CallbackInfo& info) { PangoFontMetrics *metrics; PangoLayout *layout = this->layout(); + checkFonts(); pango_layout_set_text(layout, str.Utf8Value().c_str(), -1); pango_cairo_update_layout(ctx, layout); diff --git a/src/CanvasRenderingContext2d.h b/src/CanvasRenderingContext2d.h index 16cd42d34..6b29b60f0 100644 --- a/src/CanvasRenderingContext2d.h +++ b/src/CanvasRenderingContext2d.h @@ -220,6 +220,7 @@ class Context2d : public Napi::ObjectWrap { void _setFillPattern(Napi::Value arg); void _setStrokeColor(Napi::Value arg); void _setStrokePattern(Napi::Value arg); + void checkFonts(); void paintText(const Napi::CallbackInfo&, bool); Napi::Reference _fillStyle; Napi::Reference _strokeStyle; @@ -227,4 +228,5 @@ class Context2d : public Napi::ObjectWrap { cairo_t *_context = nullptr; cairo_path_t *_path; PangoLayout *_layout = nullptr; + int fontSerial = 1; };