// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
#pragma once
#include "cairo.h"
#include "Canvas.h"
#include "color.h"
#include "napi.h"
#include "uv.h"
#include <pango/pangocairo.h>
#include <stack>
/*
* State struct.
*
* Used in conjunction with Save() / Restore() since
* cairo's gstate maintains only a single source pattern at a time.
*/
struct canvas_state_t {
rgba_t fill = { 0, 0, 0, 1 };
rgba_t stroke = { 0, 0, 0, 1 };
rgba_t shadow = { 0, 0, 0, 0 };
double shadowOffsetX = 0.;
double shadowOffsetY = 0.;
cairo_pattern_t* fillPattern = nullptr;
cairo_pattern_t* strokePattern = nullptr;
cairo_pattern_t* fillGradient = nullptr;
cairo_pattern_t* strokeGradient = nullptr;
PangoFontDescription* fontDescription = nullptr;
std::string font = "10px sans-serif";
cairo_filter_t patternQuality = CAIRO_FILTER_GOOD;
float globalAlpha = 1.f;
int shadowBlur = 0;
text_align_t textAlignment = TEXT_ALIGNMENT_LEFT; // TODO default is supposed to be START
text_baseline_t textBaseline = TEXT_BASELINE_ALPHABETIC;
canvas_draw_mode_t textDrawingMode = TEXT_DRAW_PATHS;
bool imageSmoothingEnabled = true;
canvas_state_t() {
fontDescription = pango_font_description_from_string("sans");
pango_font_description_set_absolute_size(fontDescription, 10 * PANGO_SCALE);
}
canvas_state_t(const canvas_state_t& other) {
fill = other.fill;
stroke = other.stroke;
patternQuality = other.patternQuality;
fillPattern = other.fillPattern;
strokePattern = other.strokePattern;
fillGradient = other.fillGradient;
strokeGradient = other.strokeGradient;
globalAlpha = other.globalAlpha;
textAlignment = other.textAlignment;
textBaseline = other.textBaseline;
shadow = other.shadow;
shadowBlur = other.shadowBlur;
shadowOffsetX = other.shadowOffsetX;
shadowOffsetY = other.shadowOffsetY;
textDrawingMode = other.textDrawingMode;
fontDescription = pango_font_description_copy(other.fontDescription);
font = other.font;
imageSmoothingEnabled = other.imageSmoothingEnabled;
}
~canvas_state_t() {
pango_font_description_free(fontDescription);
}
};
/*
* Equivalent to a PangoRectangle but holds floats instead of ints
* (software pixels are stored here instead of pango units)
*
* Should be compatible with PANGO_ASCENT, PANGO_LBEARING, etc.
*/
typedef struct {
float x;
float y;
float width;
float height;
} float_rectangle;
class Context2d : public Napi::ObjectWrap<Context2d> {
public:
std::stack<canvas_state_t> states;
canvas_state_t *state;
Context2d(Canvas *canvas);
static Napi::FunctionReference _DOMMatrix;
static Napi::FunctionReference _parseFont;
static Napi::FunctionReference constructor;
static void Initialize(Napi::Env& env, Napi::Object& target);
static Napi::Value New(const Napi::CallbackInfo& info);
static Napi::Value SaveExternalModules(const Napi::CallbackInfo& info);
static Napi::Value DrawImage(const Napi::CallbackInfo& info);
static Napi::Value PutImageData(const Napi::CallbackInfo& info);
static Napi::Value Save(const Napi::CallbackInfo& info);
static Napi::Value Restore(const Napi::CallbackInfo& info);
static Napi::Value Rotate(const Napi::CallbackInfo& info);
static Napi::Value Translate(const Napi::CallbackInfo& info);
static Napi::Value Scale(const Napi::CallbackInfo& info);
static Napi::Value Transform(const Napi::CallbackInfo& info);
static Napi::Value GetTransform(const Napi::CallbackInfo& info);
static Napi::Value ResetTransform(const Napi::CallbackInfo& info);
static Napi::Value SetTransform(const Napi::CallbackInfo& info);
static Napi::Value IsPointInPath(const Napi::CallbackInfo& info);
static Napi::Value BeginPath(const Napi::CallbackInfo& info);
static Napi::Value ClosePath(const Napi::CallbackInfo& info);
static Napi::Value AddPage(const Napi::CallbackInfo& info);
static Napi::Value Clip(const Napi::CallbackInfo& info);
static Napi::Value Fill(const Napi::CallbackInfo& info);
static Napi::Value Stroke(const Napi::CallbackInfo& info);
static Napi::Value FillText(const Napi::CallbackInfo& info);
static Napi::Value StrokeText(const Napi::CallbackInfo& info);
static Napi::Value SetFont(const Napi::CallbackInfo& info);
static Napi::Value SetFillColor(const Napi::CallbackInfo& info);
static Napi::Value SetStrokeColor(const Napi::CallbackInfo& info);
static Napi::Value SetStrokePattern(const Napi::CallbackInfo& info);
static Napi::Value SetTextAlignment(const Napi::CallbackInfo& info);
static Napi::Value SetLineDash(const Napi::CallbackInfo& info);
static Napi::Value GetLineDash(const Napi::CallbackInfo& info);
static Napi::Value MeasureText(const Napi::CallbackInfo& info);
static Napi::Value BezierCurveTo(const Napi::CallbackInfo& info);
static Napi::Value QuadraticCurveTo(const Napi::CallbackInfo& info);
static Napi::Value LineTo(const Napi::CallbackInfo& info);
static Napi::Value MoveTo(const Napi::CallbackInfo& info);
static Napi::Value FillRect(const Napi::CallbackInfo& info);
static Napi::Value StrokeRect(const Napi::CallbackInfo& info);
static Napi::Value ClearRect(const Napi::CallbackInfo& info);
static Napi::Value Rect(const Napi::CallbackInfo& info);
static Napi::Value RoundRect(const Napi::CallbackInfo& info);
static Napi::Value Arc(const Napi::CallbackInfo& info);
static Napi::Value ArcTo(const Napi::CallbackInfo& info);
static Napi::Value Ellipse(const Napi::CallbackInfo& info);
static Napi::Value GetImageData(const Napi::CallbackInfo& info);
static Napi::Value CreateImageData(const Napi::CallbackInfo& info);
static Napi::Value GetStrokeColor(const Napi::CallbackInfo& info);
static Napi::Value CreatePattern(const Napi::CallbackInfo& info);
static Napi::Value CreateLinearGradient(const Napi::CallbackInfo& info);
static Napi::Value CreateRadialGradient(const Napi::CallbackInfo& info);
Napi::Value GetFormat(const Napi::CallbackInfo& info);
Napi::Value GetPatternQuality(const Napi::CallbackInfo& info);
Napi::Value GetImageSmoothingEnabled(const Napi::CallbackInfo& info);
Napi::Value GetGlobalCompositeOperation(const Napi::CallbackInfo& info);
Napi::Value GetGlobalAlpha(const Napi::CallbackInfo& info);
Napi::Value GetShadowColor(const Napi::CallbackInfo& info);
Napi::Value GetMiterLimit(const Napi::CallbackInfo& info);
Napi::Value GetLineCap(const Napi::CallbackInfo& info);
Napi::Value GetLineJoin(const Napi::CallbackInfo& info);
Napi::Value GetLineWidth(const Napi::CallbackInfo& info);
Napi::Value GetLineDashOffset(const Napi::CallbackInfo& info);
Napi::Value GetShadowOffsetX(const Napi::CallbackInfo& info);
Napi::Value GetShadowOffsetY(const Napi::CallbackInfo& info);
Napi::Value GetShadowBlur(const Napi::CallbackInfo& info);
Napi::Value GetAntiAlias(const Napi::CallbackInfo& info);
Napi::Value GetTextDrawingMode(const Napi::CallbackInfo& info);
Napi::Value GetQuality(const Napi::CallbackInfo& info);
Napi::Value GetCurrentTransform(const Napi::CallbackInfo& info);
Napi::Value GetFillStyle(const Napi::CallbackInfo& info);
Napi::Value GetStrokeStyle(const Napi::CallbackInfo& info);
Napi::Value GetFont(const Napi::CallbackInfo& info);
Napi::Value GetTextBaseline(const Napi::CallbackInfo& info);
Napi::Value GetTextAlign(const Napi::CallbackInfo& info);
void SetPatternQuality(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetImageSmoothingEnabled(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetGlobalCompositeOperation(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetGlobalAlpha(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetShadowColor(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetMiterLimit(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetLineCap(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetLineJoin(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetLineWidth(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetLineDashOffset(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetShadowOffsetX(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetShadowOffsetY(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetShadowBlur(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetAntiAlias(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetTextDrawingMode(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetQuality(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetCurrentTransform(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetFillStyle(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetStrokeStyle(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetFont(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetTextBaseline(const Napi::CallbackInfo& info, const Napi::Value& value);
void SetTextAlign(const Napi::CallbackInfo& info, const Napi::Value& value);
inline void setContext(cairo_t *ctx) { _context = ctx; }
inline cairo_t *context(){ return _context; }
inline Canvas *canvas(){ return _canvas; }
inline bool hasShadow();
void inline setSourceRGBA(rgba_t color);
void inline setSourceRGBA(cairo_t *ctx, rgba_t color);
void setTextPath(double x, double y);
void blur(cairo_surface_t *surface, int radius);
void shadow(void (fn)(cairo_t *cr));
void shadowStart();
void shadowApply();
void savePath();
void restorePath();
void saveState();
void restoreState();
void inline setFillRule(Napi::Value value);
void fill(bool preserve = false);
void stroke(bool preserve = false);
void save();
void restore();
void setFontFromState();
void resetState();
inline PangoLayout *layout(){ return _layout; }
private:
~Context2d();
void _resetPersistentHandles();
Napi::Value _getFillColor();
Napi::Value _getStrokeColor();
void _setFillColor(Napi::Value arg);
void _setFillPattern(Napi::Value arg);
void _setStrokeColor(Napi::Value arg);
void _setStrokePattern(Napi::Value arg);
Napi::Persistent<v8::Value> _fillStyle;
Napi::Persistent<v8::Value> _strokeStyle;
Canvas *_canvas;
cairo_t *_context;
cairo_path_t *_path;
PangoLayout *_layout;
};
|