jsdom: add Path2D API, All CanvasRenderingContext2D methods (except image methods) (#12404)

pull/12406/head
playX 2021-11-07 11:06:28 +03:00 committed by GitHub
parent 852d85b3a9
commit d8f971ffb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 413 additions and 4 deletions

View File

@ -40,7 +40,7 @@ fn main() {
elemc := document.get_element_by_id('myCanvas') or { panic('no canvas') } elemc := document.get_element_by_id('myCanvas') or { panic('no canvas') }
canv := jsdom.get_html_canvas_element(elemc) or { panic('expected canvas') } canv := jsdom.get_html_canvas_element(elemc) or { panic('expected canvas') }
context := get_2dcontext(canv) or { panic('wow') } context := canv.get_context_2d()
mut state := DrawState{} mut state := DrawState{}
canv.add_event_listener('mousedown', fn [mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) { canv.add_event_listener('mousedown', fn [mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) {
state.drawing = true state.drawing = true

View File

@ -27,6 +27,14 @@ pub enum LineJoin {
miter miter
} }
pub enum TextAlign {
left
right
center
start
end
}
pub struct CanvasRenderingContext2D { pub struct CanvasRenderingContext2D {
mut: mut:
ctx JS.CanvasRenderingContext2D [noinit] ctx JS.CanvasRenderingContext2D [noinit]
@ -38,16 +46,54 @@ pub fn (ctx CanvasRenderingContext2D) begin_path() {
#ctx.ctx.beginPath(); #ctx.ctx.beginPath();
} }
pub fn (ctx CanvasRenderingContext2D) set_line_dash(arr []f64) {
#let tmp = []
for x in arr {
#tmp.push(x.val);
_ := x
}
#ctx.ctx.setLineDash(tmp);
}
pub fn (ctx CanvasRenderingContext2D) get_line_dash() []f64 {
arr := []f64{}
#for (elem of ctx.ctx.getLineDash()) { array_push(arr,elem); }
return arr
}
pub fn (ctx CanvasRenderingContext2D) set_text_align(align TextAlign) {
match align {
.left {
#ctx.ctx.textAlign = 'start';
}
.right {
#ctx.ctx.textAlign = 'right';
}
.center {
#ctx.ctx.textAlign = 'center';
}
.start {
#ctx.ctx.textAlign = 'start';
}
.end {
#ctx.ctx.textAlign = 'end';
}
}
}
pub fn (ctx CanvasRenderingContext2D) set_line_join(j LineJoin) { pub fn (ctx CanvasRenderingContext2D) set_line_join(j LineJoin) {
match j { match j {
.bevel { .bevel {
#ctx.ctx.lineJoin = 'bevel'.str #ctx.ctx.lineJoin = 'bevel'
} }
.round { .round {
#ctx.ctx.lineJoin = 'round'.str #ctx.ctx.lineJoin = 'round'
} }
.miter { .miter {
#ctx.ctx.lineJoin = 'miter'.str #ctx.ctx.lineJoin = 'miter'
} }
} }
} }
@ -150,6 +196,10 @@ pub fn (ctx CanvasRenderingContext2D) draw_focus_if_needed(el IElement) {
#ctx.ctx.drawFocusIfNeeded(el.val.node); #ctx.ctx.drawFocusIfNeeded(el.val.node);
} }
pub fn (ctx CanvasRenderingContext2D) draw_focus_if_needed_wpath(path Path2D, el IElement) {
#ctx.ctx.drawFocusIfNeeded(path.path, el.val.node);
}
fn (ctx JS.CanvasRenderingContext2D) createRadialGradient(x0 f64, y0 f64, r0 f64, x1 f64, y1 f64, r1 f64) JS.CanvasGradient fn (ctx JS.CanvasRenderingContext2D) createRadialGradient(x0 f64, y0 f64, r0 f64, x1 f64, y1 f64, r1 f64) JS.CanvasGradient
fn (ctx JS.CanvasRenderingContext2D) createConicGradient(startAngle f64, x f64, y f64) JS.CanvasGradient fn (ctx JS.CanvasRenderingContext2D) createConicGradient(startAngle f64, x f64, y f64) JS.CanvasGradient
@ -157,3 +207,203 @@ fn (ctx JS.CanvasRenderingContext2D) createConicGradient(startAngle f64, x f64,
fn (ctx JS.CanvasRenderingContext2D) createLinearGradient(x0 f64, y0 f64, x1 f64, y1 f64) JS.CanvasGradient fn (ctx JS.CanvasRenderingContext2D) createLinearGradient(x0 f64, y0 f64, x1 f64, y1 f64) JS.CanvasGradient
pub fn (gradient JS.CanvasGradient) addColorStop(x f64, color string) pub fn (gradient JS.CanvasGradient) addColorStop(x f64, color string)
/// fill_text draws a text string at the specified coordinates. `max_width` allows specifying a maximum
/// width for the rendered text, set max_width to -1.0 to automatically adjust text width.
pub fn (ctx CanvasRenderingContext2D) fill_text(text string, x f64, y f64, max_width f64) {
if max_width == -1.0 {
#ctx.ctx.fillText(text.str,x.val,y.val,max_width.val)
} else {
#ctx.ctx.fillText(text.str,x.val,y.val)
}
}
/// stoke_text strokes — that is, draws the outlines of — the characters of a text string at the specified coordinates.
/// `max_width` allows specifying a maximum width for the rendered text, set max_width to -1.0 to automatically adjust text width.
pub fn (ctx CanvasRenderingContext2D) stroke_text(text string, x f64, y f64, max_width f64) {
if max_width == -1.0 {
#ctx.ctx.stokeText(text.str,x.val,y.val,max_width.val)
} else {
#ctx.ctx.stokeText(text.str,x.val,y.val)
}
}
pub fn (ctx CanvasRenderingContext2D) measure_text(text string) TextMetrics {
metrics := TextMetrics{}
#let tmp = ctx.ctx.measureText(text.str);
#metrics.width = new f64(tmp.width);
#metrics.actual_bounding_box_left = new f64(tmp.actualBoundingBoxLeft);
#metrics.actual_bounding_box_right = new f64(tmp.actualBoundingBoxRight);
#metrics.actual_bounding_box_ascent = new f64(tmp.actualBoundingBoxAscent);
#metrics.actual_bounding_box_descent = new f64(tmp.actualBoundingBoxDescent);
#metrics.font_bounding_box_ascent = new f64(tmp.fontBoundingBoxAscent);
#metrics.font_bounding_box_descent = new f64(tmp.fontBoundingBoxDescent);
#metrics.em_height_ascent = new f64(tmp.emHeightAscent);
#metrics.em_height_descent = new f64(tmp.emHeightDescent);
#metrics.hanging_baseline = new f64(tmp.hangingBaseline);
#metrics.alphabetic_baseline = new f64(tmp.alphabeticBaseline);
#metrics.ideographic_baseline = new f64(tmp.ideographicBaseline);
return metrics
}
pub fn (ctx CanvasRenderingContext2D) fill_path(p Path2D) {
#ctx.ctx.fill(p.path);
}
pub enum FillRule {
nonzero
evenodd
}
pub fn (ctx CanvasRenderingContext2D) clip_rule(rule FillRule) {
match rule {
.nonzero {
#ctx.ctx.clip('nonzero')
}
.evenodd {
#ctx.ctx.clip('evenodd')
}
}
}
pub fn (ctx CanvasRenderingContext2D) clip() {
#ctx.ctx.clip();
}
pub fn (ctx CanvasRenderingContext2D) clip_path(path Path2D) {
#ctx.ctx.clip(path.path);
}
pub fn (ctx CanvasRenderingContext2D) clip_path_rule(path Path2D, rule FillRule) {
match rule {
.nonzero {
#ctx.ctx.clip(path.path, 'nonzero')
}
.evenodd {
#ctx.ctx.clip(path.path,'evenodd')
}
}
}
pub fn (ctx CanvasRenderingContext2D) is_point_in_path(x f64, y f64) bool {
res := false
#res.val = ctx.ctx.isPointInPath(x.val,y.val);
return res
}
pub fn (ctx CanvasRenderingContext2D) is_point_in_path_2(path Path2D, x f64, y f64) bool {
res := false
#res.val = ctx.ctx.isPointInPath(path.path,x.val,y.val);
return res
}
pub fn (ctx CanvasRenderingContext2D) is_point_in_path_3(path Path2D, x f64, y f64, rule FillRule) bool {
res := false
match rule {
.nonzero {
#res.val = ctx.ctx.isPointInPath(path.path,x.val,y.val,'nonzero');
}
.evenodd {
#res.val = ctx.ctx.isPointInPath(path.path,x.val,y.val,'evenadd');
}
}
return res
}
pub fn (ctx CanvasRenderingContext2D) is_point_in_path_4(x f64, y f64, rule FillRule) bool {
res := false
match rule {
.nonzero {
#res.val = ctx.ctx.isPointInPath(x.val,y.val,'nonzero');
}
.evenodd {
#res.val = ctx.ctx.isPointInPath(x.val,y.val,'evenadd');
}
}
return res
}
pub fn (ctx CanvasRenderingContext2D) is_point_in_stroke(x f64, y f64) bool {
res := false
#res.val = ctx.ctx.isPointInStroke(x.val,y.val);
return res
}
pub fn (ctx CanvasRenderingContext2D) is_point_in_stroke_path(path Path2D, x f64, y f64) bool {
res := false
#res.val = ctx.ctx.isPointInStroke(path.path, x.val,y.val);
return res
}
pub fn (ctx CanvasRenderingContext2D) get_transform() DOMMatrix {
m := DOMMatrix{}
#m.matrix = ctx.ctx.getTransform();
return m
}
pub fn (ctx CanvasRenderingContext2D) rotate(angle f64) {
#ctx.ctx.rotate(angle.val);
}
pub fn (ctx CanvasRenderingContext2D) scale(x f64, y f64) {
#ctx.ctx.scale(x.val,y.val);
}
pub fn (ctx CanvasRenderingContext2D) translate(x f64, y f64) {
#ctx.ctx.translate(x.val,y.val)
}
pub fn (ctx CanvasRenderingContext2D) transform(a f64, b f64, c f64, d f64, e f64, f f64) {
#ctx.ctx.transform(a.val,b.val,c.val,d.val,e.val,f.val);
}
pub fn (ctx CanvasRenderingContext2D) set_transform_matrix(m DOMMatrix) {
#ctx.ctx.setTransform(m.matrix);
}
pub fn (ctx CanvasRenderingContext2D) set_transform(a f64, b f64, c f64, d f64, e f64, f f64) {
#ctx.ctx.setTransform(a.val,b.val,c.val,d.val,e.val,f.val);
}
pub fn (ctx CanvasRenderingContext2D) global_alpha() f64 {
res := 0.0
#res.val = ctx.ctx.globalAlpha
return res
}
pub fn (ctx CanvasRenderingContext2D) set_global_alpha(alpha f64) {
#ctx.ctx.globalAlpha = alpha.val;
}
pub fn (ctx CanvasRenderingContext2D) global_composite_operation() string {
res := ''
#res.str = ctx.ctx.globalCompositeOperation
return res
}
pub fn (ctx CanvasRenderingContext2D) set_global_composite_operation(typ string) {
#ctx.ctx.globalCompositeOperation = typ.str;
}
pub fn (ctx CanvasRenderingContext2D) save() {
#ctx.ctx.save();
}
pub fn (ctx CanvasRenderingContext2D) restore() {
#ctx.ctx.restore()
}
pub fn (ctx CanvasRenderingContext2D) canvas() HTMLCanvasElement {
elem := HTMLCanvasElement{}
#elem.node = ctx.ctx.canvas()
return elem
}

View File

@ -184,3 +184,19 @@ fn init() {
#jsdom__document.node = document; #jsdom__document.node = document;
#jsdom__window.node = window; #jsdom__window.node = window;
} }
pub struct TextMetrics {
pub:
width f64
actual_bounding_box_left f64
actual_bounding_box_right f64
font_bounding_box_ascent f64
font_bounding_box_descent f64
actual_bounding_box_ascent f64
actual_bounding_box_descent f64
em_height_ascent f64
em_height_descent f64
hanging_baseline f64
alphabetic_baseline f64
ideographic_baseline f64
}

View File

@ -36,3 +36,12 @@ pub fn (elem HTMLCanvasElement) get_context(ctx_ string) ContextResult {
return res return res
} }
pub fn (elem HTMLCanvasElement) get_context_2d() CanvasRenderingContext2D {
mut res := CanvasRenderingContext2D{}
#let ctx = elem.node.getContext('2d');
#res = new jsdom__CanvasRenderingContext2D(ctx);
#res.ctx = ctx;
return res
}

View File

@ -0,0 +1,63 @@
module jsdom
pub struct JS.Path2D {}
pub fn (p JS.Path2D) addPath(JS.Path2D, JS.DOMMatrix)
pub fn (p JS.Path2D) closePath()
pub fn (p JS.Path2D) moveTo(x JS.Number, y JS.Number)
pub fn (p JS.Path2D) lineTo(x JS.Number, y JS.Number)
pub fn (p JS.Path2D) bezierCurveTo(cp1x JS.Number, cp1y JS.Number, cp2x JS.Number, cp2y JS.Number, x JS.Number, y JS.Number)
pub fn (p JS.Path2D) quadraticCurveTo(cpx JS.Number, cpy JS.Number, x JS.Number, y JS.Number)
pub fn (p JS.Path2D) arc(x JS.Number, y JS.Number, radius JS.Number, startAngle JS.Number, endAngle JS.Number, counter_clockwise JS.Boolean)
pub fn (p JS.Path2D) arcTo(x1 JS.Number, y1 JS.Number, x2 JS.Number, y2 JS.Number, radius JS.Number)
pub fn (p JS.Path2D) ellipse(x JS.Number, y JS.Number, radius_x JS.Number, radius_y JS.Number, rotation JS.Number, start_angle JS.Number, end_angle JS.Number, counter_clockwise JS.Boolean)
pub fn (p JS.Path2D) rect(x JS.Number, y JS.Number, width JS.Number, height JS.Number)
pub struct Path2D {
mut:
path JS.Path2D [noinit]
}
pub fn (p Path2D) add_path(p2 Path2D) {
#p.path.addPath(p2.path);
}
pub fn (p Path2D) add_path_with_transform(p2 Path2D, m DOMMatrix) {
p.path.addPath(p2.path, m.matrix)
}
pub fn (path Path2D) bezier_curve_to(cp1x f64, cp1y f64, cp2x f64, cp2y f64, x f64, y f64) {
#path.path.bezierCurveTo(cp1x.val,cp1y.val,cp2x.val,cp2y.val, x.val,y.val);
}
pub fn (path Path2D) quadratic_curve_to(cpx f64, cpy f64, x f64, y f64) {
#path.path.quadraticCurveTo(cpx.val,cpy.val,x.val,y.val);
}
pub fn (path Path2D) arc(x f64, y f64, radius f64, start_angle f64, end_angle f64, counter_clockwise bool) {
#path.path.arc(x.val,y.val,radius.val,start_angle.val,end_angle.val,counter_clockwise.val)
}
pub fn (path Path2D) arc_to(x1 f64, y1 f64, x2 f64, y2 f64, radius f64) {
#path.path.arcTo(x1.val,y1.val,x2.val,y2.val,radius.val);
}
pub fn (path Path2D) ellipse(x f64, y f64, radius_x f64, radius_y f64, rotation f64, start_angle f64, end_angle f64, counter_clockwise bool) {
#path.path.ellipse(x.val,y.val,radius_x.val,radius_y.val,rotation.val,start_angle.val,end_angle.val,counter_clockwise.val);
}
pub fn (path Path2D) rect(x f64, y f64, width f64, height f64) {
#path.path.rect(x.val,y.val,widht.val,height.val);
}
pub fn (path Path2D) line_to(x f64, y f64) {
path.path.lineTo(f64tonum(x), f64tonum(y))
}
pub fn (path Path2D) move_to(x f64, y f64) {
path.path.lineTo(f64tonum(x), f64tonum(y))
}
pub fn (path Path2D) close_path() {
path.path.closePath()
}

View File

@ -0,0 +1,71 @@
module jsdom
pub struct JS.DOMPoint {
pub mut:
x JS.Number [noinit]
y JS.Number [noinit]
z JS.Number [noinit]
w JS.Number [noinit]
}
pub struct DOMPoint {
mut:
point JS.DOMPoint
}
pub fn new_dompoint(x f64, y f64, z f64, w f64) DOMPoint {
mut point := DOMPoint{}
point.point.x = f64tonum(x)
point.point.y = f64tonum(y)
point.point.z = f64tonum(z)
point.point.w = f64tonum(w)
return point
}
pub fn (p DOMPoint) x() f64 {
return tof64(p.point.x)
}
pub fn (p DOMPoint) y() f64 {
return tof64(p.point.y)
}
pub fn (p DOMPoint) z() f64 {
return tof64(p.point.z)
}
pub fn (p DOMPoint) w() f64 {
return tof64(p.point.w)
}
pub fn (mut p DOMPoint) set_x(x f64) {
p.point.x = f64tonum(x)
}
pub fn (mut p DOMPoint) set_y(y f64) {
p.point.y = f64tonum(y)
}
pub fn (mut p DOMPoint) set_z(z f64) {
p.point.z = f64tonum(z)
}
pub fn (mut p DOMPoint) set_w(w f64) {
p.point.w = f64tonum(w)
}
pub fn (p DOMPoint) matrix_transform(matrix DOMMatrix) DOMPoint {
mut point := DOMPoint{}
#point.point = p.point.matrixTransform(matrix.matrix);
return point
}
pub fn (p DOMPoint) matrix_transform_2() DOMPoint {
mut point := DOMPoint{}
#point.point = p.point.matrixTransform();
return point
}