avm2: Implement Graphics::drawRoundRectComplex
This commit is contained in:
parent
84e4270f27
commit
db61726e5b
|
@ -495,50 +495,61 @@ const UNIT_CIRCLE_POINTS: [(f64, f64); 5] = [
|
|||
]; */
|
||||
|
||||
/// Draw a roundrect.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn draw_round_rect_internal(
|
||||
draw: &mut Drawing,
|
||||
x: f64,
|
||||
y: f64,
|
||||
width: f64,
|
||||
height: f64,
|
||||
mut ellipse_width: f64,
|
||||
mut ellipse_height: f64,
|
||||
top_left_width: f64,
|
||||
top_left_height: f64,
|
||||
top_right_width: f64,
|
||||
top_right_height: f64,
|
||||
bottom_left_width: f64,
|
||||
bottom_left_height: f64,
|
||||
bottom_right_width: f64,
|
||||
bottom_right_height: f64,
|
||||
) {
|
||||
if ellipse_height.is_nan() {
|
||||
ellipse_height = ellipse_width;
|
||||
}
|
||||
let top_left_width = top_left_width.min(width / 2.0);
|
||||
let top_left_height = top_left_height.min(height / 2.0);
|
||||
let top_right_width = top_right_width.min(width / 2.0);
|
||||
let top_right_height = top_right_height.min(height / 2.0);
|
||||
let bottom_left_width = bottom_left_width.min(width / 2.0);
|
||||
let bottom_left_height = bottom_left_height.min(height / 2.0);
|
||||
let bottom_right_width = bottom_right_width.min(width / 2.0);
|
||||
let bottom_right_height = bottom_right_height.min(height / 2.0);
|
||||
|
||||
//Clamp the ellipse sizes to the size of the rectangle.
|
||||
if ellipse_width > width {
|
||||
ellipse_width = width;
|
||||
}
|
||||
let ucp = UNIT_CIRCLE_POINTS;
|
||||
|
||||
if ellipse_height > height {
|
||||
ellipse_height = height;
|
||||
}
|
||||
let br_ellipse_center_x = x + width - bottom_right_width;
|
||||
let br_ellipse_center_y = y + height - bottom_right_height;
|
||||
|
||||
let bl_ellipse_center_x = x + bottom_left_width;
|
||||
let bl_ellipse_center_y = y + height - bottom_left_height;
|
||||
|
||||
let tl_ellipse_center_x = x + top_left_width;
|
||||
let tl_ellipse_center_y = y + top_left_height;
|
||||
|
||||
let tr_ellipse_center_x = x + width - top_right_width;
|
||||
let tr_ellipse_center_y = y + top_right_height;
|
||||
|
||||
// We'll start from the bottom-right corner of the rectangle,
|
||||
// because that's what Flash Player does.
|
||||
let ucp = UNIT_CIRCLE_POINTS;
|
||||
|
||||
let line_width = width - ellipse_width;
|
||||
let line_height = height - ellipse_height;
|
||||
|
||||
let br_ellipse_center_x = x + ellipse_width / 2.0 + line_width;
|
||||
let br_ellipse_center_y = y + ellipse_height / 2.0 + line_height;
|
||||
|
||||
let br_point_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[2].0;
|
||||
let br_point_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[2].1;
|
||||
// Middle of bottom-right ellipse
|
||||
let br_point_x = br_ellipse_center_x + bottom_right_width * ucp[2].0;
|
||||
let br_point_y = br_ellipse_center_y + bottom_right_height * ucp[2].1;
|
||||
let br_point = Point::from_pixels(br_point_x, br_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::MoveTo(br_point));
|
||||
|
||||
let br_b_curve_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[3].0;
|
||||
let br_b_curve_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[3].1;
|
||||
let br_b_curve_x = br_ellipse_center_x + bottom_right_width * ucp[3].0;
|
||||
let br_b_curve_y = br_ellipse_center_y + bottom_right_height * ucp[3].1;
|
||||
let br_b_curve = Point::from_pixels(br_b_curve_x, br_b_curve_y);
|
||||
|
||||
let right_b_point_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[4].0;
|
||||
let right_b_point_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[4].1;
|
||||
let right_b_point_x = br_ellipse_center_x + bottom_right_width * ucp[4].0;
|
||||
let right_b_point_y = br_ellipse_center_y + bottom_right_height * ucp[4].1;
|
||||
let right_b_point = Point::from_pixels(right_b_point_x, right_b_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -546,24 +557,20 @@ fn draw_round_rect_internal(
|
|||
anchor: right_b_point,
|
||||
});
|
||||
|
||||
// Oh, since we're drawing roundrects, we also need to draw lines
|
||||
// in between each ellipse. This is the bottom line.
|
||||
let tl_ellipse_center_x = x + ellipse_width / 2.0;
|
||||
let tl_ellipse_center_y = y + ellipse_height / 2.0;
|
||||
|
||||
let left_b_point_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[4].0;
|
||||
let left_b_point_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[4].1;
|
||||
// Bottom line
|
||||
let left_b_point_x = bl_ellipse_center_x + bottom_left_width * ucp[4].0;
|
||||
let left_b_point_y = bl_ellipse_center_y + bottom_left_height * ucp[4].1;
|
||||
let left_b_point = Point::from_pixels(left_b_point_x, left_b_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::LineTo(left_b_point));
|
||||
|
||||
// Bottom-left ellipse
|
||||
let b_bl_curve_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[3].0;
|
||||
let b_bl_curve_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[3].1;
|
||||
let b_bl_curve_x = bl_ellipse_center_x - bottom_left_width * ucp[3].0;
|
||||
let b_bl_curve_y = bl_ellipse_center_y + bottom_left_height * ucp[3].1;
|
||||
let b_bl_curve = Point::from_pixels(b_bl_curve_x, b_bl_curve_y);
|
||||
|
||||
let bl_point_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[2].0;
|
||||
let bl_point_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[2].1;
|
||||
let bl_point_x = bl_ellipse_center_x - bottom_left_width * ucp[2].0;
|
||||
let bl_point_y = bl_ellipse_center_y + bottom_left_height * ucp[2].1;
|
||||
let bl_point = Point::from_pixels(bl_point_x, bl_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -571,12 +578,12 @@ fn draw_round_rect_internal(
|
|||
anchor: bl_point,
|
||||
});
|
||||
|
||||
let bl_l_curve_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[1].0;
|
||||
let bl_l_curve_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[1].1;
|
||||
let bl_l_curve_x = bl_ellipse_center_x - bottom_left_width * ucp[1].0;
|
||||
let bl_l_curve_y = bl_ellipse_center_y + bottom_left_height * ucp[1].1;
|
||||
let bl_l_curve = Point::from_pixels(bl_l_curve_x, bl_l_curve_y);
|
||||
|
||||
let bottom_l_point_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[0].0;
|
||||
let bottom_l_point_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[0].1;
|
||||
let bottom_l_point_x = bl_ellipse_center_x - bottom_left_width * ucp[0].0;
|
||||
let bottom_l_point_y = bl_ellipse_center_y + bottom_left_height * ucp[0].1;
|
||||
let bottom_l_point = Point::from_pixels(bottom_l_point_x, bottom_l_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -585,19 +592,19 @@ fn draw_round_rect_internal(
|
|||
});
|
||||
|
||||
// Left side
|
||||
let top_l_point_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[0].0;
|
||||
let top_l_point_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[0].1;
|
||||
let top_l_point_x = tl_ellipse_center_x - top_left_width * ucp[0].0;
|
||||
let top_l_point_y = tl_ellipse_center_y - top_left_height * ucp[0].1;
|
||||
let top_l_point = Point::from_pixels(top_l_point_x, top_l_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::LineTo(top_l_point));
|
||||
|
||||
// Top-left ellipse
|
||||
let l_tl_curve_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[1].0;
|
||||
let l_tl_curve_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[1].1;
|
||||
let l_tl_curve_x = tl_ellipse_center_x - top_left_width * ucp[1].0;
|
||||
let l_tl_curve_y = tl_ellipse_center_y - top_left_height * ucp[1].1;
|
||||
let l_tl_curve = Point::from_pixels(l_tl_curve_x, l_tl_curve_y);
|
||||
|
||||
let tl_point_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[2].0;
|
||||
let tl_point_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[2].1;
|
||||
let tl_point_x = tl_ellipse_center_x - top_left_width * ucp[2].0;
|
||||
let tl_point_y = tl_ellipse_center_y - top_left_height * ucp[2].1;
|
||||
let tl_point = Point::from_pixels(tl_point_x, tl_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -605,12 +612,12 @@ fn draw_round_rect_internal(
|
|||
anchor: tl_point,
|
||||
});
|
||||
|
||||
let tl_t_curve_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[3].0;
|
||||
let tl_t_curve_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[3].1;
|
||||
let tl_t_curve_x = tl_ellipse_center_x - top_left_width * ucp[3].0;
|
||||
let tl_t_curve_y = tl_ellipse_center_y - top_left_height * ucp[3].1;
|
||||
let tl_t_curve = Point::from_pixels(tl_t_curve_x, tl_t_curve_y);
|
||||
|
||||
let left_t_point_x = tl_ellipse_center_x + ellipse_width / -2.0 * ucp[4].0;
|
||||
let left_t_point_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[4].1;
|
||||
let left_t_point_x = tl_ellipse_center_x - top_left_width * ucp[4].0;
|
||||
let left_t_point_y = tl_ellipse_center_y - top_left_height * ucp[4].1;
|
||||
let left_t_point = Point::from_pixels(left_t_point_x, left_t_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -619,19 +626,19 @@ fn draw_round_rect_internal(
|
|||
});
|
||||
|
||||
// Top side
|
||||
let right_t_point_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[4].0;
|
||||
let right_t_point_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[4].1;
|
||||
let right_t_point_x = tr_ellipse_center_x + top_right_width * ucp[4].0;
|
||||
let right_t_point_y = tr_ellipse_center_y - top_right_height * ucp[4].1;
|
||||
let right_t_point = Point::from_pixels(right_t_point_x, right_t_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::LineTo(right_t_point));
|
||||
|
||||
// Top-right ellipse
|
||||
let t_tr_curve_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[3].0;
|
||||
let t_tr_curve_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[3].1;
|
||||
let t_tr_curve_x = tr_ellipse_center_x + top_right_width * ucp[3].0;
|
||||
let t_tr_curve_y = tr_ellipse_center_y - top_right_height * ucp[3].1;
|
||||
let t_tr_curve = Point::from_pixels(t_tr_curve_x, t_tr_curve_y);
|
||||
|
||||
let tr_point_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[2].0;
|
||||
let tr_point_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[2].1;
|
||||
let tr_point_x = tr_ellipse_center_x + top_right_width * ucp[2].0;
|
||||
let tr_point_y = tr_ellipse_center_y - top_right_height * ucp[2].1;
|
||||
let tr_point = Point::from_pixels(tr_point_x, tr_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -639,12 +646,12 @@ fn draw_round_rect_internal(
|
|||
anchor: tr_point,
|
||||
});
|
||||
|
||||
let tr_r_curve_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[1].0;
|
||||
let tr_r_curve_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[1].1;
|
||||
let tr_r_curve_x = tr_ellipse_center_x + top_right_width * ucp[1].0;
|
||||
let tr_r_curve_y = tr_ellipse_center_y - top_right_height * ucp[1].1;
|
||||
let tr_r_curve = Point::from_pixels(tr_r_curve_x, tr_r_curve_y);
|
||||
|
||||
let top_r_point_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[0].0;
|
||||
let top_r_point_y = tl_ellipse_center_y + ellipse_height / -2.0 * ucp[0].1;
|
||||
let top_r_point_x = tr_ellipse_center_x + top_right_width * ucp[0].0;
|
||||
let top_r_point_y = tr_ellipse_center_y - top_right_height * ucp[0].1;
|
||||
let top_r_point = Point::from_pixels(top_r_point_x, top_r_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -653,14 +660,14 @@ fn draw_round_rect_internal(
|
|||
});
|
||||
|
||||
// Right side & other half of bottom-right ellipse
|
||||
let bottom_r_point_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[0].0;
|
||||
let bottom_r_point_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[0].1;
|
||||
let bottom_r_point_x = br_ellipse_center_x + bottom_right_width * ucp[0].0;
|
||||
let bottom_r_point_y = br_ellipse_center_y + bottom_right_height * ucp[0].1;
|
||||
let bottom_r_point = Point::from_pixels(bottom_r_point_x, bottom_r_point_y);
|
||||
|
||||
draw.draw_command(DrawCommand::LineTo(bottom_r_point));
|
||||
|
||||
let r_br_curve_x = br_ellipse_center_x + ellipse_width / 2.0 * ucp[1].0;
|
||||
let r_br_curve_y = br_ellipse_center_y + ellipse_height / 2.0 * ucp[1].1;
|
||||
let r_br_curve_x = br_ellipse_center_x + bottom_right_width * ucp[1].0;
|
||||
let r_br_curve_y = br_ellipse_center_y + bottom_right_height * ucp[1].1;
|
||||
let r_br_curve = Point::from_pixels(r_br_curve_x, r_br_curve_y);
|
||||
|
||||
draw.draw_command(DrawCommand::QuadraticCurveTo {
|
||||
|
@ -681,7 +688,11 @@ pub fn draw_round_rect<'gc>(
|
|||
let width = args.get_f64(activation, 2)?;
|
||||
let height = args.get_f64(activation, 3)?;
|
||||
let ellipse_width = args.get_f64(activation, 4)?;
|
||||
let ellipse_height = args.get_f64(activation, 5)?;
|
||||
let mut ellipse_height = args.get_f64(activation, 5)?;
|
||||
|
||||
if ellipse_height.is_nan() {
|
||||
ellipse_height = ellipse_width;
|
||||
}
|
||||
|
||||
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
|
||||
draw_round_rect_internal(
|
||||
|
@ -690,8 +701,52 @@ pub fn draw_round_rect<'gc>(
|
|||
y,
|
||||
width,
|
||||
height,
|
||||
ellipse_width,
|
||||
ellipse_height,
|
||||
ellipse_width / 2.0,
|
||||
ellipse_height / 2.0,
|
||||
ellipse_width / 2.0,
|
||||
ellipse_height / 2.0,
|
||||
ellipse_width / 2.0,
|
||||
ellipse_height / 2.0,
|
||||
ellipse_width / 2.0,
|
||||
ellipse_height / 2.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
/// Implements `Graphics.drawRoundRectComplex`
|
||||
pub fn draw_round_rect_complex<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(this) = this.as_display_object() {
|
||||
let x = args.get_f64(activation, 0)?;
|
||||
let y = args.get_f64(activation, 1)?;
|
||||
let width = args.get_f64(activation, 2)?;
|
||||
let height = args.get_f64(activation, 3)?;
|
||||
let top_left = args.get_f64(activation, 4)?;
|
||||
let top_right = args.get_f64(activation, 5)?;
|
||||
let bottom_left = args.get_f64(activation, 6)?;
|
||||
let bottom_right = args.get_f64(activation, 7)?;
|
||||
|
||||
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
|
||||
draw_round_rect_internal(
|
||||
&mut draw,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
top_left,
|
||||
top_left,
|
||||
top_right,
|
||||
top_right,
|
||||
bottom_left,
|
||||
bottom_left,
|
||||
bottom_right,
|
||||
bottom_right,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -717,8 +772,14 @@ pub fn draw_circle<'gc>(
|
|||
y - radius,
|
||||
radius * 2.0,
|
||||
radius * 2.0,
|
||||
radius * 2.0,
|
||||
radius * 2.0,
|
||||
radius,
|
||||
radius,
|
||||
radius,
|
||||
radius,
|
||||
radius,
|
||||
radius,
|
||||
radius,
|
||||
radius,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +800,21 @@ pub fn draw_ellipse<'gc>(
|
|||
let height = args.get_f64(activation, 3)?;
|
||||
|
||||
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
|
||||
draw_round_rect_internal(&mut draw, x, y, width, height, width, height)
|
||||
draw_round_rect_internal(
|
||||
&mut draw,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
width / 2.0,
|
||||
height / 2.0,
|
||||
width / 2.0,
|
||||
height / 2.0,
|
||||
width / 2.0,
|
||||
height / 2.0,
|
||||
width / 2.0,
|
||||
height / 2.0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -891,16 +966,6 @@ pub fn draw_path<'gc>(
|
|||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
/// Implements `Graphics.drawRoundRectComplex`
|
||||
pub fn draw_round_rect_complex<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
avm2_stub_method!(activation, "flash.display.Graphics", "drawRoundRectComplex");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
/// Implements `Graphics.drawTriangles`
|
||||
pub fn draw_triangles<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// compiled with mxmlc
|
||||
|
||||
package {
|
||||
import flash.display.MovieClip;
|
||||
|
||||
public class Test extends MovieClip {
|
||||
public function Test(){
|
||||
graphics.beginFill(0xFFCC00);
|
||||
// top left: normal
|
||||
graphics.drawRoundRect(10, 10, 100, 100, 70, 30);
|
||||
// top right: clamping
|
||||
graphics.drawRoundRect(150, 10, 100, 100, 100, 100);
|
||||
|
||||
// middle left: complex, normal
|
||||
graphics.drawRoundRectComplex(10, 150, 100, 100,
|
||||
20, 30, 40, 50);
|
||||
|
||||
// middle right: complex, clamping
|
||||
graphics.drawRoundRectComplex(150, 150, 100, 100,
|
||||
80, 60, 50, 30);
|
||||
|
||||
// bottom left: circle
|
||||
graphics.drawCircle(80, 300, 50);
|
||||
// bottom right: ellipse
|
||||
graphics.drawEllipse(150, 300, 100, 50);
|
||||
graphics.endFill();
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
num_ticks = 1
|
||||
|
||||
[player_options]
|
||||
with_renderer = { optional = false, sample_count = 1 }
|
Loading…
Reference in New Issue