Esempio n. 1
0
void render_raster_marker(RendererType ren,
                          RasterizerType & ras,
                          image_data_rgba8 & src,
                          mapnik::feature_impl const& feature,
                          agg::trans_affine const& marker_tr,
                          double opacity)
{
    using color_type = typename RendererType::color_type;
    agg::scanline_bin sl;
    double width  = src.width();
    double height = src.height();
    double p[8];
    p[0] = 0;     p[1] = 0;
    p[2] = width; p[3] = 0;
    p[4] = width; p[5] = height;
    p[6] = 0;     p[7] = height;
    marker_tr.transform(&p[0], &p[1]);
    marker_tr.transform(&p[2], &p[3]);
    marker_tr.transform(&p[4], &p[5]);
    marker_tr.transform(&p[6], &p[7]);
    ras.move_to_d(p[0],p[1]);
    ras.line_to_d(p[2],p[3]);
    ras.line_to_d(p[4],p[5]);
    ras.line_to_d(p[6],p[7]);
    ren.color(color_type(feature.id()));
    agg::render_scanlines(ras, sl, ren);
}
Esempio n. 2
0
void CAggMemoryDC::Rect(
    const GraphTypes::PointF& tl, 
    const GraphTypes::PointF& br,
    const GraphTypes::Color& clrfill,
    const GraphTypes::Color& clroutline,
    GraphTypes::REAL outline_width/*=1.0*/,
    bool bAA/*=false*/)
{
    if (m_buf==0)
        return;

    if(bAA)
    {
        PointF points[4];
        points[0].x=tl.x;
        points[0].y=tl.y;
        points[1].x=br.x;
        points[1].y=tl.y;
        points[2].x=br.x;
        points[2].y=br.y;
        points[3].x=tl.x;
        points[3].y=br.y;

        SolidPolygon(points, clrfill, 4, outline_width, clroutline); 
    }
    else
    {
        pixel_format pixf(m_rbuf);
        ren_base renb(pixf);

        primitive_renderer pren(renb);

        pren.fill_color(agg::rgba8(
            clrfill.GetR(),
            clrfill.GetG(),
            clrfill.GetB(),
            clrfill.GetA()));
        pren.line_color(agg::rgba8(
            clroutline.GetR(),
            clroutline.GetG(),
            clroutline.GetB(),
            clroutline.GetA()));

        double topx(tl.x), topy(tl.y), bottomx(br.x), bottomy(br.y);
        m_mtx.transform(&topx,&topy);
        m_mtx.transform(&bottomx,&bottomy);
        int x1=round_int(topx); 
        int y1=round_int(topy); 
        int x2=round_int(bottomx); 
        int y2=round_int(bottomy); 

        pren.solid_rectangle(x1, y1, x2, y2);
        pren.rectangle(x1, y1, x2, y2);
    }
}
Esempio n. 3
0
 void on_mouse_button_down(int x, int y, unsigned flags) 
 {
     if(flags & 1)
     {
         double xd = x;
         double yd = y;
         double r = 4.0 / m_scale.scale();
         m_scale.inverse_transform(&xd, &yd);
         m_point_idx = m_shape.hit_test(xd, yd, r);
         force_redraw();
     }
 }
Esempio n. 4
0
box2d<T>::box2d(const box2d_type &rhs, const agg::trans_affine& tr)
{
    double x0 = rhs.minx_, y0 = rhs.miny_;
    double x1 = rhs.maxx_, y1 = rhs.miny_;
    double x2 = rhs.maxx_, y2 = rhs.maxy_;
    double x3 = rhs.minx_, y3 = rhs.maxy_;
    tr.transform(&x0, &y0);
    tr.transform(&x1, &y1);
    tr.transform(&x2, &y2);
    tr.transform(&x3, &y3);
    init(x0, y0, x2, y2);
    expand_to_include(x1, y1);
    expand_to_include(x3, y3);
}
Esempio n. 5
0
void CAggMemoryDC::Line(
    const PointF& p1,
    const PointF& p2, 
    const Color& clr)
{
    if (m_buf==0)
        return;

    CPoint _p1 = p1;
    CPoint _p2 = p2;

    pixel_format pixf(m_rbuf);
    ren_base renb(pixf);

    outline_renderer outline_rd(renb, s_lineprof);
    outline_rasterizer_aa outline_rt(outline_rd);

    outline_rd.profile(s_lineprof);
    outline_rd.color(agg::rgba8(clr.GetR(), clr.GetG(), clr.GetB(), clr.GetA()));
    outline_rd.clip_box(0, 0, m_rcUpdate.Width(), m_rcUpdate.Height());

    double p1x(p1.x), p1y(p1.y), p2x(p2.x), p2y(p2.y);
    m_mtx.transform(&p1x,&p1y);
    m_mtx.transform(&p2x,&p2y);

    outline_rt.move_to_d(p1x, p1y);
    outline_rt.line_to_d(p2x, p2y);
    //outline_rt.round_cap( 1 );
    outline_rt.render(false);
}
Esempio n. 6
0
    bool only_translation(agg::trans_affine& mat, double epsilon)
    {
        double temp[6];
        mat.store_to(temp);
		return (f_eq(temp[0], 1.0) && f_eq(temp[1], 0.0) &&
				f_eq(temp[2], 0.0) && f_eq(temp[3], 1.0));
    }
Esempio n. 7
0
 void get_translation(agg::trans_affine& m, double* tx, double* ty)
 {
     double temp[6];
     m.store_to(temp);
     *tx = temp[4];
     *ty = temp[5];
 }
Esempio n. 8
0
void cairo_context::add_image(agg::trans_affine const& tr, image_rgba8 const& data, double opacity)
{
    cairo_pattern pattern(data);
    if (!tr.is_identity())
    {
        double m[6];
        tr.store_to(m);
        cairo_matrix_t cairo_matrix;
        cairo_matrix_init(&cairo_matrix,m[0],m[1],m[2],m[3],m[4],m[5]);
        cairo_matrix_invert(&cairo_matrix);
        pattern.set_matrix(cairo_matrix);
    }
    cairo_save(cairo_.get());
    cairo_set_source(cairo_.get(), const_cast<cairo_pattern_t*>(pattern.pattern()));
    cairo_paint_with_alpha(cairo_.get(), opacity);
    cairo_restore(cairo_.get());
    check_object_status_and_throw_exception(*this);
}
Esempio n. 9
0
 void get_scale(agg::trans_affine& m, double* dx, double* dy)
 {
     {
         double temp[6];
         m.store_to(temp);
         *dx = temp[0];
         *dy = temp[3];
     }
 }
Esempio n. 10
0
void
trans_affine_compose(agg::trans_affine& a, const agg::trans_affine& b)
{
    double a_tx = a.tx, a_ty = a.ty;

    a.premultiply(b);

    a.tx = b.sx  * a_tx + b.shx * a_ty + b.tx;
    a.ty = b.shy * a_tx + b.sy  * a_ty + b.ty;
}
Esempio n. 11
0
    bool is_identity(agg::trans_affine& mat, double epsilon)
    {
        double temp[6];
        mat.store_to(temp);
		return (f_eq(temp[0], 1.0) && f_eq(temp[1], 0.0) &&
				f_eq(temp[2], 0.0) && f_eq(temp[3], 1.0) &&
				f_eq(temp[4], 0.0) && f_eq(temp[5], 0.0));
//        return (temp[0] == 1.0 && temp[1] == 0.0 &&
//                temp[2] == 0.0 && temp[3] == 1.0 &&
//                temp[4] == 0.0 && temp[5] == 0.0);

    }
Esempio n. 12
0
 void render_raster_marker(agg::trans_affine const& marker_tr)
 {
     double width  = src_.width();
     double height = src_.height();
     double p[8];
     p[0] = 0;     p[1] = 0;
     p[2] = width; p[3] = 0;
     p[4] = width; p[5] = height;
     p[6] = 0;     p[7] = height;
     marker_tr.transform(&p[0], &p[1]);
     marker_tr.transform(&p[2], &p[3]);
     marker_tr.transform(&p[4], &p[5]);
     marker_tr.transform(&p[6], &p[7]);
     ras_.move_to_d(p[0],p[1]);
     ras_.line_to_d(p[2],p[3]);
     ras_.line_to_d(p[4],p[5]);
     ras_.line_to_d(p[6],p[7]);
     RendererType ren(renb_);
     ren.color(color_type(feature_.id()));
     agg::render_scanlines(ras_, sl_, ren);
 }
Esempio n. 13
0
 void render_raster_marker(agg::trans_affine const& marker_tr,
                           double opacity)
 {
     double width  = src_.width();
     double height = src_.height();
     double p[8];
     p[0] = 0;     p[1] = 0;
     p[2] = width; p[3] = 0;
     p[4] = width; p[5] = height;
     p[6] = 0;     p[7] = height;
     marker_tr.transform(&p[0], &p[1]);
     marker_tr.transform(&p[2], &p[3]);
     marker_tr.transform(&p[4], &p[5]);
     marker_tr.transform(&p[6], &p[7]);
     ras_.move_to_d(p[0],p[1]);
     ras_.line_to_d(p[2],p[3]);
     ras_.line_to_d(p[4],p[5]);
     ras_.line_to_d(p[6],p[7]);
     agg::span_allocator<color_type> sa;
     agg::image_filter_bilinear filter_kernel;
     agg::image_filter_lut filter(filter_kernel, false);
     agg::rendering_buffer marker_buf((unsigned char *)src_.getBytes(),
                                      src_.width(),
                                      src_.height(),
                                      src_.width()*4);
     agg::pixfmt_rgba32_pre pixf(marker_buf);
     typedef agg::image_accessor_clone<agg::pixfmt_rgba32_pre> img_accessor_type;
     typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type;
     typedef agg::span_image_filter_rgba_2x2<img_accessor_type,
                                             interpolator_type> span_gen_type;
     typedef agg::renderer_scanline_aa_alpha<renderer_base,
             agg::span_allocator<color_type>,
             span_gen_type> renderer_type;
     img_accessor_type ia(pixf);
     interpolator_type interpolator(agg::trans_affine(p, 0, 0, width, height) );
     span_gen_type sg(ia, interpolator, filter);
     renderer_type rp(renb_,sa, sg, unsigned(opacity*255));
     agg::render_scanlines(ras_, sl_, rp);
 }
Esempio n. 14
0
void pathAttr::apply(agg::path_storage* path, const agg::trans_affine& tr, double accuracy)
{
    double scale = sqrt(fabs(tr.determinant()));
    
    if (mCommand == stroke) {
        if (mIsoWidthFlag) {
            trans.attach(*path);
            trans.transformer(tr);
            transCurvedStroked.width(mStrokeWidth * scale);
            transCurvedStroked.line_join(mLineJoin);
            transCurvedStroked.line_cap(mLineCap);
            transCurvedStroked.miter_limit(mMiterLimit);
            transCurvedStroked.inner_join(agg::inner_round);
            transCurvedStroked.approximation_scale(accuracy);
            transCurved.approximation_scale(accuracy);
            
            // If the *visual* line width is considerable we 
            // turn on processing of curve cusps.
            //---------------------
            if (mStrokeWidth * scale > 1.0) {
                transCurved.angle_tolerance(0.2);
            } else {
                transCurved.angle_tolerance(0.0);
            }
        } else {
            curved.attach(*path);
            curvedStrokedTrans.transformer(tr);
            curvedStroked.width(mStrokeWidth);
            curvedStroked.line_join(mLineJoin);
            curvedStroked.line_cap(mLineCap);
            curvedStroked.miter_limit(mMiterLimit);
            curvedStroked.inner_join(agg::inner_round);
            curvedStroked.approximation_scale(accuracy * scale);
            curved.approximation_scale(accuracy * scale);
            
            // If the *visual* line width is considerable we 
            // turn on processing of curve cusps.
            //---------------------
            if (mStrokeWidth * scale > 1.0) {
                curved.angle_tolerance(0.2);
            } else {
                curved.angle_tolerance(0.0);
            }
        }
    } else {
        trans.attach(*path);
        trans.transformer(tr);
        transCurved.approximation_scale(accuracy);
    }
}
Esempio n. 15
0
 void on_mouse_move(int x, int y, unsigned flags) 
 {
     if((flags & 1) == 0)
     {
         on_mouse_button_up(x, y, flags);
     }
     else
     {
         if(m_point_idx >= 0)
         {
             double xd = x;
             double yd = y;
             m_scale.inverse_transform(&xd, &yd);
             m_shape.modify_vertex(m_point_idx, xd, yd);
             force_redraw();
         }
     }
 }
Esempio n. 16
0
//-----------------------------------------------------------------------------
int CAggMemoryDC::SetDIBitsToDevice(
    int x, 
    int y, 
    DWORD dwWidth, 
    DWORD dwHeight, 
    int xSrc, 
    int ySrc, 
    UINT uStartScan, 
    UINT cScanLines, 
    CONST VOID* lpvBits, 
    CONST BITMAPINFO* lpbmi, 
    UINT uColorUse)
{
    double dx = x;
    double dy = y;
    m_mtx.transform(&dx,&dy);
    return ::SetDIBitsToDevice(m_hDC, x, y, dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
}
Esempio n. 17
0
Bounds::Bounds(const agg::trans_affine& trans, 
               agg::path_storage* path, pathAttr* attr, double dilation,
               double scale)
{
    double centx = attr->mCentroid.x;
    double centy = attr->mCentroid.y;
    trans.transform(&centx, &centy);

    mValid = attr->boundingRect(path, trans, mMin_X, mMin_Y, mMax_X, mMax_Y, scale);
    
    if (mValid && mMin_X <= centx && mMax_X >= centx &&
                  mMin_Y <= centy && mMax_Y >= centy && dilation != 1.0)
    {
        mMin_X = dilation * (mMin_X - centx) + centx;
        mMax_X = dilation * (mMax_X - centx) + centx;
        mMin_Y = dilation * (mMin_Y - centy) + centy;
        mMax_Y = dilation * (mMax_Y - centy) + centy;
    }
}
Esempio n. 18
0
void SelectionScanlineSweeper::DrawImpl_rgb(agg::rect_d rect, RenderingData *data, unsigned int width, unsigned int height, int stride,
																				agg::trans_affine const &mtx, agg::trans_affine const &viewport_mtx) {
	//ScanlineSource source(data);

	typedef agg::pixfmt_alpha_blend_rgb<agg::blender_rgb<agg::rgba8,  agg::order_rgb>, agg::scanline_accessor> pixfmt_type;
	typedef pixfmt_type::color_type                        color_type;
	typedef color_type::value_type                         value_type;
	typedef agg::renderer_base<pixfmt_type>                renderer_base;
	typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;

	agg::rasterizer_scanline_aa<> l_rasterizer;
	agg::scanline_u8              l_scanline;

	//pixfmt_type       pixfmt(agg::scanline_accessor(&source, ScanlineSource::get_scanline, width, height, stride));
	pixfmt_type       pixfmt((agg::scanline_accessor(data)));
	renderer_base     rb(pixfmt);

	l_rasterizer.clip_box(0.0, 0.0, width, height);
	l_rasterizer.filling_rule(agg::fill_non_zero);
	
	if (flip_y) {
		mtx.transform(&rect.x1, &rect.y1);
		mtx.transform(&rect.x2, &rect.y2);
	}
	
	double vertexes[] = {
		rect.x1, rect.y2,
		rect.x1, rect.y1,
		rect.x2, rect.y1,
		rect.x2, rect.y2
	};
	
	agg::test_vertex_source vertex_source(vertexes, 4);
	agg::conv_transform<agg::test_vertex_source> vertex_source_converted(vertex_source, viewport_mtx);
	l_rasterizer.add_path(vertex_source_converted);
	
	renderer_solid r(rb);
	{
		r.color(color);
		agg::render_scanlines(l_rasterizer, l_scanline, r);
	}
}
Esempio n. 19
0
unsigned CAggMemoryDC::DrawScaledText(
        const TCHAR* text,
        const GraphTypes::RectF& rc,
        const GraphTypes::Color& clr,
        const char* font,
        int size,
        const PointF & descsubtract)
{
    if (m_buf==0)
        return 0;

    unsigned len=0;

    pixel_format pixf(m_rbuf);
    ren_base renb(pixf);
    solid_renderer ren_solid(renb);

    ATLASSERT(m_buf);
    conv_font_curve_type fcurves(m_fonts->m_fman.path_adaptor());
    conv_font_segm_type  fsegm(fcurves);
    conv_font_trans_type ftrans(fsegm, m_mtx);
 //   fsegm.approximation_scale(3.0);
 //   fcurves.approximation_scale(2.0);

    m_fonts->m_feng.flip_y(true);
    m_fonts->m_feng.hinting(true);

    if(m_fonts->m_feng.create_font(
        font, 
        agg::glyph_ren_outline,
        size,
        0.0,
        FW_NORMAL,
        false,
        ANSI_CHARSET,
        DEFAULT_PITCH | FF_SWISS
        ))
    {
        double x = 0.0;
        double y = 0.0;
        const TCHAR* p = text;

        TEXTMETRIC tm;
        GetTextMetrics(&tm);

        //double descent=(tm.tmDescent>descsubtract.y)?(tm.tmDescent-descsubtract.y):(tm.tmDescent-1);
        //ATLASSERT(tm.tmDescent>descsubtract.y);
        //ATLASSERT(descent>0);
        //descent *= m_mtx.scale(); 

        //m_mtx *= agg::trans_affine_translation(rc.x-m_rcUpdate.left, rc.y+rc.Height-descent-m_rcUpdate.top);

        double ascent=tm.tmAscent-descsubtract.y;
        ATLASSERT(ascent>0.0f);
        ascent *= m_mtx.scale(); 
        m_mtx *= agg::trans_affine_translation(rc.x-m_rcUpdate.left, rc.y+ascent-m_rcUpdate.top);

        ren_solid.color(agg::rgba8(clr.GetR(), clr.GetG(), clr.GetB(), clr.GetA()));

        while(*p)
        {
            const agg::glyph_cache* glyph = m_fonts->m_fman.glyph(*p);
            if(glyph)
            {
                m_fonts->m_fman.add_kerning(&x, &y);
                m_fonts->m_fman.init_embedded_adaptors(glyph, x, y);

                if(glyph->data_type == agg::glyph_data_outline)
                {
                    m_ras_aa.add_path(ftrans);
                }

                // increment pen position
                x += glyph->advance_x;
                y += glyph->advance_y;
            }
            ++p;
            ++len;
        }

        agg::render_scanlines(m_ras_aa, m_sl, ren_solid);
        ATLASSERT(m_buf);
    }

    return len;
}
Esempio n. 20
0
    void render_raster_marker(agg::trans_affine const& marker_tr,
                              double opacity)
    {
        using pixfmt_pre = agg::pixfmt_rgba32_pre;
        agg::scanline_u8 sl_;
        double width  = src_.width();
        double height = src_.height();
        if (std::fabs(1.0 - scale_factor_) < 0.001
            && (std::fabs(1.0 - marker_tr.sx) < agg::affine_epsilon)
            && (std::fabs(0.0 - marker_tr.shy) < agg::affine_epsilon)
            && (std::fabs(0.0 - marker_tr.shx) < agg::affine_epsilon)
            && (std::fabs(1.0 - marker_tr.sy) < agg::affine_epsilon))
        {
            agg::rendering_buffer src_buffer((unsigned char *)src_.getBytes(),src_.width(),src_.height(),src_.width() * 4);
            pixfmt_pre pixf_mask(src_buffer);
            if (snap_to_pixels_)
            {
                renb_.blend_from(pixf_mask,
                                 0,
                                 std::floor(marker_tr.tx + .5),
                                 std::floor(marker_tr.ty + .5),
                                 unsigned(255*opacity));
            }
            else
            {
                renb_.blend_from(pixf_mask,
                                 0,
                                 marker_tr.tx,
                                 marker_tr.ty,
                                 unsigned(255*opacity));
            }
        }
        else
        {
            using img_accessor_type = agg::image_accessor_clone<pixfmt_pre>;
            using interpolator_type = agg::span_interpolator_linear<>;
            //using span_gen_type = agg::span_image_filter_rgba_2x2<img_accessor_type,interpolator_type>;
            using span_gen_type = agg::span_image_resample_rgba_affine<img_accessor_type>;
            using renderer_type = agg::renderer_scanline_aa_alpha<renderer_base,
                                                                  agg::span_allocator<color_type>,
                                                                  span_gen_type>;

            double p[8];
            p[0] = 0;     p[1] = 0;
            p[2] = width; p[3] = 0;
            p[4] = width; p[5] = height;
            p[6] = 0;     p[7] = height;
            marker_tr.transform(&p[0], &p[1]);
            marker_tr.transform(&p[2], &p[3]);
            marker_tr.transform(&p[4], &p[5]);
            marker_tr.transform(&p[6], &p[7]);
            agg::span_allocator<color_type> sa;
            agg::image_filter_lut filter;
            filter.calculate(agg::image_filter_bilinear(), true);
            agg::rendering_buffer marker_buf((unsigned char *)src_.getBytes(),
                                             src_.width(),
                                             src_.height(),
                                             src_.width()*4);
            pixfmt_pre pixf(marker_buf);
            img_accessor_type ia(pixf);
            agg::trans_affine final_tr(p, 0, 0, width, height);
            if (snap_to_pixels_)
            {
                final_tr.tx = std::floor(final_tr.tx+.5);
                final_tr.ty = std::floor(final_tr.ty+.5);
            }
            interpolator_type interpolator(final_tr);
            span_gen_type sg(ia, interpolator, filter);
            renderer_type rp(renb_,sa, sg, unsigned(opacity*255));
            ras_.move_to_d(p[0],p[1]);
            ras_.line_to_d(p[2],p[3]);
            ras_.line_to_d(p[4],p[5]);
            ras_.line_to_d(p[6],p[7]);
            agg::render_scanlines(ras_, sl_, rp);
        }
    }
Esempio n. 21
0
bool CAggMemoryDC::DrawTransparent(
    HBITMAP hBitmap,
    int x, 
    int y,
    int width,
    int height,
    int bmpWidth,
    int bmpHeight,
    COLORREF color)
{
    ATLASSERT(width>0&&height>0);
    double dx = x;
    double dy = y;
    m_mtx.transform(&dx,&dy);

    CDC dcImage;
    bool bOk=dcImage.CreateCompatibleDC(m_hDC) != NULL;
    HBITMAP oldbmp=dcImage.SelectBitmap(hBitmap);

    // if OS supports non-leaky TransparentBlt use it (also on printer)
    if(s_bTransOk)
    {
#ifndef _WIN32_WCE
        bOk=TransparentBlt(x, y, width, height, dcImage, 0, 0, bmpWidth, bmpHeight, color) != 0;
        if (!bOk) // just in case (e.g. printing), try emulation
            goto tryEmulate;
#endif
    }
    else
    {
tryEmulate:
        CBitmap bmpMono;
        bOk=bmpMono.CreateBitmap(width, height, 1, 1, NULL) != NULL;
        if (!bOk)
            return bOk;

        CDC dcMono;
        // Create dc for the mask
        bOk = dcMono.CreateCompatibleDC(m_hDC) != NULL;
        if (!bOk)
            return bOk;

        // Select the mask bitmap into its dc
        HBITMAP oldBitmapMono = (HBITMAP)::SelectObject(dcMono, bmpMono);

        if(bOk)
        {
            // Build mask based on transparent colour

            COLORREF crOldImg=dcImage.SetBkColor(color);
            bOk=dcMono.StretchBlt(0, 0, width, height, dcImage, 0, 0, bmpWidth, bmpHeight, SRCCOPY) != 0;
            dcImage.SetBkColor(crOldImg);

            // True Mask method - no flicker if destination is not actual display
            if(bOk)
                bOk=StretchBlt(x, y, width, height, dcImage, 0, 0, bmpWidth, bmpHeight, SRCINVERT) != 0;

            if(bOk) 
            {
                // setup the destination for monochrome blit
                COLORREF crOldBack = SetBkColor(RGB(255,255,255));
                COLORREF crOldText = SetTextColor(RGB(0,0,0));

                bOk=BitBlt(x, y, width, height, dcMono, 0, 0, SRCAND) != 0;

                SetBkColor(crOldBack);
                SetTextColor(crOldText);
            }

            if(bOk)
                bOk=StretchBlt(x, y, width, height, dcImage, 0, 0, bmpWidth, bmpHeight, SRCINVERT) != 0;
        }

        dcMono.SelectBitmap(oldBitmapMono);
    }

    dcImage.SelectBitmap(oldbmp);

    return bOk;
}
Esempio n. 22
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<pixfmt_pre> renderer_base;
        typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
        typedef agg::scanline_u8 scanline;

        pixfmt_pre pixf(rbuf_window());
        renderer_base ren_base(pixf);
        ren_base.clear(agg::rgba(1.0, 1.0, 0.95));
        renderer_scanline ren(ren_base);

        agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> ras;
        agg::scanline_u8 sl;
        agg::conv_transform<agg::compound_shape> shape(m_shape, m_scale);
        agg::conv_stroke<agg::conv_transform<agg::compound_shape> > stroke(shape);

        m_shape.approximation_scale(m_scale.scale());

        unsigned i;
        agg::path_storage tmp_path;

        ras.clip_box(0, 0, width(), height());

        // This is an alternative method of Flash rasterization. 
        // We decompose the compound shape into separate paths
        // and select the ones that fit the given style (left or right).
        // So that, we form a sub-shape and draw it as a whole.
        // 
        // Here the regular scanline rasterizer is used, but it doesn't
        // automatically close the polygons. So that, the rasterizer 
        // actually works with a set of polylines instead of polygons.
        // Of course, the data integrity must be preserved, that is, 
        // the polylines must eventually form a closed contour
        // (or a set of closed contours). So that, first we set 
        // auto_close(false);
        // 
        // The second important thing is that one path can be rasterized 
        // twice, if it has both, left and right fill. Sometimes the 
        // path has equal left and right fill, so that, the same path
        // will be added twice even for a single sub-shape. If the 
        // rasterizer can tolerate these degenerates you can add them, 
        // but it's also fine just to omit them.
        //
        // The third thing is that for one side (left or right)
        // you should invert the direction of the paths.
        //
        // The main disadvantage of this method is imperfect stitching
        // of the adjacent polygons. The problem can be solved if we use
        // compositing operation "plus" instead of alpha-blend. But
        // in this case we are forced to use an RGBA buffer, clean it with 
        // zero, rasterize using "plus" operation, and then alpha-blend
        // the result over the final scene. It can be too expensive.
        //------------------------------------------------------------
        ras.auto_close(false);
        //ras.filling_rule(agg::fill_even_odd);
        start_timer();
        for(int s = m_shape.min_style(); s <= m_shape.max_style(); s++)
        {
            ras.reset();
            for(i = 0; i < m_shape.paths(); i++)
            {
                const agg::path_style& style = m_shape.style(i);
                if(style.left_fill != style.right_fill)
                {
                    if(style.left_fill == s)
                    {
                        ras.add_path(shape, style.path_id);
                    }
                    if(style.right_fill == s)
                    {
                        tmp_path.remove_all();
                        tmp_path.concat_path(shape, style.path_id);
                        tmp_path.invert_polygon(0);
                        ras.add_path(tmp_path);
                    }
                }
            }
            agg::render_scanlines_aa_solid(ras, sl, ren_base, m_colors[s]);
        }
        double tfill = elapsed_time();
        ras.auto_close(true);

        // Draw strokes
        //----------------------
        start_timer();
        stroke.width(sqrt(m_scale.scale()));
        stroke.line_join(agg::round_join);
        stroke.line_cap(agg::round_cap);
        for(i = 0; i < m_shape.paths(); i++)
        {
            ras.reset();
            if(m_shape.style(i).line >= 0)
            {
                ras.add_path(stroke, m_shape.style(i).path_id);
                ren.color(agg::srgba8(0,0,0, 128));
                agg::render_scanlines(ras, sl, ren);
            }
        }
        double tstroke = elapsed_time();


        char buf[256]; 
        agg::gsv_text t;
        t.size(8.0);
        t.flip(true);

        agg::conv_stroke<agg::gsv_text> ts(t);
        ts.width(1.6);
        ts.line_cap(agg::round_cap);

        sprintf(buf, "Fill=%.2fms (%dFPS) Stroke=%.2fms (%dFPS) Total=%.2fms (%dFPS)\n\n"
                     "Space: Next Shape\n\n"
                     "+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)",
                     tfill, int(1000.0 / tfill),
                     tstroke, int(1000.0 / tstroke),
                     tfill+tstroke, int(1000.0 / (tfill+tstroke)));

        t.start_point(10.0, 20.0);
        t.text(buf);

        ras.add_path(ts);
        ren.color(agg::rgba(0,0,0));
        agg::render_scanlines(ras, sl, ren);
    }
Esempio n. 23
0
void render_raster_marker(RendererType renb, RasterizerType & ras, image_rgba8 const& src,
                          agg::trans_affine const& tr, double opacity,
                          float scale_factor, bool snap_to_pixels)
{
    using color_type = agg::rgba8;
    using const_rendering_buffer = util::rendering_buffer<image_rgba8>;
    using pixfmt_pre = agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_pre, const_rendering_buffer, agg::pixel32_type>;

    agg::scanline_u8 sl;
    double width  = src.width();
    double height = src.height();
    if (std::fabs(1.0 - scale_factor) < 0.001
        && (std::fabs(1.0 - tr.sx) < agg::affine_epsilon)
        && (std::fabs(0.0 - tr.shy) < agg::affine_epsilon)
        && (std::fabs(0.0 - tr.shx) < agg::affine_epsilon)
        && (std::fabs(1.0 - tr.sy) < agg::affine_epsilon))
    {
        const_rendering_buffer src_buffer(src);
        pixfmt_pre pixf_mask(src_buffer);
        if (snap_to_pixels)
        {
            renb.blend_from(pixf_mask,
                            0,
                            static_cast<int>(std::floor(tr.tx + .5)),
                            static_cast<int>(std::floor(tr.ty + .5)),
                            unsigned(255*opacity));
        }
        else
        {
            renb.blend_from(pixf_mask,
                            0,
                            static_cast<int>(tr.tx),
                            static_cast<int>(tr.ty),
                            unsigned(255*opacity));
        }
    }
    else
    {
        using img_accessor_type = agg::image_accessor_clone<pixfmt_pre>;
        using interpolator_type = agg::span_interpolator_linear<>;
        //using span_gen_type = agg::span_image_filter_rgba_2x2<img_accessor_type,interpolator_type>;
        using span_gen_type = agg::span_image_resample_rgba_affine<img_accessor_type>;
        using renderer_type = agg::renderer_scanline_aa_alpha<RendererType,
                                                              agg::span_allocator<color_type>,
                                                              span_gen_type>;

        double p[8];
        p[0] = 0;     p[1] = 0;
        p[2] = width; p[3] = 0;
        p[4] = width; p[5] = height;
        p[6] = 0;     p[7] = height;
        tr.transform(&p[0], &p[1]);
        tr.transform(&p[2], &p[3]);
        tr.transform(&p[4], &p[5]);
        tr.transform(&p[6], &p[7]);
        agg::span_allocator<color_type> sa;
        agg::image_filter_lut filter;
        filter.calculate(agg::image_filter_bilinear(), true);
        const_rendering_buffer src_buffer(src);
        pixfmt_pre pixf(src_buffer);
        img_accessor_type ia(pixf);
        agg::trans_affine final_tr(p, 0, 0, width, height);
        if (snap_to_pixels)
        {
            final_tr.tx = std::floor(final_tr.tx+.5);
            final_tr.ty = std::floor(final_tr.ty+.5);
        }
        interpolator_type interpolator(final_tr);
        span_gen_type sg(ia, interpolator, filter);
        renderer_type rp(renb, sa, sg, unsigned(opacity*255));
        ras.move_to_d(p[0],p[1]);
        ras.line_to_d(p[2],p[3]);
        ras.line_to_d(p[4],p[5]);
        ras.line_to_d(p[6],p[7]);
        agg::render_scanlines(ras, sl, rp);
    }
}
Esempio n. 24
0
 void TransformReset() { m_mtx.reset(); }
Esempio n. 25
0
void agg_renderer<T0,T1>::render_marker(pixel_position const& pos,
                                    marker const& marker,
                                    agg::trans_affine const& tr,
                                    double opacity,
                                    composite_mode_e comp_op)
{
    using color_type = agg::rgba8;
    using order_type = agg::order_rgba;
    using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender
    using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
    using renderer_base = agg::renderer_base<pixfmt_comp_type>;
    using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>;
    using svg_attribute_type = agg::pod_bvector<mapnik::svg::path_attributes>;

    ras_ptr->reset();
    if (gamma_method_ != GAMMA_POWER || gamma_ != 1.0)
    {
        ras_ptr->gamma(agg::gamma_power());
        gamma_method_ = GAMMA_POWER;
        gamma_ = 1.0;
    }
    agg::scanline_u8 sl;
    agg::rendering_buffer buf(current_buffer_->raw_data(),
                              current_buffer_->width(),
                              current_buffer_->height(),
                              current_buffer_->width() * 4);
    pixfmt_comp_type pixf(buf);
    pixf.comp_op(static_cast<agg::comp_op_e>(comp_op));
    renderer_base renb(pixf);

    if (marker.is_vector())
    {
        box2d<double> const& bbox = (*marker.get_vector_data())->bounding_box();
        coord<double,2> c = bbox.center();
        // center the svg marker on '0,0'
        agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
        // apply symbol transformation to get to map space
        mtx *= tr;
        mtx *= agg::trans_affine_scaling(common_.scale_factor_);
        // render the marker at the center of the marker box
        mtx.translate(pos.x, pos.y);
        using namespace mapnik::svg;
        vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
        svg_path_adapter svg_path(stl_storage);
        svg_renderer_agg<svg_path_adapter,
            svg_attribute_type,
            renderer_type,
            pixfmt_comp_type> svg_renderer(svg_path,
                                                   (*marker.get_vector_data())->attributes());

        svg_renderer.render(*ras_ptr, sl, renb, mtx, opacity, bbox);
    }
    else
    {
        double width = (*marker.get_bitmap_data())->width();
        double height = (*marker.get_bitmap_data())->height();
        if (std::fabs(1.0 - common_.scale_factor_) < 0.001 && tr.is_identity())
        {
            double cx = 0.5 * width;
            double cy = 0.5 * height;
            composite(current_buffer_->data(), **marker.get_bitmap_data(),
                      comp_op, opacity,
                      boost::math::iround(pos.x - cx),
                      boost::math::iround(pos.y - cy),
                      false);
        }
        else
        {

            double p[8];
            double x0 = pos.x - 0.5 * width;
            double y0 = pos.y - 0.5 * height;
            p[0] = x0;         p[1] = y0;
            p[2] = x0 + width; p[3] = y0;
            p[4] = x0 + width; p[5] = y0 + height;
            p[6] = x0;         p[7] = y0 + height;

            agg::trans_affine marker_tr;

            marker_tr *= agg::trans_affine_translation(-pos.x,-pos.y);
            marker_tr *= tr;
            marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
            marker_tr *= agg::trans_affine_translation(pos.x,pos.y);

            marker_tr.transform(&p[0], &p[1]);
            marker_tr.transform(&p[2], &p[3]);
            marker_tr.transform(&p[4], &p[5]);
            marker_tr.transform(&p[6], &p[7]);

            ras_ptr->move_to_d(p[0],p[1]);
            ras_ptr->line_to_d(p[2],p[3]);
            ras_ptr->line_to_d(p[4],p[5]);
            ras_ptr->line_to_d(p[6],p[7]);


            agg::span_allocator<color_type> sa;
            agg::image_filter_bilinear filter_kernel;
            agg::image_filter_lut filter(filter_kernel, false);

            image_data_32 const& src = **marker.get_bitmap_data();
            agg::rendering_buffer marker_buf((unsigned char *)src.getBytes(),
                                             src.width(),
                                             src.height(),
                                             src.width()*4);
            agg::pixfmt_rgba32_pre marker_pixf(marker_buf);
            using img_accessor_type = agg::image_accessor_clone<agg::pixfmt_rgba32_pre>;
            using interpolator_type = agg::span_interpolator_linear<agg::trans_affine>;
            using span_gen_type = agg::span_image_filter_rgba_2x2<img_accessor_type,
                                                                  interpolator_type>;
            using renderer_type = agg::renderer_scanline_aa_alpha<renderer_base,
                                                                  agg::span_allocator<agg::rgba8>,
                                                                  span_gen_type>;
            img_accessor_type ia(marker_pixf);
            interpolator_type interpolator(agg::trans_affine(p, 0, 0, width, height) );
            span_gen_type sg(ia, interpolator, filter);
            renderer_type rp(renb,sa, sg, unsigned(opacity*255));
            agg::render_scanlines(*ras_ptr, sl, rp);
        }
    }
}
Esempio n. 26
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<pixfmt> renderer_base;
        typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_scanline;
        typedef agg::scanline_u8 scanline;

        pixfmt pixf(rbuf_window());
        renderer_base ren_base(pixf);
        ren_base.clear(agg::rgba(1.0, 1.0, 0.95));
        renderer_scanline ren(ren_base);

        unsigned i;
        unsigned w = unsigned(width());
        m_gradient.resize(w);
        agg::rgba8 c1(255, 0, 0, 180);
        agg::rgba8 c2(0, 0, 255, 180);
        for(i = 0; i < w; i++)
        {
            m_gradient[i] = c1.gradient(c2, i / width());
            m_gradient[i].premultiply();
        }

        agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> ras;
        agg::rasterizer_compound_aa<agg::rasterizer_sl_clip_dbl> rasc;
        agg::scanline_u8 sl;
        agg::scanline_bin sl_bin;
        agg::conv_transform<agg::compound_shape> shape(m_shape, m_scale);
        agg::conv_stroke<agg::conv_transform<agg::compound_shape> > stroke(shape);

        agg::test_styles style_handler(m_colors, m_gradient.data());
        agg::span_allocator<agg::rgba8> alloc;

        m_shape.approximation_scale(m_scale.scale());

        // Fill shape
        //----------------------
        rasc.clip_box(0, 0, width(), height());
        rasc.reset();
        //rasc.filling_rule(agg::fill_even_odd);
        start_timer();
        for(i = 0; i < m_shape.paths(); i++)
        {
            
            if(m_shape.style(i).left_fill >= 0 || 
               m_shape.style(i).right_fill >= 0)
            {
                rasc.styles(m_shape.style(i).left_fill, 
                            m_shape.style(i).right_fill);
                rasc.add_path(shape, m_shape.style(i).path_id);
            }
        }
        agg::render_scanlines_compound(rasc, sl, sl_bin, ren_base, alloc, style_handler);
        double tfill = elapsed_time();

        // Hit-test test
        bool draw_strokes = true;
        if(m_hit_x >= 0 && m_hit_y >= 0)
        {
            if(rasc.hit_test(m_hit_x, m_hit_y))
            {
                draw_strokes = false;
            }
        }

        // Draw strokes
        //----------------------
        start_timer();
        if(draw_strokes)
        {
            ras.clip_box(0, 0, width(), height());
            stroke.width(sqrt(m_scale.scale()));
            stroke.line_join(agg::round_join);
            stroke.line_cap(agg::round_cap);
            for(i = 0; i < m_shape.paths(); i++)
            {
                ras.reset();
                if(m_shape.style(i).line >= 0)
                {
                    ras.add_path(stroke, m_shape.style(i).path_id);
                    ren.color(agg::rgba8(0,0,0, 128));
                    agg::render_scanlines(ras, sl, ren);
                }
            }
        }
        double tstroke = elapsed_time();


        char buf[256]; 
        agg::gsv_text t;
        t.size(8.0);
        t.flip(true);

        agg::conv_stroke<agg::gsv_text> ts(t);
        ts.width(1.6);
        ts.line_cap(agg::round_cap);

        sprintf(buf, "Fill=%.2fms (%dFPS) Stroke=%.2fms (%dFPS) Total=%.2fms (%dFPS)\n\n"
                     "Space: Next Shape\n\n"
                     "+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)",
                     tfill, int(1000.0 / tfill),
                     tstroke, int(1000.0 / tstroke),
                     tfill+tstroke, int(1000.0 / (tfill+tstroke)));

        t.start_point(10.0, 20.0);
        t.text(buf);

        ras.add_path(ts);
        ren.color(agg::rgba(0,0,0));
        agg::render_scanlines(ras, sl, ren);

        if(m_gamma.gamma() != 1.0)
        {
            pixf.apply_gamma_inv(m_gamma);
        }
    }
Esempio n. 27
0
void grid_renderer<T>::render_marker(mapnik::feature_impl & feature, unsigned int step, pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity, composite_mode_e comp_op)
{
    if (marker.is_vector())
    {
        typedef coord_transform<CoordTransform,geometry_type> path_type;
        typedef agg::renderer_base<mapnik::pixfmt_gray32> ren_base;
        typedef agg::renderer_scanline_bin_solid<ren_base> renderer;
        agg::scanline_bin sl;

        grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
        mapnik::pixfmt_gray32 pixf(buf);

        ren_base renb(pixf);
        renderer ren(renb);

        ras_ptr->reset();

        box2d<double> const& bbox = (*marker.get_vector_data())->bounding_box();
        coord<double,2> c = bbox.center();
        // center the svg marker on '0,0'
        agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
        // apply symbol transformation to get to map space
        mtx *= tr;
        mtx *= agg::trans_affine_scaling(scale_factor_*(1.0/step));
        // render the marker at the center of the marker box
        mtx.translate(pos.x, pos.y);
        using namespace mapnik::svg;
        vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
        svg_path_adapter svg_path(stl_storage);
        svg_renderer_agg<svg_path_adapter,
            agg::pod_bvector<path_attributes>,
            renderer,
            mapnik::pixfmt_gray32> svg_renderer(svg_path,
                                                (*marker.get_vector_data())->attributes());

        svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), mtx, opacity, bbox);

    }
    else
    {
        image_data_32 const& data = **marker.get_bitmap_data();
        double width = data.width();
        double height = data.height();
        double cx = 0.5 * width;
        double cy = 0.5 * height;
        if (step == 1 && (std::fabs(1.0 - scale_factor_) < 0.001 && tr.is_identity()))
        {
            // TODO - support opacity
            pixmap_.set_rectangle(feature.id(), data,
                                  boost::math::iround(pos.x - cx),
                                  boost::math::iround(pos.y - cy));
        }
        else
        {
            // TODO - remove support for step != or add support for agg scaling with opacity
            double ratio = (1.0/step);
            image_data_32 target(ratio * data.width(), ratio * data.height());
            mapnik::scale_image_agg<image_data_32>(target,data, SCALING_NEAR,
                                                   scale_factor_, 0.0, 0.0, 1.0, ratio);
            pixmap_.set_rectangle(feature.id(), target,
                                  boost::math::iround(pos.x - cx),
                                  boost::math::iround(pos.y - cy));
        }
    }
    pixmap_.add_feature(feature);
}
Esempio n. 28
0
    virtual void on_draw()
    {
        pixfmt pf(rbuf_window());
        renderer_base ren_base(pf);
        ren_base.clear(agg::rgba(0.5, 0.75, 0.85));
        renderer_scanline ren(ren_base);

        rasterizer_scanline ras;
        scanline sl;

        ras.clip_box(0, 0, width(), height());

        // Pattern source. Must have an interface:
        // width() const
        // height() const
        // pixel(int x, int y) const
        // Any agg::renderer_base<> or derived
        // is good for the use as a source.
        //-----------------------------------
        pattern_src_brightness_to_alpha_rgba8 p1(rbuf_img(0));

        agg::pattern_filter_bilinear_rgba8 fltr;           // Filtering functor

        // agg::line_image_pattern is the main container for the patterns. It creates
        // a copy of the patterns extended according to the needs of the filter.
        // agg::line_image_pattern can operate with arbitrary image width, but if the 
        // width of the pattern is power of 2, it's better to use the modified
        // version agg::line_image_pattern_pow2 because it works about 15-25 percent
        // faster than agg::line_image_pattern (because of using simple masking instead 
        // of expensive '%' operation). 
        typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
        typedef agg::renderer_base<pixfmt> base_ren_type;
        typedef agg::renderer_outline_image<base_ren_type, pattern_type> renderer_img_type;
        typedef agg::rasterizer_outline_aa<renderer_img_type, agg::line_coord_sat> rasterizer_img_type;

        typedef agg::renderer_outline_aa<base_ren_type> renderer_line_type;
        typedef agg::rasterizer_outline_aa<renderer_line_type, agg::line_coord_sat> rasterizer_line_type;


        //-- Create with specifying the source
        //pattern_type patt(fltr, src);   

        //-- Create uninitialized and set the source
        pattern_type patt(fltr);        
        patt.create(p1);
        renderer_img_type ren_img(ren_base, patt);
        rasterizer_img_type ras_img(ren_img);


        //-- create uninitialized and set parameters
        agg::line_profile_aa profile;
        profile.smoother_width(10.0);                    //optional
        profile.width(8.0);                              //mandatory!
        renderer_line_type ren_line(ren_base, profile);
        ren_line.color(agg::rgba8(0,0,127));            //mandatory!
        rasterizer_line_type ras_line(ren_line);
        ras_line.round_cap(true);                       //optional
        //ras_line.line_join(agg::outline_no_join);     //optional

        // Calculate the dilation value so that, the line caps were
        // drawn correctly.
        //---------------
        double w2 = 9.0;//p1.height() / 2 + 2;


        // Set the clip box a bit bigger than you expect. You need it
        // to draw the clipped line caps correctly. The correct result
        // is achieved with raster clipping.
        //------------------------
        ren_img.scale_x(m_scale_x.value());
        ren_img.start_x(m_start_x.value());
        ren_img.clip_box (50-w2, 50-w2, width()-50+w2, height()-50+w2);
        ren_line.clip_box(50-w2, 50-w2, width()-50+w2, height()-50+w2);

        // First, draw polyline without raster clipping just to show the idea
        //------------------------
        draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points());
        draw_polyline(ras_img,  ren_img,  m_line1.polygon(), m_line1.num_points());

        // Clear the area, almost opaque, but not completely
        //------------------------
        ren_base.blend_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1), 200);


        // Set the raster clip box and then, draw again. 
        // In reality there shouldn't be two calls above. 
        // It's done only for demonstration
        //------------------------
        ren_base.clip_box((int)50, (int)50, (int)width()-50, (int)height()-50);

        // This "copy_bar" is also for demonstration only
        //------------------------
        ren_base.copy_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1));

        // Finally draw polyline correctly clipped: We use double clipping, 
        // first is vector clipping, with extended clip box, second is raster 
        // clipping with normal clip box.
        //------------------------
        ren_img.scale_x(m_scale_x.value());
        ren_img.start_x(m_start_x.value());
        draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points());
        draw_polyline(ras_img, ren_img,   m_line1.polygon(), m_line1.num_points());


        // Reset clipping and draw the controls and stuff
        ren_base.reset_clipping(true);

        m_line1.line_width(1/m_scale.scale());
        m_line1.point_radius(5/m_scale.scale());

        agg::render_ctrl(ras, sl, ren_base, m_line1);
        agg::render_ctrl(ras, sl, ren_base, m_scale_x);
        agg::render_ctrl(ras, sl, ren_base, m_start_x);


        char buf[256]; 
        agg::gsv_text t;
        t.size(10.0);

        agg::conv_stroke<agg::gsv_text> pt(t);
        pt.width(1.5);
        pt.line_cap(agg::round_cap);

        const double* p = m_line1.polygon();
        sprintf(buf, "Len=%.2f", agg::calc_distance(p[0], p[1], p[2], p[3]) * m_scale.scale());

        t.start_point(10.0, 30.0);
        t.text(buf);

        ras.add_path(pt);
        ren.color(agg::rgba(0,0,0));
        agg::render_scanlines(ras, sl, ren);

    }