From 9b6e5f9cf49df78be25720f9c4b33a733b856c9b Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 18 Jan 2003 07:23:28 +0000 Subject: [PATCH] provide RenderControls to all otk from the display class. initialize them all there. try use bitshifts instead of color tables in the TrueRenderControl class for finding correct rgbs. Move the image/pixmap/xftdraw into the surface class, and it maintains them, recreating them when it resizes. --- otk/display.cc | 18 ++++++++++-- otk/display.hh | 14 +++++---- otk/focuslabel.cc | 7 ++--- otk/focuslabel.hh | 3 -- otk/font.cc | 43 +-------------------------- otk/font.hh | 12 ++++---- otk/label.cc | 7 ++--- otk/label.hh | 3 -- otk/rendercontrol.cc | 59 ++++++++++++++++++++++++++++++++----- otk/rendercontrol.hh | 12 ++++++-- otk/surface.cc | 63 +++++++++++++++++++++++++++++++++++----- otk/surface.hh | 18 ++++++++++-- otk/truerendercontrol.cc | 40 ++++++++++++------------- otk/truerendercontrol.hh | 17 ++++++----- otk/widget.cc | 6 ++-- otk/widget.hh | 1 - 16 files changed, 200 insertions(+), 123 deletions(-) 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 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 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 + // 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; 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); -- 2.39.2