#include #include #include #include #include #include #include #include "tmalloc.h" #include "xgalaxy.h" void setBrightPoint(GdkGC *gc, int x, int y, int c) { GdkColor color; color.red=color.green=color.blue=(255-c)*256; gdk_gc_set_rgb_fg_color(gc, &color); gdk_draw_point( XGalaxy.pixmap, gc, x, y ); } void setBrightPoints(GdkGC *gc, GdkPoint *points, int n, int c) { GdkColor color; color.red=color.green=color.blue=(255-c)*256; gdk_gc_set_rgb_fg_color(gc, &color); gdk_draw_points( XGalaxy.pixmap, gc, points, n ); } #define sqr(x) ((x)*(x)) void DrawDisk(GdkGC *gc, double CenterX, double CenterY, double Radius, double Feather, double brightness) { // (c) http://www.simdesign.nl/tips/tip002.html // Draw a disk on Bitmap. Bitmap must be a 256 color (pf8bit) // palette bitmap, and parts outside the disk will get palette // index 0, parts inside will get palette index 255, and in the // antialiased area (feather), the pixels will get values // inbetween. // ***Parameters*** // Bitmap: // The bitmap to draw on // CenterX, CenterY: // The center of the disk (float precision). Note that [0, 0] // would be the center of the first pixel. To draw in the // exact middle of a 100x100 bitmap, use CenterX = 49.5 and // CenterY = 49.5 // Radius: // The radius of the drawn disk in pixels (float precision) // Feather: // The feather area. Use 1 pixel for a 1-pixel antialiased // area. Pixel centers outside 'Radius + Feather / 2' become // 0, pixel centers inside 'Radius - Feather/2' become 255. // Using a value of 0 will yield a bilevel image. // Copyright (c) 2003 Nils Haeck M.Sc. www.simdesign.nl int x, y; int Fact; double RPF2 = sqr(Radius + Feather/2.0); double RMF2 = sqr(Radius - Feather/2.0); double SqY, SqDist; // Determine bounds: int LX = floor(CenterX - RPF2); int RX = ceil (CenterX + RPF2); int LY = floor(CenterY - RPF2); int RY = ceil (CenterY + RPF2); double SqX[RX - LX + 1]; GdkPoint darkPoint[ (RY-LY)*(RX-LX) ]; int nDarkDoint=0; // Optimization run: find squares of X first for(x=LX; x<=RX; x++) SqX[x - LX] = sqr(x - CenterX); for(y=LY; y<=RY; y++) { SqY = sqr(y - CenterY); // Loop through X values for(x=LX; x<=RX; x++) { // determine squared distance from center for this pixel SqDist = SqY + SqX[x - LX]; if (SqDist < RMF2) { // inside inner circle? Most often.. // inside the inner circle.. just give the scanline the // new color darkPoint[ nDarkDoint ].x = x; darkPoint[ nDarkDoint ].y = y; nDarkDoint++; } else if (SqDist < RPF2) { // inside outer circle? // We are inbetween the inner and outer bound, now // mix the color Fact = round(((Radius - sqrt(SqDist)) * 2.0 / Feather) * 127.5 + 127.5); // just in case limit to [0, 255] setBrightPoint(gc, x,y,brightness*fmax(0, fmin(Fact, 255))); } } } if (nDarkDoint>0) setBrightPoints( gc, darkPoint, nDarkDoint, 255*brightness ); } // Draw a line with simple anti-aliasing, suitable for draggable envelope displays. // By Paul Kellett (@mda-vst.com) October 2002. // // The anti-aliasing works by oversampling the drawing position by 256 then using // the fractional part to fade in the pixel on one side of the line while fading // out the pixel on the other side. The ends of the line aren't perfect, but these // will probably be hidden by drag handles. // // Uses fictional function: drawpixel(int x, int y, int brightness) where brightness // is a value from 0 to 255, so it's easiest to draw a red, green or blue line on a // black (or near-black) background. void drawPixel(GdkGC *gc, GdkColor *color, int x, int y, int c) { GdkColor clr; double ratio = ((double)c)/255.0; clr.red = color->red + (65535-color->red) * ratio; clr.green = color->green + (65535-color->green) * ratio; clr.blue = color->blue + (65535-color->blue) * ratio; gdk_gc_set_rgb_fg_color(gc, &clr); gdk_draw_point( XGalaxy.pixmap, gc, x, y ); } void antialiasedLine(GdkGC *gc, int x0, int y0, int x1, int y1, GdkColor *color) { int x, y, xx, yy, v; int dx = x1 - x0; int dy = y1 - y0; if (dx==0 && dy==0) { drawPixel(gc, color, x1, y1, 0); return; } if(abs(dx) > abs(dy)) //for each x pixel { if(x0 > x1) //for increasing x { x = x0; x0 = x1; x1 = x; y = y0; y0 = y1; y1 = y; } dy = (dy << 8) / dx; //oversample y by 256 yy = y0 << 8; for(x=x0; x> 8; yy = yy + dy; drawPixel(gc, color,x, y, 0); drawPixel(gc, color,x, y + 1, 255-v); drawPixel(gc, color,x, y - 1, v); } } else //for each y pixel { if(y0 > y1) //for increasing y { y = y0; y0 = y1; y1 = y; x = x0; x0 = x1; x1 = x; } dx = (dx << 8) / dy; //oversample x by 256 xx = x0 << 8; for(y=y0; y> 8; xx = xx + dx; drawPixel(gc, color,x, y, 0); drawPixel(gc, color,x + 1, y, 255-v); drawPixel(gc, color,x - 1, y, v); } } }