Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Backup progress

  • Loading branch information...
commit 3539ac8e657e65eb348d948c82b8970853215468 1 parent 03ec023
@jviereck authored
View
18 lib/canvas.js
@@ -17,6 +17,7 @@ var canvas = require('./bindings')
, Context2d = require('./context2d')
, PNGStream = require('./pngstream')
, JPEGStream = require('./jpegstream')
+ , TrueTypeFontFace = canvas.TrueTypeFontFace
, fs = require('fs');
/**
@@ -47,6 +48,23 @@ exports.JPEGStream = JPEGStream;
exports.PixelArray = PixelArray;
exports.Image = Image;
+function TrueTypeFont(name, path, idx) {
+ this.name = name;
+ this._faces = {};
+
+ this.addFace(path, 'normal', 'normal', idx);
+}
+
+TrueTypeFont.prototype.addFace = function(path, weight, style, idx) {
+ style = style || 'normal';
+ weight = weight || 'normal';
+
+ var face = new TrueTypeFontFace(path, idx || 0);
+ this._faces[weight + '-' + style] = face;
+}
+
+exports.TrueTypeFont = TrueTypeFont;
+
/**
* Context2d implementation.
*/
View
46 lib/context2d.js
@@ -99,6 +99,7 @@ var parseFont = exports.parseFont = function(str){
return cache[str] = font;
};
+
/**
* Create a pattern from `Image` or `Canvas`.
*
@@ -215,6 +216,27 @@ Context2d.prototype.__defineGetter__('strokeStyle', function(){
});
+Context2d.prototype.useFont = function(font) {
+ if (!this._fonts) this._fonts = {};
+ var fonts = this._fonts;
+
+ if (fonts[font.name])
+ return;
+
+ // Add a strong reference to the font object to keep it alive.
+ var fontObj = {
+ obj: font
+ };
+
+ // Make all faces of the font available to the context.
+ Object.keys(font._faces).forEach(function(type) {
+ var idx = this.prepareTrueTypeFace(font._faces[type]);
+ fontObj[type] = idx;
+ }, this);
+
+ fonts[font.name] = fontObj;
+}
+
/**
* Set font.
*
@@ -228,12 +250,24 @@ Context2d.prototype.__defineSetter__('font', function(val){
var font;
if (font = parseFont(val)) {
this.lastFontString = val;
- this._setFont(
- font.weight
- , font.style
- , font.size
- , font.unit
- , font.family);
+
+ if (this._fonts && this._fonts[font.family]) {
+ var fontObj = this._fonts[font.family];
+ var type = font.weight + '-' + font.style;
+
+ // If there is no matching type, fallback to default face.
+ console.log(fontObj);
+ var faceIdx = fontObj[type] || fontObj['normal-normal'];
+ console.log('setFont', faceIdx, font.size);
+ this._setFontFace(faceIdx, font.size);
+ } else {
+ this._setFont(
+ font.weight
+ , font.style
+ , font.size
+ , font.unit
+ , font.family);
+ }
}
}
});
View
104 src/CanvasRenderingContext2d.cc
@@ -15,10 +15,7 @@
#include "CanvasRenderingContext2d.h"
#include "CanvasGradient.h"
#include "CanvasPattern.h"
-
-#include <ft2build.h>
-#include <cairo-ft.h>
-#include FT_FREETYPE_H
+#include "TrueTypeFont.h"
Persistent<FunctionTemplate> Context2d::constructor;
@@ -95,7 +92,8 @@ Context2d::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(constructor, "arc", Arc);
NODE_SET_PROTOTYPE_METHOD(constructor, "arcTo", ArcTo);
NODE_SET_PROTOTYPE_METHOD(constructor, "_setFont", SetFont);
- NODE_SET_PROTOTYPE_METHOD(constructor, "loadFontFace", LoadFontFace);
+ NODE_SET_PROTOTYPE_METHOD(constructor, "_setFontFace", SetFontFace);
+ NODE_SET_PROTOTYPE_METHOD(constructor, "prepareTrueTypeFace", PrepareTrueTypeFace);
NODE_SET_PROTOTYPE_METHOD(constructor, "_setFillColor", SetFillColor);
NODE_SET_PROTOTYPE_METHOD(constructor, "_setStrokeColor", SetStrokeColor);
NODE_SET_PROTOTYPE_METHOD(constructor, "_setFillPattern", SetFillPattern);
@@ -1617,71 +1615,60 @@ Context2d::MoveTo(const Arguments &args) {
return Undefined();
}
-/*
- * Load font:
- * - filepath
- */
-
Handle<Value>
-Context2d::loadFontFace(const char *name, const char *path)
-{
- FT_Library library; /* handle to library */
- FT_Face ft_face; /* handle to face object */
- FT_Error ft_error;
-
- ft_error = FT_Init_FreeType( &library );
- if (ft_error) {
- return ThrowException(Exception::Error(String::New("Could not load library")));
- }
-
- ft_error = FT_New_Face( library, path, 0, &ft_face );
- if (ft_error == FT_Err_Unknown_File_Format) {
- return ThrowException(Exception::Error(String::New("Could not load font file")));
- }
+Context2d::PrepareTrueTypeFace(const Arguments &args) {
+ HandleScope scope;
+
+ Local<Object> obj = args[0]->ToObject();
+
+ if (!TrueTypeFontFace::constructor->HasInstance(obj))
+ return ThrowException(Exception::TypeError(String::New("TrueTypeFontFace expected")));
+
+ Context2d *context = ObjectWrap::Unwrap<Context2d>(args.This());
cairo_font_face_t *cr_face;
- cr_face = cairo_ft_font_face_create_for_ft_face(ft_face, 0);
+ TrueTypeFontFace *face = ObjectWrap::Unwrap<TrueTypeFontFace>(obj);
- _loaded_fonts.insert(
- pair<string, font_data*>(
- std::string(name), new font_data(ft_face, cr_face)
- )
- );
+ cr_face = cairo_ft_font_face_create_for_ft_face(face->face, 0);
+
+ vector<cairo_font_face_t*> font_faces = context->font_faces();
+ font_faces.insert(font_faces.end(), cr_face);
- printf("=== Context2d::loadFont - done\n");
-
- return Undefined();
+ printf("=== PrepareTrueTypeFace %p %p %d\n", context, &font_faces, int(font_faces.size()));
+
+ return scope.Close(Number::New(font_faces.size() - 1));
}
Handle<Value>
-Context2d::LoadFontFace(const Arguments &args) {
+Context2d::SetFontFace(const Arguments &args) {
HandleScope scope;
// Ignore invalid args
- if (!args[0]->IsString()
- || !args[1]->IsString()) return Undefined();
+ if (!args[0]->IsNumber()
+ || !args[1]->IsNumber())
+ return ThrowException(Exception::TypeError(String::New("Expected number")));
- printf("=== Context2d::LoadFontFace\n");
+ int idx = int(args[0]->NumberValue());
+ double size = args[1]->NumberValue();
- String::AsciiValue fontName(args[0]);
- String::AsciiValue filePath(args[1]);
-
Context2d *context = ObjectWrap::Unwrap<Context2d>(args.This());
- context->loadFontFace(*fontName, *filePath);
+ cairo_t *ctx = context->context();
+ vector<cairo_font_face_t*> font_faces = context->font_faces();
+
+ printf("_setFontFace %p %p %d %d\n", context, &font_faces, int(font_faces.size()), idx);
+
+ if (idx > int(font_faces.size()) || idx < 0)
+ return ThrowException(Exception::TypeError(String::New("Try to get element out of bound")));
- return Undefined();
-}
+ cairo_set_font_size(ctx, size);
-cairo_font_face_t*
-Context2d::lookupLoadedFontFace(const char *name)
-{
- map_font_entry::iterator iter;
- iter = _loaded_fonts.find(string(name));
- if (iter != _loaded_fonts.end()) {
- return iter->second->cr_face;
- } else {
- return NULL;
- }
+ printf("_setFontFace::2 %p\n", font_faces[idx]);
+
+ cairo_set_font_face(ctx, font_faces[idx]);
+
+ printf("_setFontFace::3\n");
+
+ return Undefined();
}
/*
@@ -1730,14 +1717,7 @@ Context2d::SetFont(const Arguments &args) {
w = CAIRO_FONT_WEIGHT_BOLD;
}
- cairo_font_face_t *cr_face = context->lookupLoadedFontFace(*family);
- if (cr_face) {
- printf("=== Context2d::SetFont: Pickup font\n");
- cairo_set_font_face(ctx, cr_face);
- } else {
- printf("=== Context2d::SetFont: Pickup font NOPE\n");
- cairo_select_font_face(ctx, *family, s, w);
- }
+ cairo_select_font_face(ctx, *family, s, w);
return Undefined();
}
View
24 src/CanvasRenderingContext2d.h
@@ -17,7 +17,7 @@
#include FT_FREETYPE_H
#include <string>
-#include <map>
+#include <vector>
using namespace std;
typedef enum {
@@ -25,18 +25,6 @@ typedef enum {
TEXT_DRAW_GLYPHS
} canvas_draw_mode_t;
-typedef struct font_data {
- FT_Face ft_face;
- cairo_font_face_t *cr_face;
-
- font_data(FT_Face ft_face, cairo_font_face_t *cr_face):
- ft_face(ft_face), cr_face(cr_face)
- {
- }
-};
-
-typedef map<string, font_data*> map_font_entry;
-
/*
* State struct.
*
@@ -90,7 +78,8 @@ class Context2d: public node::ObjectWrap {
static Handle<Value> FillText(const Arguments &args);
static Handle<Value> StrokeText(const Arguments &args);
static Handle<Value> SetFont(const Arguments &args);
- static Handle<Value> LoadFontFace(const Arguments &args);
+ static Handle<Value> SetFontFace(const Arguments &args);
+ static Handle<Value> PrepareTrueTypeFace(const Arguments &args);
static Handle<Value> SetFillColor(const Arguments &args);
static Handle<Value> SetStrokeColor(const Arguments &args);
static Handle<Value> SetFillPattern(const Arguments &args);
@@ -139,6 +128,7 @@ class Context2d: public node::ObjectWrap {
inline void setContext(cairo_t *ctx) { _context = ctx; }
inline cairo_t *context(){ return _context; }
inline Canvas *canvas(){ return _canvas; }
+ inline vector<cairo_font_face_t*> font_faces(){ return _font_faces; }
inline bool hasShadow();
void inline setSourceRGBA(rgba_t color);
void setTextPath(const char *str, double x, double y);
@@ -154,17 +144,13 @@ class Context2d: public node::ObjectWrap {
void stroke(bool preserve = false);
void save();
void restore();
-
- Handle<Value> loadFontFace(const char *name, const char *path);
- cairo_font_face_t* lookupLoadedFontFace(const char *name);
-
private:
~Context2d();
Canvas *_canvas;
cairo_t *_context;
cairo_path_t *_path;
- map_font_entry _loaded_fonts;
+ vector<cairo_font_face_t*> _font_faces;
// FT_Library ft_library; /* handle to library */
// FT_Face ft_face; /* handle to face object */
// FT_Error ft_error;
View
4 src/init.cc
@@ -12,6 +12,7 @@
#include "CanvasGradient.h"
#include "CanvasPattern.h"
#include "CanvasRenderingContext2d.h"
+#include "TrueTypeFont.h"
extern "C" void
init (Handle<Object> target) {
@@ -23,7 +24,8 @@ init (Handle<Object> target) {
Context2d::Initialize(target);
Gradient::Initialize(target);
Pattern::Initialize(target);
+ TrueTypeFontFace::Initialize(target);
target->Set(String::New("cairoVersion"), String::New(cairo_version_string()));
}
-NODE_MODULE(canvas,init);
+NODE_MODULE(canvas,init);
Please sign in to comment.
Something went wrong with that request. Please try again.