X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=otk%2Frendercontrol.cc;h=6aefb8d57c9eab8b4ce39066dbfc621d690c123b;hb=1e47e17d08d72d181edc2bde598ad246055655ad;hp=8f9329688c04c4f09fffdd9db6967f466999c947;hpb=7fe3301e7ea905a8a76d54c22751f3d8a346e28b;p=chaz%2Fopenbox diff --git a/otk/rendercontrol.cc b/otk/rendercontrol.cc index 8f932968..6aefb8d5 100644 --- a/otk/rendercontrol.cc +++ b/otk/rendercontrol.cc @@ -32,7 +32,7 @@ extern "C" { namespace otk { -RenderControl *RenderControl::getRenderControl(int screen) +RenderControl *RenderControl::createRenderControl(int screen) { // get the visual on the screen and return the correct type of RenderControl int vclass = display->screenInfo(screen)->visual()->c_class; @@ -438,62 +438,50 @@ void RenderControl::drawImage(Surface &sf, int w, int h, unsigned long *data) const { pixel32 *bg = sf.pixelData(); - int x, y, c, sfw, sfh; + int c, sfw, sfh; unsigned int i, e, bgi; sfw = sf.size().width(); sfh = sf.size().height(); - x = (sfw - w) / 2; - y = (sfh - h) / 2; - - if (x < 0) x = 0; - if (y < 0) y = 0; - - // Reduce the image size if its too big to make it fit on the surface - int oldw = w, oldh = h; - unsigned long *olddata = data; - if (w > sfw) w = sfw; - if (h > sfh) h = sfh; - unsigned long newdata[w*h]; - if (w < oldw || h < oldh) { - double dx = oldw / (double)w; - double dy = oldh / (double)h; + + if (w && h) { + // scale it + unsigned long *olddata = data; + unsigned long newdata[sfw*sfh]; + double dx = w / (double)sfw; + double dy = h / (double)sfh; double px = 0.0; double py = 0.0; int iy = 0; - for (i = 0, c = 0, e = w*h; i < e; ++i) { + for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) { newdata[i] = olddata[(int)px + iy]; - if (++c >= w) { + if (++c >= sfw) { c = 0; px = 0; py += dy; - iy = (int)py * oldw; + iy = (int)py * w; } else px += dx; } data = newdata; - } - - for (i = 0, c = 0, bgi = y * sfw + x, e = w*h; i < e; ++i, ++bgi) { - unsigned char alpha = data[i] >> 24; - unsigned char r = data[i] >> 16; - unsigned char g = data[i] >> 8; - unsigned char b = data[i]; - // background color - unsigned char bgr = bg[bgi] >> default_red_shift; - unsigned char bgg = bg[bgi] >> default_green_shift; - unsigned char bgb = bg[bgi] >> default_blue_shift; + // apply the alpha channel + for (i = 0, c = 0, e = sfw*sfh; i < e; ++i, ++bgi) { + unsigned char alpha = data[i] >> 24; + unsigned char r = data[i] >> 16; + unsigned char g = data[i] >> 8; + unsigned char b = data[i]; + + // background color + unsigned char bgr = bg[i] >> default_red_shift; + unsigned char bgg = bg[i] >> default_green_shift; + unsigned char bgb = bg[i] >> default_blue_shift; - r = bgr + (((r - bgr) * alpha) >> 8); - g = bgg + (((g - bgg) * alpha) >> 8); - b = bgb + (((b - bgb) * alpha) >> 8); + r = bgr + (((r - bgr) * alpha) >> 8); + g = bgg + (((g - bgg) * alpha) >> 8); + b = bgb + (((b - bgb) * alpha) >> 8); - bg[bgi] = (r << default_red_shift) | (g << default_green_shift) | - (b << default_blue_shift); - - if (++c >= w) { - c = 0; - bgi += sfw - w; + bg[i] = (r << default_red_shift) | (g << default_green_shift) | + (b << default_blue_shift); } } @@ -508,4 +496,68 @@ void RenderControl::drawImage(Surface &sf, int w, int h, XDestroyImage(im); } +void RenderControl::drawImage(Surface &sf, Pixmap pixmap, Pixmap mask) const +{ + int junk, sfw, sfh, w, h, depth, mw, mh, mdepth; + Window wjunk; + const ScreenInfo *info = display->screenInfo(_screen); + GC mgc = 0; + + assert(pixmap != None); + + sfw = sf.size().width(); + sfh = sf.size().height(); + + XGetGeometry(**display, pixmap, &wjunk, &junk, &junk, + (unsigned int*)&w, (unsigned int*)&h, + (unsigned int*)&junk, (unsigned int*)&depth); + if (mask != None) { + XGetGeometry(**display, mask, &wjunk, &junk, &junk, + (unsigned int*)&mw, (unsigned int*)&mh, + (unsigned int*)&junk, (unsigned int*)&mdepth); + if (mw != w || mh != h || mdepth != 1) + return; + } + + Pixmap p = XCreatePixmap(**display, info->rootWindow(), sfw, sfh, + info->depth()); + Pixmap m; + if (mask == None) + m = None; + else { + m = XCreatePixmap(**display, info->rootWindow(), sfw, sfh, 1); + XGCValues gcv; + gcv.subwindow_mode = IncludeInferiors; + gcv.graphics_exposures = false; + mgc = XCreateGC(**display, m, GCGraphicsExposures | + GCSubwindowMode, &gcv); + } + + // scale it + for (int y = sfh - 1; y >= 0; --y) { + int yy = y * h / sfh; + for (int x = sfw - 1; x >= 0; --x) { + int xx = x * w / sfw; + if (depth != info->depth()) { + XCopyPlane(**display, pixmap, p, DefaultGC(**display, _screen), + xx, yy, 1, 1, x, y, 1); + } else { + XCopyArea(**display, pixmap, p, DefaultGC(**display, _screen), + xx, yy, 1, 1, x, y); + } + if (mask != None) + XCopyArea(**display, mask, m, mgc, xx, yy, 1, 1, x, y); + } + } + + XSetClipMask(**display, DefaultGC(**display, _screen), m); + XSetClipOrigin(**display, DefaultGC(**display, _screen), 0, 0); + XCopyArea(**display, p, sf.pixmap(), DefaultGC(**display, _screen), 0, 0, + sfw, sfh, 0, 0); + XSetClipMask(**display, DefaultGC(**display, _screen), None); + + XFreePixmap(**display, p); + if (m != None) XFreePixmap(**display, m); +} + }