[gnu.g++.bug] g++-1.36.0- abort

rjc@CS.UCLA.EDU (Robert Collins) (09/08/89)

Script started on Thu Sep  7 19:05:13 1989
bugs.cognet.ucla.edu% g++ -v -fthis-is-variable -c painter.cc
gcc version 1.36.0- (based on GCC 1.35.98+)
 /usr/local/lib/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ painter.cc /tmp/cca11072.cpp
GNU CPP version 1.35.98
 /usr/local/lib/gcc-cc1plus /tmp/cca11072.cpp -quiet -dumpbase painter.cc -fthis-is-variable -version -o /tmp/cca11072.s
GNU C++ version 1.36.0- (based on GCC 1.35.98+) (sparc) compiled by GNU C version 1.35.98.
default target switches: -mfpu -mepilogue
g++: Program cc1plus got fatal signal 6.



bugs.cognet.ucla.edu% cat painter.cc
# 1 "painter.cc"
 



# 1 "../../../src/InterViews/brush.h" 1
 






# 1 "../../../src/InterViews/resource.h" 1
 






# 1 "../../../src/InterViews/defs.h" 1
 






enum boolean { false, true };

enum Alignment {
    TopLeft, TopCenter, TopRight,
    CenterLeft, Center, CenterRight,
    BottomLeft, BottomCenter, BottomRight,
    Left, Right, Top, Bottom, HorizCenter, VertCenter
};

enum TextStyle {
    Plain = 0x0,
    Boldface = 0x1,
    Underlined = 0x2,
    Reversed = 0x4,
    Outlined = 0x8
};

typedef int Coord;

extern double inch, inches, cm, point, points;
static const int pixels = 1;



inline int min (int a, int b) {
    return a < b ? a : b;
}

inline int max (int a, int b) {
    return a > b ? a : b;
}

inline int round (double x) {
    return x > 0 ? int(x+0.5) : -int(-x+0.5);
}


# 8 "../../../src/InterViews/resource.h" 2


class Resource {
public:
    Resource () { refcount = 1; }
    ~Resource () { if (--refcount > 0) { this = 0; } }

    void Reference () { ++refcount; }
    boolean LastRef () { return refcount == 1; }
private:
    unsigned refcount;
};


# 8 "../../../src/InterViews/brush.h" 2


class Brush : public Resource {
public:
    Brush(int pattern, int width = 1);
    Brush(int* pattern, int count, int width = 1);
    ~Brush();

    int Width();
private:
    friend class Painter;

    class BrushRep* rep;
    int width;
};

class BrushRep {
    friend class Brush;
    friend class Painter;

    BrushRep(int* pattern, int count, int width);
    ~BrushRep();
    void* info;
    int count;
};

inline int Brush::Width () { return width; }

extern Brush* single;


# 5 "painter.cc" 2

# 1 "../../../src/InterViews/color.h" 1
 






# 1 "../../../src/InterViews/resource.h" 1
 



# 21 "../../../src/InterViews/resource.h"

# 8 "../../../src/InterViews/color.h" 2


 



typedef int ColorIntensity;

class Color : public Resource {
public:
    Color(ColorIntensity r, ColorIntensity g, ColorIntensity b);
    Color(const char*);
    Color(const char*, int length);
    Color(int pixel);
    ~Color();

    void Intensities(ColorIntensity& r, ColorIntensity& g, ColorIntensity& b);
    void DisplayIntensities(
        ColorIntensity& r, ColorIntensity& g, ColorIntensity& b
    );
    int PixelValue();
    boolean Valid();
protected:
    class ColorRep* rep;
    ColorIntensity red, green, blue;
};

class ColorRep {
private:
    friend class Color;

    ColorRep(int pixel, ColorIntensity&, ColorIntensity&, ColorIntensity&);
    ColorRep(const char*, ColorIntensity&, ColorIntensity&, ColorIntensity&);
    ColorRep(ColorIntensity, ColorIntensity, ColorIntensity);
    ~ColorRep();

    int GetPixel();
    void GetIntensities(ColorIntensity&, ColorIntensity&, ColorIntensity&);

    void* info;
};

extern Color* black;
extern Color* white;

inline void Color::Intensities (
    ColorIntensity& r, ColorIntensity& g, ColorIntensity& b
) {
    r = red; g = green; b = blue;
}

inline void Color::DisplayIntensities (
    ColorIntensity& r, ColorIntensity& g, ColorIntensity& b
) {
    rep->GetIntensities(r, g, b);
}

inline int Color::PixelValue () { return rep->GetPixel(); }


# 6 "painter.cc" 2

# 1 "../../../src/InterViews/font.h" 1
 






# 1 "../../../src/InterViews/resource.h" 1
 



# 21 "../../../src/InterViews/resource.h"

# 8 "../../../src/InterViews/font.h" 2


class Font : public Resource {
public:
    Font(const char*);
    Font(const char*, int);
    ~Font();

    int Baseline();
    boolean FixedWidth();
    int Height();
    int Index(const char*, int offset, boolean between);
    int Index(const char*, int, int offset, boolean between);
    boolean Valid();
    int Width(const char*);
    int Width(const char*, int);
    void* Info();
private:
    friend class Painter;

    class FontRep* rep;

    void GetFontByName(const char*);
    void Init();
    boolean Lookup(const char*, int);
};

class FontRep : public Resource {
    friend class Font;
    friend class Painter;

    void* id;
    void* info;
    int height;

    ~FontRep();
};

extern Font* stdfont;


# 7 "painter.cc" 2

# 1 "../../../src/InterViews/painter.h" 1
 






# 1 "../../../src/InterViews/defs.h" 1
 



# 44 "../../../src/InterViews/defs.h"

# 8 "../../../src/InterViews/painter.h" 2

# 1 "../../../src/InterViews/resource.h" 1
 



# 21 "../../../src/InterViews/resource.h"

# 9 "../../../src/InterViews/painter.h" 2


class Canvas;
class Color;
class PainterRep;
class Pattern;
class Brush;
class Font;
class Transformer;
class Bitmap;
class Raster;

class Painter : public Resource {
public:
    Painter();
    Painter(Painter*);
    ~Painter();
    void FillBg(boolean);
    boolean BgFilled();
    void SetColors(Color* f, Color* b);
    Color* GetFgColor();
    Color* GetBgColor();
    void SetPattern(Pattern*);
    Pattern* GetPattern();
    void SetBrush(Brush*);
    Brush* GetBrush();
    void SetFont(Font*);
    Font* GetFont();
    void SetStyle(int);
    int GetStyle();
    void SetTransformer(Transformer*);
    Transformer* GetTransformer();
    void MoveTo(int x, int y);
    void GetPosition(int& x, int& y);
    void SetOrigin(int x0, int y0);
    void GetOrigin(int& x0, int& y0);

    void Translate(float dx, float dy);
    void Scale(float x, float y);
    void Rotate(float angle);

    void Clip(Canvas*, Coord left, Coord bottom, Coord right, Coord top);
    void NoClip();
    void SetOverwrite(boolean);
    void SetPlaneMask(int);

    void Text(Canvas*, const char*);
    void Text(Canvas*, const char*, int);
    void Text(Canvas*, const char*, Coord, Coord);
    void Text(Canvas*, const char*, int, Coord, Coord);
    void Stencil(Canvas*, Coord x, Coord y, Bitmap* image, Bitmap* mask = 0 );
    void RasterRect(Canvas*, Coord x, Coord y, Raster*);
    void Point(Canvas*, Coord x, Coord y);
    void MultiPoint(Canvas*, Coord x[], Coord y[], int n);
    void Line(Canvas*, Coord x1, Coord y1, Coord x2, Coord y2);
    void Rect(Canvas*, Coord x1, Coord y1, Coord x2, Coord y2);
    void FillRect(Canvas*, Coord x1, Coord y1, Coord x2, Coord y2);
    void ClearRect(Canvas*, Coord x1, Coord y1, Coord x2, Coord y2);
    void Circle(Canvas*, Coord x, Coord y, int r);
    void FillCircle(Canvas*, Coord x, Coord y, int r);
    void Ellipse(Canvas*, Coord x, Coord y, int r1, int r2);
    void FillEllipse(Canvas*, Coord x, Coord y, int r1, int r2);
    void MultiLine(Canvas*, Coord x[], Coord y[], int n);
    void Polygon(Canvas*, Coord x[], Coord y[], int n);
    void FillPolygon(Canvas*, Coord x[], Coord y[], int n);
    void BSpline(Canvas*, Coord x[], Coord y[], int n);
    void ClosedBSpline(Canvas*, Coord x[], Coord y[], int n);
    void FillBSpline(Canvas*, Coord x[], Coord y[], int n);
    void Curve(Canvas*,
	Coord x0, Coord y0, Coord x1, Coord y1,
	Coord x2, Coord y2, Coord x3, Coord y3
    );
    void CurveTo(Canvas*,
	Coord x0, Coord y0, Coord x1, Coord y1, Coord x2, Coord y2
    );
    void Copy(
	Canvas* src, Coord x1, Coord y1, Coord x2, Coord y2,
	Canvas* dst, Coord x0, Coord y0
    );
    void Read(Canvas*, void*, Coord x1, Coord y1, Coord x2, Coord y2);
    void Write(Canvas*, const void*, Coord x1, Coord y1, Coord x2, Coord y2);

    PainterRep* Rep();
private:
    friend class Rubberband;

    Color* foreground;
    Color* background;
    Pattern* pattern;
    Brush* br;
    Font* font;
    int style;
    Coord curx, cury;
    int xoff, yoff;
    Transformer* matrix;
    PainterRep* rep;

    void Init();
    void Copy(Painter*);
    void Begin_xor();
    void End_xor();
    void Map(Canvas*, Coord x, Coord y, Coord& mx, Coord& my);
    void Map(Canvas*, Coord x, Coord y, short& sx, short& sy);
    void MapList(Canvas*, Coord x[], Coord y[], int n, Coord mx[], Coord my[]);
    void MapList(Canvas*, float x[], float y[], int n, Coord mx[], Coord my[]);
    void MultiLineNoMap(Canvas* c, Coord x[], Coord y[], int n);
    void FillPolygonNoMap(Canvas* c, Coord x[], Coord y[], int n);
};

inline PainterRep* Painter::Rep () { return rep; }


# 8 "painter.cc" 2

# 1 "../../../src/InterViews/pattern.h" 1
 






# 1 "../../../src/InterViews/resource.h" 1
 



# 21 "../../../src/InterViews/resource.h"

# 8 "../../../src/InterViews/pattern.h" 2


static const int patternHeight = 16;
static const int patternWidth = 16;

class Pattern : public Resource {
public:
    Pattern(int p[patternHeight]);
    Pattern(int dither);
    Pattern(class Bitmap*);
    ~Pattern();
private:
    friend class Painter;

    void* info;
};

extern Pattern* solid;
extern Pattern* clear;
extern Pattern* lightgray;
extern Pattern* gray;
extern Pattern* darkgray;


# 9 "painter.cc" 2

# 1 "../../../src/InterViews/transformer.h" 1
 






# 1 "../../../src/InterViews/defs.h" 1
 



# 44 "../../../src/InterViews/defs.h"

# 8 "../../../src/InterViews/transformer.h" 2

# 1 "../../../src/InterViews/resource.h" 1
 



# 21 "../../../src/InterViews/resource.h"

# 9 "../../../src/InterViews/transformer.h" 2


class Transformer : public Resource {
    float mat00, mat01, mat10, mat11, mat20, mat21;

    float Det(Transformer* t);
public:
    Transformer(Transformer* t =0 );	     
    Transformer(
	float a00, float a01, float a10, float a11, float a20, float a21
    );

    void GetEntries(
	float& a00, float& a01, float& a10, float& a11, float& a20, float& a21
    );
    void Premultiply(Transformer* t);
    void Postmultiply(Transformer* t);
    void Invert();

    void Translate(float dx, float dy);
    void Scale(float sx, float sy);
    void Rotate(float angle);
    boolean Translated () { return mat20 != 0 || mat21 != 0; }
    boolean Scaled () { return mat00 != 1 || mat11 != 1; }
    boolean Stretched () { return mat00 != mat11; }
    boolean Rotated () { return mat01 != 0 || mat10 != 0; }
    boolean Rotated90 () { return Rotated() && mat00 == 0 && mat11 == 0; }

    void Transform(Coord& x, Coord& y);
    void Transform(Coord x, Coord y, Coord& tx, Coord& ty);
    void Transform(float x, float y, float& tx, float& ty);
    void TransformList(Coord x[], Coord y[], int n);
    void TransformList(Coord x[], Coord y[], int n, Coord tx[], Coord ty[]);
    void InvTransform(Coord& tx, Coord& ty);
    void InvTransform(Coord tx, Coord ty, Coord& x, Coord& y);
    void InvTransform(float tx, float ty, float& x, float& y);
    void InvTransformList(Coord tx[], Coord ty[], int n);
    void InvTransformList(Coord tx[], Coord ty[], int n, Coord x[], Coord y[]);

    boolean operator == (Transformer&);
    boolean operator != (Transformer&);
    Transformer& operator = (Transformer&);
};

inline float Transformer::Det (Transformer *t) {
    return t->mat00*t->mat11 - t->mat01*t->mat10;
}


# 10 "painter.cc" 2

# 1 "/usr/local/lib/g++-include/bstring.h" 1
#pragma once
# 1 "/usr/local/lib/g++-include/std.h" 1
 
 























#pragma once

#pragma once

overload abs;
overload atoi;

extern "C" {
void volatile _exit(int);
void volatile abort(void);
int       abs(int);
int       access(const char*, int);
int       acct(const char*);
unsigned  alarm(unsigned);
void*     alloca(int);
double    atof(const char*);
int       atoi(const char*);
long      atol(const char*);
int       bcmp(const void*, const void*, int);
void      bcopy(const void*, void*, int);
int       bind(int, void*, int);
int       brk(void*);
int       bsearch (const void *, const void *, unsigned long, 
                   unsigned long, auto int (*ptf)(const void*, const void*));
void      bzero(void*, int);
void*     calloc(unsigned, unsigned);
void      cfree(void*);
int       chdir(const char*);
int       chmod(const char*, int);
int       chown(const char*, int, int);
long      clock(void);
int       close(int);
int       creat(const char*, unsigned long int);
char*     crypt(const char*, const char*);
char*     ctermid(char*);
char*     cuserid(char*);
double    drand48(void);
int       dup(int);
int       dup2(int, int);
int       dysize(int);
char*     ecvt(double, int, int*, int*);
char*     encrypt(char*, int);
double    erand(short*);
int       execl(const char*, const char *, ...);
int       execle(const char*, const char *, ...);
int       execlp(const char*, const char*, ...);
int       exect(const char*,  const char**,  char**);
int       execv(const char*,  const char**);
int       execve(const char*, const char**, char**);
int       execvp(const char*,  const char**);
void volatile exit(int);
int       fchmod(int, int);
int       fchown(int, int, int);
int       fcntl(int, int, ...);
char*     fcvt(double, int, int*, int*);
int       ffs(int);
int       flock(int, int);
int       fork(void);
void      free(void*);
int       fsync(int);
long      ftok(const char*, int);
int       ftruncate(int, unsigned long);
char*     gcvt(double, int, char*);
char*     getcwd(char*, int);
int       getdomainname(char*, int);
int       getdtablesize(void);
int       getegid(void);
char*     getenv(const char*);
int       geteuid(void);
int       getgid(void);
int       getgroups(int, int*);
long      gethostid(void);
int       gethostname(char*, int);
char*     getlogin(void);
int       getopt(int, char**, char*);
int       getpagesize(void);
char*     getpass(const char*);
int       getpgrp(void);
int       getpid(void);
int       getppid(void);
int       getpriority(int, int);
int       getpw(int, char*);
unsigned  getuid(void);
char*     getwd(char*);
char*     index(const char*, int);
char*     initstate(unsigned, char*, int);
int       ioctl(int, int, char*);
int       isatty(int);
long      jrand48(short*);
int       kill(int, int);
int       killpg(int, int);
void      lcong48(short*);
int       link(const char*, const char*);
int       listen(int, int);
int       lock(int, int, long);
long      lrand48(void);
long      lseek(int, long, int);
void*     malloc(unsigned);
void*     memalign(unsigned, unsigned);
void*     memccpy(void*, const void*, int, int);
void*     memchr(const void*, int, int);
int       memcmp(const void*, const void*, int);
void*     memcpy(void*, const void*, int);
void*     memset(void*, int, int);
int       mkdir(const char*, int);
int       mknod(const char*, int, int);
int       mkstemp(char*);
char*     mktemp(char*);
long      mrand48(void);
int       nice(int);
long      nrand48(short*);
int       open(const char*, int, ...);
void      pause(void);
void      perror(const char*);
int       pipe(int*);
void      profil(char*, int, int, int);
int       psignal(unsigned, char*);
int       ptrace(int, int, int, int);
int       putenv(const char*);
int       qsort(void*, int, unsigned, auto (*ptf)(void*,void*));
int       rand(void);
long      random(void);
int       read(int, void*, unsigned);
int       readlink(const char*, char*, int);
void*     realloc(void*, unsigned);
int       rename(const char*, const char*);
char*     rindex(const char*, int);
int       rmdir(const char*);               
void*     sbrk(int);              
short*    seed48(short*);
int       send(int, char*, int, int);
int       setgid(int);
int       sethostname(char*, int);
int       setkey(const char*);
int       setpgrp(int, int);
int       setpriority(int, int, int);
int       setregid(int, int);
int       setreuid(int, int);
char*     setstate(char*);
int       setuid(int);
int       sigblock(int);
int       siginterrupt(int, int);
int       sigpause(int);
int       sigsetmask(int);
unsigned  sleep(unsigned);
int       socket(int, int, int);
int       srand(int);
void      srand48(long);
void      srandom(int);
int       stime(long*);
char*     strcat(char*, const char*);
char*     strchr(const char*, int);
int       strcmp(const char*, const char*);
char*     strcpy(char*, const char*);
int       strcspn(const char*, const char*);
char*     strdup(const char*);
int       strlen(const char*);
char*     strncat(char*, const char*, int);
int       strncmp(const char*, const char*, int);
char*     strncpy(char*, const char*, int);
char*     strpbrk(const char*, const char*);
char*     strrchr(const char*, int);
int       strspn(const char*, const char*);
double    strtod(const char*, char**);
char*     strtok(char*, const char*);
long      strtol(const char*, char**, int);
void      swab(void*, void*, int);
int       symlink(const char*, const char*);
int       syscall(int, ...);
int       system(const char*);
char*     tempnam(char*, char*);
int       tgetent(char*, char*);
int       tgetnum(char*);
int       tgetflag(char*);
char*     tgetstr(char *, char **);
char*     tgoto(char*, int, int);
long      time(long*);
char*     tmpnam(char*);
int       tputs(char *, int, auto int (*)());
int       truncate(const char*, unsigned long);
char*     ttyname(int);
int       ttyslot(void);
unsigned  ualarm(unsigned, unsigned);
long      ulimit(int, long);
int       umask(int);
int       unlink(const char*);
unsigned  usleep(unsigned);
int       vadvise(int);
void*     valloc(unsigned);
int       vfork(void);
int       vhangup(void);
int       wait(int*);
int       write(int, const void*, unsigned);
}


extern char**   environ;
extern int      errno;
extern char*    sys_errlist[];
extern int      sys_nerr;                  
extern char*    optarg;
extern int      opterr;
extern int      optind;









# 2 "/usr/local/lib/g++-include/bstring.h" 2

# 11 "painter.cc" 2

# 1 "/usr/local/lib/g++-include/string.h" 1

# 12 "painter.cc" 2


 





void Painter::Init () {
    if (solid == 0 ) {
	solid = new Pattern(0xffff);
	clear = new Pattern(0);
	lightgray = new Pattern(0x8020);
	gray = new Pattern(0xa5a5);
	darkgray = new Pattern(0xfafa);
	single = new Brush(0xffff, 0);
    }
    foreground = 0 ;
    background = 0 ;
    pattern = 0 ;
    br = 0 ;
    font = 0 ;
    style = 0;
    matrix = 0 ;
    SetColors(black, white);
    SetPattern(solid);
    FillBg(true);
    SetBrush(single);
    SetFont(stdfont);
    SetStyle(Plain);
    SetOrigin(0, 0);
    MoveTo(0, 0);
}

void Painter::Copy (Painter* copy) {
    foreground = 0 ;
    background = 0 ;
    pattern = 0 ;
    br = 0 ;
    font = 0 ;
    style = 0;
    matrix = 0 ;
    SetColors(copy->foreground, copy->background);
    SetPattern(copy->pattern);
    SetBrush(copy->br);
    SetFont(copy->font);
    SetStyle(copy->style);
    SetTransformer(copy->matrix);
    SetOrigin(copy->xoff, copy->yoff);
    MoveTo(copy->curx, copy->cury);
}

Color* Painter::GetFgColor () {
    return foreground;
}

Color* Painter::GetBgColor () {
    return background;
}

Pattern* Painter::GetPattern () {
    return pattern;
}

Brush* Painter::GetBrush () {
    return br;
}

Font* Painter::GetFont () {
    return font;
}

void Painter::SetStyle (int s) {
    style = s;
}

int Painter::GetStyle () {
    return style;
}

void Painter::SetTransformer (Transformer *t) {
    if (matrix != t) {
	delete matrix;
	matrix = t;
	if (matrix != 0 ) {
	    matrix->Reference();
	}
    }
}

Transformer* Painter::GetTransformer () {
    return matrix;
}

void Painter::MoveTo (int x, int y) {
    curx = x;
    cury = y;
}

void Painter::GetPosition (int& x, int& y) {
    x = curx;
    y = cury;
}

void Painter::SetOrigin (int x0, int y0) {
    xoff = x0;
    yoff = y0;
}

void Painter::GetOrigin (int& x0, int& y0) {
    x0 = xoff;
    y0 = yoff;
}

void Painter::Translate (float dx, float dy) {
    if (dx != 0.0 || dy != 0.0) {
	if (matrix == 0 ) {
	    matrix = new Transformer;
	}
	matrix->Translate(dx, dy);
    }
}

void Painter::Scale (float sx, float sy) {
    if (sx != 1.0 || sy != 1.0) {
	if (matrix == 0 ) {
	    matrix = new Transformer;
	}
	matrix->Scale(sx, sy);
    }
}

void Painter::Rotate (float angle) {
    if (angle - int(angle) != 0.0 || int(angle) % 360 != 0) {
	if (matrix == 0 ) {
	    matrix = new Transformer;
	}
	matrix->Rotate(angle);
    }
}

void Painter::CurveTo (Canvas* c,
    Coord x0, Coord y0, Coord x1, Coord y1, Coord x2, Coord y2
) {
    Curve(c, curx, cury, x0, y0, x1, y1, x2, y2);
    curx = x2;
    cury = y2;
}

void Painter::Text (Canvas* c, const char* s) {
    int len = strlen(s);
    Text(c, s, len, curx, cury);
    curx += font->Width(s, len);
}

void Painter::Text (Canvas* c, const char* s, int len) {
    Text(c, s, len, curx, cury);
    curx += font->Width(s, len);
}

void Painter::Text (Canvas* c, const char* s, Coord x, Coord y) {
    Text(c, s, strlen(s), x, y);
}

 



const int INITBUFSIZE = 100;
const double SMOOTHNESS = 1.0;

static int llsize = 0;
static int llcount = 0;
static Coord* llx;
static Coord* lly;

static void GrowBufs (Coord*& b1, Coord*& b2, int& cur) {
    Coord* newb1;
    Coord* newb2;
    int newsize;

    if (cur == 0) {
        cur = INITBUFSIZE;
	b1 = new Coord[INITBUFSIZE];
	b2 = new Coord[INITBUFSIZE];
    } else {
	newsize = cur * 2;
	newb1 = new Coord[newsize];
	newb2 = new Coord[newsize];
	bcopy(b1, newb1, newsize * sizeof(Coord));
	bcopy(b2, newb2, newsize * sizeof(Coord));
	delete b1;
	delete b2;
	b1 = newb1;
	b2 = newb2;
	cur = newsize;
    }
}

inline void Midpoint (
    double x0, double y0, double x1, double y1, double& mx, double& my
) {
    mx = (x0 + x1) / 2.0;
    my = (y0 + y1) / 2.0;
}

inline void ThirdPoint (
    double x0, double y0, double x1, double y1, double& tx, double& ty
) {
    tx = (2*x0 + x1) / 3.0;
    ty = (2*y0 + y1) / 3.0;
}

inline boolean CanApproxWithLine (
    double x0, double y0, double x2, double y2, double x3, double y3
) {
    double triangleArea, sideSquared, dx, dy;
    
    triangleArea = x0*y2 - x2*y0 + x2*y3 - x3*y2 + x3*y0 - x0*y3;
    triangleArea *= triangleArea;	 
    dx = x3 - x0;
    dy = y3 - y0;
    sideSquared = dx*dx + dy*dy;
    return triangleArea <= SMOOTHNESS * sideSquared;
}

inline void AddLine (double x0, double y0, double x1, double y1) {
    if (llcount >= llsize) {
	GrowBufs(llx, lly, llsize);
    }

    if (llcount == 0) {
	llx[llcount] = round(x0);
	lly[llcount] = round(y0);
	++llcount;
    }
    llx[llcount] = round(x1);
    lly[llcount] = round(y1);
    ++llcount;
}

static void AddBezierCurve (
    double x0, double y0, double x1, double y1,
    double x2, double y2, double x3, double y3
) {
    double midx01, midx12, midx23, midlsegx, midrsegx, cx;
    double midy01, midy12, midy23, midlsegy, midrsegy, cy;
    
    Midpoint(x0, y0, x1, y1, midx01, midy01);
    Midpoint(x1, y1, x2, y2, midx12, midy12);
    Midpoint(x2, y2, x3, y3, midx23, midy23);
    Midpoint(midx01, midy01, midx12, midy12, midlsegx, midlsegy);
    Midpoint(midx12, midy12, midx23, midy23, midrsegx, midrsegy);
    Midpoint(midlsegx, midlsegy, midrsegx, midrsegy, cx, cy);    

    if (CanApproxWithLine(x0, y0, midlsegx, midlsegy, cx, cy)) {
        AddLine(x0, y0, cx, cy);
    } else if (
        (midx01 != x1) || (midy01 != y1) ||
	(midlsegx != x2) || (midlsegy != y2) ||
	(cx != x3) || (cy != y3)
    ) {    
        AddBezierCurve(
	    x0, y0, midx01, midy01, midlsegx, midlsegy, cx, cy
	);
    }
    if (CanApproxWithLine(cx, cy, midx23, midy23, x3, y3)) {
        AddLine(cx, cy, x3, y3);
    } else if (
        (cx != x0) || (cy != y0) ||
	(midrsegx != x1) || (midrsegy != y1) ||
	(midx23 != x2) || (midy23 != y2)
    ) {        
        AddBezierCurve(
	    cx, cy, midrsegx, midrsegy, midx23, midy23, x3, y3
	);
    }
}

static void CalcBSpline (
    Coord cminus1x, Coord cminus1y, Coord cx, Coord cy,
    Coord cplus1x, Coord cplus1y, Coord cplus2x, Coord cplus2y
) {
    double p0x, p1x, p2x, p3x, tempx,
	   p0y, p1y, p2y, p3y, tempy;
    
    ThirdPoint(
        double(cx), double(cy), double(cplus1x), double(cplus1y), p1x, p1y
    );
    ThirdPoint(
        double(cplus1x), double(cplus1y), double(cx), double(cy), p2x, p2y
    );
    ThirdPoint(
        double(cx), double(cy), double(cminus1x), double(cminus1y),
	tempx, tempy
    );
    Midpoint(tempx, tempy, p1x, p1y, p0x, p0y);
    ThirdPoint(
        double(cplus1x), double(cplus1y), double(cplus2x), double(cplus2y),
	tempx, tempy
    );
    Midpoint(tempx, tempy, p2x, p2y, p3x, p3y);
    
    AddBezierCurve(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y);
}

inline void CreateOpenLineList (Coord *cpx, Coord *cpy, int cpcount) {
    int cpi;
    
    llcount = 0;
    CalcBSpline(
	cpx[0], cpy[0], cpx[0], cpy[0], cpx[0], cpy[0], cpx[1], cpy[1]
    );
    CalcBSpline(
	cpx[0], cpy[0], cpx[0], cpy[0], cpx[1], cpy[1], cpx[2], cpy[2]
    );

    for (cpi = 1; cpi < cpcount - 2; ++cpi) {
	CalcBSpline(
	    cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
	    cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 2], cpy[cpi + 2]
        );
    }
    CalcBSpline(
	cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
	cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 1], cpy[cpi + 1]
    );
    CalcBSpline(
	cpx[cpi], cpy[cpi], cpx[cpi + 1], cpy[cpi + 1],
	cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 1], cpy[cpi + 1]
    );
}

inline void CreateClosedLineList (Coord *cpx, Coord *cpy, int cpcount) {
    int cpi;
    
    llcount = 0;
    CalcBSpline(
	cpx[cpcount - 1], cpy[cpcount - 1], cpx[0], cpy[0], 
	cpx[1], cpy[1], cpx[2], cpy[2]
    );

    for (cpi = 1; cpi < cpcount - 2; ++cpi) {
	CalcBSpline(
	    cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
	    cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 2], cpy[cpi + 2]
        );
    }
    CalcBSpline(
	cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
	cpx[cpi + 1], cpy[cpi + 1], cpx[0], cpy[0]
    );
    CalcBSpline(
	cpx[cpi], cpy[cpi], cpx[cpi + 1], cpy[cpi + 1],
	cpx[0], cpy[0], cpx[1], cpy[1]
    );
}

static int bufsize = 0;
static Coord* bufx, * bufy;

static void CheckBufs (Coord*& b1, Coord*& b2, int& cur, int desired) {
    if (cur < desired) {
	if (cur == 0) {
	    cur = max(INITBUFSIZE, desired);
	} else {
	    delete b1;
	    delete b2;
	    cur = max(cur * 2, desired);
	}
	b1 = new Coord[cur];
	b2 = new Coord[cur];
    }
}

void Painter::Curve (
    Canvas* c, Coord x0, Coord y0, Coord x1, Coord y1,
    Coord x2, Coord y2, Coord x3, Coord y3
) {
    Coord tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3;
    
    llcount = 0;
    Map(c, x0, y0, tx0, ty0);
    Map(c, x1, y1, tx1, ty1);
    Map(c, x2, y2, tx2, ty2);
    Map(c, x3, y3, tx3, ty3);
    AddBezierCurve(tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3);
    MultiLineNoMap(c, llx, lly, llcount);
}

void Painter::BSpline (Canvas* c, Coord x[], Coord y[], int count) {
    CheckBufs(bufx, bufy, bufsize, count);
    MapList(c, x, y, count, bufx, bufy);
    if (count < 3) {
        MultiLineNoMap(c, bufx, bufy, count);
    } else {
	CreateOpenLineList(bufx, bufy, count);
	MultiLineNoMap(c, llx, lly, llcount);
    }
}

void Painter::ClosedBSpline (Canvas* c, Coord x[], Coord y[], int count) {
    CheckBufs(bufx, bufy, bufsize, count);
    MapList(c, x, y, count, bufx, bufy);
    if (count < 3) {
        MultiLineNoMap(c, bufx, bufy, count);
    } else {
        CreateClosedLineList(bufx, bufy, count);
        MultiLineNoMap(c, llx, lly, llcount);
    }
}

void Painter::FillBSpline (Canvas* c, Coord x[], Coord y[], int count) {
    CheckBufs(bufx, bufy, bufsize, count);
    MapList(c, x, y, count, bufx, bufy);
    if (count < 3) {
        FillPolygonNoMap(c, bufx, bufy, count);
    } else {
        CreateClosedLineList(bufx, bufy, count);
        FillPolygonNoMap(c, llx, lly, llcount);
    }
}

void Painter::Map (Canvas* c, Coord x, Coord y, short& sx, short& sy) {
    Coord cx, cy;

    Map(c, x, y, cx, cy);
    sx = short(cx);
    sy = short(cy);
}

const float axis = 0.42;
const float seen = 1.025;

void Painter::Ellipse (Canvas* c, Coord cx, Coord cy, int r1, int r2) {
    float px1, py1, px2, py2, x[8], y[8];

    px1 = float(r1)*axis; py1 = float(r2)*axis;
    px2 = float(r1)*seen; py2 = float(r2)*seen;
    x[0] = cx + px1;	y[0] = cy + py2;
    x[1] = cx - px1;	y[1] = y[0];
    x[2] = cx - px2;	y[2] = cy + py1;
    x[3] = x[2];	y[3] = cy - py1;
    x[4] = x[1];	y[4] = cy - py2;
    x[5] = x[0];	y[5] = y[4];
    x[6] = cx + px2;	y[6] = y[3];
    x[7] = x[6];	y[7] = y[2];

    CheckBufs(bufx, bufy, bufsize, 8);
    MapList(c, (float*) x, (float*) y, 8, bufx, bufy);
    CreateClosedLineList(bufx, bufy, 8);
    MultiLineNoMap(c, llx, lly, llcount);
}

void Painter::FillEllipse (Canvas* c, Coord cx, Coord cy, int r1, int r2) {
    float px1, py1, px2, py2, x[8], y[8];

    px1 = float(r1)*axis; py1 = float(r2)*axis;
    px2 = float(r1)*seen; py2 = float(r2)*seen;
    x[0] = cx + px1;	y[0] = cy + py2;
    x[1] = cx - px1;	y[1] = y[0];
    x[2] = cx - px2;	y[2] = cy + py1;
    x[3] = x[2];	y[3] = cy - py1;
    x[4] = x[1];	y[4] = cy - py2;
    x[5] = x[0];	y[5] = y[4];
    x[6] = cx + px2;	y[6] = y[3];
    x[7] = x[6];	y[7] = y[2];

    CheckBufs(bufx, bufy, bufsize, 8);
    MapList(c, (float*) x, (float*) y, 8, bufx, bufy);
    CreateClosedLineList(bufx, bufy, 8);
    FillPolygonNoMap(c, llx, lly, llcount);
}
bugs.cognet.ucla.edu% ^D
script done on Thu Sep  7 19:06:01 1989