FLTK logo

Article #898: Using the Anti-Grain Light 2D rendering engine with FLTK

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 Home  |  Articles & FAQs  |  Bugs & Features  |  Documentation  |  Download  |  Screenshots  ]
 

Return to Articles | Show Comments | Submit Comment ]

Article #898: Using the Anti-Grain Light 2D rendering engine with FLTK

Created at 08:40 Apr 06, 2009 by MCO

Last modified at 10:43 Apr 06, 2009

Anti-Grain a high quality rendering engine for C++, it was written by Maxim Shemanarev and is available here : http://www.antigrain.com/

The author also produced a lighter version of that library, called 'The Lighweight Rasterizer', available here : http://www.antigrain.com/lite/agg2_lite.zip

The tiny object code produced by that library seems to fit the FLTK philosophy perfectly. Of course, it is also lighter in terms of features, eg there is no font drawing code.

The main idea is to use AGG Lite primitives to draw in a buffer that's blitted with fl_draw_image in an FLTK surface.

Here is some 'proof of concept' code :

AGG_Lite_Window.h

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_draw.H>

#include "agg.h"
#include <math.h>
#include

#ifndef AGG_LITE_WINDOW_DEF
#define AGG_LITE_WINDOW_DEF

typedef unsigned char uchar8;

class AGG_Lite_Window : public Fl_Double_Window {

 public:

  AGG_Lite_Window(int x, int y, int w, int h, char *s);    
     ~AGG_Lite_Window() { delete [] buf; delete rbuf; delete ren; };

 private:

  uchar8 *buf;
  agg::rendering_buffer *rbuf;
     agg::rasterizer ras;
  agg::renderer *ren;

  void draw(void);
  int handle(int event);

  void move_to(double x, double y);
  void line_to(double x, double y);
  void draw_ellipse(double x,  double y, double rx, double ry);  
  void draw_line(double x1, double y1, double x2, double y2, double width);
  void clear_buffer(void);
  void blit_buffer(void);
  void render(uchar8 r,uchar8 g,uchar8 b,uchar8 a);
};

#endif

AGG_Lite_Window.cpp

#include "AGG_Lite_Window.h"

AGG_Lite_Window::AGG_Lite_Window(int x, int y, int w, int h, char *s)
     : Fl_Double_Window(x,y,w,h,s) {

    buf = new uchar8[w * h * 3];
    rbuf = new agg::rendering_buffer(buf, w, h, w * 3);
    ren = new agg::renderer(*rbuf);
    ras.gamma(1.3);
    ras.filling_rule(agg::fill_non_zero);
}

void AGG_Lite_Window::move_to(double x,  double y) {
    ras.move_to_d(x, y);
}

void AGG_Lite_Window::line_to(double x,  double y) {
    ras.line_to_d(x, y);
}

void AGG_Lite_Window::draw_ellipse(double x,  double y, double rx, double ry) {

    ras.move_to_d(x + rx, y);

    for(int i = 1; i < 360; i++) {
        double a = double(i) * 3.1415926 / 180.0;
        ras.line_to_d(x + cos(a) * rx, y + sin(a) * ry);
    }
}

void AGG_Lite_Window::draw_line(double x1, double y1, double x2, double y2, double width) {

    double dx = x2 - x1;
    double dy = y2 - y1;
    double d = sqrt(dx*dx + dy*dy);
    
    dx = width * (y2 - y1) / d;
    dy = width * (x2 - x1) / d;

    ras.move_to_d(x1 - dx,  y1 + dy);
    ras.line_to_d(x2 - dx,  y2 + dy);
    ras.line_to_d(x2 + dx,  y2 - dy);
    ras.line_to_d(x1 + dx,  y1 - dy);
}

void AGG_Lite_Window::clear_buffer(void) {
    ren->clear(agg::rgba8(210, 210, 210));
    ras.reset();
}

void AGG_Lite_Window::blit_buffer(void) {
 fl_draw_image(buf, 0, 0, w(), h()) ;
}

void AGG_Lite_Window::render(uchar8 r, uchar8 g, uchar8 b, uchar8 a ) {
    ras.render(*ren, agg::rgba8(r, g, b, a));
}

and a simple test program :

#include <FL/Fl.H>
#include "AGG_Lite_Window.h"
#include "stdlib.h"

enum { width  = 1000, height = 700 };

void AGG_Lite_Window::draw(void) {

 int x = Fl::event_x();
 int y = Fl::event_y();

 // Draw with AGG Lite
 
 clear_buffer();

    draw_ellipse(x, y, 10, 10);
    render(0xAF, 0xAF, 0xAF, 20);

    draw_line(x, y, 50, 50, 1.0);
    render(0, 0, 0, 120);

    draw_ellipse( x, y, 100, 50);
    render(0xFF, 0xCF, 0x5F,230);

    draw_ellipse( 50, 250, 100, 50);
    render(0x0F, 0xFF, 0x5F,30);

    move_to(10,10);
    line_to(60,10);
    line_to(50,50);
    line_to(10,60);

    render(0xFF, 0, 0, 180);

    blit_buffer();

    // Draw with FLTK functions on top

 fl_font(FL_HELVETICA, 24);
 fl_color(FL_RED);
    fl_draw("Click and drag the mouse...",450,450);

 fl_color(FL_BLACK);
 fl_line_style(FL_SOLID, 1);
    fl_line(100,100,600,200);

 fl_font(FL_HELVETICA, 12);
    fl_draw("< Line drawn with FLTK",600,200);

}

int AGG_Lite_Window::handle(int e) {

    if ( Fl_Double_Window::handle(e) )
       return(1);

 int x = Fl::event_x();
 int y = Fl::event_y();

 switch (e) {
  
  case FL_PUSH:
   redraw();
   return 1; 
   
  case FL_DRAG:
   redraw();
   return 1; 
 }
 return 0;
}

int main(int argc, char ** argv)
{
 AGG_Lite_Window *window;

 window = new AGG_Lite_Window( 10, 10, width, height, "FLTK + AGG Lite - Test program");

 window->end();
 Fl::visual(FL_DOUBLE|FL_INDEX);
 window->show(argc, argv);

 return(Fl::run());
}

This blog post : http://dtedm.blogspot.com/2009/03/fltk-agg-lite.html provides a screenshot and a small windows executable that shows both anti-aliased drawing and transparency.

Manuel Cornes

Download | Home Page | Listing ]


Comments

Submit Comment ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.