diff --git a/otk/display.cc b/otk/display.cc index 0f76a1cd..8a7646b8 100644 --- a/otk/display.cc +++ b/otk/display.cc @@ -7,6 +7,7 @@ #include "display.hh" #include "screeninfo.hh" #include "gccache.hh" +#include "rendercontrol.hh" #include "util.hh" extern "C" { @@ -84,6 +85,7 @@ Display::Display() _scroll_lock_mask(0), _grab_count(0), _screenInfoList(), + _renderControlList(), _gccache((GCCache*) 0) { int junk; @@ -168,7 +170,11 @@ DISPLAY environment variable approriately.\n\n")); // Get information on all the screens which are available. _screenInfoList.reserve(ScreenCount(_display)); for (int i = 0; i < ScreenCount(_display); ++i) - _screenInfoList.push_back(ScreenInfo(i)); + _screenInfoList.push_back(i); + + _renderControlList.reserve(ScreenCount(_display)); + for (int i = 0; i < ScreenCount(_display); ++i) + _renderControlList.push_back(RenderControl::getRenderControl(i)); _gccache = new GCCache(_screenInfoList.size()); } @@ -193,7 +199,7 @@ const ScreenInfo* Display::screenInfo(int snum) const ScreenInfo* Display::findScreen(Window root) { - ScreenInfoList::iterator it, end = _screenInfoList.end(); + std::vector::iterator it, end = _screenInfoList.end(); for (it = _screenInfoList.begin(); it != end; ++it) if (it->rootWindow() == root) return &(*it); @@ -201,6 +207,14 @@ const ScreenInfo* Display::findScreen(Window root) } +const RenderControl *Display::renderControl(int snum) +{ + assert(snum >= 0); + assert(snum < (signed) _renderControlList.size()); + return _renderControlList[snum]; +} + + void Display::grab() { if (_grab_count == 0) diff --git a/otk/display.hh b/otk/display.hh index 5f658cd3..9402a8e7 100644 --- a/otk/display.hh +++ b/otk/display.hh @@ -12,6 +12,7 @@ namespace otk { class ScreenInfo; class GCCache; +class RenderControl; class Display; @@ -21,10 +22,6 @@ extern Display *display; //! Manages a single X11 display. class Display { -public: - //! A List of ScreenInfo instances - typedef std::vector ScreenInfoList; - private: //! The X display ::Display *_display; @@ -57,7 +54,11 @@ private: int _grab_count; //! A list of information for all screens on the display - ScreenInfoList _screenInfoList; + std::vector _screenInfoList; + + //! A list of RenderControl objects, which are used for all graphics on a + //! screen + std::vector _renderControlList; //! A cache for re-using GCs, used by the drawing objects /*! @@ -100,6 +101,9 @@ public: //! Find a ScreenInfo based on a root window const ScreenInfo* findScreen(Window root); + //! Gets the RenderControl for a screen + const RenderControl *renderControl(int snum); + //! Returns if the display has the xkb extension available inline bool xkb() const { return _xkb; } //! Returns the xkb extension's event base diff --git a/otk/focuslabel.cc b/otk/focuslabel.cc index b1b8c764..eed535c3 100644 --- a/otk/focuslabel.cc +++ b/otk/focuslabel.cc @@ -13,14 +13,10 @@ namespace otk { FocusLabel::FocusLabel(Widget *parent) : FocusWidget(parent), _text("") { - const ScreenInfo *info = display->screenInfo(screen()); - _xftdraw = XftDrawCreate(**display, window(), info->visual(), - info->colormap()); } FocusLabel::~FocusLabel() { - XftDrawDestroy(_xftdraw); } @@ -72,7 +68,8 @@ void FocusLabel::update(void) FocusWidget::update(); - ft->drawString(_xftdraw, x, 0, *text_color, t); + display->renderControl(_screen)-> + drawString(this, *ft, x, 0, *text_color, t); } else FocusWidget::update(); } diff --git a/otk/focuslabel.hh b/otk/focuslabel.hh index ea9f9b66..9fc5f590 100644 --- a/otk/focuslabel.hh +++ b/otk/focuslabel.hh @@ -3,7 +3,6 @@ #define __label_hh #include "focuswidget.hh" -#include "font.hh" namespace otk { @@ -22,8 +21,6 @@ public: virtual void setStyle(Style *style); private: - //! Object used by Xft to render to the drawable - XftDraw *_xftdraw; //! Text displayed in the label ustring _text; }; diff --git a/otk/font.cc b/otk/font.cc index a38946f0..21b9bfb0 100644 --- a/otk/font.cc +++ b/otk/font.cc @@ -14,9 +14,9 @@ extern "C" { #include #include "font.hh" +#include "surface.hh" #include "util.hh" #include "display.hh" -#include "color.hh" #include "screeninfo.hh" extern "C" { @@ -82,47 +82,6 @@ Font::~Font(void) } -void Font::drawString(XftDraw *d, int x, int y, const Color &color, - const ustring &string) const -{ - assert(d); - - if (_shadow) { - XftColor c; - c.color.red = 0; - c.color.green = 0; - c.color.blue = 0; - c.color.alpha = _tint | _tint << 8; // transparent shadow - c.pixel = BlackPixel(**display, _screen_num); - - if (string.utf8()) - XftDrawStringUtf8(d, &c, _xftfont, x + _offset, - _xftfont->ascent + y + _offset, - (FcChar8*)string.c_str(), string.bytes()); - else - XftDrawString8(d, &c, _xftfont, x + _offset, - _xftfont->ascent + y + _offset, - (FcChar8*)string.c_str(), string.bytes()); - } - - XftColor c; - c.color.red = color.red() | color.red() << 8; - c.color.green = color.green() | color.green() << 8; - c.color.blue = color.blue() | color.blue() << 8; - c.pixel = color.pixel(); - c.color.alpha = 0xff | 0xff << 8; // no transparency in Color yet - - if (string.utf8()) - XftDrawStringUtf8(d, &c, _xftfont, x, _xftfont->ascent + y, - (FcChar8*)string.c_str(), string.bytes()); - else - XftDrawString8(d, &c, _xftfont, x, _xftfont->ascent + y, - (FcChar8*)string.c_str(), string.bytes()); - - return; -} - - unsigned int Font::measureString(const ustring &string) const { XGlyphInfo info; diff --git a/otk/font.hh b/otk/font.hh index dcff6526..afc36dea 100644 --- a/otk/font.hh +++ b/otk/font.hh @@ -3,6 +3,7 @@ #define __font_hh #include "ustring.hh" +#include "truerendercontrol.hh" extern "C" { #include @@ -15,6 +16,7 @@ extern "C" { namespace otk { class Color; +class Surface; class Font { /* @@ -60,13 +62,9 @@ public: unsigned int measureString(const ustring &string) const; - //! Draws a string into an XftDraw object - /*! - Be Warned: If you use an XftDraw object and a color, or a font from - different screens, you WILL have unpredictable results! :) - */ - void drawString(XftDraw *d, int x, int y, const Color &color, - const ustring &string) const; + // The RenderControl classes use the internal data to render the fonts, but + // noone else needs it, so its private. + friend class RenderControl; }; } diff --git a/otk/label.cc b/otk/label.cc index da9edfd1..2d8b9442 100644 --- a/otk/label.cc +++ b/otk/label.cc @@ -11,14 +11,10 @@ namespace otk { Label::Label(Widget *parent) : Widget(parent), _text("") { - const ScreenInfo *info = display->screenInfo(screen()); - _xftdraw = XftDrawCreate(**display, window(), info->visual(), - info->colormap()); } Label::~Label() { - XftDrawDestroy(_xftdraw); } void Label::setStyle(Style *style) @@ -66,7 +62,8 @@ void Label::update(void) Widget::update(); - ft->drawString(_xftdraw, x, 0, *style()->getTextUnfocus(), t); + display->renderControl(_screen)-> + drawString(this, *ft, x, 0, *style()->getTextUnfocus(), t); } else Widget::update(); } diff --git a/otk/label.hh b/otk/label.hh index ad938f10..e52c34f4 100644 --- a/otk/label.hh +++ b/otk/label.hh @@ -3,7 +3,6 @@ #define __label_hh #include "widget.hh" -#include "font.hh" namespace otk { @@ -22,8 +21,6 @@ public: virtual void setStyle(Style *style); private: - //! Object used by Xft to render to the drawable - XftDraw *_xftdraw; //! Text displayed in the label ustring _text; }; diff --git a/otk/rendercontrol.cc b/otk/rendercontrol.cc index 479de3d9..ef49f7e1 100644 --- a/otk/rendercontrol.cc +++ b/otk/rendercontrol.cc @@ -9,6 +9,10 @@ #include "rendertexture.hh" #include "display.hh" #include "screeninfo.hh" +#include "surface.hh" +#include "color.hh" +#include "font.hh" +#include "ustring.hh" extern "C" { #ifdef HAVE_STDLIB_H @@ -23,19 +27,17 @@ namespace otk { RenderControl *RenderControl::getRenderControl(int screen) { - const ScreenInfo *info = display->screenInfo(screen); - // get the visual on the screen and return the correct type of RenderControl - int vclass = info->visual()->c_class; + int vclass = display->screenInfo(screen)->visual()->c_class; switch (vclass) { case TrueColor: - return new TrueRenderControl(info); + return new TrueRenderControl(screen); case PseudoColor: case StaticColor: -// return new PseudoRenderControl(info); +// return new PseudoRenderControl(screen); case GrayScale: case StaticGray: -// return new GrayRenderControl(info); +// return new GrayRenderControl(screen); default: printf(_("RenderControl: Unsupported visual %d specified. Aborting.\n"), vclass); @@ -43,7 +45,7 @@ RenderControl *RenderControl::getRenderControl(int screen) } } -RenderControl::RenderControl(const ScreenInfo *screen) +RenderControl::RenderControl(int screen) : _screen(screen) { printf("Initializing RenderControl\n"); @@ -58,4 +60,47 @@ RenderControl::~RenderControl() } +void RenderControl::drawString(Surface *sf, const Font &font, int x, int y, + const Color &color, const ustring &string) const +{ + assert(sf); + assert(sf->_screen == _screen); + XftDraw *d = sf->_xftdraw; + assert(d); + + if (font._shadow) { + XftColor c; + c.color.red = 0; + c.color.green = 0; + c.color.blue = 0; + c.color.alpha = font._tint | font._tint << 8; // transparent shadow + c.pixel = BlackPixel(**display, _screen); + + if (string.utf8()) + XftDrawStringUtf8(d, &c, font._xftfont, x + font._offset, + font._xftfont->ascent + y + font._offset, + (FcChar8*)string.c_str(), string.bytes()); + else + XftDrawString8(d, &c, font._xftfont, x + font._offset, + font._xftfont->ascent + y + font._offset, + (FcChar8*)string.c_str(), string.bytes()); + } + + XftColor c; + c.color.red = color.red() | color.red() << 8; + c.color.green = color.green() | color.green() << 8; + c.color.blue = color.blue() | color.blue() << 8; + c.pixel = color.pixel(); + c.color.alpha = 0xff | 0xff << 8; // no transparency in Color yet + + if (string.utf8()) + XftDrawStringUtf8(d, &c, font._xftfont, x, font._xftfont->ascent + y, + (FcChar8*)string.c_str(), string.bytes()); + else + XftDrawString8(d, &c, font._xftfont, x, font._xftfont->ascent + y, + (FcChar8*)string.c_str(), string.bytes()); + + return; +} + } diff --git a/otk/rendercontrol.hh b/otk/rendercontrol.hh index 37119846..a512060f 100644 --- a/otk/rendercontrol.hh +++ b/otk/rendercontrol.hh @@ -12,10 +12,13 @@ namespace otk { class ScreenInfo; class Surface; class RenderTexture; +class Font; +class Color; +class ustring; class RenderControl { protected: - const ScreenInfo *_screen; + int _screen; /* // color tables, meaning, 256 (possibly) different shades of each color, @@ -58,13 +61,18 @@ protected: int _ncolors; */ - RenderControl(const ScreenInfo *screen); + RenderControl(int screen); public: virtual ~RenderControl(); static RenderControl *getRenderControl(int screen); + //! Draws a string onto a Surface + virtual void drawString(Surface *sf, const Font &font, int x, int y, + const Color &color, const ustring &string) const; + + //! Draws a background onto a Surface, as specified by a RenderTexture virtual void drawBackground(Surface *sf, const RenderTexture &texture) const = 0; }; diff --git a/otk/surface.cc b/otk/surface.cc index cea793f2..c02526f3 100644 --- a/otk/surface.cc +++ b/otk/surface.cc @@ -6,29 +6,78 @@ #include "surface.hh" #include "display.hh" +#include "screeninfo.hh" + +extern "C" { +#include +} namespace otk { -Surface::Surface() - : _size(1, 1), - _pm(None) +Surface::Surface(int screen) + : _screen(screen), + _size(1, 1), + _im(0), + _pm(None), + _xftdraw(0) { + createObjects(); } -Surface::Surface(const Point &size) - : _size(size), - _pm(None) +Surface::Surface(int screen, const Point &size) + : _screen(screen), + _size(size), + _im(0), + _pm(None), + _xftdraw(0) { + createObjects(); } Surface::~Surface() { - if (_pm != None) XFreePixmap(**display, _pm); + destroyObjects(); +} + +void Surface::createObjects() +{ + assert(!_im); assert(_pm == None); assert(!_xftdraw); + + const ScreenInfo *info = display->screenInfo(_screen); + + _im = XCreateImage(**display, info->visual(), info->depth(), + ZPixmap, 0, NULL, _size.x(), _size.y(), 32, 0); + + _pm = XCreatePixmap(**display, info->rootWindow(), _size.x(), _size.y(), + info->depth()); + + _xftdraw = XftDrawCreate(**display, _pm, info->visual(), info->colormap()); +} + +void Surface::destroyObjects() +{ + assert(_im); assert(_pm != None); assert(_xftdraw); + + // do the delete ourselves cuz we alloc it with new not malloc + delete [] _im->data; + _im->data = NULL; + XDestroyImage(_im); + _im = 0; + + XFreePixmap(**display, _pm); + _pm = None; + + XftDrawDestroy(_xftdraw); + _xftdraw = 0; } void Surface::setSize(int w, int h) { + if (w == _size.x() && h == _size.y()) return; // no change + _size.setPoint(w, h); + destroyObjects(); + createObjects(); } } diff --git a/otk/surface.hh b/otk/surface.hh index b027f796..53738128 100644 --- a/otk/surface.hh +++ b/otk/surface.hh @@ -7,28 +7,42 @@ extern "C" { #include +#define _XFT_NO_COMPAT_ // no Xft 1 API +#include } namespace otk { -class Surface { - Point _size; - Pixmap _pm; +class ScreenInfo; +class Surface { + int _screen; + Point _size; + XImage *_im; + Pixmap _pm; + XftDraw *_xftdraw; + + void createObjects(); + void destroyObjects(); + protected: - Surface(); - Surface(const Point &size); + Surface(int screen); + Surface(int screen, const Point &size); virtual void setSize(int w, int h); public: virtual ~Surface(); + inline int screen(void) const { return _screen; } virtual const Point& size() const { return _size; } virtual int width() const { return _size.x(); } virtual int height() const { return _size.y(); } virtual Pixmap pixmap() const { return _pm; } // TEMP + // The RenderControl classes use the internal objects in this class to render + // to it. Noone else needs them tho, so they are private. + friend class RenderControl; friend class TrueRenderControl; }; diff --git a/otk/truerendercontrol.cc b/otk/truerendercontrol.cc index a1995c4c..74dd057d 100644 --- a/otk/truerendercontrol.cc +++ b/otk/truerendercontrol.cc @@ -20,7 +20,7 @@ extern "C" { namespace otk { -TrueRenderControl::TrueRenderControl(const ScreenInfo *screen) +TrueRenderControl::TrueRenderControl(int screen) : RenderControl(screen), _red_offset(0), _green_offset(0), @@ -28,12 +28,13 @@ TrueRenderControl::TrueRenderControl(const ScreenInfo *screen) { printf("Initializing TrueColor RenderControl\n"); + Visual *visual = display->screenInfo(_screen)->visual(); unsigned long red_mask, green_mask, blue_mask; // find the offsets for each color in the visual's masks - red_mask = screen->visual()->red_mask; - green_mask = screen->visual()->green_mask; - blue_mask = screen->visual()->blue_mask; + red_mask = visual->red_mask; + green_mask = visual->green_mask; + blue_mask = visual->blue_mask; while (! (red_mask & 1)) { _red_offset++; red_mask >>= 1; } while (! (green_mask & 1)) { _green_offset++; green_mask >>= 1; } @@ -52,6 +53,7 @@ TrueRenderControl::~TrueRenderControl() } + static inline void renderPixel(XImage *im, unsigned char *dp, unsigned long pixel) { @@ -102,34 +104,28 @@ void TrueRenderControl::drawBackground(Surface *sf, assert(sf); int w = sf->width(), h = sf->height(); - - XImage *im = XCreateImage(**display, _screen->visual(), _screen->depth(), - ZPixmap, 0, NULL, w, h, 32, 0); + XImage *im = sf->_im; + Pixmap pm = sf->_pm; + assert(im); assert(pm != None); unsigned char *data = new unsigned char[im->bytes_per_line * h]; unsigned char *dp = data; + unsigned int bytes_per_pixel = im->bits_per_pixel/8; for (int y = 0; y < h/3; ++y) - for (int x = 0; x < w; ++x, dp += im->bits_per_pixel/8) - renderPixel(im, dp, (255*x/w) << _red_offset << _red_shift); + for (int x = 0; x < w; ++x, dp += bytes_per_pixel) + renderPixel(im, dp, (255*x/w) >> _red_shift << _red_offset); for (int y = 0; y < h/3; ++y) - for (int x = 0; x < w; ++x, dp += im->bits_per_pixel/8) - renderPixel(im, dp, (255*x/w) << _green_offset << _green_shift); + for (int x = 0; x < w; ++x, dp += bytes_per_pixel) + renderPixel(im, dp, (255*x/w) >> _green_shift << _green_offset); for (int y = 0; y < h/3; ++y) - for (int x = 0; x < w; ++x, dp += im->bits_per_pixel/8) - renderPixel(im, dp, (255*x/w) << _blue_offset << _blue_shift); + for (int x = 0; x < w; ++x, dp += bytes_per_pixel) + renderPixel(im, dp, (255*x/w) >> _blue_shift << _blue_offset); im->data = (char*) data; - if (!sf->_pm) - sf->_pm = XCreatePixmap(**display, _screen->rootWindow(), w, h, - _screen->depth()); - XPutImage(**display, sf->_pm, DefaultGC(**display, _screen->screen()), - im, 0, 0, 0, 0, w, h); - - //delete [] image->data; - //image->data = NULL; - XDestroyImage(im); + XPutImage(**display, pm, DefaultGC(**display, _screen), + sf->_im, 0, 0, 0, 0, w, h); } } diff --git a/otk/truerendercontrol.hh b/otk/truerendercontrol.hh index dfa0aa34..bd6d80af 100644 --- a/otk/truerendercontrol.hh +++ b/otk/truerendercontrol.hh @@ -4,24 +4,25 @@ #include "rendercontrol.hh" +#include + namespace otk { class TrueRenderControl : public RenderControl { private: + // the number of bits to shift a color value (from 0-255) to the right, to + // fit it into the the color mask (do this before the offset) + int _red_shift; + int _green_shift; + int _blue_shift; + // the offset of each color in a color mask int _red_offset; int _green_offset; int _blue_offset; - // the number of bits to shift a color value (from 0-255) to fit it into the - // the color mask - int _red_shift; - int _green_shift; - int _blue_shift; - - public: - TrueRenderControl(const ScreenInfo *screen); + TrueRenderControl(int screen); virtual ~TrueRenderControl(); virtual void drawBackground(Surface *sf, const RenderTexture &texture) const; diff --git a/otk/widget.cc b/otk/widget.cc index 551a7900..dc4cfa2e 100644 --- a/otk/widget.cc +++ b/otk/widget.cc @@ -15,7 +15,8 @@ namespace otk { Widget::Widget(Widget *parent, Direction direction) - : EventHandler(), + : Surface(parent->screen()), + EventHandler(), _dirty(false), _focused(false), _parent(parent), _style(parent->style()), _direction(direction), _cursor(parent->cursor()), _bevel_width(parent->bevelWidth()), @@ -37,7 +38,8 @@ Widget::Widget(Widget *parent, Direction direction) Widget::Widget(EventDispatcher *event_dispatcher, Style *style, Direction direction, Cursor cursor, int bevel_width, bool override_redirect) - : EventHandler(), + : Surface(style->getScreen()), + EventHandler(), _dirty(false),_focused(false), _parent(0), _style(style), _direction(direction), _cursor(cursor), _bevel_width(bevel_width), _ignore_config(0), _visible(false), diff --git a/otk/widget.hh b/otk/widget.hh index 1cfa627f..33c6e99f 100644 --- a/otk/widget.hh +++ b/otk/widget.hh @@ -42,7 +42,6 @@ public: inline Window window(void) const { return _window; } inline const Widget *parent(void) const { return _parent; } inline const WidgetList &children(void) const { return _children; } - inline unsigned int screen(void) const { return _screen; } inline Rect rect(void) const { return Rect(_pos, size()); } void move(const Point &to);