b33e9c9bff
Forgot to register ctx.get_source, done now. Originally committed to SVN as r1801.
2738 lines
74 KiB
C++
2738 lines
74 KiB
C++
/*
|
|
* Lua interface for the cairo graphics library
|
|
*
|
|
|
|
Copyright 2007 Niels Martin Hansen
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
Contact:
|
|
E-mail: <jiifurusu@gmail.com>
|
|
IRC: jfs in #aegisub on irc.rizon.net
|
|
|
|
*/
|
|
|
|
#include "cairo_wrap.h"
|
|
#include "../lua51/src/lauxlib.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
|
|
// Macros to help implementing callables
|
|
|
|
#define CALLABLE_IMPL(C,N) int C ## ::lua_ ## N (lua_State *L)
|
|
#define CALLABLE_NOTIMPL(C,N) CALLABLE_IMPL(C,N) { lua_pushliteral(L, "Method " # N " in class " # C " is not implemented"); lua_error(L); return 0; }
|
|
#define CALLABLE_REG(name) AddCallable(lua_ ## name, # name)
|
|
#define CALLABLE_REG2(func,name) AddCallable(lua_ ## func, # name)
|
|
|
|
|
|
// Maps from strings to various cairo enum types
|
|
|
|
static const char *status_names_list[] = {
|
|
"success",
|
|
"no_memory",
|
|
"invalid_restore", "invalid_pop_group", "no_current_point",
|
|
"invalid_matrix", "invalid_status", "null_pointer",
|
|
"invalid_string", "invalid_path_data",
|
|
"read_error", "write_error",
|
|
"surface_type_mismatch", "pattern_type_mismatch",
|
|
"invalid_content", "invalid_format", "invalid_visual",
|
|
"file_not_found",
|
|
"invalid_dash", "invalid_dsc_comment", "invalid_index",
|
|
"clip_not_representable",
|
|
0 };
|
|
static const char *fill_rule_list[] = {"winding", "even_odd", 0};
|
|
static const char *line_cap_list[] = {"butt", "round", "square", 0};
|
|
static const char *line_join_list[] = {"miter", "round", "bevel", 0};
|
|
static const char *antialias_types_list[] = {"default", "none", "gray", "subpixel", 0};
|
|
static const char *subpixel_order_list[] ={"default", "rgb", "bgr", "vrgb", "vbgr", 0};
|
|
static const char *hint_style_list[] = {"default", "none", "slight", "medium", "full", 0};
|
|
static const char *hint_metrics_list[] = {"default", "on", "off", 0};
|
|
static const char *content_types_list[] = {"c", "a", "ca", 0};
|
|
static const char *operators_list[] = {
|
|
"clear",
|
|
"source", "over", "in", "out", "atop",
|
|
"dest", "dest_over", "dest_in", "dest_out", "dest_atop",
|
|
"xor", "add", "saturate",
|
|
0 };
|
|
static const char *font_slant_list[] = {"", "italic", "oblique", 0};
|
|
static const char *font_weight_list[] = {"", "bold", 0};
|
|
static const char *image_formats_list[] = {"argb32", "rgb24", "a8", "a1", "rgb16_565", 0};
|
|
static const char *pattern_extend_list[] = {"none", "repeat", "reflect", "pad", 0};
|
|
static const char *pattern_filter_list[] = {"fast", "good", "best", "nearest", "bilinear", "gaussian", 0};
|
|
static const char *pattern_type_list[] = {"solid", "surface", "linear", "radial", 0};
|
|
|
|
|
|
// Misc. helper functions
|
|
|
|
static void font_extents_to_lua(lua_State *L, cairo_font_extents_t &extents)
|
|
{
|
|
lua_newtable(L);
|
|
lua_pushnumber(L, extents.ascent);
|
|
lua_setfield(L, -2, "ascent");
|
|
lua_pushnumber(L, extents.descent);
|
|
lua_setfield(L, -2, "descent");
|
|
lua_pushnumber(L, extents.height);
|
|
lua_setfield(L, -2, "height");
|
|
lua_pushnumber(L, extents.max_x_advance);
|
|
lua_setfield(L, -2, "max_x_advance");
|
|
lua_pushnumber(L, extents.max_y_advance);
|
|
lua_setfield(L, -2, "max_y_advance");
|
|
}
|
|
|
|
static void text_extents_to_lua(lua_State *L, cairo_text_extents_t &extents)
|
|
{
|
|
lua_newtable(L);
|
|
lua_pushnumber(L, extents.x_bearing);
|
|
lua_setfield(L, -2, "x_bearing");
|
|
lua_pushnumber(L, extents.y_bearing);
|
|
lua_setfield(L, -2, "y_bearing");
|
|
lua_pushnumber(L, extents.width);
|
|
lua_setfield(L, -2, "width");
|
|
lua_pushnumber(L, extents.height);
|
|
lua_setfield(L, -2, "height");
|
|
lua_pushnumber(L, extents.x_advance);
|
|
lua_setfield(L, -2, "x_advance");
|
|
lua_pushnumber(L, extents.y_advance);
|
|
lua_setfield(L, -2, "y_advance");
|
|
}
|
|
|
|
|
|
// Context (cairo_t)
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, reference)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoContext *newctx = new LuaCairoContext(L, ctx->context);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, status)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_status_t st = cairo_status(ctx->context);
|
|
lua_pushstring(L, status_names_list[st]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, save)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_save(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, restore)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_restore(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_target)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_surface_t *surf = cairo_get_target(ctx->context);
|
|
new LuaCairoSurface(L, surf);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, push_group)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_push_group(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, push_group_with_content)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_content_t ct = (cairo_content_t)luaL_checkoption(L, 1, "ca", content_types_list);
|
|
cairo_push_group_with_content(ctx->context, ct);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, pop_group)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_pattern_t *pat = cairo_pop_group(ctx->context);
|
|
LuaCairoPattern *patobj = new LuaCairoPattern(L, pat);
|
|
cairo_pattern_destroy(pat);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, pop_group_to_source)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_pop_group_to_source(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_group_target)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_surface_t *surf = cairo_get_group_target(ctx->context);
|
|
new LuaCairoSurface(L, surf);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_source_rgb)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double r = luaL_checknumber(L, 1);
|
|
double g = luaL_checknumber(L, 2);
|
|
double b = luaL_checknumber(L, 3);
|
|
cairo_set_source_rgb(ctx->context, r, g, b);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_source_rgba)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double r = luaL_checknumber(L, 1);
|
|
double g = luaL_checknumber(L, 2);
|
|
double b = luaL_checknumber(L, 3);
|
|
double a = luaL_checknumber(L, 4);
|
|
cairo_set_source_rgba(ctx->context, r, g, b, a);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_source)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoPattern *pat = LuaCairoPattern::GetObjPointer(L, 1);
|
|
cairo_set_source(ctx->context, pat->GetPattern());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_source_surface)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoSurface *surf = LuaCairoSurface::GetObjPointer(L, 1);
|
|
double surfx = luaL_checknumber(L, 2);
|
|
double surfy = luaL_checknumber(L, 3);
|
|
cairo_set_source_surface(ctx->context, surf->GetSurface(), surfx, surfy);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_source)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_pattern_t *pat = cairo_get_source(ctx->context);
|
|
// The pattern is owned by cairo here, so creating the Lua object will create the needed reference from Lua
|
|
new LuaCairoPattern(L, pat);
|
|
// Meaning that calling pattern_destroy here would be wrong
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_antialias)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_antialias_t aa = (cairo_antialias_t)luaL_checkoption(L, 1, NULL, antialias_types_list);
|
|
cairo_set_antialias(ctx->context, aa);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_antialias)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_antialias_t aa = cairo_get_antialias(ctx->context);
|
|
lua_pushstring(L, antialias_types_list[aa]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_dash)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
|
|
if (lua_isnoneornil(L, 1)) {
|
|
// left out parameters, disable dashing
|
|
cairo_set_dash(ctx->context, NULL, 0, 0);
|
|
return 0;
|
|
|
|
} else if (lua_istable(L, 1)) {
|
|
// dashing pattern in table, complex case
|
|
double offset = luaL_optnumber(L, 2, 0);
|
|
size_t num_dashes = lua_objlen(L, 1);
|
|
double *dashes = new double[num_dashes];
|
|
size_t i = 0;
|
|
lua_pushnil(L);
|
|
while (lua_next(L, 1)) {
|
|
if (lua_isnumber(L, -1)) {
|
|
dashes[i] = lua_tonumber(L, -1);
|
|
} else {
|
|
dashes[i] = 0;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
cairo_set_dash(ctx->context, dashes, (int)num_dashes, offset);
|
|
delete[] dashes;
|
|
return 0;
|
|
|
|
} else if (lua_isnumber(L, 1)) {
|
|
// single dash, alternating on/off
|
|
double dash = luaL_checknumber(L, 1);
|
|
double offset = luaL_optnumber(L, 2, 0);
|
|
if (dash > 0) {
|
|
cairo_set_dash(ctx->context, &dash, 1, offset);
|
|
} else {
|
|
// ok number was invalid, disable dashing instead of putting context into error state
|
|
cairo_set_dash(ctx->context, NULL, 0, 0);
|
|
}
|
|
return 0;
|
|
|
|
} else {
|
|
luaL_error(L, "First argument to set_dash must be nil, table or number, was %s", luaL_typename(L, 1));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_dash_count)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
int dash_count = cairo_get_dash_count(ctx->context);
|
|
lua_pushinteger(L, dash_count);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_dash)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
int dash_count = cairo_get_dash_count(ctx->context);
|
|
|
|
if (dash_count <= 0) {
|
|
lua_newtable(L);
|
|
lua_pushnumber(L, 0);
|
|
return 2;
|
|
}
|
|
|
|
double *dashes = new double[dash_count];
|
|
double offset;
|
|
cairo_get_dash(ctx->context, dashes, &offset);
|
|
lua_newtable(L);
|
|
for (int i = 0; i < dash_count; i++) {
|
|
lua_pushnumber(L, dashes[i]);
|
|
lua_rawseti(L, -2, i+1);
|
|
}
|
|
delete[] dashes;
|
|
lua_pushnumber(L, offset);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_fill_rule)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_fill_rule_t fr = (cairo_fill_rule_t)luaL_checkoption(L, 1, NULL, fill_rule_list);
|
|
cairo_set_fill_rule(ctx->context, fr);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_fill_rule)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_fill_rule_t fr = cairo_get_fill_rule(ctx->context);
|
|
lua_pushstring(L, fill_rule_list[fr]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_line_cap)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_line_cap_t lc = (cairo_line_cap_t)luaL_checkoption(L, 1, NULL, line_cap_list);
|
|
cairo_set_line_cap(ctx->context, lc);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_line_cap)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_line_cap_t lc = cairo_get_line_cap(ctx->context);
|
|
lua_pushstring(L, line_cap_list[lc]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_line_join)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_line_join_t lj = (cairo_line_join_t)luaL_checkoption(L, 1, NULL, line_join_list);
|
|
cairo_set_line_join(ctx->context, lj);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_line_join)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_line_join_t lj = cairo_get_line_join(ctx->context);
|
|
lua_pushstring(L, line_join_list[lj]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_line_width)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double w = luaL_checknumber(L, 1);
|
|
cairo_set_line_width(ctx->context, w);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_line_width)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double w = cairo_get_line_width(ctx->context);
|
|
lua_pushnumber(L, w);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_miter_limit)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double l = luaL_checknumber(L, 1);
|
|
cairo_set_miter_limit(ctx->context, l);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_miter_limit)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double l = cairo_get_miter_limit(ctx->context);
|
|
lua_pushnumber(L, l);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_operator)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_operator_t op = (cairo_operator_t)luaL_checkoption(L, 1, NULL, operators_list);
|
|
cairo_set_operator(ctx->context, op);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_operator)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_operator_t op = cairo_get_operator(ctx->context);
|
|
lua_pushstring(L, operators_list[op]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_tolerance)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double tol = luaL_checknumber(L, 1);
|
|
cairo_set_tolerance(ctx->context, tol);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_tolerance)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double tol = cairo_get_tolerance(ctx->context);
|
|
lua_pushnumber(L, tol);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, clip)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_clip(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, clip_preserve)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_clip_preserve(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, clip_extents)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x1, y1, x2, y2;
|
|
cairo_clip_extents(ctx->context, &x1, &y1, &x2, &y2);
|
|
lua_pushnumber(L, x1);
|
|
lua_pushnumber(L, y1);
|
|
lua_pushnumber(L, x2);
|
|
lua_pushnumber(L, y2);
|
|
return 4;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, reset_clip)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_reset_clip(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoContext, copy_clip_rectangle_list)
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, fill)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_fill(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, fill_preserve)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_fill_preserve(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, fill_extents)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x1, y1, x2, y2;
|
|
cairo_fill_extents(ctx->context, &x1, &y1, &x2, &y2);
|
|
lua_pushnumber(L, x1);
|
|
lua_pushnumber(L, y1);
|
|
lua_pushnumber(L, x2);
|
|
lua_pushnumber(L, y2);
|
|
return 4;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, in_fill)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
lua_pushboolean(L, cairo_in_fill(ctx->context, x, y));
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, mask)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoPattern *pat = LuaCairoPattern::GetObjPointer(L, 1);
|
|
cairo_mask(ctx->context, pat->GetPattern());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, mask_surface)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoSurface *surf = LuaCairoSurface::GetObjPointer(L, 1);
|
|
double surfx = luaL_checknumber(L, 2);
|
|
double surfy = luaL_checknumber(L, 3);
|
|
cairo_mask_surface(ctx->context, surf->GetSurface(), surfx, surfy);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, paint)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_paint(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, paint_with_alpha)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double a = luaL_checknumber(L, 1);
|
|
cairo_paint_with_alpha(ctx->context, a);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, stroke)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_stroke(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, stroke_preserve)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_stroke_preserve(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, stroke_extents)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x1, y1, x2, y2;
|
|
cairo_stroke_extents(ctx->context, &x1, &y1, &x2, &y2);
|
|
lua_pushnumber(L, x1);
|
|
lua_pushnumber(L, y1);
|
|
lua_pushnumber(L, x2);
|
|
lua_pushnumber(L, y2);
|
|
return 4;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, in_stroke)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
lua_pushboolean(L, cairo_in_stroke(ctx->context, x, y));
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, copy_page)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_copy_page(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, show_page)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_show_page(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, copy_path)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_path_t *path = cairo_copy_path(ctx->context);
|
|
new LuaCairoPath(L, path);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, copy_path_flat)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_path_t *path = cairo_copy_path_flat(ctx->context);
|
|
new LuaCairoPath(L, path);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, append_path)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoPath *path = LuaCairoPath::GetObjPointer(L, 1);
|
|
cairo_append_path(ctx->context, path->GetPath());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_current_point)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x, y;
|
|
cairo_get_current_point(ctx->context, &x, &y);
|
|
lua_pushnumber(L, x);
|
|
lua_pushnumber(L, y);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, new_path)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_new_path(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, new_sub_path)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_new_sub_path(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, close_path)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_close_path(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, arc)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double xc = luaL_checknumber(L, 1);
|
|
double yc = luaL_checknumber(L, 2);
|
|
double radius = luaL_checknumber(L, 3);
|
|
double angle1 = luaL_checknumber(L, 4);
|
|
double angle2 = luaL_checknumber(L, 5);
|
|
cairo_arc(ctx->context, xc, yc, radius, angle1, angle2);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, arc_negative)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double xc = luaL_checknumber(L, 1);
|
|
double yc = luaL_checknumber(L, 2);
|
|
double radius = luaL_checknumber(L, 3);
|
|
double angle1 = luaL_checknumber(L, 4);
|
|
double angle2 = luaL_checknumber(L, 5);
|
|
cairo_arc_negative(ctx->context, xc, yc, radius, angle1, angle2);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, curve_to)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x1 = luaL_checknumber(L, 1);
|
|
double y1 = luaL_checknumber(L, 2);
|
|
double x2 = luaL_checknumber(L, 3);
|
|
double y2 = luaL_checknumber(L, 4);
|
|
double x3 = luaL_checknumber(L, 5);
|
|
double y3 = luaL_checknumber(L, 6);
|
|
cairo_curve_to(ctx->context, x1, y1, x2, y2, x3, y3);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, line_to)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_line_to(ctx->context, x, y);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, move_to)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_move_to(ctx->context, x, y);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, rectangle)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x1 = luaL_checknumber(L, 1);
|
|
double y1 = luaL_checknumber(L, 2);
|
|
double x2 = luaL_checknumber(L, 3);
|
|
double y2 = luaL_checknumber(L, 4);
|
|
cairo_rectangle(ctx->context, x1, y1, x2, y2);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoContext, glyph_path)
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, text_path)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
const char *utf8 = luaL_checkstring(L, 1);
|
|
cairo_text_path(ctx->context, utf8);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, rel_curve_to)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x1 = luaL_checknumber(L, 1);
|
|
double y1 = luaL_checknumber(L, 2);
|
|
double x2 = luaL_checknumber(L, 3);
|
|
double y2 = luaL_checknumber(L, 4);
|
|
double x3 = luaL_checknumber(L, 5);
|
|
double y3 = luaL_checknumber(L, 6);
|
|
cairo_rel_curve_to(ctx->context, x1, y1, x2, y2, x3, y3);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, rel_line_to)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_rel_line_to(ctx->context, x, y);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, rel_move_to)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_rel_move_to(ctx->context, x, y);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, translate)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double tx = luaL_checknumber(L, 1);
|
|
double ty = luaL_checknumber(L, 2);
|
|
cairo_translate(ctx->context, tx, ty);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, scale)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double sx = luaL_checknumber(L, 1);
|
|
double sy = luaL_checknumber(L, 2);
|
|
cairo_scale(ctx->context, sx, sy);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, rotate)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double rads = luaL_checknumber(L, 1);
|
|
cairo_rotate(ctx->context, rads);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, transform)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoMatrix *mat = LuaCairoMatrix::GetObjPointer(L, 1);
|
|
cairo_transform(ctx->context, mat->GetMatrix());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_matrix)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoMatrix *mat = LuaCairoMatrix::GetObjPointer(L, 1);
|
|
cairo_set_matrix(ctx->context, mat->GetMatrix());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_matrix)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_matrix_t mat;
|
|
cairo_get_matrix(ctx->context, &mat);
|
|
new LuaCairoMatrix(L, &mat);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, identity_matrix)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_identity_matrix(ctx->context);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, user_to_device)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_user_to_device(ctx->context, &x, &y);
|
|
lua_pushnumber(L, x);
|
|
lua_pushnumber(L, y);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, user_to_device_distance)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_user_to_device_distance(ctx->context, &x, &y);
|
|
lua_pushnumber(L, x);
|
|
lua_pushnumber(L, y);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, device_to_user)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_device_to_user(ctx->context,& x, &y);
|
|
lua_pushnumber(L, x);
|
|
lua_pushnumber(L, y);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, device_to_user_distance)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_device_to_user_distance(ctx->context, &x, &y);
|
|
lua_pushnumber(L, x);
|
|
lua_pushnumber(L, y);
|
|
return 2;
|
|
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, select_font_face)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
const char *family = luaL_checkstring(L, 1);
|
|
cairo_font_slant_t slant = (cairo_font_slant_t)luaL_checkoption(L, 2, "", font_slant_list);
|
|
cairo_font_weight_t weight = (cairo_font_weight_t)luaL_checkoption(L, 3, "", font_weight_list);
|
|
cairo_select_font_face(ctx->context, family, slant, weight);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_font_size)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
double sz = luaL_checknumber(L, 1);
|
|
cairo_set_font_size(ctx->context, sz);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_font_matrix)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoMatrix *mat = LuaCairoMatrix::GetObjPointer(L, 1);
|
|
cairo_set_font_matrix(ctx->context, mat->GetMatrix());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_font_matrix)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoMatrix *mat = new LuaCairoMatrix(L);
|
|
cairo_get_font_matrix(ctx->context, mat->GetMatrix());
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_font_options)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoFontOptions *fo = LuaCairoFontOptions::GetObjPointer(L, 1);
|
|
cairo_set_font_options(ctx->context, fo->GetFontOptions());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_font_options)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoFontOptions *fo = new LuaCairoFontOptions(L);
|
|
cairo_get_font_options(ctx->context, fo->GetFontOptions());
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_font_face)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoFontFace *face = LuaCairoFontFace::GetObjPointer(L, 1);
|
|
cairo_set_font_face(ctx->context, face->GetFontFace());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_font_face)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_font_face_t *face = cairo_get_font_face(ctx->context);
|
|
new LuaCairoFontFace(L, face);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, set_scaled_font)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoScaledFont *sf = LuaCairoScaledFont::GetObjPointer(L, 1);
|
|
cairo_set_scaled_font(ctx->context, sf->GetScaledFont());
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, get_scaled_font)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_scaled_font_t *sf = cairo_get_scaled_font(ctx->context);
|
|
new LuaCairoScaledFont(L, sf);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, show_text)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
const char *utf8 = luaL_checkstring(L, 1);
|
|
cairo_show_text(ctx->context, utf8);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoContext, show_glyphs)
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, font_extents)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_font_extents_t extents;
|
|
cairo_font_extents(ctx->context, &extents);
|
|
font_extents_to_lua(L, extents);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoContext, text_extents)
|
|
{
|
|
LuaCairoContext *ctx = GetObjPointer(L, lua_upvalueindex(1));
|
|
const char *utf8 = luaL_checkstring(L, 1);
|
|
cairo_text_extents_t extents;
|
|
cairo_text_extents(ctx->context, utf8, &extents);
|
|
text_extents_to_lua(L, extents);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoContext, glyph_extents)
|
|
|
|
const char *LuaCairoContext::GetTypeName()
|
|
{
|
|
return "context";
|
|
}
|
|
|
|
LuaCairoContext::LuaCairoContext(lua_State *L, cairo_t *_context) :
|
|
LuaCairoBase(L)
|
|
{
|
|
CALLABLE_REG(reference);
|
|
CALLABLE_REG(status);
|
|
CALLABLE_REG(save);
|
|
CALLABLE_REG(restore);
|
|
CALLABLE_REG(get_target);
|
|
CALLABLE_REG(push_group);
|
|
CALLABLE_REG(push_group_with_content);
|
|
CALLABLE_REG(pop_group);
|
|
CALLABLE_REG(pop_group_to_source);
|
|
CALLABLE_REG(get_group_target);
|
|
CALLABLE_REG(set_source_rgb);
|
|
CALLABLE_REG(set_source_rgba);
|
|
CALLABLE_REG(set_source);
|
|
CALLABLE_REG(set_source_surface);
|
|
CALLABLE_REG(get_source);
|
|
CALLABLE_REG(set_antialias);
|
|
CALLABLE_REG(get_antialias);
|
|
CALLABLE_REG(set_dash);
|
|
CALLABLE_REG(get_dash_count);
|
|
CALLABLE_REG(get_dash);
|
|
CALLABLE_REG(set_fill_rule);
|
|
CALLABLE_REG(get_fill_rule);
|
|
CALLABLE_REG(set_line_cap);
|
|
CALLABLE_REG(get_line_cap);
|
|
CALLABLE_REG(set_line_join);
|
|
CALLABLE_REG(get_line_join);
|
|
CALLABLE_REG(set_line_width);
|
|
CALLABLE_REG(get_line_width);
|
|
CALLABLE_REG(set_miter_limit);
|
|
CALLABLE_REG(get_miter_limit);
|
|
CALLABLE_REG(set_operator);
|
|
CALLABLE_REG(get_operator);
|
|
CALLABLE_REG(set_tolerance);
|
|
CALLABLE_REG(get_tolerance);
|
|
CALLABLE_REG(clip);
|
|
CALLABLE_REG(clip_preserve);
|
|
CALLABLE_REG(clip_extents);
|
|
CALLABLE_REG(reset_clip);
|
|
CALLABLE_REG(copy_clip_rectangle_list);
|
|
CALLABLE_REG(fill);
|
|
CALLABLE_REG(fill_preserve);
|
|
CALLABLE_REG(fill_extents);
|
|
CALLABLE_REG(in_fill);
|
|
CALLABLE_REG(mask);
|
|
CALLABLE_REG(mask_surface);
|
|
CALLABLE_REG(paint);
|
|
CALLABLE_REG(paint_with_alpha);
|
|
CALLABLE_REG(stroke);
|
|
CALLABLE_REG(stroke_preserve);
|
|
CALLABLE_REG(stroke_extents);
|
|
CALLABLE_REG(in_stroke);
|
|
CALLABLE_REG(copy_page);
|
|
CALLABLE_REG(show_page);
|
|
CALLABLE_REG(copy_path);
|
|
CALLABLE_REG(copy_path_flat);
|
|
CALLABLE_REG(append_path);
|
|
CALLABLE_REG(get_current_point);
|
|
CALLABLE_REG(new_path);
|
|
CALLABLE_REG(new_sub_path);
|
|
CALLABLE_REG(close_path);
|
|
CALLABLE_REG(arc);
|
|
CALLABLE_REG(arc_negative);
|
|
CALLABLE_REG(curve_to);
|
|
CALLABLE_REG(line_to);
|
|
CALLABLE_REG(move_to);
|
|
CALLABLE_REG(rectangle);
|
|
CALLABLE_REG(glyph_path);
|
|
CALLABLE_REG(text_path);
|
|
CALLABLE_REG(rel_curve_to);
|
|
CALLABLE_REG(rel_line_to);
|
|
CALLABLE_REG(rel_move_to);
|
|
CALLABLE_REG(translate);
|
|
CALLABLE_REG(scale);
|
|
CALLABLE_REG(rotate);
|
|
CALLABLE_REG(transform);
|
|
CALLABLE_REG(set_matrix);
|
|
CALLABLE_REG(get_matrix);
|
|
CALLABLE_REG(identity_matrix);
|
|
CALLABLE_REG(user_to_device);
|
|
CALLABLE_REG(user_to_device_distance);
|
|
CALLABLE_REG(device_to_user);
|
|
CALLABLE_REG(device_to_user_distance);
|
|
CALLABLE_REG(select_font_face);
|
|
CALLABLE_REG(set_font_size);
|
|
CALLABLE_REG(set_font_matrix);
|
|
CALLABLE_REG(get_font_matrix);
|
|
CALLABLE_REG(set_font_options);
|
|
CALLABLE_REG(get_font_options);
|
|
CALLABLE_REG(set_font_face);
|
|
CALLABLE_REG(get_font_face);
|
|
CALLABLE_REG(set_scaled_font);
|
|
CALLABLE_REG(get_scaled_font);
|
|
CALLABLE_REG(show_text);
|
|
CALLABLE_REG(show_glyphs);
|
|
CALLABLE_REG(font_extents);
|
|
CALLABLE_REG(text_extents);
|
|
CALLABLE_REG(glyph_extents);
|
|
|
|
cairo_reference(_context);
|
|
context = _context;
|
|
}
|
|
|
|
LuaCairoContext::~LuaCairoContext()
|
|
{
|
|
cairo_destroy(context);
|
|
}
|
|
|
|
|
|
// Surface (cairo_surface_t)
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, create_similar)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_content_t ct = (cairo_content_t)luaL_checkoption(L, 1, NULL, content_types_list);
|
|
int width = luaL_checkint(L, 2);
|
|
int height = luaL_checkint(L, 3);
|
|
cairo_surface_t *nsurf = cairo_surface_create_similar(surf->surface, ct, width, height);
|
|
new LuaCairoSurface(L, nsurf);
|
|
cairo_surface_destroy(nsurf);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoSurface, reference)
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, status)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_status_t st = cairo_surface_status(surf->surface);
|
|
lua_pushstring(L, status_names_list[st]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, create_context)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
|
|
cairo_t *context = cairo_create(surf->surface);
|
|
|
|
if (!context || cairo_status(context) != CAIRO_STATUS_SUCCESS) {
|
|
lua_pushliteral(L, "Failed creating cairo context");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
|
|
LuaCairoContext *ctxojb = new LuaCairoContext(L, context);
|
|
cairo_destroy(context);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, finish)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_surface_finish(surf->surface);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, flush)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_surface_flush(surf->surface);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, get_font_options)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoFontOptions *fo = new LuaCairoFontOptions(L);
|
|
cairo_surface_get_font_options(surf->surface, fo->GetFontOptions());
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, get_content)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_content_t ct = cairo_surface_get_content(surf->surface);
|
|
lua_pushstring(L, content_types_list[ct]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, mark_dirty)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_surface_mark_dirty(surf->surface);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, mark_dirty_rectangle)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
int x = luaL_checkint(L, 1);
|
|
int y = luaL_checkint(L, 2);
|
|
int width = luaL_checkint(L, 3);
|
|
int height = luaL_checkint(L, 4);
|
|
cairo_surface_mark_dirty_rectangle(surf->surface, x, y, width, height);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, set_device_offset)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
double xofs = luaL_checknumber(L, 1);
|
|
double yofs = luaL_checknumber(L, 2);
|
|
cairo_surface_set_device_offset(surf->surface, xofs, yofs);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, get_device_offset)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
double xofs, yofs;
|
|
cairo_surface_get_device_offset(surf->surface, &xofs, &yofs);
|
|
lua_pushnumber(L, xofs);
|
|
lua_pushnumber(L, yofs);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, set_fallback_resolution)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
double xppi = luaL_checknumber(L, 1);
|
|
double yppi = luaL_checknumber(L, 2);
|
|
cairo_surface_set_device_offset(surf->surface, xppi, yppi);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoSurface, get_type)
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, image_get_format)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
if (cairo_surface_get_type(surf->GetSurface()) != CAIRO_SURFACE_TYPE_IMAGE) {
|
|
lua_pushliteral(L, "Surface is not an image surface");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
|
|
switch (cairo_image_surface_get_format(surf->GetSurface())) {
|
|
case CAIRO_FORMAT_ARGB32:
|
|
lua_pushliteral(L, "argb32");
|
|
return 1;
|
|
case CAIRO_FORMAT_RGB24:
|
|
lua_pushliteral(L, "rgb24");
|
|
return 1;
|
|
case CAIRO_FORMAT_A8:
|
|
lua_pushliteral(L, "a8");
|
|
return 1;
|
|
case CAIRO_FORMAT_A1:
|
|
lua_pushliteral(L, "a1");
|
|
return 1;
|
|
default:
|
|
lua_pushnil(L);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, image_get_width)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
if (cairo_surface_get_type(surf->GetSurface()) != CAIRO_SURFACE_TYPE_IMAGE) {
|
|
lua_pushliteral(L, "Surface is not an image surface");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
|
|
lua_pushinteger(L, cairo_image_surface_get_width(surf->GetSurface()));
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, image_get_height)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
if (cairo_surface_get_type(surf->GetSurface()) != CAIRO_SURFACE_TYPE_IMAGE) {
|
|
lua_pushliteral(L, "Surface is not an image surface");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
|
|
lua_pushinteger(L, cairo_image_surface_get_height(surf->GetSurface()));
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoSurface, image_set_pixel)
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, image_get_pixel)
|
|
{
|
|
LuaCairoSurface *surf = GetObjPointer(L, lua_upvalueindex(1));
|
|
int x = luaL_checkint(L, 1);
|
|
int y = luaL_checkint(L, 2);
|
|
if (cairo_surface_get_type(surf->surface) != CAIRO_SURFACE_TYPE_IMAGE) {
|
|
lua_pushliteral(L, "Surface is not an image surface");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
|
|
// Assume the surface is already flush()ed
|
|
int width = cairo_image_surface_get_width(surf->surface);
|
|
int height = cairo_image_surface_get_height(surf->surface);
|
|
int stride = cairo_image_surface_get_stride(surf->surface);
|
|
cairo_format_t format = cairo_image_surface_get_format(surf->surface);
|
|
unsigned char *data = cairo_image_surface_get_data(surf->surface);
|
|
|
|
switch (format) {
|
|
case CAIRO_FORMAT_ARGB32: {
|
|
uint32_t pixel = *(uint32_t*)(data + y*stride + x * 4);
|
|
lua_pushinteger(L, (pixel & 0xff000000)>>24); // alpha
|
|
lua_pushinteger(L, (pixel & 0x00ff0000)>>16); // red
|
|
lua_pushinteger(L, (pixel & 0x0000ff00)>>8); // green
|
|
lua_pushinteger(L, pixel & 0x000000ff); // blue
|
|
return 4; }
|
|
|
|
case CAIRO_FORMAT_RGB24: {
|
|
uint32_t pixel = *(uint32_t*)(data + y*stride + x * 4);
|
|
lua_pushinteger(L, (pixel & 0x00ff0000)>>16); // red
|
|
lua_pushinteger(L, (pixel & 0x0000ff00)>>8); // green
|
|
lua_pushinteger(L, pixel & 0x000000ff); // blue
|
|
return 3; }
|
|
|
|
case CAIRO_FORMAT_A8:
|
|
lua_pushinteger(L, data[y*stride+x]);
|
|
return 1;
|
|
|
|
default:
|
|
lua_pushliteral(L, "Unhandled pixel format in image surface get pixel");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoSurface, image_surface_create)
|
|
{
|
|
// Swap arguments a bit and make a default value for the format
|
|
int width = luaL_checkint(L, 1);
|
|
int height = luaL_checkint(L, 2);
|
|
cairo_format_t format = (cairo_format_t)luaL_checkoption(L, 3, "argb32", image_formats_list);
|
|
|
|
// Create surface from parameters
|
|
cairo_surface_t *surf = cairo_image_surface_create(format, width, height);
|
|
|
|
// Check that the surface was successfully created
|
|
if (!surf || cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS)
|
|
return 0;
|
|
|
|
// Create wrapping Lua object
|
|
LuaCairoSurface *surfobj = new LuaCairoSurface(L, surf);
|
|
// Lua object takes its own reference to surface, so release ours
|
|
cairo_surface_destroy(surf);
|
|
// Return surface object
|
|
return 1;
|
|
}
|
|
|
|
const char *LuaCairoSurface::GetTypeName()
|
|
{
|
|
return "surface";
|
|
}
|
|
|
|
LuaCairoSurface::LuaCairoSurface(lua_State *L, cairo_surface_t *_surface) :
|
|
LuaCairoBase(L)
|
|
{
|
|
cairo_surface_reference(_surface);
|
|
surface = _surface;
|
|
|
|
cairo_surface_type_t st = cairo_surface_get_type(surface);
|
|
|
|
CALLABLE_REG(create_similar);
|
|
CALLABLE_REG(reference);
|
|
CALLABLE_REG(status);
|
|
CALLABLE_REG(create_context);
|
|
CALLABLE_REG(finish);
|
|
CALLABLE_REG(flush);
|
|
CALLABLE_REG(get_font_options);
|
|
CALLABLE_REG(get_content);
|
|
CALLABLE_REG(mark_dirty);
|
|
CALLABLE_REG(mark_dirty_rectangle);
|
|
CALLABLE_REG(set_device_offset);
|
|
CALLABLE_REG(get_device_offset);
|
|
CALLABLE_REG(set_fallback_resolution);
|
|
CALLABLE_REG(get_type);
|
|
|
|
if (st == CAIRO_SURFACE_TYPE_IMAGE) {
|
|
CALLABLE_REG2(image_get_format, get_format);
|
|
CALLABLE_REG2(image_get_width, get_width);
|
|
CALLABLE_REG2(image_get_height, get_height);
|
|
CALLABLE_REG2(image_set_pixel, set_pixel);
|
|
CALLABLE_REG2(image_get_pixel, get_pixel);
|
|
}
|
|
}
|
|
|
|
LuaCairoSurface::~LuaCairoSurface()
|
|
{
|
|
cairo_surface_destroy(surface);
|
|
}
|
|
|
|
|
|
// Font face (cairo_font_face_t)
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoFontFace, create_scaled_font)
|
|
CALLABLE_NOTIMPL(LuaCairoFontFace, reference)
|
|
|
|
CALLABLE_IMPL(LuaCairoFontFace, status)
|
|
{
|
|
LuaCairoFontFace *face = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_status_t st = cairo_font_face_status(face->font_face);
|
|
lua_pushstring(L, status_names_list[st]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoFontFace, get_type)
|
|
|
|
const char *LuaCairoFontFace::GetTypeName()
|
|
{
|
|
return "font_face";
|
|
}
|
|
|
|
LuaCairoFontFace::LuaCairoFontFace(lua_State *L, cairo_font_face_t *_font_face) :
|
|
LuaCairoBase(L)
|
|
{
|
|
CALLABLE_REG(create_scaled_font);
|
|
CALLABLE_REG(reference);
|
|
CALLABLE_REG(status);
|
|
CALLABLE_REG(get_type);
|
|
|
|
cairo_font_face_reference(_font_face);
|
|
font_face = _font_face;
|
|
}
|
|
|
|
LuaCairoFontFace::~LuaCairoFontFace()
|
|
{
|
|
cairo_font_face_destroy(font_face);
|
|
}
|
|
|
|
|
|
// Scaled font (cairo_scaled_font_t)
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoScaledFont, reference)
|
|
|
|
CALLABLE_IMPL(LuaCairoScaledFont, status)
|
|
{
|
|
LuaCairoScaledFont*sf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_status_t st = cairo_scaled_font_status(sf->scaled_font);
|
|
lua_pushstring(L, status_names_list[st]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoScaledFont, extents)
|
|
{
|
|
LuaCairoScaledFont *scf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_font_extents_t extents;
|
|
cairo_scaled_font_extents(scf->scaled_font, &extents);
|
|
font_extents_to_lua(L, extents);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoScaledFont, text_extents)
|
|
{
|
|
LuaCairoScaledFont *scf = GetObjPointer(L, lua_upvalueindex(1));
|
|
const char *utf8 = luaL_checkstring(L, 1);
|
|
cairo_text_extents_t extents;
|
|
cairo_scaled_font_text_extents(scf->scaled_font, utf8, &extents);
|
|
text_extents_to_lua(L, extents);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoScaledFont, glyph_extents)
|
|
|
|
CALLABLE_IMPL(LuaCairoScaledFont, get_font_face)
|
|
{
|
|
LuaCairoScaledFont *scf = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_font_face_t *face = cairo_scaled_font_get_font_face(scf->scaled_font);
|
|
new LuaCairoFontFace(L, face);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoScaledFont, get_font_options)
|
|
{
|
|
LuaCairoScaledFont *scf = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoFontOptions *opt = new LuaCairoFontOptions(L);
|
|
cairo_scaled_font_get_font_options(scf->scaled_font, opt->GetFontOptions());
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoScaledFont, get_font_matrix)
|
|
{
|
|
LuaCairoScaledFont *scf = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoMatrix *mat = new LuaCairoMatrix(L);
|
|
cairo_scaled_font_get_font_matrix(scf->scaled_font, mat->GetMatrix());
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoScaledFont, get_ctm)
|
|
{
|
|
LuaCairoScaledFont *scf = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoMatrix *mat = new LuaCairoMatrix(L);
|
|
cairo_scaled_font_get_ctm(scf->scaled_font, mat->GetMatrix());
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoScaledFont, get_type)
|
|
|
|
const char *LuaCairoScaledFont::GetTypeName()
|
|
{
|
|
return "scaled_font";
|
|
}
|
|
|
|
LuaCairoScaledFont::LuaCairoScaledFont(lua_State *L, cairo_scaled_font_t *_scaled_font) :
|
|
LuaCairoBase(L)
|
|
{
|
|
CALLABLE_REG(reference);
|
|
CALLABLE_REG(status);
|
|
CALLABLE_REG(extents);
|
|
CALLABLE_REG(text_extents);
|
|
CALLABLE_REG(glyph_extents);
|
|
CALLABLE_REG(get_font_face);
|
|
CALLABLE_REG(get_font_options);
|
|
CALLABLE_REG(get_font_matrix);
|
|
CALLABLE_REG(get_ctm);
|
|
CALLABLE_REG(get_type);
|
|
|
|
cairo_scaled_font_reference(_scaled_font);
|
|
scaled_font = _scaled_font;
|
|
}
|
|
|
|
LuaCairoScaledFont::~LuaCairoScaledFont()
|
|
{
|
|
cairo_scaled_font_destroy(scaled_font);
|
|
}
|
|
|
|
|
|
// Font options (cairo_font_options_t)
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, copy)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_font_options_t *nfo = cairo_font_options_copy(fo->font_options);
|
|
new LuaCairoFontOptions(L, nfo);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, status)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_status_t st = cairo_font_options_status(fo->font_options);
|
|
lua_pushstring(L, status_names_list[st]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, merge)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoFontOptions *other = GetObjPointer(L, 1);
|
|
cairo_font_options_merge(fo->font_options, other->font_options);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, hash)
|
|
{
|
|
char hash[sizeof(unsigned long)*2+1]; // hex + null
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
unsigned long lhash = cairo_font_options_hash(fo->font_options);
|
|
sprintf(hash, "%0*x", sizeof(unsigned long)*2, lhash);
|
|
lua_pushstring(L, hash);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, equal)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoFontOptions *other = GetObjPointer(L, 1);
|
|
cairo_bool_t eq = cairo_font_options_equal(fo->font_options, other->font_options);
|
|
lua_pushboolean(L, eq);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, set_antialias)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_antialias_t aa = (cairo_antialias_t)luaL_checkoption(L, 1, NULL, antialias_types_list);
|
|
cairo_font_options_set_antialias(fo->font_options, aa);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, get_antialias)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_antialias_t aa = cairo_font_options_get_antialias(fo->font_options);
|
|
lua_pushstring(L, antialias_types_list[aa]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, set_subpixel_order)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_subpixel_order_t spo = (cairo_subpixel_order_t)luaL_checkoption(L, 1, NULL, subpixel_order_list);
|
|
cairo_font_options_set_subpixel_order(fo->font_options, spo);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, get_subpixel_order)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_subpixel_order_t spo = cairo_font_options_get_subpixel_order(fo->font_options);
|
|
lua_pushstring(L, subpixel_order_list[spo]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, set_hint_style)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_hint_style_t hs = (cairo_hint_style_t)luaL_checkoption(L, 1, NULL, hint_style_list);
|
|
cairo_font_options_set_hint_style(fo->font_options, hs);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, get_hint_style)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_hint_style_t hs = cairo_font_options_get_hint_style(fo->font_options);
|
|
lua_pushstring(L, hint_style_list[hs]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, set_hint_metrics)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_hint_metrics_t hm = (cairo_hint_metrics_t)luaL_checkoption(L, 1, NULL, hint_metrics_list);
|
|
cairo_font_options_set_hint_metrics(fo->font_options, hm);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, get_hint_metrics)
|
|
{
|
|
LuaCairoFontOptions *fo = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_hint_metrics_t hm = cairo_font_options_get_hint_metrics(fo->font_options);
|
|
lua_pushstring(L, hint_metrics_list[hm]);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoFontOptions, create)
|
|
{
|
|
new LuaCairoFontOptions(L);
|
|
return 1;
|
|
}
|
|
|
|
void LuaCairoFontOptions::RegFontOptionsCallables()
|
|
{
|
|
CALLABLE_REG(copy);
|
|
CALLABLE_REG(status);
|
|
CALLABLE_REG(merge);
|
|
CALLABLE_REG(hash);
|
|
CALLABLE_REG(equal);
|
|
CALLABLE_REG(set_antialias);
|
|
CALLABLE_REG(get_antialias);
|
|
CALLABLE_REG(set_subpixel_order);
|
|
CALLABLE_REG(get_subpixel_order);
|
|
CALLABLE_REG(set_hint_style);
|
|
CALLABLE_REG(get_hint_style);
|
|
CALLABLE_REG(set_hint_metrics);
|
|
CALLABLE_REG(get_hint_metrics);
|
|
}
|
|
|
|
const char *LuaCairoFontOptions::GetTypeName()
|
|
{
|
|
return "font_options";
|
|
}
|
|
|
|
LuaCairoFontOptions::LuaCairoFontOptions(lua_State *L) :
|
|
LuaCairoBase(L)
|
|
{
|
|
RegFontOptionsCallables();
|
|
|
|
owned = true;
|
|
font_options = cairo_font_options_create();
|
|
}
|
|
|
|
LuaCairoFontOptions::LuaCairoFontOptions(lua_State *L, cairo_font_options_t *_font_options) :
|
|
LuaCairoBase(L)
|
|
{
|
|
RegFontOptionsCallables();
|
|
|
|
owned = false;
|
|
font_options = _font_options;
|
|
}
|
|
|
|
LuaCairoFontOptions::~LuaCairoFontOptions()
|
|
{
|
|
if (owned)
|
|
cairo_font_options_destroy(font_options);
|
|
}
|
|
|
|
|
|
// Matrix (cairo_matrix_t)
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, init)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double xx = luaL_checknumber(L, 1);
|
|
double yx = luaL_checknumber(L, 2);
|
|
double xy = luaL_checknumber(L, 3);
|
|
double yy = luaL_checknumber(L, 4);
|
|
double x0 = luaL_checknumber(L, 5);
|
|
double y0 = luaL_checknumber(L, 6);
|
|
cairo_matrix_init(&mat->matrix, xx, yx, xy, yy, x0, y0);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, init_identity)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_matrix_init_identity(&mat->matrix);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, init_translate)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double tx = luaL_checknumber(L, 1);
|
|
double ty = luaL_checknumber(L, 2);
|
|
cairo_matrix_init_translate(&mat->matrix, tx, ty);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, init_scale)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double sx = luaL_checknumber(L, 1);
|
|
double sy = luaL_checknumber(L, 2);
|
|
cairo_matrix_init_scale(&mat->matrix, sx, sy);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, init_rotate)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double rads = luaL_checknumber(L, 1);
|
|
cairo_matrix_init_rotate(&mat->matrix, rads);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, translate)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double tx = luaL_checknumber(L, 1);
|
|
double ty = luaL_checknumber(L, 2);
|
|
cairo_matrix_translate(&mat->matrix, tx, ty);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, scale)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double sx = luaL_checknumber(L, 1);
|
|
double sy = luaL_checknumber(L, 2);
|
|
cairo_matrix_scale(&mat->matrix, sx, sy);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, rotate)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double rads = luaL_checknumber(L, 1);
|
|
cairo_matrix_rotate(&mat->matrix, rads);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, invert)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_status_t res = cairo_matrix_invert(&mat->matrix);
|
|
if (res == CAIRO_STATUS_SUCCESS)
|
|
lua_pushboolean(L, 1);
|
|
else
|
|
lua_pushboolean(L, 0);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, multiply)
|
|
{
|
|
LuaCairoMatrix *mat1 = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
LuaCairoMatrix *mat2 = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
cairo_matrix_t res;
|
|
cairo_matrix_multiply(&res, &mat1->matrix, &mat2->matrix);
|
|
new LuaCairoMatrix(L, &res);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, transform_distance)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double dx = luaL_checknumber(L, 1);
|
|
double dy = luaL_checknumber(L, 2);
|
|
cairo_matrix_transform_distance(&mat->matrix, &dx, &dy);
|
|
lua_pushnumber(L, dx);
|
|
lua_pushnumber(L, dy);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, transform_point)
|
|
{
|
|
LuaCairoMatrix *mat = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_checknumber(L, 2);
|
|
cairo_matrix_transform_distance(&mat->matrix, &x, &y);
|
|
lua_pushnumber(L, x);
|
|
lua_pushnumber(L, y);
|
|
return 2;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, op_add)
|
|
{
|
|
if (lua_isuserdata(L, 1) && lua_isuserdata(L, 2)) {
|
|
// matrix + matrix (pointwise)
|
|
LuaCairoMatrix *mat1 = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
LuaCairoMatrix *mat2 = (LuaCairoMatrix*)GetObjPointer(L, 2);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_t &a = mat1->matrix, &b = mat2->matrix, &res = matR->matrix;
|
|
res.xx = a.xx + b.xx; res.yx = a.yx + b.yx;
|
|
res.xy = a.xy + b.xy; res.yy = a.yy + b.yy;
|
|
res.x0 = a.x0 + b.x0; res.y0 = a.y0 + b.y0;
|
|
return 1;
|
|
|
|
} else if (lua_isuserdata(L, 1) && lua_isnumber(L, 2)) {
|
|
// matrix + number
|
|
LuaCairoMatrix *matI = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
double num = luaL_checknumber(L, 2);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_t &I = matI->matrix, &R = matR->matrix;
|
|
R.xx = num + I.xx; R.yx = num + I.yx;
|
|
R.xy = num + I.xy; R.yy = num + I.yy;
|
|
R.x0 = num + I.x0; R.y0 = num + I.y0;
|
|
return 1;
|
|
|
|
} else {
|
|
lua_pushliteral(L, "Unsupported addition operation on matrix");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, op_sub)
|
|
{
|
|
if (lua_isuserdata(L, 1) && lua_isuserdata(L, 2)) {
|
|
// matrix - matrix (pointwise)
|
|
LuaCairoMatrix *mat1 = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
LuaCairoMatrix *mat2 = (LuaCairoMatrix*)GetObjPointer(L, 2);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_t &a = mat1->matrix, &b = mat2->matrix, &res = matR->matrix;
|
|
res.xx = a.xx - b.xx; res.yx = a.yx - b.yx;
|
|
res.xy = a.xy - b.xy; res.yy = a.yy - b.yy;
|
|
res.x0 = a.x0 - b.x0; res.y0 = a.y0 - b.y0;
|
|
return 1;
|
|
|
|
} else if (lua_isuserdata(L, 1) && lua_isnumber(L, 2)) {
|
|
// matrix - number
|
|
LuaCairoMatrix *matI = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
double num = luaL_checknumber(L, 2);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_t &I = matI->matrix, &R = matR->matrix;
|
|
R.xx = I.xx - num; R.yx = I.yx - num;
|
|
R.xy = I.xy - num; R.yy = I.yy - num;
|
|
R.x0 = I.x0 - num; R.y0 = I.y0 - num;
|
|
return 1;
|
|
|
|
} else {
|
|
lua_pushliteral(L, "Unsupported subtraction operation on matrix");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, op_mul)
|
|
{
|
|
if (lua_isuserdata(L, 1) && lua_isuserdata(L, 2)) {
|
|
// matrix * matrix (matrix multiplication)
|
|
LuaCairoMatrix *mat1 = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
LuaCairoMatrix *mat2 = (LuaCairoMatrix*)GetObjPointer(L, 2);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_multiply(&matR->matrix, &mat1->matrix, &mat2->matrix);
|
|
return 1;
|
|
|
|
} else if ((lua_isuserdata(L, 1) && lua_isnumber(L, 2)) || (lua_isnumber(L, 1) && lua_isuserdata(L, 2))) {
|
|
// matrix * number or number * matrix
|
|
LuaCairoMatrix *matI;
|
|
double num;
|
|
if (lua_isuserdata(L, 1)) {
|
|
matI = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
num = luaL_checknumber(L, 2);
|
|
} else {
|
|
num = luaL_checknumber(L, 1);
|
|
matI = (LuaCairoMatrix*)GetObjPointer(L, 2);
|
|
}
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_t &I = matI->matrix, &R = matR->matrix;
|
|
R.xx = num * I.xx; R.yx = num * I.yx;
|
|
R.xy = num * I.xy; R.yy = num * I.yy;
|
|
R.x0 = num * I.x0; R.y0 = num * I.y0;
|
|
return 1;
|
|
|
|
} else {
|
|
lua_pushliteral(L, "Unsupported multiplication operation on matrix");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, op_div)
|
|
{
|
|
if (lua_isuserdata(L, 1) && lua_isnumber(L, 2)) {
|
|
// matrix / number = matrix * (1/number)
|
|
LuaCairoMatrix *matI = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
double num = luaL_checknumber(L, 2);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_t &I = matI->matrix, &R = matR->matrix;
|
|
R.xx = I.xx / num; R.yx = I.yx / num;
|
|
R.xy = I.xy / num; R.yy = I.yy / num;
|
|
R.x0 = I.x0 / num; R.y0 = I.y0 / num;
|
|
return 1;
|
|
|
|
} else if (lua_isnumber(L, 1) && lua_isuserdata(L, 2)) {
|
|
// number / matrix = number * inv(matrix)
|
|
LuaCairoMatrix *matI = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
double num = luaL_checknumber(L, 2);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L, &matI->matrix);
|
|
cairo_matrix_t &I = matI->matrix, &R = matR->matrix;
|
|
if (!cairo_matrix_invert(&R)) {
|
|
// inversion failed, result is nil
|
|
lua_pushnil(L);
|
|
return 1;
|
|
}
|
|
R.xx = R.xx * num; R.yx = R.yx * num;
|
|
R.xy = R.xy * num; R.yy = R.yy * num;
|
|
R.x0 = R.x0 * num; R.y0 = R.y0 * num;
|
|
return 1;
|
|
|
|
} else {
|
|
lua_pushliteral(L, "Unsupported division operation on matrix");
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, op_unm)
|
|
{
|
|
LuaCairoMatrix *matI = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
LuaCairoMatrix *matR = new LuaCairoMatrix(L);
|
|
cairo_matrix_t &I = matI->matrix, &R = matR->matrix;
|
|
R.xx = -I.xx; R.yx = -I.yx;
|
|
R.xy = -I.xy; R.yy = -I.yy;
|
|
R.x0 = -I.x0; R.y0 = -I.y0;
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, op_eq)
|
|
{
|
|
LuaCairoMatrix *mat1 = (LuaCairoMatrix*)GetObjPointer(L, 1);
|
|
LuaCairoMatrix *mat2 = (LuaCairoMatrix*)GetObjPointer(L, 2);
|
|
cairo_matrix_t &a = mat1->matrix, &b = mat2->matrix;
|
|
bool res =
|
|
a.xx==b.xx && a.yx==b.yx &&
|
|
a.xy==b.xy && a.yy==b.yy &&
|
|
a.x0==b.x0 && a.y0==b.y0;
|
|
lua_pushboolean(L, (int)res);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, copy)
|
|
{
|
|
LuaCairoMatrix *org = (LuaCairoMatrix*)GetObjPointer(L, lua_upvalueindex(1));
|
|
new LuaCairoMatrix(L, &org->matrix);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoMatrix, create)
|
|
{
|
|
new LuaCairoMatrix(L);
|
|
return 1;
|
|
}
|
|
|
|
void LuaCairoMatrix::RegMatrixCallables(lua_State *L)
|
|
{
|
|
CALLABLE_REG(init);
|
|
CALLABLE_REG(init_identity);
|
|
CALLABLE_REG(init_translate);
|
|
CALLABLE_REG(init_scale);
|
|
CALLABLE_REG(init_rotate);
|
|
CALLABLE_REG(translate);
|
|
CALLABLE_REG(scale);
|
|
CALLABLE_REG(rotate);
|
|
CALLABLE_REG(invert);
|
|
CALLABLE_REG(multiply);
|
|
CALLABLE_REG(transform_distance);
|
|
CALLABLE_REG(transform_point);
|
|
CALLABLE_REG(copy);
|
|
}
|
|
|
|
int LuaCairoMatrix::internal_lua_index(lua_State *L)
|
|
{
|
|
if (lua_type(L, 2) == LUA_TSTRING) {
|
|
const char *field = lua_tostring(L, 2);
|
|
if (strcmp(field, "xx") == 0) {
|
|
lua_pushnumber(L, matrix.xx);
|
|
return 1;
|
|
} else if (strcmp(field, "yx") == 0) {
|
|
lua_pushnumber(L, matrix.yx);
|
|
return 1;
|
|
} else if (strcmp(field, "xy") == 0) {
|
|
lua_pushnumber(L, matrix.xy);
|
|
return 1;
|
|
} else if (strcmp(field, "yy") == 0) {
|
|
lua_pushnumber(L, matrix.yy);
|
|
return 1;
|
|
} else if (strcmp(field, "x0") == 0) {
|
|
lua_pushnumber(L, matrix.x0);
|
|
return 1;
|
|
} else if (strcmp(field, "y0") == 0) {
|
|
lua_pushnumber(L, matrix.y0);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return LuaCairoBase::internal_lua_index(L);
|
|
}
|
|
|
|
int LuaCairoMatrix::internal_lua_newindex(lua_State *L)
|
|
{
|
|
if (lua_type(L, 2) == LUA_TSTRING) {
|
|
const char *field = lua_tostring(L, 2);
|
|
if (strcmp(field, "xx") == 0) {
|
|
matrix.xx = luaL_checknumber(L, 3);
|
|
return 0;
|
|
} else if (strcmp(field, "yx") == 0) {
|
|
matrix.yx = luaL_checknumber(L, 3);
|
|
return 0;
|
|
} else if (strcmp(field, "xy") == 0) {
|
|
matrix.xy = luaL_checknumber(L, 3);
|
|
return 0;
|
|
} else if (strcmp(field, "yy") == 0) {
|
|
matrix.yy = luaL_checknumber(L, 3);
|
|
return 0;
|
|
} else if (strcmp(field, "x0") == 0) {
|
|
matrix.x0 = luaL_checknumber(L, 3);
|
|
return 0;
|
|
} else if (strcmp(field, "y0") == 0) {
|
|
matrix.y0 = luaL_checknumber(L, 3);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return LuaCairoBase::internal_lua_newindex(L);
|
|
}
|
|
|
|
const char *LuaCairoMatrix::GetTypeName()
|
|
{
|
|
return "matrix";
|
|
}
|
|
|
|
void LuaCairoMatrix::CreateMetaTable(lua_State *L)
|
|
{
|
|
LuaCairoBase::CreateMetaTable(L);
|
|
|
|
lua_pushcclosure(L, lua_op_add, 0);
|
|
lua_setfield(L, -2, "__add");
|
|
lua_pushcclosure(L, lua_op_sub, 0);
|
|
lua_setfield(L, -2, "__sub");
|
|
lua_pushcclosure(L, lua_op_mul, 0);
|
|
lua_setfield(L, -2, "__mul");
|
|
lua_pushcclosure(L, lua_op_div, 0);
|
|
lua_setfield(L, -2, "__div");
|
|
lua_pushcclosure(L, lua_op_unm, 0);
|
|
lua_setfield(L, -2, "__unm");
|
|
lua_pushcclosure(L, lua_op_eq, 0);
|
|
lua_setfield(L, -2, "__eq");
|
|
}
|
|
|
|
LuaCairoMatrix::LuaCairoMatrix(lua_State *L) :
|
|
LuaCairoBase(L)
|
|
{
|
|
RegMatrixCallables(L);
|
|
|
|
cairo_matrix_init_identity(&matrix);
|
|
}
|
|
|
|
LuaCairoMatrix::LuaCairoMatrix(lua_State *L, const cairo_matrix_t *_matrix) :
|
|
LuaCairoBase(L)
|
|
{
|
|
RegMatrixCallables(L);
|
|
|
|
memcpy(&matrix, _matrix, sizeof(matrix));
|
|
}
|
|
|
|
LuaCairoMatrix::~LuaCairoMatrix()
|
|
{
|
|
// Automatic memory management here - nothing to free
|
|
}
|
|
|
|
cairo_matrix_t *LuaCairoMatrix::GetMatrix()
|
|
{
|
|
return &matrix;
|
|
}
|
|
|
|
|
|
// Path (cairo_path_t)
|
|
|
|
static void path_element_to_lua(cairo_path_data_t *path, lua_State *L)
|
|
{
|
|
lua_newtable(L);
|
|
switch (path[0].header.type) {
|
|
case CAIRO_PATH_MOVE_TO:
|
|
lua_pushliteral(L, "move_to");
|
|
lua_setfield(L, -2, "type");
|
|
lua_pushnumber(L, path[1].point.x);
|
|
lua_setfield(L, -2, "x");
|
|
lua_pushnumber(L, path[1].point.y);
|
|
lua_setfield(L, -2, "y");
|
|
break;
|
|
|
|
case CAIRO_PATH_LINE_TO:
|
|
lua_pushliteral(L, "line_to");
|
|
lua_setfield(L, -2, "type");
|
|
lua_pushnumber(L, path[1].point.x);
|
|
lua_setfield(L, -2, "x");
|
|
lua_pushnumber(L, path[1].point.y);
|
|
lua_setfield(L, -2, "y");
|
|
break;
|
|
|
|
case CAIRO_PATH_CURVE_TO:
|
|
lua_pushliteral(L, "curve_to");
|
|
lua_setfield(L, -2, "type");
|
|
lua_pushnumber(L, path[1].point.x);
|
|
lua_setfield(L, -2, "x0");
|
|
lua_pushnumber(L, path[1].point.y);
|
|
lua_setfield(L, -2, "y0");
|
|
lua_pushnumber(L, path[2].point.x);
|
|
lua_setfield(L, -2, "x1");
|
|
lua_pushnumber(L, path[2].point.y);
|
|
lua_setfield(L, -2, "y1");
|
|
lua_pushnumber(L, path[3].point.x);
|
|
lua_setfield(L, -2, "x2");
|
|
lua_pushnumber(L, path[3].point.y);
|
|
lua_setfield(L, -2, "y2");
|
|
break;
|
|
|
|
case CAIRO_PATH_CLOSE_PATH:
|
|
lua_pushliteral(L, "close");
|
|
lua_setfield(L, -2, "type");
|
|
break;
|
|
|
|
default:
|
|
lua_pushliteral(L, "unknown");
|
|
lua_setfield(L, -2, "type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void read_lua_path_element(lua_State *L, cairo_path_data_t *path)
|
|
{
|
|
lua_getfield(L, -1, "type");
|
|
if (!lua_isstring(L, -1)) {
|
|
luaL_error(L, "Invalid or missing 'type' field in path element table");
|
|
return;
|
|
}
|
|
const char *type = lua_tostring(L, -1);
|
|
|
|
if (strcmp(type, "move_to") == 0) {
|
|
path[0].header.length = 2;
|
|
path[0].header.type = CAIRO_PATH_MOVE_TO;
|
|
lua_getfield(L, -2, "x");
|
|
lua_getfield(L, -3, "y");
|
|
if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
|
|
luaL_error(L, "Invalid 'x' or 'y' field in path element table with type 'move_to'");
|
|
return;
|
|
}
|
|
path[1].point.x = lua_tonumber(L, -2);
|
|
path[1].point.y = lua_tonumber(L, -1);
|
|
lua_pop(L, 3);
|
|
return;
|
|
|
|
} else if (strcmp(type, "line_to") == 0) {
|
|
path[0].header.length = 2;
|
|
path[0].header.type = CAIRO_PATH_LINE_TO;
|
|
lua_getfield(L, -2, "x");
|
|
lua_getfield(L, -3, "y");
|
|
if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
|
|
luaL_error(L, "Invalid 'x' or 'y' field in path element table with type 'line_to'");
|
|
return;
|
|
}
|
|
path[1].point.x = lua_tonumber(L, -2);
|
|
path[1].point.y = lua_tonumber(L, -1);
|
|
lua_pop(L, 3);
|
|
return;
|
|
|
|
} else if (strcmp(type, "curve_to") == 0) {
|
|
path[0].header.length = 4;
|
|
path[0].header.type = CAIRO_PATH_CURVE_TO;
|
|
lua_getfield(L, -2, "x0");
|
|
lua_getfield(L, -3, "y0");
|
|
if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
|
|
luaL_error(L, "Invalid 'x0' or 'y0' field in path element table with type 'line_to'");
|
|
return;
|
|
}
|
|
path[1].point.x = lua_tonumber(L, -2);
|
|
path[1].point.y = lua_tonumber(L, -1);
|
|
lua_getfield(L, -4, "x1");
|
|
lua_getfield(L, -5, "y1");
|
|
if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
|
|
luaL_error(L, "Invalid 'x1' or 'y1' field in path element table with type 'line_to'");
|
|
return;
|
|
}
|
|
path[2].point.x = lua_tonumber(L, -2);
|
|
path[2].point.y = lua_tonumber(L, -1);
|
|
lua_getfield(L, -2, "x2");
|
|
lua_getfield(L, -3, "y2");
|
|
if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
|
|
luaL_error(L, "Invalid 'x2' or 'y2' field in path element table with type 'line_to'");
|
|
return;
|
|
}
|
|
path[3].point.x = lua_tonumber(L, -2);
|
|
path[3].point.y = lua_tonumber(L, -1);
|
|
lua_pop(L, 7);
|
|
return;
|
|
|
|
} else if (strcmp(type, "close") == 0) {
|
|
path[0].header.length = 1;
|
|
path[0].header.type = CAIRO_PATH_CLOSE_PATH;
|
|
lua_pop(L, 1);
|
|
return;
|
|
|
|
} else {
|
|
luaL_error(L, "Invalid 'type' field in path element table, '%s'", type);
|
|
}
|
|
}
|
|
|
|
CALLABLE_NOTIMPL(LuaCairoPath, clear)
|
|
CALLABLE_NOTIMPL(LuaCairoPath, move_to)
|
|
CALLABLE_NOTIMPL(LuaCairoPath, line_to)
|
|
CALLABLE_NOTIMPL(LuaCairoPath, curve_to)
|
|
CALLABLE_NOTIMPL(LuaCairoPath, close)
|
|
|
|
CALLABLE_IMPL(LuaCairoPath, map)
|
|
{
|
|
LuaCairoPath *path = GetObjPointer(L, lua_upvalueindex(1));
|
|
if (!lua_isfunction(L, 1)) {
|
|
luaL_error(L, "First argument to path.map_coords must be a function, is %s", luaL_typename(L, 1));
|
|
return 0;
|
|
}
|
|
|
|
// Function should be p->p
|
|
cairo_path_t *p = path->path;
|
|
if (!p->num_data || !p->data) return 0;
|
|
|
|
// Prepare a new path for building
|
|
path->path = (cairo_path_t*)malloc(sizeof(cairo_path_t));
|
|
cairo_path_t *np = path->path;
|
|
np->num_data = 0;
|
|
np->status = CAIRO_STATUS_SUCCESS;
|
|
np->data = 0;
|
|
|
|
cairo_path_data_t *pd = p->data;
|
|
int outi = 0;
|
|
for (int i = 0; i < p->num_data; ) {
|
|
lua_pushvalue(L, 1);
|
|
path_element_to_lua(pd, L);
|
|
lua_call(L, 1, 1);
|
|
|
|
path->EnsureSpaceFor(4); // dumb but simple, ensures there's always enough space for even the longest segments
|
|
read_lua_path_element(L, np->data+outi);
|
|
np->num_data += np->data[outi].header.length;
|
|
outi += np->data[outi].header.length;
|
|
|
|
i += pd->header.length;
|
|
pd += pd->header.length;
|
|
}
|
|
|
|
if (path->cairo_owns_memory) {
|
|
cairo_path_destroy(p);
|
|
path->cairo_owns_memory = false;
|
|
} else {
|
|
free(p->data);
|
|
free(p);
|
|
}
|
|
|
|
// Now just r should be left on top of stack
|
|
return 1;}
|
|
|
|
CALLABLE_IMPL(LuaCairoPath, map_coords)
|
|
{
|
|
LuaCairoPath *path = GetObjPointer(L, lua_upvalueindex(1));
|
|
if (!lua_isfunction(L, 1)) {
|
|
luaL_error(L, "First argument to path.map_coords must be a function, is %s", luaL_typename(L, 1));
|
|
return 0;
|
|
}
|
|
|
|
// Function should be (x,y)->(x,y)
|
|
cairo_path_t *p = path->path;
|
|
if (!p->num_data || !p->data) return 0;
|
|
|
|
int length_to_go = 0;
|
|
cairo_path_data_t *pd = p->data;
|
|
for (int i = 0; i < p->num_data; i++, pd++) {
|
|
if (length_to_go > 0) {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushnumber(L, pd->point.x);
|
|
lua_pushnumber(L, pd->point.y);
|
|
lua_call(L, 2, 2);
|
|
if (!lua_isnumber(L, -1) || !lua_isnumber(L, -2)) {
|
|
luaL_error(L, "The function given to path.map_coords must return two numbers");
|
|
return 0;
|
|
}
|
|
pd->point.x = lua_tonumber(L, -2);
|
|
pd->point.y = lua_tonumber(L, -1);
|
|
lua_pop(L, 2);
|
|
length_to_go--;
|
|
|
|
} else {
|
|
length_to_go = pd->header.length-1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPath, fold)
|
|
{
|
|
LuaCairoPath *path = GetObjPointer(L, lua_upvalueindex(1));
|
|
if (!lua_isfunction(L, 1)) {
|
|
luaL_error(L, "First argument to path.map_coords must be a function, is %s", luaL_typename(L, 1));
|
|
return 0;
|
|
}
|
|
luaL_checkany(L, 2);
|
|
|
|
// Function should be (r,p)->r
|
|
cairo_path_t *p = path->path;
|
|
if (!p->num_data || !p->data) return 0;
|
|
|
|
cairo_path_data_t *pd = p->data;
|
|
lua_pushvalue(L, 2); // initial 'r' for function
|
|
for (int i = 0; i < p->num_data; ) {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushvalue(L, -2); // dig up 'r'
|
|
lua_remove(L, -3); // remove dug up 'r'
|
|
path_element_to_lua(pd, L);
|
|
lua_call(L, 2, 1);
|
|
// leave result 'r' on stack for next iteration or final return
|
|
i += pd->header.length;
|
|
pd += pd->header.length;
|
|
}
|
|
|
|
// Now just r should be left on top of stack
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPath, fold_coords)
|
|
{
|
|
LuaCairoPath *path = GetObjPointer(L, lua_upvalueindex(1));
|
|
if (!lua_isfunction(L, 1)) {
|
|
luaL_error(L, "First argument to path.map_coords must be a function, is %s", luaL_typename(L, 1));
|
|
return 0;
|
|
}
|
|
luaL_checkany(L, 2);
|
|
|
|
// Function should be (r,x,y)->r
|
|
cairo_path_t *p = path->path;
|
|
if (!p->num_data || !p->data) return 0;
|
|
|
|
int length_to_go = 0;
|
|
cairo_path_data_t *pd = p->data;
|
|
lua_pushvalue(L, 2); // initial 'r' for function
|
|
for (int i = 0; i < p->num_data; i++, pd++) {
|
|
if (length_to_go > 0) {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushvalue(L, -2); // dig up 'r'
|
|
lua_remove(L, -3); // remove dug up 'r'
|
|
lua_pushnumber(L, pd->point.x);
|
|
lua_pushnumber(L, pd->point.y);
|
|
lua_call(L, 3, 1);
|
|
// leave result 'r' on stack for next iteration or final return
|
|
length_to_go--;
|
|
|
|
} else {
|
|
length_to_go = pd->header.length - 1;
|
|
}
|
|
}
|
|
|
|
// Now just r should be left on top of stack
|
|
return 1;
|
|
}
|
|
|
|
void LuaCairoPath::EnsurePathOwned()
|
|
{
|
|
if (cairo_owns_memory) {
|
|
cairo_path_t *np = (cairo_path_t*)malloc(sizeof(cairo_path_t));
|
|
np->status = path->status;
|
|
np->num_data = path->num_data;
|
|
np->data = (cairo_path_data_t*)malloc(path->num_data*sizeof(cairo_path_data_t));
|
|
memcpy(np->data, path->data, np->num_data*sizeof(cairo_path_data_t));
|
|
cairo_path_destroy(path);
|
|
path = np;
|
|
cairo_owns_memory = false;
|
|
}
|
|
}
|
|
|
|
void LuaCairoPath::EnsureSpaceFor(size_t n)
|
|
{
|
|
EnsurePathOwned();
|
|
|
|
if (path_elements_allocated - path->num_data < n) {
|
|
path_elements_allocated = path->num_data*2 + n;
|
|
path->data = (cairo_path_data_t*)realloc(path->data, path_elements_allocated*sizeof(cairo_path_data_t));
|
|
}
|
|
}
|
|
|
|
void LuaCairoPath::RegPathCallables(lua_State *L)
|
|
{
|
|
CALLABLE_REG(clear);
|
|
CALLABLE_REG(move_to);
|
|
CALLABLE_REG(line_to);
|
|
CALLABLE_REG(curve_to);
|
|
CALLABLE_REG(close);
|
|
CALLABLE_REG(map);
|
|
CALLABLE_REG(map_coords);
|
|
CALLABLE_REG(fold);
|
|
CALLABLE_REG(fold_coords);
|
|
}
|
|
|
|
int LuaCairoPath::internal_lua_index(lua_State *L)
|
|
{
|
|
return LuaCairoBase::internal_lua_index(L);
|
|
}
|
|
|
|
const char *LuaCairoPath::GetTypeName()
|
|
{
|
|
return "path";
|
|
}
|
|
|
|
LuaCairoPath::LuaCairoPath(lua_State *L) :
|
|
LuaCairoBase(L)
|
|
{
|
|
RegPathCallables(L);
|
|
|
|
cairo_owns_memory = false;
|
|
path = (cairo_path_t*)malloc(sizeof(cairo_path_t));
|
|
path->status = CAIRO_STATUS_SUCCESS;
|
|
path->num_data = 0;
|
|
path->data = 0;
|
|
EnsureSpaceFor(8);
|
|
}
|
|
|
|
LuaCairoPath::LuaCairoPath(lua_State *L, cairo_path_t *_path) :
|
|
LuaCairoBase(L)
|
|
{
|
|
RegPathCallables(L);
|
|
|
|
cairo_owns_memory = true;
|
|
path = _path;
|
|
}
|
|
|
|
LuaCairoPath::~LuaCairoPath()
|
|
{
|
|
if (cairo_owns_memory)
|
|
cairo_path_destroy(path);
|
|
else {
|
|
free(path->data);
|
|
free(path);
|
|
}
|
|
}
|
|
|
|
|
|
// Pattern (cairo_pattern_t)
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, add_color_stop_rgb)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
double offset = luaL_checknumber(L, 1);
|
|
double red = luaL_checknumber(L, 2);
|
|
double green = luaL_checknumber(L, 3);
|
|
double blue = luaL_checknumber(L, 4);
|
|
cairo_pattern_add_color_stop_rgb(pat->pattern, offset, red, green, blue);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, add_color_stop_rgba)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
double offset = luaL_checknumber(L, 1);
|
|
double red = luaL_checknumber(L, 2);
|
|
double green = luaL_checknumber(L, 3);
|
|
double blue = luaL_checknumber(L, 4);
|
|
double alpha = luaL_checknumber(L, 5);
|
|
cairo_pattern_add_color_stop_rgba(pat->pattern, offset, red, green, blue, alpha);
|
|
return 0;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, get_color_stop_count)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
int count;
|
|
cairo_status_t res = cairo_pattern_get_color_stop_count(pat->pattern, &count);
|
|
if (res != CAIRO_STATUS_SUCCESS)
|
|
return 0;
|
|
lua_pushinteger(L, count);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, get_color_stop_rgba)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
int index = luaL_checkint(L, 1);
|
|
double offset, red, green, blue, alpha;
|
|
cairo_status_t res = cairo_pattern_get_color_stop_rgba(pat->pattern, index, &offset, &red, &green, &blue, &alpha);
|
|
if (res != CAIRO_STATUS_SUCCESS)
|
|
return 0;
|
|
lua_pushnumber(L, offset);
|
|
lua_pushnumber(L, red);
|
|
lua_pushnumber(L, green);
|
|
lua_pushnumber(L, blue);
|
|
lua_pushnumber(L, alpha);
|
|
return 5;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, get_rgba)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
double red, green, blue, alpha;
|
|
cairo_status_t res = cairo_pattern_get_rgba(pat->pattern, &red, &green, &blue, &alpha);
|
|
if (res != CAIRO_STATUS_SUCCESS)
|
|
return 0;
|
|
lua_pushnumber(L, red);
|
|
lua_pushnumber(L, green);
|
|
lua_pushnumber(L, blue);
|
|
lua_pushnumber(L, alpha);
|
|
return 4;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, get_surface)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
cairo_surface_t *surf;
|
|
cairo_status_t res = cairo_pattern_get_surface(pat->pattern, &surf);
|
|
if (res != CAIRO_STATUS_SUCCESS)
|
|
return 0;
|
|
new LuaCairoSurface(L, surf);
|
|
return 1;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, get_linear_points)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x0, y0, x1, y1;
|
|
cairo_status_t res = cairo_pattern_get_linear_points(pat->pattern, &x0, &y0, &x1, &y1);
|
|
if (res != CAIRO_STATUS_SUCCESS)
|
|
return 0;
|
|
lua_pushnumber(L, x0);
|
|
lua_pushnumber(L, y0);
|
|
lua_pushnumber(L, x1);
|
|
lua_pushnumber(L, y1);
|
|
return 4;
|
|
}
|
|
|
|
CALLABLE_IMPL(LuaCairoPattern, get_radial_circles)
|
|
{
|
|
LuaCairoPattern *pat = GetObjPointer(L, lua_upvalueindex(1));
|
|
double x0, y0, r0, x1, y1, r1;
|
|
cairo_status_t res = cairo_pattern_get_radial_circles(pat->pattern, &x0, &y0, &r0, &x1, &y1, &r1);
|
|
if (res != CAIRO_STATUS_SUCCESS)
|
|
return 0;
|
|
lua_pushnumber(L, x0);
|
|
lua_pushnumber(L, y0);
|
|
lua_pushnumber( |