Dear Fltk programers:

  I find a lot fl_graphics_driver in "fl_draw.H" but not in "fl_draw.cxx"
my current link version of fltk used to compile my chapter.12.3 program(of book 
of Mr. Bjarne Stroustrup-"Programming-Principle and practice using c++" 4th 
Ed.) is 1.3.x
(is that right one?)
I am in Ubuntu10.04,gcc/g++4.4.3

  Is I missing any header files on my(or Mr. Stroustrup's) Graph.h or Graph.cpp?
---------------------------------------------------------
r...@eric-laptop:/home/eric/BStrou/usingC++4/code/Chapter12# make
g++ -o Graph  Graph.o -lstdc++ -lbookgui -lfltk -lfltk_images -lX11 -ljpeg
/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
Graph.o: In function `Graph_lib::Shape::draw() const':
Graph.cpp:(.text+0xac): undefined reference to `fl_graphics_driver'
Graph.cpp:(.text+0xc6): undefined reference to `fl_graphics_driver'
Graph.cpp:(.text+0xf1): undefined reference to `fl_graphics_driver'
Graph.cpp:(.text+0x102): undefined reference to `fl_graphics_driver'
Graph.o: In function `Graph_lib::Text::draw_lines() const':
Graph.cpp:(.text+0xd97): undefined reference to `fl_graphics_driver'
Graph.o:Graph.cpp:(.text+0xe0e): more undefined references to 
`fl_graphics_driver' follow
Graph.o:(.rodata._ZTVN9Graph_lib9Bad_imageE[vtable for 
Graph_lib::Bad_image]+0x14): undefined reference to 
`Fl_Image::color_average(unsigned int, float)'
collect2: ld returned 1 exit status
make: *** [Graph] Error 1
---------------------------------------
------------Graph.h--------------------
//
// This is a GUI support code to the chapters 12-16 of the book
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//

#ifndef GRAPH_GUARD
#define GRAPH_GUARD 1

#include <FL/fl_draw.H>
#include <FL/Fl_Image.H>
#include "Point.h"
#include "std_lib_facilities.h"

namespace Graph_lib {

// defense against ill-behaved Linux macros:
#undef major
#undef minor

//------------------------------------------------------------------------------

// Color is the type we use to represent color. We can use Color like this:
//    grid.set_color(Color::red);
struct Color {
    enum Color_type {
        red=FL_RED,
        blue=FL_BLUE,
        green=FL_GREEN,
        yellow=FL_YELLOW,
        white=FL_WHITE,
        black=FL_BLACK,
        magenta=FL_MAGENTA,
        cyan=FL_CYAN,
        dark_red=FL_DARK_RED,
        dark_green=FL_DARK_GREEN,
        dark_yellow=FL_DARK_YELLOW,
        dark_blue=FL_DARK_BLUE,
        dark_magenta=FL_DARK_MAGENTA,
        dark_cyan=FL_DARK_CYAN
    };

    enum Transparency { invisible = 0, visible=255 };

    Color(Color_type cc) :c(Fl_Color(cc)), v(visible) { }
    Color(Color_type cc, Transparency vv) :c(Fl_Color(cc)), v(vv) { }
    Color(int cc) :c(Fl_Color(cc)), v(visible) { }
    Color(Transparency vv) :c(Fl_Color()), v(vv) { }    // default color

    int as_int() const { return c; }

    char visibility() const { return v; }
    void set_visibility(Transparency vv) { v=vv; }
private:
    char v;    // invisible and visible for now
    Fl_Color c;
};

//------------------------------------------------------------------------------

struct Line_style {
    enum Line_style_type {
        solid=FL_SOLID,            // -------
        dash=FL_DASH,              // - - - -
        dot=FL_DOT,                // .......
        dashdot=FL_DASHDOT,        // - . - .
        dashdotdot=FL_DASHDOTDOT,  // -..-..
    };

    Line_style(Line_style_type ss) :s(ss), w(0) { }
    Line_style(Line_style_type lst, int ww) :s(lst), w(ww) { }
    Line_style(int ss) :s(ss), w(0) { }

    int width() const { return w; }
    int style() const { return s; }
private:
    int s;
    int w;
};

//------------------------------------------------------------------------------

class Font {
public:
    enum Font_type {
        helvetica=FL_HELVETICA,
        helvetica_bold=FL_HELVETICA_BOLD,
        helvetica_italic=FL_HELVETICA_ITALIC,
        helvetica_bold_italic=FL_HELVETICA_BOLD_ITALIC,
        courier=FL_COURIER,
        courier_bold=FL_COURIER_BOLD,
        courier_italic=FL_COURIER_ITALIC,
        courier_bold_italic=FL_COURIER_BOLD_ITALIC,
        times=FL_TIMES,
        times_bold=FL_TIMES_BOLD,
        times_italic=FL_TIMES_ITALIC,
        times_bold_italic=FL_TIMES_BOLD_ITALIC,
        symbol=FL_SYMBOL,
        screen=FL_SCREEN,
        screen_bold=FL_SCREEN_BOLD,
        zapf_dingbats=FL_ZAPF_DINGBATS
    };

    Font(Font_type ff) :f(ff) { }
    Font(int ff) :f(ff) { }

    int as_int() const { return f; }
private:
    int f;
};

//------------------------------------------------------------------------------

template<class T> class Vector_ref {
    vector<T*> v;
    vector<T*> owned;
public:
    Vector_ref() {}
    Vector_ref(T& a) { push_back(a); }
    Vector_ref(T& a, T& b);
    Vector_ref(T& a, T& b, T& c);
    Vector_ref(T* a, T* b = 0, T* c = 0, T* d = 0)
    {
        if (a) push_back(a);
        if (b) push_back(b);
        if (c) push_back(c);
        if (d) push_back(d);
    }

    ~Vector_ref() { for (int i=0; i<owned.size(); ++i) delete owned[i]; }

    void push_back(T& s) { v.push_back(&s); }
    void push_back(T* p) { v.push_back(p); owned.push_back(p); }

    T& operator[](int i) { return *v[i]; }
    const T& operator[](int i) const { return *v[i]; }

    int size() const { return v.size(); }
};

//------------------------------------------------------------------------------

typedef double Fct(double);

class Shape  {        // deals with color and style, and holds sequence of lines
public:
    void draw() const;                 // deal with color and draw lines
    virtual void move(int dx, int dy); // move the shape +=dx and +=dy

    void set_color(Color col) { lcolor = col; }
    Color color() const { return lcolor; }
    void set_style(Line_style sty) { ls = sty; }
    Line_style style() const { return ls; }
    void set_fill_color(Color col) { fcolor = col; }
    Color fill_color() const { return fcolor; }

    Point point(int i) const { return points[i]; } // read only access to points
    int number_of_points() const { return int(points.size()); }

    virtual ~Shape() { }
protected:
    Shape();
    virtual void draw_lines() const;   // draw the appropriate lines
    void add(Point p);                 // add p to points
    void set_point(int i,Point p);     // points[i]=p;
private:
    vector<Point> points;              // not used by all shapes
    Color lcolor;                      // color for lines and characters
    Line_style ls;
    Color fcolor;                      // fill color

    Shape(const Shape&);               // prevent copying
    Shape& operator=(const Shape&);
};

//------------------------------------------------------------------------------

struct Function : Shape {
    // the function parameters are not stored
    Function(Fct f, double r1, double r2, Point orig,
        int count = 100, double xscale = 25, double yscale = 25);
};

//------------------------------------------------------------------------------

struct Line : Shape {            // a Line is a Shape defined by two Points
    Line(Point p1, Point p2);    // construct a line from two points
};

//------------------------------------------------------------------------------

struct Rectangle : Shape {

    Rectangle(Point xy, int ww, int hh) : w(ww), h(hh)
    {
        add(xy);
        if (h<=0 || w<=0) error("Bad rectangle: non-positive side");
    }

    Rectangle(Point x, Point y) : w(y.x-x.x), h(y.y-x.y)
    {
        add(x);
        if (h<=0 || w<=0) error("Bad rectangle: non-positive width or height");
    }
    void draw_lines() const;

    int height() const { return h; }
    int width() const { return w; }
private:
    int h;    // height
    int w;    // width
};

//------------------------------------------------------------------------------

struct Open_polyline : Shape {         // open sequence of lines
    void add(Point p) { Shape::add(p); }
    void draw_lines() const;
};

//------------------------------------------------------------------------------

struct Closed_polyline : Open_polyline { // closed sequence of lines
    void draw_lines() const;
};

//------------------------------------------------------------------------------

struct Polygon : Closed_polyline {    // closed sequence of non-intersecting 
lines
    void add(Point p);
    void draw_lines() const;
};

//------------------------------------------------------------------------------

struct Lines : Shape {                 // related lines
    void draw_lines() const;
    void add(Point p1, Point p2);      // add a line defined by two points
};

//------------------------------------------------------------------------------

struct Text : Shape {
    // the point is the bottom left of the first letter
    Text(Point x, const string& s) : lab(s), fnt(fl_font()), fnt_sz(fl_size()) 
{ add(x); }

    void draw_lines() const;

    void set_label(const string& s) { lab = s; }
    string label() const { return lab; }

    void set_font(Font f) { fnt = f; }
    Font font() const { return Font(fnt); }

    void set_font_size(int s) { fnt_sz = s; }
    int font_size() const { return fnt_sz; }
private:
    string lab;    // label
    Font fnt;
    int fnt_sz;
};

//------------------------------------------------------------------------------

struct Axis : Shape {
    enum Orientation { x, y, z };
    Axis(Orientation d, Point xy, int length,
        int number_of_notches=0, string label = "");

    void draw_lines() const;
    void move(int dx, int dy);
    void set_color(Color c);

    Text label;
    Lines notches;
};

//------------------------------------------------------------------------------

struct Circle : Shape {
    Circle(Point p, int rr);    // center and radius

    void draw_lines() const;

    Point center() const ;
    int radius() const { return r; }
    void set_radius(int rr) { r=rr; }
private:
    int r;
};

//------------------------------------------------------------------------------

struct Ellipse : Shape {
    Ellipse(Point p, int w, int h)    // center, min, and max distance from 
center
        : w(w), h(h)
    {
        add(Point(p.x-w,p.y-h));
    }

    void draw_lines() const;

    Point center() const { return Point(point(0).x+w,point(0).y+h); }
    Point focus1() const { return 
Point(center().x+int(sqrt(double(w*w-h*h))),center().y); }
    Point focus2() const { return 
Point(center().x-int(sqrt(double(w*w-h*h))),center().y); }

    void set_major(int ww) { w=ww; }
    int major() const { return w; }
    void set_minor(int hh) { h=hh; }
    int minor() const { return h; }
private:
    int w;
    int h;
};

//------------------------------------------------------------------------------

struct Marked_polyline : Open_polyline {
    Marked_polyline(const string& m) :mark(m) { }
    void draw_lines() const;
private:
    string mark;
};

//------------------------------------------------------------------------------

struct Marks : Marked_polyline {
    Marks(const string& m) :Marked_polyline(m)
    {
        set_color(Color(Color::invisible));
    }
};

//------------------------------------------------------------------------------

struct Mark : Marks {
    Mark(Point xy, char c) : Marks(string(1,c))
    {
        add(xy);
    }
};

//------------------------------------------------------------------------------

struct Suffix {
    enum Encoding { none, jpg, gif  };
};

Suffix::Encoding get_encoding(const string& s);

//------------------------------------------------------------------------------

struct Image : Shape {
    Image(Point xy, string file_name, Suffix::Encoding e = Suffix::none);
    ~Image() { delete p; }
    void draw_lines() const;
    void set_mask(Point xy, int ww, int hh) { w=ww; h=hh; cx=xy.x; cy=xy.y; }
private:
    int w,h;  // define "masking box" within image relative to position (cx,cy)
    int cx,cy;
    Fl_Image* p;
    Text fn;
};

//------------------------------------------------------------------------------

struct Bad_image : Fl_Image {
    Bad_image(int h, int w) : Fl_Image(h,w,0) { }
    void draw(int x,int y, int, int, int, int) { draw_empty(x,y); }
};

//------------------------------------------------------------------------------

} // of namespace Graph_lib

#endif
-------------------------------------------------------------
---------------this is Graph.cpp--------------------------



//

// This is a GUI support code to the chapters 12-16 of the book

// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup

//



#include <FL/Fl_GIF_Image.H>

#include <FL/Fl_JPEG_Image.H>

#include "Graph.h"

#include <cstdlib>

#include <cstring>



//------------------------------------------------------------------------------



namespace Graph_lib {



//------------------------------------------------------------------------------



Shape::Shape() :

    lcolor(fl_color()),      // default color for lines and characters

    ls(0),                   // default style

    fcolor(Color::invisible) // no fill

{}



//------------------------------------------------------------------------------



void Shape::add(Point p)     // protected

{

    points.push_back(p);

}



//------------------------------------------------------------------------------



void Shape::set_point(int i,Point p)        // not used; not necessary so far

{

    points[i] = p;

}



//------------------------------------------------------------------------------



void Shape::draw_lines() const

{

    if (color().visibility() && 1<points.size())    // draw sole pixel?

        for (unsigned int i=1; i<points.size(); ++i)

            fl_line(points[i-1].x,points[i-1].y,points[i].x,points[i].y);

}



//------------------------------------------------------------------------------



void Shape::draw() const

{

    Fl_Color oldc = fl_color();

    // there is no good portable way of retrieving the current style

    fl_color(lcolor.as_int());            // set color

    fl_line_style(ls.style(),ls.width()); // set style

    draw_lines();

    fl_color(oldc);      // reset color (to previous)

    fl_line_style(0);    // reset line style to default

}



//------------------------------------------------------------------------------





void Shape::move(int dx, int dy)    // move the shape +=dx and +=dy

{

    for (int i = 0; i<points.size(); ++i) {

        points[i].x+=dx;

        points[i].y+=dy;

    }

}



//------------------------------------------------------------------------------



Line::Line(Point p1, Point p2)    // construct a line from two points

{

    add(p1);    // add p1 to this shape

    add(p2);    // add p2 to this shape

}



//------------------------------------------------------------------------------



void Lines::add(Point p1, Point p2)

{

    Shape::add(p1);

    Shape::add(p2);

}



//------------------------------------------------------------------------------



// draw lines connecting pairs of points

void Lines::draw_lines() const

{

    if (color().visibility())

        for (int i=1; i<number_of_points(); i+=2)

            fl_line(point(i-1).x,point(i-1).y,point(i).x,point(i).y);

}



//------------------------------------------------------------------------------



// does two lines (p1,p2) and (p3,p4) intersect?

// if se return the distance of the intersect point as distances from p1

inline pair<double,double> line_intersect(Point p1, Point p2, Point p3, Point 
p4, bool& parallel)

{

    double x1 = p1.x;

    double x2 = p2.x;

    double x3 = p3.x;

    double x4 = p4.x;

    double y1 = p1.y;

    double y2 = p2.y;

    double y3 = p3.y;

    double y4 = p4.y;



    double denom = ((y4 - y3)*(x2-x1) - (x4-x3)*(y2-y1));

    if (denom == 0){

        parallel= true;

        return pair<double,double>(0,0);

    }

    parallel = false;

    return pair<double,double>( ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))/denom,

                                ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3))/denom);

}



//------------------------------------------------------------------------------



//intersection between two line segments

//Returns true if the two segments intersect,

//in which case intersection is set to the point of intersection

bool line_segment_intersect(Point p1, Point p2, Point p3, Point p4, Point& 
intersection){

   bool parallel;

   pair<double,double> u = line_intersect(p1,p2,p3,p4,parallel);

   if (parallel || u.first < 0 || u.first > 1 || u.second < 0 || u.second > 1) 
return false;

   intersection.x = p1.x + u.first*(p2.x - p1.x);

   intersection.y = p1.y + u.first*(p2.y - p1.y);

   return true;

}



//------------------------------------------------------------------------------



void Polygon::add(Point p)

{

    int np = number_of_points();



    if (1<np) {    // check that thenew line isn't parallel to the previous one

        if (p==point(np-1)) error("polygon point equal to previous point");

        bool parallel;

        line_intersect(point(np-1),p,point(np-2),point(np-1),parallel);

        if (parallel)

            error("two polygon points lie in a straight line");

    }



    for (int i = 1; i<np-1; ++i) {    // check that new segment doesn't 
interset and old point

        Point ignore(0,0);

        if (line_segment_intersect(point(np-1),p,point(i-1),point(i),ignore))

            error("intersect in polygon");

    }





    Closed_polyline::add(p);

}



//------------------------------------------------------------------------------



void Polygon::draw_lines() const

{

    if (number_of_points() < 3) error("less than 3 points in a Polygon");

    Closed_polyline::draw_lines();

}



//------------------------------------------------------------------------------



void Open_polyline::draw_lines() const

{

    if (fill_color().visibility()) {

        fl_color(fill_color().as_int());

        fl_begin_complex_polygon();

        for(int i=0; i<number_of_points(); ++i){

            fl_vertex(point(i).x, point(i).y);

        }

        fl_end_complex_polygon();

        fl_color(color().as_int());    // reset color

    }



    if (color().visibility())

        Shape::draw_lines();

}



//------------------------------------------------------------------------------



void Closed_polyline::draw_lines() const

{

    Open_polyline::draw_lines();    // first draw the "open poly line part"

    // then draw closing line:

    if (color().visibility())

        fl_line(point(number_of_points()-1).x,

        point(number_of_points()-1).y,

        point(0).x,

        point(0).y);

}



//------------------------------------------------------------------------------



void draw_mark(Point xy, char c)

{

    static const int dx = 4;

    static const int dy = 4;



    string m(1,c);

    fl_draw(m.c_str(),xy.x-dx,xy.y+dy);

}



//------------------------------------------------------------------------------



void Marked_polyline::draw_lines() const

{

    Open_polyline::draw_lines();

    for (int i=0; i<number_of_points(); ++i)

        draw_mark(point(i),mark[i%mark.size()]);

}



//------------------------------------------------------------------------------



void Rectangle::draw_lines() const

{

    if (fill_color().visibility()) {    // fill

        fl_color(fill_color().as_int());

        fl_rectf(point(0).x,point(0).y,w,h);

    }



    if (color().visibility()) {    // lines on top of fill

        fl_color(color().as_int());

        fl_rect(point(0).x,point(0).y,w,h);

    }

}



//------------------------------------------------------------------------------



Circle::Circle(Point p, int rr)    // center and radius

:r(rr)

{

    add(Point(p.x-r,p.y-r));       // store top-left corner

}



//------------------------------------------------------------------------------



Point Circle::center() const

{

    return Point(point(0).x+r, point(0).y+r);

}



//------------------------------------------------------------------------------



void Circle::draw_lines() const

{

    if (color().visibility())

        fl_arc(point(0).x,point(0).y,r+r,r+r,0,360);

}



//------------------------------------------------------------------------------



void Ellipse::draw_lines() const

{

    if (color().visibility())

        fl_arc(point(0).x,point(0).y,w+w,h+h,0,360);

}



//------------------------------------------------------------------------------



void Text::draw_lines() const

{

    int ofnt = fl_font();

    int osz = fl_size();

    fl_font(fnt.as_int(),fnt_sz);

    fl_draw(lab.c_str(),point(0).x,point(0).y);

    fl_font(ofnt,osz);

}



//------------------------------------------------------------------------------



Axis::Axis(Orientation d, Point xy, int length, int n, string lab) :

    label(Point(0,0),lab)

{

    if (length<0) error("bad axis length");

    switch (d){

    case Axis::x:

    {

        Shape::add(xy); // axis line

        Shape::add(Point(xy.x+length,xy.y));



        if (1<n) {      // add notches

            int dist = length/n;

            int x = xy.x+dist;

            for (int i = 0; i<n; ++i) {

                notches.add(Point(x,xy.y),Point(x,xy.y-5));

                x += dist;

            }

        }

        // label under the line

        label.move(length/3,xy.y+20);

        break;

    }

    case Axis::y:

    {

        Shape::add(xy); // a y-axis goes up

        Shape::add(Point(xy.x,xy.y-length));



        if (1<n) {      // add notches

            int dist = length/n;

            int y = xy.y-dist;

            for (int i = 0; i<n; ++i) {

                notches.add(Point(xy.x,y),Point(xy.x+5,y));

                y -= dist;

            }

        }

        // label at top

        label.move(xy.x-10,xy.y-length-10);

        break;

    }

    case Axis::z:

        error("z axis not implemented");

    }

}



//------------------------------------------------------------------------------



void Axis::draw_lines() const

{

    Shape::draw_lines();

    notches.draw();  // the notches may have a different color from the line

    label.draw();    // the label may have a different color from the line

}



//------------------------------------------------------------------------------



void Axis::set_color(Color c)

{

    Shape::set_color(c);

    notches.set_color(c);

    label.set_color(c);

}



//------------------------------------------------------------------------------



void Axis::move(int dx, int dy)

{

    Shape::move(dx,dy);

    notches.move(dx,dy);

    label.move(dx,dy);

}



//------------------------------------------------------------------------------



Function::Function(Fct f, double r1, double r2, Point xy,

                   int count, double xscale, double yscale)

// graph f(x) for x in [r1:r2) using count line segments with (0,0) displayed 
at xy

// x coordinates are scaled by xscale and y coordinates scaled by yscale

{

    if (r2-r1<=0) error("bad graphing range");

    if (count <=0) error("non-positive graphing count");

    double dist = (r2-r1)/count;

    double r = r1;

    for (int i = 0; i<count; ++i) {

        add(Point(xy.x+int(r*xscale),xy.y-int(f(r)*yscale)));

        r += dist;

    }

}



//------------------------------------------------------------------------------



bool can_open(const string& s)

// check if a file named s exists and can be opened for reading

{

    ifstream ff(s.c_str());

    return ff;

}



//------------------------------------------------------------------------------



#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))



Suffix::Encoding get_encoding(const string& s)

{

    struct SuffixMap

    {

        const char*      extension;

        Suffix::Encoding suffix;

    };



    static SuffixMap smap[] = {

        {".jpg",  Suffix::jpg},

        {".jpeg", Suffix::jpg},

        {".gif",  Suffix::gif},

    };



    for (int i = 0, n = ARRAY_SIZE(smap); i < n; i++)

    {

        int len = strlen(smap[i].extension);



        if (s.length() >= len && s.substr(s.length()-len, len) == 
smap[i].extension)

            return smap[i].suffix;

    }



    return Suffix::none;

}



//------------------------------------------------------------------------------



// somewhat over-elaborate constructor

// because errors related to image files can be such a pain to debug

Image::Image(Point xy, string s, Suffix::Encoding e)

    :w(0), h(0), fn(xy,"")

{

    add(xy);



    if (!can_open(s)) {    // can we open s?

        fn.set_label("cannot open \""+s+'\"');

        p = new Bad_image(30,20);    // the "error image"

        return;

    }



    if (e == Suffix::none) e = get_encoding(s);



    switch(e) {        // check if it is a known encoding

    case Suffix::jpg:

        p = new Fl_JPEG_Image(s.c_str());

        break;

    case Suffix::gif:

        p = new Fl_GIF_Image(s.c_str());

        break;

    default:    // Unsupported image encoding

        fn.set_label("unsupported file type \""+s+'\"');

        p = new Bad_image(30,20);    // the "error image"

    }

}



//------------------------------------------------------------------------------



void Image::draw_lines() const

{

    if (fn.label()!="") fn.draw_lines();



    if (w&&h)

        p->draw(point(0).x,point(0).y,w,h,cx,cy);

    else

        p->draw(point(0).x,point(0).y);

}



//------------------------------------------------------------------------------



} // of namespace Graph_lib

----------------------------------------------------
so plz help, eric, [email protected], [email protected]


_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to