/* * Smiley * ------ * This program draws a smiley inside a window. It uses a drawing * area with a redraw call-back function to ensure the smile is * always drawn. * * Note there is a problem with this program: if you resize the * window to be too small, it hangs there forever. Why? * The answer is in the drawarc function drawing the smile. * If the face rectangle r1 gets too small, r2 (which is r1 inset * by 30 pixels) gets a negative width and/or height. * * Negative-sized rectangles are no good. The computer hardware * treats rectangle widths and heights as unsigned integers. * A negative number when cast to an unsigned int becomes very large * indeed. The graphics hardware is then trying to draw an impossibly * large arc, hence the program sits there drawing for a long time. * * Solution? Add this line before drawarc: r2 = rcanon(r2); * The rcanon function corrects for negative widths and/or heights * and makes them positive again, while preserving the size of the * rectangle. */ #include void draw_smile(drawing d, rect r) { rect r1 = insetr(r, 10); /* inset r1 from edge of drawing */ rect r2; point p; setcolour(LightBlue); /* blue face */ fillellipse(r1); /* draw face */ setcolour(Red); /* red lips */ setlinewidth(2); /* thicker lips */ r2 = insetr(r1, 30); /* inset from face rectangle */ drawarc(r2, 270-60, 270+60); /* smile between arc angles */ setcolour(Brown); /* brown eyes */ p.x = r1.x + r1.width * 1/2; p.y = r1.y + r1.height * 1/4; r2 = rect(p.x - 30, p.y, 20,20); fillellipse(r2); /* draw left eye */ r2 = rect(p.x + 10, p.y, 20,20); fillellipse(r2); /* draw right eye */ } void resize_smile(window w, rect r) { /* retrieve remembered drawing */ drawing d = (drawing) getdata(w); resize(d, r); } void main(void) { window w; drawing d; w = newwindow("Smile!", rect(50,50,120,120), StandardWindow); d = newdrawing(rect(0,0,120,120), draw_smile); setdata(w, d); /* store the pointer with the window */ setresize(w, resize_smile); show(w); mainloop(); }