diff options
-rw-r--r-- | draw/draw_mesh.c | 200 | ||||
-rw-r--r-- | fitz/res_shade.c | 179 |
2 files changed, 185 insertions, 194 deletions
diff --git a/draw/draw_mesh.c b/draw/draw_mesh.c index 532f78f4..885a6944 100644 --- a/draw/draw_mesh.c +++ b/draw/draw_mesh.c @@ -448,184 +448,6 @@ fz_paint_triangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n, fz_bbo } } -static void -fz_paint_quad(fz_pixmap *pix, - fz_point p0, fz_point p1, fz_point p2, fz_point p3, - float c0, float c1, float c2, float c3, - int n, fz_bbox bbox) -{ - float v[4][3]; - - v[0][0] = p0.x; - v[0][1] = p0.y; - v[0][2] = c0; - - v[1][0] = p1.x; - v[1][1] = p1.y; - v[1][2] = c1; - - v[2][0] = p2.x; - v[2][1] = p2.y; - v[2][2] = c2; - - v[3][0] = p3.x; - v[3][1] = p3.y; - v[3][2] = c3; - - fz_paint_triangle(pix, v[0], v[2], v[3], n, bbox); - fz_paint_triangle(pix, v[0], v[3], v[1], n, bbox); -} - -/* - * linear, radial and mesh painting - */ - -#define HUGENUM 32000 /* how far to extend axial/radial shadings */ -#define RADSEGS 32 /* how many segments to generate for radial meshes */ - -static fz_point -fz_point_on_circle(fz_point p, float r, float theta) -{ - p.x = p.x + my_cosf(theta) * r; - p.y = p.y + my_sinf(theta) * r; - - return p; -} - -static void -fz_paint_linear(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) -{ - fz_point p0, p1; - fz_point v0, v1, v2, v3; - fz_point e0, e1; - float theta; - - p0.x = shade->u.a_or_r.coords[0][0]; - p0.y = shade->u.a_or_r.coords[0][1]; - p0 = fz_transform_point(ctm, p0); - - p1.x = shade->u.a_or_r.coords[1][0]; - p1.y = shade->u.a_or_r.coords[1][1]; - p1 = fz_transform_point(ctm, p1); - - theta = my_atan2f(p1.y - p0.y, p1.x - p0.x); - theta += (float)M_PI * 0.5f; - - v0 = fz_point_on_circle(p0, HUGENUM, theta); - v1 = fz_point_on_circle(p1, HUGENUM, theta); - v2 = fz_point_on_circle(p0, -HUGENUM, theta); - v3 = fz_point_on_circle(p1, -HUGENUM, theta); - - fz_paint_quad(dest, v0, v1, v2, v3, 0, 255, 0, 255, 3, bbox); - - if (shade->u.a_or_r.extend[0]) - { - e0.x = v0.x - (p1.x - p0.x) * HUGENUM; - e0.y = v0.y - (p1.y - p0.y) * HUGENUM; - - e1.x = v2.x - (p1.x - p0.x) * HUGENUM; - e1.y = v2.y - (p1.y - p0.y) * HUGENUM; - - fz_paint_quad(dest, e0, e1, v0, v2, 0, 0, 0, 0, 3, bbox); - } - - if (shade->u.a_or_r.extend[1]) - { - e0.x = v1.x + (p1.x - p0.x) * HUGENUM; - e0.y = v1.y + (p1.y - p0.y) * HUGENUM; - - e1.x = v3.x + (p1.x - p0.x) * HUGENUM; - e1.y = v3.y + (p1.y - p0.y) * HUGENUM; - - fz_paint_quad(dest, e0, e1, v1, v3, 255, 255, 255, 255, 3, bbox); - } -} - -static void -fz_paint_annulus(fz_matrix ctm, - fz_point p0, float r0, float c0, - fz_point p1, float r1, float c1, - fz_pixmap *dest, fz_bbox bbox) -{ - fz_point t0, t1, t2, t3, b0, b1, b2, b3; - float theta, step; - int i; - - theta = my_atan2f(p1.y - p0.y, p1.x - p0.x); - step = (float)M_PI * 2 / RADSEGS; - - for (i = 0; i < RADSEGS / 2; i++) - { - t0 = fz_point_on_circle(p0, r0, theta + i * step); - t1 = fz_point_on_circle(p0, r0, theta + i * step + step); - t2 = fz_point_on_circle(p1, r1, theta + i * step); - t3 = fz_point_on_circle(p1, r1, theta + i * step + step); - b0 = fz_point_on_circle(p0, r0, theta - i * step); - b1 = fz_point_on_circle(p0, r0, theta - i * step - step); - b2 = fz_point_on_circle(p1, r1, theta - i * step); - b3 = fz_point_on_circle(p1, r1, theta - i * step - step); - - t0 = fz_transform_point(ctm, t0); - t1 = fz_transform_point(ctm, t1); - t2 = fz_transform_point(ctm, t2); - t3 = fz_transform_point(ctm, t3); - b0 = fz_transform_point(ctm, b0); - b1 = fz_transform_point(ctm, b1); - b2 = fz_transform_point(ctm, b2); - b3 = fz_transform_point(ctm, b3); - - fz_paint_quad(dest, t0, t1, t2, t3, c0, c0, c1, c1, 3, bbox); - fz_paint_quad(dest, b0, b1, b2, b3, c0, c0, c1, c1, 3, bbox); - } -} - -static void -fz_paint_radial(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) -{ - fz_point p0, p1; - float r0, r1; - fz_point e; - float er, rs; - - p0.x = shade->u.a_or_r.coords[0][0]; - p0.y = shade->u.a_or_r.coords[0][1]; - r0 = shade->u.a_or_r.coords[0][2]; - - p1.x = shade->u.a_or_r.coords[1][0]; - p1.y = shade->u.a_or_r.coords[1][1]; - r1 = shade->u.a_or_r.coords[1][2]; - - if (shade->u.a_or_r.extend[0]) - { - if (r0 < r1) - rs = r0 / (r0 - r1); - else - rs = -HUGENUM; - - e.x = p0.x + (p1.x - p0.x) * rs; - e.y = p0.y + (p1.y - p0.y) * rs; - er = r0 + (r1 - r0) * rs; - - fz_paint_annulus(ctm, e, er, 0, p0, r0, 0, dest, bbox); - } - - fz_paint_annulus(ctm, p0, r0, 0, p1, r1, 255, dest, bbox); - - if (shade->u.a_or_r.extend[1]) - { - if (r0 > r1) - rs = r1 / (r1 - r0); - else - rs = -HUGENUM; - - e.x = p1.x + (p0.x - p1.x) * rs; - e.y = p1.y + (p0.y - p1.y) * rs; - er = r1 + (r0 - r1) * rs; - - fz_paint_annulus(ctm, p1, r1, 255, e, er, 255, dest, bbox); - } -} - struct paint_tri_data { fz_context *ctx; @@ -679,6 +501,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_pixmap *temp = NULL; fz_pixmap *conv = NULL; float color[FZ_MAX_COLORS]; + struct paint_tri_data ptd; int i, k; fz_var(temp); @@ -706,21 +529,12 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, temp = dest; } - switch (shade->type) - { - case FZ_LINEAR: fz_paint_linear(shade, ctm, temp, bbox); break; - case FZ_RADIAL: fz_paint_radial(shade, ctm, temp, bbox); break; - default: - { - struct paint_tri_data ptd; - ptd.ctx = ctx; - ptd.dest = temp; - ptd.shade = shade; - ptd.bbox = bbox; - fz_process_mesh(ctx, shade, ctm, &do_paint_tri, &ptd); - break; - } - } + ptd.ctx = ctx; + ptd.dest = temp; + ptd.shade = shade; + ptd.bbox = bbox; + + fz_process_mesh(ctx, shade, ctm, &do_paint_tri, &ptd); if (shade->use_function) { diff --git a/fitz/res_shade.c b/fitz/res_shade.c index 231a7ba0..4bd3ad39 100644 --- a/fitz/res_shade.c +++ b/fitz/res_shade.c @@ -12,7 +12,7 @@ static void paint_quad(fz_mesh_processor *painter, fz_vertex *v0, fz_vertex *v1, fz_vertex *v2, fz_vertex *v3) { painter->process(painter->process_arg, v0, v1, v3); - painter->process(painter->process_arg, v1, v3, v2); + painter->process(painter->process_arg, v2, v3, v1); } static void @@ -66,6 +66,179 @@ fz_mesh_type1_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_p } } +/* FIXME: Nasty */ +#define HUGENUM 32000 /* how far to extend axial/radial shadings */ + +static fz_point +fz_point_on_circle(fz_point p, float r, float theta) +{ + p.x = p.x + cosf(theta) * r; + p.y = p.y + sinf(theta) * r; + + return p; +} + +static void +fz_mesh_type2_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter) +{ + fz_point p0, p1; + fz_vertex v0, v1, v2, v3; + fz_vertex e0, e1; + float theta; + + p0.x = shade->u.a_or_r.coords[0][0]; + p0.y = shade->u.a_or_r.coords[0][1]; + p0 = fz_transform_point(ctm, p0); + + p1.x = shade->u.a_or_r.coords[1][0]; + p1.y = shade->u.a_or_r.coords[1][1]; + p1 = fz_transform_point(ctm, p1); + + theta = atan2f(p1.y - p0.y, p1.x - p0.x); + theta += (float)M_PI * 0.5f; + + v0.p = fz_point_on_circle(p0, HUGENUM, theta); + v1.p = fz_point_on_circle(p1, HUGENUM, theta); + v2.p = fz_point_on_circle(p0, -HUGENUM, theta); + v3.p = fz_point_on_circle(p1, -HUGENUM, theta); + + v0.c[0] = 0; + v1.c[0] = 1; + v2.c[0] = 0; + v3.c[0] = 1; + + paint_quad(painter, &v0, &v2, &v3, &v1); + + if (shade->u.a_or_r.extend[0]) + { + e0.p.x = v0.p.x - (p1.x - p0.x) * HUGENUM; + e0.p.y = v0.p.y - (p1.y - p0.y) * HUGENUM; + + e1.p.x = v2.p.x - (p1.x - p0.x) * HUGENUM; + e1.p.y = v2.p.y - (p1.y - p0.y) * HUGENUM; + + e0.c[0] = 0; + e1.c[0] = 0; + v0.c[0] = 0; + v2.c[0] = 0; + + paint_quad(painter, &e0, &v0, &v2, &e1); + } + + if (shade->u.a_or_r.extend[1]) + { + e0.p.x = v1.p.x + (p1.x - p0.x) * HUGENUM; + e0.p.y = v1.p.y + (p1.y - p0.y) * HUGENUM; + + e1.p.x = v3.p.x + (p1.x - p0.x) * HUGENUM; + e1.p.y = v3.p.y + (p1.y - p0.y) * HUGENUM; + + e0.c[0] = 1; + e1.c[0] = 1; + v1.c[0] = 1; + v3.c[0] = 1; + + paint_quad(painter, &e0, &v1, &v3, &e1); + } +} + +/* FIXME: Nasty */ +#define RADSEGS 32 /* how many segments to generate for radial meshes */ + +static void +fz_paint_annulus(fz_matrix ctm, + fz_point p0, float r0, float c0, + fz_point p1, float r1, float c1, + fz_mesh_processor *painter) +{ + fz_vertex t0, t1, t2, t3, b0, b1, b2, b3; + float theta, step; + int i; + + theta = atan2f(p1.y - p0.y, p1.x - p0.x); + step = (float)M_PI * 2 / RADSEGS; + + for (i = 0; i < RADSEGS / 2; i++) + { + t0.p = fz_point_on_circle(p0, r0, theta + i * step); + t1.p = fz_point_on_circle(p0, r0, theta + i * step + step); + t2.p = fz_point_on_circle(p1, r1, theta + i * step); + t3.p = fz_point_on_circle(p1, r1, theta + i * step + step); + b0.p = fz_point_on_circle(p0, r0, theta - i * step); + b1.p = fz_point_on_circle(p0, r0, theta - i * step - step); + b2.p = fz_point_on_circle(p1, r1, theta - i * step); + b3.p = fz_point_on_circle(p1, r1, theta - i * step - step); + + t0.p = fz_transform_point(ctm, t0.p); + t1.p = fz_transform_point(ctm, t1.p); + t2.p = fz_transform_point(ctm, t2.p); + t3.p = fz_transform_point(ctm, t3.p); + b0.p = fz_transform_point(ctm, b0.p); + b1.p = fz_transform_point(ctm, b1.p); + b2.p = fz_transform_point(ctm, b2.p); + b3.p = fz_transform_point(ctm, b3.p); + + t0.c[0] = c0; + t1.c[0] = c0; + t2.c[0] = c1; + t3.c[0] = c1; + b0.c[0] = c0; + b1.c[0] = c0; + b2.c[0] = c1; + b3.c[0] = c1; + + paint_quad(painter, &t0, &t2, &t3, &t1); + paint_quad(painter, &b0, &b2, &b3, &b1); + } +} + +static void +fz_mesh_type3_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter) +{ + fz_point p0, p1; + float r0, r1; + fz_point e; + float er, rs; + + p0.x = shade->u.a_or_r.coords[0][0]; + p0.y = shade->u.a_or_r.coords[0][1]; + r0 = shade->u.a_or_r.coords[0][2]; + + p1.x = shade->u.a_or_r.coords[1][0]; + p1.y = shade->u.a_or_r.coords[1][1]; + r1 = shade->u.a_or_r.coords[1][2]; + + if (shade->u.a_or_r.extend[0]) + { + if (r0 < r1) + rs = r0 / (r0 - r1); + else + rs = -HUGENUM; + + e.x = p0.x + (p1.x - p0.x) * rs; + e.y = p0.y + (p1.y - p0.y) * rs; + er = r0 + (r1 - r0) * rs; + + fz_paint_annulus(ctm, e, er, 0, p0, r0, 0, painter); + } + + fz_paint_annulus(ctm, p0, r0, 0, p1, r1, 1, painter); + + if (shade->u.a_or_r.extend[1]) + { + if (r0 > r1) + rs = r1 / (r1 - r0); + else + rs = -HUGENUM; + + e.x = p1.x + (p0.x - p1.x) * rs; + e.y = p1.y + (p0.y - p1.y) * rs; + er = r1 + (r0 - r1) * rs; + + fz_paint_annulus(ctm, p1, r1, 1, e, er, 1, painter); + } +} + static inline float read_sample(fz_stream *stream, int bits, float min, float max) { /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */ @@ -738,6 +911,10 @@ fz_process_mesh(fz_context *ctx, fz_shade *shade, fz_matrix ctm, if (shade->type == FZ_FUNCTION_BASED) fz_mesh_type1_process(ctx, shade, ctm, &painter); + else if (shade->type == FZ_LINEAR) + fz_mesh_type2_process(ctx, shade, ctm, &painter); + else if (shade->type == FZ_RADIAL) + fz_mesh_type3_process(ctx, shade, ctm, &painter); else if (shade->type == FZ_MESH_TYPE4) fz_mesh_type4_process(ctx, shade, ctm, &painter); else if (shade->type == FZ_MESH_TYPE5) |