sync to tree to support stippi's Painter classes
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10694 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+391
@@ -0,0 +1,391 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.2
|
||||
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: [email protected]
|
||||
// [email protected]
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// classes span_pattern_filter_rgba32*
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SPAN_PATTERN_FILTER_RGBA32_INCLUDED
|
||||
#define AGG_SPAN_PATTERN_FILTER_RGBA32_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba8.h"
|
||||
#include "agg_span_image_filter.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===========================================span_pattern_filter_rgba32_nn
|
||||
template<class Order,
|
||||
class Interpolator,
|
||||
class RemainderX,
|
||||
class RemainderY,
|
||||
class Allocator = span_allocator<rgba8> >
|
||||
class span_pattern_filter_rgba32_nn :
|
||||
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||
{
|
||||
public:
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef Allocator alloc_type;
|
||||
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||
typedef rgba8 color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_filter_rgba32_nn(alloc_type& alloc) :
|
||||
base_type(alloc),
|
||||
m_remainder_x(1),
|
||||
m_remainder_y(1)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_filter_rgba32_nn(alloc_type& alloc,
|
||||
const rendering_buffer& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(alloc, src, color_type(0,0,0,0), inter, 0),
|
||||
m_remainder_x(src.width()),
|
||||
m_remainder_y(src.height())
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void source_image(const rendering_buffer& src)
|
||||
{
|
||||
base_type::source_image(src);
|
||||
m_remainder_x = RemainderX(src.width());
|
||||
m_remainder_y = RemainderX(src.height());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
const unsigned char *fg_ptr;
|
||||
color_type* span = base_type::allocator().span();
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x = m_remainder_x(x >> image_subpixel_shift);
|
||||
y = m_remainder_y(y >> image_subpixel_shift);
|
||||
|
||||
fg_ptr = base_type::source_image().row(y) + (x << 2);
|
||||
span->r = fg_ptr[Order::R];
|
||||
span->g = fg_ptr[Order::G];
|
||||
span->b = fg_ptr[Order::B];
|
||||
span->a = fg_ptr[Order::A];
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
|
||||
return base_type::allocator().span();
|
||||
}
|
||||
|
||||
private:
|
||||
RemainderX m_remainder_x;
|
||||
RemainderY m_remainder_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================span_pattern_filter_rgba32_bilinear
|
||||
template<class Order,
|
||||
class Interpolator,
|
||||
class RemainderX,
|
||||
class RemainderY,
|
||||
class Allocator = span_allocator<rgba8> >
|
||||
class span_pattern_filter_rgba32_bilinear :
|
||||
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||
{
|
||||
public:
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef Allocator alloc_type;
|
||||
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||
typedef rgba8 color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_filter_rgba32_bilinear(alloc_type& alloc) :
|
||||
base_type(alloc),
|
||||
m_remainder_x(1),
|
||||
m_remainder_y(1)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_filter_rgba32_bilinear(alloc_type& alloc,
|
||||
const rendering_buffer& src,
|
||||
interpolator_type& inter) :
|
||||
base_type(alloc, src, color_type(0,0,0,0), inter, 0),
|
||||
m_remainder_x(src.width()),
|
||||
m_remainder_y(src.height())
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void source_image(const rendering_buffer& src)
|
||||
{
|
||||
base_type::source_image(src);
|
||||
m_remainder_x = RemainderX(src.width());
|
||||
m_remainder_y = RemainderX(src.height());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
int fg[4];
|
||||
const int8u *fg_ptr;
|
||||
color_type* span = base_type::allocator().span();
|
||||
|
||||
do
|
||||
{
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
|
||||
unsigned x1 = m_remainder_x(x_lr);
|
||||
unsigned x2 = x1 + 1;
|
||||
if(x2 >= base_type::source_image().width()) x2 = 0;
|
||||
x1 <<= 2;
|
||||
x2 <<= 2;
|
||||
|
||||
unsigned y1 = m_remainder_y(y_lr);
|
||||
unsigned y2 = y1 + 1;
|
||||
if(y2 >= base_type::source_image().height()) y2 = 0;
|
||||
const int8u* ptr1 = base_type::source_image().row(y1);
|
||||
const int8u* ptr2 = base_type::source_image().row(y2);
|
||||
|
||||
fg[0] =
|
||||
fg[1] =
|
||||
fg[2] =
|
||||
fg[3] = image_subpixel_size * image_subpixel_size / 2;
|
||||
|
||||
x_hr &= image_subpixel_mask;
|
||||
y_hr &= image_subpixel_mask;
|
||||
|
||||
int weight;
|
||||
fg_ptr = ptr1 + x1;
|
||||
weight = (image_subpixel_size - x_hr) *
|
||||
(image_subpixel_size - y_hr);
|
||||
fg[0] += weight * fg_ptr[0];
|
||||
fg[1] += weight * fg_ptr[1];
|
||||
fg[2] += weight * fg_ptr[2];
|
||||
fg[3] += weight * fg_ptr[3];
|
||||
|
||||
fg_ptr = ptr1 + x2;
|
||||
weight = x_hr * (image_subpixel_size - y_hr);
|
||||
fg[0] += weight * fg_ptr[0];
|
||||
fg[1] += weight * fg_ptr[1];
|
||||
fg[2] += weight * fg_ptr[2];
|
||||
fg[3] += weight * fg_ptr[3];
|
||||
|
||||
fg_ptr = ptr2 + x1;
|
||||
weight = (image_subpixel_size - x_hr) * y_hr;
|
||||
fg[0] += weight * fg_ptr[0];
|
||||
fg[1] += weight * fg_ptr[1];
|
||||
fg[2] += weight * fg_ptr[2];
|
||||
fg[3] += weight * fg_ptr[3];
|
||||
|
||||
fg_ptr = ptr2 + x2;
|
||||
weight = x_hr * y_hr;
|
||||
fg[0] += weight * fg_ptr[0];
|
||||
fg[1] += weight * fg_ptr[1];
|
||||
fg[2] += weight * fg_ptr[2];
|
||||
fg[3] += weight * fg_ptr[3];
|
||||
|
||||
span->r = (int8u)(fg[Order::R] >> image_subpixel_shift * 2);
|
||||
span->g = (int8u)(fg[Order::G] >> image_subpixel_shift * 2);
|
||||
span->b = (int8u)(fg[Order::B] >> image_subpixel_shift * 2);
|
||||
span->a = (int8u)(fg[Order::A] >> image_subpixel_shift * 2);
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
|
||||
return base_type::allocator().span();
|
||||
}
|
||||
private:
|
||||
RemainderX m_remainder_x;
|
||||
RemainderY m_remainder_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==============================================span_pattern_filter_rgba32
|
||||
template<class Order,
|
||||
class Interpolator,
|
||||
class RemainderX,
|
||||
class RemainderY,
|
||||
class Allocator = span_allocator<rgba8> >
|
||||
class span_pattern_filter_rgba32 :
|
||||
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||
{
|
||||
public:
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef Allocator alloc_type;
|
||||
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||
typedef rgba8 color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_filter_rgba32(alloc_type& alloc) :
|
||||
base_type(alloc)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_pattern_filter_rgba32(alloc_type& alloc,
|
||||
const rendering_buffer& src,
|
||||
interpolator_type& inter,
|
||||
const image_filter_base& filter) :
|
||||
base_type(alloc, src, color_type(0,0,0,0), inter, &filter),
|
||||
m_remainder_x(src.width()),
|
||||
m_remainder_y(src.height())
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void source_image(const rendering_buffer& src)
|
||||
{
|
||||
base_type::source_image(src);
|
||||
m_remainder_x = RemainderX(src.width());
|
||||
m_remainder_y = RemainderX(src.height());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
int fg[4];
|
||||
|
||||
const unsigned char *fg_ptr;
|
||||
|
||||
unsigned dimension = base_type::filter().dimension();
|
||||
int start = base_type::filter().start();
|
||||
const int* weight_array = base_type::filter().weight_array_int();
|
||||
|
||||
color_type* span = base_type::allocator().span();
|
||||
|
||||
int x_count;
|
||||
int weight_y;
|
||||
|
||||
do
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x -= base_type::filter_dx_int();
|
||||
y -= base_type::filter_dy_int();
|
||||
|
||||
int x_hr = x;
|
||||
int y_hr = y;
|
||||
|
||||
int x_fract = x_hr & image_subpixel_mask;
|
||||
unsigned y_count = dimension;
|
||||
|
||||
int y_lr = m_remainder_y((y >> image_subpixel_shift) + start);
|
||||
int x_int = m_remainder_x((x >> image_subpixel_shift) + start);
|
||||
int x_lr;
|
||||
|
||||
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||
fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2;
|
||||
|
||||
do
|
||||
{
|
||||
x_count = dimension;
|
||||
weight_y = weight_array[y_hr];
|
||||
x_hr = image_subpixel_mask - x_fract;
|
||||
x_lr = x_int;
|
||||
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
|
||||
|
||||
do
|
||||
{
|
||||
int weight = (weight_y * weight_array[x_hr] +
|
||||
image_filter_size / 2) >>
|
||||
image_filter_shift;
|
||||
|
||||
fg[0] += *fg_ptr++ * weight;
|
||||
fg[1] += *fg_ptr++ * weight;
|
||||
fg[2] += *fg_ptr++ * weight;
|
||||
fg[3] += *fg_ptr++ * weight;
|
||||
|
||||
x_hr += image_subpixel_size;
|
||||
++x_lr;
|
||||
if(x_lr >= int(base_type::source_image().width()))
|
||||
{
|
||||
x_lr = 0;
|
||||
fg_ptr = base_type::source_image().row(y_lr);
|
||||
}
|
||||
|
||||
} while(--x_count);
|
||||
|
||||
y_hr += image_subpixel_size;
|
||||
++y_lr;
|
||||
if(y_lr >= int(base_type::source_image().height())) y_lr = 0;
|
||||
|
||||
} while(--y_count);
|
||||
|
||||
fg[0] >>= image_filter_shift;
|
||||
fg[1] >>= image_filter_shift;
|
||||
fg[2] >>= image_filter_shift;
|
||||
fg[3] >>= image_filter_shift;
|
||||
|
||||
if(fg[0] < 0) fg[0] = 0;
|
||||
if(fg[1] < 0) fg[1] = 0;
|
||||
if(fg[2] < 0) fg[2] = 0;
|
||||
if(fg[3] < 0) fg[3] = 0;
|
||||
|
||||
if(fg[Order::A] > 255) fg[Order::A] = 255;
|
||||
if(fg[Order::R] > fg[Order::A]) fg[Order::R] = fg[Order::A];
|
||||
if(fg[Order::G] > fg[Order::A]) fg[Order::G] = fg[Order::A];
|
||||
if(fg[Order::B] > fg[Order::A]) fg[Order::B] = fg[Order::A];
|
||||
|
||||
span->r = fg[Order::R];
|
||||
span->g = fg[Order::G];
|
||||
span->b = fg[Order::B];
|
||||
span->a = fg[Order::A];
|
||||
++span;
|
||||
++base_type::interpolator();
|
||||
|
||||
} while(--len);
|
||||
|
||||
return base_type::allocator().span();
|
||||
}
|
||||
|
||||
private:
|
||||
RemainderX m_remainder_x;
|
||||
RemainderY m_remainder_y;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+22
-16
@@ -13,35 +13,41 @@ SharedLibrary agg :
|
||||
src/agg_bezier_arc.cpp
|
||||
src/agg_bspline.cpp
|
||||
src/agg_curves.cpp
|
||||
src/agg_embedded_raster_fonts.cpp
|
||||
src/agg_gsv_text.cpp
|
||||
src/agg_image_filters.cpp
|
||||
src/agg_line_aa_basics.cpp
|
||||
src/agg_line_profile_aa.cpp
|
||||
src/agg_path_storage.cpp
|
||||
src/agg_rasterizer_scanline_aa.cpp
|
||||
src/agg_rounded_rect.cpp
|
||||
src/agg_sqrt_tables.cpp
|
||||
src/agg_trans_affine.cpp
|
||||
src/agg_trans_double_path.cpp
|
||||
src/agg_trans_single_path.cpp
|
||||
src/agg_trans_warp_magnifier.cpp
|
||||
src/agg_vcgen_bspline.cpp
|
||||
src/agg_vcgen_contour.cpp
|
||||
src/agg_vcgen_dash.cpp
|
||||
src/agg_vcgen_markers_term.cpp
|
||||
src/agg_vcgen_smooth_poly1.cpp
|
||||
src/agg_vcgen_stroke.cpp
|
||||
src/agg_vcgen_bspline.cpp
|
||||
src/agg_gsv_text.cpp
|
||||
src/agg_image_filters.cpp
|
||||
src/agg_path_storage.cpp
|
||||
src/agg_rasterizer_scanline_aa.cpp
|
||||
src/agg_line_aa_basics.cpp
|
||||
src/agg_line_profile_aa.cpp
|
||||
src/agg_rounded_rect.cpp
|
||||
src/agg_sqrt_tables.cpp
|
||||
src/agg_embedded_raster_fonts.cpp
|
||||
src/agg_trans_affine.cpp
|
||||
src/agg_trans_warp_magnifier.cpp
|
||||
src/agg_trans_single_path.cpp
|
||||
src/agg_trans_double_path.cpp
|
||||
src/agg_vpgen_clip_polygon.cpp
|
||||
src/agg_vpgen_clip_polyline.cpp
|
||||
src/agg_vpgen_segmentator.cpp
|
||||
src/ctrl/agg_bezier_ctrl.cpp
|
||||
src/ctrl/agg_cbox_ctrl.cpp
|
||||
src/ctrl/agg_gamma_ctrl.cpp
|
||||
src/ctrl/agg_gamma_spline.cpp
|
||||
src/ctrl/agg_polygon_ctrl.cpp
|
||||
src/ctrl/agg_rbox_ctrl.cpp
|
||||
src/ctrl/agg_scale_ctrl.cpp
|
||||
src/ctrl/agg_slider_ctrl.cpp
|
||||
src/ctrl/agg_spline_ctrl.cpp
|
||||
src/ctrl/agg_scale_ctrl.cpp
|
||||
gpc/gpc.c
|
||||
|
||||
# uncomment this line to enable the General Polygon Clipper
|
||||
# see the license in gpc.c for usage information
|
||||
#gpc/gpc.c
|
||||
;
|
||||
|
||||
LinkSharedOSLibs libagg.so : root be
|
||||
|
||||
@@ -771,10 +771,10 @@ namespace agg
|
||||
m_resolution,
|
||||
m_height,
|
||||
m_width,
|
||||
m_matrix.xx,
|
||||
m_matrix.xy,
|
||||
m_matrix.yx,
|
||||
m_matrix.yy,
|
||||
int(m_matrix.xx),
|
||||
int(m_matrix.xy),
|
||||
int(m_matrix.yx),
|
||||
int(m_matrix.yy),
|
||||
int(m_hinting),
|
||||
int(m_flip_y),
|
||||
gamma_hash);
|
||||
@@ -827,6 +827,7 @@ namespace agg
|
||||
{
|
||||
case glyph_ren_native_mono:
|
||||
m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO);
|
||||
//printf("%i\n", m_last_error);
|
||||
if(m_last_error == 0)
|
||||
{
|
||||
decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap,
|
||||
@@ -1007,6 +1008,7 @@ namespace agg
|
||||
{
|
||||
switch(m_data_type)
|
||||
{
|
||||
default: return;
|
||||
case glyph_data_mono: m_scanlines_bin.serialize(data); break;
|
||||
case glyph_data_gray8: m_scanlines_aa.serialize(data); break;
|
||||
case glyph_data_outline:
|
||||
@@ -1019,6 +1021,7 @@ namespace agg
|
||||
m_path16.serialize(data);
|
||||
}
|
||||
break;
|
||||
case glyph_data_invalid: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace agg
|
||||
x_ctrl = x0;
|
||||
y_ctrl = y0;
|
||||
}
|
||||
curve3(x_ctrl, x_ctrl, x_to, y_to);
|
||||
curve3(x_ctrl, y_ctrl, x_to, y_to);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,15 +26,20 @@ namespace agg
|
||||
//------------------------------------------------------------------------
|
||||
vcgen_contour::vcgen_contour() :
|
||||
m_src_vertices(),
|
||||
m_out_vertices(),
|
||||
m_width(1.0),
|
||||
m_line_join(bevel_join),
|
||||
m_inner_line_join(miter_join_revert),
|
||||
m_approx_scale(1.0),
|
||||
m_abs_width(1.0),
|
||||
m_signed_width(1.0),
|
||||
m_miter_limit(4.0),
|
||||
m_inner_miter_limit(1.0 + 1.0/64.0),
|
||||
m_status(initial),
|
||||
m_src_vertex(0),
|
||||
m_closed(0),
|
||||
m_orientation(0),
|
||||
m_auto_detect(true)
|
||||
m_auto_detect(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -116,8 +121,8 @@ namespace agg
|
||||
//------------------------------------------------------------------------
|
||||
unsigned vcgen_contour::vertex(double* x, double* y)
|
||||
{
|
||||
bool done = false;
|
||||
while(!done)
|
||||
unsigned cmd = path_cmd_line_to;
|
||||
while(!is_stop(cmd))
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
@@ -125,98 +130,62 @@ namespace agg
|
||||
rewind(0);
|
||||
|
||||
case ready:
|
||||
if(m_src_vertices.size() < 3)
|
||||
if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
|
||||
{
|
||||
return path_cmd_stop;
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
m_src_vertex = 0;
|
||||
m_status = outline;
|
||||
cmd = path_cmd_move_to;
|
||||
m_src_vertex = 0;
|
||||
m_out_vertex = 0;
|
||||
|
||||
case outline:
|
||||
if(m_src_vertex >= m_src_vertices.size())
|
||||
{
|
||||
m_status = end_poly;
|
||||
return path_cmd_end_poly | m_orientation | m_closed;
|
||||
}
|
||||
if(calc_miter(m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex)))
|
||||
{
|
||||
m_status = add_point;
|
||||
break;
|
||||
}
|
||||
stroke_calc_join(m_out_vertices,
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_signed_width,
|
||||
m_line_join,
|
||||
m_inner_line_join,
|
||||
m_miter_limit,
|
||||
m_inner_miter_limit,
|
||||
m_approx_scale);
|
||||
++m_src_vertex;
|
||||
*x = m_x1;
|
||||
*y = m_y1;
|
||||
return ((m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to);
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
|
||||
case add_point:
|
||||
*x = m_x2;
|
||||
*y = m_y2;
|
||||
m_status = outline;
|
||||
return path_cmd_line_to;
|
||||
case out_vertices:
|
||||
if(m_out_vertex >= m_out_vertices.size())
|
||||
{
|
||||
m_status = outline;
|
||||
}
|
||||
else
|
||||
{
|
||||
const point_type& c = m_out_vertices[m_out_vertex++];
|
||||
*x = c.x;
|
||||
*y = c.y;
|
||||
return cmd;
|
||||
}
|
||||
break;
|
||||
|
||||
case end_poly:
|
||||
done = true;
|
||||
break;
|
||||
if(!m_closed) return path_cmd_stop;
|
||||
m_status = stop;
|
||||
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
|
||||
|
||||
case stop:
|
||||
return path_cmd_stop;
|
||||
}
|
||||
}
|
||||
return path_cmd_stop;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool vcgen_contour::calc_miter(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2)
|
||||
{
|
||||
double dx1, dy1, dx2, dy2;
|
||||
|
||||
dx1 = m_signed_width * (v1.y - v0.y) / v0.dist;
|
||||
dy1 = m_signed_width * (v1.x - v0.x) / v0.dist;
|
||||
|
||||
dx2 = m_signed_width * (v2.y - v1.y) / v1.dist;
|
||||
dy2 = m_signed_width * (v2.x - v1.x) / v1.dist;
|
||||
|
||||
double xi;
|
||||
double yi;
|
||||
|
||||
if(!calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&xi, &yi))
|
||||
{
|
||||
m_x1 = v1.x + dx1;
|
||||
m_y1 = v1.y - dy1;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
double d1 = calc_distance(v1.x, v1.y, xi, yi);
|
||||
double lim = m_abs_width * m_miter_limit;
|
||||
if(d1 > lim)
|
||||
{
|
||||
d1 = lim / d1;
|
||||
m_x1 = v1.x + dx1;
|
||||
m_y1 = v1.y - dy1;
|
||||
m_x2 = v1.x + dx2;
|
||||
m_y2 = v1.y - dy2;
|
||||
|
||||
m_x1 += (xi - m_x1) * d1;
|
||||
m_y1 += (yi - m_y1) * d1;
|
||||
m_x2 += (xi - m_x2) * d1;
|
||||
m_y2 += (yi - m_y2) * d1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_x1 = xi;
|
||||
m_y1 = yi;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -29,10 +29,12 @@ namespace agg
|
||||
m_out_vertices(),
|
||||
m_width(0.5),
|
||||
m_miter_limit(4.0),
|
||||
m_inner_miter_limit(1.0 + 1.0/64.0),
|
||||
m_approx_scale(1.0),
|
||||
m_shorten(0.0),
|
||||
m_line_cap(butt_cap),
|
||||
m_line_join(miter_join),
|
||||
m_inner_line_join(miter_join_revert),
|
||||
m_closed(0),
|
||||
m_status(initial),
|
||||
m_src_vertex(0),
|
||||
@@ -86,6 +88,7 @@ namespace agg
|
||||
{
|
||||
m_src_vertices.close(m_closed != 0);
|
||||
shorten_path(m_src_vertices, m_shorten, m_closed);
|
||||
if(m_src_vertices.size() < 3) m_closed = 0;
|
||||
}
|
||||
m_status = ready;
|
||||
m_src_vertex = 0;
|
||||
@@ -105,7 +108,7 @@ namespace agg
|
||||
rewind(0);
|
||||
|
||||
case ready:
|
||||
if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
|
||||
if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
|
||||
{
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
@@ -117,9 +120,13 @@ namespace agg
|
||||
break;
|
||||
|
||||
case cap1:
|
||||
calc_cap(m_src_vertices[0],
|
||||
m_src_vertices[1],
|
||||
m_src_vertices[0].dist);
|
||||
stroke_calc_cap(m_out_vertices,
|
||||
m_src_vertices[0],
|
||||
m_src_vertices[1],
|
||||
m_src_vertices[0].dist,
|
||||
m_line_cap,
|
||||
m_width,
|
||||
m_approx_scale);
|
||||
m_src_vertex = 1;
|
||||
m_prev_status = outline1;
|
||||
m_status = out_vertices;
|
||||
@@ -127,9 +134,13 @@ namespace agg
|
||||
break;
|
||||
|
||||
case cap2:
|
||||
calc_cap(m_src_vertices[m_src_vertices.size() - 1],
|
||||
m_src_vertices[m_src_vertices.size() - 2],
|
||||
m_src_vertices[m_src_vertices.size() - 2].dist);
|
||||
stroke_calc_cap(m_out_vertices,
|
||||
m_src_vertices[m_src_vertices.size() - 1],
|
||||
m_src_vertices[m_src_vertices.size() - 2],
|
||||
m_src_vertices[m_src_vertices.size() - 2].dist,
|
||||
m_line_cap,
|
||||
m_width,
|
||||
m_approx_scale);
|
||||
m_prev_status = outline2;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
@@ -153,12 +164,18 @@ namespace agg
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
calc_join(m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_src_vertices.curr(m_src_vertex).dist);
|
||||
stroke_calc_join(m_out_vertices,
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_width,
|
||||
m_line_join,
|
||||
m_inner_line_join,
|
||||
m_miter_limit,
|
||||
m_inner_miter_limit,
|
||||
m_approx_scale);
|
||||
++m_src_vertex;
|
||||
m_prev_status = m_status;
|
||||
m_status = out_vertices;
|
||||
@@ -178,11 +195,18 @@ namespace agg
|
||||
}
|
||||
|
||||
--m_src_vertex;
|
||||
calc_join(m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_src_vertices.prev(m_src_vertex).dist);
|
||||
stroke_calc_join(m_out_vertices,
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_width,
|
||||
m_line_join,
|
||||
m_inner_line_join,
|
||||
m_miter_limit,
|
||||
m_inner_miter_limit,
|
||||
m_approx_scale);
|
||||
|
||||
m_prev_status = m_status;
|
||||
m_status = out_vertices;
|
||||
@@ -196,7 +220,7 @@ namespace agg
|
||||
}
|
||||
else
|
||||
{
|
||||
const coord_type& c = m_out_vertices[m_out_vertex++];
|
||||
const point_type& c = m_out_vertices[m_out_vertex++];
|
||||
*x = c.x;
|
||||
*y = c.y;
|
||||
return cmd;
|
||||
@@ -219,202 +243,4 @@ namespace agg
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::calc_arc(double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
double a1 = atan2(dy1, dx1);
|
||||
double a2 = atan2(dy2, dx2);
|
||||
double da = a1 - a2;
|
||||
|
||||
if(fabs(da) < vcgen_stroke_theta)
|
||||
{
|
||||
m_out_vertices.add(coord_type(x + dx1, y + dy1));
|
||||
m_out_vertices.add(coord_type(x + dx2, y + dy2));
|
||||
return;
|
||||
}
|
||||
|
||||
bool ccw = da > 0.0 && da < pi;
|
||||
|
||||
da = fabs(1.0 / (m_width * m_approx_scale));
|
||||
if(!ccw)
|
||||
{
|
||||
if(a1 > a2) a2 += 2 * pi;
|
||||
while(a1 < a2)
|
||||
{
|
||||
m_out_vertices.add(coord_type(x + cos(a1) * m_width, y + sin(a1) * m_width));
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(a1 < a2) a2 -= 2 * pi;
|
||||
while(a1 > a2)
|
||||
{
|
||||
m_out_vertices.add(coord_type(x + cos(a1) * m_width, y + sin(a1) * m_width));
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
m_out_vertices.add(coord_type(x + dx2, y + dy2));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::calc_cap(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len)
|
||||
{
|
||||
m_out_vertices.remove_all();
|
||||
|
||||
double dx1 = m_width * (v1.y - v0.y) / len;
|
||||
double dy1 = m_width * (v1.x - v0.x) / len;
|
||||
double dx2 = 0;
|
||||
double dy2 = 0;
|
||||
|
||||
|
||||
if(m_line_cap == square_cap)
|
||||
{
|
||||
dx2 = dy1;
|
||||
dy2 = dx1;
|
||||
}
|
||||
|
||||
if(m_line_cap == round_cap)
|
||||
{
|
||||
double a1 = atan2(dy1, -dx1);
|
||||
double a2 = a1 + pi;
|
||||
double da = fabs(1.0 / (m_width * m_approx_scale));
|
||||
while(a1 < a2)
|
||||
{
|
||||
m_out_vertices.add(coord_type(v0.x + cos(a1) * m_width,
|
||||
v0.y + sin(a1) * m_width));
|
||||
a1 += da;
|
||||
}
|
||||
m_out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2));
|
||||
m_out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::calc_miter(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
bool revert_flag)
|
||||
{
|
||||
double xi = v1.x;
|
||||
double yi = v1.y;
|
||||
if(!calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&xi, &yi))
|
||||
{
|
||||
// The calculation didn't succeed, most probaly
|
||||
// the the three points lie one straight line
|
||||
//----------------
|
||||
m_out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
}
|
||||
else
|
||||
{
|
||||
double d1 = calc_distance(v1.x, v1.y, xi, yi);
|
||||
double lim = m_width * m_miter_limit;
|
||||
if(d1 > lim)
|
||||
{
|
||||
// Miter limit exceeded
|
||||
//------------------------
|
||||
if(revert_flag)
|
||||
{
|
||||
// For the compatibility with SVG, PDF, etc,
|
||||
// we use a simple bevel join instead of
|
||||
// "smart" bevel
|
||||
//-------------------
|
||||
m_out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
m_out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Smart bevel that cuts the miter at the limit point
|
||||
//-------------------
|
||||
d1 = lim / d1;
|
||||
double x1 = v1.x + dx1;
|
||||
double y1 = v1.y - dy1;
|
||||
double x2 = v1.x + dx2;
|
||||
double y2 = v1.y - dy2;
|
||||
|
||||
x1 += (xi - x1) * d1;
|
||||
y1 += (yi - y1) * d1;
|
||||
x2 += (xi - x2) * d1;
|
||||
y2 += (yi - y2) * d1;
|
||||
m_out_vertices.add(coord_type(x1, y1));
|
||||
m_out_vertices.add(coord_type(x2, y2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inside the miter limit
|
||||
//---------------------
|
||||
m_out_vertices.add(coord_type(xi, yi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::calc_join(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1, double len2)
|
||||
{
|
||||
double dx1, dy1, dx2, dy2;
|
||||
|
||||
dx1 = m_width * (v1.y - v0.y) / len1;
|
||||
dy1 = m_width * (v1.x - v0.x) / len1;
|
||||
|
||||
dx2 = m_width * (v2.y - v1.y) / len2;
|
||||
dy2 = m_width * (v2.x - v1.x) / len2;
|
||||
|
||||
m_out_vertices.remove_all();
|
||||
if(m_line_join == miter_join)
|
||||
{
|
||||
calc_miter(v0, v1, v2, dx1, dy1, dx2, dy2, m_line_join == miter_join_revert);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(calc_point_location(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0.0)
|
||||
{
|
||||
calc_miter(v0, v1, v2, dx1, dy1, dx2, dy2, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_line_join == round_join)
|
||||
{
|
||||
calc_arc(v1.x, v1.y, dx1, -dy1, dx2, -dy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_line_join == miter_join_revert)
|
||||
{
|
||||
calc_miter(v0, v1, v2, dx1, dy1, dx2, dy2, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
m_out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.2
|
||||
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: [email protected]
|
||||
// [email protected]
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_vpgen_clip_polyline.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
static double clip_epsilon = 1e-10;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void vpgen_clip_polyline::reset()
|
||||
{
|
||||
m_vertex = 0;
|
||||
m_num_vertices = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void vpgen_clip_polyline::move_to(double x, double y)
|
||||
{
|
||||
m_vertex = 0;
|
||||
m_num_vertices = 0;
|
||||
m_f1 = clipping_flags(x, y);
|
||||
if(m_f1 == 0)
|
||||
{
|
||||
m_x[0] = x;
|
||||
m_y[0] = y;
|
||||
m_cmd[0] = path_cmd_move_to;
|
||||
m_num_vertices = 1;
|
||||
}
|
||||
m_x1 = x;
|
||||
m_y1 = y;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool vpgen_clip_polyline::move_point(double& x, double& y, unsigned& flags)
|
||||
{
|
||||
double bound;
|
||||
|
||||
if(flags & (clip_x1 | clip_x2))
|
||||
{
|
||||
bound = (flags & clip_x1) ? m_clip_box.x1 : m_clip_box.x2;
|
||||
y = (bound - m_x1) * (m_y2 - m_y1) / (m_x2 - m_x1) + m_y1;
|
||||
x = bound;
|
||||
flags = clipping_flags_y(y);
|
||||
}
|
||||
if(fabs(m_y2 - m_y1) < clip_epsilon && fabs(m_x2 - m_x1) < clip_epsilon)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(flags & (clip_y1 | clip_y2))
|
||||
{
|
||||
bound = (flags & clip_y1) ? m_clip_box.y1 : m_clip_box.y2;
|
||||
x = (bound - m_y1) * (m_x2 - m_x1) / (m_y2 - m_y1) + m_x1;
|
||||
y = bound;
|
||||
}
|
||||
flags = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void vpgen_clip_polyline::clip_line_segment()
|
||||
{
|
||||
if((m_f1 & m_f2) == 0)
|
||||
{
|
||||
if(m_f1)
|
||||
{
|
||||
if(!move_point(m_x1, m_y1, m_f1)) return;
|
||||
if(m_f1) return;
|
||||
m_x[0] = m_x1;
|
||||
m_y[0] = m_y1;
|
||||
m_cmd[0] = path_cmd_move_to;
|
||||
m_num_vertices = 1;
|
||||
}
|
||||
if(m_f2)
|
||||
{ // Move Point 2
|
||||
if(!move_point(m_x2, m_y2, m_f2)) return;
|
||||
}
|
||||
m_x[m_num_vertices] = m_x2;
|
||||
m_y[m_num_vertices] = m_y2;
|
||||
m_cmd[m_num_vertices++] = path_cmd_line_to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void vpgen_clip_polyline::line_to(double x, double y)
|
||||
{
|
||||
m_vertex = 0;
|
||||
m_num_vertices = 0;
|
||||
unsigned f = m_f2 = clipping_flags(m_x2 = x, m_y2 = y);
|
||||
|
||||
if(m_f2 == m_f1)
|
||||
{
|
||||
if(m_f2 == 0)
|
||||
{
|
||||
m_x[0] = x;
|
||||
m_y[0] = y;
|
||||
m_cmd[0] = path_cmd_line_to;
|
||||
m_num_vertices = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clip_line_segment();
|
||||
}
|
||||
|
||||
m_f1 = f;
|
||||
m_x1 = x;
|
||||
m_y1 = y;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
unsigned vpgen_clip_polyline::vertex(double* x, double* y)
|
||||
{
|
||||
if(m_vertex < m_num_vertices)
|
||||
{
|
||||
*x = m_x[m_vertex];
|
||||
*y = m_y[m_vertex];
|
||||
return m_cmd[m_vertex++];
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace agg
|
||||
m_dx = 0.0;
|
||||
m_dy = 0.0;
|
||||
m_dl = 2.0;
|
||||
m_ddl = 2.0;
|
||||
m_cmd = path_cmd_move_to;
|
||||
}
|
||||
|
||||
@@ -48,10 +49,13 @@ namespace agg
|
||||
|
||||
unsigned cmd = m_cmd;
|
||||
m_cmd = path_cmd_line_to;
|
||||
if(m_dl > 1.0)
|
||||
if(m_dl >= 1.0 - m_ddl)
|
||||
{
|
||||
m_dl = 1.0;
|
||||
m_cmd = path_cmd_stop;
|
||||
*x = m_x1 + m_dx;
|
||||
*y = m_y1 + m_dy;
|
||||
return cmd;
|
||||
}
|
||||
*x = m_x1 + m_dx * m_dl;
|
||||
*y = m_y1 + m_dy * m_dl;
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.2
|
||||
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: [email protected]
|
||||
// [email protected]
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// classes bezier_ctrl_impl, bezier_ctrl
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "ctrl/agg_bezier_ctrl.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bezier_ctrl_impl::bezier_ctrl_impl() :
|
||||
ctrl(0,0,1,1,false),
|
||||
m_stroke(m_curve),
|
||||
m_poly(4, 5.0),
|
||||
m_idx(0)
|
||||
{
|
||||
m_poly.in_polygon_check(false);
|
||||
m_poly.xn(0) = 100.0;
|
||||
m_poly.yn(0) = 0.0;
|
||||
m_poly.xn(1) = 100.0;
|
||||
m_poly.yn(1) = 50.0;
|
||||
m_poly.xn(2) = 50.0;
|
||||
m_poly.yn(2) = 100.0;
|
||||
m_poly.xn(3) = 0.0;
|
||||
m_poly.yn(3) = 100.0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void bezier_ctrl_impl::curve(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
m_poly.xn(0) = x1;
|
||||
m_poly.yn(0) = y1;
|
||||
m_poly.xn(1) = x2;
|
||||
m_poly.yn(1) = y2;
|
||||
m_poly.xn(2) = x3;
|
||||
m_poly.yn(2) = y3;
|
||||
m_poly.xn(3) = x4;
|
||||
m_poly.yn(3) = y4;
|
||||
curve();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
curve4& bezier_ctrl_impl::curve()
|
||||
{
|
||||
m_curve.init(m_poly.xn(0), m_poly.yn(0),
|
||||
m_poly.xn(1), m_poly.yn(1),
|
||||
m_poly.xn(2), m_poly.yn(2),
|
||||
m_poly.xn(3), m_poly.yn(3));
|
||||
return m_curve;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void bezier_ctrl_impl::rewind(unsigned idx)
|
||||
{
|
||||
m_idx = idx;
|
||||
|
||||
switch(idx)
|
||||
{
|
||||
default:
|
||||
case 0: // Control line 1
|
||||
m_curve.init(m_poly.xn(0), m_poly.yn(0),
|
||||
(m_poly.xn(0) + m_poly.xn(1)) * 0.5,
|
||||
(m_poly.yn(0) + m_poly.yn(1)) * 0.5,
|
||||
(m_poly.xn(0) + m_poly.xn(1)) * 0.5,
|
||||
(m_poly.yn(0) + m_poly.yn(1)) * 0.5,
|
||||
m_poly.xn(1), m_poly.yn(1));
|
||||
m_stroke.rewind(0);
|
||||
break;
|
||||
|
||||
case 1: // Control line 2
|
||||
m_curve.init(m_poly.xn(2), m_poly.yn(2),
|
||||
(m_poly.xn(2) + m_poly.xn(3)) * 0.5,
|
||||
(m_poly.yn(2) + m_poly.yn(3)) * 0.5,
|
||||
(m_poly.xn(2) + m_poly.xn(3)) * 0.5,
|
||||
(m_poly.yn(2) + m_poly.yn(3)) * 0.5,
|
||||
m_poly.xn(3), m_poly.yn(3));
|
||||
m_stroke.rewind(0);
|
||||
break;
|
||||
|
||||
case 2: // Curve itself
|
||||
m_curve.init(m_poly.xn(0), m_poly.yn(0),
|
||||
m_poly.xn(1), m_poly.yn(1),
|
||||
m_poly.xn(2), m_poly.yn(2),
|
||||
m_poly.xn(3), m_poly.yn(3));
|
||||
m_stroke.rewind(0);
|
||||
break;
|
||||
|
||||
case 3: // Point 1
|
||||
m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20);
|
||||
m_ellipse.rewind(0);
|
||||
break;
|
||||
|
||||
case 4: // Point 2
|
||||
m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20);
|
||||
m_ellipse.rewind(0);
|
||||
break;
|
||||
|
||||
case 5: // Point 3
|
||||
m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20);
|
||||
m_ellipse.rewind(0);
|
||||
break;
|
||||
|
||||
case 6: // Point 4
|
||||
m_ellipse.init(m_poly.xn(3), m_poly.yn(3), point_radius(), point_radius(), 20);
|
||||
m_ellipse.rewind(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned bezier_ctrl_impl::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
switch(m_idx)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
cmd = m_stroke.vertex(x, y);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
cmd = m_ellipse.vertex(x, y);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!is_stop(cmd))
|
||||
{
|
||||
transform_xy(x, y);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool bezier_ctrl_impl::in_rect(double x, double y) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool bezier_ctrl_impl::on_mouse_button_down(double x, double y)
|
||||
{
|
||||
inverse_transform_xy(&x, &y);
|
||||
return m_poly.on_mouse_button_down(x, y);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool bezier_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
|
||||
{
|
||||
inverse_transform_xy(&x, &y);
|
||||
return m_poly.on_mouse_move(x, y, button_flag);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool bezier_ctrl_impl::on_mouse_button_up(double x, double y)
|
||||
{
|
||||
return m_poly.on_mouse_button_up(x, y);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool bezier_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
|
||||
{
|
||||
return m_poly.on_arrow_keys(left, right, down, up);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -131,8 +131,8 @@ namespace agg
|
||||
m_text.start_point(m_x1 + m_text_height * 2.0, m_y1 + m_text_height / 5.0);
|
||||
m_text.size(m_text_height, m_text_width);
|
||||
m_text_poly.width(m_text_thickness);
|
||||
m_text_poly.line_join(vcgen_stroke::round_join);
|
||||
m_text_poly.line_cap(vcgen_stroke::round_cap);
|
||||
m_text_poly.line_join(round_join);
|
||||
m_text_poly.line_cap(round_cap);
|
||||
m_text_poly.rewind(0);
|
||||
break;
|
||||
|
||||
|
||||
@@ -245,8 +245,8 @@ namespace agg
|
||||
m_text.size(m_text_height, m_text_width);
|
||||
m_text.start_point(m_xt1 + m_border_width * 2.0, (m_yt1 + m_yt2) * 0.5 - m_text_height * 0.5);
|
||||
m_text_poly.width(m_text_thickness);
|
||||
m_text_poly.line_join(vcgen_stroke::round_join);
|
||||
m_text_poly.line_cap(vcgen_stroke::round_cap);
|
||||
m_text_poly.line_join(round_join);
|
||||
m_text_poly.line_cap(round_cap);
|
||||
m_text_poly.rewind(0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.2
|
||||
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: [email protected]
|
||||
// [email protected]
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// classes polygon_ctrl_impl
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "ctrl/agg_polygon_ctrl.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
polygon_ctrl_impl::~polygon_ctrl_impl()
|
||||
{
|
||||
delete [] m_polygon;
|
||||
}
|
||||
|
||||
|
||||
polygon_ctrl_impl::polygon_ctrl_impl(unsigned np, double point_radius) :
|
||||
ctrl(0, 0, 1, 1, false),
|
||||
m_polygon(new double[np * 2]),
|
||||
m_num_points(np),
|
||||
m_node(-1),
|
||||
m_edge(-1),
|
||||
m_vs(m_polygon, m_num_points, false),
|
||||
m_stroke(m_vs),
|
||||
m_point_radius(point_radius),
|
||||
m_status(0),
|
||||
m_dx(0.0),
|
||||
m_dy(0.0)
|
||||
{
|
||||
m_stroke.width(1.0);
|
||||
}
|
||||
|
||||
|
||||
void polygon_ctrl_impl::rewind(unsigned)
|
||||
{
|
||||
m_status = 0;
|
||||
m_stroke.rewind(0);
|
||||
}
|
||||
|
||||
unsigned polygon_ctrl_impl::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
double r = m_point_radius;
|
||||
if(m_status == 0)
|
||||
{
|
||||
cmd = m_stroke.vertex(x, y);
|
||||
if(!is_stop(cmd))
|
||||
{
|
||||
transform_xy(x, y);
|
||||
return cmd;
|
||||
}
|
||||
if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
|
||||
m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
|
||||
++m_status;
|
||||
}
|
||||
cmd = m_ellipse.vertex(x, y);
|
||||
if(!is_stop(cmd))
|
||||
{
|
||||
transform_xy(x, y);
|
||||
return cmd;
|
||||
}
|
||||
if(m_status >= m_num_points) return path_cmd_stop;
|
||||
if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
|
||||
m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
|
||||
++m_status;
|
||||
cmd = m_ellipse.vertex(x, y);
|
||||
if(!is_stop(cmd))
|
||||
{
|
||||
transform_xy(x, y);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
bool polygon_ctrl_impl::check_edge(unsigned i, double x, double y) const
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
unsigned n1 = i;
|
||||
unsigned n2 = (i + m_num_points - 1) % m_num_points;
|
||||
double x1 = xn(n1);
|
||||
double y1 = yn(n1);
|
||||
double x2 = xn(n2);
|
||||
double y2 = yn(n2);
|
||||
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
|
||||
if(sqrt(dx*dx + dy*dy) > 0.0000001)
|
||||
{
|
||||
double x3 = x;
|
||||
double y3 = y;
|
||||
double x4 = x3 - dy;
|
||||
double y4 = y3 + dx;
|
||||
|
||||
double den = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1);
|
||||
double u1 = ((x4-x3) * (y1-y3) - (y4-y3) * (x1-x3)) / den;
|
||||
|
||||
double xi = x1 + u1 * (x2 - x1);
|
||||
double yi = y1 + u1 * (y2 - y1);
|
||||
|
||||
dx = xi - x;
|
||||
dy = yi - y;
|
||||
|
||||
if (u1 > 0.0 && u1 < 1.0 && sqrt(dx*dx + dy*dy) <= m_point_radius)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool polygon_ctrl_impl::in_rect(double x, double y) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool polygon_ctrl_impl::on_mouse_button_down(double x, double y)
|
||||
{
|
||||
unsigned i;
|
||||
bool ret = false;
|
||||
m_node = -1;
|
||||
m_edge = -1;
|
||||
inverse_transform_xy(&x, &y);
|
||||
for (i = 0; i < m_num_points; i++)
|
||||
{
|
||||
if(sqrt( (x-xn(i)) * (x-xn(i)) + (y-yn(i)) * (y-yn(i)) ) < m_point_radius)
|
||||
{
|
||||
m_dx = x - xn(i);
|
||||
m_dy = y - yn(i);
|
||||
m_node = int(i);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ret)
|
||||
{
|
||||
for (i = 0; i < m_num_points; i++)
|
||||
{
|
||||
if(check_edge(i, x, y))
|
||||
{
|
||||
m_dx = x;
|
||||
m_dy = y;
|
||||
m_edge = int(i);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!ret)
|
||||
{
|
||||
if(point_in_polygon(x, y))
|
||||
{
|
||||
m_dx = x;
|
||||
m_dy = y;
|
||||
m_node = int(m_num_points);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool polygon_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
|
||||
{
|
||||
bool ret = false;
|
||||
double dx;
|
||||
double dy;
|
||||
inverse_transform_xy(&x, &y);
|
||||
if(m_node == int(m_num_points))
|
||||
{
|
||||
dx = x - m_dx;
|
||||
dy = y - m_dy;
|
||||
unsigned i;
|
||||
for(i = 0; i < m_num_points; i++)
|
||||
{
|
||||
xn(i) += dx;
|
||||
yn(i) += dy;
|
||||
}
|
||||
m_dx = x;
|
||||
m_dy = y;
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_edge >= 0)
|
||||
{
|
||||
unsigned n1 = m_edge;
|
||||
unsigned n2 = (n1 + m_num_points - 1) % m_num_points;
|
||||
dx = x - m_dx;
|
||||
dy = y - m_dy;
|
||||
xn(n1) += dx;
|
||||
yn(n1) += dy;
|
||||
xn(n2) += dx;
|
||||
yn(n2) += dy;
|
||||
m_dx = x;
|
||||
m_dy = y;
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_node >= 0)
|
||||
{
|
||||
xn(m_node) = x - m_dx;
|
||||
yn(m_node) = y - m_dy;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool polygon_ctrl_impl::on_mouse_button_up(double x, double y)
|
||||
{
|
||||
bool ret = (m_node >= 0) || (m_edge >= 0);
|
||||
m_node = -1;
|
||||
m_edge = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool polygon_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//======= Crossings Multiply algorithm of InsideTest ========================
|
||||
//
|
||||
// By Eric Haines, 3D/Eye Inc, [email protected]
|
||||
//
|
||||
// This version is usually somewhat faster than the original published in
|
||||
// Graphics Gems IV; by turning the division for testing the X axis crossing
|
||||
// into a tricky multiplication test this part of the test became faster,
|
||||
// which had the additional effect of making the test for "both to left or
|
||||
// both to right" a bit slower for triangles than simply computing the
|
||||
// intersection each time. The main increase is in triangle testing speed,
|
||||
// which was about 15% faster; all other polygon complexities were pretty much
|
||||
// the same as before. On machines where division is very expensive (not the
|
||||
// case on the HP 9000 series on which I tested) this test should be much
|
||||
// faster overall than the old code. Your mileage may (in fact, will) vary,
|
||||
// depending on the machine and the test data, but in general I believe this
|
||||
// code is both shorter and faster. This test was inspired by unpublished
|
||||
// Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
|
||||
// Related work by Samosky is in:
|
||||
//
|
||||
// Samosky, Joseph, "SectionView: A system for interactively specifying and
|
||||
// visualizing sections through three-dimensional medical image data",
|
||||
// M.S. Thesis, Department of Electrical Engineering and Computer Science,
|
||||
// Massachusetts Institute of Technology, 1993.
|
||||
//
|
||||
// Shoot a test ray along +X axis. The strategy is to compare vertex Y values
|
||||
// to the testing point's Y and quickly discard edges which are entirely to one
|
||||
// side of the test ray. Note that CONVEX and WINDING code can be added as
|
||||
// for the CrossingsTest() code; it is left out here for clarity.
|
||||
//
|
||||
// Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
|
||||
// _point_, returns 1 if inside, 0 if outside.
|
||||
bool polygon_ctrl_impl::point_in_polygon(double tx, double ty) const
|
||||
{
|
||||
if(m_num_points < 3) return false;
|
||||
if(!m_in_polygon_check) return false;
|
||||
|
||||
unsigned j;
|
||||
int yflag0, yflag1, inside_flag;
|
||||
double vtx0, vty0, vtx1, vty1;
|
||||
|
||||
vtx0 = xn(m_num_points - 1);
|
||||
vty0 = yn(m_num_points - 1);
|
||||
|
||||
// get test bit for above/below X axis
|
||||
yflag0 = (vty0 >= ty);
|
||||
|
||||
vtx1 = xn(0);
|
||||
vty1 = yn(0);
|
||||
|
||||
inside_flag = 0;
|
||||
for (j = 1; j <= m_num_points; ++j)
|
||||
{
|
||||
yflag1 = (vty1 >= ty);
|
||||
// Check if endpoints straddle (are on opposite sides) of X axis
|
||||
// (i.e. the Y's differ); if so, +X ray could intersect this edge.
|
||||
// The old test also checked whether the endpoints are both to the
|
||||
// right or to the left of the test point. However, given the faster
|
||||
// intersection point computation used below, this test was found to
|
||||
// be a break-even proposition for most polygons and a loser for
|
||||
// triangles (where 50% or more of the edges which survive this test
|
||||
// will cross quadrants and so have to have the X intersection computed
|
||||
// anyway). I credit Joseph Samosky with inspiring me to try dropping
|
||||
// the "both left or both right" part of my code.
|
||||
if (yflag0 != yflag1)
|
||||
{
|
||||
// Check intersection of pgon segment with +X ray.
|
||||
// Note if >= point's X; if so, the ray hits it.
|
||||
// The division operation is avoided for the ">=" test by checking
|
||||
// the sign of the first vertex wrto the test point; idea inspired
|
||||
// by Joseph Samosky's and Mark Haigh-Hutchinson's different
|
||||
// polygon inclusion tests.
|
||||
if ( ((vty1-ty) * (vtx0-vtx1) >=
|
||||
(vtx1-tx) * (vty0-vty1)) == yflag1 )
|
||||
{
|
||||
inside_flag ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next pair of vertices, retaining info as possible.
|
||||
yflag0 = yflag1;
|
||||
vtx0 = vtx1;
|
||||
vty0 = vty1;
|
||||
|
||||
unsigned k = (j >= m_num_points) ? j - m_num_points : j;
|
||||
vtx1 = xn(k);
|
||||
vty1 = yn(k);
|
||||
}
|
||||
return inside_flag != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,8 +146,8 @@ namespace agg
|
||||
m_text.start_point(m_xs1 + m_dy * 1.5, m_ys1 + m_dy / 2.0);
|
||||
m_text.size(m_text_height, m_text_width);
|
||||
m_text_poly.width(m_text_thickness);
|
||||
m_text_poly.line_join(vcgen_stroke::round_join);
|
||||
m_text_poly.line_cap(vcgen_stroke::round_cap);
|
||||
m_text_poly.line_join(round_join);
|
||||
m_text_poly.line_cap(round_cap);
|
||||
m_text_poly.rewind(0);
|
||||
break;
|
||||
|
||||
|
||||
@@ -168,8 +168,8 @@ namespace agg
|
||||
m_text.start_point(m_x1, m_y1);
|
||||
m_text.size((m_y2 - m_y1) * 1.2, m_y2 - m_y1);
|
||||
m_text_poly.width(m_text_thickness);
|
||||
m_text_poly.line_join(vcgen_stroke::round_join);
|
||||
m_text_poly.line_cap(vcgen_stroke::round_cap);
|
||||
m_text_poly.line_join(round_join);
|
||||
m_text_poly.line_cap(round_cap);
|
||||
m_text_poly.rewind(0);
|
||||
break;
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace agg
|
||||
#ifdef _WIN32
|
||||
if(dbg_new_level == -1)
|
||||
{
|
||||
FILE* fd = fopen("stdout.txt", "wt");
|
||||
FILE* fd = fopen("stdout.txt", "w");
|
||||
fclose(fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -160,7 +160,6 @@ class AGGView : public BView {
|
||||
|
||||
virtual void FrameResized(float width, float height)
|
||||
{
|
||||
delete fBitmap;
|
||||
BRect r(0.0, 0.0, width, height);
|
||||
BBitmap* bitmap = new BBitmap(r, 0, B_RGBA32);
|
||||
if (bitmap->IsValid()) {
|
||||
|
||||
Reference in New Issue
Block a user