Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
chearon committed Dec 27, 2024
1 parent 322b129 commit 7090dc9
Show file tree
Hide file tree
Showing 9 changed files with 1,040 additions and 69 deletions.
3 changes: 2 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@
'src/Image.cc',
'src/ImageData.cc',
'src/init.cc',
'src/register_font.cc'
'src/register_font.cc',
'src/FontParser.cc'
],
'conditions': [
['OS=="win"', {
Expand Down
3 changes: 0 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const Canvas = require('./lib/canvas')
const Image = require('./lib/image')
const CanvasRenderingContext2D = require('./lib/context2d')
const CanvasPattern = require('./lib/pattern')
const parseFont = require('./lib/parse-font')
const packageJson = require('./package.json')
const bindings = require('./lib/bindings')
const fs = require('fs')
Expand All @@ -12,7 +11,6 @@ const JPEGStream = require('./lib/jpegstream')
const { DOMPoint, DOMMatrix } = require('./lib/DOMMatrix')

bindings.setDOMMatrix(DOMMatrix)
bindings.setParseFont(parseFont)

function createCanvas (width, height, type) {
return new Canvas(width, height, type)
Expand Down Expand Up @@ -73,7 +71,6 @@ exports.DOMPoint = DOMPoint

exports.registerFont = registerFont
exports.deregisterAllFonts = deregisterAllFonts
exports.parseFont = parseFont

exports.createCanvas = createCanvas
exports.createImageData = createImageData
Expand Down
38 changes: 37 additions & 1 deletion src/Canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "Util.h"
#include <vector>
#include "node_buffer.h"
#include "FontParser.h"

#ifdef HAVE_JPEG
#include "JPEGStream.h"
Expand Down Expand Up @@ -68,7 +69,8 @@ Canvas::Initialize(Napi::Env& env, Napi::Object& exports) {
StaticValue("PNG_FILTER_PAETH", Napi::Number::New(env, PNG_FILTER_PAETH), napi_default_jsproperty),
StaticValue("PNG_ALL_FILTERS", Napi::Number::New(env, PNG_ALL_FILTERS), napi_default_jsproperty),
StaticMethod<&Canvas::RegisterFont>("_registerFont", napi_default_method),
StaticMethod<&Canvas::DeregisterAllFonts>("_deregisterAllFonts", napi_default_method)
StaticMethod<&Canvas::DeregisterAllFonts>("_deregisterAllFonts", napi_default_method),
StaticMethod<&Canvas::ParseFont>("parseFont", napi_default_method)
});

data->CanvasCtor = Napi::Persistent(ctor);
Expand Down Expand Up @@ -749,6 +751,40 @@ Canvas::DeregisterAllFonts(const Napi::CallbackInfo& info) {
if (!success) Napi::Error::New(env, "Could not deregister one or more fonts").ThrowAsJavaScriptException();
}

/*
* This is only exported for testing
*/
Napi::Value
Canvas::ParseFont(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();

if (info.Length() != 1) return env.Undefined();

Napi::String str;
if (!info[0].ToString().UnwrapTo(&str)) return env.Undefined();

bool ok;
auto props = FontParser::parse(str, &ok);
if (!ok) return env.Undefined();

Napi::Object obj = Napi::Object::New(env);
obj.Set("size", Napi::Number::New(env, props.fontSize));
Napi::Array families = Napi::Array::New(env);
obj.Set("families", families);

unsigned int index = 0;

for (auto& family : props.fontFamily) {
families[index++] = Napi::String::New(env, family);
}

obj.Set("weight", Napi::Number::New(env, props.fontWeight));
obj.Set("variant", Napi::Number::New(env, static_cast<int>(props.fontVariant)));
obj.Set("style", Napi::Number::New(env, static_cast<int>(props.fontStyle)));

return obj;
}

/*
* Get a PangoStyle from a CSS string (like "italic")
*/
Expand Down
1 change: 1 addition & 0 deletions src/Canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class Canvas : public Napi::ObjectWrap<Canvas> {
void StreamJPEGSync(const Napi::CallbackInfo& info);
static void RegisterFont(const Napi::CallbackInfo& info);
static void DeregisterAllFonts(const Napi::CallbackInfo& info);
static Napi::Value ParseFont(const Napi::CallbackInfo& info);
Napi::Error CairoError(cairo_status_t status);
static void ToPngBufferAsync(Closure* closure);
static void ToJpegBufferAsync(Closure* closure);
Expand Down
63 changes: 32 additions & 31 deletions src/CanvasRenderingContext2d.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "CanvasGradient.h"
#include "CanvasPattern.h"
#include "InstanceData.h"
#include "FontParser.h"
#include <cmath>
#include <cstdlib>
#include "Image.h"
Expand Down Expand Up @@ -2575,54 +2576,54 @@ Context2d::GetFont(const Napi::CallbackInfo& info) {

void
Context2d::SetFont(const Napi::CallbackInfo& info, const Napi::Value& value) {
InstanceData* data = env.GetInstanceData<InstanceData>();

if (!value.IsString()) return;

if (!value.As<Napi::String>().Utf8Value().length()) return;

Napi::Value mparsed;

// parseFont returns undefined for invalid CSS font strings
if (!data->parseFont.Call({ value }).UnwrapTo(&mparsed) || mparsed.IsUndefined()) return;
std::string str = value.As<Napi::String>().Utf8Value();
if (!str.length()) return;

Napi::Object font = mparsed.As<Napi::Object>();

Napi::String empty = Napi::String::New(env, "");
Napi::Number zero = Napi::Number::New(env, 0);

std::string weight = font.Get("weight").UnwrapOr(empty).ToString().UnwrapOr(empty).Utf8Value();
std::string style = font.Get("style").UnwrapOr(empty).ToString().UnwrapOr(empty).Utf8Value();
double size = font.Get("size").UnwrapOr(zero).ToNumber().UnwrapOr(zero).DoubleValue();
std::string unit = font.Get("unit").UnwrapOr(empty).ToString().UnwrapOr(empty).Utf8Value();
std::string family = font.Get("family").UnwrapOr(empty).ToString().UnwrapOr(empty).Utf8Value();
bool success;
auto props = FontParser::parse(str, &success);
if (!success) return;

PangoFontDescription *desc = pango_font_description_copy(state->fontDescription);
pango_font_description_free(state->fontDescription);

pango_font_description_set_style(desc, Canvas::GetStyleFromCSSString(style.c_str()));
pango_font_description_set_weight(desc, Canvas::GetWeightFromCSSString(weight.c_str()));
// Map our FontStyle enum to Pango style
PangoStyle style = PANGO_STYLE_NORMAL;
switch (props.fontStyle) {
case FontStyle::Italic:
style = PANGO_STYLE_ITALIC;
break;
case FontStyle::Oblique:
style = PANGO_STYLE_OBLIQUE;
break;
default:
break;
}
pango_font_description_set_style(desc, style);

// Weight is already in the correct range (1-1000)
pango_font_description_set_weight(desc, static_cast<PangoWeight>(props.fontWeight));

if (family.length() > 0) {
// See #1643 - Pango understands "sans" whereas CSS uses "sans-serif"
std::string s1(family);
std::string s2("sans-serif");
if (streq_casein(s1, s2)) {
pango_font_description_set_family(desc, "sans");
} else {
pango_font_description_set_family(desc, family.c_str());
}
// Join font families with commas
std::string family = props.fontFamily.empty() ? "" : props.fontFamily[0];
for (size_t i = 1; i < props.fontFamily.size(); i++) {
family += "," + props.fontFamily[i];
}
pango_font_description_set_family(desc, family.c_str());

// Convert font size to Pango units (points * PANGO_SCALE)
pango_font_description_set_size(desc, props.fontSize * PANGO_SCALE);

PangoFontDescription *sys_desc = Canvas::ResolveFontDescription(desc);
pango_font_description_free(desc);

if (size > 0) pango_font_description_set_absolute_size(sys_desc, size * PANGO_SCALE);
pango_font_description_set_absolute_size(sys_desc, props.fontSize * PANGO_SCALE);

state->fontDescription = sys_desc;
pango_layout_set_font_description(_layout, sys_desc);

state->font = value.As<Napi::String>().Utf8Value().c_str();
state->font = str;
}

/*
Expand Down
Loading

0 comments on commit 7090dc9

Please sign in to comment.