void Fl_Device::line(int x, int y, int x1, int y1) { fl_transform(x,y); fl_transform(x1,y1); #ifdef _WIN32 fl_set_cosmetic_pen(); fl_line_drawer.move(x, y); fl_line_drawer.line(x1, y1); #else XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1); #endif }
// Intersect & push a new clip rectangle: void Fl_Device::push_clip(int x, int y, int w, int h) { Region r; if (w > 0 && h > 0) { fl_transform(x,y); r = XRectangleRegion(x, y, w, h); Region current = rstack[rstackptr]; if (current) { #ifndef _WIN32 Region temp = XCreateRegion(); XIntersectRegion(current, r, temp); XDestroyRegion(r); r = temp; #else CombineRgn(r,r,current,RGN_AND); #endif } } // make empty clip region: else { #ifndef _WIN32 r = XCreateRegion(); #else r = CreateRectRgn(0,0,0,0); #endif } if (rstackptr < STACK_MAX) rstack[++rstackptr] = r; fl_restore_clip(); }
void Fl_Device::point(int x, int y) { fl_transform(x,y); #ifdef _WIN32 SetPixel(fl_gc, x, y, fl_colorref); #else XDrawPoint(fl_display, fl_window, fl_gc, x, y); #endif }
void Fl_Device::rect(int x, int y, int w, int h) { if (w<=0 || h<=0) return; fl_transform(x,y); #ifdef _WIN32 fl_set_cosmetic_pen(); w--; h--; fl_line_drawer.move(x,y); fl_line_drawer.line(x+w, y); fl_line_drawer.line(x+w, y+h); fl_line_drawer.line(x, y+h); fl_line_drawer.line(x, y); #else XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1); #endif }
void WPaper::_draw(int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh, Fl_Flags f) { if(!id) Fl_Image::_draw(dx,dy,dw,dh,sx,sy,sw,sh,f); if(id && m_data) { delete m_data; m_data=0; } if(id) { // convert to Xlib coordinates: Pixmap pix = (Pixmap) id; fl_transform(dx,dy); fl_copy_offscreen(dx,dy,dw,dh,pix,0,0); // Set X root (used by terms for 'transparency') Atom prop_root = XInternAtom(fl_display, "_XROOTPMAP_ID", False); XChangeProperty(fl_display, RootWindow(fl_display, fl_screen), prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pix, 1); } }
void Fl_Device::rectf(int x, int y, int w, int h) { if (w<=0 || h<=0) return; fl_transform(x,y); #ifdef _WIN32 RECT rect; rect.left = x; rect.top = y; rect.right = x + w; rect.bottom = y + h; #if 1 // From the MFC CDC class, apparently this is faster: SetBkColor(fl_gc, fl_colorref); ExtTextOut(fl_gc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); #else FillRect(fl_gc, &rect, fl_brush()); #endif #else XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h); #endif }
// Replace top of stack with top of stack minus this rectangle: void Fl_Device::clip_out(int x, int y, int w, int h) { if (w <= 0 || h <= 0) return; Region current = rstack[rstackptr]; // current must not be zero, you must push a rectangle first. I // return without doing anything because that makes some old fltk code work: if (!current) return; fl_transform(x,y); Region r = XRectangleRegion(x, y, w, h); #ifndef _WIN32 Region temp = XCreateRegion(); XSubtractRegion(current, r, temp); XDestroyRegion(r); XDestroyRegion(current); rstack[rstackptr] = temp; #else CombineRgn(current,current,r,RGN_DIFF); DeleteObject(r); #endif fl_restore_clip(); }
// does this rectangle intersect current clip? int Fl_Device::not_clipped(int x, int y, int w, int h) { fl_transform(x,y); // first check against the window so we get rid of coordinates // outside the 16-bit range the X/Win32 calls take: if (x+w <= 0 || y+h <= 0 || x >= Fl_Window::current()->w() || y >= Fl_Window::current()->h()) return 0; Region r = rstack[rstackptr]; if (!r) return 1; #ifndef _WIN32 return XRectInRegion(r, x, y, w, h); #else //RECT rect; //rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; //return RectInRegion(r,&rect); // The win32 API makes no distinction between partial and complete // intersection, so we have to check for partial intersection ourselves. int ret = 0; Region rr = XRectangleRegion(x,y,w,h); Region temp = CreateRectRgn(0,0,0,0); // disjoint if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { ret = 0; } // complete else if (EqualRgn(temp, rr)) { ret = 1; } // parital intersection else { ret = 2; } DeleteObject(temp); DeleteObject(rr); return ret; #endif }
void Fl_Device::curve(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) { fl_transform(x0,y0); fl_transform(x1,y1); fl_transform(x2,y2); fl_transform(x3,y3); float x = x0; float y = y0; #define MAXPOINTS 100 float points[MAXPOINTS][2]; float* p = points[0]; *p++ = float(x); *p++ = float(y); // find the area: float a = fabs((x-x2)*(y3-y1)-(y-y2)*(x3-x1)); float b = fabs((x-x3)*(y2-y1)-(y-y3)*(x2-x1)); if (b > a) a = b; // use that to guess at the number of segments: int n = int(sqrt(a)/4); if (n > 1) { if (n > MAXPOINTS-1) n = MAXPOINTS-1; float e = 1.0f/n; // calculate the coefficients of 3rd order equation: float xa = (x3-3*x2+3*x1-x); float xb = 3*(x2-2*x1+x); float xc = 3*(x1-x); // calculate the forward differences: float dx1 = ((xa*e+xb)*e+xc)*e; float dx3 = 6*xa*e*e*e; float dx2 = dx3 + 2*xb*e*e; // calculate the coefficients of 3rd order equation: float ya = (y3-3*y2+3*y1-y); float yb = 3*(y2-2*y1+y); float yc = 3*(y1-y); // calculate the forward differences: float dy1 = ((ya*e+yb)*e+yc)*e; float dy3 = 6*ya*e*e*e; float dy2 = dy3 + 2*yb*e*e; // draw points 1 .. n-2: for (int m=2; m<n; m++) { x += dx1; *p++ = x; dx1 += dx2; dx2 += dx3; y += dy1; *p++ = y; dy1 += dy2; dy2 += dy3; } // draw point n-1: *p++ = x+dx1; *p++ = y+dy1; } // draw point n: *p++ = x3; *p++ = y3; fl_transformed_vertices((p-points[0])/2, points); }
static void innards(const uchar *buf, int X, int Y, int W, int H, int delta, int linedelta, int mono, Fl_Draw_Image_Cb cb, void* userdata) { #if USE_COLORMAP char indexed = (fl_palette != 0); #endif if (!linedelta) linedelta = W*delta; int x, y, w, h; fl_clip_box(X,Y,W,H,x,y,w,h); if (w<=0 || h<=0) return; if (buf) buf += (x-X)*delta + (y-Y)*linedelta; fl_transform(x,y); fl_transform(X,Y); static U32 bmibuffer[256+12] = {0}; BITMAPINFO &bmi = *((BITMAPINFO*)bmibuffer); if (!bmi.bmiHeader.biSize) { bmi.bmiHeader.biSize = sizeof(bmi)-4; // does it use this to determine type? bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biXPelsPerMeter = 0; bmi.bmiHeader.biYPelsPerMeter = 0; bmi.bmiHeader.biClrUsed = 0; bmi.bmiHeader.biClrImportant = 0; } #if USE_COLORMAP if (indexed) { for (int i=0; i<256; i++) { *((short*)(bmi.bmiColors)+i) = i; } } else #endif if (mono) { for (int i=0; i<256; i++) { bmi.bmiColors[i].rgbBlue = i; bmi.bmiColors[i].rgbGreen = i; bmi.bmiColors[i].rgbRed = i; bmi.bmiColors[i].rgbReserved = i; } } bmi.bmiHeader.biWidth = w; #if USE_COLORMAP bmi.bmiHeader.biBitCount = mono|indexed ? 8 : 24; int pixelsize = mono|indexed ? 1 : 3; #else bmi.bmiHeader.biBitCount = mono ? 8 : 24; int pixelsize = mono ? 1 : 3; #endif int linesize = (pixelsize*w+3)&~3; static U32* buffer; int blocking = h; {int size = linesize*h; if (size > MAXBUFFER) { size = MAXBUFFER; blocking = MAXBUFFER/linesize; } static long buffer_size; if (size > buffer_size) { delete[] buffer; buffer_size = size; buffer = new U32[(size+3)/4]; }} bmi.bmiHeader.biHeight = blocking; static U32* line_buffer; if (!buf) { int size = W*delta; static int line_buf_size; if (size > line_buf_size) { delete[] line_buffer; line_buf_size = size; line_buffer = new U32[(size+3)/4]; } } for (int j=0; j<h; ) { int k; for (k = 0; j<h && k<blocking; k++, j++) { const uchar* from; if (!buf) { // run the converter: cb(userdata, x-X, y-Y+j, w, (uchar*)line_buffer); from = (uchar*)line_buffer; } else { from = buf; buf += linedelta; } uchar *to = (uchar*)buffer+(blocking-k-1)*linesize; #if USE_COLORMAP if (indexed) { if (mono) monodither(to, from, w, delta); else dither(to, from, w, delta); to += w; } else #endif if (mono) { for (int i=w; i--; from += delta) *to++ = *from; } else { for (int i=w; i--; from += delta, to += 3) { uchar r = from[0]; to[0] = from[2]; to[1] = from[1]; to[2] = r; } } } SetDIBitsToDevice(fl_gc, x, y+j-k, w, k, 0, 0, 0, k, (LPSTR)((uchar*)buffer+(blocking-k)*linesize), &bmi, #if USE_COLORMAP indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS #else DIB_RGB_COLORS #endif ); } }
// return rectangle surrounding intersection of this rectangle and clip, int Fl_Device::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) { Region r = rstack[rstackptr]; if (!r) {X = x; Y = y; W = w; H = h; return 0;} // Test against the window to get 16-bit values (this is only done if // a clip region exists as otherwise it breaks fl_push_no_clip()): int ret = 1; int dx = x; int dy = y; fl_transform(x,y); dx = x-dx; dy = y-dy; if (x < 0) { w += x; x = 0; ret = 2; } int t = Fl_Window::current()->w(); if (x+w > t) { w = t-x; ret = 2; } if (y < 0) { h += y; y = 0; ret = 2; } t = Fl_Window::current()->h(); if (y+h > t) { h = t-y; ret = 2; } // check for total clip (or for empty rectangle): if (w <= 0 || h <= 0) { W = H = 0; return 0; } #ifndef _WIN32 switch (XRectInRegion(r, x, y, w, h)) { case 0: // completely outside W = H = 0; return 0; case 1: // completely inside: X = x-dx; Y = y-dy; W = w; H = h; return ret; default: // partial: { Region rr = XRectangleRegion(x,y,w,h); Region temp = XCreateRegion(); XIntersectRegion(r, rr, temp); XRectangle rect; XClipBox(temp, &rect); X = rect.x-dx; Y = rect.y-dy; W = rect.width; H = rect.height; XDestroyRegion(temp); XDestroyRegion(rr); return 2; } } #else // The win32 API makes no distinction between partial and complete // intersection, so we have to check for partial intersection ourselves. // However, given that the regions may be composite, we have to do // some voodoo stuff... Region rr = XRectangleRegion(x,y,w,h); Region temp = CreateRectRgn(0,0,0,0); if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint W = H = 0; ret = 0; } else if (EqualRgn(temp, rr)) { // complete X = x-dx; Y = y-dy; W = w; H = h; // ret = ret } else { // parital intersection RECT rect; GetRgnBox(temp, &rect); X = rect.left-dx; Y = rect.top-dy; W = rect.right - rect.left; H = rect.bottom - rect.top; ret = 2; } DeleteObject(temp); DeleteObject(rr); return ret; #endif }