Skip to content

Commit

Permalink
allow registerFont after a canvas has been created
Browse files Browse the repository at this point in the history
Fixes 1921
  • Loading branch information
chearon committed Jan 11, 2025
1 parent a0c8031 commit 12a1b50
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion src/Canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@

using namespace std;

std::vector<FontFace> font_face_list;
std::vector<FontFace> Canvas::font_face_list;

// Increases each time a font is (de)registered
int Canvas::fontSerial = 1;

/*
* Initialize Canvas.
Expand Down Expand Up @@ -734,6 +737,7 @@ Canvas::RegisterFont(const Napi::CallbackInfo& info) {
free(family);
free(weight);
free(style);
fontSerial++;
}

void
Expand All @@ -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();
}

Expand Down
2 changes: 2 additions & 0 deletions src/Canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,11 @@ class Canvas : public Napi::ObjectWrap<Canvas> {
void resurface(Napi::Object This);

Napi::Env env;
static int fontSerial;

private:
Backend* _backend;
Napi::ObjectReference _jsBackend;
Napi::FunctionReference ctor;
static std::vector<FontFace> font_face_list;
};
27 changes: 19 additions & 8 deletions src/CanvasRenderingContext2d.cc
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,18 @@ Context2d::Initialize(Napi::Env& env, Napi::Object& exports) {
data->Context2dCtor = Napi::Persistent(ctor);
}

void
Context2d::recreateLayout() {
if (_layout) g_object_unref(_layout);
_layout = pango_cairo_create_layout(_context);
// As of January 2023, Pango rounds glyph positions which renders text wider
// or narrower than the browser. See #2184 for more information
#if PANGO_VERSION_CHECK(1, 44, 0)
pango_context_set_round_glyph_positions(pango_layout_get_context(_layout), FALSE);
#endif
pango_layout_set_font_description(_layout, state->fontDescription);
}

/*
* Create a cairo context.
*/
Expand Down Expand Up @@ -222,17 +234,10 @@ Context2d::Context2d(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Context2
}

_context = _canvas->createCairoContext();
_layout = pango_cairo_create_layout(_context);

// As of January 2023, Pango rounds glyph positions which renders text wider
// or narrower than the browser. See #2184 for more information
#if PANGO_VERSION_CHECK(1, 44, 0)
pango_context_set_round_glyph_positions(pango_layout_get_context(_layout), FALSE);
#endif

states.emplace();
state = &states.top();
pango_layout_set_font_description(_layout, state->fontDescription);
recreateLayout();
}

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

// If fonts have been registered, the PangoLayout is using an outdated FontMap
if (canvas()->fontSerial != fontSerial) {
recreateLayout();
fontSerial = canvas()->fontSerial;
}

PangoLayout *layout = this->layout();

pango_layout_set_text(layout, str.c_str(), -1);
Expand Down
2 changes: 2 additions & 0 deletions src/CanvasRenderingContext2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ class Context2d : public Napi::ObjectWrap<Context2d> {
void setFontFromState();
void resetState();
inline PangoLayout *layout(){ return _layout; }
void recreateLayout();
~Context2d();
Napi::Env env;

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

0 comments on commit 12a1b50

Please sign in to comment.