From 83cd5b0ba2c4264ce24b9972814ad2cdc71057e5 Mon Sep 17 00:00:00 2001 From: Casper Boemann Date: Fri, 15 Jun 2007 20:11:33 +0000 Subject: [PATCH] Import Oxygen windec into kdebase svn path=/trunk/KDE/kdebase/workspace/; revision=676051 --- clients/oxygen/CMakeLists.txt | 49 + clients/oxygen/README - config | 83 ++ clients/oxygen/animation.cpp | 668 +++++++++++++ clients/oxygen/debug.h | 127 +++ clients/oxygen/drawcomplexcontrol.cpp | 625 ++++++++++++ clients/oxygen/drawcontrol.cpp | 1311 +++++++++++++++++++++++++ clients/oxygen/drawprimitive.cpp | 858 ++++++++++++++++ clients/oxygen/dynamicbrush.cpp | 1190 ++++++++++++++++++++++ clients/oxygen/dynamicbrush.h | 115 +++ clients/oxygen/genpixmaps.cpp | 521 ++++++++++ clients/oxygen/gradients.cpp | 341 +++++++ clients/oxygen/inlinehelp.cpp | 199 ++++ clients/oxygen/makros.h | 29 + clients/oxygen/oxrender.cpp | 220 +++++ clients/oxygen/oxrender.h | 61 ++ clients/oxygen/oxygen.cpp | 1226 +++++++++++++++++++++++ clients/oxygen/oxygen.h | 363 +++++++ clients/oxygen/oxygen.pro | 13 + clients/oxygen/oxygen.qrc | 7 + clients/oxygen/oxygen.themerc | 22 + clients/oxygen/pixelmetric.cpp | 203 ++++ clients/oxygen/qrc_oxygen.cpp | 1213 +++++++++++++++++++++++ clients/oxygen/qsubcmetrics.cpp | 520 ++++++++++ clients/oxygen/sizefromcontents.cpp | 168 ++++ clients/oxygen/stdpix.cpp | 185 ++++ clients/oxygen/stylehint.cpp | 152 +++ clients/oxygen/t_render1.cpp | 81 ++ clients/oxygen/tileset.cpp | 650 ++++++++++++ clients/oxygen/tileset.h | 121 +++ 29 files changed, 11321 insertions(+) create mode 100644 clients/oxygen/CMakeLists.txt create mode 100644 clients/oxygen/README - config create mode 100644 clients/oxygen/animation.cpp create mode 100644 clients/oxygen/debug.h create mode 100644 clients/oxygen/drawcomplexcontrol.cpp create mode 100644 clients/oxygen/drawcontrol.cpp create mode 100644 clients/oxygen/drawprimitive.cpp create mode 100644 clients/oxygen/dynamicbrush.cpp create mode 100644 clients/oxygen/dynamicbrush.h create mode 100644 clients/oxygen/genpixmaps.cpp create mode 100644 clients/oxygen/gradients.cpp create mode 100644 clients/oxygen/inlinehelp.cpp create mode 100644 clients/oxygen/makros.h create mode 100644 clients/oxygen/oxrender.cpp create mode 100644 clients/oxygen/oxrender.h create mode 100644 clients/oxygen/oxygen.cpp create mode 100644 clients/oxygen/oxygen.h create mode 100644 clients/oxygen/oxygen.pro create mode 100644 clients/oxygen/oxygen.qrc create mode 100644 clients/oxygen/oxygen.themerc create mode 100644 clients/oxygen/pixelmetric.cpp create mode 100644 clients/oxygen/qrc_oxygen.cpp create mode 100644 clients/oxygen/qsubcmetrics.cpp create mode 100644 clients/oxygen/sizefromcontents.cpp create mode 100644 clients/oxygen/stdpix.cpp create mode 100644 clients/oxygen/stylehint.cpp create mode 100644 clients/oxygen/t_render1.cpp create mode 100644 clients/oxygen/tileset.cpp create mode 100644 clients/oxygen/tileset.h diff --git a/clients/oxygen/CMakeLists.txt b/clients/oxygen/CMakeLists.txt new file mode 100644 index 0000000000..fce6546586 --- /dev/null +++ b/clients/oxygen/CMakeLists.txt @@ -0,0 +1,49 @@ +project(kstyle-oxygen) + +########### next target ############### + +set( oxygen_SRCS + oxygen.cpp + tileset.cpp + stylehint.cpp + sizefromcontents.cpp + qsubcmetrics.cpp + pixelmetric.cpp + stdpix.cpp + drawcomplexcontrol.cpp + drawcontrol.cpp + drawprimitive.cpp + dynamicbrush.cpp + oxrender.cpp + ) + +qt4_add_resources(oxygen.qrc oxygen.qrc) + +kde4_automoc( ${oxygen_SRCS} ) +kde4_add_plugin(kstyle-oxygen ${oxygen_SRCS} ) + +# TODO: check if too much definitions. +target_link_libraries( kstyle-oxygen + ${KDE4_KDECORE_LIBS} + ${QT_QT3SUPPORT_LIBRARY} + ${QT_QTOPENGL_LIBRARY} + ${KDE4_KDEFX_LIBS} + ${X11_X11_LIB} + ${X11_Xfixes_LIB} + ${X11_Xcursor_LIB} + ${X11_Xinerama_LIB} + ${X11_Xrender_LIB} + ${X11_Xrandr_LIB} + ${X11_XTest_LIB} + ${X11_LIBRARIES} +# freetype +# fontconfig + GLU GL +) + +install( TARGETS kstyle-oxygen DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/styles/ ) + +########### install files ############### + +install( FILES oxygen.themerc DESTINATION ${DATA_INSTALL_DIR}/kstyle/themes ) + diff --git a/clients/oxygen/README - config b/clients/oxygen/README - config new file mode 100644 index 0000000000..489ed7a916 --- /dev/null +++ b/clients/oxygen/README - config @@ -0,0 +1,83 @@ +# NOTE: The file is ready-to-use. You can just copy it to ~/.config/Oxygen/Style.conf. + +# Config file path: +# ~/.config/Oxygen/Style.conf + +# style section: (with def. values) + +[Style] +# controls the way the huge bg pixmaps (BackgroundMode=3) are created +# 0: No acceleration, the pixmap is fetched from a daemon "oxygenPP" that MUST be running if you wanna use this (maybe removed) +# 1: the QGradient classes are used (afaics pure software) - slow +# 2: XRender, *use this*, currently the fastest and in matters of color best adjusted function +# 3: OpenGL, currently too dark - slow as long as we don't have HW for gl_ext_pixmap_from_texture... +Acceleration=2 + +# the background appereance +# 0: plain color +# 1: the beloved scanlines - don't argue, they'll stay ;) +# 2: [reserved] +# 3: complex lights (i.e. huge pixmap with several gradients, see above) +# 4: Simple gradient that brightens on the upper and darkens on the lower end (fallback suggestion 1, alphablending can be cached) +# 5: Simple gradient that darkens on left and right side +# 6: The window vertically brightens to the center +# 7: The window horizontally brightens to the center (like Apples Brushed Metal, fallback suggestion 2, requires realtime alphablending) +BackgroundMode=3 + +# 0: X +# 1: V +# 2: O +CheckType=0 + +# do you like glass/gloss? +Aqua=true + +# invert (sink) normal buttons etc by default +InverseButtons=false + +# not fully supportes yet, don't try values < 1 here (if you want a stable desktop ;) +Scale=1.0 + +# whether there shall be unstylish icons in popupmenus +ShowMenuIcons=false + +# affects the scanlines +# 0: scanlines +# 1: checkboard +# 2: should have been bricks, looks crap ;P +Structure=0 + +# the color roles to use for various elements, the counter color is autocalculated +# WindowText: 0 +# Window: 10 +# Base: 9 +# Text: 6 +# Button: 1 +# ButtonText: 8 +# Highlight: 12 +# HighlightedText: 13 + +# all buttons, colored parts of combos, sliders (in scrollbars as well) +role_button=10 +role_buttonHover=1 +# popup menus (also for non editable combos), menubar highlight +role_popup=10 +# the progressbar +role_progress=10 +role_progressGroove=0 +# tabwidget header +role_tab=1 + +# the way of tabblending +# 0: Jump +# 1: CrossFade +# 2: ScanlineBlend +# 3: SlideIn +# 4: SlideOut +# 5: RollIn +# 6: RollOut +# 7: OpenVertically +# 8: CloseVertically +# 9: OpenHorizontally +# 10: CloseHorizontally +TabTransition=1 diff --git a/clients/oxygen/animation.cpp b/clients/oxygen/animation.cpp new file mode 100644 index 0000000000..cb67126c70 --- /dev/null +++ b/clients/oxygen/animation.cpp @@ -0,0 +1,668 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "oxrender.h" + +#define ANIMATIONS (activeTabs + progressbars.count() + \ +hoverWidgets.count() + complexHoverWidgets.count() + indexedHoverWidgets.count()) + +#define startTimer if (!timer->isActive()) timer->start(50) + +bool TabAnimInfo::eventFilter( QObject* object, QEvent* event ) { + if (event->type() != QEvent::Paint || !animStep) + return false; + QPainter p((QWidget*)object); + p.drawPixmap(0,0, tabPix[2]); + p.end(); + return true; +} + +// QPixmap::grabWidget(.) currently fails on the background offset, +// so we use our own implementation +//TODO: fix scrollareas (the scrollbars aren't painted, so check for availability and usage...) +QPixmap grabWidget(QWidget * root) { + if (!root) + return QPixmap(); + + QPixmap pix(root->size()); + QPoint zero(0,0); + QPainter p(&pix); + const QBrush bg = root->palette().brush(root->backgroundRole()); + if (bg.style() == Qt::TexturePattern) + p.drawTiledPixmap(root->rect(), bg.texture(), root->mapTo(root->topLevelWidget(), zero)); + else + p.fillRect(root->rect(), bg); + p.end(); + + QList widgets = root->findChildren(); + + // resizing (in case) + if (root->testAttribute(Qt::WA_PendingResizeEvent) || + !root->testAttribute(Qt::WA_WState_Created)) { + QResizeEvent e(root->size(), QSize()); + QApplication::sendEvent(root, &e); + } + foreach (QWidget *w, widgets) { + if (root->testAttribute(Qt::WA_PendingResizeEvent) || + !root->testAttribute(Qt::WA_WState_Created)) { + QResizeEvent e(w->size(), QSize()); + QApplication::sendEvent(w, &e); + } + } + + // painting + QPainter::setRedirected( root, &pix ); + QPaintEvent e = QPaintEvent(QRect(zero, root->size())); + QCoreApplication::sendEvent(root, &e); + QPainter::restoreRedirected(root); + + foreach (QWidget *w, widgets) { + if (w->isVisibleTo(root)) { + if (w->autoFillBackground()) { + const QBrush bg = w->palette().brush(w->backgroundRole()); + QPainter p(&pix); + QRect wrect = QRect(zero, w->size()).translated(w->mapTo(root, zero)); + if (bg.style() == Qt::TexturePattern) + p.drawTiledPixmap(wrect, bg.texture(), w->mapTo(root->topLevelWidget(), zero)); + else + p.fillRect(wrect, bg); + p.end(); + } + QPainter::setRedirected( w, &pix, -w->mapTo(root, zero) ); + e = QPaintEvent(QRect(zero, w->size())); + QCoreApplication::sendEvent(w, &e); + QPainter::restoreRedirected(w); + } + } + + return pix; +} + +static QHash progressbars; +typedef QHash HoverFades; +static HoverFades hoverWidgets; +typedef QHash ComplexHoverFades; +static ComplexHoverFades complexHoverWidgets; +typedef QHash IndexedFades; +static IndexedFades indexedHoverWidgets; +static QHash tabwidgets; +static int activeTabs = 0; + +// --- ProgressBars -------------------- +void OxygenStyle::updateProgressbars() { + if (progressbars.isEmpty()) + return; + //Update the registered progressbars. + QHash::iterator iter; + QProgressBar *pb; + animationUpdate = true; + for (iter = progressbars.begin(); iter != progressbars.end(); iter++) { + if ( !qobject_cast(iter.key()) ) + continue; + pb = (QProgressBar*)(iter.key()); + if (pb->paintingActive() || !pb->isVisible() || + !(pb->value() > pb->minimum()) || !(pb->value() < pb->maximum())) + continue; +// int mod = (pb->orientation() == Qt::Horizontal) ? +// (pb->height()-dpi.$8)*2 : +// (pb->width()-dpi.$6)*2; +// if (!mod) +// continue; +// ++iter.value(); +// if (mod) +// iter.value() %= mod; + if (iter.value() % 2) { // odd - fade out + iter.value() -= 2; + if (iter.value() < 4) // == 3 + ++iter.value(); // 4 + if ((iter.value()+1) % 4) // save some cycles... + continue; + } + else { //fade in + iter.value() += 2; + if (iter.value() > 39) // == 40 + ++iter.value(); // 41 + if (iter.value() % 4) // save some cycles... + continue; + } + pb->repaint(pb->rect().adjusted(dpi.$3,dpi.$4,-dpi.$3,-dpi.$5)); + } + animationUpdate = false; +} + +int OxygenStyle::progressStep(const QWidget *w) const { + return progressbars.value(const_cast(w),0); +} + +void OxygenStyle::progressbarDestroyed(QObject* obj) { + progressbars.remove(static_cast(obj)); + if (!ANIMATIONS) timer->stop(); +} + +// --- TabWidgets -------------------- +void OxygenStyle::tabChanged(int index) { + if (config.tabTransition == Jump) return; // ugly nothing ;) + QTabWidget* tw = (QTabWidget*)sender(); + QHash::iterator i = tabwidgets.find(tw); + if (i == tabwidgets.end()) // this tab isn't handled for some reason? + return; + + TabAnimInfo* tai = i.value(); + + QWidget *ctw = tw->widget(tai->lastTab); + tai->lastTab = index; + if (!ctw) + return; + tai->tabPix[0] = /*QPixmap::*/grabWidget(ctw); + + ctw = tw->currentWidget(); + if (!ctw) { + tai->tabPix[0] = QPixmap(); + return; + } + tai->tabPix[1] = /*QPixmap::*/grabWidget(ctw); + tai->tabPix[2] = tai->tabPix[0]; + + tai->animStep = 6; + // TAB Transitions, NOTE, I'm using a bit X11 code here as this prevents deep pixmap + // copies that are sometimes not necessary + // TODO make an - ifdef'd ? - qt version for other platforms + switch (config.tabTransition) { + case CrossFade: + OXRender::blend(tai->tabPix[1], tai->tabPix[2], 0.1666); + break; + case SlideIn: { + //TODO handle different bar positions + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, 6*tai->tabPix[1].height()/7, + tai->tabPix[1].width(), tai->tabPix[1].height()/7, 0, 0 ); + XFreeGC ( dpy , gc ); + break; + } + case SlideOut: { + tai->tabPix[2] = tai->tabPix[1]; + //TODO handle different bar positions + QPainter p(&tai->tabPix[2]); + p.drawPixmap(0,0,tai->tabPix[0],0,tai->tabPix[0].height()/7,tai->tabPix[0].width(),6*tai->tabPix[0].height()/7); + break; + } + case RollOut: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int h = tai->tabPix[1].height()/7; + int y = (tai->tabPix[1].height()-h)/2; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, y, tai->tabPix[1].width(), h, 0, y ); + XFreeGC ( dpy , gc ); + break; + } + case RollIn: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int h = tai->tabPix[1].height()/14; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, 0, tai->tabPix[1].width(), h, 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, tai->tabPix[1].height()-h, tai->tabPix[1].width(), h, + 0, tai->tabPix[1].height()-h ); + XFreeGC ( dpy , gc ); + break; + } + case CloseVertically: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int h = tai->tabPix[1].height()/14; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, tai->tabPix[1].height()/2-h, tai->tabPix[1].width(), h, 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, tai->tabPix[1].height()/2, tai->tabPix[1].width(), h, + 0, tai->tabPix[1].height()-h ); + XFreeGC ( dpy , gc ); + break; + } + case OpenVertically: { + tai->tabPix[2] = tai->tabPix[1]; + QPainter p(&tai->tabPix[2]); + int h = 6*tai->tabPix[0].height()/14; + p.drawPixmap(0,0,tai->tabPix[0],0,tai->tabPix[0].height()/2-h, + tai->tabPix[0].width(),h); + p.drawPixmap(0,tai->tabPix[0].height()-h,tai->tabPix[0], + 0,tai->tabPix[0].height()/2,tai->tabPix[0].width(),h); + break; + } + case CloseHorizontally: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int w = tai->tabPix[1].width()/14; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + tai->tabPix[1].width()/2-w, 0, w, tai->tabPix[1].height(), 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + tai->tabPix[1].width()/2, 0, w, tai->tabPix[1].height(), + tai->tabPix[1].width()-w, 0 ); + XFreeGC ( dpy , gc ); + break; + } + case OpenHorizontally: { + tai->tabPix[2] = tai->tabPix[1]; + QPainter p(&tai->tabPix[2]); + int w = 6*tai->tabPix[0].width()/14; + p.drawPixmap(0,0,tai->tabPix[0],tai->tabPix[0].width()/2-w,0, + w,tai->tabPix[0].height()); + p.drawPixmap(tai->tabPix[0].width()-w,0,tai->tabPix[0], + tai->tabPix[0].width()/2,0,w,tai->tabPix[0].height()); + break; + } + case ScanlineBlend: + default: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + for (int i = 6; i < tai->tabPix[2].height(); i+=6) + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, i, tai->tabPix[1].width(), 1, 0, i ); + XFreeGC ( dpy , gc ); + } + } + ctw->parentWidget()->installEventFilter(tai); + _BLOCKEVENTS_(ctw); + QList widgets = ctw->findChildren(); + foreach(QWidget *widget, widgets) { + _BLOCKEVENTS_(widget); + if (widget->autoFillBackground()) { + tai->autofillingWidgets.append(widget); + widget->setAutoFillBackground(false); + } + } + ctw->repaint(); + startTimer; +} + +void OxygenStyle::updateTabAnimation() { + if (tabwidgets.isEmpty()) + return; + QHash::iterator i; + activeTabs = 0; + TabAnimInfo* tai; + QWidget *ctw = 0, *widget = 0; QList widgets; + int index; + for (i = tabwidgets.begin(); i != tabwidgets.end(); i++) { + tai = i.value(); + if (!tai->animStep) + continue; + ctw = i.key()->currentWidget(); + if (! --(tai->animStep)) { // zero, stop animation + tai->tabPix[2] = + tai->tabPix[1] = + tai->tabPix[0] = QPixmap(); + ctw->parentWidget()->removeEventFilter(tai); + _UNBLOCKEVENTS_(ctw); + widgets = ctw->findChildren(); +// ctw->repaint(); + foreach(widget, widgets) { + index = tai->autofillingWidgets.indexOf(widget); + if (index != -1) { + tai->autofillingWidgets.removeAt(index); + widget->setAutoFillBackground(true); + } + _UNBLOCKEVENTS_(widget); + widget->update(); //if necessary + } + ctw->repaint(); //asap + tai->autofillingWidgets.clear(); + continue; + } + ++activeTabs; + switch (config.tabTransition) { + case CrossFade: + OXRender::blend(tai->tabPix[1], tai->tabPix[2], 1.1666-0.1666*tai->animStep); + break; + case SlideIn: { + //TODO handle different bar positions + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, tai->animStep*tai->tabPix[1].height()/7, + tai->tabPix[1].width(), (7-tai->animStep)*tai->tabPix[1].height()/7, + 0, 0 ); + XFreeGC ( dpy , gc ); + break; + } + case SlideOut: { + tai->tabPix[2] = tai->tabPix[1]; + //TODO handle different bar positions + QPainter p(&tai->tabPix[2]); + p.drawPixmap(0,0,tai->tabPix[0],0,(7-tai->animStep)*tai->tabPix[0].height()/7,tai->tabPix[0].width(),tai->animStep*tai->tabPix[0].height()/7); + break; + } + case RollOut: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int h = (7-tai->animStep)*tai->tabPix[1].height()/7; + int y = (tai->tabPix[1].height()-h)/2; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, y, tai->tabPix[1].width(), h, 0, y ); + XFreeGC ( dpy , gc ); + break; + } + case RollIn: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int h = (7-tai->animStep)*tai->tabPix[1].height()/14; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, 0, tai->tabPix[1].width(), h, 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, tai->tabPix[1].height()-h, tai->tabPix[1].width(), h, + 0, tai->tabPix[1].height()-h ); + XFreeGC ( dpy , gc ); + break; + } + case CloseVertically: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int h = (7-tai->animStep)*tai->tabPix[1].height()/14; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, tai->tabPix[1].height()/2-h, tai->tabPix[1].width(), h, 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, tai->tabPix[1].height()/2, tai->tabPix[1].width(), h, + 0, tai->tabPix[1].height()-h ); + XFreeGC ( dpy , gc ); + break; + } + case OpenVertically: { + tai->tabPix[2] = tai->tabPix[1]; + QPainter p(&tai->tabPix[2]); + int h = tai->animStep*tai->tabPix[0].height()/14; + p.drawPixmap(0,0,tai->tabPix[0],0,tai->tabPix[0].height()/2-h, + tai->tabPix[0].width(),h); + p.drawPixmap(0,tai->tabPix[0].height()-h,tai->tabPix[0], + 0,tai->tabPix[0].height()/2,tai->tabPix[0].width(),h); + break; + } + case CloseHorizontally: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + int w = (7-tai->animStep)*tai->tabPix[1].width()/14; + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + tai->tabPix[1].width()/2-w, 0, w, tai->tabPix[1].height(), 0, 0 ); + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + tai->tabPix[1].width()/2, 0, w, tai->tabPix[1].height(), + tai->tabPix[1].width()-w, 0 ); + XFreeGC ( dpy , gc ); + break; + } + case OpenHorizontally: { + tai->tabPix[2] = tai->tabPix[1]; + QPainter p(&tai->tabPix[2]); + int w = tai->animStep*tai->tabPix[0].width()/14; + p.drawPixmap(0,0,tai->tabPix[0],tai->tabPix[0].width()/2-w,0, + w,tai->tabPix[0].height()); + p.drawPixmap(tai->tabPix[0].width()-w,0,tai->tabPix[0], + tai->tabPix[0].width()/2,0,w,tai->tabPix[0].height()); + break; + } + case ScanlineBlend: + default: { + Display *dpy = QX11Info::display(); + GC gc = XCreateGC( dpy, tai->tabPix[2].handle(), 0, 0 ); + for (int i = tai->animStep; i < tai->tabPix[2].height(); i+=6) + XCopyArea( dpy, tai->tabPix[1].handle(), tai->tabPix[2].handle(), gc, + 0, i, tai->tabPix[1].width(), 1, 0, i ); + XFreeGC ( dpy , gc ); + } + } + ctw->parentWidget()->repaint(); + } + if (!ANIMATIONS) timer->stop(); +} + +void OxygenStyle::tabDestroyed(QObject* obj) { + tabwidgets.remove(static_cast(obj)); +// delete tai; + if (!ANIMATIONS) timer->stop(); +} + + +// -- Buttons etc. ------------------------------- +void OxygenStyle::updateFades() { + if (hoverWidgets.isEmpty()) + return; + HoverFades::iterator it = hoverWidgets.begin(); + while (it != hoverWidgets.end()) { + if (it.value().fadeIn) { + it.value().step += 1; + it.key()->update(); + if (it.value().step > 7) + it = hoverWidgets.erase(it); + else + ++it; + } + else { // fade out + it.value().step-=2; + it.key()->update(); + if (it.value().step < 1) + it = hoverWidgets.erase(it); + else + ++it; + } + } + if (!ANIMATIONS) timer->stop(); +} + +void OxygenStyle::fadeIn(QWidget *widget) { + HoverFades::iterator it = hoverWidgets.find(widget); + if (it == hoverWidgets.end()) { + it = hoverWidgets.insert(widget, HoverFadeInfo(1, true)); + } + it.value().fadeIn = true; + connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(fadeDestroyed(QObject*))); + startTimer; +} + +void OxygenStyle::fadeOut(QWidget *widget) { + HoverFades::iterator it = hoverWidgets.find(widget); + if (it == hoverWidgets.end()) { + it = hoverWidgets.insert(widget, HoverFadeInfo(6, false)); + } + it.value().fadeIn = false; + connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(fadeDestroyed(QObject*))); + startTimer; +} + +void OxygenStyle::fadeDestroyed(QObject* obj) { + hoverWidgets.remove(static_cast(obj)); + if (!ANIMATIONS) timer->stop(); +} + +int OxygenStyle::hoverStep(const QWidget *widget) const { + if (!widget) + return 0; + HoverFades::iterator it = hoverWidgets.find(const_cast(widget)); + if (it != hoverWidgets.end()) + return it.value().step; + return 0; +} + +// -- Complex controls ---------------------- + +void OxygenStyle::updateComplexFades() { + if (complexHoverWidgets.isEmpty()) + return; + bool update; + ComplexHoverFades::iterator it = complexHoverWidgets.begin(); + while (it != complexHoverWidgets.end()) { + ComplexHoverFadeInfo &info = it.value(); + update = false; + for (SubControl control = (SubControl)0x01; + control <= (SubControl)0x80; + control = (SubControl)(control<<1)) { + if (info.fadingInControls & control) { + update = true; + info.steps[control] += 2; + if (info.steps.value(control) > 4) + info.fadingInControls &= ~control; + } + else if (info.fadingOutControls & control) { + update = true; + --info.steps[control]; + if (info.steps.value(control) < 1) + info.fadingOutControls &= ~control; + } + } + if (update) + it.key()->update(); + if (info.activeSubControls == SC_None && // needed to detect changes! + info.fadingOutControls == SC_None && + info.fadingInControls == SC_None) + it = complexHoverWidgets.erase(it); + else + ++it; + } + if (!ANIMATIONS) timer->stop(); +} + +const ComplexHoverFadeInfo *OxygenStyle::complexHoverFadeInfo(const QWidget *widget, + SubControls activeSubControls) const { + QWidget *w = const_cast(widget); + ComplexHoverFades::iterator it = complexHoverWidgets.find(w); + if (it == complexHoverWidgets.end()) { + // we have no entry yet + if (activeSubControls == SC_None) + return 0; // no need here + // ...but we'll need one + it = complexHoverWidgets.insert(w, ComplexHoverFadeInfo()); + connect(widget, SIGNAL(destroyed(QObject*)), + this, SLOT(complexFadeDestroyed(QObject*))); + startTimer; + } + // we now have an entry - check for validity and update in case + ComplexHoverFadeInfo *info = &it.value(); + if (info->activeSubControls != activeSubControls) { // sth. changed + SubControls diff = info->activeSubControls ^ activeSubControls; + SubControls newActive = diff & activeSubControls; + SubControls newDead = diff & info->activeSubControls; + info->fadingInControls &= ~newDead; + info->fadingInControls |= newActive; + info->fadingOutControls &= ~newActive; + info->fadingOutControls |= newDead; + info->activeSubControls = activeSubControls; + for (SubControl control = (SubControl)0x01; + control <= (SubControl)0x80; + control = (SubControl)(control<<1)) { + if (newActive & control) + info->steps[control] = 1; + else if (newDead & control) { + info->steps[control] = 6; + } + } + } + return info; +} + +void OxygenStyle::complexFadeDestroyed(QObject* obj) { + complexHoverWidgets.remove(static_cast(obj)); + if (!ANIMATIONS) timer->stop(); +} + +// -- Indexed items like menus, tabs --------------------- +void OxygenStyle::updateIndexedFades() { + if (indexedHoverWidgets.isEmpty()) + return; + IndexedFades::iterator it; + QHash::iterator stepIt; + it = indexedHoverWidgets.begin(); + while (it != indexedHoverWidgets.end()) { + IndexedFadeInfo &info = it.value(); + if (info.fadingInIndices.isEmpty() && info.fadingOutIndices.isEmpty()) { + ++it; + continue; + } + + stepIt = info.fadingInIndices.begin(); + while (stepIt != info.fadingInIndices.end()) { + stepIt.value() += 2; + if (stepIt.value() > 4) + stepIt = info.fadingInIndices.erase(stepIt); + else + ++stepIt; + } + + stepIt = info.fadingOutIndices.begin(); + while (stepIt != info.fadingOutIndices.end()) { + --stepIt.value(); + if (stepIt.value() < 1) + stepIt = info.fadingOutIndices.erase(stepIt); + else + ++stepIt; + } + + it.key()->update(); + + if (info.index == 0L && // nothing actually hovered + info.fadingInIndices.isEmpty() && // no fade ins + info.fadingOutIndices.isEmpty()) // no fade outs + it = indexedHoverWidgets.erase(it); + else + ++it; + } + if (!ANIMATIONS) timer->stop(); +} + +const IndexedFadeInfo *OxygenStyle::indexedFadeInfo(const QWidget *widget, + long int index) const { + QWidget *w = const_cast(widget); + IndexedFades::iterator it = indexedHoverWidgets.find(w); + if (it == indexedHoverWidgets.end()) { + // we have no entry yet + if (index == 0L) + return 0L; + // ... but we'll need one + it = indexedHoverWidgets.insert(w, IndexedFadeInfo(0L)); + connect(widget, SIGNAL(destroyed(QObject*)), + this, SLOT(indexedFadeDestroyed(QObject*))); + startTimer; + } + // we now have an entry - check for validity and update in case + IndexedFadeInfo *info = &it.value(); + if (info->index != index) { // sth. changed + info->fadingInIndices[index] = 1; + if (info->index) + info->fadingOutIndices[info->index] = 6; + info->index = index; + } + return info; +} + +void OxygenStyle::indexedFadeDestroyed(QObject* obj) { + indexedHoverWidgets.remove(static_cast(obj)); + if (!ANIMATIONS) timer->stop(); +} + +int IndexedFadeInfo::step(long int index) { + typedef QHash Index2Step; + Index2Step::iterator stepIt; + for (stepIt = fadingInIndices.begin(); stepIt != fadingInIndices.end(); stepIt++) + if (stepIt.key() == index) + return stepIt.value(); + for (stepIt = fadingOutIndices.begin(); stepIt != fadingOutIndices.end(); stepIt++) + if (stepIt.key() == index) + return stepIt.value(); + return 0; +} diff --git a/clients/oxygen/debug.h b/clients/oxygen/debug.h new file mode 100644 index 0000000000..2bca3a1f0d --- /dev/null +++ b/clients/oxygen/debug.h @@ -0,0 +1,127 @@ +#define PRINTDEVICE(p) qWarning("device is %s", (p->device()->devType() == QInternal::Widget) ?\ +"Widget": (p->device()->devType() == QInternal::Pixmap) ?\ +"Pixmap": (p->device()->devType() == QInternal::Printer) ?\ +"Printer": (p->device()->devType() == QInternal::Picture) ?\ +"Picture": (p->device()->devType() == QInternal::UndefinedDevice) ?\ +"UndefinedDevice": "fuckdevice!" ); + +#define PRINTFLAGS(f) qWarning("Style Flags:\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",\ +f & QStyle::Style_Default ? "Default, " : "",\ +f & QStyle::Style_Enabled ? "Enabled, " : "",\ +f & QStyle::Style_Raised ? "Raised, " : "",\ +f & QStyle::Style_Sunken ? "Sunken, " : "",\ +f & QStyle::Style_Off ? "Off, " : "",\ +f & QStyle::Style_NoChange ? "NoChange, " : "",\ +f & QStyle::Style_On ? "On, " : "",\ +f & QStyle::Style_Down ? "Down, " : "",\ +f & QStyle::Style_Horizontal ? "Horizontal, " : "",\ +f & QStyle::Style_HasFocus ? "HasFocus, " : "",\ +f & QStyle::Style_Top ? "Top, " : "",\ +f & QStyle::Style_Bottom ? "Bottom, " : "",\ +f & QStyle::Style_FocusAtBorder ? "FocusAtBorder, " : "",\ +f & QStyle::Style_AutoRaise ? "AutoRaise, " : "",\ +f & QStyle::Style_MouseOver ? "MouseOver, " : "",\ +f & QStyle::Style_Up ? "Style_Up, " : "",\ +f & QStyle::Style_Selected ? "Selected, " : "",\ +f & QStyle::Style_HasFocus ? "HasFocus, " : "",\ +f & QStyle::Style_Active ? "Active, " : "",\ +f & QStyle::Style_ButtonDefault ? "ButtonDefault" : "" ) + +#define PRINTEVENT(e) qWarning("Event: %s",\ +e->type() == QEvent::Timer ? " Timer " : \ +e->type() == QEvent::MouseButtonPress ? " MouseButtonPress " : \ +e->type() == QEvent::MouseButtonRelease ? " MouseButtonRelease " : \ +e->type() == QEvent::MouseButtonDblClick ? " MouseButtonDblClick " : \ +e->type() == QEvent::MouseMove ? " MouseMove " : \ +e->type() == QEvent::KeyPress ? " KeyPress " : \ +e->type() == QEvent::KeyRelease ? " KeyRelease " : \ +e->type() == QEvent::FocusIn ? " FocusIn " : \ +e->type() == QEvent::FocusOut ? " FocusOut " : \ +e->type() == QEvent::Enter ? " Enter " : \ +e->type() == QEvent::Leave ? " Leave " : \ +e->type() == QEvent::Paint ? " Paint " : \ +e->type() == QEvent::Move ? " Move " : \ +e->type() == QEvent::Resize ? " Resize " : \ +e->type() == QEvent::Create ? " Create " : \ +e->type() == QEvent::Destroy ? " Destroy " : \ +e->type() == QEvent::Show ? " Show " : \ +e->type() == QEvent::Hide ? " Hide " : \ +e->type() == QEvent::Close ? " Close " : \ +e->type() == QEvent::Quit ? " Quit " : \ +e->type() == QEvent::Reparent ? " Reparent " : \ +e->type() == QEvent::ShowMinimized ? " ShowMinimized " : \ +e->type() == QEvent::ShowNormal ? " ShowNormal " : \ +e->type() == QEvent::WindowActivate ? " WindowActivate " : \ +e->type() == QEvent::WindowDeactivate ? " WindowDeactivate " : \ +e->type() == QEvent::ShowToParent ? " ShowToParent " : \ +e->type() == QEvent::HideToParent ? " HideToParent " : \ +e->type() == QEvent::ShowMaximized ? " ShowMaximized " : \ +e->type() == QEvent::ShowFullScreen ? " ShowFullScreen " : \ +e->type() == QEvent::Accel ? " Accel " : \ +e->type() == QEvent::Wheel ? " Wheel " : \ +e->type() == QEvent::AccelAvailable ? " AccelAvailable " : \ +e->type() == QEvent::CaptionChange ? " CaptionChange " : \ +e->type() == QEvent::IconChange ? " IconChange " : \ +e->type() == QEvent::ParentFontChange ? " ParentFontChange " : \ +e->type() == QEvent::ApplicationFontChange ? " ApplicationFontChange " : \ +e->type() == QEvent::ParentPaletteChange ? " ParentPaletteChange " : \ +e->type() == QEvent::ApplicationPaletteChange ? " ApplicationPaletteChange " : \ +e->type() == QEvent::PaletteChange ? " PaletteChange " : \ +e->type() == QEvent::Clipboard ? " Clipboard " : \ +e->type() == QEvent::Speech ? " Speech " : \ +e->type() == QEvent::SockAct ? " SockAct " : \ +e->type() == QEvent::AccelOverride ? " AccelOverride " : \ +e->type() == QEvent::DeferredDelete ? " DeferredDelete " : \ +e->type() == QEvent::DragEnter ? " DragEnter " : \ +e->type() == QEvent::DragMove ? " DragMove " : \ +e->type() == QEvent::DragLeave ? " DragLeave " : \ +e->type() == QEvent::Drop ? " Drop " : \ +e->type() == QEvent::DragResponse ? " DragResponse " : \ +e->type() == QEvent::ChildInserted ? " ChildInserted " : \ +e->type() == QEvent::ChildRemoved ? " ChildRemoved " : \ +e->type() == QEvent::LayoutHint ? " LayoutHint " : \ +e->type() == QEvent::ShowWindowRequest ? " ShowWindowRequest " : \ +e->type() == QEvent::WindowBlocked ? " WindowBlocked " : \ +e->type() == QEvent::WindowUnblocked ? " WindowUnblocked " : \ +e->type() == QEvent::ActivateControl ? " ActivateControl " : \ +e->type() == QEvent::DeactivateControl ? " DeactivateControl " : \ +e->type() == QEvent::ContextMenu ? " ContextMenu " : \ +e->type() == QEvent::IMStart ? " IMStart " : \ +e->type() == QEvent::IMCompose ? " IMCompose " : \ +e->type() == QEvent::IMEnd ? " IMEnd " : \ +e->type() == QEvent::Accessibility ? " Accessibility " : \ +e->type() == QEvent::TabletMove ? " TabletMove " : \ +e->type() == QEvent::LocaleChange ? " LocaleChange " : \ +e->type() == QEvent::LanguageChange ? " LanguageChange " : \ +e->type() == QEvent::LayoutDirectionChange ? " LayoutDirectionChange " : \ +e->type() == QEvent::Style ? " Style " : \ +e->type() == QEvent::TabletPress ? " TabletPress " : \ +e->type() == QEvent::TabletRelease ? " TabletRelease " : \ +e->type() == QEvent::OkRequest ? " OkRequest " : \ +e->type() == QEvent::HelpRequest ? " HelpRequest " : \ +e->type() == QEvent::WindowStateChange ? " WindowStateChange " : \ +e->type() == QEvent::IconDrag ? " IconDrag " : "Unknown Event"); + +#define PRINTCOMPLEXCONTROL(cc) qWarning("Complex Control: %s",\ +QStyle::CC_SpinWidget ? " QStyle::CC_SpinWidget " : \ +QStyle::CC_ComboBox ? " CC_ComboBox " : \ +QStyle::CC_ScrollBar ? " CC_ScrollBar " : \ +QStyle::CC_Slider ? " CC_Slider " : \ +QStyle::CC_ToolButton ? " CC_ToolButton " : \ +QStyle::CC_TitleBar ? "CC_TitleBar " : \ +QStyle::CC_ListView ? "CC_ListView " : "Unknow Control"); + +#define _IDENTIFYOBJECT_(o) qWarning("%s (%s)%s%s (%s)", o->name(), o->className(), o->parent() ? " is child of " : " has no daddy", o->parent() ? o->parent()->name() : "", o->parent() ? o->parent()->className() : "!") + +#define _COMPARECOLORS_(c1,c2) qWarning("%d/%d/%d vs. %d/%d/%d", c1.red(), c1.green(), c1.blue(), c2.red(), c2.green(), c2.blue()); + +// #define MOUSEDEBUG +#undef MOUSEDEBUG + +//#define FUNCTIONALBG + #undef FUNCTIONALBG + +#include +#define _PROFILESTART_ QTime timer; int time; timer.start(); +#define _PROFILERESTART_ timer.restart(); +#define _PROFILESTOP_(_STRING_) time = timer.elapsed(); qWarning("%s: %d",_STRING_,time); diff --git a/clients/oxygen/drawcomplexcontrol.cpp b/clients/oxygen/drawcomplexcontrol.cpp new file mode 100644 index 0000000000..bb9d2d3e3a --- /dev/null +++ b/clients/oxygen/drawcomplexcontrol.cpp @@ -0,0 +1,625 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +// #include +#include +#include +#include "oxygen.h" + +using namespace Oxygen; + +extern Config config; +extern Dpi dpi; + +#include "inlinehelp.cpp" +#include "makros.h" + +void OxygenStyle::drawComplexControl ( ComplexControl control, const QStyleOptionComplex * option, QPainter * painter, const QWidget * widget) const +{ + Q_ASSERT(option); + Q_ASSERT(painter); + + bool sunken = option->state & State_Sunken; + bool isEnabled = option->state & State_Enabled; + bool hover = isEnabled && (option->state & State_MouseOver); + bool hasFocus = option->state & State_HasFocus; + + switch ( control ) + { + case CC_SpinBox: // A spinbox, like QSpinBox + if (const QStyleOptionSpinBox *sb = + qstyleoption_cast(option)) { + QStyleOptionSpinBox copy = *sb; + int uh = 0; + + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) + drawPrimitive ( PE_PanelLineEdit, sb, painter, widget ); + + if (!isEnabled) + break; // why bother the user with elements he can't use... ;) + + Tile::PosFlags pf; + + if (sb->subControls & SC_SpinBoxUp) { + copy.subControls = SC_SpinBoxUp; + copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); + uh = copy.rect.height(); + + pf = Tile::Top | Tile::Left | Tile::Right; + isEnabled = sb->stepEnabled & QAbstractSpinBox::StepUpEnabled; + hover = isEnabled && (sb->activeSubControls == SC_SpinBoxUp); + sunken = sunken && (sb->activeSubControls == SC_SpinBoxUp); + + int dx = copy.rect.width()/4, dy = copy.rect.height()/4; + copy.rect.adjust(dx, 2*dy,-dx,-dpi.$1); + + QColor c; + if (hover) + c = COLOR(Highlight); + else if (isEnabled) + c = COLOR(Text); + else + c = midColor(COLOR(Base), QPalette::Text); + + painter->setPen(c); + drawPrimitive(PE_IndicatorSpinUp, ©, painter, widget); + } + + if (sb->subControls & SC_SpinBoxDown) { + copy.subControls = SC_SpinBoxDown; + copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); + + pf = Tile::Bottom | Tile::Left | Tile::Right; + isEnabled = sb->stepEnabled & QAbstractSpinBox::StepDownEnabled; + hover = isEnabled && (sb->activeSubControls == SC_SpinBoxDown); + sunken = sunken && (sb->activeSubControls == SC_SpinBoxDown); + + int dx = copy.rect.width()/4, dy = copy.rect.height()/4; + copy.rect.adjust(dx, dpi.$1,-dx,-2*dy); + + QColor c; + if (hover) + c = COLOR(Highlight); + else if (isEnabled) + c = COLOR(Text); + else + c = midColor(COLOR(Base), QPalette::Text); + + painter->setPen(c); + drawPrimitive(PE_IndicatorSpinDown, ©, painter, widget); + } + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = + qstyleoption_cast(option)) { + if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { + QStyleOptionFrameV2 frame; + frame.QStyleOption::operator=(*groupBox); + frame.features = groupBox->features; + frame.lineWidth = groupBox->lineWidth; + frame.midLineWidth = groupBox->midLineWidth; + frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget); + drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + } + + // Draw title + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && + !groupBox->text.isEmpty()) { + QColor textColor = groupBox->textColor; + if (textColor.isValid()) painter->setPen(textColor); + QFont tmpfnt = painter->font(); tmpfnt.setBold(true); + painter->setFont ( tmpfnt ); + QStyleOptionGroupBox copy = *groupBox; copy.fontMetrics = QFontMetrics(tmpfnt); + QRect textRect = subControlRect(CC_GroupBox, ©, SC_GroupBoxLabel, widget); + int alignment = Qt::AlignCenter; //int(groupBox->textAlignment); + if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + alignment |= Qt::TextHideMnemonic; + else + alignment |= Qt::TextShowMnemonic; + + drawItemText(painter, textRect, alignment, groupBox->palette, isEnabled, groupBox->text, + textColor.isValid() ? QPalette::NoRole : QPalette::Foreground); + int x = textRect.bottom(); textRect = RECT; textRect.setTop(x); + x = textRect.width()/4; textRect.adjust(x,0,-x,0); + shadows.line[0][Sunken].render(textRect, painter); + } + + // Draw checkbox // TODO: sth better - maybe a round thing in the upper left corner...? also doesn't hover - yet. + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget); + drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + } + break; + case CC_ComboBox: // A combobox, like QComboBox + if (const QStyleOptionComboBox *cmb = + qstyleoption_cast(option)) { + QRect ar, r = RECT.adjusted(0,0,0,-dpi.$2); + const QComboBox* combo = widget ? + qobject_cast(widget) : 0; + const bool listShown = combo && combo->view() && + ((QWidget*)(combo->view()))->isVisible(); + const bool reverse = (option->direction == Qt::RightToLeft); + + // do we have an arrow? + if ((cmb->subControls & SC_ComboBoxArrow)) + ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget); + + // the label + if ((cmb->subControls & SC_ComboBoxFrame) && cmb->frame) { + if (cmb->editable) + drawPrimitive(PE_PanelLineEdit, option, painter, widget); + else { + drawPrimitive(PE_PanelButtonBevel, option, painter, widget); + } + } + + // the arrow + if (!ar.isNull()) { + ar.adjust(ar.width()/3,ar.height()/3,-ar.width()/3,-ar.height()/3); + QStyleOptionComboBox tmpOpt = *cmb; + PrimitiveElement arrow; + if (!listShown) + arrow = PE_IndicatorArrowDown; + else if (reverse) + arrow = PE_IndicatorArrowRight; + else + arrow = PE_IndicatorArrowLeft; + if (cmb->editable) + hover = hover && (cmb->activeSubControls == SC_ComboBoxArrow); + painter->setRenderHint ( QPainter::Antialiasing, true ); + painter->save(); + + painter->setPen(COLOR(Text)); + if (hover || listShown) { + if (cmb->editable) + painter->setPen(COLOR(Highlight)); + } + tmpOpt.rect = ar; + drawPrimitive(arrow, &tmpOpt, painter, widget); + painter->restore(); + } + } + break; + case CC_ScrollBar: // A scroll bar, like QScrollBar + if (const QStyleOptionSlider *scrollbar = + qstyleoption_cast(option)) { + // Make a copy here and reset it for each primitive. + QStyleOptionSlider newScrollbar = *scrollbar; + + // TODO: this is a stupid hack, move the whole special scrollbar painting here! + if (widget && widget->parentWidget() && + widget->parentWidget()->parentWidget() && + widget->parentWidget()->parentWidget()->inherits("QComboBoxListView")) { + painter->fillRect(RECT, PAL.brush(QPalette::Base)); + newScrollbar.state |= State_Item; + } + + State saveFlags = newScrollbar.state; + if (scrollbar->minimum == scrollbar->maximum) + saveFlags &= ~State_Enabled; + + SubControls hoverControls = scrollbar->activeSubControls & + (SC_ScrollBarSubLine | SC_ScrollBarAddLine | SC_ScrollBarSlider); + const ComplexHoverFadeInfo *info = + complexHoverFadeInfo(widget, hoverControls); + +#define PAINT_ELEMENT(_SC_, _CE_)\ + if (scrollbar->subControls & _SC_) {\ + newScrollbar.rect = scrollbar->rect;\ + newScrollbar.state = saveFlags;\ + newScrollbar.rect = subControlRect(control, &newScrollbar, _SC_, widget);\ + if (newScrollbar.rect.isValid()) {\ + if (!(scrollbar->activeSubControls & _SC_))\ + newScrollbar.state &= ~(State_Sunken | State_MouseOver);\ + if (info && (info->fadingInControls & _SC_ || info->fadingOutControls & _SC_))\ + const_cast( this )->complexStep = info->steps.value(_SC_); \ + else \ + const_cast( this )->complexStep = 0; \ + drawControl(_CE_, &newScrollbar, painter, widget);\ + }\ + }// + + PAINT_ELEMENT(SC_ScrollBarSubLine, CE_ScrollBarSubLine); + PAINT_ELEMENT(SC_ScrollBarAddLine, CE_ScrollBarAddLine); + PAINT_ELEMENT(SC_ScrollBarSubPage, CE_ScrollBarSubPage); + PAINT_ELEMENT(SC_ScrollBarAddPage, CE_ScrollBarAddPage); +// PAINT_ELEMENT(SC_ScrollBarFirst, CE_ScrollBarFirst); +// PAINT_ELEMENT(SC_ScrollBarLast, CE_ScrollBarLast); + + if (scrollbar->subControls & SC_ScrollBarSlider) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, + SC_ScrollBarSlider, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSlider)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + if (scrollbar->state & State_HasFocus) + newScrollbar.state |= (State_Sunken | State_MouseOver); + if (info && (info->fadingInControls & SC_ScrollBarSlider || + info->fadingOutControls & SC_ScrollBarSlider)) + const_cast( this )->complexStep = + info->steps.value(SC_ScrollBarSlider); + else + const_cast( this )->complexStep = 0; + drawControl(CE_ScrollBarSlider, &newScrollbar, painter, widget); + } + } + } + break; + case CC_Slider: // A slider, like QSlider + if (const QStyleOptionSlider *slider = + qstyleoption_cast(option)) { + QRect groove = QCommonStyle::subControlRect(CC_Slider, slider, SC_SliderGroove, widget); + QRect handle = QCommonStyle::subControlRect(CC_Slider, slider, SC_SliderHandle, widget); + + isEnabled = isEnabled && (slider->maximum > slider->minimum); + hover = isEnabled && hover && (slider->activeSubControls & SC_SliderHandle); + sunken = sunken && (slider->activeSubControls & SC_SliderHandle); + + const int ground = 0; + + if ((slider->subControls & SC_SliderGroove) && + groove.isValid()) { + QRect r; + QColor c = btnBgColor(PAL, isEnabled, hasFocus); + if ( slider->orientation == Qt::Horizontal ) { + // the groove + groove.adjust(0,handle.height()/3,0,-handle.height()/3); + fillWithMask(painter, groove, gradient(COLOR(Window), + groove.height(), Qt::Vertical, GradSunken), + &masks.button); +#if 0 + // the "temperature" + if (slider->sliderPosition != ground && + slider->maximum > slider->minimum) { + groove.adjust(0,dpi.$1,0,-dpi.$1); + int groundX = groove.width() * (ground - slider->minimum) / + (slider->maximum - slider->minimum); + bool rightSide = slider->sliderPosition > ground; + if (slider->upsideDown) { + rightSide = !rightSide; + groundX = groove.right() - groundX; + } + else + groundX += groove.left(); + + if (rightSide) { + groove.setLeft(groundX); + groove.setRight(handle.center().x()); + } + else { + groove.setLeft(handle.center().x()); + groove.setRight(groundX); + } + fillWithMask(painter, groove, gradient(COLOR(Window), + groove.height(), Qt::Vertical, config.gradient), + &masks.button); + } +#else + groove.adjust(0,dpi.$1,0,-dpi.$1); + fillWithMask(painter, groove, gradient(COLOR(Window), + groove.height(), Qt::Vertical, config.gradient), + &masks.button); +#endif + // for later (cosmetic) + handle.translate(0,dpi.$3); + } + else { // Vertical + // the groove + groove.adjust(handle.width()/3,0,-handle.width()/3,0); + fillWithMask(painter, groove, gradient(COLOR(Window), + groove.width(), Qt::Horizontal, GradSunken), + &masks.button); +#if 0 + // the "temperature" + if (slider->sliderPosition != ground && + slider->maximum > slider->minimum) { + groove.adjust(dpi.$1,0,-dpi.$1,0); + int groundY = groove.height() * (ground - slider->minimum) / + (slider->maximum - slider->minimum); + bool upside = slider->sliderPosition > ground; + if (slider->upsideDown) { + upside = !upside; + groundY = groove.bottom() - groundY; + } + else + groundY += groove.top(); + + if (upside) { + groove.setBottom(handle.center().y()); + groove.setTop(groundY); + } + else { + groove.setBottom(groundY); + groove.setTop(handle.center().y()); + } + fillWithMask(painter, groove, gradient(COLOR(Window), + groove.width(), Qt::Horizontal, config.gradient), + &masks.button); + } +#else + groove.adjust(dpi.$1,0,-dpi.$1,0); + fillWithMask(painter, groove, gradient(COLOR(Window), + groove.width(), Qt::Horizontal, config.gradient), + &masks.button); +#endif + // for later (cosmetic) + handle.translate(dpi.$3,0); + } + } + + int direction = 0; + if (slider->orientation == Qt::Vertical) + ++direction; + + // ticks - TODO: paint our own ones? + if ((slider->subControls & SC_SliderTickmarks) && + (slider->tickPosition != QSlider::NoTicks) ) { + if (slider->tickPosition == QSlider::TicksAbove) { + direction += 2; + if (slider->orientation == Qt::Horizontal) + handle.translate(0,-dpi.$6); + else + handle.translate(-dpi.$6,0); + } + QStyleOptionSlider tmpSlider = *slider; + tmpSlider.subControls = SC_SliderTickmarks; + QCommonStyle::drawComplexControl(control, &tmpSlider, painter, widget); + } + + // handle + if (slider->subControls & SC_SliderHandle) { + int step = 0; + if (!hasFocus) { + const ComplexHoverFadeInfo *info = + complexHoverFadeInfo(widget, slider->activeSubControls & SC_SliderHandle); + if (info && (info->fadingInControls & SC_SliderHandle || + info->fadingOutControls & SC_SliderHandle)) + step = info->steps.value(SC_SliderHandle); + } + // shadow + QPoint xy = handle.topLeft(); + painter->drawPixmap(sunken ? xy + QPoint(dpi.$1,dpi.$1) : xy, + shadows.slider[direction][sunken][hover]); + // gradient + xy += QPoint(dpi.$2, direction?dpi.$1:0); + fillWithMask(painter, xy, gradient(btnBgColor(PAL, isEnabled, + hover || hasFocus, step), dpi.SliderControl-dpi.$4, + Qt::Vertical, config.gradBtn), masks.slider[direction]); + painter->drawPixmap(xy, lights.slider[direction]); +// SAVE_PEN; +// painter->setPen(btnFgColor(PAL, isEnabled, hover || hasFocus, step)); +// painter->drawPoint(handle.center()); +// RESTORE_PEN; + } + } + break; + case CC_ToolButton: // A tool button, like QToolButton + // special handling for the tabbar scrollers ---------------------------------- + if (widget && widget->parentWidget() && + qobject_cast(widget->parent())) { + QColor c = widget->parentWidget()->palette().color(config.role_tab[0]); + QColor c2 = widget->parentWidget()->palette().color(config.role_tab[1]); + if (sunken) { + int dy = (RECT.height()-RECT.width())/2; + QRect r = RECT.adjusted(dpi.$2,dy,-dpi.$2,-dy); + painter->drawTiledPixmap(r, gradient(c, r.height(), Qt::Vertical, GradSunken)); + } + painter->save(); + painter->setPen( isEnabled ? c2 : midColor(c, c2) ); + drawControl(CE_ToolButtonLabel, option, painter, widget); + painter->restore(); + break; + } + // -------------------------------------------------------------------- + + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(option)) { + QRect menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget); + QRect button = subControlRect(control, toolbutton, SC_ToolButton, widget); + State bflags = toolbutton->state; + + if ((bflags & State_AutoRaise) && !hover) + bflags &= ~State_Raised; + + State mflags = bflags; + + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + + hover = isEnabled && (bflags & (State_Sunken | State_On | State_Raised | State_HasFocus)); + + QStyleOption tool(0); tool.palette = toolbutton->palette; + + // frame around whole button + if (hover) { + tool.rect = RECT; tool.state = bflags; + drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); + } + + // don't paint a dropdown arrow iff the button's really pressed + if (!(bflags & State_Sunken) && + (toolbutton->subControls & SC_ToolButtonMenu)) { + if (toolbutton->activeSubControls & SC_ToolButtonMenu) + painter->drawTiledPixmap(menuarea, gradient(COLOR(Window), + menuarea.height(), Qt::Vertical, + GradSunken)); + QPen oldPen = painter->pen(); + painter->setPen(midColor(COLOR(Window), COLOR(WindowText), 2, 1)); + tool.rect = menuarea; tool.state = mflags; + drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget); + painter->setPen(oldPen); + if (hover) { + menuarea.setLeft(button.right()-shadows.line[1][Sunken].thickness()/2); + shadows.line[1][Sunken].render(menuarea, painter); + } + } + + // label in the toolbutton area + QStyleOptionToolButton label = *toolbutton; + label.rect = button; + drawControl(CE_ToolButtonLabel, &label, painter, widget); + } + break; + case CC_TitleBar: // A Title bar, like what is used in Q3Workspace + if (const QStyleOptionTitleBar *tb = + qstyleoption_cast(option)) + { + painter->fillRect(RECT, PAL.brush(QPalette::Window)); + QRect ir; + if (option->subControls & SC_TitleBarLabel) + { + ir = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget); + painter->setPen(PAL.color(QPalette::WindowText)); + painter->drawText(ir.x() + dpi.$2, ir.y(), ir.width() - dpi.$2, ir.height(), Qt::AlignCenter | Qt::TextSingleLine, tb->text); + } + + +#define PAINT_WINDOW_BUTTON(_scbtn_, _spbtn_)\ + {\ + tmpOpt.rect = subControlRect(CC_TitleBar, tb, _scbtn_, widget);\ + if (tb->activeSubControls & _scbtn_)\ + tmpOpt.state = tb->state;\ + else\ + tmpOpt.state &= ~(State_Sunken | State_MouseOver);\ + pm = standardPixmap ( _spbtn_, &tmpOpt, widget );\ + painter->drawPixmap(tmpOpt.rect.topLeft(), pm);\ + } + + QPixmap pm; + QStyleOptionTitleBar tmpOpt = *tb; + if (tb->subControls & SC_TitleBarCloseButton) + PAINT_WINDOW_BUTTON(SC_TitleBarCloseButton, SP_TitleBarCloseButton) + + if (tb->subControls & SC_TitleBarMaxButton + && tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + { + if (tb->titleBarState & Qt::WindowMaximized) + PAINT_WINDOW_BUTTON(SC_TitleBarNormalButton, SP_TitleBarNormalButton) + else + PAINT_WINDOW_BUTTON(SC_TitleBarMaxButton, SP_TitleBarMaxButton) + } + + if (tb->subControls & SC_TitleBarMinButton + && tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + { + if (tb->titleBarState & Qt::WindowMinimized) + PAINT_WINDOW_BUTTON(SC_TitleBarNormalButton, SP_TitleBarNormalButton) + else + PAINT_WINDOW_BUTTON(SC_TitleBarMinButton, SP_TitleBarMinButton) + } + + if (tb->subControls & SC_TitleBarNormalButton && + tb->titleBarFlags & Qt::WindowMinMaxButtonsHint) + PAINT_WINDOW_BUTTON(SC_TitleBarNormalButton, SP_TitleBarNormalButton) + + if (tb->subControls & SC_TitleBarShadeButton) + PAINT_WINDOW_BUTTON(SC_TitleBarShadeButton, SP_TitleBarShadeButton) + + if (tb->subControls & SC_TitleBarUnshadeButton) + PAINT_WINDOW_BUTTON(SC_TitleBarUnshadeButton, SP_TitleBarUnshadeButton) + + if (tb->subControls & SC_TitleBarContextHelpButton + && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + PAINT_WINDOW_BUTTON(SC_TitleBarContextHelpButton, SP_TitleBarContextHelpButton) + + if (tb->subControls & SC_TitleBarSysMenu + && tb->titleBarFlags & Qt::WindowSystemMenuHint) + { + if (!tb->icon.isNull()) + { + ir = subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget); + tb->icon.paint(painter, ir); + } + else + PAINT_WINDOW_BUTTON(SC_TitleBarSysMenu, SP_TitleBarMenuButton) + } + } + break; +// case CC_Q3ListView: // Used for drawing the Q3ListView class + case CC_Dial: // A dial, like QDial + if (const QStyleOptionSlider *dial = + qstyleoption_cast(option)) { + painter->save(); + QRect rect = RECT; + if (rect.width() > rect.height()) { + rect.setLeft(rect.x()+(rect.width()-rect.height())/2); rect.setWidth(rect.height()); + } + else { + rect.setTop(rect.y()+(rect.height()-rect.width())/2); rect.setHeight(rect.width()); + } + + int d = qMax(rect.width()/6, dpi.$10); + int r = (rect.width()-d)/2; + qreal a; + if (dial->maximum == dial->minimum) + a = M_PI / 2; + else if (dial->dialWrapping) + a = M_PI * 3 / 2 - (dial->sliderValue - dial->minimum) * 2 * M_PI + / (dial->maximum - dial->minimum); + else + a = (M_PI * 8 - (dial->sliderValue - dial->minimum) * 10 * M_PI + / (dial->maximum - dial->minimum)) / 6; + + QPoint cp((int)(r * cos(a)), -(int)(r * sin(a))); + cp += rect.center(); + + // the huge ring + r = d/2; rect.adjust(r,r,-r,-r); + painter->setPen(COLOR(Window).dark(115)); + painter->setRenderHint( QPainter::Antialiasing ); + painter->drawEllipse(rect); + rect.translate(0, 1); + painter->setPen(COLOR(Window).light(108)); + painter->drawEllipse(rect); + // the value + QFont fnt = painter->font(); + fnt.setPixelSize( rect.height()/3 ); + painter->setFont(fnt); + painter->setBrush(Qt::NoBrush); + painter->setPen(PAL.foreground().color()); + drawItemText(painter, rect, Qt::AlignCenter, PAL, isEnabled, + QString::number(dial->sliderValue)); + // the drop + painter->setPen(Qt::NoPen); + rect = QRect(0,0,d,d); + rect.moveCenter(cp); + painter->setBrush(QColor(0,0,0,50)); + painter->drawEllipse(rect); + rect.adjust(dpi.$2,dpi.$1,-dpi.$2,-dpi.$2); + painter->setBrushOrigin(rect.topLeft()); + painter->setBrush(gradient(btnBgColor(PAL, isEnabled, hover||hasFocus), + rect.height(), Qt::Vertical, GradRadialGloss)); + painter->drawEllipse(rect); + painter->restore(); + } + break; + default: + QCommonStyle::drawComplexControl( control, option, painter, widget ); + } // switch +} diff --git a/clients/oxygen/drawcontrol.cpp b/clients/oxygen/drawcontrol.cpp new file mode 100644 index 0000000000..911d11d37d --- /dev/null +++ b/clients/oxygen/drawcontrol.cpp @@ -0,0 +1,1311 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oxygen.h" + +#include + +using namespace Oxygen; + +extern Config config; +extern Dpi dpi; +// extern HoverFades hoverWidgets;q +extern int complexStep; + +#include "inlinehelp.cpp" +#include "makros.h" + +static const int windowsItemFrame = 1; // menu item frame width +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 1; // menu item ver text margin +static const int windowsRightBorder = 12; // right border on windows + +static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbutton, + const QRect &rect, QPainter *painter, const QWidget *widget = 0) +{ + QStyle::PrimitiveElement pe; + switch (toolbutton->arrowType) { + case Qt::LeftArrow: + pe = QStyle::PE_IndicatorArrowLeft; + break; + case Qt::RightArrow: + pe = QStyle::PE_IndicatorArrowRight; + break; + case Qt::UpArrow: + pe = QStyle::PE_IndicatorArrowUp; + break; + case Qt::DownArrow: + pe = QStyle::PE_IndicatorArrowDown; + break; + default: + return; + } + QStyleOption arrowOpt; + arrowOpt.rect = rect; + arrowOpt.palette = toolbutton->palette; + arrowOpt.state = toolbutton->state; + style->drawPrimitive(pe, &arrowOpt, painter, widget); +} + +bool scrollAreaHovered(const QWidget* slider) { +// bool scrollerActive = false; + QWidget *scrollWidget = const_cast(slider); + if (!scrollWidget->isEnabled()) + return false; + while (scrollWidget && + !(qobject_cast(scrollWidget) || + qobject_cast(scrollWidget))) + scrollWidget = const_cast(scrollWidget->parentWidget()); + bool isActive = true; + if (scrollWidget) { +// QAbstractScrollArea* scrollWidget = (QAbstractScrollArea*)daddy; + QPoint tl = scrollWidget->mapToGlobal(QPoint(0,0)); + QRegion scrollArea(tl.x(),tl.y(),scrollWidget->width(),scrollWidget->height()); + QList scrollChilds = scrollWidget->findChildren(); + for (int i = 0; i < scrollChilds.size(); ++i) { + QPoint tl = scrollChilds[i]->mapToGlobal(QPoint(0,0)); + scrollArea -= QRegion(tl.x(), tl.y(), scrollChilds[i]->width(), scrollChilds[i]->height()); + } + QList scrollChilds2 = scrollWidget->findChildren(); + for (int i = 0; i < scrollChilds2.size(); ++i) { + QPoint tl = scrollChilds[i]->mapToGlobal(QPoint(0,0)); + scrollArea -= QRegion(tl.x(), tl.y(), scrollChilds2[i]->width(), scrollChilds2[i]->height()); + } +// scrollerActive = scrollArea.contains(QCursor::pos()); + isActive = scrollArea.contains(QCursor::pos()); + } + return isActive; +} + +void OxygenStyle::drawControl ( ControlElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget) const +{ + Q_ASSERT(option); + Q_ASSERT(painter); + + bool sunken = option->state & State_Sunken; + bool isEnabled = option->state & State_Enabled; + bool hover = isEnabled && (option->state & State_MouseOver); + bool hasFocus = option->state & State_HasFocus; + + switch ( element ) { + case CE_PushButton: // A QPushButton, draws case CE_PushButtonBevel, case CE_PushButtonLabel and PE_FrameFocusRect + if (const QStyleOptionButton *btn = + qstyleoption_cast(option)) { + QStyleOptionButton tmpBtn = *btn; + if (btn->features & QStyleOptionButton::Flat) { // more like a toolbtn + //TODO: handle focus indication here (or in the primitive...)! + drawPrimitive(PE_PanelButtonTool, option, painter, widget); + } + else + drawControl(CE_PushButtonBevel, &tmpBtn, painter, widget); +// tmpBtn.rect = subElementRect(SE_PushButtonContents, btn, widget); + tmpBtn.rect = btn->rect.adjusted(dpi.$4,dpi.$3,-dpi.$4,-dpi.$4); + drawControl(CE_PushButtonLabel, &tmpBtn, painter, widget); + } + break; + case CE_PushButtonBevel: // The bevel and default indicator of a QPushButton. + if (const QStyleOptionButton *btn = + qstyleoption_cast(option)) { + drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + if (btn->features & QStyleOptionButton::HasMenu) { +// int mbi = pixelMetric(PM_MenuButtonIndicator, btn, widget); + QStyleOptionButton newBtn = *btn; + int sz = (RECT.height()-dpi.$6)/2; + newBtn.rect = QRect(RECT.right() - (dpi.$4+sz), (RECT.height()-sz)/2+dpi.$2, sz, sz); + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(midColor(COLOR(Window),COLOR(WindowText))); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); + painter->restore(); + } + } + break; + case CE_PushButtonLabel: // The label (icon with text or pixmap) of a QPushButton + if (const QStyleOptionButton *btn = + qstyleoption_cast(option)) { + QRect ir = btn->rect; + uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; + if (!styleHint(SH_UnderlineShortcut, btn, widget)) + tf |= Qt::TextHideMnemonic; + + if (!btn->icon.isNull()) { + QIcon::Mode mode = isEnabled ? QIcon::Normal + : QIcon::Disabled; + if (mode == QIcon::Normal && hasFocus) + mode = QIcon::Active; + QIcon::State state = QIcon::Off; + if (btn->state & State_On) + state = QIcon::On; + QPixmap pixmap = btn->icon.pixmap(btn->iconSize, mode, state); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + + //Center the icon if there is no text + QPoint point; + if (btn->text.isEmpty()) + point = QPoint(ir.x() + ir.width() / 2 - pixw / 2, ir.y() + ir.height() / 2 - pixh / 2); + else + point = QPoint(ir.x() + 2, ir.y() + ir.height() / 2 - pixh / 2); + + if (btn->direction == Qt::RightToLeft) + point.rx() += pixw; + + painter->drawPixmap(visualPos(btn->direction, btn->rect, point), pixmap); + + if (btn->direction == Qt::RightToLeft) + ir.translate(-4, 0); + else + ir.translate(pixw + 4, 0); + ir.setWidth(ir.width() - (pixw + 4)); + // left-align text if there is + if (!btn->text.isEmpty()) + tf |= Qt::AlignLeft; + } + else + tf |= Qt::AlignHCenter; + + painter->save(); + QColor fc, bc; + if (btn->features & QStyleOptionButton::Flat) { + bc = COLOR(Window); + fc = COLOR(WindowText); + } + else { + bc = btnBgColor(PAL, isEnabled, hover || hasFocus); + fc = btnFgColor(PAL, isEnabled, hover || hasFocus); + } + if (qGray(bc.rgb()) < 148) { // dark background, let's paint an emboss + painter->setPen(bc.dark(103)); + ir.moveTop(ir.top()-1); + drawItemText(painter, ir, tf, PAL, isEnabled, btn->text); + ir.moveTop(ir.top()+1); + } + painter->setPen(fc); + drawItemText(painter, ir, tf, PAL, isEnabled, btn->text); + painter->restore(); + } + break; + case CE_DockWidgetTitle: // Dock window title. + if (const QStyleOptionDockWidget *dwOpt = + qstyleoption_cast(option)) { + QRect textRect; + int x3 = RECT.right()-7; + if (dwOpt->floatable) + x3 -= 18; + if (dwOpt->closable) + x3 -= 18; + int x2 = x3; + if (!dwOpt->title.isEmpty()) { + int itemtextopts = Qt::AlignCenter | Qt::TextShowMnemonic; + drawItemText(painter, RECT, itemtextopts, PAL, isEnabled, dwOpt->title, QPalette::WindowText); + textRect = painter->boundingRect ( RECT, itemtextopts, dwOpt->title ); + x2 = textRect.x()-8; + } + + const Tile::Line &line = shadows.line[0][Sunken]; + textRect.setTop(textRect.top()+(textRect.height()-line.thickness())/2); + int x = textRect.right()+dpi.$4; + textRect.setRight(textRect.left()-dpi.$4); + textRect.setLeft(qMin(RECT.x()+RECT.width()/4,textRect.x()-(textRect.x()-RECT.x())/2)); + line.render(textRect, painter, Tile::Left|Tile::Center); + textRect.setLeft(x); + textRect.setRight(qMax(RECT.right()-RECT.width()/4,x+(RECT.right()-x)/2)); + line.render(textRect, painter, Tile::Right|Tile::Center); + //TODO: hover? + } + break; + case CE_Splitter: // Splitter handle; see also QSplitter. + drawPrimitive(PE_IndicatorDockWidgetResizeHandle,option,painter,widget); + break; + case CE_RadioButton: // A QRadioButton, draws a PE_ExclusiveRadioButton, a case CE_RadioButtonLabel + case CE_CheckBox: // A QCheckBox, draws a PE_IndicatorCheckBox, a case CE_CheckBoxLabel + if (const QStyleOptionButton *btn = + qstyleoption_cast(option)) { + QStyleOptionButton subopt = *btn; + if (element == CE_RadioButton) { + subopt.rect = subElementRect(SE_RadioButtonIndicator, btn, widget); + drawPrimitive(PE_IndicatorRadioButton, &subopt, painter, widget); + subopt.rect = subElementRect(SE_RadioButtonContents, btn, widget); + drawControl(CE_RadioButtonLabel, &subopt, painter, widget); + } + else { + subopt.rect = subElementRect(SE_CheckBoxIndicator, btn, widget); + drawPrimitive(PE_IndicatorCheckBox, &subopt, painter, widget); + subopt.rect = subElementRect(SE_CheckBoxContents, btn, widget); + drawControl(CE_CheckBoxLabel, &subopt, painter, widget); + } + } + break; +// case CE_CheckBoxLabel: // The label (text or pixmap) of a QCheckBox +// case CE_RadioButtonLabel: // The label (text or pixmap) of a QRadioButton + case CE_TabBarTab: // The tab and label within a QTabBar + if (const QStyleOptionTab *tab = + qstyleoption_cast(option)) { + // do we have to exclude the scrollers? + bool needRestore = false; + if (widget && (RECT.right() > widget->width())) { + painter->save(); + needRestore = true; + QRect r = RECT; + r.setRight(widget->width() - + 2*pixelMetric(PM_TabBarScrollButtonWidth,option,widget)); + painter->setClipRect(r); + } + // paint shape and label + drawControl(CE_TabBarTabShape, tab, painter, widget); + drawControl(CE_TabBarTabLabel, tab, painter, widget); + if (needRestore) + painter->restore(); + } + break; + case CE_TabBarTabShape: // The tab shape within a tab bar + if (const QStyleOptionTab *tab = + qstyleoption_cast(option)) { + const bool selected = option->state & State_Selected; + IndexedFadeInfo *info = 0; + int index = -1, hoveredIndex = -1, step = 0; + + // fade animation stuff + if (widget) + if (const QTabBar* tbar = qobject_cast(widget)) { + // NOTICE: the index increment is IMPORTANT to make sure it's no "0" + index = tbar->tabAt(RECT.topLeft()) + 1; // is the action for this item! + hoveredIndex = hover ? index : + tbar->tabAt(tbar->mapFromGlobal(QCursor::pos())) + 1; + info = const_cast(indexedFadeInfo(widget, hoveredIndex)); + } + if (info) + step = info->step(index); + + // maybe we're done here?! + if (!(step || hover || selected || sunken)) + break; + + int size = 0; + const int $2 = dpi.$2, $4 = dpi.$4; + Tile::PosFlags pf = Tile::Ring; + Qt::Orientation o = Qt::Vertical; + QRect rect = RECT; + + // invert the shape alignment if we're not on a tabwidget + // (safari style tabs) + int shape = tab->shape; + if (widget && !(widget->parentWidget() && + qobject_cast(widget->parentWidget()))) { + //NOTICE: this is elegant but NOT invariant against enum changes!!! + shape%2 ? --shape : ++shape; + } + + if (selected) { + QRect fillRect = RECT; + switch ((QTabBar::Shape)shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: { + pf &= ~Tile::Bottom; + const QPixmap &shadow = tabShadow(fillRect.height()-$4); + rect.adjust(0, $2, 0, 0); + fillRect = rect.adjusted($2, $2, -$2, 0); + painter->drawPixmap(fillRect.topRight(), shadow); + break; + } + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: { + pf &= ~Tile::Top; + const QPixmap &shadow = tabShadow(fillRect.height()-$4, true); + rect.adjust(0, 0, 0, -$2); + fillRect = rect.adjusted($2, 0, -$2, -$4); + painter->drawPixmap(fillRect.topRight(), shadow); + break; + } + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + pf &= ~Tile::Left; + fillRect.adjust(0, $2, -dpi.$6, -$4); + rect.adjust(0, 0, -$4, 0); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + pf &= ~Tile::Right; + fillRect.adjust(dpi.$6, $2, 0, -$4); + rect.adjust($4, 0, 0, 0); + break; + } + QPoint zero = fillRect.topLeft(); + if (widget) + zero = widget->mapTo(widget->topLevelWidget(), zero); + fillWithMask(painter, fillRect, PAL.brush(QPalette::Window), + &masks.tab, pf | Tile::Center, false, zero); + shadows.tab.render(rect, painter, pf); + } + else { + QPoint off; + switch ((QTabBar::Shape)shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + if (sunken) + rect.adjust(0, rect.height()/4, 0, -rect.height()/4); + else + rect.setTop(rect.bottom()-rect.height()/2); + size = RECT.height()-dpi.$2; + off = QPoint(0, rect.y()-(RECT.y()+dpi.$2)); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + rect = RECT.adjusted(0,$4,0,-dpi.$6); + size = rect.height(); + off = QPoint(0, -dpi.$1); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + o = Qt::Horizontal; + rect = RECT.adjusted($4,0,-dpi.$6, 0); + size = rect.width(); + off = QPoint(-dpi.$1, 0); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + o = Qt::Horizontal; + rect = RECT.adjusted(dpi.$6,0,-$4, 0); + size = RECT.width()-$4; + off = QPoint(-dpi.$1, 0); + break; + } + + if (sunken) step = 12; + else if (!step) step = 6; +#if 0 + QColor c = midColor(PAL.color(config.role_tab[0]), COLOR(Highlight), + 12-step, 8); +#else + QColor c = PAL.color(config.role_tab[0]); + int h,s,v; c.getHsv(&h,&s,&v); + if (v < 80) v = 80; + v = ((100+step*7)*v)/100; + c.setHsv(h,s,CLAMP(v,0,255)); +#endif + const QPixmap &fill = gradient(c, size, o, + config.gradientStrong); + fillWithMask(painter, rect, fill, &lights.button, Tile::Full, false, off ); + } + } + break; + case CE_TabBarTabLabel: // The label within a tab + if (const QStyleOptionTab *tab = + qstyleoption_cast(option)) { + painter->save(); + QStyleOptionTabV2 tabV2(*tab); + QRect tr = tabV2.rect; + bool verticalTabs = false; + bool east = false; + bool selected = tabV2.state & State_Selected; + if (selected) hover = false; + int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; + bool bottom = false; + + int shape = tab->shape; + if (widget && !(widget->parentWidget() && + qobject_cast(widget->parentWidget()))) { + //NOTICE: this is elegant but NOT invariant against enum changes!!! + shape%2 ? --shape : ++shape; + } + + switch((QTabBar::Shape)shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + if (selected) + tr.setTop(tr.top()+dpi.$2); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + bottom = true; + if (selected) + tr.setBottom(tr.bottom()-2); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + if (selected) tr.setRight(tr.right()-2); + verticalTabs = true; east = true; + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + if (selected) tr.setLeft(tr.left()+2); + verticalTabs = true; + break; + } + + if (verticalTabs) { + int newX, newY, newRot; + if (east) { + newX = tr.width(); newY = tr.y(); newRot = 90; + } + else { + newX = 0; newY = tr.y() + tr.height(); newRot = -90; + } + tr.setRect(0, 0, tr.height(), tr.width()); + QMatrix m; + m.translate(newX, newY); m.rotate(newRot); + painter->setMatrix(m, true); + } + + if (!tabV2.icon.isNull()) { + QSize iconSize = tabV2.iconSize; + if (!iconSize.isValid()) { + int iconExtent = pixelMetric(PM_SmallIconSize); + iconSize = QSize(iconExtent, iconExtent); + } + QPixmap tabIcon = tabV2.icon.pixmap(iconSize, (isEnabled) ? + QIcon::Normal : QIcon::Disabled); + painter->drawPixmap(tr.left() + 6, + tr.center().y() - tabIcon.height() / 2, tabIcon); + tr.setLeft(tr.left() + iconSize.width() + 4); + } + + // color adjustment + QColor cF, cB; + if (selected) { + cF = COLOR(WindowText); cB = COLOR(Window); + } + else { + cF = PAL.color(config.role_tab[1]); + cB = PAL.color(config.role_tab[0]); + } + + if (qGray(cB.rgb()) < 148) { // dark background, let's paint an emboss + painter->setPen(cB.dark(120)); + tr.moveTop(tr.top()-1); + drawItemText(painter, tr, alignment, PAL, isEnabled, tab->text); + tr.moveTop(tr.top()+1); + } + painter->setPen(cF); + drawItemText(painter, tr, alignment, PAL, isEnabled, tab->text); + + painter->restore(); + } + break; + case CE_ProgressBar: // CE_ProgressBarGroove, CE_ProgressBarContents, CE_ProgressBarLabel + if (const QStyleOptionProgressBar *pb + = qstyleoption_cast(option)) { + QStyleOptionProgressBarV2 subopt = *pb; + // groove + subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget); + drawControl(CE_ProgressBarGroove, &subopt, painter, widget); + // contents + subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget); + drawControl(CE_ProgressBarContents, &subopt, painter, widget); +#if 0 + // label? + if (false && pb->textVisible) { + subopt.rect = subElementRect(SE_ProgressBarLabel, pb, widget); + drawControl(CE_ProgressBarLabel, &subopt, painter, widget); + } +#endif + } + break; + case CE_ProgressBarGroove: // The groove where the progress indicator is drawn in a QProgressBar + if (const QStyleOptionProgressBarV2 *pb = + qstyleoption_cast(option)) { + int size = RECT.height(); + Qt::Orientation o = Qt::Vertical; + if (pb->orientation == Qt::Vertical) { + size = RECT.width(); + o = Qt::Horizontal; + } + const QPixmap &groove = gradient(PAL.color(config.role_progress[0]), size, + o, config.glassProgress ? GradGlass : GradSunken); + fillWithMask(painter, RECT.adjusted(0,0,0,-dpi.$2), groove, &masks.button, Tile::Full); + if (!animationUpdate) + shadows.lineEdit[isEnabled].render(RECT, painter); + } + break; + case CE_ProgressBarContents: // The progress indicator of a QProgressBar + if (const QStyleOptionProgressBarV2 *pb = + qstyleoption_cast(option)) { + double val = pb->progress; val /= (pb->maximum - pb->minimum); + if (val == 0.0) + break; + QRect r = RECT; int size = r.height(); + Qt::Orientation o = Qt::Vertical; + bool reverse = option->direction == Qt::RightToLeft; + if (pb->invertedAppearance) + reverse = !reverse; + int step = progressStep(widget); + if (pb->orientation == Qt::Vertical) { + size = r.width(); + o = Qt::Horizontal; + r.setTop(r.bottom() - + (int)(val*RECT.height())); + } + else if (reverse) { + r.setLeft(r.right() - + (int)(val*RECT.width())); + } + else { + r.setRight(r.left() + + (int)(val*RECT.width())); + } + const bool unicolor = config.role_progress[0] == config.role_progress[1]; + const QColor c1 = (pb->progress == pb->maximum || unicolor ) ? + PAL.color(config.role_progress[0]) : + midColor( PAL.color(config.role_progress[0]), + PAL.color(config.role_progress[1]), 10, 10+step/2); + const QColor c2 = unicolor ? + PAL.color(config.role_progress[0]).light(85+step) : + midColor( PAL.color(config.role_progress[0]), + PAL.color(config.role_progress[1]), 1, 2); + const QPixmap &chunk1 = gradient(c1, size, o, config.gradientStrong); + const QPixmap &chunk2 = gradient(c2, size, o, config.gradientStrong); + + QPixmap pix; QPainter p; + if (pb->orientation == Qt::Horizontal) { + pix = QPixmap(2*size, size); + p.begin(&pix); + p.fillRect(0,0,size,size, chunk1); + p.fillRect(size,0,size,size, chunk2); + } + else { + pix = QPixmap(size, 2*size); + p.begin(&pix); + p.fillRect(0,0,size,size, chunk1); + p.fillRect(0,size,size,size, chunk2); + } + p.end(); + + fillWithMask(painter, r, pix, &masks.button/*, Tile::Full, false, off*/); + } + break; + case CE_ProgressBarLabel: // The text label of a QProgressBar + break; + if (const QStyleOptionProgressBarV2 *progress = + qstyleoption_cast(option)) { + if (!animationUpdate) + painter->save(); + QFont fnt = painter->font(); + fnt.setBold(true); + painter->setFont(fnt); + QRect rect = RECT; + double val = progress->progress; + bool reverse = option->direction == Qt::RightToLeft; + if (progress->invertedAppearance) reverse = !reverse; + val = val / (progress->maximum - progress->minimum); + QMatrix m; QPalette::ColorRole role; + if (progress->orientation == Qt::Vertical) { + rect.setRect(RECT.x(), RECT.y(), RECT.height(), RECT.width()); + if (progress->bottomToTop) { + m.translate(0.0, RECT.height()); m.rotate(-90); + } + else { + m.translate(RECT.width(), 0.0); m.rotate(90); + } + } + if ( val > 0.0 ) { + int s; + QRect cr; + if (progress->orientation == Qt::Vertical) { + s = qMin( RECT.height(), ( int ) (val * RECT.height() ) ); + if ( s > 1 ) + cr = QRect(RECT.x(), RECT.bottom()-s+1, RECT.width(), s); + } + else { + s = qMin( RECT.width(), ( int ) (val * RECT.width() ) ); + if ( s > 1 ) { +// QRect progressRect = RECT; + cr = RECT; + if (reverse) { + cr.setLeft(RECT.right()-s+1); + cr.setWidth(s); +// int left = progressRect.x()-progressRect.height(); +// for (int i = 0; i < progressRect.height(); i++) +// cr += QRect(left+i,progressRect.y()+i,progressRect.height(),1); + } + else +// { + cr.setWidth(s); +/* int right = progressRect.x()+progressRect.width(); + for (int i = 0; i < progressRect.height(); i++) + cr += QRect(right-i-1, progressRect.y()+i, progressRect.height(),1); + } + cr = QRegion(progressRect) - cr;*/ + } + } +// painter->setClipRegion(cr); + painter->setClipRect(cr); + painter->setMatrix(m); +#if 1 + role = hasFocus?QPalette::HighlightedText:QPalette::Window; +#else + role = hasFocus?QPalette::HighlightedText:QPalette::WindowText; +#endif + drawItemText(painter, rect, Qt::AlignCenter | Qt::TextSingleLine, PAL, isEnabled, + progress->text, role); + painter->resetMatrix(); + painter->setClipRegion(QRegion(RECT).subtract(cr)); + } + if (animationUpdate) + break; + painter->setMatrix(m); +#if 1 + role = hasFocus?QPalette::Highlight:QPalette::WindowText; +#else + role = hasFocus?QPalette::Highlight:QPalette::Window; +#endif + drawItemText(painter, rect, Qt::AlignCenter | Qt::TextSingleLine, PAL, isEnabled, + progress->text, role); + painter->restore(); + } + break; + case CE_ToolButtonLabel: // A tool button's label + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(option)) { + // Arrow type always overrules and is always shown + bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow; + if ((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty() || + toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) { + drawItemText(painter, RECT, + Qt::AlignCenter | Qt::TextShowMnemonic, PAL, + isEnabled, toolbutton->text, QPalette::WindowText); + } + else { + QPixmap pm; + QSize pmSize = toolbutton->iconSize; + if (!toolbutton->icon.isNull()) { + QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off; + QIcon::Mode mode; + if (!isEnabled) + mode = QIcon::Disabled; + else if (hover && (option->state & State_AutoRaise)) + mode = QIcon::Active; + else + mode = QIcon::Normal; + pm = toolbutton->icon.pixmap(RECT.size().boundedTo(toolbutton->iconSize), mode, state); + pmSize = pm.size(); + } + + if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) { + painter->setFont(toolbutton->font); + QRect pr = RECT, tr = RECT; + int alignment = Qt::TextShowMnemonic; + + if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { + int fh = painter->fontMetrics().height(); + pr.adjust(0, dpi.$3, 0, -fh - dpi.$5); + tr.adjust(0, pr.bottom(), 0, -dpi.$3); + if (!hasArrow) + drawItemPixmap(painter, pr, Qt::AlignCenter, pm); + else + drawArrow(this, toolbutton, pr, painter, widget); + alignment |= Qt::AlignCenter; + } + else { + pr.setWidth(pmSize.width() + dpi.$8); + tr.adjust(pr.right(), 0, 0, 0); + if (!hasArrow) + drawItemPixmap(painter, pr, Qt::AlignCenter, pm); + else + drawArrow(this, toolbutton, pr, painter, widget); + alignment |= Qt::AlignLeft | Qt::AlignVCenter; + } + drawItemText(painter, tr, alignment, PAL, isEnabled, toolbutton->text, QPalette::WindowText); + } + else { + if (hasArrow) + drawArrow(this, toolbutton, RECT.adjusted(dpi.$5,dpi.$5,-dpi.$5,-dpi.$5), painter, widget); + else + drawItemPixmap(painter, RECT, Qt::AlignCenter, pm); + } + } + } + break; + case CE_MenuBarItem: // A menu item in a QMenuBar + if (const QStyleOptionMenuItem *mbi = + qstyleoption_cast(option)) { + QPalette::ColorRole cr = QPalette::WindowText; + IndexedFadeInfo *info = 0; + QAction *action = 0, *activeAction = 0; + int step = 0; + if (widget) + if (const QMenuBar* mbar = qobject_cast(widget)) { + action = mbar->actionAt(RECT.topLeft()); // is the action for this item! + activeAction = mbar->activeAction(); + info = const_cast(indexedFadeInfo(widget, (long int)activeAction)); + } + if (info && (!activeAction || !activeAction->menu() || + activeAction->menu()->isHidden())) + step = info->step((long int)action); + if (step || option->state & State_Selected) { + QRect r = RECT; + if (step) { + step = 6-step; + int dx = step*r.width()/18, dy = step*r.height()/18; + r.adjust(dx, dy, -dx, -dy); + } + QRect rect = r; + if (sunken) + rect.adjust(dpi.$2, dpi.$1, -dpi.$2, -dpi.$2); + shadows.button[sunken][true].render(rect, painter); + rect = r.adjusted(dpi.$3, dpi.$2, -dpi.$3, -dpi.$3); + const QPixmap &fill = gradient(CONF_COLOR(role_popup[0]), rect.height(), Qt::Vertical, config.gradient); + fillWithMask(painter, rect, fill, &masks.button); + masks.button.outline(rect, painter, Qt::white, true); + cr = config.role_popup[1]; + } + QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize), isEnabled ? QIcon::Normal : QIcon::Disabled); + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!pix.isNull()) + drawItemPixmap(painter,mbi->rect, alignment, pix); + else + drawItemText(painter, mbi->rect, alignment, mbi->palette, isEnabled, mbi->text, cr); + } + break; + case CE_MenuBarEmptyArea: // The empty area of a QMenuBar + break; + case CE_MenuItem: // A menu item in a QMenu + // Draws one item in a popup menu. + if (const QStyleOptionMenuItem *menuItem = + qstyleoption_cast(option)) { + bool selected = menuItem->state & State_Selected; + QPalette::ColorRole fgr = QPalette::WindowText; + QPalette::ColorRole bgr = QPalette::Window; + if (widget) { + bgr = widget->backgroundRole(); + fgr = widget->foregroundRole(); + } + + if (selected && isEnabled) { + QPalette::ColorRole hlp = bgr; bgr = fgr; fgr = hlp; + } + + QColor bg = PAL.color(bgr); + QColor fg = isEnabled ? PAL.color(fgr) : + midColor(PAL.color(bgr),PAL.color(fgr),2,1); + + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + int dx = RECT.width()/6, + dy = (RECT.height()-shadows.line[0][Sunken].thickness())/2; + shadows.line[0][Sunken].render(RECT.adjusted(dx,dy,-dx,-dy), painter); + if (!menuItem->text.isEmpty()) { + painter->setFont(menuItem->font); + drawItemText(painter, RECT, Qt::AlignCenter, PAL, isEnabled, + menuItem->text, fgr); + } + break; + } + painter->save(); + bool checkable = + (menuItem->checkType != QStyleOptionMenuItem::NotCheckable); + bool checked = checkable && menuItem->checked; + + + if (selected && isEnabled) + fillWithMask(painter, RECT, + gradient(bg, RECT.height(), Qt::Vertical, config.gradient), + &masks.button, Tile::Full); + + // Text and icon, ripped from windows style + const QStyleOptionMenuItem *menuitem = menuItem; + int iconCol = config.showMenuIcons*menuitem->maxIconWidth; + + if (config.showMenuIcons && !menuItem->icon.isNull()) { + QRect vCheckRect = visualRect(option->direction, RECT, + QRect(RECT.x(), RECT.y(), iconCol, RECT.height())); + QIcon::Mode mode = isEnabled ? (selected ? QIcon::Active : + QIcon::Normal) : QIcon::Disabled; + QPixmap pixmap = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize), + mode, checked ? QIcon::On : QIcon::Off); + + QRect pmr(QPoint(0, 0), pixmap.size()); + pmr.moveCenter(vCheckRect.center()); + + painter->drawPixmap(pmr.topLeft(), pixmap); + } + + painter->setPen ( fg ); + painter->setBrush ( Qt::NoBrush ); + + int x, y, w, h; + RECT.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + int cDim = 2*(RECT.height() - dpi.$4)/3; + int xm = windowsItemFrame + iconCol + windowsItemHMargin; + int xpos = RECT.x() + xm; + QRect textRect(xpos, y + windowsItemVMargin, + w - xm - menuItem->menuHasCheckableItems*(cDim+dpi.$7) - + windowsRightBorder - tab + 1, + h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(option->direction, RECT, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { + // draw text + int t = s.indexOf('\t'); + const int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | + Qt::TextDontClip | Qt::TextSingleLine; + if (t >= 0) { + QRect vShortcutRect = visualRect(option->direction, RECT, + QRect(textRect.topRight(), + QPoint(textRect.right()+tab, textRect.bottom()))); + painter->drawText(vShortcutRect, text_flags | Qt::AlignLeft, s.mid(t + 1)); + s = s.left(t); + } + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) { + QFont font = menuitem->font; + font.setBold(true); + painter->setFont(font); + } + painter->drawText(vTextRect, text_flags | Qt::AlignLeft, s.left(t)); + } + // Arrow + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) { + // draw sub menu arrow + PrimitiveElement arrow = (option->direction == Qt::RightToLeft) ? + PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + + int dim = RECT.height()/3; + xpos = RECT.x() + RECT.width() - dpi.$7 - dim; + + QStyleOptionMenuItem tmpOpt = *menuItem; + tmpOpt.rect = visualRect(option->direction, RECT, + QRect(xpos, RECT.y() + + (RECT.height() - dim)/2, dim, dim)); + painter->setPen(midColor(bg, fg, 1, 3)); + drawPrimitive(arrow, &tmpOpt, painter, widget); + } + else if (checkable) { // Checkmark + xpos = RECT.right() - dpi.$7 - cDim; + QRect checkRect(xpos, RECT.y() + (RECT.height() - cDim)/2, cDim, cDim); + checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); + if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) { + // Radio button + painter->setRenderHint ( QPainter::Antialiasing ); + painter->drawEllipse ( checkRect ); + if (checked || sunken) { + painter->setBrush ( fg ); + painter->drawEllipse ( checkRect.adjusted(checkRect.width()/4, + checkRect.height()/4, -checkRect.width()/4, + -checkRect.height()/4) ); +// painter->setBrush ( Qt::NoBrush ); + } + } + else { + // Check box +// painter->setBrush ( Qt::NoBrush ); + QStyleOptionMenuItem tmpOpt = *menuItem; + tmpOpt.rect = checkRect; + if (checked) + tmpOpt.state |= State_On; + else + tmpOpt.state &= ~State_On; + drawPrimitive(PE_IndicatorMenuCheckMark, &tmpOpt, painter, widget); + } + } + painter->restore(); + } + break; + case CE_MenuScroller: { // Scrolling areas in a QMenu when the style supports scrolling + QPalette::ColorRole bg = widget ? widget->backgroundRole() : QPalette::Window; + if (option->state & State_DownArrow) { + painter->drawTiledPixmap(RECT, gradient(PAL.color(QPalette::Active, bg), + RECT.height()*2, Qt::Vertical, sunken ? GradSunken : GradSimple), QPoint(0,RECT.height())); + drawPrimitive(PE_IndicatorArrowDown, option, painter, widget); + } + else { + painter->drawTiledPixmap(RECT, gradient(PAL.color(QPalette::Active, bg), + RECT.height()*2, Qt::Vertical, sunken ? GradSunken : GradSimple)); + drawPrimitive(PE_IndicatorArrowUp, option, painter, widget); + } + break; + } +// case CE_MenuTearoff: // A menu item representing the tear off section of a QMenu + case CE_MenuEmptyArea: // The area in a menu without menu items + case CE_MenuHMargin: // The horizontal extra space on the left/right of a menu + case CE_MenuVMargin: { // The vertical extra space on the top/bottom of a menu +// QPalette::ColorRole role = QPalette::Background; +// if (widget) +// role = qobject_cast(widget) ? +// QPalette::WindowText : widget->backgroundRole(); +// painter->fillRect(RECT, PAL.brush(role)); + break; + } + case CE_Q3DockWindowEmptyArea: // The empty area of a QDockWidget + break; + case CE_ToolBoxTab: // The toolbox's tab area + if (const QStyleOptionToolBox* tbt = + qstyleoption_cast(option)) { + + // Qt does some funky color updates on the toolboxbutton palette, leading to button color on init display, so i just skip it and use daddies palette... + const QPalette &pal = (widget && widget->parentWidget()) ? + widget->parentWidget()->palette() : PAL; + + QPalette::ColorRole role = QPalette::WindowText, bgRole = QPalette::Window; + if (isEnabled) { + if (option->state & State_Selected) { + const QPixmap &fill = gradient(pal.color(QPalette::WindowText), + RECT.height(), Qt::Vertical, + config.gradientStrong); + painter->drawTiledPixmap(RECT, fill); + QFont f(painter->font()); + f.setBold(true); + painter->setFont(f); + bgRole = QPalette::WindowText; + role = QPalette::Window; + } + else { + painter->drawTiledPixmap(RECT, gradient(pal.color(QPalette::Window), + RECT.height(), Qt::Vertical, sunken ? + GradSunken : hover ? + config.gradientStrong : + config.gradient) ); + } + } +/*======================================================================== + i WANT (read this TrottelTech: WANT!) this to be color swapped on + select (and centered as sugar on top) + now as the toolboxbutton is a private class and it's selected member is + as well, i cannot overwrite the paint event + so instead i respond a null rect for selected tabs contents + (from subElementRect query), what makes the widget abort the content + painting - then i paint it instead... works ;) +========================================================================*/ + const QPixmap &pm = + tbt->icon.pixmap(pixelMetric(QStyle::PM_SmallIconSize), + isEnabled ? QIcon::Normal : QIcon::Disabled); + + QRect cr = option->rect.adjusted(0, 0, -30, 0); + QRect tr, ir; + int ih = 0; + if (pm.isNull()) { + tr = cr; + tr.adjust(4, 0, -8, 0); + } + else { + int iw = pm.width() + 4; + ih = pm.height(); + ir = QRect(cr.left() + 4, cr.top(), iw + 2, ih); + tr = QRect(ir.right(), cr.top(), cr.width() - ir.right() - 4, cr.height()); + } + + QString txt = tbt->text; + if (painter->fontMetrics().width(txt) > tr.width()) { + txt = txt.left(1); + int ew = painter->fontMetrics().width("..."); + int i = 1; + while (painter->fontMetrics().width(txt) + ew + painter->fontMetrics().width(tbt->text[i]) < tr.width()) + txt += tbt->text[i++]; + txt += "..."; + } + + if (ih) + painter->drawPixmap(ir.left(), (RECT.height() - ih) / 2, pm); + + // dark background, let's paint an emboss + if (qGray(pal.color(bgRole).rgb()) < 128) { + painter->save(); + painter->setPen(pal.color(bgRole).dark(120)); + tr.moveTop(tr.top()-1); + drawItemText(painter, tr, Qt::AlignCenter | Qt::TextShowMnemonic, + pal, isEnabled, txt); + tr.moveTop(tr.top()+1); + painter->restore(); + } + + drawItemText(painter, tr, Qt::AlignCenter | Qt::TextShowMnemonic, + pal, isEnabled, txt, role); + } + break; +// case CE_SizeGrip: // Window resize handle; see also QSizeGrip. + case CE_Header: // A header + if (const QStyleOptionHeader *header = + qstyleoption_cast(option)) { + // init + const QRegion clipRegion = painter->clipRegion(); + painter->setClipRect(option->rect); + QStyleOptionHeader subopt = *header; + const QHeaderView* hdv = qobject_cast(widget); + // extend the sunken state on sorting headers + sunken = sunken || + (hdv && hdv->isClickable () && hdv->sortIndicatorSection() == header->section); + if (sunken) + subopt.state |= State_Sunken; + + // base + drawControl(CE_HeaderSection, &subopt, painter, widget); + + // label + subopt.rect = subElementRect(SE_HeaderLabel, header, widget); + if (subopt.rect.isValid()) + drawControl(CE_HeaderLabel, &subopt, painter, widget); + + // sort Indicator on sorting or (inverted) on hovered headers + if (hover && hdv && hdv->isSortIndicatorShown()) { + if (subopt.sortIndicator == QStyleOptionHeader::SortDown) + subopt.sortIndicator = QStyleOptionHeader::SortUp; + else + subopt.sortIndicator = QStyleOptionHeader::SortDown; + } + if (subopt.sortIndicator != QStyleOptionHeader::None) { + subopt.rect = subElementRect(SE_HeaderArrow, option, widget); + painter->save(); + if (hover) + painter->setPen(COLOR(Text)); + else + painter->setPen(Qt::NoPen); + const QPixmap &fill = gradient(hover?COLOR(Base):midColor(COLOR(Text),COLOR(Base)), RECT.height(), Qt::Vertical, sunken?GradSunken:config.gradient); + painter->setBrush(fill); + drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget); + painter->restore(); + } + painter->setClipRegion(clipRegion); + break; + } + case CE_HeaderSection: { // A header section + if (sunken) + painter->drawTiledPixmap(RECT, gradient(COLOR(Text), RECT.height(), Qt::Vertical, GradSunken)); + else { + QRect r = RECT; r.setWidth(RECT.width()-1); + painter->drawTiledPixmap(r, gradient(COLOR(Text), RECT.height(), Qt::Vertical, hover?config.gradientStrong:config.gradient)); + r = RECT; r.setLeft(r.right()-dpi.$1); + painter->drawTiledPixmap(r, gradient(COLOR(Text), RECT.height(), Qt::Vertical, GradSunken)); + } + break; + } + case CE_HeaderLabel: { // The header's label + const QStyleOptionHeader* hopt = qstyleoption_cast(option); + QRect rect = option->rect; + if ( !hopt->icon.isNull() ) { + QPixmap pixmap = hopt->icon.pixmap( 22,22, isEnabled ? QIcon::Normal : QIcon::Disabled ); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + + QRect pixRect = option->rect; + pixRect.setY( option->rect.center().y() - (pixh - 1) / 2 ); + // "pixh - 1" because of tricky integer division + drawItemPixmap ( painter, pixRect, Qt::AlignCenter, pixmap ); + rect.setLeft( rect.left() + pixw + 2 ); + } + if (hopt->text.isEmpty()) + break; + painter->save(); + QColor bg = COLOR(Text), fg = COLOR(Base); + if (qGray(bg.rgb()) < 148) { // dark background, let's paint an emboss + rect.moveTop(rect.top()-1); + painter->setPen(bg.dark(120)); + drawItemText ( painter, rect, Qt::AlignCenter, PAL, isEnabled, hopt->text); + rect.moveTop(rect.top()+1); + } + painter->setPen(fg); + drawItemText ( painter, rect, Qt::AlignCenter, PAL, isEnabled, hopt->text); + painter->restore(); + break; + } + case CE_ScrollBarAddLine: // ======= scroll down + if (option->state & State_Item) { // combobox scroller + painter->save(); + painter->setPen(hover?COLOR(Text):midColor(COLOR(Base),COLOR(Text))); + QStyleOption opt = *option; + opt.rect = RECT.adjusted(RECT.width()/4, RECT.height()/4, + -RECT.width()/4, -RECT.height()/4); + if (option->state & QStyle::State_Horizontal) + drawPrimitive (PE_IndicatorArrowRight, &opt, painter, widget); + else + drawPrimitive (PE_IndicatorArrowDown, &opt, painter, widget); + painter->restore(); + break; + } + case CE_ScrollBarSubLine: // ======= scroll up + if (option->state & State_Item) { // combobox scroller + painter->save(); + painter->setPen(hover?COLOR(Text):midColor(COLOR(Base),COLOR(Text))); + QStyleOption opt = *option; + opt.rect = RECT.adjusted(RECT.width()/4, RECT.height()/4, + -RECT.width()/4, -RECT.height()/4); + if (option->state & QStyle::State_Horizontal) + drawPrimitive (PE_IndicatorArrowLeft, &opt, painter, widget); + else + drawPrimitive (PE_IndicatorArrowUp, &opt, painter, widget); + painter->restore(); + break; + } + if (const QStyleOptionSlider *opt = + qstyleoption_cast(option)) { + bool alive = isEnabled && ((element == CE_ScrollBarAddLine && + opt->sliderValue < opt->maximum) || + (element == CE_ScrollBarSubLine && + opt->sliderValue > opt->minimum)); + hover = hover && alive; + QPoint xy = RECT.topLeft(); + if (sunken || !alive) + painter->drawPixmap(xy+QPoint(dpi.$1,dpi.$1), shadows.radio[1][hover]); + else + painter->drawPixmap(xy, shadows.radio[0][hover]); + xy += QPoint(dpi.$2,dpi.$1); + int sz = dpi.ExclusiveIndicator - dpi.$4; + fillWithMask(painter, xy, gradient(btnBgColor(PAL, alive, hover, complexStep), + sz, Qt::Vertical, + alive?config.gradient:GradSunken), masks.radio); + break; + } + case CE_ScrollBarSubPage: // Scroll bar page decrease indicator (i.e., page up). + case CE_ScrollBarAddPage: {// Scolllbar page increase indicator (i.e., page down). + if (option->state & State_Item) // combobox scroller + break; + + SAVE_PEN; + painter->setPen(QPen(COLOR(Window).dark(120), dpi.$2)); + if (option->state & QStyle::State_Horizontal) { + const int y = RECT.center().y(); + painter->drawLine(RECT.x(), y, RECT.right(), y); + } + else { + const int x = RECT.center().x(); + painter->drawLine(x, RECT.y(), x, RECT.bottom()); + } + RESTORE_PEN; + break; + } + case CE_ScrollBarSlider: // Scroll bar slider. + if (option->state & State_Item) { + painter->fillRect(RECT.adjusted(dpi.$2, 0, -dpi.$2, 0), + (hover || sunken) ? COLOR(Text) : + midColor(COLOR(Base), COLOR(Text), 8, 1)); + break; + } + if (/*const QStyleOptionSlider *opt =*/ + qstyleoption_cast(option)) { + + // the groove (if min == max, i.e. no slide usefull) + if (!isEnabled) { + SAVE_PEN; + painter->setPen(QPen(COLOR(Window).dark(120), dpi.$2)); + if (option->state & QStyle::State_Horizontal) { + const int y = RECT.center().y(); + painter->drawLine(RECT.x(), y, RECT.right(), y); + } + else { + const int x = RECT.center().x(); + painter->drawLine(x, RECT.y(), x, RECT.bottom()); + } + RESTORE_PEN; + break; + } + + // we need to paint a slider + int size; Qt::Orientation direction; + hover = hover || sunken; + QRect r = RECT; + if (sunken) r.adjust(dpi.$1,dpi.$1,-dpi.$1,-dpi.$2); + shadows.button[sunken][hover].render(r, painter); + r = RECT.adjusted(dpi.$2,dpi.$1,-dpi.$2,-dpi.$3); + if (option->state & QStyle::State_Horizontal) { + size = r.height(); direction = Qt::Vertical; + } + else { + size = r.width(); direction = Qt::Horizontal; + } + + // slider base + fillWithMask(painter, r, gradient(btnBgColor(PAL, isEnabled, hover, complexStep), + size, direction, config.gradBtn), &masks.button); + masks.button.outline(r, painter, Qt::white, true); + + // and maybe a "scrollarea hovered indicator" + if (hover && !complexStep) + break; + int step = hoverStep(widget); + if (step || scrollAreaHovered(widget)) { + int dx, dy, off = sunken?dpi.$1:0; + if (option->state & QStyle::State_Horizontal) { + dx = r.width()/10+dpi.$1; dy = r.height()/3; + r.adjust(dx,dy+off,-dx,-dy+off); + size = r.height(); + } + else { + dx = r.width()/3; dy = r.height()/10+dpi.$1; + r.adjust(dx+off,dy,-dx+off,-dy); + size = r.width(); + } + painter->drawTiledPixmap(r, gradient(btnBgColor(PAL, isEnabled, true, step), + size, direction, config.gradBtn)); + } + } + break; +// case CE_ScrollBarFirst: // Scroll bar first line indicator (i.e., home). +// case CE_ScrollBarLast: // Scroll bar last line indicator (i.e., end). + case CE_RubberBand: {// Rubber band used in such things as iconview. + painter->save(); + QColor c = COLOR(Highlight); + painter->setPen(c); + c.setAlpha(100); + painter->setBrush(c); + painter->drawRect(RECT.adjusted(0,0,-1,-1)); + painter->restore(); + break; + } + case CE_FocusFrame: // Focus Frame that can is style controled. + break; + case CE_ComboBoxLabel: // The label of a non-editable QComboBox + if (const QStyleOptionComboBox *cb = + qstyleoption_cast(option)) { + QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget); + painter->save(); + painter->setClipRect(editRect); + // icon + if (!cb->currentIcon.isNull()) { + QIcon::Mode mode = isEnabled ? QIcon::Normal + : QIcon::Disabled; + QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(cb->iconSize.width() + 4); + iconRect = alignedRect(QApplication::layoutDirection(), Qt::AlignLeft | Qt::AlignVCenter, iconRect.size(), editRect); +/* if (cb->editable) + painter->fillRect(iconRect, opt->palette.brush(QPalette::Base));*/ + drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + + if (cb->direction == Qt::RightToLeft) + editRect.translate(-4 - cb->iconSize.width(), 0); + else + editRect.translate(cb->iconSize.width() + 4, 0); + } + // text + if (!cb->currentText.isEmpty() && !cb->editable) { + int $3 = dpi.$3; + editRect.adjust($3,0, -$3, 0); + painter->setPen(COLOR(Text)); + painter->drawText(editRect, Qt::AlignCenter, cb->currentText); + } + painter->restore(); + } + break; + case CE_ToolBar: + break; + default: + QCommonStyle::drawControl( element, option, painter, widget ); + } // switch +} diff --git a/clients/oxygen/drawprimitive.cpp b/clients/oxygen/drawprimitive.cpp new file mode 100644 index 0000000000..530ad21f0b --- /dev/null +++ b/clients/oxygen/drawprimitive.cpp @@ -0,0 +1,858 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oxygen.h" +#include "oxrender.h" +#include "dynamicbrush.h" + +#include + +#include + +using namespace Oxygen; + +extern int bgYoffset_; +extern Pixmap shadowPix; +extern Config config; +extern Dpi dpi; + +#include "inlinehelp.cpp" +#include "makros.h" + + +void OxygenStyle::drawPrimitive ( PrimitiveElement pe, const QStyleOption * option, QPainter * painter, const QWidget * widget) const { + Q_ASSERT(option); + Q_ASSERT(painter); + + bool sunken = option->state & State_Sunken; + bool isEnabled = option->state & State_Enabled; + bool hover = isEnabled && (option->state & State_MouseOver); + bool hasFocus = option->state & State_HasFocus; + bool up = false; + + + switch ( pe ) { + case PE_FrameDefaultButton: // This frame around a default button, e.g. in a dialog. + // we swap colors instead, frame only on focus! + break; + case PE_PanelButtonCommand: // Button used to initiate an action, for example, a QPushButton. + case PE_PanelButtonBevel: { // Generic panel with a button bevel. + const int $4 = dpi.$4; + //bool isOn = option->state & State_On; + const QStyleOptionButton* opt = qstyleoption_cast(option); + //bool isDefault = opt && (opt->features & QStyleOptionButton::DefaultButton); + + int step = hoverStep(widget); + + QColor c = btnBgColor(PAL, isEnabled, 0, 0); + QRect r = RECT; + + // shadow + shadows.button[sunken][step?step:hover*7].render(r, painter); + + r.adjust($4, $4, -$4, -$4); + + // background + painter->setRenderHint(QPainter::Antialiasing,false); + fillWithMask(painter, r, c, &masks.button); + + // edge and a nice light gradient + painter->setRenderHint(QPainter::Antialiasing); + QLinearGradient lg(r.x(), r.y(), r.x(), r.bottom()); + QGradientStops stops; + stops << QGradientStop( 0, QColor(255,255,255, (isEnabled&&!sunken ? 220 : 160)) ) + << QGradientStop( 0.1, QColor(255,255,255, (isEnabled&&!sunken ? 100 : 60)) ) + << QGradientStop( 1, QColor(255,255,255, (isEnabled&&!sunken ? 50 : 35)) ); + lg.setStops(stops); + QLinearGradient lg2(r.x(), r.y(), r.x(), r.bottom()); + stops.clear(); + stops << QGradientStop( 0, QColor(255,255,255, 40) ) + << QGradientStop( 1, QColor(255,255,255, 0) ); + lg2.setStops(stops); + painter->setPen(QPen(QBrush(lg),1)); + painter->setBrush(lg2); + QRectF rf = r; + rf.adjust(0.5, 0.5,-0.5,-0.5); + painter->drawRoundRect(rf, int(ceil(9*90.0/r.width())), int(ceil(9*90.0/r.height()))); + + // hover effect + QRadialGradient rg = QRadialGradient(r.width()/2.0, 0.35*r.height(), qMax(r.width(),r.height())/2.0 - 5, r.width()/2.0, 0.35*r.height()); + c = btnBgColor(PAL, isEnabled, hover, step); + c.setAlpha(190); + QColor c2= c; + c2.setAlpha(60); + stops << QGradientStop( 0, c ) << QGradientStop( 1, c2 ); + rg.setStops(stops); + painter->setPen(Qt::NoPen); + painter->setBrush(rg); + r.adjust(1,1,-1,-1); + painter->drawRoundRect(r, int(ceil(9*90.0/r.width())), int(ceil(9*90.0/r.height()))); + break; + } + case PE_PanelButtonTool: { // Panel for a Tool button, used with QToolButton. + if (sunken || (option->state & State_On)) { + if (sunken) hover = false; +/* + fillWithMask(painter, RECT, + gradient(COLOR(Window), RECT.height(), Qt::Vertical, + hover ? GradButton : GradSunken), &masks.button); + shadows.lineEdit[1].render(RECT, painter); +*/ + QRect r = RECT; + painter->setRenderHint(QPainter::Antialiasing); + QRadialGradient rg(r.width()/2, r.height()/2, r.height()/2, r.width()/2, r.height()/4); + QGradientStops stops; + stops << QGradientStop( 0, QColor(0,0,0, 50) ) + << QGradientStop( 1, QColor(0,0,0, 0) ); + rg.setStops(stops); + painter->fillRect(r, rg); + rg = QRadialGradient(r.width()/2, r.height()/2, r.height()/2, r.width()/2, 3*r.height()/4); + stops.clear(); + stops << QGradientStop( 0, QColor(255,255,255, 190) ) + << QGradientStop( 1, QColor(255,255,255, 0) ); + rg.setStops(stops); + painter->fillRect(r, rg); + } +/* else if (hover) { + fillWithMask(painter, RECT.adjusted(dpi.$2,dpi.$1,-dpi.$2,0), + gradient(COLOR(Window), RECT.height(), Qt::Vertical, + GradButton), &masks.button); + shadows.group.render(RECT, painter, Tile::Ring); + } +*/ break; + } + case PE_PanelLineEdit: { // Panel for a QLineEdit. + // spinboxes and combos allready have a lineedit as global frame + if (widget && widget->parentWidget() && + (widget->parentWidget()->inherits("QAbstractSpinBox") || + widget->parentWidget()->inherits("QComboBox"))) + break; + if (qstyleoption_cast(option) && + static_cast(option)->lineWidth < 1) { + painter->fillRect(RECT, COLOR(Base)); break; + } + + if (isEnabled) { + fillWithMask(painter, RECT, COLOR(Base), &masks.button); + if (hasFocus) { + painter->save(); + painter->setPen(QPen(COLOR(Highlight), dpi.$2)); + painter->drawLine(RECT.left()+dpi.$4, RECT.bottom(), + RECT.right()-dpi.$3, RECT.bottom()); + painter->restore(); + } + } + shadows.lineEdit[isEnabled].render(RECT, painter); + break; + } + case PE_FrameFocusRect: { // Generic focus indicator. + painter->save(); + painter->setBrush(Qt::NoBrush); + painter->setPen(COLOR(Highlight)); + painter->drawLine(RECT.bottomLeft(), RECT.bottomRight()); + painter->restore(); + break; + } + case PE_IndicatorArrowUp: // Generic Up arrow. + case PE_IndicatorSpinUp: // Up symbol for a spin widget, for example a QSpinBox. + case PE_IndicatorSpinPlus: // Increase symbol for a spin widget. + up = true; + case PE_IndicatorHeaderArrow: // Arrow used to indicate sorting on a list or table header + case PE_IndicatorButtonDropDown: // indicator for a drop down button, for example, a tool button that displays a menu. + case PE_IndicatorArrowDown: // Generic Down arrow. + case PE_IndicatorSpinDown: // Down symbol for a spin widget. + case PE_IndicatorSpinMinus: { // Decrease symbol for a spin widget. + if (const QStyleOptionHeader* hopt = + qstyleoption_cast(option)) { + if (hopt->sortIndicator == QStyleOptionHeader::None) + break; + up = hopt->sortIndicator == QStyleOptionHeader::SortUp; + } + SAVE_ANTIALIAS; + bool hadNoBrush = painter->brush() == Qt::NoBrush; + painter->setRenderHint(QPainter::Antialiasing); + if (hadNoBrush) + painter->setBrush(painter->pen().brush()); + + int w = RECT.width(); + + // we want a golden mean cut arrow ;) 1:1.6180339887498948482 + int x[3], y[2]; + if (w < 8*RECT.height()/5) { + if (w%2) --w; + x[0] = RECT.x(); x[1] = RECT.right(); x[2] = x[0] + w/2; + int h = 5*w/8; if (!(h%2)) --h; + y[0] = RECT.y() + (RECT.height()-h)/2; y[1] = y[0] + h; + } + else { + w = 8*RECT.height()/5; + if (w%2) --w; + x[0] = RECT.x() + (RECT.width()-w)/2; x[1] = x[0] + w; x[2] = x[0] + w/2; + y[0] = RECT.y(); y[1] = RECT.bottom(); + } + if (up) { + // 0.5 is to have sharp horizontal edges + const QPointF points[3] = { QPointF(x[0], y[1]+0.5), QPointF(x[1], y[1]+0.5), QPointF(x[2], y[0]) }; + painter->drawPolygon(points, 3); + } + else { + // 0.5 is to have sharp horizontal edges + const QPointF points[3] = { QPointF(x[0], y[0]-0.5), QPointF(x[1], y[0]-0.5), QPointF(x[2], y[1]) }; + painter->drawPolygon(points, 3); + } + if (hadNoBrush) + painter->setBrush(Qt::NoBrush); + RESTORE_ANTIALIAS; + break; + } + case PE_IndicatorArrowRight: // Generic Right arrow. + up = true; + case PE_IndicatorArrowLeft: { // Generic Left arrow. + SAVE_ANTIALIAS; + bool hadNoBrush = painter->brush() == Qt::NoBrush; + painter->setRenderHint(QPainter::Antialiasing); + if (hadNoBrush) + painter->setBrush(painter->pen().brush()); + int x[2], y[3], h = RECT.height(); + if (h < 8*RECT.width()/5) { + if (h%2) --h; + y[0] = RECT.y(); y[1] = RECT.bottom(); y[2] = y[0] + h/2; + int w = 5*h/8; if (!(w%2)) --w; + x[0] = RECT.x() + (RECT.width()-w)/2; x[1] = x[0] + w; + } + else { + h = 8*RECT.width()/5; + if (h%2) --h; + y[0] = RECT.y() + (RECT.height()-h)/2; y[1] = y[0] + h; y[2] = y[0] + h/2; + x[0] = RECT.x(); x[1] = RECT.right(); + } + if (up) { //right + // 0.5 is to have sharp vertical edge + const QPointF points[3] = { QPointF(x[0]+0.5, y[0]), QPointF(x[0]+0.5, y[1]), QPointF(x[1], y[2]) }; + painter->drawPolygon(points, 3); + } + else { + const QPointF points[3] = { QPointF(x[0], y[2]), QPointF(x[1]-0.5, y[0]), QPointF(x[1]-0.5, y[1]) }; + painter->drawPolygon(points, 3); + } + if (hadNoBrush) + painter->setBrush(Qt::NoBrush); + RESTORE_ANTIALIAS; + break; + } + case PE_IndicatorCheckBox: { // On/off indicator, for example, a QCheckBox. + + drawPrimitive(PE_PanelButtonBevel, option, painter, widget); + + if (!(sunken || (option->state & State_Off))) { + QColor c = btnFgColor(PAL, isEnabled, hover||hasFocus); + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + QRect r = RECT.adjusted(dpi.$6,dpi.$6,-dpi.$6,-dpi.$6); + const QPixmap &fill = gradient(c, r.height(), Qt::Vertical, config.gradBtn); + switch (config.checkType) { + case 0: { + QPen pen(fill, r.width()/5, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin); + painter->setPen(pen); + painter->drawLine(r.x(),r.bottom(),r.right(),r.y()); + if (option->state & State_On) + painter->drawLine(r.x(),r.y(),r.right(),r.bottom()); + break; + } + default: + case 1: { + QPen pen(fill, r.width()/5, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin); + painter->setPen(pen); + const QPoint points[4] = { + QPoint(r.right(), r.top()), + QPoint(r.x()+r.width()/3, r.bottom()), + QPoint(r.x(), r.bottom()-r.height()/3), + QPoint(r.x()+r.width()/3, r.bottom()-r.height()/5) + }; + painter->drawPolygon(points, (option->state & State_On)?4:2); + break; + } + case 2: + if (option->state & State_On) + painter->fillRect(r, fill); + else { + QRect r2 = r; r2.setBottom(r.top()+r.height()/3); + fillWithMask(painter, r2, fill, &masks.button); + r2 = r; r2.setTop(r.bottom()-r.height()/3); + fillWithMask(painter, r2, fill, &masks.button); + } + } + painter->restore(); + } + break; + } + case PE_IndicatorRadioButton: { // Exclusive on/off indicator, for example, a QRadioButton. + bool isOn = option->state & State_On; + if (isOn) sunken = false; + hover = hover && !isOn; + const int $2 = dpi.$2, $1 = dpi.$1; + int step = isOn ? 0 : hoverStep(widget); + QColor c = btnBgColor(PAL, isEnabled, hover||hasFocus, step); + QPoint xy = RECT.topLeft(); + + // shadow + painter->drawPixmap(sunken?xy+QPoint($1,$1):xy, shadows.radio[sunken][hover||hasFocus]); + + // glass + xy += QPoint($2,$1); + int sz = dpi.ExclusiveIndicator - dpi.$4; + if (isEnabled) + fillWithMask(painter, xy, gradient(c, sz, Qt::Vertical, config.gradBtn), masks.radio); + else + fillWithMask(painter, xy, c, masks.radio); + painter->save(); + painter->setBrush(Qt::NoBrush); + painter->setPen(Qt::white); + painter->setRenderHint(QPainter::Antialiasing); + painter->drawEllipse(xy.x(), xy.y(), sz, sz); + painter->restore(); + + if (isOn) { // drop? + xy += QPoint($2,$2); + sz -= dpi.$4; + QColor c = btnFgColor(PAL, isEnabled, hover||hasFocus); + xy += QPoint($2,$2); + fillWithMask(painter, xy, gradient(c, sz, Qt::Vertical, config.gradBtn), masks.radioIndicator); + } + break; + } + case PE_Q3DockWindowSeparator: // Item separator for Qt 3 compatible dock window and toolbar contents. + break; + case PE_Frame: { // Generic frame; see also QFrame. + if (widget) { + // handle the + if (widget->inherits("QComboBoxPrivateContainer")) { + SAVE_PEN; + painter->setPen(COLOR(Base)); + painter->drawRect(RECT.adjusted(0,0,-1,-1)); + RESTORE_PEN; + break; + } + + bool inverse = true, niceFrame = false; + QRect rect = RECT; const QRect *outerRect = 0; + + const Tile::Mask *mask = 0L; const Tile::Set *shadow = 0L; + if (sunken) { + shadow = &shadows.lineEdit[isEnabled]; + mask = &masks.button; + } + else if (option->state & State_Raised) { + shadow = &shadows.tab; + mask = &masks.tab; + } + QPoint zero; + const QBrush *brush = &PAL.brush(widget->backgroundRole()); + if (qobject_cast(widget)) { // frame, can be killed unless... + if (widget->inherits("QTextEdit")) { // ...it's a TextEdit! + niceFrame = true; + inverse = false; brush = &PAL.brush(QPalette::Base); + } + else { // maybe we need to corect a textlabels margin + if (const QLabel* label = qobject_cast(widget)) + if (label->text() != QString() && label->margin() < dpi.$3) + const_cast(label)->setMargin(dpi.$3); + break; // painted on visual frame + } + } + else if (qobject_cast(widget)) { + if (widget->parentWidget() && widget->parentWidget()->parentWidget()) + brush = &PAL.brush(widget->parentWidget()->parentWidget()->backgroundRole()); + niceFrame = true; + zero = widget->mapTo(widget->topLevelWidget(), QPoint(0,0)); + if (!sunken) { + outerRect = &RECT; + if (option->state & State_Raised) + rect = RECT.adjusted(dpi.$2,dpi.$1,-dpi.$2,-dpi.$4); + else + rect = RECT.adjusted(dpi.$2,dpi.$2,-dpi.$2,-dpi.$2); + } + } + if (niceFrame) { + if (mask) + fillWithMask(painter, rect, *brush, mask, Tile::Full, false, zero, inverse, outerRect); + if (hasFocus) { + painter->save(); + painter->setPen(QPen(COLOR(Highlight), dpi.$2)); + painter->drawLine(rect.left()+dpi.$4, rect.bottom(), rect.right()-dpi.$3, rect.bottom()); + painter->restore(); + } + if (shadow) + shadow->render(RECT, painter); + else { // plain frame + //horizontal + shadows.line[false][Sunken].render(RECT, painter, Tile::Full, false); + shadows.line[false][Sunken].render(RECT, painter, Tile::Full, true); + //vertical + shadows.line[true][Sunken].render(RECT, painter, Tile::Full, false); + shadows.line[true][Sunken].render(RECT, painter, Tile::Full, true); + break; + } + break; + } + } + // fallback, we cannot paint shaped frame contents + if (sunken) + shadows.sunken.render(RECT,painter); + else if (option->state & State_Raised) +// shadows.raised.render(RECT,painter); + break; + else { + //horizontal + shadows.line[false][Sunken].render(RECT, painter, Tile::Full, false); + shadows.line[false][Sunken].render(RECT, painter, Tile::Full, true); + //vertical + shadows.line[true][Sunken].render(RECT, painter, Tile::Full, false); + shadows.line[true][Sunken].render(RECT, painter, Tile::Full, true); + } + break; + } + case PE_FrameMenu: { // Frame for popup windows/menus; see also QMenu. + SAVE_PEN; + QRect frame = RECT; + int x,y,w,h; + frame.getRect(&x, &y, &w, &h); + + painter->setRenderHint(QPainter::Antialiasing); + painter->setBrush(Qt::NoBrush); + QLinearGradient lg(0, 0, 0, 10); + QGradientStops stops; + stops << QGradientStop( 0, QColor(255,255,255, 110) ) + << QGradientStop( 1, QColor(128,128,128, 60) ); + lg.setStops(stops); + painter->setPen(QPen(QBrush(lg),1)); + painter->drawLine(QPointF(6.3, 0.5), QPointF(w-6.3, 0.5)); + painter->drawArc(QRectF(0.5, 0.5, 9.5, 9.5),90*16, 90*16); + painter->drawArc(QRectF(w-9.5-0.5, 0.5, 9.5, 9.5), 0, 90*16); + + painter->setPen(QColor(128,128,128, 60)); + painter->drawLine(QPointF(0.5, 6.3), QPointF(0.5, h-6.3)); + painter->drawLine(QPointF(w-0.5, 6.3), QPointF(w-0.5, h-6.3)); + + lg = QLinearGradient(0, h-10, 0, h); + stops.clear(); + stops << QGradientStop( 0, QColor(128,128,128, 60) ) + << QGradientStop( 1, QColor(0,0,0, 50) ); + lg.setStops(stops); + painter->setPen(QPen(QBrush(lg),1)); + painter->drawArc(QRectF(0.5, h-9.5-0.5, 9.5, 9.5),180*16, 90*16); + painter->drawArc(QRectF(w-9.5-0.5, h-9.5-0.5, 9.5, 9.5), 270*16, 90*16); + painter->drawLine(QPointF(6.3, h-0.5), QPointF(w-6.3, h-0.5)); + + RESTORE_PEN; +#if 0 + if (config.glassMenus) { + painter->save(); + painter->setPen(Qt::white); + painter->setBrush(Qt::NoBrush); + painter->drawRect(RECT.adjusted(0,0,-1,-1)); + painter->restore(); +// painter->fillRect(RECT, Qt::white); + } + if (config.menuShadow) { + QRect rect = RECT.adjusted(0,0, // don't ask... + shadows.line[true][Sunken].thickness()+1, + shadows.line[false][Sunken].thickness()+1); + //horizontal + shadows.line[false][Sunken].render(rect, painter, Tile::Full, false); + shadows.line[false][Sunken].render(rect, painter, Tile::Full, true); + //vertical + shadows.line[true][Sunken].render(rect, painter, Tile::Full, false); + shadows.line[true][Sunken].render(rect, painter, Tile::Full, true); + } +#endif + break; + } + case PE_PanelMenuBar: // Panel for menu bars. + case PE_FrameDockWidget: // Panel frame for dock windows and toolbars. + break; + case PE_FrameTabWidget: // Frame for tab widgets. + if (const QStyleOptionTabWidgetFrame *twf = + qstyleoption_cast(option)) { + + bool mirror = false, vertical = false; + switch (twf->shape) { + case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: + break; + case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: + mirror = true; break; + case QTabBar::RoundedEast: case QTabBar::TriangularEast: + mirror = true; + case QTabBar::RoundedWest: case QTabBar::TriangularWest: + vertical = true; break; + } + + int baseHeight = + vertical ? twf->tabBarSize.width() : twf->tabBarSize.height(); + if (baseHeight < 0) + baseHeight = pixelMetric( PM_TabBarBaseHeight, option, widget )-dpi.$2; + if (!baseHeight) { + shadows.tab.render(RECT, painter); + break; + } + + QRect rect(RECT), tabRect(RECT), fillRect; + int offset = 8; + Qt::Orientation o = Qt::Vertical; + Tile::PosFlags pf = Tile::Ring; + if (vertical) { // east or west + o = Qt::Horizontal; + rect.adjust(0,offset,0,-offset); + if (mirror) { // east + rect.setLeft(rect.right()-baseHeight); + fillRect = rect.adjusted(0, dpi.$2, -dpi.$3, -dpi.$3); + pf &= ~Tile::Left; + o = Qt::Horizontal; + tabRect.setRight(tabRect.right()-(baseHeight-dpi.$2)); + } + else { + rect.setWidth(baseHeight); + fillRect = rect.adjusted(dpi.$3, dpi.$2, 0, -dpi.$3); + pf &= ~Tile::Right; + o = Qt::Horizontal; + tabRect.setLeft(tabRect.left()+(baseHeight-dpi.$2)); + } + baseHeight = fillRect.width(); + } + else { // north or south + rect.adjust(offset,0,-offset,0); + if (mirror) { //south + rect.setTop(rect.bottom()-baseHeight); + fillRect = rect.adjusted(dpi.$3, 0, -dpi.$3, -dpi.$3); + pf &= ~Tile::Top; + tabRect.setBottom(tabRect.bottom()-(baseHeight-dpi.$3)); + } + else { // north + rect.setHeight(baseHeight); + fillRect = rect.adjusted(dpi.$3, dpi.$2, -dpi.$3, 0); + pf &= ~Tile::Bottom; + tabRect.setTop(tabRect.top()+baseHeight); + } + baseHeight = fillRect.height(); + } + + shadows.tab.render(rect, painter, pf); + fillWithMask(painter, fillRect, gradient(CONF_COLOR(role_tab[0]), baseHeight, o, config.gradientStrong), &masks.tab, pf | Tile::Center); + masks.tab.outline(fillRect, painter, CONF_COLOR(role_tab[0]).dark(110), true, pf); + shadows.tab.render(tabRect, painter, Tile::Ring); + } + break; + case PE_FrameLineEdit: // Panel frame for line edits. + shadows.lineEdit[isEnabled].render(RECT.adjusted(0,0,0,-dpi.$2),painter); + break; + case PE_FrameGroupBox: { // Panel frame around group boxes. + QRect rect = RECT.adjusted(dpi.$4,dpi.$2,-dpi.$4,0); + rect.setHeight(qMax(dpi.$32, RECT.height())); + fillWithMask(painter, rect, groupLight(rect.height()), &masks.button, + Tile::Full&~Tile::Bottom); + rect.setBottom(RECT.bottom()-dpi.$32); + shadows.group.render(RECT, painter, Tile::Ring); + masks.button.outline(rect, painter, COLOR(Window).light(120), true, + Tile::Full&~Tile::Bottom); + break; + } +// case PE_FrameButtonBevel: // Panel frame for a button bevel +// case PE_FrameButtonTool: // Panel frame for a tool button + case PE_FrameStatusBar: // Frame for a section of a status bar; see also QStatusBar. + break; + case PE_FrameWindow: // Frame around a MDI window or a docking window. + { + painter->save(); + painter->setPen(PAL.color(QPalette::Window).dark(110)); + painter->drawRect(RECT); + painter->restore(); + break; + } + case PE_Q3Separator: // Qt 3 compatible generic separator. + break; + case PE_IndicatorViewItemCheck: // On/off indicator for a view item + case PE_Q3CheckListIndicator: // Qt 3 compatible Checkbox part of a list view item. + case PE_IndicatorMenuCheckMark: { // Check mark used in a menu. + QRect rect; + if (RECT.width() > RECT.height()) + rect.setRect(RECT.x()+(RECT.width()-RECT.height())/2, RECT.y(), + RECT.height()-1, RECT.height()-1); + else + rect.setRect(RECT.x(), RECT.y()+(RECT.height()-RECT.width())/2, + RECT.width()-1, RECT.width()-1); + int off = rect.width()/4; + + painter->save(); + const bool selected = option->state & State_Selected && isEnabled; + painter->setBrush(Qt::NoBrush); + QPalette::ColorRole fgr; + if (pe == PE_IndicatorMenuCheckMark) { + if (widget) + fgr = selected ? widget->backgroundRole() : widget->foregroundRole(); + else + fgr = selected ? QPalette::Window : QPalette::WindowText; + } + else + fgr = selected ? QPalette::HighlightedText : QPalette::Text; + + painter->setPen(PAL.color(fgr)); + painter->drawRect(rect.adjusted(0, off, -off, 0)); + + if (!(option->state & State_Off)) { + painter->setRenderHint(QPainter::Antialiasing); + if (!(pe == PE_IndicatorMenuCheckMark || selected)) { + fgr = QPalette::Highlight; + painter->setPen(PAL.color(fgr)); + } + painter->setBrush(PAL.color(fgr)); + const QPoint points[4] = { + QPoint(rect.right(), rect.top()), + QPoint(rect.x()+rect.width()/3, rect.bottom()), + QPoint(rect.x(), rect.bottom()-rect.height()/3), + QPoint(rect.x()+rect.width()/3, rect.bottom()-rect.height()/5) + }; + painter->drawPolygon(points, 4); + } + painter->restore(); + break; + } + case PE_Q3CheckListExclusiveIndicator: // Qt 3 compatible Radio button part of a list view item. + painter->save(); + painter->setRenderHint ( QPainter::Antialiasing ); + painter->drawEllipse ( RECT ); + _PRINTFLAGS_; + if (option->state & State_On) { + painter->setBrush ( painter->pen().color() ); + painter->drawEllipse ( RECT.adjusted(RECT.width()/4, RECT.height()/4, -RECT.width()/4, -RECT.height()/4) ); + } + painter->restore(); + break; +// case PE_IndicatorProgressChunk: // Section of a progress bar indicator; see also QProgressBar. +// case PE_Q3CheckListController: // Qt 3 compatible Controller part of a list view item. + case PE_IndicatorBranch: // Lines used to represent the branch of a tree in a tree view. + { + SAVE_PEN; + int mid_h = RECT.x() + RECT.width() / 2; + int mid_v = RECT.y() + RECT.height() / 2; + int bef_h = mid_h; + int bef_v = mid_v; + int aft_h = mid_h; + int aft_v = mid_v; + + painter->setPen(widget ? + midColor( PAL.color(widget->backgroundRole()), PAL.color(widget->foregroundRole())) : + midColor( PAL.color(QPalette::Base), PAL.color(QPalette::Text)) ); + static const int decoration_size = 9; + if (option->state & State_Children) { + int delta = decoration_size / 2 + 2; + bef_h -= delta; + bef_v -= delta; + aft_h += delta; + aft_v += delta; + QStyleOption tmpOpt = *option; + tmpOpt.rect = QRect(bef_h+2, bef_v+2, decoration_size, decoration_size); + drawPrimitive(option->state & State_Open ? PE_IndicatorArrowDown : + option->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : + PE_IndicatorArrowRight, &tmpOpt, painter, widget); + } + if (RECT.x() == -1) { // this is for the first col and i don't see why we'd need a line here + RESTORE_PEN; + break; + } + + if (option->state & (State_Item | State_Sibling)) + painter->drawLine(mid_h, RECT.y(), mid_h, bef_v); + if (option->state & State_Sibling) + painter->drawLine(mid_h, aft_v, mid_h, RECT.bottom()); + if (option->state & State_Item) { + if (option->direction == Qt::RightToLeft) + painter->drawLine(RECT.left(), mid_v, bef_h, mid_v); + else + painter->drawLine(aft_h, mid_v, RECT.right(), mid_v); + } + RESTORE_PEN; + break; + } + case PE_IndicatorDockWidgetResizeHandle: // Resize handle for dock windows. + { + QPoint *points; int num; + const int $12 = dpi.$12, $6 = dpi.$6; + if (RECT.width() > RECT.height()) { + int x = RECT.left()+RECT.width()/3; + int y = RECT.top()+(RECT.height()-$6)/2; + num = RECT.width()/(3*$12); + if ((RECT.width()/3) % $12) ++num; + points = new QPoint[num]; + for (int i = 0; i < num; ++i) { + points[i] = QPoint(x,y); x += $12; + } + } + else { + int x = RECT.left()+(RECT.width()-$6)/2; + int y = RECT.top()+RECT.height()/3; + num = RECT.height()/(3*$12); + if ((RECT.height()/3) % $12) ++num; + points = new QPoint[num]; + for (int i = 0; i < num; ++i) { + points[i] = QPoint(x,y); y += $12; + } + } + painter->save(); + painter->setPen(Qt::NoPen); + const QPixmap *fill; int cnt = num/2, imp = 1; + QPalette::ColorRole role = QPalette::WindowText; + if (hover) { + role = QPalette::Highlight; + imp = 8; + } + if (num%2) + { + fill = &gradient(midColor(COLOR(Window), PAL.color(role), 3, imp), $6, Qt::Vertical, GradSunken); + fillWithMask(painter, points[cnt], *fill, masks.notch); + } + --num; + for (int i = 0; i < cnt; ++i) + { + fill = &gradient(midColor(COLOR(Window), PAL.color(role), 3+cnt-i, imp), $6, Qt::Vertical, GradSunken); + fillWithMask(painter, points[i], *fill, masks.notch); + fillWithMask(painter, points[num-i], *fill, masks.notch); + } + painter->restore(); + delete[] points; + break; + } + case PE_IndicatorToolBarHandle: // The handle of a toolbar. + if (!(widget && widget->parentWidget()) || + widget->parentWidget()->underMouse()) { + painter->save(); + QRect rect = RECT; bool line = false; int dx(0), dy(0); + if (RECT.width() > RECT.height()) { + line = (RECT.width() > 9*RECT.height()/2); + if (line) { + dx = 3*RECT.height()/2; dy = 0; + } + rect.setLeft(rect.left()+(rect.width()-rect.height())/2); + rect.setWidth(rect.height()); + } + else { + line = (RECT.height() > 3*RECT.width()); + if (line) { + dx = 0; dy = 3*RECT.width()/2; + } + rect.setTop(rect.top()+(rect.height()-rect.width())/2); + rect.setHeight(rect.width()); + } + QColor c = hover?COLOR(Highlight):COLOR(Window).dark(110); + painter->setRenderHint(QPainter::Antialiasing); + painter->setBrush(gradient(c, rect.height(), Qt::Vertical, GradSunken)); + painter->setPen(Qt::NoPen); + painter->setBrushOrigin(rect.topLeft()); + painter->drawEllipse(rect); + if (line) { + const int $1 = dpi.$1; + rect.adjust($1,$1,-$1,-$1); + painter->setBrush(gradient(c, rect.height(), Qt::Vertical, GradSunken)); + rect.translate(-dx,-dy); + painter->setBrushOrigin(rect.topLeft()); + painter->drawEllipse(rect); + rect.translate( 2*dx, 2*dy); + painter->setBrushOrigin(rect.topLeft()); + painter->drawEllipse(rect); + } + painter->restore(); + } + break; + case PE_IndicatorToolBarSeparator: // The separator in a toolbar. + break; + case PE_PanelToolBar: // The panel for a toolbar. + break; +// case PE_PanelTipLabel: // The panel for a tip label. + case PE_FrameTabBarBase: // The frame that is drawn for a tabbar, ususally drawn for a tabbar that isn't part of a tab widget + if (widget && + (qobject_cast(widget) || // we alter the paintevent + (widget->parentWidget() && + qobject_cast(widget->parentWidget())))) // KDE abuse, allready has a nice base + break; + + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast(option)) { + int size(0); Qt::Orientation o = Qt::Vertical; + Tile::PosFlags pf = Tile::Ring; + QRect fillRect; + bool north = false; + switch (tbb->shape) { + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: +// fillRect = RECT.adjusted(dpi.$3, dpi.$2, -dpi.$3, 0); + pf &= ~Tile::Top; + size = /*fillRect*/RECT.height(); + break; + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + north = true; +// fillRect = RECT.adjusted(dpi.$3, 0, -dpi.$3, -dpi.$3); + pf &= ~Tile::Bottom; + size = /*fillRect*/RECT.height(); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: +// fillRect = RECT.adjusted(0, dpi.$2, -dpi.$3, -dpi.$3); + pf &= ~Tile::Right; + o = Qt::Horizontal; + size = /*fillRect*/RECT.width(); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: +// fillRect = RECT.adjusted(dpi.$3, dpi.$2, 0, -dpi.$3); + pf &= ~Tile::Left; + o = Qt::Horizontal; + size = /*fillRect*/RECT.width(); + break; + } + fillWithMask(painter, RECT, + gradient(CONF_COLOR(role_tab[0]), size, o, config.gradientStrong), + &masks.button, pf | Tile::Center); + if (north) + shadows.lineEdit[0].render(RECT, painter, Tile::Ring & ~Tile::Bottom); + else + shadows.tab.render(RECT, painter, pf); +// masks.tab.outline(fillRect, painter, CONF_COLOR(role_tab[0]).dark(110), true, pf); + } + break; + case PE_IndicatorTabTear: // An indicator that a tab is partially scrolled out of the visible tab bar when there are many tabs. + break; + default: + QCommonStyle::drawPrimitive( pe, option, painter, widget ); + } // switch +} diff --git a/clients/oxygen/dynamicbrush.cpp b/clients/oxygen/dynamicbrush.cpp new file mode 100644 index 0000000000..d9d4ad45b2 --- /dev/null +++ b/clients/oxygen/dynamicbrush.cpp @@ -0,0 +1,1190 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GL_GLEXT_PROTOTYPES +#include +// #include +// #include + +#include +#include + +#include "oxrender.h" + +#include "dynamicbrush.h" + +static BgPixCache tlwbacks; +static BgSet _bgSet; + +// #include "endian.h" + +#define SETBACKGROUND(_pix_)\ + const_cast(&QApplication::palette().brush(QPalette::Active, QPalette::Window))->setTexture(_pix_);\ + const_cast(&QApplication::palette().brush(QPalette::Inactive, QPalette::Window))->setTexture(_pix_);\ + const_cast(&QApplication::palette().brush(QPalette::Disabled, QPalette::Window))->setTexture(_pix_) + +#ifndef CLAMP +#define CLAMP(x,l,u) (x) < (l) ? (l) :\ +(x) > (u) ? (u) :\ +(x) +#endif + +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + +static QPixmap mirror(const QPixmap &pix, Qt::Orientation o) +{ + Display *dpy = QX11Info::display(); + QPixmap mirror(pix.size()); + GC gc = XCreateGC( dpy, mirror.handle(), 0, 0 ); + if (o == Qt::Horizontal) + { + int x = pix.width() - 1; + for (int i = 0; i < pix.width(); ++i) + XCopyArea( dpy, pix.handle(), mirror.handle(), gc, + x-i, 0, 1, pix.height(), i, 0 ); + } + else + { + int y = pix.height() - 1; + for (int i = 0; i < pix.height(); ++i) + XCopyArea( dpy, pix.handle(), mirror.handle(), gc, + 0, y-i, pix.width(), 1, 0, i ); + } + XFreeGC ( dpy , gc ); + return mirror; +} + +static const Atom oxygen_isQtWindow = +XInternAtom(QX11Info::display(), "OXYGEN_IS_QT_WINDOW", False); + +static GLuint _background; + +const BgSet* (DynamicBrush::*bgSet)(const QSize&, bool); + +BgSet::BgSet() { + window = decoTop = decoBottom = decoLeft = decoRight = 0L; +} + +BgSet::BgSet(const QPixmap* pix, int dx, int dy, int w, int h, + bool updateDeco) +{ + window = decoTop = decoBottom = decoLeft = decoRight = 0L; + setPixmap(pix, dx, dy, w, h, updateDeco); +} + +BgSet::BgSet(const QPixmap* pix, int d, int s, Qt::Orientation o, + bool updateDeco) +{ + window = decoTop = decoBottom = decoLeft = decoRight = 0L; + setPixmap(pix, d, s, o, updateDeco); +} + +void BgSet::setPixmap(const QPixmap* pix, int dx, int dy, int w, int h, + bool updateDeco) +{ + + if (window) delete window; + window = new QPixmap(w, h); + QPainter p(window); + p.drawPixmap(0,0, w, h, *pix, dx, dy, w, h); + p.end(); + + if (!updateDeco) + return; + + int iW, iH; + +#define NEW_PIX(_PIX_, _W_, _H_) if (_PIX_) delete _PIX_; \ + _PIX_ = new QPixmap(_W_, _H_); if (!_PIX_->isNull()) { p.begin(_PIX_) + + NEW_PIX(decoTop, w, dy); + p.drawPixmap(0, 0, w, dy, *pix, dx, 0, w, dy); p.end(); } + + iH = pix->height() - (dy + h); + NEW_PIX(decoBottom, w, iH); + p.drawPixmap(0, 0, w, iH, *pix, dx, pix->height()-iH, w, iH); p.end(); } + + iH = pix->height(); + NEW_PIX(decoLeft, dx, iH); + p.drawPixmap(0, 0, dx, iH, *pix, 0, 0, dx, iH); p.end(); } + + iW = pix->width() - (dx + w); + NEW_PIX(decoRight, iW, pix->height()); + p.drawPixmap(0, 0, iW, iH, *pix, pix->width()-iW, 0, iW, iH); p.end(); } + +} + +void BgSet::setPixmap(const QPixmap* pix, int d, int s, Qt::Orientation o, + bool updateDeco) +{ + QPainter p; int w,h; + if (o == Qt::Vertical) { + w = pix->width(); + NEW_PIX(window, w, s); + p.drawPixmap(0,0, w, s, *pix, 0, d, w, s); p.end(); } + + if (!updateDeco) + return; + + NEW_PIX(decoTop, w, d); + p.drawPixmap(0, 0, w, d, *pix, 0, 0, w, d); p.end(); } + + h = pix->height() - (d + s); + NEW_PIX(decoBottom, w, h); + p.drawPixmap(0, 0, w, h, *pix, 0, pix->height()-h, w, h); p.end(); } + + h = pix->height(); + NEW_PIX(decoLeft, w, h); + p.drawPixmap(0, 0, w, h, *pix, 0, 0, w, h); p.end(); } + + decoRight = decoLeft; + + } + else { + + h = pix->height(); + NEW_PIX(window, s, h); + p.drawPixmap(0,0, s, h, *pix, d, 0, s, h); p.end(); } + + if (!updateDeco) + return; + + NEW_PIX(decoTop, s, h); + p.drawPixmap(0, 0, s, h, *pix, 0, 0, s, h); p.end(); } + + decoBottom = decoTop; + + NEW_PIX(decoLeft, s, h); + p.drawPixmap(0, 0, s, h, *pix, 0, 0, s, h); p.end(); } + + w = pix->width() - (d + s); + NEW_PIX(decoRight, w, h); + p.drawPixmap(0, 0, w, h, *pix, pix->width()-w, 0, w, h); p.end(); } + + } + +#undef NEW_PIX +} + +void BgSet::wipe() { + if (window) { delete window; window = 0L; } + if (decoBottom && decoBottom != decoTop) { delete decoBottom; decoBottom = 0L; } + if (decoTop) { delete decoTop; decoTop = 0L; } + if (decoRight && decoRight != decoLeft) { delete decoRight; decoRight = 0L; } + if (decoLeft) { delete decoLeft; decoLeft = 0L; } +} + +BgSet::~BgSet() { + wipe(); +} + +DynamicBrush::DynamicBrush(Mode mode, QObject *parent) : QObject(parent), +_glContext(0), _mode(mode), _isActiveWindow(true) +{ + for (int i = 0; i < 4; ++i) decoDim[i] = 0; + _timerBgWipe = new QTimer(this); + connect (_timerBgWipe, SIGNAL(timeout()), this, SLOT(wipeBackground())); + switch (_mode) + { + case Tiled: bgSet = &DynamicBrush::bgSetTiled; break; + case XRender: bgSet = &DynamicBrush::bgSetRender; break; + case QtGradient: bgSet = &DynamicBrush::bgSetQt; break; + case OpenGL: + bgSet = &DynamicBrush::bgSetGL; + _glContext = new QGLWidget( QGLFormat::defaultFormat(), 0 ); + initGL(); + break; + case HGradient1: + case VGradient1: bgSet = &DynamicBrush::bgSetGradient1; generateTiles(mode); break; + case HGradient2: + case VGradient2: bgSet = &DynamicBrush::bgSetGradient2; generateTiles(mode); break; + case Glass: bgSet = &DynamicBrush::bgSetGlass; generateTiles(mode); break; + } +} + +DynamicBrush::DynamicBrush(OXPixmap pixmap, int bgYoffset, QObject *parent) : +QObject(parent), _pixmap(pixmap), _bgYoffset(bgYoffset), _glContext(0), _mode(Tiled) +{ + for (int i = 0; i < 4; ++i) decoDim[i] = 0; + _timerBgWipe = new QTimer(this); + connect (_timerBgWipe, SIGNAL(timeout()), this, SLOT(wipeBackground())); + bgSet = &DynamicBrush::bgSetTiled; +} + +DynamicBrush::~DynamicBrush() { + glDeleteLists( _background, 1 ); +// QObject::~QObject(); +} + +static const Atom oxygen_decoDim = +XInternAtom(QX11Info::display(), "OXYGEN_DECO_DIM", False); + +void DynamicBrush::readDecoDim(QWidget *topLevelWidget) { + unsigned char *data = 0; + Atom actual; + int format, result; + unsigned long n, left; + result = XGetWindowProperty(QX11Info::display(), topLevelWidget->winId(), + oxygen_decoDim, 0L, 1L, False, XA_CARDINAL, + &actual, &format, &n, &left, &data); + if (result == Success && data != None) { // found set design + uint tmp; + memcpy (&tmp, data, sizeof (unsigned int)); + decoDim[0] = tmp & 0xff; + decoDim[1] = (tmp >> 8) & 0xff; + decoDim[2] = (tmp >> 16) & 0xff; + decoDim[3] = (tmp >> 24) & 0xff; + } +} + +void DynamicBrush::setMode(Mode mode) { + if (mode == _mode) return; + if (_mode == OpenGL) { + glDeleteLists( _background, 1 ); + delete _glContext; + _glContext = 0L; + } + _mode = mode; + switch (_mode) { + case Tiled: bgSet = &DynamicBrush::bgSetTiled; break; + case XRender: bgSet = &DynamicBrush::bgSetRender; break; + case QtGradient: bgSet = &DynamicBrush::bgSetQt; break; + case OpenGL: + bgSet = &DynamicBrush::bgSetGL; + if (!_glContext) { + _glContext = new QGLWidget( QGLFormat::defaultFormat(), 0 ); + initGL(); + } + break; + case HGradient1: + case VGradient1: bgSet = &DynamicBrush::bgSetGradient1; generateTiles(mode); break; + case HGradient2: + case VGradient2: bgSet = &DynamicBrush::bgSetGradient2; generateTiles(mode); break; + case Glass: bgSet = &DynamicBrush::bgSetGlass; generateTiles(mode); break; + } +} + +void DynamicBrush::generateTiles(Mode mode) { + QLinearGradient lg1, lg2; + QPainter p; + for (int i = 0; i < 2; ++i) + { + _bgC[i] = QApplication::palette().color(i?QPalette::Active:QPalette::Inactive, QPalette::Window); + switch (mode) + { + case HGradient1: { + _tile[i][0] = QPixmap(64,32); + _tile[i][1] = QPixmap(64,32); + QColor dark = _bgC[i].dark(105); + lg1 = QLinearGradient(QPoint(0,0), QPoint(64, 0)); + lg1.setColorAt(0, dark); lg1.setColorAt(1, _bgC[i]); + lg2 = QLinearGradient(QPoint(0,0), QPoint(64, 0)); + lg2.setColorAt(0, _bgC[i]); lg2.setColorAt(1, dark); + break; + } + case VGradient1: { + _tile[i][0] = QPixmap(32,64); + _tile[i][1] = QPixmap(32,64); + lg1 = QLinearGradient(QPoint(0,0), QPoint(0, 64)); + lg1.setColorAt(0, _bgC[i].light(105)); lg1.setColorAt(1, _bgC[i]); + lg2 = QLinearGradient(QPoint(0,0), QPoint(0, 64)); + lg2.setColorAt(0, _bgC[i]); lg2.setColorAt(1, _bgC[i].dark(105)); + break; + } + case HGradient2: { + _tile[i][0] = QPixmap(512,32); + _tile[i][1] = QPixmap(512,32); + QColor light = _bgC[i].light(104); + lg1 = QLinearGradient(QPoint(0,0), QPoint(512, 0)); + lg1.setColorAt(0, _bgC[i]); lg1.setColorAt(1, light); + lg2 = QLinearGradient(QPoint(0,0), QPoint(512, 0)); + lg2.setColorAt(0, light); lg2.setColorAt(1, _bgC[i]); + break; + } + case VGradient2: { + _tile[i][0] = QPixmap(32, 512); + _tile[i][1] = QPixmap(32, 512); + QColor light = _bgC[i].light(104); + lg1 = QLinearGradient(QPoint(0,0), QPoint(0, 512)); + lg1.setColorAt(0, _bgC[i]); lg1.setColorAt(1, light); + lg2 = QLinearGradient(QPoint(0,0), QPoint(0, 512)); + lg2.setColorAt(0, light); lg2.setColorAt(1, _bgC[i]); + break; + } + default: + _tile[i][0] = _tile[i][1] = QPixmap(); + return; + } + p.begin(&_tile[i][0]); + p.fillRect(_tile[i][0].rect(), lg1); + p.end(); + p.begin(&_tile[i][1]); + p.fillRect(_tile[i][1].rect(), lg2); + p.end(); + } +} + +static const Atom oxygen_deco_top = +XInternAtom(QX11Info::display(), "OXYGEN_DECO_TOP", False); +static const Atom oxygen_deco_bottom = +XInternAtom(QX11Info::display(), "OXYGEN_DECO_BOTTOM", False); +static const Atom oxygen_deco_left = +XInternAtom(QX11Info::display(), "OXYGEN_DECO_LEFT", False); +static const Atom oxygen_deco_right = +XInternAtom(QX11Info::display(), "OXYGEN_DECO_RIGHT", False); + +#define EXPORT_DECO_PIX(_ATOM_, _PIX_) \ +if (!set->_PIX_->isNull()) { \ +card = set->_PIX_->x11PictureHandle();\ +XRenderChangePicture(QX11Info::display(), card, CPRepeat, &pa);\ +XChangeProperty(QX11Info::display(), widget->winId(), _ATOM_, XA_CARDINAL, 32,\ +PropModeReplace, (unsigned char *) &(card), 1L);\ +} + +bool DynamicBrush::eventFilter ( QObject * object, QEvent * ev ) +{ + // Rule out non widgets (this should never happen, but who knows...) + if (!qobject_cast(object)) { + object->removeEventFilter(this); + return false; + } + + QWidget *widget = (QWidget*)object; + + // we're not interested in hidden elements + if (!widget->isVisible()) return false; + // or in "opaque" ones - like e.g. a textinput, scrollview etc. + if (widget->autoFillBackground()) return false; + + // Test for the currently demanded bg size + QSize size; + bool triggerUpdate = false; + if (ev->type() == QEvent::UpdateRequest) { + _topLevelWidget = widget->topLevelWidget(); + size = _topLevelWidget->size(); + } + else if (widget->isWindow()) { + _topLevelWidget = widget; + if (ev->type() == QEvent::Resize) { + readDecoDim(widget); + triggerUpdate = true; + size = ((QResizeEvent*)ev)->size(); + } + else if ( ev->type() == QEvent::WindowActivate || + ev->type() == QEvent::WindowDeactivate ) { + readDecoDim(widget); + size = ((QWidget*)object)->size(); + } + else if (ev->type() == QEvent::Show) { + readDecoDim(widget); + size = ((QWidget*)object)->size(); + triggerUpdate = true; + } + else if (ev->type() == QEvent::Hide) + size = QSize(); + else + return false; + } + else + return false; + + // we don't need a bg pix for the moment, let's save some RAM + if (size.isNull()) { + wipeBackground(); + tlwbacks.remove(_topLevelWidget); + return false; + } + + // the timer will wipe the background, if it's not updated since 7.777 secs + // (maybe the window is completely covered) + _timerBgWipe->start(7777); + + // In case the demanded size differs from the one we have: make an update ;) + bool needNewPix = true; + if (_mode == VGradient1 || _mode == VGradient2 || _mode == Glass) + needNewPix = (_size.height() != size.height()); + else if (_mode == HGradient1 || _mode == HGradient2) + needNewPix = (_size.width() != size.width()); + else // complex etc. + needNewPix = (_size != size); + + if (needNewPix) { + _size = size; + QSize fullSize = size + QSize(decoDim[2]+decoDim[3], + decoDim[0]+decoDim[1]); + const BgSet* set = (this->*bgSet)(fullSize, triggerUpdate); + + SETBACKGROUND(*(set->window)); + + if (triggerUpdate) { // tell the deco about new pics + int card; + XRenderPictureAttributes pa; + pa.repeat = True; + EXPORT_DECO_PIX(oxygen_deco_top, decoTop); + EXPORT_DECO_PIX(oxygen_deco_bottom, decoBottom); + EXPORT_DECO_PIX(oxygen_deco_left, decoLeft); + EXPORT_DECO_PIX(oxygen_deco_right, decoRight); + } + } + + // Maybe we better force an update + if (triggerUpdate) + widget->update(); + + return false; +} + +#undef EXPORT_DECO_PIX + +void DynamicBrush::wipeBackground() +{ + _timerBgWipe->stop(); + _size = QSize(); + QPixmap qPix; + SETBACKGROUND(qPix); + tlwbacks.clear(); +} + +BgPixCache::iterator DynamicBrush::checkCache(bool &found) { + found = false; + BgPixCache::iterator i, tlw = tlwbacks.end(), sm = tlwbacks.end(); + QPixmap *pix = false; + for (i = tlwbacks.begin(); i != tlwbacks.end(); ++i) { + pix = i.value()->window; + if (pix && pix->size() == _size) { + sm = i; + if (tlw != tlwbacks.end()) break; + } + if (i.key() == _topLevelWidget) { + tlw = i; + if (sm != tlwbacks.end()) break; + } + } + if (sm != tlwbacks.end()) { // we found a match + if (sm != tlw) { // from another window with the same size: share! + if (tlw == tlwbacks.end()) // new top level widget -> insert + tlw = tlwbacks.insert(_topLevelWidget, sm.value()); + else // just share + tlw.value() = sm.value(); + } + // anyway, we have a pixmap + found = true; + } + return tlw; +} + +const BgSet* DynamicBrush::bgSetTiled(const QSize &size, bool updateDeco) +{ + return &_bgSet; +#if 0 + Display *dpy = QX11Info::display(); + int ttbh = 22; + int height = _bgYoffset - ttbh; + int width = _size.width(); + int xb = QApplication::desktop()->width() - width; + int x = xb/3; + int w_2 = (width >> 1); + /* The following is a bit tricky. + we want a complex background including three different gradients (light sources) + to gain this, we created a desktop sized pixmap and now extract parts from it to + create a new window sized pixmap. + In our particular case we want to shape away 2/3 from the sides and 1/3 from the + center - in the upper region. below that, we take a center part + (i.e.shape away 1/2 of the difference from each side, this could be smarter) + */ + QPixmap qPix(_size); + // first the left and right top part ================== + GC gc = XCreateGC( dpy, qPix.handle(), 0, 0 ); + XCopyArea( dpy, _pixmap, qPix.handle(), gc, x, ttbh, w_2, height, 0, 0 ); + x = (x<<1) + w_2; + XCopyArea( dpy, _pixmap, qPix.handle(), gc, x, ttbh, width-w_2, height, w_2, 0 ); + // =================================== + // now the bottom center part =========================== + XCopyArea( dpy, _pixmap, qPix.handle(), gc, xb>>1, _bgYoffset, width, _size.height() - height, 0, height ); + XFreeGC ( dpy , gc ); + + /* update the brush textures*/ + SETBACKGROUND(qPix); +#endif +} + +const BgSet* DynamicBrush::bgSetGradient1(const QSize &size, bool updateDeco) +{ + QPixmap *qPix; + if (_mode == VGradient1) + { + qPix = new QPixmap(32, size.height()); + qPix->fill(_bgC[_isActiveWindow]); + QPainter p(qPix); + int h = qMin(64,(qPix->height()+1)/2); + p.drawTiledPixmap( 0, 0, 32, h, _tile[_isActiveWindow][0], 0, 64-h ); + h = qMin(64,(qPix->height())/2); + p.drawTiledPixmap( 0, qPix->height()-h, 32, h, _tile[_isActiveWindow][1] ); + p.end(); + _bgSet.setPixmap(qPix, decoDim[0], _size.height(), Qt::Vertical, updateDeco); + } + else // horizontal + { + qPix = new QPixmap(size.width(), 32); + qPix->fill(_bgC[_isActiveWindow]); + QPainter p(qPix); + int w = qMin(64,(qPix->width()+1)/2); + p.drawTiledPixmap( 0, 0, w, 32, _tile[_isActiveWindow][0], 64-w ); + w = qMin(64,(qPix->width())/2); + p.drawTiledPixmap( qPix->width()-w, 0, w, 32, _tile[_isActiveWindow][1] ); + p.end(); + _bgSet.setPixmap(qPix, decoDim[2], _size.width(), Qt::Horizontal, updateDeco); + } + return &_bgSet; +} + +const BgSet* DynamicBrush::bgSetGradient2(const QSize &size, bool updateDeco) +{ + QPixmap *qPix; + if (_mode == VGradient2) + { + qPix = new QPixmap(32, size.height()); + qPix->fill(_bgC[_isActiveWindow]); + QPainter p(qPix); + int h = qMin(512,(qPix->height()+1)/2); + int h_2 = qPix->height()/2; + p.drawTiledPixmap( 0, h_2-h, 32, h, _tile[_isActiveWindow][0], 0, (512-h)/2 ); + h = qMin(512, h_2); + p.drawTiledPixmap( 0, h_2, 32, h, _tile[_isActiveWindow][1], 0, (512-h)/2 ); + p.end(); + _bgSet.setPixmap(qPix, decoDim[0], _size.height(), Qt::Vertical, updateDeco); + } + else // horizontal + { + qPix = new QPixmap(size.width(), 32); + qPix->fill(_bgC[_isActiveWindow]); + QPainter p(qPix); + int w = qMin(512,(qPix->width()+1)/2); + int w_2 = qPix->width()/2; + p.drawTiledPixmap( w_2-w, 0, w, 32, _tile[_isActiveWindow][0], (512-w)/2 ); + w = qMin(512,w_2); + p.drawTiledPixmap( w_2, 0, w, 32, _tile[_isActiveWindow][1], (512-w)/2 ); + p.end(); + _bgSet.setPixmap(qPix, decoDim[2], _size.width(), Qt::Horizontal, updateDeco); + } + return &_bgSet; +} + +const BgSet* DynamicBrush::bgSetGlass(const QSize &size, bool updateDeco) +{ + // first check the cache + bool found; + BgPixCache::iterator tlw = checkCache(found); + if (found) + return tlw.value(); + + // nope, create one + QPixmap *qPix = new QPixmap(32, size.height()); + QColor c = QApplication::palette().color(QPalette::Window); + int h,s, v; + int ch,cs,cv, delta, add; + QColor dd,bb; + c.getHsv(&h,&s,&v); + if (v < 80) { // very dark colors won't make nice backgrounds ;) + v = 80; + c.setHsv(h,s,80); + } + + + add = ((180-qGray(c.rgb()))>>1); + if (add < 0) + add = -add/2; + add = add>>4; + + // bb + cv = v+27+add; + if (cv > 255) { + delta = cv-255; cv = 255; + cs = s - delta; if (cs < 0) cs = 0; + ch = h - delta/6; if (ch < 0) ch = 360+ch; + } + else { + ch = h; cs = s; + } + bb.setHsv(ch,cs,cv); + + //dd + cv = v - 14-add; if (cv < 0) cv = 0; + cs = s*13/7; if (cs > 255) cs = 255; + dd.setHsv(h,cs,cv); + + // gradient + QLinearGradient lg(QPoint(0,0), QPoint(0, qPix->height())); + lg.setColorAt(0,bb); lg.setColorAt(0.5,c); + lg.setColorAt(0.5, dd); lg.setColorAt(1, c); + QPainter p(qPix); p.fillRect(qPix->rect(), lg); p.end(); + + // cache + if (tlw == tlwbacks.end()) + tlw = tlwbacks.insert(_topLevelWidget, new BgSet(qPix, decoDim[0], + _size.height(), Qt::Vertical)); + else + tlw.value()->setPixmap(qPix, decoDim[0], _size.height(), + Qt::Vertical, updateDeco); + + // pixmap can be deleted now + delete qPix; + + return tlw.value(); +} + +void DynamicBrush::initGL() +{ + _glContext->makeCurrent(); + glClearColor (0.0, 0.0, 0.0, 0.0); + glShadeModel (GL_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + _glContext->doneCurrent(); +// glNewList( _background, GL_COMPILE ); +// +// glEndList(); +} + +QPixmap *DynamicBrush::glPixmap(const QRect &rect, const QSize &size, int darkness) +{ + // so we'll use false colors here, avoiding image swap orgies +# if __BYTE_ORDER == __BIG_ENDIAN // OpenGL talks RGBA; Qt wants ARGB, do sth. about read type, need ppc arch for testing +#define _COLORS_ &a,&r,&g,&b + double r,g,b,a; +#else // OpenGL talks ABGR; Qt wants ARGB +#define _COLORS_ &b,&g,&r + double r,g,b; +#endif + if (darkness) + QApplication::palette().color(QPalette::Window).dark(100+darkness).getRgbF(_COLORS_); + else + QApplication::palette().color(QPalette::Window).getRgbF(_COLORS_); + _glContext->makeCurrent(); + int width = 128, height = 128; // texture_2d must be 2^n, we start with 2^7 to save some time here ;) + while (width < size.width()) width = (width<<1); + while (height < size.height()) height = (height<<1); + +// if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) +// { +// qWarning("ARRGHHH... system doesn't support framebuffers!?!"); +// return QPixmap(); +// } + + QGLFramebufferObject *buffer = new QGLFramebufferObject(width, height ); + if (!buffer->isValid()) { + qWarning("ARRGHHH... failed to create a texture buffer!"); + return new QPixmap(); + } + if (!buffer->bind()) { + qWarning("ARRGHHH... failed to bind gl rendering to texture buffer!"); + return new QPixmap(); + } + + glViewport(0, 0, (GLsizei) size.width(), (GLsizei) size.height()); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); +// gluOrtho2D (0.0, 30.0, 30.0, 0.0); //lrbt + GLfloat fw = 30.0/size.width(), fh = 30.0/size.height(); + // the statement is vertically mirrored, as is the pbuffer to a qimage + // we simply avoid a software mirror and paint "mirrored" in gl (no one will see ;) + glOrtho( rect.x()*fw, rect.right()*fw, rect.y()*fh, rect.bottom()*fh, -1, 1 ); + glMatrixMode(GL_MODELVIEW); + glBegin (GL_QUADS); + glColor4f (r*0.8, g*0.8, b*0.8, 1.0); + glVertex2f (0.0, 30.0); + glVertex2f (30.0, 30.0); + glColor4f (r, g, b, 1.0); + glVertex2f (30.0, 0.0); + glVertex2f (0.0, 0.0); + glEnd(); + glBegin (GL_TRIANGLES); + glColor4f (r, g, b, 0.6); + glVertex2f (30.0, 30.0); + glColor4f (r, g, b, 0.0); + glVertex2f (15.0, 30.0); + glVertex2f (30.0, 5.0); + glEnd(); + glBegin (GL_TRIANGLE_FAN); + r *= 1.1; g *= 1.1; b *=1.1; + glColor4f (r, g, b, .8); + glVertex2f (15.0, 00.0); + glColor4f (r, g, b, 0.0); + glVertex2f (30.0, 0.0); + glVertex2f (26.0, 3.0); + glVertex2f (22.0, 3.5); + glVertex2f (17.0, 5.0); + glVertex2f (13.0, 5.0); + glVertex2f (8.0, 3.5); + glVertex2f (4.0, 3.0); + glVertex2f (0.0, 0.0); + glEnd(); +// glCallList(_background); + glFlush(); + + /* ================================================================ + Hi complex... + + the qimage -> qpixmap conversion is slow, + so we try to avoid it by using knowledge of the special + structure of the image + + #1. the upper 5/30 mirror horizontal, mirroring a pixmap is faster than + double conversion (at least for big images, small are not so important) + + #2. the lower left tiles horizontally, so we convert only 32xheight pixles + and tile them together as pixmaps + + #3. only the lower right is unique - so we need to convert it completely + + the thing gets worse as we need to be able to extract parts for + eg. the groupbox shadows... i hate my life ;P + + IF ANYONE EVER TOUCHES THIS CODE AND THERE IS "glExtPixmapFromTexture" OR SIMILAR: + THIS WOULD BE BY FAR BETTER!!! + ================================================================ */ + + QPixmap *pix = new QPixmap(rect.size()); + int w_2 = (size.width()+1)/2; + int yOff = 5*size.height()/30; + int rlw = w_2 - rect.x(); + int rYOff = yOff-rect.y(); + int w,h; + QPixmap tmp; + QPainter p(pix); + + // top -------------------- + if (rect.y() < yOff) + { + w = MAX(w_2-rect.x(), rect.right()-w_2+1); + h = yOff-rect.y(); + QImage *top = new QImage(w, h, QImage::Format_RGB32); + glReadPixels(w_2-w, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, top->bits()); + tmp = QPixmap::fromImage(*top, Qt::ColorOnly|Qt::OrderedDither); + p.drawPixmap(rect.x(),0, tmp, rect.x(),0,w_2-rect.x(),-1); + tmp = mirror(tmp, Qt::Horizontal); + p.drawPixmap(w_2,0, tmp,0,0,rect.right()-w_2+1,-1); + delete top; + } + // bottom left -------------------- + if (rlw > 0) + { + h = rect.bottom() - yOff + 1; + QImage *btmLeft = new QImage(32,h, QImage::Format_RGB32); + glReadPixels(0, yOff, 32, h, GL_RGBA, GL_UNSIGNED_BYTE, btmLeft->bits()); + tmp = QPixmap::fromImage(*btmLeft, Qt::ColorOnly|Qt::OrderedDither); + p.drawTiledPixmap(0,rYOff,rlw,h, tmp); + delete btmLeft; + } + // bottom right -------------------- + w_2 = (size.width()-1)/2; + w = rect.right() - w_2; + if (w > 0) + { + h = rect.bottom() - yOff + 1; + QImage *btmRight = new QImage(w,h, QImage::Format_RGB32); + glReadPixels(w_2, yOff, w, h, GL_RGBA, GL_UNSIGNED_BYTE, btmRight->bits()); + tmp = QPixmap::fromImage(*btmRight, Qt::ColorOnly|Qt::OrderedDither); + delete btmRight; + p.drawPixmap(rlw,rYOff, tmp); + } + p.end(); + delete buffer; + return pix; +} + +const BgSet* DynamicBrush::bgSetGL(const QSize &size, bool updateDeco) +{ + + // first check the cache + bool found; + BgPixCache::iterator tlw = checkCache(found); + if (found) + return tlw.value(); + + QPixmap *qPix = glPixmap(QRect(QPoint(0,0), size), size); + + // cache + if (tlw == tlwbacks.end()) + tlw = tlwbacks.insert(_topLevelWidget, new BgSet(qPix, decoDim[2], + decoDim[0], _size.width(), _size.height())); + else + tlw.value()->setPixmap(qPix, decoDim[2], decoDim[0], _size.width(), + _size.height(), updateDeco); + + // pixmap can be deleted now + delete qPix; + + return tlw.value(); + +} + +const BgSet* DynamicBrush::bgSetRender(const QSize &size, bool updateDeco) { + + // first check the cache + bool found; + BgPixCache::iterator tlw = checkCache(found); + if (found) + return tlw.value(); + + // we have no sufficient pixmap, create one and set it + QColor c = QApplication::palette().color(QPalette::Window); + QPixmap *qPix = new QPixmap(size); + int w = size.width(), h = size.height(); + ColorArray ca = ColorArray() << c << c.dark(110); + OXPicture lgp = OXRender::gradient(QPoint(0,0), QPoint(0, h), ca); + OXRender::composite (lgp, None, *qPix, 0, 0, 0, 0, 0, 0, w, h); + OXRender::freePicture(lgp); + c = c.light(160); + c.setAlpha(180); ca.replace(0, c); + c.setAlpha(0); ca.replace(1, c); + float f[2] = { pow(0.5, (float)h/w), pow(0.5, (float)w/h) }; + lgp = OXRender::gradient(QPoint(w, h), QPoint(w*f[0], h*f[1]), ca); + OXRender::composite (lgp, None, *qPix, 0, 0, 0, 0, 0, 0, w, h, PictOpOver); + OXRender::freePicture(lgp); + h = qPix->height()/6; + int r = -(pow(w, 2)/4 + pow(h,2)) / (-2*h); + lgp = OXRender::gradient(QPoint(w/2, 0), 0, QPoint(w/2,h-r), r, ca); + OXRender::composite (lgp, None, *qPix, 0, 0, 0, 0, 0, 0, + w, qPix->height(), PictOpOver); + OXRender::freePicture(lgp); + + // cache + if (tlw == tlwbacks.end()) + tlw = tlwbacks.insert(_topLevelWidget, new BgSet(qPix, decoDim[2], + decoDim[0], _size.width(), _size.height())); + else + tlw.value()->setPixmap(qPix, decoDim[2], decoDim[0], _size.width(), + _size.height(), updateDeco); + + // pixmap can be deleted now + delete qPix; + + return tlw.value(); +} + +const BgSet* DynamicBrush::bgSetQt(const QSize &size, bool updateDeco) +{ + + // first check the cache + bool found; + BgPixCache::iterator tlw = checkCache(found); + if (found) + return tlw.value(); + + QColor c = QApplication::palette().color(QPalette::Window); + QPixmap *qPix = new QPixmap(_size); + QLinearGradient lg1(QPoint(0,0), QPoint(0, size.height())); + lg1.setColorAt(0, c); + lg1.setColorAt(1, c.dark(110)); + QLinearGradient lg2(QPoint(size.width()/2, size.height()/2), + QPoint(size.width(), size.height())); + QColor ct = c; ct.setAlpha(0); + lg2.setColorAt(0, ct); + ct.setAlpha(140); + lg2.setColorAt(1, ct); + QPainter p(qPix); + p.setPen(Qt::NoPen); + p.setBrush(lg1); + p.drawRect( 0, 0, qPix->width(), qPix->height()); + QPoint points[3] = { + QPoint(size.width(), 0), + QPoint(size.width(), size.height()), + QPoint(0, size.height()) + }; + p.setBrush(lg2); + p.drawPolygon(points, 3); + p.end(); + + // cache + if (tlw == tlwbacks.end()) + tlw = tlwbacks.insert(_topLevelWidget, new BgSet(qPix, decoDim[2], + decoDim[0], _size.width(), _size.height())); + else + tlw.value()->setPixmap(qPix, decoDim[2], decoDim[0], _size.width(), + _size.height(), updateDeco); + + // pixmap can be deleted now + delete qPix; + + return tlw.value(); +} + +// QPixmap DynamicBrush::shadow(const QRect &rect) +// { +// switch (_mode) +// { +// case Tiled2: +// { +// QPixmap qPix(rect.size()); +// int width = _size.width(); +// int height = rect.height(); +// float factor = MIN(1.0, ((float)width)/(2*_tile[0][0].width()+2*_center[0][0].width())); +// int wt = (int) (factor * _tile[0][0].width()); +// int wc = (int) (factor * _center[0][0].width()); +// int x = width/2 - wc; +// QPainter p(&qPix); +// //left +// p.drawTiledPixmap(-rect.x(), 0, x, height, _tile[1][0], x % wt); +// //left center +// x -= rect.x(); +// p.drawTiledPixmap(x, 0, wc, height, _center[1][0]); +// // right center +// x += wc; +// p.drawTiledPixmap(x, 0, wc, height, _center[1][1], _center[1][0].width()-wc); +// // right +// x += wc; +// p.drawTiledPixmap(x, 0, rect.right()-x, height, _tile[1][1]); +// p.end(); +// return qPix; +// } +// case Tiled: +// { +// QPixmap qPix(rect.size()); +// Drawable x11d = qPix.handle(); +// Display *dpy = QX11Info::display(); +// GC gc = XCreateGC( dpy, x11d, 0, 0 ); +// +// int ttbh = 20; +// int W_TopOff = _bgYoffset - ttbh; +// int W_xBottom = QApplication::desktop()->width() - _size.width(); +// int W_xTop = W_xBottom/3; +// int W_w_2 = (_size.width()>>1); +// // topleft geometry : W_xTop, ttbh, W_w_2, W_TopOff +// // topright geometry : (W_xTop<<1) + W_w_2, ttbh, windowSize.width() - W_w_2, W_TopOff +// // bottom geometry: W_xBottom, yoff, windowSize.width(), windowSize.height() - yoff +// +// // top left ---------------- +// if (rect.x() < W_w_2 && rect.y() < W_TopOff) +// { +// XCopyArea( dpy, _shadow, x11d, gc, +// W_xTop + rect.x(), ttbh + rect.y(), +// //widget->width() - (rect.x() + rect.width() - W_w_2), +// W_w_2 - rect.x(), +// //widget->height() - (rect.y() + rect.height() - W_TopOff), +// W_TopOff - rect.y(), +// 0, 0 ); +// } +// +// // top right ---------------- +// if (rect.right() > W_w_2 && rect.y() < W_TopOff) +// { +// W_xTop = (W_xTop<<1) + W_w_2; +// int x, xOff, w; +// if (rect.x() < W_w_2) +// { +// w = rect.right() - W_w_2; +// x = W_w_2 - rect.x(); +// xOff = W_xTop; +// } +// else +// { +// w = rect.width(); +// x = 0; +// xOff = W_xTop + (rect.x() - W_w_2); +// } +// XCopyArea( dpy, _shadow, x11d, gc, +// xOff, ttbh + rect.y(), w, W_TopOff - rect.y(), +// x, 0 ); +// } +// +// // bottom center part ---------------- +// if (rect.bottom() > W_TopOff) +// { +// int h, y, yOff; +// if (rect.y() < W_TopOff) +// { +// h = rect.y() + rect.height() - W_TopOff; +// y = W_TopOff - rect.y(); +// yOff = _bgYoffset; +// } +// else +// { +// h = rect.height(); +// y = 0; +// yOff = rect.y() + ttbh; +// } +// XCopyArea( dpy, _shadow, x11d, gc, +// W_xBottom + rect.x(), yOff, rect.width(), h, +// 0, y ); +// } +// XFreeGC ( dpy , gc ); +// return qPix; +// } +// case OpenGL: +// if (_glShadow.isNull() || _lastShadowRect != rect ) +// { +// _lastShadowRect = rect; +// _glShadow = glPixmap(rect, 10); +// } +// return _glShadow; +// case QtGradient: +// case XRender: +// if (_glShadow.isNull() || _lastShadowRect != rect ) +// { +// _glShadow = QPixmap(rect.size()); +// _lastShadowRect = rect; +// QColor c = QApplication::palette().color(QPalette::Window).light(105); +// ColorArray ca = ColorArray() << c << c.dark(110); +// QPoint center(_glShadow.width()/2, _glShadow.height()); +// int r = sqrt(pow(_glShadow.width()/2,2)+pow(_glShadow.height(),2)); +// OXPicture rg = OXRender::gradient(center, 0, center, r, ca); +// XRenderComposite (QX11Info::display(), PictOpSrc, rg, None, _glShadow.x11PictureHandle(), +// 0, 0, 0, 0, 0, 0, _glShadow.width(), _glShadow.height()); +// XRenderFreePicture(QX11Info::display(), rg); +// } +// return _glShadow; +// } +// return QPixmap(); +// } + +#if 0 // this is some stored code - yet not used, but maybe later on + +static bool eraseWidget(const QWidget *widget, const QPaintDevice *device, bool pseudoTransparent, const QRegion &clipRegion) +{ + const QWidget *bgWidget = (pseudoTransparent && widget->parentWidget()) ? widget->parentWidget() : widget; + if (bgWidget->backgroundRole() == Qt::NoBackground || !widget->palette().brush( QPalette::Active, bgWidget->backgroundRole() ).texture().isNull()) + return false; + + OXPixmap _bgPx; + if (bgWidget->palette().color(QPalette::Active, bgWidget->backgroundRole()) == qApp->palette().color( QPalette::Active, QPalette::Background)) + _bgPx = bgPix; + else if (bgWidget->palette().color(QPalette::Active, bgWidget->backgroundRole()) == groupShadowColor_) + _bgPx = _shadow; + else + return false; + + if (!_bgPx) + return false; + + QPoint windowOffset = widget->backgroundOffset(); + int ttbh = 20; + QSize windowSize = widget->topLevelWidget()->size(); + int W_TopOff = _bgYoffset - ttbh; + int W_xBottom = qApp->desktop()->width() - windowSize.width(); + int W_xTop = W_xBottom/3; + int W_w_2 = (windowSize.width()>>1); + // topleft geometry : W_xTop, ttbh, W_w_2, W_TopOff + // topright geometry : (W_xTop<<1) + W_w_2, ttbh, windowSize.width() - W_w_2, W_TopOff + // bottom geometry: W_xBottom, yoff, windowSize.width(), windowSize.height() - yoff + + // painting + GC gc = XCreateGC( QX11Info::display(), device->handle(), 0, 0 ); + + if (!clipRegion.isNull()) + { + int num; + XRectangle *rects = (XRectangle *)qt_getClipRects( clipRegion, num ); + XSetClipRectangles( QX11Info::display(), gc, 0, 0, rects, num, YXBanded ); + } + + // top left + if (windowOffset.x() < W_w_2 && windowOffset.y() < W_TopOff) + { + + XCopyArea( QX11Info::display(), _bgPx, device->handle(), gc, + W_xTop + windowOffset.x(), + ttbh + windowOffset.y(), + //widget->width() - (windowOffset.x() + widget->width() - W_w_2), + W_w_2 - windowOffset.x(), + //widget->height() - (windowOffset.y() + widget->height() - W_TopOff), + W_TopOff - windowOffset.y(), + 0, 0 ); + } + + // top right + if (windowOffset.x() + widget->width() > W_w_2 + && windowOffset.y() < W_TopOff) + { + W_xTop = (W_xTop<<1) + W_w_2; + int x, xOff, w; + if (windowOffset.x() < W_w_2) + { + w = windowOffset.x() + widget->width() - W_w_2; + x = W_w_2 - windowOffset.x(); + xOff = W_xTop; + } + else + { + w = widget->width(); + x = 0; + xOff = W_xTop + (windowOffset.x() - W_w_2); + } + XCopyArea( QX11Info::display(), _bgPx, device->handle(), gc, + xOff, + ttbh + windowOffset.y(), + w, + W_TopOff - windowOffset.y(), + x, 0 ); + } + + // bottom center part + if (windowOffset.y() + widget->height() > W_TopOff) + { + int h, y, yOff; + if (windowOffset.y() < W_TopOff) + { + h = windowOffset.y() + widget->height() - W_TopOff; + y = W_TopOff - windowOffset.y(); + yOff = _bgYoffset; + } + else + { + h = widget->height(); + y = 0; + yOff = windowOffset.y() + ttbh; + } + XCopyArea( QX11Info::display(), _bgPx, device->handle(), gc, + W_xBottom + windowOffset.x(), + yOff, + widget->width(), h, + 0, y ); + } + + XFreeGC ( QX11Info::display() , gc ); + return true; +} +#endif + +void DynamicBrush::setXPixmap(OXPixmap pixmap) +{ + if (pixmap != -1) + _pixmap = pixmap; +} +// cause of cmake +#include "dynamicbrush.moc" + diff --git a/clients/oxygen/dynamicbrush.h b/clients/oxygen/dynamicbrush.h new file mode 100644 index 0000000000..f1e59ea332 --- /dev/null +++ b/clients/oxygen/dynamicbrush.h @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef DYNAMICBRUSH_H +#define DYNAMICBRUSH_H + +class QTimer; +class QImage; +class QRect; +class QGLWidget; + +#include +#include +#include +#include +#include +#include +#include + +class BgSet { +public: + BgSet(); + BgSet(const QPixmap* pix, int dx, int dy, int w, int h, + bool updateDeco = true); + BgSet(const QPixmap* pix, int d, int s, Qt::Orientation o, + bool updateDeco = true); + void setPixmap(const QPixmap* pix, int dx, int dy, int w, int h, + bool updateDeco = false); + void setPixmap(const QPixmap* pix, int d, int s, Qt::Orientation o, + bool updateDeco = false); + void wipe(); + ~BgSet(); + QPixmap *window, + *decoTop, *decoBottom, *decoLeft, *decoRight; +}; + +typedef QMap BgPixCache; + +class DynamicBrush : public QObject +{ + Q_OBJECT +public: + enum Mode {Tiled = 0, QtGradient, XRender, OpenGL, + VGradient1, HGradient1, VGradient2, HGradient2, Glass}; + DynamicBrush(Mode mode, QObject *parent = 0); + DynamicBrush(Pixmap pixmap = -1, int bgYoffset = 0, QObject *parent = 0); + ~DynamicBrush(); +// QPixmap shadow(const QRect &rect); + void setMode(Mode); + void setXPixmap(Pixmap pixmap = -1); +protected: + virtual bool eventFilter ( QObject * watched, QEvent * event ); +private: + // bg pixmap creating + const BgSet* bgSetTiled(const QSize &size, bool updateDeco); + const BgSet* bgSetGL(const QSize &size, bool updateDeco); + const BgSet* bgSetRender(const QSize &size, bool updateDeco); + const BgSet* bgSetGradient1(const QSize &size, bool updateDeco); + const BgSet* bgSetGradient2(const QSize &size, bool updateDeco); + const BgSet* bgSetQt(const QSize &size, bool updateDeco); + const BgSet* bgSetGlass(const QSize &size, bool updateDeco); + + // get the deco dimensions from the deco + void readDecoDim(QWidget *topLevelWidget); + + // tiling + Pixmap _pixmap; + int _bgYoffset; + void generateTiles(Mode mode); + + // complex (gl/qt/render) + BgPixCache::iterator checkCache(bool &found); + + // openGL + void initGL(); + QGLWidget *_glContext; + QPixmap *glPixmap(const QRect &rect, const QSize &size, int darkness = 0); + + // gradients + QPixmap _tile[2][2]; + QColor _bgC[2]; + + // states + QSize _size; + Mode _mode; + bool _isActiveWindow; + int decoDim[4]; + + // bender + QWidget *_topLevelWidget; + + // wiping + QTimer *_timerBgWipe; +private slots: + void wipeBackground(); +}; + +#endif //DYNAMICBRUSH_H diff --git a/clients/oxygen/genpixmaps.cpp b/clients/oxygen/genpixmaps.cpp new file mode 100644 index 0000000000..6dbea607e6 --- /dev/null +++ b/clients/oxygen/genpixmaps.cpp @@ -0,0 +1,521 @@ +#define fillRect(_X_,_Y_,_W_,_H_,_B_) setPen(Qt::NoPen); p.setBrush(_B_); p.drawRect(_X_,_Y_,_W_,_H_) + +void OxygenStyle::generatePixmaps() +{ + QPixmap tmp; QPainter p; + QLinearGradient lg; QGradientStops stops; + QRadialGradient rg; + + // PUSHBUTTON ===================================== + // shadow + int $1 = dpi.$1, $2 = dpi.$2, $2_2 = lround($2/2.0); + int $3 = dpi.$3, $4 = dpi.$4, $5 = dpi.$5; + int $9 = dpi.$9, $9_2 = ($9-1)/2; + int $7 = dpi.$7, $8 = dpi.$8; + int $13 = dpi.$13, $15 = $7+$8, $6 = dpi.$6; + tmp = QPixmap($15,$15); + for (int i = 0; i < 8; ++i) { // opaque? + for (int j = 0; j < 2; ++j) { // sunken? + tmp.fill(Qt::transparent); + p.begin(&tmp); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + QRadialGradient rg; + if (j) { + rg = QRadialGradient($15/2.0, $15/2.0, $5, $15/2.0, $15/2.0+$3); + stops.clear(); + stops << QGradientStop( 0, QColor(0,0,0, 150) ) + << QGradientStop( 0.59, QColor(0,0,0, 70) ) + << QGradientStop( 1, QColor(0,0,0, 0) ); + rg.setStops(stops); + } + else { + rg = QRadialGradient($15/2.0, $15/2.0, $15/2.0, $15/2.0, $15/2.0+$2); + stops.clear(); + stops << QGradientStop( 0, QColor(0,0,0, 160) ) + << QGradientStop( 0.4, QColor(0,0,0, 60) ) + << QGradientStop( 0.85, QColor(0,0,0, 0) ) + << QGradientStop( 1, QColor(0,0,0, 0) ); + rg.setStops(stops); + + if (i) { + rg = QRadialGradient($15/2.0, $15/2.0, $15/2.0, $15/2.0, $15/2.0); + stops.clear(); + QColor c = QColor(222,193,0);//COLOR(Highlight); + c.setAlpha(180*i/8); + stops << QGradientStop( 0, c ); + c.setAlpha(0); + stops << QGradientStop( 1, c ); + rg.setStops(stops); + } + } + + p.setBrush(rg); + p.drawRoundRect(0,0,$15,$15,90,90); + + p.end(); + shadows.button[j][i] = Tile::Set(tmp,$7,$7,$15-2*$7,$15-2*$7); + } + } + + // light + tmp.fill(Qt::transparent); + p.begin(&tmp); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,80)); + p.drawRoundRect(0,0,$9,$9,90,90); + p.setBrush(QColor(0,0,0,80)); + p.drawRoundRect($1,$1,$9-2*$1,$9-2*$1,80,80); + p.setBrush(QColor(0,0,0,80)); + p.drawRoundRect($2,$2,$9-2*$2,$9-2*$2,70,70); + p.setBrush(QColor(0,0,0,255)); + p.drawRoundRect($3,$3,$9-2*$3,$9-2*$3,60,60); + p.end(); + lights.button = + Tile::Mask(tmp,$9_2,$9_2,$9-2*$9_2,$9-2*$9_2, $3,$3,-$3,-$3, 75,75); + + // mask + tmp = QPixmap($9,$9); + tmp.fill(Qt::transparent); + p.begin(&tmp); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,255)); + p.drawRoundRect(0,0,$9,$9,90,90); + p.end(); + masks.button = Tile::Mask(tmp,$9_2,$9_2,$9-2*$9_2,$9-2*$9_2,0,0,0,0,90,90); + + // -> LINEEDIT + QImage tmpImg($9,$9+$9, QImage::Format_ARGB32); + + for (int i = 0; i < 2; ++i) { + int add = i*30; + tmpImg.fill(Qt::transparent); + + p.begin(&tmpImg); + + // draw the shadows themselves, they appear on the inside naturally - as it's sunken + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + rg = QRadialGradient($9/2.0,$9/2.0, dpi.$5, $9/2.0,$9/2.0+1.5*$1); + stops.clear(); + stops << QGradientStop( 0, QColor(0,0,0, 0) ) + << QGradientStop( 0.4, QColor(0,0,0, 0) ) + << QGradientStop( 0.58, QColor(0,0,0, 40/2) ) + << QGradientStop( 0.75, QColor(0,0,0, 103/3) ) + << QGradientStop( 0.88, QColor(0,0,0, 161/3) ) + << QGradientStop( 1, QColor(0,0,0, 255/3) ); + rg.setStops(stops); + p.setBrush(rg); + + p.drawRoundRect(0,0,$9,$9,80,80); + + // move the bottom part + p.drawImage(QPoint(0,$9+dpi.$4), tmpImg, QRect(0,dpi.$5,$9,$9_2)); + + // draw white edge at bottom + p.setBrush(Qt::NoBrush); + p.setPen(QColor(255,255,255,160)); + p.drawRoundRect(0,$9,$9,$9,80,80); + p.setPen(Qt::red); + p.setPen(QColor(255,255,255,210)); + p.setRenderHint(QPainter::Antialiasing,false); + p.drawLine($1, $9+$9 -$2,$2, $9 + $9 - $3); + p.drawLine($9-$2, $9+$9 -$2, $9-$3, $9 + $9 - $3); + p.setRenderHint(QPainter::Antialiasing); + p.setPen(Qt::NoPen); + + // repeat the one good line we have for the next 9 lines (where we later draw the long shadow on top) + p.setCompositionMode( QPainter::CompositionMode_Source ); + p.drawImage(QRect(0,dpi.$5,$9,dpi.$9), tmpImg, QRect(0,$9_2,$9,$1)); + p.setCompositionMode( QPainter::CompositionMode_SourceOver ); + + // draw the shadow from the top and down + lg = QLinearGradient(0,$3,0,dpi.$12); + stops.clear(); + stops << QGradientStop( 0, QColor(106,56,0, 15) ) + << QGradientStop( 1.0, QColor(106,56,0, 0) ); + + lg.setStops(stops); + p.fillRect($2,$3,dpi.$5,dpi.$10, lg); + stops.clear(); + p.end(); + + shadows.lineEdit[i] = Tile::Set(QPixmap::fromImage(tmpImg),$9_2,$9_2+$9,$9-2*$9_2,$9-2*$9_2); + } + + // relief + tmp = QPixmap($9,$9); + tmp.fill(Qt::transparent); + p.begin(&tmp); + QPen pen = p.pen(); pen.setWidth($1); p.setPen(pen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(Qt::NoBrush); + p.setPen(QColor(255,255,255,40)); + p.drawRoundRect(0,0,$9-$2,$9-$2,60,60); + p.setPen(QColor(255,255,255,60)); + p.drawRoundRect($2,$2,$9-$2,$9-$2,60,60); + p.setPen(QColor(0,0,0,50)); + p.drawRoundRect($1,$1,$9-dpi.$3,$9-dpi.$3,60,60); + p.end(); + shadows.relief = Tile::Set(tmp,$9_2,$9_2,$9-2*$9_2,$9-2*$9_2); + + + // outlines + tmp = QPixmap($9,$9); + for (int i = 0; i < 2; ++i) { + tmp.fill(Qt::transparent); + p.begin(&tmp); + p.setRenderHint(QPainter::Antialiasing); + p.setPen(QColor(255,255,255,100+i*60)); + p.setBrush(Qt::NoBrush); + p.drawRoundRect(0,0,$9,2*$9,75,38); + p.end(); + frames.button[i] = Tile::Set(tmp,$9_2,$9_2,$9-2*$9_2,$9-2*$9_2); + } +// frames.button[0] = Tile::Nuno(100); +// frames.button[1] = Tile::Nuno(160); + + // toplight + int $49 = SCALE(49); + int $49_2 = ($49-1)/2; + tmp = QPixmap($49,$49); + tmp.fill(Qt::transparent); + rg = QRadialGradient( tmp.rect().center(), $49_2 ); + rg.setColorAt ( 0, QColor(255,255,255,160) ); + rg.setColorAt ( 1, QColor(255,255,255,0) ); + p.begin(&tmp); + p.fillRect(0,0,$49,$49,rg); + p.end(); + tmp = tmp.scaled( $49, dpi.$5, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); + tmp = tmp.copy(0,$2,$49,dpi.$3); + lights.top = Tile::Line(tmp,Qt::Horizontal,$49_2,-$49_2); + + // ================================================================ + + // RADIOUTTON ===================================== + int rw = dpi.ExclusiveIndicator; + int rh = dpi.ExclusiveIndicator; + // shadow + for (int i = 0; i < 2; ++i) { // opaque? + for (int j = 0; j < 2; ++j) { // sunken? + shadows.radio[j][i] = QPixmap(rw-$1*j, rh-$1*j); + shadows.radio[j][i].fill(Qt::transparent); + p.begin(&shadows.radio[j][i]); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,(1+i+j)*9)); + p.drawEllipse(shadows.radio[j][i].rect()); + if (!j) { + p.setBrush(QColor(0,0,0,(i+1)*20)); + p.drawEllipse($2_2,$2_2,rw-$2,rh-$2); + } + p.end(); + } + } + + // mask + rw -= dpi.$4; rh -= dpi.$4; + masks.radio = QPixmap(rw, rh); + masks.radio.fill(Qt::transparent); + p.begin(&masks.radio); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,255)); + p.drawEllipse(0,0,rw,rh); + p.end(); + + rw -= dpi.$4; rh -= dpi.$4; + masks.radioGroove = QPixmap(rw, rh); + masks.radioGroove.fill(Qt::transparent); + p.begin(&masks.radioGroove); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,255)); + p.drawEllipse(0,0,rw,rh); + p.end(); + + // mask fill + rw -= dpi.$4; rh -= dpi.$4; + masks.radioIndicator = QPixmap(rw, rh); + masks.radioIndicator.fill(Qt::transparent); + p.begin(&masks.radioIndicator); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,255)); + p.drawEllipse(0,0,rw,rh); + p.end(); + + // ================================================================ + + // NOTCH ===================================== + masks.notch = QPixmap(dpi.$6, dpi.$6); + masks.notch.fill(Qt::transparent); + p.begin(&masks.notch); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(Qt::black); + p.drawEllipse(0,0,dpi.$6,dpi.$6); + p.end(); + // ================================================================ + + // RECTANGULAR ===================================== + + // raised + + // sunken + tmp = QPixmap($9,$9); + tmp.fill(Qt::transparent); + p.begin(&tmp); + p.fillRect($1,0,$9-$2,$1, QColor(0,0,0,10)); + p.fillRect($2,$1,$9-$4,$1, QColor(0,0,0,20)); + p.fillRect($2,$2,$9-$4,$1, QColor(0,0,0,40)); + p.fillRect($3,$3,$9-$6,$1, QColor(0,0,0,80)); + + p.fillRect($1,$9-$1,$9-$2,$1, QColor(255,255,255,10)); + p.fillRect($2,$9-$2,$9-$4,$1, QColor(255,255,255,20)); + p.fillRect($2,$9-$3,$9-$4,$1, QColor(255,255,255,40)); + p.fillRect($3,$9-$4,$9-$6,$1, QColor(255,255,255,80)); + + p.fillRect(0,$1,$1,$9-$2, QColor(128,128,128,10)); + p.fillRect($1,$2,$1,$9-$4, QColor(128,128,128,20)); + p.fillRect($2,$2,$1,$9-$4, QColor(128,128,128,40)); + p.fillRect($3,$3,$1,$9-$6, QColor(128,128,128,80)); + + p.fillRect($9-$1,$1,$1,$9-$2, QColor(128,128,128,10)); + p.fillRect($9-$2,$2,$1,$9-$4, QColor(128,128,128,20)); + p.fillRect($9-$3,$2,$1,$9-$4, QColor(128,128,128,40)); + p.fillRect($9-$4,$3,$1,$9-$6, QColor(128,128,128,80)); + + p.end(); + shadows.sunken = Tile::Set(tmp,$9_2,$9_2,$9-2*$9_2,$9-2*$9_2); + + // ================================================================ + + // TABBAR ===================================== + + // mask + tmp = QPixmap($13,$13); + tmp.fill(Qt::transparent); + p.begin(&tmp); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,255)); + p.drawRoundRect(0,0,$13,$13,99,99); + p.end(); + int $13_2 = ($13-1)/2; + masks.tab = Tile::Mask(tmp,$13_2,$13_2,$13-2*$13_2,$13-2*$13_2,0,0,0,0,99,99); + + // shadow + int $17 = SCALE(17); + tmpImg = QImage($17,$17, QImage::Format_ARGB32); + tmpImg.fill(Qt::transparent); + p.begin(&tmpImg); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,15)); p.drawRoundRect(0,0,$17,$17,90,90); + p.setBrush(QColor(0,0,0,18)); p.drawRoundRect($1,$1,$17-$2,$17-$2,93,93); + p.setBrush(QColor(0,0,0,23)); p.drawRoundRect($2,$2,$17-dpi.$4,$17-dpi.$4,96,96); + p.setBrush(QColor(0,0,0,28)); p.drawRoundRect(dpi.$3,dpi.$3,$17-dpi.$6,$17-dpi.$6,99,99); + p.setCompositionMode( QPainter::CompositionMode_DestinationOut ); + p.setBrush(QColor(0,0,0,255)); p.drawRoundRect($2,$1,$17-dpi.$4,$17-dpi.$5,99,99); + p.setCompositionMode( QPainter::CompositionMode_SourceOver ); + p.setPen(QColor(255,255,255,170)); p.setBrush(Qt::NoBrush); + p.drawRoundRect($2,$1,$17-dpi.$4,$17-dpi.$5,99,99); + p.end(); + int $17_2 = ($17-1)/2; + shadows.tab = Tile::Set(QPixmap::fromImage(tmpImg),$17_2,$17_2,$17-2*$17_2,$17-2*$17_2); + + // GROUPBOX ===================================== + + // shadow + tmpImg = QImage($49,$49, QImage::Format_ARGB32); + tmpImg.fill(Qt::transparent); + p.begin(&tmpImg); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(QColor(0,0,0,5)); p.drawRoundRect(0,0,$49,2*$49,14,7); + p.setBrush(QColor(0,0,0,9)); p.drawRoundRect($1,$1,$49-$2,2*$49,13,7); + p.setBrush(QColor(0,0,0,11)); p.drawRoundRect($2,$2,$49-dpi.$4,2*$49,12,6); + p.setBrush(QColor(0,0,0,13)); p.drawRoundRect(dpi.$3,dpi.$3,$49-dpi.$6,2*$49,48,24); + p.setCompositionMode( QPainter::CompositionMode_DestinationIn ); + p.setBrush(QColor(0,0,0,0)); p.drawRoundRect(dpi.$4,dpi.$2,$49-dpi.$8,2*$49,11,6); +// p.setCompositionMode( QPainter::CompositionMode_SourceOver ); +// p.setPen(QColor(255,255,255,200)); p.setBrush(Qt::NoBrush); +// p.drawRoundRect(dpi.$4,dpi.$2,$49-dpi.$8,2*$49,11,6); + p.setRenderHint(QPainter::Antialiasing, false); +// p.setCompositionMode( QPainter::CompositionMode_DestinationIn ); + int $33 = SCALE(33); + for (int i = 1; i < $33; ++i) { + p.setPen(QColor(0,0,0,CLAMP(i*lround(255.0/dpi.$32),0,255))); + p.drawLine(0, $49-i, $49, $49-i); + } + p.end(); + int $12 = dpi.$12; + shadows.group = Tile::Set(QPixmap::fromImage(tmpImg),$12,$12,$49-2*$12,$1); + + // mask --> uses buttons +// int $25 = SCALE(25); +// tmp = QPixmap($25,$25); +// tmp.fill(Qt::transparent); +// p.begin(&tmp); +// p.setPen(Qt::NoPen); +// p.setRenderHint(QPainter::Antialiasing); +// p.setBrush(QColor(0,0,0,255)); +// p.drawRoundRect(0,0,$25,$25,22,22); +// p.end(); +// $12 = ($25-1)/2; +// masks.group = Tile::Mask(tmp,$12,$12,$25-2*$12,$25-2*$12,0,0,0,0,22,22); + + // shadow line + int w,h,c1,c2; + for (int i = 0; i < 2; ++i) { // orientarion + if (i) { + w = $2; h = $49; + lg = QLinearGradient(0,0,0,$49); + } + else { + w = $49; h = $2; + lg = QLinearGradient(0,0,$49,0); + } + tmp = QPixmap(w,h); + for (int j = 0; j < 3; ++j) { // direction + c1 = (j > 0) ? 255 : 111; c2 = (j > 0) ? 111 : 255; + tmp.fill(Qt::transparent); + p.begin(&tmp); + stops << QGradientStop( 0, QColor(c1,c1,c1,0) ) + << QGradientStop( 0.5, QColor(c1,c1,c1,71) ) + << QGradientStop( 1, QColor(c1,c1,c1,0) ); + lg.setStops(stops); + if (i) { + p.fillRect(0,0,$1,$49,lg); + } + else { + p.fillRect(0,0,$49,$1,lg); + } + stops.clear(); + stops << QGradientStop( 0, QColor(c2,c2,c2,0) ) + << QGradientStop( 0.5, QColor(c2,c2,c2,74) ) + << QGradientStop( 1, QColor(c2,c2,c2,0) ); + lg.setStops(stops); + if (i) { + p.fillRect($1,0,$2-$1,$49,lg); + } + else { + p.fillRect(0,$1,$49,$2-$1,lg); + } + stops.clear(); + p.end(); + shadows.line[i][j] = + Tile::Line(tmp, i ? Qt::Vertical : Qt::Horizontal, $49_2, -$49_2); + } + } + + // slider handles ================================================= + QPoint triangle[3] = { QPoint(0, 100), QPoint(-100, -100), QPoint(100, -100) }; + int size; + for (int i = 0; i < 4; ++i) { // direction + size = dpi.SliderControl; + for (int j = 0; j < 2; ++j) { // sunken? + if (j) size -= $2; + for (int k = 0; k < 2; ++k) { // opaque? + shadows.slider[i][j][k] = QPixmap(size, size); + shadows.slider[i][j][k].fill(Qt::transparent); + p.begin(&shadows.slider[i][j][k]); + p.setRenderHint(QPainter::Antialiasing); + p.setPen(Qt::NoPen); + p.setBrush(QColor(0,0,0, (1+j+k)*18)); + p.translate(size/2, size/2); + p.scale(size/200.0, size/200.0); + p.rotate(-i*90.0); + p.drawPolygon(triangle, 3); + if (!j) { + p.scale(0.78, 0.78); + p.setBrush(QColor(0,0,0, (k+1)*12)); + p.drawPolygon(triangle, 3); + } + p.end(); + } + } + size = dpi.SliderControl - $4; + masks.slider[i] = QPixmap(size, size); + masks.slider[i].fill(Qt::transparent); + p.begin(&masks.slider[i]); + p.setRenderHint(QPainter::Antialiasing); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + p.translate(size/2, size/2); p.scale(size/200.0, size/200.0); + p.rotate(-i*90.0); + p.drawPolygon(triangle, 3); + p.end(); + lights.slider[i] = QPixmap(size, size); + lights.slider[i].fill(Qt::transparent); + p.begin(&lights.slider[i]); + p.setRenderHint(QPainter::Antialiasing); + p.setPen(Qt::white); + p.setBrush(Qt::NoBrush); + p.translate(size/2, size/2); p.scale(size/200.0, size/200.0); + p.rotate(-i*90.0); + p.drawPolygon(triangle, 3); + p.end(); + } + // ================================================================ + // ================================================================ + // Popup corners - not really pxmaps, though ;) =================== +// masks.popupCorner[0] = QRegion(0,0,$9,$9); +// masks.popupCorner[1] = QRegion(0,0,$9,$9); +// masks.popupCorner[2] = QRegion(0,0,$9,$9); +// masks.popupCorner[3] = QRegion(0,0,$9,$9); + // ================================================================ +#define _INITPIX_(_PIX_,_W_,_H_)\ + _PIX_ = QPixmap(_W_, _H_);\ + _PIX_.fill(Qt::transparent);\ + p.begin(&_PIX_);\ + p.setPen(Qt::NoPen);\ + p.setRenderHint(QPainter::Antialiasing) + +#define _CLOSE_ARROW_(_PIX_, _OFF_)\ + triangle[0] = QPoint(_OFF_, _PIX_.rect().center().y()+_OFF_);\ + triangle[1] = _PIX_.rect().topRight()+QPoint(-_OFF_,_OFF_);\ + triangle[2] = _PIX_.rect().bottomRight()-QPoint(_OFF_,_OFF_);\ + p.drawPolygon(triangle, 3) + +#define _MIN_ARROW_(_PIX_, _OFF_)\ + triangle[0] = _PIX_.rect().bottomLeft()+QPoint(_OFF_,-_OFF_);\ + triangle[1] = _PIX_.rect().topLeft()+QPoint(_OFF_,_OFF_);\ + triangle[2] = _PIX_.rect().bottomRight()-QPoint(_OFF_,_OFF_);\ + p.drawPolygon(triangle, 3) + +#define _MAX_ARROW_(_PIX_, _OFF_)\ + triangle[0] = _PIX_.rect().topLeft()+QPoint(_OFF_,_OFF_);\ + triangle[1] = _PIX_.rect().topRight()+QPoint(-_OFF_,_OFF_);\ + triangle[2] = _PIX_.rect().bottomRight()-QPoint(_OFF_,_OFF_);\ + p.drawPolygon(triangle, 3) + + // Window Buttons =================================== +// QPoint triangle[3]; + int $14 = SCALE(14);// $15 = SCALE(15), $16 = dpi.$16; + _INITPIX_(masks.winClose, $14,$14); + p.setBrush(Qt::black); + _CLOSE_ARROW_(masks.winClose, 0); + p.end(); + _INITPIX_(masks.winMin,$14,$14); + p.setBrush(Qt::black); + _MIN_ARROW_(masks.winMin, 0); + p.end(); + _INITPIX_(masks.winMax,$14,$14); + p.setBrush(Qt::black); + _MAX_ARROW_(masks.winMax, 0); + p.end(); + /* + shadows.winClose[0] = QPixmap($16, $16); + shadows.winMin[0] = QPixmap($16, $16); + shadows.winMax[0] = QPixmap($16, $16); + shadows.winClose[0] = QPixmap($15, $15); + shadows.winMin[0] = QPixmap($15, $15); + shadows.winMax[0] = QPixmap($15, $15); + */ + // ================================================================ +} +#undef fillRect diff --git a/clients/oxygen/gradients.cpp b/clients/oxygen/gradients.cpp new file mode 100644 index 0000000000..bfd125d1d0 --- /dev/null +++ b/clients/oxygen/gradients.cpp @@ -0,0 +1,341 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +/* ========= MAGIC NUMBERS ARE COOL ;) ================= +Ok, we want to cache the gradients, but unfortunately we have no idea about +what kind of gradients will be demanded in the future +Thus creating a 2 component map (uint for color and uint for size) +would be some overhead and cause a lot of unused space in the dictionaries - +while hashing by a string is stupid slow ;) + +So we store all the gradients by a uint index +Therefore we substitute the alpha component (byte << 24) of the demanded color +with the demanded size +As this would limit the size to 255/256 pixels we'll be a bit sloppy, +depending on the users resolution (e.g. use 0 to store a gradient with 2px, +usefull for demand of 1px or 2px) and shift the index +(e.g. gradients from 0 to 6 px size will hardly be needed - +maybe add statistics on this) +So the handled size is actually demandedSize + (demandedSize % sizeSloppyness), +beeing at least demanded size and the next sloppy size above at max +====================================================== */ +static inline uint +hash(int size, const QColor &c, int *sloppyAdd) { + + uint magicNumber = 0; + int sizeSloppyness = 1, frameBase = 0, frameSize = 20; + while ((frameBase += frameSize) < size) { + ++sizeSloppyness; + frameSize += 20; + } + + frameBase -=frameSize; frameSize -= 20; + + *sloppyAdd = size % sizeSloppyness; + if (!*sloppyAdd) + *sloppyAdd = sizeSloppyness; + + // first 11 bits to store the size, remaining 21 bits for the color (7bpc) + magicNumber = (((frameSize + (size - frameBase)/sizeSloppyness) & 0xff) << 21) | + (((c.red() >> 1) & 0x7f) << 14) | + (((c.green() >> 1) & 0x7f) << 7 ) | + ((c.blue() >> 1) & 0x7f); + + return magicNumber; +} + +static QPixmap* +newPix(int size, Qt::Orientation o, QPoint *start, QPoint *stop) { + QPixmap *pix; + if (o == Qt::Horizontal) { + pix = new QPixmap(size, 32); + *start = QPoint(0,32); *stop = QPoint(pix->width(),32); + } + else { + pix = new QPixmap(32, size); + *start = QPoint(32, 0); *stop = QPoint(32, pix->height()); + } + return pix; +} + +#define PREPARE_OXRENDER_GRADIENT QPoint start, stop; ColorArray colors; PointArray stops;\ +QPixmap *pix = newPix(size, o, &start, &stop) + +#define MAKE_OXRENDER_GRADIENT OXPicture grad = OXRender::gradient(start, stop, colors, stops);\ +OXRender::composite (grad, X::None, *pix, 0, 0, 0, 0, 0, 0, pix->width(), pix->height());\ +OXRender::freePicture(grad) + +static inline QPixmap* +simpleGradient(const QColor &c, int size, Qt::Orientation o) { + PREPARE_OXRENDER_GRADIENT; + colors << c.light(100+config.gradientIntensity*60/100) + << c.dark(100+config.gradientIntensity*20/100); + MAKE_OXRENDER_GRADIENT; + return pix; +} + +static inline QPixmap * +sunkenGradient(const QColor &c, int size, Qt::Orientation o) { + PREPARE_OXRENDER_GRADIENT; + colors << c.dark(100+config.gradientIntensity*20/100) + << c.light(100+config.gradientIntensity*60/100); + MAKE_OXRENDER_GRADIENT; + return pix; +} + +static inline QPixmap * +buttonGradient(const QColor &c, int size, Qt::Orientation o) { + + PREPARE_OXRENDER_GRADIENT; + + int h,s,v, inc, dec; + c.getHsv(&h,&s,&v); + + // calc difference + inc = 15; dec = 6; + if (v+15 > 255) { + inc = 255-v; dec += (15-inc); + } + + // make colors + QColor ic; + ic.setHsv(h,s,v+inc); colors << ic; + ic.setHsv(h,s,v-dec); colors << ic; + stops << 0 << 0.75; + + MAKE_OXRENDER_GRADIENT; + return pix; +} + +inline static void +gl_ssColors(const QColor &c, QColor *bb, QColor *dd, bool glass = false) { + + int h,s,v, ch,cs,cv, delta, add; + + c.getHsv(&h,&s,&v); + + // calculate the variation + add = ((180-qGray(c.rgb()))>>1); + if (add < 0) add = -add/2; + if (glass) + add = add>>4; + + // the brightest color (top) + cv = v+27+add; + if (cv > 255) { + delta = cv-255; cv = 255; + cs = s - delta; if (cs < 0) cs = 0; + ch = h - delta/6; if (ch < 0) ch = 360+ch; + } + else { + ch = h; cs = s; + } + bb->setHsv(ch,cs,cv); + + // the darkest color (lower center) + cv = v - 14-add; if (cv < 0) cv = 0; + cs = s*13/7; if (cs > 255) cs = 255; + dd->setHsv(h,cs,cv); +} + +static inline QPixmap * +gl_ssGradient(const QColor &c, int size, Qt::Orientation o, bool glass = false) { + QColor bb,dd; // b = d = c; + gl_ssColors(c, &bb, &dd, glass); + QPoint start, stop; + QPixmap *pix = newPix(size, o, &start, &stop); + +#if 0 + ColorArray colors; PointArray stops; + colors << bb << b << dd << d; + stops << 0 << 0.5 << 0.5 << 1; +#else + // many xrender imps are unable to create gradients with #stops > 2 + // so we "fall back" to the qt software solution here - for the moment... + QLinearGradient lg(start, stop); + lg.setColorAt(0,bb); lg.setColorAt(0.5,c); + lg.setColorAt(0.5, dd); lg.setColorAt(glass ? 1 : .90, bb); + QPainter p(pix); p.fillRect(pix->rect(), lg); p.end(); +#endif + return pix; +} + +static inline QPixmap * +rGlossGradient(const QColor &c, int size) { + QColor bb,dd; // b = d = c; + gl_ssColors(c, &bb, &dd); + QPixmap *pix = new QPixmap(size, size); + +#if 0 + ColorArray colors; PointArray stops; + colors << bb << b << dd << d; + stops << 0 << 0.5 << 0.5 << 1; +#else + // many xrender imps are unable to create gradients with #stops > 2 + // so we "fall back" to the qt software solution here - for the moment... + QRadialGradient rg(2*pix->width()/3, pix->height(), pix->height()); + rg.setColorAt(0,c); rg.setColorAt(0.8,dd); + rg.setColorAt(0.8, c); rg.setColorAt(1, bb); + QPainter p(pix); p.fillRect(pix->rect(), rg); p.end(); +#endif + return pix; +} + +const QPixmap& +OxygenStyle::gradient(const QColor &c, int size, Qt::Orientation o, GradientType type) const { + // validity check + if (size <= 0) { + qWarning("NULL Pixmap requested, size was %d",size); + return nullPix; + } + else if (size > 105883) { // this is where our dictionary reaches - should be enough for the moment ;) + qWarning("gradient with more than 105883 steps requested, returning NULL pixmap"); + return nullPix; + } + + // very dark colors won't make nice buttons =) + QColor iC = c; + int v = colorValue(c); + if (v < 80) { + int h,s; + c.getHsv(&h,&s,&v); + iC.setHsv(h,s,80); + } + + // hash + int sloppyAdd = 1; + uint magicNumber = hash(size, iC, &sloppyAdd); + + PixmapCache *cache = + &(const_cast( this )->gradients[o == Qt::Horizontal][type]); + QPixmap *pix = cache->object(magicNumber); + if (pix) + return *pix; + + // no cache entry found, so let's create one + size += sloppyAdd; // rather to big than to small ;) + switch (type) { + case GradButton: + pix = buttonGradient(iC, size, o); + break; + case GradGlass: + pix = gl_ssGradient(iC, size, o, true); + break; + case GradSimple: + default: + pix = simpleGradient(iC, size, o); + break; + case GradSunken: + pix = sunkenGradient(iC, size, o); + break; + case GradGloss: + pix = gl_ssGradient(iC, size, o); + break; + case GradRadialGloss: + pix = rGlossGradient(iC, size); + break; + } + + // cache for later + cache->insert(magicNumber, pix, (pix->width()*pix->height()*pix->depth())>>3); + return *pix; +} + +const QPixmap &OxygenStyle::groupLight(int height) const { + if (height <= 0) { + qWarning("NULL Pixmap requested, height was %d",height); + return nullPix; + } + QPixmap *pix = _groupLight.object(height); + if (pix) + return *pix; + + pix = new QPixmap(32, height); //golden mean relations + pix->fill(Qt::transparent); + QPoint start(0,0), stop(0,height); + PointArray stops; + ColorArray colors = ColorArray() << QColor(255,255,255,50) << QColor(255,255,255,0); + MAKE_OXRENDER_GRADIENT; + + // cache for later ;) + PixmapCache *cache = &(const_cast( this )->_groupLight); + cache->insert(height, pix); + return *pix; +} + +const QPixmap &OxygenStyle::btnAmbient(int height) const { + if (height <= 0) { + qWarning("NULL Pixmap requested, height was %d",height); + return nullPix; + } + QPixmap *pix = _btnAmbient.object(height); + if (pix) + return *pix; + + pix = new QPixmap(16*height/9,height); //golden mean relations + pix->fill(Qt::transparent); + ColorArray colors = ColorArray() << QColor(255,255,255,128) << QColor(255,255,255,0); + OXPicture grad = OXRender::gradient(QPoint(pix->width(), pix->height()), + QPoint(pix->width()/2,pix->height()/2), colors); + OXRender::composite (grad, None, *pix, 0, 0, 0, 0, 0, 0, pix->width(), pix->height()); + OXRender::freePicture(grad); + + // cache for later ;) + PixmapCache *cache = &(const_cast( this )->_btnAmbient); + cache->insert(height, pix); + return *pix; +} + +const QPixmap &OxygenStyle::tabShadow(int height, bool bottom) const { + if (height <= 0) { + qWarning("NULL Pixmap requested, height was %d",height); + return nullPix; + } + uint val = height + bottom*0x80000000; + QPixmap *pix = _tabShadow.object(val); + if (pix) + return *pix; + + pix = new QPixmap(height/3,height); + pix->fill(Qt::transparent); + ColorArray colors = ColorArray() << QColor(0,0,0,75) << QColor(0,0,0,0); + float hypo = sqrt(pow(pix->width(),2)+pow(pix->height(),2)); + float cosalpha = (float)(pix->height())/hypo; + QPoint p1, p2; + if (bottom) { + p1 = QPoint(0, 0); + p2 = QPoint((int)(pix->width()*pow(cosalpha, 2)), + (int)(pow(pix->width(), 2)*cosalpha/hypo)); + } + else { + p1 = QPoint(0, pix->height()); + p2 = QPoint((int)(pix->width()*pow(cosalpha, 2)), + (int)pix->height() - (int)(pow(pix->width(), 2)*cosalpha/hypo)); + } + OXPicture grad = OXRender::gradient(p1, p2, colors); + OXRender::composite (grad, None, *pix, 0, 0, 0, 0, 0, 0, pix->width(), pix->height()); + OXRender::freePicture(grad); + + // cache for later ;) + PixmapCache *cache = &(const_cast( this )->_tabShadow); + cache->insert(val, pix); + return *pix; +} diff --git a/clients/oxygen/inlinehelp.cpp b/clients/oxygen/inlinehelp.cpp new file mode 100644 index 0000000000..8ee05e57ec --- /dev/null +++ b/clients/oxygen/inlinehelp.cpp @@ -0,0 +1,199 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef INLINEHELP_CPP +#define INLINEHELP_CPP + +#ifndef CLAMP +#define CLAMP(x,l,u) (x) < (l) ? (l) :\ +(x) > (u) ? (u) :\ +(x) +#endif + +#ifndef QABS +#define QABS(x) (x) > 0 ? (x) : (-(x)) +#endif + +#ifndef _PRINTFLAGS_ +#define _PRINTFLAGS_ option ? qWarning("State Flags:\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",\ +option->state & State_Active ? "Active, " : "",\ +option->state & State_AutoRaise ? "AutoRaise, " : "",\ +option->state & State_Bottom ? "Bottom, " : "",\ +option->state & State_Children ? "Children, " : "",\ +option->state & State_None ? "None, " : "",\ +option->state & State_DownArrow ? "DownArrow, " : "",\ +option->state & State_Editing ? "Editing, " : "",\ +option->state & State_Enabled ? "Enabled, " : "",\ +option->state & State_FocusAtBorder ? "FocusAtBorder, " : "",\ +option->state & State_HasFocus ? "HasFocus, " : "",\ +option->state & State_Horizontal ? "Horizontal, " : "",\ +option->state & State_Item ? "Item, " : "",\ +option->state & State_MouseOver ? "MouseOver, " : "",\ +option->state & State_NoChange ? "NoChange, " : "",\ +option->state & State_Off ? "Off, " : "",\ +option->state & State_On ? "On, " : "",\ +option->state & State_Open ? "Open, " : "",\ +option->state & State_Raised ? "Raised, " : "",\ +option->state & State_Selected ? "Selected, " : "",\ +option->state & State_Sibling ? "Sibling, " : "",\ +option->state & State_Sunken ? "Sunken, " : "",\ +option->state & State_Top ? "Top, " : "",\ +option->state & State_UpArrow ? "UpArrow, " : "",\ +option->state & State_KeyboardFocusChange ? "KeyboardFocusChange, " : "",\ +option->state & State_ReadOnly ? "ReadOnly, " : "") : qWarning("MISSING OPTIONS") +#endif + +/**Internal calculates hsv v from color, faster than calling qcolor.hsv if you only want v*/ +inline int colorValue(const QColor &c) { + int v = c.red(); + if (c.green() > v) v = c.green(); + if (c.blue() > v) v = c.blue(); + return v; +} + +/**Internal, calcs weighted mid of two colors*/ +inline QColor midColor(const QColor &oc1, const QColor &c2, int w1 = 1, int w2 = 1) { + int sum = (w1+w2); + QColor c1 = oc1; + int h,s, v = colorValue(c1); + if (v < 70) { + c1.getHsv(&h,&s,&v); + c1.setHsv(h,s,70); + } + return QColor((w1*c1.red() + w2*c2.red())/sum, + (w1*c1.green() + w2*c2.green())/sum, + (w1*c1.blue() + w2*c2.blue())/sum, + (w1*c1.alpha() + w2*c2.alpha())/sum); +} + +#define TMP_COLOR(_ROLE_) pal.color(QPalette::_ROLE_) +#define TMP_CONF_COLOR(_ROLE_) pal.color(config._ROLE_) + +/**Internal, calcs button color depending on state*/ + +inline QColor btnBgColor(const QPalette &pal, bool isEnabled, bool hover = false, int step = 0) { + if (!isEnabled) + return TMP_COLOR(Window); + if (step) + return midColor(TMP_CONF_COLOR(role_btn[0]), + TMP_CONF_COLOR(role_btnHover[0]), + 8-step, step); + if (hover) + return TMP_CONF_COLOR(role_btnHover[0]); + return TMP_CONF_COLOR(role_btn[0]).dark(103); +} + + + +/**Internal, calcs buttonText color depending on state*/ +inline QColor btnFgColor(const QPalette &pal, bool isEnabled, bool hover = false, int step = 0) { + if (!isEnabled) + return midColor(TMP_COLOR(Window), TMP_COLOR(WindowText), 1, 3); + if (step) + return midColor(TMP_CONF_COLOR(role_btn[1]), + TMP_CONF_COLOR(role_btnHover[1]), + 6-step, step); + if (hover) + return TMP_CONF_COLOR(role_btnHover[1]); + return TMP_CONF_COLOR(role_btn[1]); +} + +#undef TMP_COLOR +#undef TMP_CONF_COLOR + +/**Internal, calcs a contrasted color to a qcolor*/ +inline QColor emphasize(const QColor &c, int value = 10) { + int h,s,v; + QColor ret; + c.getHsv(&h,&s,&v); + if (v < 75+value) { + ret.setHsv(h,s,CLAMP(85+value,85,255)); + return ret; + } + if (v > 200) { + if (s > 30) { + h -= 5; if (h < 0) h = 360 + h; + s = (s<<3)/9; + v += value; + ret.setHsv(h,CLAMP(s,30,255),CLAMP(v,0,255)); + return ret; + } + if (v > 230) { + ret.setHsv(h,s,CLAMP(v-value,0,255)); + return ret; + } + } + if (v > 128) + ret.setHsv(h,s,CLAMP(v+value,0,255)); + else + ret.setHsv(h,s,CLAMP(v-value,0,255)); + return ret; +} + +/**Internal, calcs a lightned version of a qcolor*/ +inline QColor light(const QColor &c, int value) +{ + int h,s,v; + c.getHsv(&h,&s,&v); + QColor ret; + if (v < 255-value) { + ret.setHsv(h,s,CLAMP(v+value,0,255)); //value could be negative + return ret; + } + // psychovisual uplightning, i.e. shift hue and lower saturation + if (s > 30) { + h -= (value*5/20); if (h < 0) h = 400 + h; + s = CLAMP((s<<3)/9,30,255); + ret.setHsv(h,s,255); + return ret; + } + else // hue shifting has no sense, half saturation (btw, white won't get brighter :) + ret.setHsv(h,s>>1,255); + return ret; +} + +inline bool verticalTabs(QTabBar::Shape shape) { + return shape == QTabBar::RoundedEast || + shape == QTabBar::TriangularEast || + shape == QTabBar::RoundedWest || + shape == QTabBar::TriangularWest; +} + +#if 0 +/**Internal, checks if there's contrast between two colors*/ +static bool thereIsContrastBetween(const QColor &a, const QColor &b) +{ + int ar,ag,ab,br,bg,bb; + a.getRgb(&ar,&ag,&ab); + b.getRgb(&br,&bg,&bb); + + int diff = (299*(ar-br) + 587*(ag-bg) + 114*(ab-bb)); + + if (QABS(diff) < 91001) + return false; + + diff = qMax(ar,br) + qMax(ag,bg) + qMax(ab,bb) + - (qMin(ar,br) + qMin(ag,bg) + qMin(ab,bb)); + + return (diff > 300); +} +#endif + +#endif //INLINEHELP_CPP diff --git a/clients/oxygen/makros.h b/clients/oxygen/makros.h new file mode 100644 index 0000000000..865dfef476 --- /dev/null +++ b/clients/oxygen/makros.h @@ -0,0 +1,29 @@ +#ifndef OXYGEN_DEFS_H +#define OXYGEN_DEFS_H + +#define _IsNotHtmlWidget(w) ( w->objectName() != "__khtml" ) +#define _IsHtmlWidget(w) ( w->objectName() == "__khtml" ) +#define _IsViewportChild(w) w->parent() &&\ +( w->parent()->objectName() == "qt_viewport" || \ + w->parent()->objectName() == "qt_clipped_viewport" ) + +#define _HighContrastColor(c) (qGray(c.rgb()) < 128 ) ? Qt::white : Qt::black + +#define _BLOCKEVENTS_(obj) obj->installEventFilter(eventKiller) +#define _UNBLOCKEVENTS_(obj) obj->removeEventFilter(eventKiller) + +#define _IsTabStack(w) ( w->objectName() == "qt_tabwidget_stackedwidget" ) + +#define SAVE_PEN QPen saved_pen = painter->pen(); +#define RESTORE_PEN painter->setPen(saved_pen); +#define SAVE_BRUSH QBrush saved_brush = painter->brush(); +#define RESTORE_BRUSH painter->setBrush(saved_brush); +#define SAVE_ANTIALIAS bool hadAntiAlias = painter->renderHints() & QPainter::Antialiasing; +#define RESTORE_ANTIALIAS painter->setRenderHint(QPainter::Antialiasing, hadAntiAlias); + +#define RECT option->rect +#define PAL option->palette +#define COLOR(_TYPE_) option->palette.color(QPalette::_TYPE_) +#define CONF_COLOR(_TYPE_) option->palette.color(config._TYPE_) + +#endif //OXYGEN_DEFS_H diff --git a/clients/oxygen/oxrender.cpp b/clients/oxygen/oxrender.cpp new file mode 100644 index 0000000000..dc4030c218 --- /dev/null +++ b/clients/oxygen/oxrender.cpp @@ -0,0 +1,220 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "oxrender.h" + +static Display *dpy = QX11Info::display(); +static Window root = RootWindow (dpy, DefaultScreen (dpy)); + +/* "qt_getClipRects" is friend enough to qregion... ;)*/ +inline void *qt_getClipRects( const QRegion &r, int &num ) +{ + return r.clipRectangles( num ); +} + +static OXPicture createFill(Display *dpy, const XRenderColor *c) +{ + XRenderPictureAttributes pa; + OXPixmap pixmap = XCreatePixmap (dpy, root, 1, 1, 32); + if (!pixmap) + return X::None; + pa.repeat = True; + OXPicture fill = XRenderCreatePicture (dpy, pixmap, XRenderFindStandardFormat (dpy, PictStandardARGB32), CPRepeat, &pa); + if (!fill) + { + XFreePixmap (dpy, pixmap); + return X::None; + } + XRenderFillRectangle (dpy, PictOpSrc, fill, c, 0, 0, 1, 1); + XFreePixmap (dpy, pixmap); + return fill; +} + +void OXRender::composite(OXPicture src, OXPicture mask, OXPicture dst, + int sx, int sy, int mx, int my, int dx, int dy, + uint w, uint h, int op) +{ + XRenderComposite (dpy, op, src, mask, dst, sx, sy, mx, my, dx, dy, w, h); +} +void OXRender::composite(OXPicture src, OXPicture mask, const QPixmap &dst, + int sx, int sy, int mx, int my, int dx, int dy, + uint w, uint h, int op) +{ + XRenderComposite (dpy, op, src, mask, dst.x11PictureHandle(), sx, sy, mx, my, dx, dy, w, h); +} +void OXRender::composite(const QPixmap &src, OXPicture mask, const QPixmap &dst, + int sx, int sy, int mx, int my, int dx, int dy, + uint w, uint h, int op) +{ + XRenderComposite (dpy, op, src.x11PictureHandle(), mask, dst.x11PictureHandle(), sx, sy, mx, my, dx, dy, w, h); +} + +bool OXRender::blend(const QPixmap &upper, QPixmap &lower, double opacity) +{ + XRenderColor c = {0,0,0, (ushort)(opacity * 0xffff) }; + OXPicture alpha = createFill (dpy, &c); + if (alpha == X::None) + return false; + XRenderComposite (dpy, PictOpOver, upper.x11PictureHandle(), alpha, lower.x11PictureHandle(), 0, 0, 0, 0, 0, 0, upper.width(), upper.height()); + XRenderFreePicture (dpy, alpha); + return true; +} + +QPixmap OXRender::applyAlpha(const QPixmap &toThisPix, const QPixmap &fromThisPix, const QRect &rect, const QRect &alphaRect) { + return applyAlpha(toThisPix, fromThisPix.x11PictureHandle(), rect, alphaRect); +} + +QPixmap OXRender::applyAlpha(const QPixmap &toThisPix, const OXPicture &fromThisPict, const QRect &rect, const QRect &alphaRect) { + int sx,sy,ax,ay,w,h; + if (rect.isNull()) { + sx = sy = 0; w = toThisPix.width(); h = toThisPix.height(); + } + else + rect.getRect(&sx,&sy,&w,&h); + if (alphaRect.isNull()) { + ax = ay = 0; + } + else { + ax = alphaRect.x(); ay = alphaRect.y(); + w = qMin(alphaRect.width(),w); h = qMin(alphaRect.height(),h); + } + + QPixmap pix(w,h); + pix.fill(Qt::transparent); + XRenderComposite (dpy, PictOpOver, toThisPix.x11PictureHandle(), + fromThisPict, pix.x11PictureHandle(), + sx, sy, ax, ay, 0, 0, w, h); + return pix; +} + +void OXRender::setAlpha(QPixmap &pix, const OXPicture &alpha) +{ + XRenderPictureAttributes pa; + pa.alpha_map = alpha; + pa.alpha_x_origin = pa.alpha_y_origin = 0; + XRenderChangePicture(dpy, pix.x11PictureHandle(), CPAlphaMap|CPAlphaXOrigin|CPAlphaYOrigin, &pa); +} + +QPixmap OXRender::fade(const QPixmap &pix, double percent) +{ + QPixmap newPix(pix.size()); + newPix.fill(Qt::transparent); + blend(pix, newPix, percent); + return newPix; +} + +void OXRender::setColor(XRenderColor &xc, double r, double g, double b, double a) +{ + xc.red = ushort(r * 0xffff); + xc.green = ushort(g * 0xffff); + xc.blue = ushort(b * 0xffff); + xc.alpha = ushort(a * 0xffff); +} + +void OXRender::setColor(XRenderColor &xc, QColor qc) +{ + xc.red = qc.red()*0x101; xc.green = qc.green()*0x101; + xc.blue = qc.blue()*0x101; xc.alpha = qc.alpha()*0x101; +} + +void OXRender::setGradient(XLinearGradient &lg, QPoint p1, QPoint p2) +{ + lg.p1.x = p1.x(); lg.p1.y = p1.y(); + lg.p2.x = p2.x(); lg.p2.y = p2.y(); +} + +void OXRender::setGradient(XLinearGradient &lg, XFixed x1, XFixed y1, XFixed x2, XFixed y2) +{ + lg.p1.x = x1; lg.p1.y = y1; + lg.p2.x = x2; lg.p2.y = y2; +} + +OXPicture OXRender::gradient(const QPoint start, const QPoint stop, const ColorArray &colors, const PointArray &stops) +{ + XLinearGradient lg = { + { start.x() << 16, start.y() << 16 }, + { stop.x() << 16, stop.y() << 16} }; + QVarLengthArray cs(colors.size()); + for (int i = 0; i < colors.size(); ++i) + setColor(cs[i], colors.at(i)); + XFixed *stps; + if (stops.size() < 2) + { + stps = new XFixed[2]; + stps[0] = 0; stps[1] = (1<<16); + } + else + { + int d = (1<<16); + stps = new XFixed[stops.size()]; + for (int i = 0; i < stops.size(); ++i) + { + if (stops.at(i) < 0) continue; + if (stops.at(i) > 1) break; + stps[i] = stops.at(i)*d; + } + } + XFlush (dpy); + OXPicture lgp = XRenderCreateLinearGradient(dpy, &lg, stps, &cs[0], qMin(qMax(stops.size(),2),colors.size())); + delete[] stps; + return lgp; +} + +OXPicture OXRender::gradient(const QPoint c1, int r1, const QPoint c2, int r2, const ColorArray &colors, const PointArray &stops) +{ + XRadialGradient rg = { + { c1.x() << 16, c1.y() << 16, r1 << 16 }, + { c2.x() << 16, c2.y() << 16, r2 << 16 } }; + QVarLengthArray cs(colors.size()); + for (int i = 0; i < colors.size(); ++i) + setColor(cs[i], colors.at(i)); + XFixed *stps; + if (stops.size() < 2) + { + stps = new XFixed[2]; + stps[0] = 0; stps[1] = (1<<16); + } + else + { + int d = ((int)(sqrt(pow(c2.x()-c1.x(),2)+pow(c2.y()-c1.y(),2)))) << 16; + stps = new XFixed[stops.size()]; + for (int i = 0; i < stops.size(); ++i) + { + if (stops.at(i) < 0) continue; + if (stops.at(i) > 1) break; + stps[i] = stops.at(i)*d; + } + } + XFlush (dpy); + OXPicture lgp = XRenderCreateRadialGradient(dpy, &rg, stps, &cs[0], qMin(qMax(stops.size(),2),colors.size())); + delete[] stps; + return lgp; +} + +void OXRender::freePicture(OXPicture pict) +{ + XRenderFreePicture (dpy, pict); +} diff --git a/clients/oxygen/oxrender.h b/clients/oxygen/oxrender.h new file mode 100644 index 0000000000..0eb03c38fe --- /dev/null +++ b/clients/oxygen/oxrender.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef OXRENDER_H +#define OXRENDER_H + +#include +#include +#include +#include +#include + +typedef QVector PointArray; +typedef QVector ColorArray; +typedef Picture OXPicture; +typedef Pixmap OXPixmap; + +class OXRender +{ +// public: +// OXRender(){} +public: + static void composite(OXPicture src, OXPicture mask, OXPicture dst, int sx, int sy, int mx, int my, int dx, int dy, uint w, uint h, int op = PictOpSrc); + static void composite(OXPicture src, OXPicture mask, const QPixmap &dst, int sx, int sy, int mx, int my, int dx, int dy, uint w, uint h, int op = PictOpSrc); + static void composite(const QPixmap &src, OXPicture mask, const QPixmap &dst, int sx, int sy, int mx, int my, int dx, int dy, uint w, uint h, int op = PictOpSrc); + static bool blend(const QPixmap &upper, QPixmap &lower, double opacity = 0.5); + static QPixmap fade(const QPixmap &pix, double percent); + static void setColor(XRenderColor &xc, double r, double g, double b, double a = 1); + static void setColor(XRenderColor &xc, QColor qc); + static void setAlpha(QPixmap &pix, const OXPicture &mask); + static QPixmap applyAlpha(const QPixmap &toThisPix, const QPixmap &fromThisPix, + const QRect &rect = QRect(), const QRect &alphaRect = QRect()); + static QPixmap applyAlpha(const QPixmap &toThisPix, const OXPicture &fromThisPict, + const QRect &rect = QRect(), const QRect &alphaRect = QRect()); + static void setGradient(XLinearGradient &lg, QPoint p1, QPoint p2); + static void setGradient(XLinearGradient &lg, XFixed x1, XFixed y1, XFixed x2, XFixed y2); + static OXPicture gradient(const QPoint start, const QPoint stop, const ColorArray &colors, const PointArray &stops = PointArray()); + static OXPicture gradient(const QPoint c1, int r1, const QPoint c2, int r2, const ColorArray &colors, const PointArray &stops = PointArray()); + static void freePicture(OXPicture pict); +}; + +#define Q2XRenderColor(_XRC_, _QC_) XRenderColor _XRC_; OXRender::setColor(_XRC_, _QC_) + +#endif //OXRENDER_H diff --git a/clients/oxygen/oxygen.cpp b/clients/oxygen/oxygen.cpp new file mode 100644 index 0000000000..c1276223a2 --- /dev/null +++ b/clients/oxygen/oxygen.cpp @@ -0,0 +1,1226 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +/**================== Qt4 includes ======================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/**============= Qt3 support includes ======================*/ +#include +/**========================================================*/ + +/**============= System includes ==========================*/ +// #include +#include +#include +#include +#include +// #include +#include +#include +#include +#include +/**========================================================*/ + +/**============= DEBUG includes ==========================*/ +#undef DEBUG +#ifdef DEBUG +#define MOUSEDEBUG 1 +#include +#include "debug.h" +#define oDEBUG qDebug() +#include +#define _PROFILESTART_ QTime timer; int time; timer.start(); +#define _PROFILERESTART_ timer.restart(); +#define _PROFILESTOP_(_STRING_) time = timer.elapsed(); qDebug("%s: %d",_STRING_,time); +#else +#define oDEBUG // +#undef MOUSEDEBUG +#endif +/**========================================================*/ + +/**============= Oxygen includes ==========================*/ +#include "oxygen.h" +#include "dynamicbrush.h" +#include "makros.h" +/**=========================================================*/ + + +/**============= extern C stuff ==========================*/ +class OxygenStylePlugin : public QStylePlugin +{ +public: + QStringList keys() const { + return QStringList() << "Oxygen"; + } + + QStyle *create(const QString &key) { + if (key == "oxygen") + return new Oxygen::OxygenStyle; + return 0; + } +}; + +Q_EXPORT_PLUGIN2(OxygenStyle, OxygenStylePlugin) +/**=========================================================*/ +using namespace Oxygen; + +/** static config object */ +Config config; +Dpi dpi; + +/** The event killer*/ +bool EventKiller::eventFilter( QObject *, QEvent *) +{ + return true; +} +static EventKiller *eventKiller = new EventKiller(); + +/** Let's try if we can supply round frames that shape their content */ + +VisualFrame::VisualFrame(QFrame *parent, int st, int sl, int sr, int sb) : QWidget(parent) { + if (!(parent && (st+sl+sr+sb))) { + deleteLater(); return; + } + connect(parent, SIGNAL(destroyed(QObject*)), this, SLOT(deleteLater())); + off[0] = st; off[1] = sl; off[2] = sr; off[3] = sb; + parent->installEventFilter(this); + this->installEventFilter(this); + show(); +} + +void VisualFrame::paintEvent ( QPaintEvent * event ) { + if (!parent()) { + deleteLater(); return; + } + QFrame *frame = static_cast(parent()); + QPainter p(this); + p.setClipRegion(event->region(), Qt::IntersectClip); + QStyleOption opt; + if (frame->frameShadow() == QFrame::Raised) + opt.state |= QStyle::State_Raised; + else if (frame->frameShadow() == QFrame::Sunken) + opt.state |= QStyle::State_Sunken; + if (frame->hasFocus()) + opt.state |= QStyle::State_HasFocus; + if (frame->isEnabled()) + opt.state |= QStyle::State_Enabled; + opt.rect = rect(); + style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, this); + p.end(); +} + +void VisualFrame::passDownEvent(QEvent *ev, const QPoint &gMousePos) { + if (!parent()) { + deleteLater(); return; + } + // the raised frames don't look like you could click in, we'll see if this should be chnged... + QFrame *frame = static_cast(parent()); + if (frame->frameShadow() == QFrame::Raised) + return; + QList candidates = frame->findChildren(); + QList::const_iterator i = candidates.constEnd(); + QWidget *match = 0; + while (i != candidates.constBegin()) { + --i; + if (*i == this) + continue; + if ((*i)->rect().contains((*i)->mapFromGlobal(gMousePos))) + { + match = *i; + break; + } + } + if (!match) match = frame; + QCoreApplication::sendEvent( match, ev ); +} + +void VisualFrame::mouseDoubleClickEvent ( QMouseEvent * event ) { passDownEvent((QEvent *)event, event->globalPos()); } +void VisualFrame::mouseMoveEvent ( QMouseEvent * event ) { passDownEvent((QEvent *)event, event->globalPos()); } +void VisualFrame::mousePressEvent ( QMouseEvent * event ) { passDownEvent((QEvent *)event, event->globalPos()); } +void VisualFrame::mouseReleaseEvent ( QMouseEvent * event ) { passDownEvent((QEvent *)event, event->globalPos()); } +void VisualFrame::wheelEvent ( QWheelEvent * event ) { passDownEvent((QEvent *)event, event->globalPos()); } + +bool VisualFrame::eventFilter ( QObject * o, QEvent * ev ) { + if (o == this) { + if (ev->type() == QEvent::ZOrderChange) + this->raise(); + return false; + } + if (o != parent()) { + o->removeEventFilter(this); + return false; + } + if (ev->type() == QEvent::Resize) { + QRect rect = static_cast(o)->frameRect(); + move(rect.topLeft()); resize(rect.size()); + setMask(QRegion(rect).subtracted(rect.adjusted(off[0],off[1],-off[2],-off[3]))); + return false; + } + if (ev->type() == QEvent::FocusIn || + ev->type() == QEvent::FocusOut) { + update(); + return false; + } + return false; +} + +/** to be able to send nullpix refs */ +static QPixmap nullPix; + +/** Get some excluded code */ +#include "inlinehelp.cpp" +#include "animation.cpp" +#include "gradients.cpp" + +/** Internal, handles the shared bg pixmaps*/ +static Pixmap bgPix = 0; +static Pixmap fgPix = 0; +Pixmap shadowPix; +int bgYoffset_; + +static void loadPixmaps() +{ + QFile file("/tmp/oxygenPixIDs"); + char ignore; + if (file.open( QIODevice::ReadOnly )) + { + QTextStream ts( &file ); + ts >> bgPix >> ignore >> shadowPix >> ignore >> fgPix >> ignore >> bgYoffset_; + file.close(); +// QSettings settings; +// settings.beginGroup("/oxygen/Style"); +// config.bgMode = (BGTileMode) settings.value("BackgroundMode", FullPix).toInt(); +// settings.endGroup(); + } + else + { + fgPix = shadowPix = bgPix = 0; + } +} + +/**For painting the shared xpixmap on a qmenu*/ +inline void *qt_getClipRects( const QRegion &r, int &num ) +{ + return r.clipRectangles( num ); +} +extern Drawable qt_x11Handle(const QPaintDevice *pd); +/**=====================================================================*/ + +/**Some static variables*/ + +// static const int windowsItemFrame = 1; // menu item frame width +// static const int windowsSepHeight = 2; // separator item height +// static const int windowsItemHMargin = 3; // menu item hor text margin +// static const int windowsItemVMargin = 1; // menu item ver text margin +// static const int windowsArrowHMargin = 6; // arrow horizontal margin +// static const int windowsTabSpacing = 12; // space between text and tab +// static const int windowsCheckMarkHMargin= 2; // horiz. margins of check mark +// static const int windowsRightBorder = 12; // right border on windows +// static const int windowsCheckMarkWidth = 14; // checkmarks width on windows + +static QColor originalBgColor_; +static QColor groupShadowColor_; + +static bool invColorRole(QPalette::ColorRole &from, QPalette::ColorRole &to, + QPalette::ColorRole defFrom = QPalette::WindowText, QPalette::ColorRole defTo = QPalette::Window) +{ + switch (from) + { + case QPalette::WindowText: //0 + to = QPalette::Window; break; + case QPalette::Window: //10 + to = QPalette::WindowText; break; + case QPalette::Base: //9 + to = QPalette::Text; break; + case QPalette::Text: //6 + to = QPalette::Base; break; + case QPalette::Button: //1 + to = QPalette::ButtonText; break; + case QPalette::ButtonText: //8 + to = QPalette::Button; break; + case QPalette::Highlight: //12 + to = QPalette::HighlightedText; break; + case QPalette::HighlightedText: //13 + to = QPalette::Highlight; break; + default: + from = defFrom; + to = defTo; + return false; + } + return true; +} + +void OxygenStyle::makeStructure(int num, const QColor &c) +{ + if (!_scanlines[num]) + _scanlines[num] = new QPixmap(64, 64); + QPainter p(_scanlines[num]); + switch (config.structure) + { + default: + case 0: { // scanlines + _scanlines[num]->fill( c.light(110).rgb() ); + p.setPen( (num == 1) ? c.light(106) : c.light(103) ); + int i; + for ( i = 1; i < 64; i += 4 ) + { + p.drawLine( 0, i, 63, i ); + p.drawLine( 0, i+2, 63, i+2 ); + } + p.setPen( c ); + for ( i = 2; i < 63; i += 4 ) + p.drawLine( 0, i, 63, i ); + break; + } + case 1: { //checkboard + p.setPen(Qt::NoPen); + p.setBrush(c.light(102)); + if (num == 1) { + p.drawRect(0,0,16,16); p.drawRect(32,0,16,16); + p.drawRect(16,16,16,16); p.drawRect(48,16,16,16); + p.drawRect(0,32,16,16); p.drawRect(32,32,16,16); + p.drawRect(16,48,16,16); p.drawRect(48,48,16,16); + } + else { + p.drawRect(0,0,32,32); + p.drawRect(32,32,32,32); + } + p.setBrush(c.dark(102)); + if (num == 1) { + p.drawRect(16,0,16,16); p.drawRect(48,0,16,16); + p.drawRect(0,16,16,16); p.drawRect(32,16,16,16); + p.drawRect(16,32,16,16); p.drawRect(48,32,16,16); + p.drawRect(0,48,16,16); p.drawRect(32,48,16,16); + } + else { + p.drawRect(32,0,32,32); + p.drawRect(0,32,32,32); + } + break; + } + case 2: // bricks - sucks... + p.setPen(c.dark(105)); + p.setBrush(c.light(102)); + p.drawRect(0,0,32,16); p.drawRect(32,0,32,16); + p.drawRect(0,16,16,16); p.drawRect(16,16,32,16); p.drawRect(48,16,16,16); + p.drawRect(0,32,32,16); p.drawRect(32,32,32,16); + p.drawRect(0,48,16,16); p.drawRect(16,48,32,16); p.drawRect(48,48,16,16); + break; + } + p.end(); +} + +void OxygenStyle::readSettings() +{ + QSettings settings("Oxygen", "Style"); + settings.beginGroup("Style"); + + config.bgMode = (BGMode) settings.value("BackgroundMode", FullPix).toInt(); + config.acceleration = (Acceleration) settings.value("Acceleration", XRender).toInt(); + if (config.acceleration == None) config.bgMode = Plain; + config.structure = settings.value("Structure", 0).toInt(); + + config.scale = settings.value("Scale", 1.0).toDouble(); + config.checkType = settings.value("CheckType", 1).toInt(); + + + config.gradientIntensity = settings.value("GradientIntensity",70).toInt(); + + config.tabTransition = (TabTransition) settings.value("TabTransition", ScanlineBlend).toInt(); + + config.gradient = GradGlass; + config.gradientStrong = GradGloss; + config.aqua = settings.value("Aqua", true).toBool(); + if (!config.aqua) { + config.gradient = GradButton; + config.gradientStrong = GradSimple; + } + if (settings.value("InverseButtons", false).toBool()) + config.gradBtn = GradSunken; + else + config.gradBtn = config.gradient; + + config.showMenuIcons = settings.value("ShowMenuIcons", false).toBool(); + config.glassMenus = !settings.value("RuphysMenu", false).toBool(); + config.menuShadow = settings.value("MenuShadow", false).toBool(); + + config.glassProgress = settings.value("GlassProgress", true).toBool(); + + // color roles + config.role_progress[0] = + (QPalette::ColorRole) settings.value("role_progressGroove", QPalette::WindowText).toInt(); + invColorRole(config.role_progress[0], config.role_progress[1], + QPalette::WindowText, QPalette::Window); + config.role_progress[1] = + (QPalette::ColorRole) settings.value("role_progress", config.role_progress[1]).toInt(); + config.role_tab[0] = + (QPalette::ColorRole) settings.value("role_tab", QPalette::Button).toInt(); + invColorRole(config.role_tab[0], config.role_tab[1], + QPalette::Button, QPalette::ButtonText); + config.role_btn[0] = + (QPalette::ColorRole) settings.value("role_button", QPalette::Window).toInt(); + invColorRole(config.role_btn[0], config.role_btn[1], + QPalette::Button, QPalette::WindowText); + config.role_btnHover[0] = + (QPalette::ColorRole) settings.value("role_buttonHover", QPalette::Button).toInt(); + invColorRole(config.role_btnHover[0], config.role_btnHover[1], + QPalette::Button, QPalette::ButtonText); + config.role_popup[0] = + (QPalette::ColorRole) settings.value("role_popup", QPalette::Window).toInt(); + invColorRole(config.role_popup[0], config.role_popup[1], + QPalette::Window, QPalette::WindowText); + + settings.endGroup(); +} + +#define SCALE(_N_) lround(_N_*config.scale) + +#include "genpixmaps.cpp" + +void OxygenStyle::initMetrics() +{ + dpi.$1 = SCALE(1); dpi.$2 = SCALE(2); + dpi.$3 = SCALE(3); dpi.$4 = SCALE(4); + dpi.$5 = SCALE(5); dpi.$6 = SCALE(6); + dpi.$7 = SCALE(7); dpi.$8 = SCALE(8); + dpi.$9 = SCALE(9); dpi.$10 =SCALE(10); + + dpi.$12 = SCALE(12); dpi.$13 = SCALE(13); + dpi.$16 = SCALE(16); dpi.$18 = SCALE(18); + dpi.$20 = SCALE(20); dpi.$32 = SCALE(32); + dpi.$80 = SCALE(80); + + dpi.ScrollBarExtent = SCALE(20); + dpi.ScrollBarSliderMin = SCALE(40); + dpi.SliderThickness = SCALE(24); + dpi.SliderControl = SCALE(17); + dpi.Indicator = SCALE(24); + dpi.ExclusiveIndicator = SCALE(19); +} + +#undef SCALE + +/**THE STYLE ITSELF*/ +OxygenStyle::OxygenStyle() : QCommonStyle(), animationUpdate(false), +mouseButtonPressed_(false), internalEvent_(false), _bgBrush(0L), popupPix(0L), +timer(0L) { + _scanlines[0] = _scanlines[1] = 0L; + readSettings(); + initMetrics(); + generatePixmaps(); + // init the caches + for (int i = 0; i < 2; ++i) + for (int j = 0; j < NumGrads; ++j) + gradients[i][j].setMaxCost( 1024<<10 ); + + //====== TOOLTIP ====================== +// tooltipPalette = qApp->palette(); +// tooltipPalette.setBrush( QPalette::Background, QColor( 255, 255, 220 ) ); +// tooltipPalette.setBrush( QPalette::Foreground, Qt::black ); + //======================================= + + +// if (KApplication::kApplication()) +// connect(KApplication::kApplication(), SIGNAL(kipcMessage(int, int)), this, SLOT (handleIPC(int, int))); + +#if 0 + // TEST!!! + if (KApplication::kApplication()) + { + _PROFILESTART_ + QByteArray data, replyData; + QCString replyType; + QDataStream arg(data, IO_WriteOnly); + arg << ""; + if (!KApplication::kApplication()->dcopClient()->call("kwin", "OxygenInterface", "pixmap()", data, replyType, replyData)) + qDebug("there was some error using DCOP."); + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QPixmap") + { + QPixmap result; + reply >> result; + } + else + qDebug("pixmap() returned an unexpected type of reply!"); + } + _PROFILESTOP_("dcop pixmap") + } + //=========== +#endif + + // start being animated + timer = new QTimer( this ); +// timer->start(50); + connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressbars())); + connect(timer, SIGNAL(timeout()), this, SLOT(updateTabAnimation())); + connect(timer, SIGNAL(timeout()), this, SLOT(updateFades())); + connect(timer, SIGNAL(timeout()), this, SLOT(updateComplexFades())); + connect(timer, SIGNAL(timeout()), this, SLOT(updateIndexedFades())); +} + +OxygenStyle::~OxygenStyle() { + for (int i = 0; i < 2; i++) + for (int j = 0; j < NumGrads; j++) + gradients[i][j].clear(); + glowCache.clear(); + _btnAmbient.clear(); + _tabShadow.clear(); + roundGlowCache.clear(); + if (timer) { + timer->disconnect(); + timer->stop(); +// delete timer; + } + progressbars.clear(); + +// bfi.clear(); +// fadeColorMap.clear(); + + bgPix = 0L; + shadowPix = 0L; + fgPix = 0L; +} + +/**handles updates to the bg pixmap*/ +void OxygenStyle::handleIPC(int /*id*/, int /*data*/) +{ +#if 0 + if (id != 32 || data != 151616) //TODO: use custom ID as soon as kapp supports random values on this + return; + loadPixmaps(); + if (qApp->desktop()) + bgYoffset_ = qApp->desktop()->height()*bgYoffset_/738; + popupPix = config.inversePopups ? fgPix : bgPix; + // tell the deco that this it a oxygen styled qt window + if (!bgPix) + { + foreach (QWidget *w, QApplication::topLevelWidgets()) + { + if (!(qobject_cast(w) || + qobject_cast(w) || + (w->windowType() == Qt::Desktop) || + w->inherits("QTipLabel") || + qobject_cast(w))) + w->setPalette(QPalette()); //TODO: make sure this is a bgPix'd widget! + } + } + else + { + foreach (QWidget *w, QApplication::topLevelWidgets()) + { + if (!(qobject_cast(w) || + qobject_cast(w) || + (w->windowType() == Qt::Desktop) || + w->inherits("QTipLabel") || + qobject_cast(w))) + { + // faking resize to make sure the window's bg is updated + QResizeEvent* rev = new QResizeEvent(w->size(), QSize(0,0)); + backgroundHandler_->eventFilter( w, rev ); + } + } + } +#endif +} + +/** for creating the highlight glow pixmps*/ +QPixmap *OxygenStyle::tint(const QImage &img, const QColor& oc) const +{ + QImage *dest = new QImage( img.width(), img.height(), QImage::Format_ARGB32/*_Premultiplied*/ ); +// dest->fill(0); + unsigned int *data = ( unsigned int * ) img.bits(); + unsigned int *destData = ( unsigned int* ) dest->bits(); + int total = img.width() * img.height(); + int red, green, blue; + int current; + oc.getHsv(&red,&green,&blue); // not really ;) green is saturation + current = green/60; + green = CLAMP(green*(1+current)/current,0,255); + QColor c; c.setHsv(red,green,blue); + + int srcR = c.red() - 128; + int srcG = c.green() - 128; + int srcB = c.blue() - 128; + int destR, destG, destB; + + // grain/merge from the gimp. TODO: use mmx/sse here + for ( current = 0 ; current < total ; ++current ) + { + red = srcR + qRed( data[ current ] ); + green = srcG + qGreen( data[ current ] ); + blue = srcB + qBlue( data[ current ] ); + destR = CLAMP(red, 0, 255); + destG = CLAMP(green, 0, 255); + destB = CLAMP(blue, 0, 255); + destData[ current ] = qRgba( destR, destG, destB, qAlpha(data[ current ]) ); + } + QPixmap *pix = new QPixmap(QPixmap::fromImage(*dest, 0)); + delete dest; + return pix; +} + +const Tile::Set &OxygenStyle::glow(const QColor & c, bool round) const +{ + TileCache *cache = const_cast(round ? &roundGlowCache : &glowCache); + TileCache::const_iterator it = cache->find(c.rgb()); + if (it != cache->end()) + return it.value(); + + // need to create a new one + QPixmap *pix; + Tile::Set frame; + + if (round) + { + pix = tint(QImage(":/round-glow"), c); + frame = Tile::Set(*pix,10,10,7,6); + } + else + { + pix = tint(QImage(":/glow"), c); + frame = Tile::Set(*pix,15,12,6,4); + } + + delete pix; + if (cache->size() == cache->capacity()) + cache->clear(); + it = cache->insert(c.rgb(), frame); + return it.value(); +} +/**=========================*/ + +void OxygenStyle::fillWithMask(QPainter *painter, const QPoint &xy, const QBrush &brush, const QPixmap &mask, QPoint offset) const +{ + QPixmap qPix(mask.size()); + if (brush.texture().isNull()) + qPix.fill(brush.color()); + else { + QPainter p(&qPix); + p.drawTiledPixmap(mask.rect(),brush.texture(),offset); + p.end(); + } + qPix = OXRender::applyAlpha(qPix, mask); + painter->drawPixmap(xy, qPix); +} + +void OxygenStyle::fillWithMask(QPainter *painter, const QRect &rect, const QBrush &brush, const Tile::Mask *mask, Tile::PosFlags pf, bool justClip, QPoint offset, bool inverse, const QRect *outerRect) const +{ + // TODO: get rid of this?! - masks now render themselves! + bool pixmode = !brush.texture().isNull(); + if (!mask) { + if (pixmode) + painter->drawTiledPixmap(rect, brush.texture(), offset); + else + painter->fillRect(rect, brush.color()); + return; + } + mask->render(rect, painter, brush, pf, justClip, offset, inverse, outerRect); +} + +/**======================================*/ + +/**QStyle reimplementation ========================================= */ + +void OxygenStyle::polish ( QApplication * app ) { +// if (timer && !timer->isActive()) +// timer->start(50); + loadPixmaps(); + if (app->desktop()) + bgYoffset_ = app->desktop()->height()*bgYoffset_/738; + popupPix = bgPix; + QPalette pal = app->palette(); + polish(pal); + app->setPalette(pal); + if (!_bgBrush && config.bgMode > Dummy) { + if (config.bgMode > FullPix) + _bgBrush = new DynamicBrush((DynamicBrush::Mode)config.bgMode, this); + else { + if (config.acceleration > None) + _bgBrush = new DynamicBrush((DynamicBrush::Mode)config.acceleration, this); + else + _bgBrush = new DynamicBrush(bgPix, bgYoffset_, this); + } + } + app->installEventFilter(this); +} + +#define _SHIFTCOLOR_(clr) clr = QColor(CLAMP(clr.red()-10,0,255),CLAMP(clr.green()-10,0,255),CLAMP(clr.blue()-10,0,255)) + +void OxygenStyle::polish( QPalette &pal ) +{ + if (config.bgMode == Scanlines) { + QColor c = pal.color(QPalette::Active, QPalette::Background); + makeStructure(0, c); + QBrush brush( c, *_scanlines[0] ); + pal.setBrush( QPalette::Background, brush ); + } + else if (config.bgMode != Plain) { + int h,s,v; + QColor c = pal.color(QPalette::Active, QPalette::Background); + c.getHsv(&h,&s,&v); + originalBgColor_ = c; + if (v < 70) // very dark colors won't make nice backgrounds ;) + c.setHsv(h,s,70); + pal.setColor( QPalette::Window, c ); + } + + int highlightGray = qGray(pal.color(QPalette::Active, QPalette::Highlight).rgb()); + pal.setColor(QPalette::Disabled, QPalette::Highlight, QColor(highlightGray,highlightGray,highlightGray)); + + //inactive palette + pal.setColor(QPalette::Inactive, QPalette::WindowText, midColor(pal.color(QPalette::Active, QPalette::Window),pal.color(QPalette::Active, QPalette::WindowText))); + pal.setColor(QPalette::Inactive, QPalette::Text, midColor(pal.color(QPalette::Active, QPalette::Base),pal.color(QPalette::Active, QPalette::Text),1,3)); + pal.setColor(QPalette::Inactive, QPalette::Highlight, midColor(pal.color(QPalette::Active, QPalette::Highlight),pal.color(QPalette::Active, QPalette::HighlightedText),3,1)); + pal.setColor(QPalette::Inactive, QPalette::AlternateBase, midColor(pal.color(QPalette::Active, QPalette::AlternateBase),pal.color(QPalette::Active, QPalette::Base),3,1)); + +// loadPixmaps(); +// if (qApp->desktop()) +// bgYoffset_ = qApp->desktop()->height()*bgYoffset_/738; + + popupPix = bgPix; +} + +#include + +static Atom winTypePopup = XInternAtom(QX11Info::display(), "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); +static Atom winType = XInternAtom(QX11Info::display(), "_NET_WM_WINDOW_TYPE", False); + +void OxygenStyle::polish( QWidget * widget) { + + // installs dynamic brush to all widgets, taking care of a correct bg pixmap size + //TODO maybe we can exclude some more widgets here... (currently only popup menus) + + if (_bgBrush && !( + qobject_cast(widget) || + widget->inherits("QAlphaWidget") || + widget->inherits("QComboBoxListView") || + widget->inherits("QComboBoxPrivateContainer") || + // Kwin stuff =========================== + widget->topLevelWidget()->objectName() == "decoration widget" || + widget->topLevelWidget()->inherits("QDesktopWidget") || + widget->topLevelWidget()->objectName() == "desktop_widget" + )) + widget->installEventFilter(_bgBrush); + +#ifdef MOUSEDEBUG + widget->installEventFilter(this); +#endif + + if (false +// qobject_cast(widget) +// #ifndef QT_NO_COMBOBOX +// || qobject_cast(widget) +// #endif +#ifndef QT_NO_SPINBOX + || qobject_cast(widget) +#endif +// || qobject_cast(widget) + || qobject_cast(widget) + || widget->inherits("QHeaderView") +// || qobject_cast(widget) +#ifndef QT_NO_SPLITTER + || qobject_cast(widget) +#endif +#ifndef QT_NO_TABBAR + || qobject_cast(widget) +#endif + || widget->inherits("QWorkspaceTitleBar") + || widget->inherits("QToolButton") + || widget->inherits("QDockWidget") + || widget->inherits("QToolBar") + || widget->inherits("QToolBarHandle") + || widget->inherits("QDockSeparator") + || widget->inherits("QToolBoxButton") + || widget->inherits("QAbstractSlider") + || widget->inherits("QDockWidgetSeparator") + || widget->inherits("Q3DockWindowResizeHandle") + ) + widget->setAttribute(Qt::WA_Hover); + + if (qobject_cast(widget)) { + if (widget->inherits("QToolBoxButton")) + widget->setForegroundRole ( QPalette::WindowText ); + else { + widget->setBackgroundRole ( config.role_btn[0] ); + widget->setForegroundRole ( config.role_btn[1] ); + widget->installEventFilter(this); + } + } + if (qobject_cast(widget)) { + widget->setBackgroundRole ( QPalette::Base ); + widget->setForegroundRole ( QPalette::Text ); + widget->installEventFilter(this); + } + if (qobject_cast(widget)) { + widget->installEventFilter(this); + if (qobject_cast(widget) && + !(widget->parentWidget() && + widget->parentWidget()->parentWidget() && + widget->parentWidget()->parentWidget()->inherits("QComboBoxListView"))) + widget->setAttribute(Qt::WA_OpaquePaintEvent, false); + } + + if (qobject_cast(widget)) { + widget->setBackgroundRole ( config.role_progress[0] ); + widget->setForegroundRole ( config.role_progress[1] ); + widget->installEventFilter(this); + if (!timer->isActive()) timer->start(50); + connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(progressbarDestroyed(QObject*))); + } + + if (qobject_cast(widget)) { + connect((QTabWidget*)widget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); + connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(tabDestroyed(QObject*))); + } + if (qobject_cast(widget)) { + widget->setBackgroundRole ( config.role_tab[0] ); + widget->setForegroundRole ( config.role_tab[1] ); + widget->installEventFilter(this); + } + + + if (qobject_cast(widget) || qobject_cast(widget) || + widget->inherits("QWorkspaceTitleBar")) + widget->installEventFilter(this); + + if (widget->inherits("QWorkspace")) + connect(this, SIGNAL(MDIPopup(QPoint)), widget, SLOT(_q_popupOperationMenu(QPoint))); + + + if (false // to simplify the #ifdefs +#ifndef QT_NO_MENUBAR + || qobject_cast(widget) +#endif +#ifdef QT3_SUPPORT + || widget->inherits("Q3ToolBar") +#endif +#ifndef QT_NO_TOOLBAR + || qobject_cast(widget) + || (widget && qobject_cast(widget->parent())) +#endif + ) { + widget->setBackgroundRole(QPalette::Window); + if (config.bgMode == Scanlines) { + widget->setAutoFillBackground ( true ); + QPalette pal = widget->palette(); + QColor c = pal.color(QPalette::Active, QPalette::Window); + + if (!_scanlines[1]) + makeStructure(1, c); + QBrush brush( c, *_scanlines[1] ); + pal.setBrush( QPalette::Window, brush ); + widget->setPalette(pal); + } + } + + if (!widget->isWindow()) + if (QFrame *frame = qobject_cast(widget)) { + // kill ugly winblows frames... + if (frame->frameShape() == QFrame::Box || + frame->frameShape() == QFrame::Panel || + frame->frameShape() == QFrame::WinPanel) + frame->setFrameShape(QFrame::StyledPanel); + + // overwrite ugly lines + if (frame->frameShape() == QFrame::HLine || + frame->frameShape() == QFrame::VLine) + widget->installEventFilter(this); + + // toolbox handling - a shame they look that crap by default! + else if (widget->inherits("QToolBox")) { + widget->setBackgroundRole(QPalette::Window); + widget->setForegroundRole(QPalette::WindowText); + if (widget->layout()) { + widget->layout()->setMargin ( 0 ); + widget->layout()->setSpacing ( 0 ); + } + } + + else if (widget->inherits("QListView")) { + // don't do anything as it breaks drag and drop + } +// && !( +// widget->inherits("QComboBoxListView") || +// widget->inherits("QComboBoxPrivateContainer")) + else if (frame->frameShape() == QFrame::StyledPanel) { + if (widget->inherits("QTextEdit") && frame->lineWidth() == 1) + frame->setLineWidth(dpi.$4); + else { + QList vfs = frame->findChildren(); + bool addVF = true; + foreach (VisualFrame* vf, vfs) + if (vf->parent() == frame) addVF = false; + if (addVF) + new VisualFrame(frame, dpi.$4, dpi.$4, dpi.$4, frame->frameShadow() == QFrame::Sunken ? dpi.$2 : dpi.$4); + } + } + } + + if (widget->autoFillBackground() && + // dad + widget->parentWidget() && + ( widget->parentWidget()->objectName() == "qt_scrollarea_viewport" ) && + //grampa + widget->parentWidget()->parentWidget() && + qobject_cast(widget->parentWidget()->parentWidget()) && + // grangrampa + widget->parentWidget()->parentWidget()->parentWidget() && + widget->parentWidget()->parentWidget()->parentWidget()->inherits("QToolBox") + ) { + widget->parentWidget()->setAutoFillBackground(false); + widget->setAutoFillBackground(false); + } + + // swap qmenu colors + if (qobject_cast(widget)) { + // this should tell beryl et. al this is a popup - doesn't work... yet + XChangeProperty(QX11Info::display(), widget->winId(), winType, + XA_CARDINAL, 32, PropModeReplace, (const unsigned char*)&winTypePopup, 1L); + // WARNING: compmgrs like e.g. beryl deny to shadow shaped windows, + // if we cannot find a way to get ARGB menus independent from the app settings, the compmgr must handle the round corners here + widget->installEventFilter(this); // for the round corners + widget->setAutoFillBackground (true); + widget->setBackgroundRole ( config.role_popup[0] ); + widget->setForegroundRole ( config.role_popup[1] ); + if (qGray(widget->palette().color(QPalette::Active, widget->backgroundRole()).rgb()) < 100) { + QFont tmpFont = widget->font(); + tmpFont.setBold(true); + widget->setFont(tmpFont); + } + } + + //======================== + +} + +bool OxygenStyle::eventFilter( QObject *object, QEvent *ev ) { + switch (ev->type()) { + case QEvent::Paint: { + if (QFrame *frame = qobject_cast(object)) { + if (frame->frameShape() == QFrame::HLine || + frame->frameShape() == QFrame::VLine) { + QPainter p(frame); + Orientation3D o3D = (frame->frameShadow() == QFrame::Sunken) ? Sunken: + (frame->frameShadow() == QFrame::Raised) ? Raised : Relief; + shadows.line[frame->frameShape() == QFrame::VLine][o3D].render(frame->rect(), &p); + p.end(); + return true; + } + } + else if (QTabBar *tabBar = qobject_cast(object)) { + if (tabBar->parentWidget() && + qobject_cast(tabBar->parentWidget())) + return false; // no extra tabbar here please... + QPainter p(tabBar); + QStyleOptionTabBarBase opt; + opt.initFrom(tabBar); + drawPrimitive ( PE_FrameTabBarBase, &opt, &p); + p.end(); + } + return false; + } + case QEvent::Resize: { + if (QMenu *menu = qobject_cast(object)) { +/* QPalette::ColorRole role = menu->backgroundRole(); + QColor c = menu->palette().color(QPalette::Active, role); + int size = ((QResizeEvent*)ev)->size().height(); + QBrush brush; + + if (config.glassMenus) { + const QPixmap &glass = gradient(c, size, Qt::Vertical, config.gradient); + brush = QBrush(c, glass); + } + else { + int v = colorValue(c); + if (v < 80) { + int h,s; c.getHsv(&h,&s,&v); v = 80; c.setHsv(h,s,v); + } + QPixmap pix(32,size); + QLinearGradient lg(QPoint(0, 0), QPoint(0, size)); + QColor dark = c.dark(100+3000/v); + lg.setColorAt(0, c); lg.setColorAt(0.2, dark); + lg.setColorAt(0.8, c); + QPainter p(&pix); p.fillRect(pix.rect(), lg); p.end(); + brush = QBrush(c, pix); + } + + QPalette pal = menu->palette(); + pal.setBrush(role, brush); + menu->setPalette(pal); +*/ return false; + } +// QResizeEvent *rev = (QResizeEvent*)ev; +// int w = ((QResizeEvent*)ev)->size().width(), +// h = ((QResizeEvent*)ev)->size().height(); +// QRegion mask(0,0,w,h); +// mask -= masks.popupCorner[0]; // tl +// QRect br = masks.popupCorner[1].boundingRect(); +// mask -= masks.popupCorner[1].translated(w-br.width(), 0); // tr +// br = masks.popupCorner[2].boundingRect(); +// mask -= masks.popupCorner[2].translated(0, h-br.height()); // bl +// br = masks.popupCorner[3].boundingRect(); +// mask -= masks.popupCorner[3].translated(w-br.width(), h-br.height()); // br +// menu->setMask(mask); +// } +// } + return false; + } + case QEvent::MouseButtonPress: { + QMouseEvent *mev = (QMouseEvent*)ev; +#ifdef MOUSEDEBUG + qDebug() << object; +#endif + if (( mev->button() == Qt::LeftButton) && + object->inherits("QWorkspaceTitleBar")) { + //TODO this is a hack to get the popupmenu to the right side. bug TT to query the position with a SH + QWidget *widget = (QWidget*)object; + // check for menu button + QWidget *MDI = qobject_cast(widget->parent()); if (!MDI) return false; //this is elsewhat... + /// this does not work as TT keeps the flag in a private to the titlebar (for no reason?) +// if (!(widget->windowFlags() & Qt::WindowSystemMenuHint)) return false; + // check if we clicked it.. + if (mev->x() < widget->width()-widget->height()-2) return false; + // find popup + MDI = qobject_cast(MDI->parent()); if (!MDI) return false; //this is elsewhat... + MDI = MDI->findChild("qt_internal_mdi_popup"); + if (!MDI) { + qWarning("MDI popup not found, unable to calc menu position"); + return false; + } + // calc menu position + emit MDIPopup(widget->mapToGlobal( QPoint(widget->width() - MDI->sizeHint().width(), widget->height()))); + return true; + } + return false; + } + case QEvent::Show: { + if (qobject_cast(object) && + ((QWidget*)object)->isEnabled()) { + progressbars[(QWidget*)object] = 0; + return false; + } + if (qobject_cast(object)) { + tabwidgets[(QTabWidget*)object] = + new TabAnimInfo((QTabWidget*)object, ((QTabWidget*)object)->currentIndex()); + return false; + } + return false; + } + +#define HANDLE_SCROLL_AREA_EVENT \ + if (area->horizontalScrollBar()->isVisible())\ + fadeIn(area->horizontalScrollBar());\ + if (area->verticalScrollBar()->isVisible())\ + fadeIn(area->verticalScrollBar()); + case QEvent::Enter: + if (qobject_cast(object) || + qobject_cast(object)) { + QWidget *widget = (QWidget*)object; + if (!widget->isEnabled()) + return false; + if (widget->hasFocus()) { + widget->update(); return false; + } + fadeIn(widget); + return false; + } + else if (QAbstractScrollArea* area = + qobject_cast(object)) { + if (!area->isEnabled()) return false; + HANDLE_SCROLL_AREA_EVENT + return false; + } + else if (Q3ScrollView* area = + qobject_cast(object)) { + if (!area->isEnabled()) return false; + HANDLE_SCROLL_AREA_EVENT + return false; + } + return false; + +#undef HANDLE_SCROLL_AREA_EVENT +#define HANDLE_SCROLL_AREA_EVENT \ + if (area->horizontalScrollBar()->isVisible())\ + fadeOut(area->horizontalScrollBar());\ + if (area->verticalScrollBar()->isVisible())\ + fadeOut(area->verticalScrollBar()); + case QEvent::Leave: + if (qobject_cast(object) || + qobject_cast(object)) { + QWidget *widget = (QWidget*)object; + if (!widget->isEnabled()) + return false; + if (widget->hasFocus()) { + widget->update(); return false; + } + fadeOut(widget); + return false; + } + else if (QAbstractScrollArea* area = + qobject_cast(object)) { + if (!area->isEnabled()) return false; + HANDLE_SCROLL_AREA_EVENT + return false; + } + else if (Q3ScrollView* area = + qobject_cast(object)) { + HANDLE_SCROLL_AREA_EVENT + return false; + } + return false; +#undef HANDLE_SCROLL_AREA_EVENT + + case QEvent::FocusIn: + if (qobject_cast(object) || + qobject_cast(object)) { + QWidget *widget = (QWidget*)object; + if (!widget->isEnabled()) return false; + if (widget->testAttribute(Qt::WA_UnderMouse)) + widget->repaint(); + else + fadeIn(widget); + return false; + } + return false; + case QEvent::FocusOut: + if (qobject_cast(object) || + qobject_cast(object)) { + QWidget *widget = (QWidget*)object; + if (!widget->isEnabled()) return false; + if (widget->testAttribute(Qt::WA_UnderMouse)) + widget->repaint(); + else + fadeOut((QWidget*)(object)); + return false; + } + return false; + case QEvent::EnabledChange: + if (qobject_cast(object)) { + if (((QWidget*)object)->isEnabled()) + progressbars[(QWidget*)object] = 0; + else + progressbars.remove((QWidget*)object); + return false; + } + return false; + default: + return false; + } +} + +void OxygenStyle::unPolish( QApplication */*app */) +{ + if (timer) + timer->stop(); +// inExitPolish = true; +// QPalette pal( app->palette() ); +// // rQWidgeteset bg Tileset +// for (int i = QPalette::Disabled; i < QPalette::NColorGroups; i++) +// { +// if ( !pal.brush( (QPalette::ColorGroup)i, QPalette::Background ).texture().isNull() ) +// pal.setBrush( (QPalette::ColorGroup)i, QPalette::Background, originalBgColor_ ); +// if ( !pal.brush( (QPalette::ColorGroup)i, QPalette::Button ).texture().isNull() ) +// pal.setBrush( (QPalette::ColorGroup)i, QPalette::Button, originalBgColor_ ); +// } +// app->setPalette( pal ); +// inExitPolish = false; +} + +void OxygenStyle::unPolish( QWidget *widget ) +{ + if (qobject_cast(widget)) { + widget->removeEventFilter(this); + disconnect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(progressbarDestroyed(QObject*))); + } + if (qobject_cast(widget) || qobject_cast(widget)) + widget->removeEventFilter(this); + if (_bgBrush) + widget->removeEventFilter(this); + if (qobject_cast(widget)) + widget->deleteLater(); +// w->removeEventFilter(this); +// if (w->isTopLevel() || qobject_cast(w) || w->inherits("KActiveLabel")) +// w->setPalette(QPalette()); +} + +QPalette OxygenStyle::standardPalette () const +{ + QPalette pal ( Qt::black, QColor(30,31,32), // windowText, button + Qt::white, QColor(200,201,202), QColor(221,222,223), //light, dark, mid + Qt::black, Qt::white, //text, bright_text + QColor(251,254,255), QColor(234,236,238) ); //base, window + pal.setColor(QPalette::ButtonText, QColor(234,236,238)); + return pal; +} + +/** eventcontrol slots*/ + +void OxygenStyle::fakeMouse() +{ + if (mouseButtonPressed_) // delayed mousepress for move event + { + QCursor::setPos ( cursorPos_ ); + XTestFakeButtonEvent(QX11Info::display(),1, false, 0); + XTestFakeKeyEvent(QX11Info::display(),XKeysymToKeycode(QX11Info::display(), XK_Alt_L), true, 0); + XTestFakeButtonEvent(QX11Info::display(),1, true, 0); + XTestFakeKeyEvent(QX11Info::display(),XKeysymToKeycode(QX11Info::display(), XK_Alt_L), false, 0); + XFlush(QX11Info::display()); + } +} + +// cause of cmake +#include "oxygen.moc" + diff --git a/clients/oxygen/oxygen.h b/clients/oxygen/oxygen.h new file mode 100644 index 0000000000..53571a5f4a --- /dev/null +++ b/clients/oxygen/oxygen.h @@ -0,0 +1,363 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef OXYGEN_STYLE_H +#define OXYGEN_STYLE_H + +class QAbstractButton; +class QHeaderView; +class QMenuBar; +class QPushButton; +class QScrollBar; +class QTabBar; +class DynamicBrush; +class QPaintEvent; +class QFrame; +// class GradientCache; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tileset.h" + +namespace Oxygen { + +enum BGMode { Plain = 0, Scanlines, Dummy, FullPix, VGradient1, HGradient1, VGradient2, HGradient2, Glass }; +enum Acceleration { None = 0, QtGradient, XRender, OpenGL }; +enum TabTransition {Jump = 0, CrossFade, ScanlineBlend, SlideIn, SlideOut, RollIn, RollOut, OpenVertically, CloseVertically, OpenHorizontally, CloseHorizontally }; + +class EventKiller : public QObject +{ + Q_OBJECT +public: + bool eventFilter( QObject *object, QEvent *event); +}; + +class OxygenStyle; + +class HoverFadeInfo { +public: + HoverFadeInfo(int s = 0, bool fI = true) {step = s; fadeIn = fI; } + int step; + bool fadeIn; +}; + +class ComplexHoverFadeInfo { +public: + ComplexHoverFadeInfo() { + activeSubControls = fadingInControls = fadingOutControls = QStyle::SC_None; + } + QStyle::SubControls activeSubControls, fadingInControls, fadingOutControls; + QHash steps; +}; + +class IndexedFadeInfo { +public: + IndexedFadeInfo(long int index) { this->index = index; } + long int index; + QHash fadingInIndices, fadingOutIndices; + int step(long int index); +}; + +class TabAnimInfo : public QObject { + Q_OBJECT +public: + TabAnimInfo(QObject *parent = 0, int currentTab = -1) : + QObject(parent), lastTab(currentTab), animStep(0){} +protected: + bool eventFilter( QObject* object, QEvent* event ); +public: + QList < QWidget* > autofillingWidgets; + int lastTab, animStep; + QPixmap tabPix[3]; +}; + +enum Orientation3D {Sunken = 0, Relief, Raised}; +enum GradientType { + GradSimple = 0, + GradSunken, + GradGloss, + GradGlass, + GradRadialGloss, + GradButton, + NumGrads +}; + +typedef struct { + int $1, $2, $3, $4, $5, $6, $7, $8, $9, $10; + int $12, $13, $16, $32, $18, $20, $80; + int ScrollBarExtent; + int ScrollBarSliderMin; + int SliderThickness; + int SliderControl; + int Indicator; + int ExclusiveIndicator; +} Dpi; + +typedef struct Config { + GradientType gradient, gradBtn, gradientStrong; + BGMode bgMode; + Acceleration acceleration; + int structure; + TabTransition tabTransition; + int gradientIntensity; + bool aqua, showMenuIcons, glassProgress, glassMenus, menuShadow; + double scale; + int checkType; + QPalette::ColorRole role_progress[2], role_tab[2], + role_btn[2], role_btnHover[2], role_popup[2]; +} Config; + +class VisualFrame : public QWidget { + Q_OBJECT +public: + VisualFrame(QFrame *parent, int top = 0, int left = 0, int right = 0, int bottom = 0); + bool eventFilter ( QObject * o, QEvent * ev ); + void paintEvent ( QPaintEvent * event ); +protected: +// void dragEnterEvent ( QDragEnterEvent * event ) { passDownEvent(event, event->globalPos()); } +// void dragLeaveEvent ( QDragLeaveEvent * event ) { passDownEvent(event, event->globalPos()); } +// void dragMoveEvent ( QDragMoveEvent * event ) { passDownEvent(event, event->globalPos()); } +// void dropEvent ( QDropEvent * event ) { passDownEvent(event, event->globalPos()); } +// void enterEvent ( QEvent * event ) { passDownEvent(event, event->globalPos()); } +// void leaveEvent ( QEvent * event ) { passDownEvent(event, event->globalPos()); } + void mouseDoubleClickEvent ( QMouseEvent * event ); + void mouseMoveEvent ( QMouseEvent * event ); + void mousePressEvent ( QMouseEvent * event ); + void mouseReleaseEvent ( QMouseEvent * event ); + void wheelEvent ( QWheelEvent * event ); +private: + void passDownEvent(QEvent *ev, const QPoint &gMousePos); + int off[4]; +}; + +class OxygenStyle : public QCommonStyle { + Q_OBJECT +public: + enum WidgetState{Basic = 0, Hovered, Focused, Active}; + + OxygenStyle(); + ~OxygenStyle(); + + //inheritance from QStyle + void drawComplexControl ( ComplexControl control, + const QStyleOptionComplex * option, + QPainter * painter, + const QWidget * widget = 0 ) const; + + void drawControl ( ControlElement element, + const QStyleOption * option, + QPainter * painter, + const QWidget * widget = 0 ) const; + + /**what do they do? + virtual void drawItemPixmap ( QPainter * painter, const QRect & rect, int alignment, const QPixmap & pixmap ) const; + virtual void drawItemText ( QPainter * painter, const QRect & rect, int alignment, const QPalette & pal, bool enabled, const QString & text, QPalette::ColorRole textRole = QPalette::NoRole ) const; + */ + + void drawPrimitive ( PrimitiveElement elem, + const QStyleOption * option, + QPainter * painter, + const QWidget * widget = 0 ) const; + + QPixmap standardPixmap ( StandardPixmap standardPixmap, + const QStyleOption * option = 0, + const QWidget * widget = 0 ) const; + +// what do they do? ======================================== +// QPixmap generatedIconPixmap ( QIcon::Mode iconMode, +// const QPixmap & pixmap, +// const QStyleOption * option ) const; +// SubControl hitTestComplexControl ( ComplexControl control, +// const QStyleOptionComplex * option, +// const QPoint & pos, +// const QWidget * widget = 0 ) const; +// QRect itemPixmapRect ( const QRect & rect, +// int alignment, +// const QPixmap & pixmap ) const; +// QRect itemTextRect ( const QFontMetrics & metrics, +// const QRect & rect, +// int alignment, +// bool enabled, +// const QString & text ) const; +//============================================================= + + int pixelMetric ( PixelMetric metric, + const QStyleOption * option = 0, + const QWidget * widget = 0 ) const; + + void polish( QWidget *w ); + void polish( QApplication * ); + void polish( QPalette &pal ); + + QSize sizeFromContents ( ContentsType type, + const QStyleOption * option, + const QSize & contentsSize, + const QWidget * widget = 0 ) const; + + int styleHint ( StyleHint hint, + const QStyleOption * option = 0, + const QWidget * widget = 0, + QStyleHintReturn * returnData = 0 ) const; + + QRect subControlRect ( ComplexControl control, + const QStyleOptionComplex * option, + SubControl subControl, + const QWidget * widget = 0 ) const; + + QRect subElementRect ( SubElement element, + const QStyleOption * option, + const QWidget * widget = 0 ) const; + + QPalette standardPalette () const; + + void unPolish( QWidget *w ); + void unPolish( QApplication *a ); + + // from QObject + bool eventFilter( QObject *object, QEvent *event ); + +signals: + void MDIPopup(QPoint); + +private slots: + void fakeMouse(); + void handleIPC(int, int); + + // animation slots ============================ + void progressbarDestroyed(QObject*); + void updateProgressbars(); + + void tabChanged(int index); + void updateTabAnimation(); + void tabDestroyed(QObject* obj); + + void updateFades(); + void fadeDestroyed(QObject* obj); + + void updateComplexFades(); + void complexFadeDestroyed(QObject* obj); + + void updateIndexedFades(); + void indexedFadeDestroyed(QObject* obj); + + //========================================= + +private: + OxygenStyle( const OxygenStyle & ); + OxygenStyle& operator=( const OxygenStyle & ); + const QPixmap &gradient(const QColor &c, + int size, + Qt::Orientation o, + GradientType type = GradSimple) const; + const QPixmap &btnAmbient(int height) const; + const QPixmap &tabShadow(int height, bool bottom = false) const; + const QPixmap &groupLight(int height) const; + + void fillWithMask(QPainter *painter, + const QRect &rect, + const QBrush &brush, + const Tile::Mask *mask, + Tile::PosFlags pf = Tile::Full, + bool justClip = false, + QPoint offset = QPoint(), + bool inverse = false, + const QRect *outerRect = 0L) const; + void fillWithMask(QPainter *painter, + const QPoint &xy, + const QBrush &brush, + const QPixmap &mask, + QPoint offset = QPoint()) const; + + QColor mapFadeColor(const QColor &color, int index) const; + void fadeIn(QWidget *widget); + void fadeOut(QWidget *widget ); + QPixmap *tint(const QImage &img, const QColor& c) const; + const Tile::Set &glow(const QColor & c, bool round = false) const; + void readSettings(); + void generatePixmaps(); + void initMetrics(); + void makeStructure(int num, const QColor &c); + int hoverStep(const QWidget *widget) const; + const ComplexHoverFadeInfo *complexHoverFadeInfo(const QWidget *widget, + SubControls activeSubControls) const; + const IndexedFadeInfo *indexedFadeInfo(const QWidget *widget, long int index) const; + int progressStep(const QWidget *w) const; + +private: + typedef QHash HoverFades; + typedef QCache PixmapCache; + typedef QHash TileCache; + struct { + Tile::Mask /*rect[3], round[3], */button, tab/*, group*/; + QPixmap radio, radioIndicator, radioGroove, notch, slider[4]; + QPixmap winClose, winMin, winMax; + QRegion popupCorner[4]; + } masks; + struct { + Tile::Set button[2][8], tab, sunken, group, lineEdit[2], raised, relief; + QPixmap radio[2][2]; + QPixmap winClose[2], winMin[2], winMax[2]; + Tile::Line line[2][3]; + QPixmap slider[4][2][2]; + } shadows; + struct { + Tile::Set rect[3], round[3], button[2]; + } frames; + struct { + Tile::Line top; + QPixmap slider[4]; + Tile::Mask button; + } lights; + + // pixmaps + QPixmap *_scanlines[2]; + // cache +// GradientCache *gradients[2][NumGrads]; + PixmapCache gradients[2][NumGrads]; + PixmapCache _btnAmbient, _tabShadow, _groupLight; + TileCache glowCache; + TileCache roundGlowCache; + + + //anmiated progressbars + bool animationUpdate; + int complexStep; + +// QPalette tooltipPalette; + + // toolbar title functionality ======================== + QPoint cursorPos_; + bool mouseButtonPressed_; + bool internalEvent_; + // =========================== + DynamicBrush *_bgBrush; + Pixmap popupPix; + QTimer* timer; +}; + +} // namespace Oxygen +#endif //OXYGEN_STYLE_H diff --git a/clients/oxygen/oxygen.pro b/clients/oxygen/oxygen.pro new file mode 100644 index 0000000000..d512e864d6 --- /dev/null +++ b/clients/oxygen/oxygen.pro @@ -0,0 +1,13 @@ +HEADERS = oxrender.h oxygen.h dynamicbrush.h \ + tileset.h debug.h +SOURCES = oxrender.cpp oxygen.cpp tileset.cpp stylehint.cpp \ + sizefromcontents.cpp qsubcmetrics.cpp \ + pixelmetric.cpp stdpix.cpp \ + drawcomplexcontrol.cpp drawcontrol.cpp \ + drawprimitive.cpp dynamicbrush.cpp +TEMPLATE = lib +PLUGIN = true +RESOURCES = oxygen.qrc +CONFIG += qt x11 plugin +QT += qt3support opengl +VERSION = 0.1 diff --git a/clients/oxygen/oxygen.qrc b/clients/oxygen/oxygen.qrc new file mode 100644 index 0000000000..e5d08ce2a3 --- /dev/null +++ b/clients/oxygen/oxygen.qrc @@ -0,0 +1,7 @@ + + +../imagebase/leftCenter.png +../imagebase/leftTile.png +../imagebase/glow.png + + \ No newline at end of file diff --git a/clients/oxygen/oxygen.themerc b/clients/oxygen/oxygen.themerc new file mode 100644 index 0000000000..1fcdcd35ef --- /dev/null +++ b/clients/oxygen/oxygen.themerc @@ -0,0 +1,22 @@ +[Misc] +Name=Oxygen +Name[vi]=Oxy +Name[xx]=xxOxygenxx +ConfigPage=kstyle-oxygen-config +Comment=A really cool style +Comment[be]=Сапраўды круты стыль +Comment[bg]=Наистина супер стил +Comment[br]=Ur giz kool a-walc'h +Comment[de]=Ein wirklich frischer Stil +Comment[el]=Ένα πολύ όμορφο στυλ +Comment[es]=Un estilo realmente bueno +Comment[et]=Tõeliselt lahe stiil +Comment[it]=Uno stile veramente carino +Comment[nl]=Een erg gave stijl +Comment[pt]=Um estilo realmente giro +Comment[pt_BR]=Um estilo realmente giro +Comment[sv]=En verkligt häftig stil +Comment[tr]=Basit ve temiz bir stil +Comment[xx]=xxA really cool stylexx +[KDE] +WidgetStyle=Oxygen diff --git a/clients/oxygen/pixelmetric.cpp b/clients/oxygen/pixelmetric.cpp new file mode 100644 index 0000000000..9acd7cecd9 --- /dev/null +++ b/clients/oxygen/pixelmetric.cpp @@ -0,0 +1,203 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "oxygen.h" + +#include + +using namespace Oxygen; + +extern Dpi dpi; + +int OxygenStyle::pixelMetric ( PixelMetric pm, const QStyleOption * option, const QWidget * widget ) const +{ +#if 1 + switch ( pm ) + { + case PM_ButtonMargin: // Amount of whitespace between push button labels and the frame + return dpi.$4; + case PM_ButtonDefaultIndicator: // Width of the default-button indicator frame + return dpi.$2; + case PM_MenuButtonIndicator: // Width of the menu button indicator proportional to the widget height + return dpi.$7; + case PM_ButtonShiftHorizontal: // Horizontal contents shift of a button when the button is down + case PM_ButtonShiftVertical: // Vertical contents shift of a button when the button is down + return 0; + case PM_DefaultFrameWidth: // Default frame width (usually 2) + if (widget && widget->inherits("QComboBoxPrivateContainer")) + return 1; + if (widget && qobject_cast(widget) && + static_cast(widget)->frameShape() == QFrame::StyledPanel && + !widget->inherits("QTextEdit")) + return dpi.$1; +#warning stupid idea? + return dpi.$1; + case PM_SpinBoxFrameWidth: // Frame width of a spin box, defaults to PM_DefaultFrameWidth + return dpi.$1; + case PM_ComboBoxFrameWidth: // Frame width of a combo box, defaults to PM_DefaultFrameWidth. + return dpi.$2; +// case PM_MDIFrameWidth: // Frame width of an MDI window +// case PM_MDIMinimizedWidth: // Width of a minimized MDI window + case PM_MaximumDragDistance: // Some feels require the scroll bar or other sliders to jump back to the original position when the mouse pointer is too far away while dragging; a value of -1 disables this behavior + return -1; + case PM_ScrollBarExtent: // Width of a vertical scroll bar and the height of a horizontal scroll bar + return (widget && widget->parentWidget() && + widget->parentWidget()->parentWidget() && + widget->parentWidget()->parentWidget()->inherits("QComboBoxListView")) ? + dpi.$16 : dpi.ScrollBarExtent; + case PM_ScrollBarSliderMin: // The minimum height of a vertical scroll bar's slider and the minimum width of a horizontal scroll bar's slider + return dpi.ScrollBarSliderMin; + case PM_SliderThickness: // Total slider thickness + return dpi.SliderThickness; + case PM_SliderControlThickness: // Thickness of the slider handle + case PM_SliderLength: // Length of the slider + return dpi.SliderControl; +// case PM_SliderTickmarkOffset: // The offset between the tickmarks and the slider + case PM_SliderSpaceAvailable: { // The available space for the slider to move + if (!widget) + return 0; + if ( const QSlider *slider = qobject_cast(widget)) + if (slider->orientation() == Qt::Horizontal) + return (widget->width() - dpi.SliderControl); + else + return (widget->height() - dpi.SliderControl); + } + case PM_DockWidgetSeparatorExtent: // Width of a separator in a horizontal dock window and the height of a separator in a vertical dock window + return dpi.$10; + case PM_DockWidgetHandleExtent: // Width of the handle in a horizontal dock window and the height of the handle in a vertical dock window + return dpi.$6; + case PM_DockWidgetFrameWidth: // Frame width of a dock window + return dpi.$1; + case PM_MenuBarPanelWidth: // Frame width of a menubar, defaults to PM_DefaultFrameWidth + return 0; + case PM_MenuBarItemSpacing: // Spacing between menubar items + return dpi.$6; + case PM_MenuBarHMargin: // Spacing between menubar items and left/right of bar + return dpi.$6; + case PM_MenuBarVMargin: // Spacing between menubar items and top/bottom of bar + return 0; + case PM_ToolBarFrameWidth: // Width of the frame around toolbars + return dpi.$4; + case PM_ToolBarHandleExtent: // Width of a toolbar handle in a horizontal toolbar and the height of the handle in a vertical toolbar + return dpi.$6; + case PM_ToolBarItemMargin: // Spacing between the toolbar frame and the items + return dpi.$4; + case PM_ToolBarItemSpacing: // Spacing between toolbar items + return 0; + case PM_ToolBarSeparatorExtent: // Width of a toolbar separator in a horizontal toolbar and the height of a separator in a vertical toolbar + return dpi.$2; + case PM_ToolBarExtensionExtent: // Width of a toolbar extension button in a horizontal toolbar and the height of the button in a vertical toolbar + return dpi.$16; + case PM_TabBarTabOverlap: // Number of pixels the tabs should overlap + return 0; + case PM_TabBarTabHSpace: // Extra space added to the tab width + return dpi.$12; + case PM_TabBarTabVSpace: // Extra space added to the tab height + return dpi.$10; + case PM_TabBarBaseHeight: // Height of the area between the tab bar and the tab pages + case PM_TabBarBaseOverlap: { // Number of pixels the tab bar overlaps the tab bar base + if (!widget) + return dpi.$16; + const QTabBar *tabBar = qobject_cast(widget); + if (qobject_cast(widget) && + !widget->children().isEmpty()) { + foreach(QObject *obj, widget->children()) { + if (qobject_cast(obj)) { + tabBar = (QTabBar*)obj; + break; + } + } + } + if (!tabBar || !tabBar->isVisible()) + return dpi.$16; + if (const QStyleOptionTabWidgetFrame *twf = + qstyleoption_cast(option)) { + if (twf->shape == QTabBar::RoundedEast || + twf->shape == QTabBar::TriangularEast || + twf->shape == QTabBar::RoundedWest || + twf->shape == QTabBar::TriangularWest) + return tabBar->width(); + } + return tabBar->height(); + } + case PM_TabBarScrollButtonWidth: // + return dpi.$16; + case PM_TabBarTabShiftHorizontal: // Horizontal pixel shift when a tab is selected + return 0; + case PM_TabBarTabShiftVertical: // Vertical pixel shift when a tab is selected + return dpi.$2; +// case PM_ProgressBarChunkWidth: // Width of a chunk in a progress bar indicator + case PM_SplitterWidth: // Width of a splitter + return dpi.$9; + case PM_TitleBarHeight: // Height of the title bar + return dpi.ExclusiveIndicator; + case PM_IndicatorWidth: // Width of a check box indicator + case PM_IndicatorHeight: // Height of a checkbox indicator + return dpi.Indicator; + case PM_ExclusiveIndicatorWidth: // Width of a radio button indicator + case PM_ExclusiveIndicatorHeight: // Height of a radio button indicator + return dpi.ExclusiveIndicator; + case PM_MenuPanelWidth: // Border width (applied on all sides) for a QMenu + return dpi.$3; + case PM_MenuHMargin: // Additional border (used on left and right) for a QMenu + return 0; //dpi.$2; + case PM_MenuVMargin: // Additional border (used for bottom and top) for a QMenu + return 0; //dpi.$1; +// case PM_MenuScrollerHeight: // Height of the scroller area in a QMenu +// case PM_MenuTearoffHeight: // Height of a tear off area in a QMenu +// case PM_MenuDesktopFrameWidth: // +// case PM_CheckListButtonSize: // Area (width/height) of the checkbox/radio button in a Q3CheckListItem +// case PM_CheckListControllerSize: // Area (width/height) of the controller in a Q3CheckListItem +// case PM_DialogButtonsSeparator: // Distance between buttons in a dialog buttons widget +// case PM_DialogButtonsButtonWidth: // Minimum width of a button in a dialog buttons widget +// case PM_DialogButtonsButtonHeight: // Minimum height of a button in a dialog buttons widget +// case PM_HeaderMarkSize: // +// case PM_HeaderGripMargin: // + case PM_HeaderMargin: // + return dpi.$2; + case PM_SpinBoxSliderHeight: // The height of the optional spin box slider + return dpi.$4; +// case PM_DefaultTopLevelMargin: // +// case PM_DefaultChildMargin: // +// case PM_DefaultLayoutSpacing: // + case PM_ToolBarIconSize: // Default tool bar icon size, defaults to PM_SmallIconSize + return 32; + case PM_SmallIconSize: // Default small icon size + return 22; + case PM_LargeIconSize: // Default large icon size + return 32; + case PM_FocusFrameHMargin: // Horizontal margin that the focus frame will outset the widget by. + return dpi.$4; + case PM_FocusFrameVMargin: // Vertical margin that the focus frame will outset the widget by. + return dpi.$2; +// case PM_IconViewIconSize: // +// case PM_ListViewIconSize: // +// case PM_ToolTipLabelFrameWidth: // + default: +#endif + return QCommonStyle::pixelMetric( pm, option, widget ); + } // switch +} diff --git a/clients/oxygen/qrc_oxygen.cpp b/clients/oxygen/qrc_oxygen.cpp new file mode 100644 index 0000000000..619e586967 --- /dev/null +++ b/clients/oxygen/qrc_oxygen.cpp @@ -0,0 +1,1213 @@ +/**************************************************************************** +** Resource object code +** +** Created: Mon May 7 23:06:01 2007 +** by: The Resource Compiler for Qt version 4.3.0-snapshot-20070423 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // /usr/src/svn/Oxygen/style/imagebase/glow.png + 0x0,0x0,0x3,0xe8, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x24,0x0,0x0,0x0,0x1c,0x8,0x6,0x0,0x0,0x0,0x9,0x29,0x1d,0x58, + 0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd, + 0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0, + 0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7, + 0xd6,0x4,0x4,0xd,0x38,0x4,0x6a,0x7b,0x8f,0xb4,0x0,0x0,0x3,0x75,0x49,0x44, + 0x41,0x54,0x48,0xc7,0xed,0x97,0xc1,0x6e,0x1c,0x47,0xc,0x44,0xab,0x8a,0x3d,0xb3, + 0x2b,0xaf,0x6c,0x39,0x6,0x2,0x38,0x40,0xce,0xb9,0xe6,0x7f,0xfc,0xb,0xf9,0x9e, + 0xfc,0x82,0x4f,0xf6,0x6f,0x5,0x9,0x92,0xc8,0xb2,0xa4,0xd5,0xae,0x66,0x9b,0xac, + 0x1c,0xd2,0x23,0x38,0xb9,0xe4,0xb6,0xf2,0x21,0x4,0x6,0xc4,0x9c,0xf8,0x86,0xc3, + 0x66,0x57,0xf1,0xe3,0xc7,0x8f,0xdb,0xc3,0xe1,0x10,0x97,0x97,0x97,0x13,0x0,0xf6, + 0xde,0xc3,0xf6,0x44,0x52,0x11,0x11,0xbd,0x77,0x1,0x8,0x92,0x2,0x40,0x0,0xaa, + 0x2a,0x2,0x60,0x44,0xc8,0x36,0xf1,0x45,0x90,0x74,0x66,0x16,0x0,0x4b,0x32,0x80, + 0x2,0x60,0xdb,0x5,0x20,0x5b,0x6b,0x95,0x99,0x39,0xde,0xfb,0x34,0x4d,0x1d,0x40, + 0x7f,0x78,0x78,0xa8,0xd6,0x5a,0x36,0x92,0x17,0xdb,0xed,0x76,0xee,0xbd,0x6f,0xaa, + 0x6a,0xb,0x60,0x3,0x60,0x67,0x7b,0xaa,0xaa,0xd9,0xf6,0x2c,0xa9,0x65,0x66,0x93, + 0xd4,0xaa,0xaa,0x1,0x8,0x0,0x91,0x99,0x31,0x20,0x51,0x55,0x1c,0x0,0xb6,0x9d, + 0x0,0x32,0x33,0x53,0x52,0xaf,0xaa,0xbe,0xe6,0xd3,0xe9,0xb4,0x0,0x58,0x0,0x9c, + 0x0,0xec,0x97,0x65,0x59,0x5a,0x6b,0xc7,0xed,0x76,0xfb,0x8,0x60,0x69,0x0,0x2e, + 0x1,0xec,0x46,0xbe,0xb2,0x7d,0x49,0xf2,0xd,0x80,0x17,0xb6,0x77,0x55,0x75,0x1, + 0x60,0x9b,0x99,0xdb,0xcc,0xdc,0x4a,0x9a,0x6d,0xcf,0x0,0x26,0x0,0x2b,0x1c,0x6c, + 0xd3,0xb6,0x1,0x24,0x80,0xe,0xe0,0x44,0x72,0x19,0x0,0x47,0x0,0xc7,0xaa,0x3a, + 0x4a,0x3a,0x90,0xdc,0x3,0x78,0xb0,0xfd,0x89,0xe4,0x7d,0xef,0xfd,0x56,0xd2,0xbd, + 0xed,0x7d,0xeb,0xbd,0x5f,0x91,0x7c,0xd,0xe0,0xd,0x80,0xb7,0x0,0x5e,0x57,0xd5, + 0xf7,0x55,0xf5,0xda,0xf6,0x15,0xc9,0x57,0xbd,0xf7,0x97,0xb6,0x2f,0xab,0x6a,0x63, + 0x7b,0x3,0x60,0xb2,0x1d,0x0,0xd6,0xdf,0x88,0x91,0x3d,0x9e,0x22,0x99,0x3,0xea, + 0x51,0xd2,0xa3,0xed,0x7b,0x92,0x77,0xbd,0xf7,0x5b,0x92,0x9f,0x25,0xdd,0x0,0xf8, + 0x85,0xe4,0xd,0xc9,0xdf,0xaa,0xea,0x1a,0xc0,0xdc,0x5a,0x6b,0x77,0x99,0xf9,0xc6, + 0xf6,0xdb,0xde,0xfb,0x8f,0xef,0xde,0xbd,0xfb,0x9,0x67,0x8c,0xf7,0xef,0xdf,0xff, + 0xdc,0x5a,0x2b,0x92,0x7f,0x46,0xc4,0x27,0xf5,0xde,0x3,0xc0,0xc,0x60,0x37,0x3a, + 0x75,0xd6,0x18,0x35,0x77,0x0,0xe6,0xde,0x7b,0x34,0x92,0x51,0x55,0x73,0x55,0xed, + 0xaa,0xea,0xea,0xdc,0x40,0xa3,0xe6,0x4e,0xd2,0x2c,0x29,0x34,0x66,0x61,0x2,0xb0, + 0x25,0x79,0xf9,0xc,0x1d,0xba,0x4,0xb0,0x5d,0xe7,0x52,0x92,0x34,0x4e,0xcb,0x9c, + 0x99,0x2f,0xce,0xd,0x34,0x6a,0xce,0x0,0xda,0xa,0x43,0x49,0xcd,0xf6,0x34,0x76, + 0xd0,0xb9,0x63,0x63,0x7b,0x92,0xd4,0x0,0x50,0x55,0xc5,0xb1,0xd4,0x56,0xa8,0xb3, + 0xc6,0xa,0xf3,0xc4,0x81,0xaf,0x2c,0xfe,0x7,0xfa,0x4f,0x20,0x49,0x24,0xa9,0x71, + 0x69,0x4e,0xcf,0xc0,0x30,0x55,0x55,0x23,0x29,0x49,0x5f,0xe1,0xc,0x55,0x95,0x6d, + 0x97,0xa4,0x3e,0x24,0xc1,0xb9,0xe3,0x24,0xa9,0xdb,0xae,0xaa,0xb2,0x24,0x59,0x92, + 0xab,0xaa,0x93,0x3c,0x3b,0x10,0xc9,0xd3,0xd0,0x4b,0x96,0x64,0x1,0xf8,0x12,0xe6, + 0xf1,0x19,0x3a,0xf4,0xb8,0x42,0x1,0xb0,0xaa,0xaa,0x86,0xa0,0x5a,0x22,0xe2,0xe1, + 0xdc,0x34,0xa3,0xe6,0x2,0xa0,0x57,0x55,0x69,0x15,0x52,0x0,0x8e,0xb6,0xef,0x9f, + 0x61,0x53,0xdf,0xf,0x45,0x79,0x22,0x99,0xcd,0x76,0x4a,0x5a,0x86,0xac,0xfc,0xfc, + 0xc,0x7b,0xe7,0x73,0x44,0xec,0x49,0x2e,0xb6,0x53,0xad,0xb5,0x1c,0x2d,0xdb,0xdb, + 0xbe,0x79,0x86,0xe,0xdd,0x0,0xd8,0x3,0x58,0x5a,0x6b,0x29,0x0,0x49,0xf2,0x8, + 0x60,0x1f,0x11,0xd7,0xcf,0x30,0x43,0xd7,0x0,0xf6,0x83,0x21,0xf9,0xe1,0xc3,0x87, + 0x1f,0x86,0x6a,0xfb,0x6,0xc0,0xb7,0x0,0x5e,0xd9,0xfe,0x2e,0x33,0x5f,0x1,0x78, + 0x49,0xf2,0x65,0x66,0xee,0x24,0xed,0x32,0xf3,0x82,0xe4,0x45,0x55,0x6d,0x24,0x4d, + 0x99,0xd9,0xbe,0xb8,0x7e,0x56,0x91,0x5f,0x11,0xd1,0xab,0xea,0x34,0xc4,0xfd,0x21, + 0x22,0xe,0x55,0xb5,0x8f,0x88,0xbd,0xed,0x3b,0x0,0x77,0x11,0x71,0x4b,0xf2,0x57, + 0xdb,0x77,0x92,0x7e,0xb7,0x7d,0x23,0xe9,0xb6,0x1,0xb8,0x97,0x94,0x0,0x96,0xde, + 0xfb,0x41,0xd2,0x85,0xa4,0xeb,0x61,0x83,0x2e,0x48,0x6e,0x25,0x6d,0xab,0x6a,0x33, + 0xcf,0xf3,0x5c,0x55,0xb3,0xa4,0x9,0xc0,0x24,0xa9,0xd,0x4d,0x5,0xdb,0x24,0xe9, + 0xf5,0xd4,0x4a,0x3a,0x91,0x3c,0x49,0x5a,0xaa,0x6a,0x99,0xa6,0xe9,0x71,0x1c,0x9c, + 0x23,0xc9,0x83,0xa4,0x87,0x1,0x71,0xb0,0x7d,0xdb,0x5a,0xdb,0x93,0x3c,0xb4,0xde, + 0xfb,0x9e,0xe4,0x12,0x11,0xc7,0xd6,0xda,0x3d,0xc9,0xb9,0xf7,0xfe,0x87,0xa4,0xd5, + 0xee,0x34,0x92,0x4f,0x1e,0xac,0xb5,0xd6,0xaa,0x2a,0x24,0x85,0xed,0x27,0x1b,0xb4, + 0x2,0x49,0x32,0xc9,0xaa,0xaa,0x94,0x94,0x63,0xe9,0xe5,0xd8,0xc6,0xa7,0xf5,0x46, + 0xa8,0xaa,0xc7,0x88,0x38,0xe,0xe0,0x23,0x80,0x85,0xe4,0xd2,0x6c,0x1f,0x5b,0x6b, + 0xa7,0xf1,0x5,0xf,0xc3,0x3a,0xff,0xc3,0x4a,0xaf,0x1e,0x2c,0x22,0xb8,0xe6,0xd5, + 0x4e,0x4b,0xe2,0xbf,0x44,0xbb,0x6d,0x3b,0x22,0xc,0xc0,0x11,0x51,0x7f,0x3b,0x67, + 0x17,0xc9,0x27,0x2b,0x3d,0x2c,0x76,0x8f,0x88,0x8c,0x88,0xbe,0xdf,0xef,0x6b,0xb3, + 0xd9,0xe4,0x5f,0xe3,0xac,0x74,0x2d,0x23,0x99,0x32,0x16,0x0,0x0,0x0,0x0,0x49, + 0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // /usr/src/svn/Oxygen/style/imagebase/leftCenter.png + 0x0,0x0,0x2f,0x60, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x2,0x0,0x0,0x0,0x0,0x20,0x8,0x2,0x0,0x0,0x0,0xeb,0x29,0x57,0xb2, + 0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13, + 0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd7,0x1, + 0xd,0x14,0x26,0x34,0xf5,0xa0,0xb,0x67,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74, + 0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20, + 0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x20, + 0x0,0x49,0x44,0x41,0x54,0x78,0xda,0x7d,0x5d,0xed,0x92,0xe5,0x4a,0xd,0xb3,0x3c, + 0xf,0xc,0xef,0x5f,0x35,0x16,0x3f,0xfc,0x25,0x77,0x66,0x1,0xa,0x96,0xbd,0x33, + 0x39,0x39,0x49,0xb7,0xdb,0x96,0x64,0x19,0xff,0xfd,0xcf,0x7f,0xcc,0xcc,0xc,0x34, + 0x33,0x23,0x0,0x92,0x66,0x6,0x98,0x11,0x84,0xc1,0x48,0x83,0x91,0x80,0x99,0xc1, + 0xcc,0x2c,0xff,0xc6,0xcc,0x68,0x26,0xff,0x3,0x33,0xd6,0x7f,0xc3,0x40,0xcb,0xdf, + 0x98,0xbf,0x44,0xfe,0x23,0xc2,0x40,0x5a,0xff,0x0,0xd9,0xbf,0x6b,0x86,0xfc,0xc0, + 0xbe,0x81,0xf3,0xdb,0x66,0xf3,0x21,0xf2,0x7f,0xc8,0xfe,0x33,0xa0,0x3f,0x83,0xbe, + 0x2a,0x69,0xfb,0x21,0xf5,0x81,0xe8,0xbb,0xa9,0xf,0x32,0xf4,0x55,0xf3,0x7f,0x58, + 0x37,0x63,0x94,0x87,0x32,0x1f,0xe,0x5a,0xf4,0x2f,0xd0,0xcd,0xd9,0xbf,0x58,0x9f, + 0xd0,0xb7,0x87,0xfe,0x4e,0x66,0x7b,0x6b,0x84,0x19,0xd9,0x9f,0x68,0x75,0x6f,0x79, + 0xef,0xa4,0xb9,0x59,0x98,0xc1,0xf2,0x2d,0xa0,0xef,0x59,0x1e,0x2c,0xf7,0x1b,0x92, + 0x79,0x19,0xd2,0xf2,0x6,0x61,0x6,0x20,0x62,0x9e,0xc3,0x3c,0x1a,0x79,0x75,0xf9, + 0xf6,0xee,0x7b,0x91,0xef,0x36,0x77,0x33,0x37,0xc,0xe4,0xcf,0x3b,0x2c,0xcc,0x7c, + 0xff,0x61,0xdd,0x15,0xfa,0x82,0xf5,0x83,0x44,0x7d,0x67,0x33,0xaf,0xef,0x19,0x24, + 0xea,0xb1,0x12,0xf0,0xbc,0x7,0x7d,0xa9,0x66,0xe6,0xf0,0x60,0x78,0x3e,0x69,0x0, + 0xb5,0x50,0xea,0x23,0x7a,0xbd,0xd8,0xe7,0x3a,0xf5,0xc9,0x41,0xc2,0xdc,0xe4,0x47, + 0xfa,0x3e,0xb0,0x6b,0x94,0x74,0x77,0x92,0xfd,0xc2,0x50,0x77,0xcd,0x7d,0xde,0xb5, + 0xea,0xe1,0x30,0x8b,0x88,0xbe,0x5,0x33,0x33,0x77,0x9f,0x47,0x37,0x8f,0xe0,0xbc, + 0x6b,0x5d,0x8,0x36,0x4f,0x67,0x6f,0x21,0x82,0xee,0xc8,0xcd,0x23,0x2f,0xad,0x96, + 0x41,0xad,0x53,0xcc,0x97,0xea,0x17,0xbe,0x2f,0x8,0x64,0xa0,0xef,0x58,0xde,0x67, + 0xaf,0x8a,0x7c,0x26,0x78,0xf7,0x4c,0xde,0x36,0x1c,0x16,0x6,0x60,0xff,0x59,0xef, + 0x1f,0x0,0x7a,0x15,0x30,0x1f,0x2f,0x83,0xf5,0xc2,0xd1,0xb,0x25,0x2c,0x7c,0x56, + 0xaf,0x61,0x1f,0xad,0x99,0xf7,0xae,0xd3,0x5d,0xeb,0x3f,0x4e,0x92,0x24,0xc,0xbd, + 0xa0,0xd,0x8e,0x7e,0x21,0x74,0x38,0x49,0x77,0xcf,0x45,0x92,0xbb,0x52,0xb6,0xb5, + 0x39,0x9c,0xcc,0xc5,0x95,0xab,0x82,0x80,0x93,0xe1,0xa8,0x67,0x4e,0xf4,0x2e,0x22, + 0xcd,0xdd,0x48,0x46,0x98,0x7b,0x3e,0xa6,0xf9,0x96,0x34,0x3,0xe0,0x66,0x51,0x1f, + 0x17,0xb2,0x3f,0xd,0x0,0x80,0xdf,0xdf,0xc8,0x7,0xc5,0xa8,0xcd,0x95,0x8f,0x39, + 0x1f,0xb8,0x3e,0xed,0xbc,0x61,0x9,0x37,0xc1,0x7a,0x68,0xd6,0xfb,0xc5,0x2d,0xb7, + 0x22,0x6a,0x79,0xd7,0xef,0xd2,0xe0,0x8,0x86,0xd1,0xdc,0xfd,0x7d,0x53,0xf5,0xc4, + 0x49,0x8d,0xb7,0x1b,0xc1,0x7a,0xd9,0xd7,0x6d,0xe4,0x52,0x97,0x3d,0xb,0xb7,0xe0, + 0x79,0xf,0xfd,0x8,0xcc,0x2c,0xc2,0x1c,0x66,0x70,0x5d,0x57,0x6e,0x1b,0xb0,0xce, + 0x62,0xb2,0x7e,0x61,0x34,0x9c,0xb8,0x31,0x3f,0x50,0x4b,0xe7,0x2c,0xf8,0xbb,0x3d, + 0xf6,0x5a,0x94,0x8b,0x6f,0xf4,0xc7,0x5e,0x5c,0x2e,0xa2,0x97,0x21,0x29,0xb7,0xf4, + 0x6,0xd,0x52,0x3e,0x9e,0xa8,0x58,0xc6,0xa,0x44,0x76,0xb6,0x2b,0xc0,0x1b,0x6, + 0xf3,0x52,0x80,0x9c,0x64,0xef,0x17,0xe8,0x6b,0x4e,0x30,0xfe,0xeb,0x5f,0x15,0xcd, + 0xb1,0x81,0x60,0x63,0x8e,0x7c,0x20,0xcf,0xee,0x60,0xfd,0xd0,0xbd,0x43,0xbb,0xf7, + 0xa7,0x6f,0x45,0xcf,0x15,0x3c,0x3f,0xd4,0xcb,0x83,0xcc,0xc5,0x8d,0xcf,0x1d,0xe6, + 0x33,0xe9,0x1f,0x2,0x6c,0xd7,0x8,0x36,0x7e,0xed,0xed,0xe1,0x79,0x2f,0xf5,0x9c, + 0xdd,0xbe,0xd1,0xbf,0x3e,0x7a,0x8e,0x81,0xfe,0xce,0xac,0x8d,0x41,0x9,0xf1,0x6, + 0xd6,0x4a,0x5,0x4c,0x57,0x8f,0xc3,0xe7,0x3,0xc9,0x7a,0x54,0xf3,0xcb,0x7c,0x96, + 0xc7,0x1c,0x60,0xc,0x83,0x1,0x7c,0xd6,0xf,0xea,0x8,0xd5,0x9d,0x63,0xef,0x62, + 0x3d,0xbf,0x13,0xc,0xde,0x85,0x1a,0x94,0xd5,0xe8,0xee,0xf0,0xb9,0x1d,0x9c,0x57, + 0xd3,0x87,0x31,0xe7,0x1d,0xcc,0x4d,0x7b,0xbd,0xe2,0xbe,0x18,0x1c,0x5e,0x2b,0xe, + 0xff,0xdc,0x34,0x7b,0xa7,0x9c,0x8c,0xa4,0xd2,0x13,0x5a,0xe8,0x7,0x67,0xc8,0xa9, + 0x24,0xc6,0x7f,0xe0,0x3f,0xff,0xef,0x8a,0x77,0x45,0x31,0x5f,0xf2,0xbc,0xfd,0x7c, + 0x56,0x79,0x6b,0xfd,0xc4,0xa2,0x23,0xd2,0x46,0x27,0x8b,0x8d,0xf7,0xf6,0xc7,0xc6, + 0xef,0xb7,0xba,0xc7,0x61,0x86,0x4e,0x77,0xaf,0xac,0x8c,0x67,0x6f,0x9f,0xa8,0x4a, + 0xb2,0x8e,0x2e,0xd4,0x71,0x9b,0x1f,0x1a,0x31,0x79,0x4a,0x1f,0x21,0x81,0x89,0xa7, + 0x66,0xc6,0xd8,0xb3,0x38,0x62,0x53,0x43,0x80,0x8c,0x79,0xfa,0xb2,0xe,0x11,0xfd, + 0x63,0x95,0x9d,0x91,0x8c,0x20,0xe9,0x9e,0x47,0x7f,0x7d,0x97,0xb9,0x87,0x27,0x34, + 0xe5,0xdf,0x3b,0x9e,0x70,0xd4,0x89,0x64,0x7e,0x29,0x49,0xc4,0x60,0xfb,0x89,0xf5, + 0x4c,0xf8,0x59,0x1,0x31,0x69,0x16,0xe7,0x1a,0xbb,0xce,0x35,0xfd,0x65,0x74,0x80, + 0x33,0x3c,0x6f,0x22,0xea,0x18,0x20,0x31,0x9,0xcd,0x89,0xa9,0xf0,0xba,0x93,0xbe, + 0x77,0xbf,0x67,0xb6,0x26,0x16,0xb9,0x9a,0x9,0x1a,0xf2,0x86,0x24,0x5f,0xef,0x6d, + 0xbc,0x67,0x35,0x24,0x91,0x47,0x6e,0x43,0x8d,0x9a,0xb2,0xe1,0x81,0xa,0x9a,0xf9, + 0xf4,0x2b,0x9e,0x61,0xbe,0xd2,0xae,0x89,0xc,0x56,0x5d,0x9,0x54,0x46,0xc7,0x4f, + 0xe4,0xbb,0x5f,0x12,0x98,0x23,0x50,0x83,0x6c,0xfe,0x24,0x6f,0x3c,0xc8,0xbc,0x7, + 0xe7,0xee,0x9f,0xd7,0x79,0xd3,0x3d,0xea,0x3f,0xf5,0x3a,0x3e,0x39,0x87,0xd,0x3b, + 0x95,0xc7,0x16,0x2b,0x7b,0x63,0x1a,0xbc,0xfe,0xa,0x43,0xb4,0x9b,0xd3,0x4d,0x96, + 0xd6,0xa9,0xf,0xff,0xbd,0xa3,0xad,0xce,0x14,0x5a,0xc8,0x8f,0x41,0xe,0x95,0x5e, + 0x73,0x55,0xd1,0xc9,0x97,0xce,0x97,0xc9,0xc9,0x98,0xea,0x87,0x80,0x4d,0xff,0x27, + 0x24,0x54,0xc6,0x68,0xfb,0x34,0x31,0xb9,0xec,0x9e,0xa5,0x70,0x78,0x46,0xcc,0xe8, + 0xfb,0x71,0x63,0x18,0x41,0xc6,0x3c,0x2b,0xcc,0x76,0x8a,0x59,0xe2,0x0,0x30,0x99, + 0x87,0x7c,0x35,0x6a,0xf1,0x54,0xdb,0xa0,0xa2,0x80,0x21,0xd3,0x7f,0xf4,0x21,0x47, + 0xeb,0xa5,0x23,0xaf,0xfe,0xc9,0x29,0x34,0x89,0xa8,0xd4,0x69,0x1f,0x9a,0xe7,0x5e, + 0x82,0x21,0xb7,0x3a,0x77,0x93,0x76,0xc,0x43,0x85,0xe4,0xf7,0x39,0x6b,0x50,0xe8, + 0x55,0xa1,0x1,0x31,0x22,0x22,0xd8,0xd7,0xc0,0xf7,0xd5,0x4f,0x6e,0x30,0x97,0x82, + 0x94,0x57,0x6,0x9,0x22,0xf3,0xb2,0x0,0x63,0x44,0xfc,0x46,0x85,0xc2,0x3f,0xd2, + 0x7f,0xab,0x7c,0xbe,0xbe,0x4b,0xbf,0xff,0x7e,0x9,0xa0,0xb1,0xb6,0xd3,0xbe,0x97, + 0x93,0xcd,0x74,0xf4,0x34,0xff,0x6b,0xa7,0x18,0xcc,0x22,0xdf,0x30,0xce,0x26,0x23, + 0x99,0x11,0x7,0x98,0xfa,0xa4,0x8b,0x23,0xf9,0xc9,0x7c,0x4c,0xde,0x55,0xf,0x24, + 0x46,0x7b,0xad,0x24,0xeb,0x40,0xe4,0xa4,0x31,0x22,0xa2,0x2a,0xe9,0x7c,0xe,0xc1, + 0x13,0x64,0x48,0x82,0x74,0x3,0xba,0xdc,0xc0,0x6,0x49,0x3a,0xe0,0x70,0x5d,0x16, + 0x70,0xcf,0xa0,0xed,0x0,0x63,0xe3,0x6f,0x90,0xc1,0xe8,0x12,0x3a,0x1f,0x8,0x22, + 0x22,0xff,0x7e,0xef,0xdd,0x1c,0x40,0xf0,0x57,0x2b,0x0,0xb8,0x67,0xe2,0x8f,0x3c, + 0xfb,0x39,0x19,0x8c,0xc1,0xfb,0xe5,0x67,0xc8,0xce,0xc4,0x3f,0x34,0xd3,0x45,0xa6, + 0xea,0x37,0xb,0x62,0xaf,0xcf,0xa9,0xde,0xdd,0xcc,0x6d,0xc2,0x70,0xc7,0xbe,0x5b, + 0x88,0x4e,0x9a,0x65,0xc6,0x70,0xf4,0x55,0x21,0x7,0x40,0xc7,0xb0,0x5a,0x0,0xa8, + 0xe3,0x16,0x86,0x3d,0xab,0x70,0xca,0x4,0x54,0x6,0xae,0x25,0xb6,0xae,0xd0,0xbe, + 0x8f,0x7d,0xc3,0xac,0xd,0x5c,0x1b,0x90,0x67,0xa7,0xf4,0x81,0x52,0xaf,0xbf,0x9e, + 0x78,0x27,0x4b,0x15,0x68,0x1a,0x82,0x41,0x7,0xac,0x3c,0x4c,0xf4,0xa3,0xab,0x8c, + 0x84,0xa4,0x52,0xc0,0x37,0x49,0x79,0xb3,0x91,0x1b,0xf7,0xf9,0xd4,0x22,0xa8,0xd8, + 0x2,0x9e,0x7c,0x59,0xc0,0x93,0x8e,0xbe,0xd4,0x2b,0xb0,0x4e,0x2d,0x90,0xe0,0x9e, + 0x49,0x59,0x84,0x7,0x9f,0x83,0xb6,0x91,0xe,0x9,0x28,0x5d,0xe1,0xe6,0xd7,0x22, + 0x3e,0xb9,0xbf,0xd6,0x39,0x30,0xd2,0x5c,0x20,0x1a,0x77,0x0,0x59,0xa,0xdf,0xc2, + 0xbc,0x83,0xc2,0x1e,0x9e,0xe8,0x88,0x7c,0xc3,0xfb,0x8d,0xfe,0x34,0x47,0xad,0x17, + 0x4e,0xaa,0x43,0x9c,0x6c,0xb6,0xfe,0x6f,0x44,0x30,0xb6,0xea,0xf7,0x44,0x2d,0x1c, + 0x8e,0x41,0x80,0xf6,0xfa,0xba,0xd5,0x33,0x78,0x83,0x5a,0x2a,0xd5,0xd1,0x8b,0x4, + 0x16,0xc1,0x8e,0xaa,0xf9,0xc3,0xc1,0x2,0x8e,0x22,0x48,0xbc,0x5,0xd,0x36,0xed, + 0x30,0x9,0xc7,0xb5,0xc0,0x7a,0xcd,0x79,0xd7,0x1f,0xa8,0xdd,0x58,0x2f,0x3a,0xa1, + 0x0,0xb3,0xc9,0x23,0xe1,0x30,0x1,0x3f,0x7,0xcb,0xab,0x70,0x9c,0xd5,0xaa,0x60, + 0x33,0xe6,0xb5,0xfc,0xf2,0x3b,0x46,0x84,0xfb,0xac,0xed,0xc6,0xa2,0xea,0x7e,0xa4, + 0xb4,0xa6,0x6c,0x4a,0xec,0x39,0x5,0x89,0x3,0xf5,0xb,0x11,0x83,0x51,0xb8,0xff, + 0x38,0x9c,0xf8,0x67,0x11,0x0,0x83,0xc5,0xe4,0x1,0x53,0x58,0xcf,0xf6,0xe6,0x3d, + 0x2,0x37,0xb1,0x83,0x0,0x85,0xb9,0x1e,0x83,0xa4,0xe1,0xd6,0x7c,0x40,0xa2,0x40, + 0x51,0x27,0x13,0x1c,0x93,0x41,0xe7,0x3,0x64,0x98,0xbb,0xd,0xd2,0x26,0xb,0xd5, + 0x8d,0x74,0xd9,0xa7,0xbc,0x67,0x76,0x58,0xf4,0x81,0x9b,0x20,0x58,0x87,0x6c,0x81, + 0x28,0xfc,0x41,0x38,0xdd,0x9,0x84,0x91,0x7d,0x28,0x6a,0x59,0x93,0xc9,0x81,0x63, + 0xf7,0x46,0x62,0xa7,0xee,0xf8,0xfd,0xd,0x48,0xd,0x5d,0x47,0x45,0xed,0x17,0xd6, + 0xe9,0xd,0xcb,0x5f,0xef,0xb3,0xcf,0x68,0x91,0x7b,0x63,0xb3,0xa8,0x8,0x8b,0xc8, + 0x4f,0xf,0x46,0xa5,0x8f,0x19,0x43,0x60,0xc1,0x28,0x50,0xc8,0x3a,0xf1,0x3f,0x95, + 0x72,0x66,0x38,0x5d,0x39,0x56,0xe1,0x88,0xc9,0xf8,0x3b,0x3e,0xd4,0x17,0x84,0x22, + 0xd0,0x89,0x2,0x9d,0x40,0x97,0x87,0x3b,0x68,0x8,0x5e,0xa4,0x81,0x5b,0x1,0x40, + 0xd2,0xff,0x4f,0xae,0x49,0x9c,0xb7,0x52,0x28,0xbe,0x49,0xa,0xb2,0xe5,0xc6,0x1f, + 0x59,0x2e,0x76,0x29,0x65,0x28,0xaf,0xb0,0xbc,0x10,0xa2,0xf1,0x16,0xd4,0xf,0x7, + 0x50,0xdb,0x63,0x22,0x1d,0xe4,0x57,0xf6,0xa6,0x4,0x65,0xb9,0x91,0x4e,0x6b,0x5b, + 0x49,0xd4,0xf3,0x4,0x81,0x2c,0xf5,0x4c,0xd1,0xe7,0xf2,0x13,0x70,0x59,0x75,0x8a, + 0xd4,0x1a,0x61,0xd1,0x90,0xde,0x56,0x44,0xa7,0x54,0xec,0x6f,0x28,0x88,0x29,0xc0, + 0x4e,0x41,0x71,0xb,0x7e,0xaf,0xc4,0x3c,0x51,0xda,0x7,0xe4,0xdd,0x43,0xe8,0x1c, + 0x4b,0x5b,0x35,0xe5,0xc9,0x99,0x3b,0xf3,0xec,0x9c,0xc8,0xd2,0xf6,0x42,0x71,0xff, + 0x7,0xb6,0xab,0x35,0x86,0x17,0xfc,0x91,0x5c,0xd1,0xe,0x66,0x26,0x65,0xd,0x29, + 0xdc,0xcb,0xa9,0x7e,0x22,0x51,0xf6,0x8e,0x3,0x79,0xaf,0x7c,0xb0,0x9b,0x4e,0xce, + 0xb3,0x2,0xd8,0x83,0xa5,0xde,0x3b,0xf6,0xb8,0x6d,0x64,0x85,0x16,0x40,0x1d,0x4a, + 0x79,0xd8,0xbd,0xd5,0x5b,0x97,0xad,0x83,0xd0,0x54,0x36,0x6a,0x38,0xf,0x2a,0xa2, + 0xcf,0xbc,0xc5,0xa4,0xe0,0x9b,0x84,0xc2,0x90,0x87,0x1,0x2e,0xfc,0x31,0x61,0x4c, + 0x98,0x33,0xec,0x99,0xdc,0x7f,0x66,0xb3,0x3e,0x19,0x10,0x31,0xb9,0xd0,0x1c,0x4b, + 0x19,0xa4,0xa4,0xc,0x6d,0x72,0x6a,0xaf,0x86,0x2a,0x5,0xb3,0x86,0xea,0xcd,0x98, + 0x79,0x2b,0x35,0x53,0x39,0x40,0x15,0xbe,0x8,0x6,0x5e,0x74,0xb0,0xb1,0x4e,0x9b, + 0xc3,0x2b,0xfa,0xf5,0x2e,0xce,0x6e,0x5b,0x5d,0x45,0x66,0xd6,0xe7,0xa8,0x43,0x4c, + 0x85,0xde,0x2b,0x99,0xb2,0xf0,0x66,0xd1,0x32,0x1a,0x18,0xb,0x9b,0xb,0xfe,0xc6, + 0x6f,0x55,0x5a,0xd1,0x9f,0xa8,0x37,0xcd,0x2e,0x3b,0xfa,0xf1,0x76,0xa2,0x93,0x68, + 0x77,0xed,0xbd,0x60,0x95,0x71,0xec,0x43,0x71,0xea,0x18,0x6e,0x9c,0xa6,0xeb,0x85, + 0x33,0x85,0xa7,0x19,0x36,0xee,0xef,0xa9,0x2f,0xab,0x32,0x6b,0xca,0xac,0x8,0x61, + 0xf5,0x3,0xfd,0xd8,0xab,0x2,0x68,0x80,0xee,0x26,0x67,0x7d,0x5a,0x57,0x71,0xe6, + 0x20,0xea,0x80,0x8c,0x88,0x88,0xc0,0x83,0xd8,0xc6,0x86,0xe,0xc0,0x4e,0x8,0xaa, + 0x4d,0x14,0x64,0x18,0x6d,0x71,0x93,0x2e,0xe,0xc9,0x46,0x90,0xbc,0x2,0x34,0x1b, + 0x86,0x19,0x1a,0xc0,0xdd,0x94,0x32,0xb0,0xd9,0x33,0xbd,0x28,0x79,0x42,0xf2,0x2, + 0xc5,0x99,0xac,0xbc,0x71,0xa1,0x1,0x7a,0x2a,0x64,0xa1,0x39,0xc5,0xa0,0x98,0x37, + 0x27,0x83,0x2,0xae,0x92,0x74,0xb2,0xca,0xfc,0xf,0x56,0x7b,0x16,0x5b,0xed,0xd5, + 0x77,0x2d,0x5f,0xe4,0x1a,0xfa,0x2,0x7,0x73,0x18,0x2a,0x75,0x2e,0x41,0xb2,0xab, + 0x1,0x3e,0x71,0x95,0xf3,0x41,0xbd,0x8d,0x3b,0xa0,0x3b,0xe7,0x78,0x48,0xf4,0x43, + 0x96,0x58,0x65,0x98,0x5b,0xd8,0x70,0xde,0xd6,0x1c,0xc,0x15,0xdc,0xf9,0x37,0x8c, + 0x3a,0xa4,0xa4,0xd2,0xe3,0xd,0x6e,0x2d,0x49,0xbe,0xc5,0x3c,0x98,0x5b,0x82,0x5, + 0x5c,0x62,0xa2,0xff,0xc5,0x36,0x1a,0xc4,0x6b,0x1a,0xa0,0x81,0xb8,0x73,0x1f,0x60, + 0xd1,0x4a,0xc4,0x45,0x22,0x73,0x75,0xc6,0xe1,0xbc,0xf3,0x12,0xdc,0xdb,0x93,0xf3, + 0xd7,0x1,0x83,0x3b,0x1c,0x28,0x74,0x26,0xe1,0xe0,0x5c,0xd8,0x8d,0xdd,0x61,0x50, + 0xa0,0x8,0x13,0x48,0x18,0xdc,0x4,0x38,0x4f,0x52,0x9c,0x40,0xf4,0x10,0x62,0x83, + 0x78,0x42,0xe2,0x6,0xf7,0xf8,0xaf,0xfc,0x69,0x21,0x1d,0x4c,0xbc,0x54,0x26,0x60, + 0x4b,0xe5,0xba,0xab,0x9,0x52,0x79,0x6,0xbc,0x4,0x0,0x4d,0x37,0xa7,0xd9,0x41, + 0x69,0xea,0x51,0x77,0x58,0x89,0x88,0xe4,0x81,0x83,0x7c,0xf,0x5f,0xf8,0x1c,0x19, + 0xe7,0x8c,0x5e,0xb1,0x5,0xf4,0x98,0x99,0x3a,0xc6,0xea,0x3c,0xeb,0xe5,0xba,0xeb, + 0xda,0x4e,0xfd,0xdd,0x29,0xf9,0x2,0x92,0xd8,0x4c,0xcb,0x70,0x81,0x55,0xd9,0xb8, + 0x59,0xf9,0x44,0xef,0x3e,0x87,0x70,0x35,0xb,0x76,0xf1,0x70,0xef,0x2c,0xca,0x15, + 0xf2,0x18,0xeb,0x9d,0x77,0x7a,0xc1,0x20,0xbc,0xa2,0x5b,0xf2,0xc0,0x41,0x26,0xa6, + 0xf3,0xfb,0xfb,0x9b,0x9c,0x81,0x0,0x5c,0x2a,0xf9,0xd8,0x25,0x99,0x55,0x53,0xca, + 0x16,0xa2,0x4f,0xf7,0xda,0x3b,0x80,0x45,0x24,0x95,0x4d,0x54,0xcd,0x18,0x7d,0xbb, + 0xbd,0x6,0xa,0xee,0x48,0xc0,0x21,0x17,0x6a,0xad,0x82,0xfe,0x88,0xdf,0x88,0x5c, + 0x3a,0x2e,0xd4,0x2b,0x8d,0x9e,0xff,0x12,0xb8,0xaf,0xc0,0x1f,0x78,0xeb,0x9,0x30, + 0xfb,0xb0,0x39,0xc4,0x1,0xa6,0x90,0xe9,0x3f,0xea,0xcc,0x6b,0xfe,0xe9,0x81,0x4, + 0xf6,0xe1,0x36,0xbb,0xb,0xc,0xec,0x29,0x18,0xc4,0x92,0x6a,0x90,0x2a,0x96,0x37, + 0xee,0x37,0x24,0xc6,0x88,0x53,0x1e,0x1c,0xe,0xa0,0x79,0x79,0x65,0x79,0xa1,0x49, + 0xf4,0x1f,0xea,0x7,0x49,0xff,0x9f,0xcc,0x5b,0xe3,0x7,0x2e,0xa,0x34,0x7b,0x73, + 0xd2,0x66,0xac,0x6c,0x3,0x5c,0xae,0x78,0xff,0x8,0x85,0xf9,0x39,0x4c,0xcb,0x49, + 0xb4,0x95,0x6,0x7e,0x58,0x7,0x6b,0x31,0x80,0xd5,0xfb,0xb6,0x41,0x98,0x72,0x15, + 0x89,0xd2,0x2,0x2,0x92,0x5e,0x14,0xc8,0x30,0x6c,0x4c,0xfe,0x18,0x1f,0x86,0x85, + 0x4d,0x7b,0x69,0xb6,0xfd,0x5c,0x47,0x79,0x42,0x5c,0x96,0xa2,0x1,0x95,0x81,0xbf, + 0xd0,0x87,0xd6,0x73,0x38,0x2d,0x3e,0x46,0x1b,0x9c,0x38,0x89,0xea,0xe7,0xec,0x74, + 0x7,0x63,0x8f,0x84,0x25,0x9f,0xf7,0x75,0xd7,0x49,0xf6,0xd0,0xbe,0x55,0x31,0x6e, + 0xb8,0x31,0xd0,0xcc,0xe7,0x86,0x9f,0x3c,0x92,0xd,0xb3,0x4c,0xb8,0xb4,0x8,0x4e, + 0xb4,0x8e,0xa,0x4c,0x20,0x85,0xd0,0xea,0x6f,0x97,0xf0,0xa8,0xa3,0xce,0x0,0x89, + 0xe3,0x80,0x16,0xac,0xfc,0x83,0xf8,0x30,0x1a,0x2d,0xfa,0x10,0xde,0x3d,0xb3,0xd8, + 0x65,0xe5,0x6f,0xbd,0xb8,0xf5,0xe9,0xd9,0x2d,0xc4,0x12,0x2c,0x6,0x27,0x1,0x8c, + 0x88,0xcc,0xf8,0x6,0x59,0xe2,0xe8,0x76,0x78,0x43,0x2c,0x1e,0x55,0x90,0x0,0xdd, + 0x95,0x14,0xe7,0x17,0xac,0x23,0xf0,0x14,0x10,0x7b,0xea,0x9d,0xdf,0x56,0x69,0xdb, + 0x5e,0x57,0x6e,0xbe,0x76,0x48,0x1f,0x62,0x8c,0xd0,0x3d,0x70,0xf9,0x21,0x66,0x38, + 0x76,0x78,0x1e,0xad,0x79,0x5c,0xe0,0x79,0xe7,0xb3,0xa,0xb0,0x68,0x84,0x23,0xd3, + 0xc6,0x3a,0xf,0x4a,0xed,0x23,0x8a,0xa5,0x86,0xb1,0x4,0x79,0x43,0x45,0xff,0x84, + 0x83,0x32,0x2e,0x9b,0x28,0xc8,0xa,0x19,0x42,0xdf,0x12,0x39,0x8c,0xeb,0xfc,0xfc, + 0x90,0x1c,0x11,0x11,0x16,0x6,0xf9,0x54,0xf7,0x4c,0x6e,0x42,0x8e,0x6c,0xff,0x9c, + 0x8b,0x49,0x39,0x61,0xc4,0x39,0xd,0x1,0x65,0xea,0xed,0x75,0xcf,0x44,0x7e,0xaf, + 0x3e,0x3c,0xd0,0x18,0xdd,0x8f,0xfb,0x4f,0x15,0x58,0xb1,0xc2,0xb4,0x14,0x9c,0x91, + 0xbf,0xbf,0xbf,0x2d,0x3c,0xcb,0xbf,0x77,0xeb,0xf8,0x50,0xcc,0xd9,0xdc,0x5c,0x27, + 0x8a,0x8b,0x6c,0x13,0xc,0xb2,0x57,0xd7,0xe2,0x3f,0xf9,0x87,0x98,0xdd,0xd4,0x92, + 0xb7,0xaa,0x98,0xe2,0xd1,0x42,0xc,0xda,0xb5,0x38,0x4d,0x30,0x33,0x3e,0x1c,0x40, + 0x8f,0xf3,0xdf,0x5e,0x65,0xe8,0x6,0x15,0xd7,0xfd,0x56,0xab,0x60,0xe4,0x55,0xb, + 0xe0,0x43,0x4f,0x6,0x4d,0xde,0x5e,0x9d,0x45,0xb,0xc,0xf8,0xa9,0x83,0x32,0x47, + 0xbf,0xa7,0x5,0x7a,0x5,0x43,0xd1,0x2a,0x21,0xd6,0xa0,0x34,0x64,0xa5,0xcd,0x50, + 0xc8,0x86,0x9d,0xad,0x4a,0xee,0xf7,0x84,0x5c,0xf9,0xc4,0x4c,0x6f,0x2b,0x65,0xb1, + 0x53,0x9f,0xa,0xff,0x82,0xab,0xe3,0x9c,0xdd,0xcc,0xc6,0x46,0xf9,0x55,0x6c,0xc, + 0xe5,0xb1,0x22,0x3b,0xec,0xa6,0xc6,0xbf,0x54,0x44,0xa4,0xdd,0x6a,0xd3,0xb8,0xe7, + 0x1f,0x17,0xee,0x5a,0x3e,0x93,0x72,0xdb,0xe8,0x88,0x3b,0xe8,0x17,0x17,0x39,0xdc, + 0x22,0x20,0xe3,0x44,0xfe,0x5b,0xcf,0xaa,0x4d,0xd9,0xac,0x39,0x16,0x7e,0x75,0x59, + 0x9d,0x16,0x28,0xc6,0xa,0xe3,0x97,0xbc,0xe4,0x25,0x74,0x16,0x70,0xb5,0xda,0x53, + 0x6e,0xde,0xe7,0x31,0x86,0xb,0xea,0xea,0x38,0x79,0x34,0x29,0xd1,0x1a,0xab,0x53, + 0x55,0xe0,0x16,0x57,0x44,0xb3,0x6a,0x5d,0x7,0x20,0x6b,0xf0,0x1,0x7f,0xaa,0x2a, + 0x18,0x21,0xa6,0x26,0x89,0xf6,0xe6,0xfd,0xa3,0xb4,0x49,0x14,0x88,0xa5,0x11,0x34, + 0x86,0x10,0xcb,0xc5,0xc4,0xf0,0x41,0xe6,0xce,0x8a,0xd0,0xa7,0xe4,0xef,0xde,0x28, + 0x2,0x60,0x8f,0xdc,0x4b,0xea,0x34,0x9,0xb4,0xca,0x6,0x3d,0x1e,0x4c,0x4a,0x6d, + 0x8a,0x38,0xb4,0xbf,0x8e,0xfb,0xcf,0x5b,0x26,0xeb,0xca,0xa,0x4e,0x6,0x6a,0xb, + 0x2f,0xf1,0x11,0x33,0x59,0xd7,0x7f,0x5,0xec,0x70,0xcb,0x58,0x55,0xb8,0x29,0x4c, + 0x58,0xc9,0x50,0x82,0x3a,0x8b,0x56,0x76,0xfa,0xb3,0x55,0x57,0xca,0x5b,0x7a,0xed, + 0xc,0x16,0xda,0xb8,0x5f,0x72,0xb3,0x59,0xa5,0xc9,0xd7,0x34,0xc0,0xdd,0xfc,0x64, + 0x50,0x11,0xa8,0xd3,0x62,0x36,0x2f,0xc,0x76,0x6b,0xdd,0x23,0x2c,0x7b,0x60,0x8, + 0x77,0x9f,0x68,0x92,0x48,0x17,0x54,0xf0,0x43,0x66,0xfa,0x6f,0x27,0x19,0xed,0x88, + 0xe9,0x6e,0x66,0x3f,0x3f,0x3f,0xfe,0xa6,0xbe,0xa5,0x4f,0x85,0x48,0x38,0x8b,0xd3, + 0xa6,0x45,0x44,0xf1,0x5b,0x5d,0x11,0x96,0x34,0x68,0x82,0xfe,0x90,0xc0,0x2d,0x3, + 0xbd,0x20,0x4c,0xd6,0xf2,0x52,0xb4,0xed,0xe1,0x1e,0xb8,0xc,0x56,0x25,0xf9,0x43, + 0x96,0x26,0xfa,0x1f,0xe6,0x7e,0x13,0x3,0x91,0x81,0xf2,0x9f,0xca,0x17,0xce,0x1a, + 0x3f,0xc9,0x19,0xe4,0x78,0x90,0x4d,0xdd,0x2a,0xae,0xab,0xd6,0xc1,0xa2,0xb1,0xbd, + 0xe6,0xb0,0xe9,0x71,0xa1,0x55,0x9b,0x12,0x63,0x8a,0xd3,0xc1,0x55,0x47,0x5,0x6b, + 0x42,0x56,0xf2,0x5,0xdd,0x25,0x48,0x29,0x33,0x3d,0x40,0x95,0xfd,0x2d,0x6,0x81, + 0xa8,0xe1,0xa9,0x78,0x65,0xff,0x9b,0x26,0x9a,0x47,0xce,0x29,0xe3,0x64,0xf4,0xb9, + 0xb8,0x79,0xfa,0x26,0x56,0xec,0x85,0xf9,0xc2,0x2c,0x1f,0x9a,0xcb,0xb1,0x27,0x1f, + 0x47,0x21,0xb7,0xfc,0xc4,0x22,0xd,0x2f,0x40,0xfa,0xd5,0x9d,0xbf,0x15,0x40,0x27, + 0xd2,0x27,0xf5,0x96,0xfa,0x1d,0x58,0xf2,0x7c,0xcf,0x7b,0xfe,0x41,0xd,0xea,0x39, + 0x74,0xa,0x98,0x26,0x0,0x12,0xa3,0x3e,0xfc,0xce,0x44,0x87,0x64,0x20,0x59,0xe2, + 0x12,0xf2,0x76,0x4f,0x44,0xc9,0x3a,0x1e,0xb5,0x6b,0x2f,0x93,0x96,0x95,0x9,0x7e, + 0x95,0x77,0x91,0x2,0xc1,0xcc,0x4c,0x93,0x85,0xa3,0x26,0xb6,0xe8,0x42,0x73,0xf0, + 0xcb,0x54,0x5e,0x77,0x32,0x2b,0x8b,0x22,0xc2,0x18,0xf3,0xe9,0x59,0x8e,0x94,0xda, + 0xcf,0xb,0xf1,0x2b,0x1e,0x58,0xd8,0x2a,0xbe,0xe8,0xe4,0x95,0x89,0x99,0x59,0x3, + 0xca,0xa6,0xba,0x48,0xb6,0xbc,0xae,0x53,0xf7,0x62,0xd4,0x5e,0x1,0xf4,0x54,0xbc, + 0xb8,0x48,0x60,0xc9,0x7e,0x52,0x67,0x72,0x6a,0x70,0x56,0x26,0xf4,0xa,0x81,0xba, + 0x9,0x20,0x5,0x23,0xb6,0xd,0x26,0x8b,0x1e,0xcd,0xa9,0x42,0x83,0x9f,0x62,0xf7, + 0xab,0x9d,0x1e,0x76,0x9e,0x57,0x20,0x94,0x6b,0x68,0x93,0xf7,0x83,0xc5,0x2b,0xc3, + 0x71,0xe3,0x4c,0x85,0x42,0x32,0x22,0x50,0xdc,0xb9,0xdb,0x5b,0x5,0x4d,0xc4,0x29, + 0xd1,0x53,0x17,0x2b,0x5e,0x6a,0x82,0x6,0x40,0xf3,0x35,0x47,0x6b,0xc4,0x27,0xe5, + 0x94,0x97,0xfb,0x90,0x6b,0xab,0x28,0xcd,0x3e,0x0,0xa9,0xc9,0xb2,0xbf,0x4,0x9, + 0xe2,0xd7,0x4a,0x46,0x83,0x63,0xcd,0x27,0x61,0x20,0x72,0x2e,0x2c,0x39,0xd0,0xd8, + 0xea,0x9b,0x20,0x2,0xbf,0x60,0x92,0xe4,0x78,0xd0,0xff,0x3c,0x6,0x78,0x1,0x97, + 0x95,0xcf,0x17,0x5e,0x95,0x5a,0xba,0x29,0x3e,0x36,0xe3,0x6,0x95,0x4f,0xe6,0xf2, + 0x66,0x59,0x8a,0x7d,0x95,0x41,0xe6,0xdf,0x8c,0x61,0xc5,0x97,0x9b,0x30,0xae,0x18, + 0xb3,0x69,0x35,0x68,0x74,0x55,0xcc,0xfa,0x2b,0xa8,0xe4,0x14,0x2,0x89,0x5a,0xc0, + 0x8e,0x46,0x5c,0x49,0x69,0x70,0xa8,0x43,0xc1,0x55,0xa5,0x7b,0xa0,0xa1,0x1c,0xed, + 0x54,0x38,0xc7,0xd5,0xfc,0x2d,0x4e,0x2b,0x0,0xe4,0x2f,0xb8,0xc5,0x22,0x9a,0x3, + 0x10,0x9e,0xf6,0x14,0xf9,0x26,0x3d,0x39,0xb6,0x8a,0x14,0xf3,0x64,0x20,0x3f,0xd1, + 0x18,0x53,0x17,0x9f,0xe2,0x3,0x47,0xb,0x3b,0xc7,0x88,0x89,0xda,0xc7,0x82,0xe6, + 0xfb,0x34,0xea,0x58,0x44,0x37,0x92,0x2d,0xc8,0xf7,0xd7,0x53,0xce,0xa6,0x9b,0xab, + 0xc0,0x2b,0x59,0x9b,0x8b,0x58,0x10,0x5f,0x4,0xef,0x2a,0x44,0xe5,0x68,0xff,0x67, + 0xeb,0xc3,0xc4,0x23,0x8c,0x9e,0x67,0x24,0x31,0xb,0xbd,0xb,0x67,0x9f,0xdb,0x93, + 0x25,0x57,0xab,0x6,0x36,0x4c,0x67,0x46,0xc6,0xe,0x87,0x3b,0x5c,0x85,0x65,0x97, + 0x52,0x2a,0x15,0xd0,0xb4,0x4f,0x15,0xe2,0x51,0x1a,0xf,0x2d,0x7b,0xc1,0x91,0xb9, + 0xf7,0xa3,0x9b,0xcd,0x9f,0x9b,0x56,0x11,0xb8,0x82,0xaa,0xdd,0xd,0xce,0x2,0xca, + 0xf3,0xb9,0x79,0x4a,0x3e,0xf2,0x24,0x98,0xf3,0xc0,0x6e,0x6b,0xd6,0x91,0x81,0xa, + 0xc1,0xf4,0xd7,0xb,0xd2,0x58,0xa,0xc7,0x95,0x76,0x76,0xdf,0xc2,0xed,0xd6,0x78, + 0xce,0x84,0x25,0xbd,0x9f,0xfa,0xb,0xfe,0x13,0xf1,0xab,0xdb,0x98,0xf7,0x7d,0xd5, + 0x2b,0x8,0x13,0xb5,0x92,0x6d,0x91,0x39,0xd5,0x7c,0x49,0xa3,0x8b,0x47,0x75,0xcd, + 0x40,0x50,0xc,0x6d,0xc9,0x3d,0xcd,0x1e,0x1,0xf5,0x72,0x52,0x97,0x52,0xe9,0xf8, + 0xa0,0x47,0x2d,0xb1,0x95,0x77,0x89,0x2,0x76,0x81,0xe2,0xf0,0xd5,0x11,0xd1,0x0, + 0x13,0x55,0xc5,0x8c,0x89,0xed,0x22,0x27,0x89,0x8,0x46,0x58,0xd4,0xde,0x1c,0x15, + 0xd0,0xd9,0x3b,0x80,0xb1,0x5a,0x3f,0x9a,0xb4,0x28,0xe5,0xe1,0xea,0x7f,0x1a,0xae, + 0xa9,0xaf,0x5c,0xcb,0xac,0xf0,0x1f,0x4a,0xf1,0xca,0x95,0x66,0xd6,0x51,0x1d,0xad, + 0xd8,0xae,0xc3,0xac,0x16,0x27,0x96,0x8d,0x72,0x9c,0xa5,0x58,0xfa,0xba,0x83,0xbb, + 0xd,0x52,0xbe,0x5b,0x77,0x42,0x3f,0x9f,0xf0,0x14,0xdb,0x10,0x45,0x58,0x69,0x4, + 0xa,0x81,0xaf,0xb6,0xd7,0x43,0x77,0x29,0x91,0xb6,0x10,0xd0,0xc0,0x17,0x9f,0xfd, + 0x4e,0x69,0x9b,0xdd,0xa0,0x7d,0x9b,0xb0,0xc8,0x83,0xcb,0xe,0x52,0xff,0x24,0xf, + 0x7c,0xf6,0x84,0x36,0xe,0x74,0xdf,0xf1,0xa3,0x83,0xd4,0x3,0x49,0x82,0xd4,0x1c, + 0x29,0xcf,0xa1,0x46,0xd8,0x6d,0x99,0x7a,0xe3,0x26,0xb4,0x35,0x2b,0xc9,0x19,0xe2, + 0x8f,0x7,0x63,0x92,0x77,0xb5,0x5e,0x8f,0x8b,0x87,0x57,0xf4,0x19,0x59,0xba,0x1d, + 0x99,0x10,0x94,0xe1,0x96,0x9c,0x14,0xc3,0x72,0x43,0xba,0x78,0x4d,0x92,0xb2,0x73, + 0xf8,0x64,0x83,0xe8,0x9b,0xe8,0x9f,0x3c,0x73,0x45,0xe9,0xb0,0x82,0x98,0xfd,0x28, + 0xb,0x52,0x8,0x4,0x3b,0x87,0xe9,0x7b,0xb5,0xdb,0x21,0x47,0xed,0xa5,0xd0,0x65, + 0x90,0xbd,0xca,0x2b,0xa6,0xfa,0x43,0x52,0x4,0x39,0x44,0x53,0xc0,0xcd,0x2c,0xb1, + 0xfb,0x9,0xf8,0xf0,0x31,0x1a,0xc5,0x60,0xd3,0xa,0xa0,0xad,0x25,0xf7,0x9b,0xf2, + 0x96,0xaa,0x5b,0x7,0x0,0x59,0x90,0xc9,0x43,0x7c,0xea,0x53,0x5,0x15,0x4b,0x32, + 0xb4,0xf0,0x9,0x3c,0x83,0x62,0x34,0x7,0xc8,0x23,0x4,0xcc,0xe8,0xaf,0x5c,0x24, + 0x96,0x84,0xe7,0xa3,0x3e,0xbc,0xeb,0x8d,0xc1,0x6a,0x53,0xe6,0x9f,0xf8,0x1f,0x9e, + 0xe6,0xc6,0x5,0xd4,0x2f,0xdb,0x36,0xea,0x6e,0x4a,0xc3,0x44,0xd3,0xa2,0x19,0x8f, + 0xe2,0xd5,0x6d,0xbc,0x30,0x23,0x13,0xdd,0x6e,0xb0,0x52,0x34,0xfe,0x73,0x54,0xb2, + 0xfb,0xcb,0x5b,0xd8,0x33,0xb9,0x69,0x6e,0xad,0xf9,0x1e,0x5e,0x2b,0xf3,0x7c,0x6, + 0x85,0x1a,0xcf,0xc,0x57,0x6a,0x6d,0x91,0x38,0x7a,0x61,0x2f,0x99,0xe6,0x7b,0x4b, + 0xe2,0x3d,0x59,0x1b,0xae,0x2c,0xb8,0x5b,0x93,0xbc,0x13,0x8a,0x51,0xc7,0x77,0x5c, + 0xe,0xee,0x71,0x87,0x4,0xd9,0x1c,0xee,0xd9,0x85,0x3b,0x7d,0x0,0xd1,0xa,0x27, + 0x88,0x24,0xd7,0x6f,0xf6,0x96,0xf9,0x84,0x45,0xfc,0x59,0xa6,0x67,0x76,0x92,0x0, + 0x4e,0xfd,0x7a,0xf3,0x18,0x5e,0xf9,0xdc,0xb2,0x5b,0x37,0x2f,0xb4,0xb0,0x8,0xeb, + 0x73,0x43,0xd2,0xff,0x3,0x0,0x24,0x6e,0xe3,0x57,0x1d,0x7e,0xba,0x3e,0x53,0x7e, + 0x35,0x7c,0x86,0x4b,0x27,0xcf,0x27,0x58,0x7b,0x1f,0xb8,0x7f,0xf4,0x9b,0x9,0xdf, + 0xcc,0x95,0x81,0x52,0x72,0x72,0x36,0x3f,0xb6,0x10,0xe3,0x54,0xf7,0x63,0x6b,0xc0, + 0x2f,0x47,0xff,0xa4,0x88,0xc6,0x37,0x3,0x32,0x45,0xb4,0x4e,0x3b,0xf1,0x6,0x40, + 0xd9,0xe4,0x2a,0x3,0xe0,0x29,0x2,0x41,0x2d,0x73,0x25,0x5,0xe1,0xb4,0x1f,0x50, + 0x9a,0x80,0x46,0x2,0xa4,0x3d,0x1,0x3,0x90,0xfd,0xa1,0x99,0x6,0x1f,0xd,0x76, + 0xfe,0x62,0xe2,0xc2,0x24,0x8f,0x42,0xb4,0x17,0xff,0x62,0x23,0xc4,0xbb,0x8b,0x8d, + 0x76,0x6e,0xc6,0xe4,0x6c,0x3f,0x1c,0xfb,0x45,0x46,0xa8,0xaa,0x2c,0xf2,0x51,0xb9, + 0xc,0x9a,0x56,0xe2,0xa0,0xd1,0xf0,0xc5,0xd2,0x0,0x79,0x18,0xb8,0x43,0xc5,0xa3, + 0x72,0x96,0xa,0xa5,0x3c,0x32,0xd9,0xac,0x68,0x21,0x72,0x2f,0xd7,0x8e,0x91,0xfa, + 0xbf,0x2b,0xb2,0x25,0xb5,0xfc,0xe2,0xcb,0xa9,0xac,0x1b,0xc4,0x39,0xd7,0x5b,0x49, + 0x6c,0xb8,0x9c,0xea,0x28,0xdb,0x4e,0xc7,0xef,0x4d,0x8,0xea,0x43,0x88,0x52,0x18, + 0x39,0x1f,0x3d,0x8f,0x1c,0xba,0xc2,0xfe,0xa,0x3d,0x3f,0x68,0x47,0x4b,0x72,0x52, + 0xe3,0xa7,0x3c,0x5b,0xeb,0xf6,0xaa,0x73,0x72,0x4a,0xfe,0x85,0xc5,0xf0,0x34,0x4c, + 0xdf,0xae,0x43,0x54,0x66,0xb7,0x2a,0x4,0x6d,0x75,0x9e,0x82,0x19,0xde,0xa4,0xd5, + 0x2b,0xc,0x9e,0x77,0xdf,0x74,0xc6,0x90,0x41,0x31,0xdd,0x6,0x93,0xba,0x6,0xe9, + 0xfe,0x33,0xa4,0xe1,0x3,0x85,0xe,0x25,0x4b,0x32,0xbd,0x46,0xa8,0xd4,0xa,0xf1, + 0x80,0x2d,0x19,0x11,0xbd,0x43,0xbf,0x57,0x72,0x43,0x57,0xca,0xf0,0x2a,0x3f,0x70, + 0xb7,0xf7,0x61,0x1d,0xc,0xa,0x17,0x91,0x6c,0xd0,0x85,0xea,0x29,0x31,0x7e,0x21, + 0xc5,0x1,0xa0,0xfb,0x42,0x2c,0x2a,0xdf,0xaa,0xfa,0x2a,0x44,0x5d,0x59,0x4b,0x34, + 0x6,0x25,0x4f,0x58,0x46,0xa4,0x23,0x79,0xc,0x64,0x84,0x76,0x33,0x6f,0x4c,0x2f, + 0xdf,0x6f,0x13,0x5c,0x6,0xf7,0xf8,0xfd,0x4d,0x85,0x52,0xd5,0x2e,0xd9,0xa4,0xc2, + 0x60,0x77,0xb7,0x25,0x67,0x5b,0x94,0x46,0xbf,0xe8,0x5a,0xd8,0xe6,0x8e,0x1f,0x93, + 0xd6,0x6,0x6b,0xc9,0xaf,0x9b,0xbb,0xf9,0x11,0x2,0x79,0xf1,0x5e,0x5,0x79,0x29, + 0x46,0xd6,0x94,0x0,0xbc,0xfb,0x22,0xf0,0xc5,0xb5,0x63,0xf8,0xec,0xbf,0x30,0xad, + 0x6f,0xf5,0x59,0x92,0x20,0x2f,0x80,0xa1,0xfb,0x33,0xb0,0x32,0x50,0x5c,0xe9,0xc, + 0xed,0x2b,0xf7,0x10,0xe1,0x3f,0xab,0x3,0x88,0x5a,0x86,0x8a,0x28,0x6c,0xb,0x5b, + 0x8a,0xc3,0x8e,0x5d,0x4c,0x9,0x4f,0xcf,0xe2,0x58,0x29,0x94,0xd8,0x59,0x65,0x90, + 0xf,0xb2,0xfd,0xed,0x43,0x2f,0x52,0xaa,0xb1,0x88,0x41,0x25,0x36,0x29,0xeb,0x9a, + 0xaa,0xe1,0x49,0xde,0xc2,0x7d,0x37,0x29,0xf8,0x97,0xa5,0x5,0xa4,0xed,0x5e,0x48, + 0x19,0xd7,0x2,0x6d,0xd2,0xa0,0x8a,0x50,0x2b,0xe1,0x0,0x6e,0x75,0xa3,0x42,0x8e, + 0xdd,0xee,0xe,0xc9,0xc0,0xf1,0x76,0xf2,0x5d,0xb6,0x1d,0xe3,0x60,0x34,0xdd,0x4c, + 0x58,0xcc,0x47,0x2b,0x80,0x2e,0x25,0x85,0xdf,0x25,0xed,0x76,0xef,0x15,0xf5,0x3c, + 0xb9,0xf9,0x23,0xd1,0xef,0xc6,0x48,0x60,0x29,0x26,0xa,0x82,0x95,0x5c,0xeb,0x3, + 0xa,0x23,0x33,0x1d,0x89,0xfe,0x16,0xd2,0x41,0xbc,0x4c,0xcb,0xc1,0x3b,0x83,0xfc, + 0x16,0x7d,0xdb,0x22,0xae,0xd5,0xd2,0x1f,0x8b,0x9e,0x5f,0x7a,0x4,0x4f,0xb7,0x93, + 0x50,0xb6,0x1c,0x2d,0x61,0x54,0x6,0x9d,0xe8,0xf7,0xb8,0xc,0xb9,0x3b,0x23,0xc6, + 0x99,0x0,0xe,0xf5,0x4d,0x32,0x35,0x79,0xe2,0x15,0x2a,0xb5,0x6a,0x32,0xbf,0xf, + 0x46,0xfe,0xa2,0x94,0x86,0xb5,0x1e,0x5e,0xda,0xf,0xec,0xb3,0x28,0x1e,0x7d,0xcd, + 0x2d,0x16,0x36,0xa4,0xba,0xff,0x54,0xa2,0x13,0x61,0x7c,0xbf,0xa3,0x74,0xb1,0xd5, + 0x41,0x8e,0x21,0x87,0xba,0xcd,0xba,0xb4,0x9b,0xd3,0x6,0x58,0x89,0xf6,0x2a,0x86, + 0x82,0xc,0xb,0xbe,0xe5,0xe3,0x73,0xe8,0xca,0xd7,0xf4,0x51,0xda,0x35,0x42,0xc0, + 0x75,0x6a,0x30,0xe1,0xc6,0xd4,0xf9,0x4a,0x35,0x88,0x11,0x5,0x79,0x4d,0x83,0x9b, + 0x6d,0xed,0x95,0x68,0xb2,0x1f,0x82,0xa1,0x61,0xc1,0x62,0xdb,0x4f,0x67,0xbb,0xa1, + 0xcf,0x89,0xbc,0x6c,0x33,0xd,0x8b,0x63,0x15,0xa1,0x22,0xea,0x55,0x29,0xa3,0x97, + 0xe,0x8f,0xd5,0x86,0x36,0x7d,0x96,0x5e,0x40,0xa7,0x6d,0x8f,0x29,0xcd,0xae,0xa, + 0x80,0xe1,0xf0,0x6b,0x8b,0xb2,0x67,0xc9,0x47,0x66,0xad,0xea,0x4b,0x14,0xd1,0xd8, + 0xbc,0x5d,0x9,0x8d,0x2c,0xb2,0x7b,0x48,0x2b,0xb4,0x8e,0x49,0x8d,0x2,0xed,0x99, + 0x79,0x13,0x6e,0x86,0xbe,0x37,0x7f,0x56,0x53,0xd1,0x48,0xea,0xbc,0xb1,0x29,0x49, + 0x1f,0xbc,0xdd,0xc8,0x69,0x7f,0xb,0xd9,0xdf,0x1c,0xe4,0xdb,0x23,0xd5,0xd8,0x71, + 0x3b,0x70,0x8d,0xe0,0x91,0xe7,0xf7,0x79,0x12,0x95,0xad,0x24,0x20,0xee,0xa,0x23, + 0xe4,0xbc,0xaa,0xa7,0xdb,0x17,0xae,0x5c,0xd0,0x7a,0x3f,0x8c,0x5f,0x0,0xb5,0x82, + 0x5a,0x62,0xe7,0xb2,0x68,0x75,0x6d,0x4c,0x6a,0x19,0x91,0x76,0x1,0x37,0xbb,0x96, + 0xc3,0x6d,0xc3,0x6b,0xa9,0x5b,0xe7,0xe1,0xb9,0x9c,0x70,0xd3,0x44,0x46,0x9b,0xe3, + 0x78,0x20,0xb5,0x84,0x65,0x87,0x99,0x39,0xd2,0x3d,0xae,0xaa,0x56,0x5f,0xd3,0x54, + 0x0,0xc5,0x0,0xf,0x58,0x4a,0xfc,0xb1,0x7b,0x47,0x47,0xf1,0x85,0x1d,0x6,0xfe, + 0x2,0xec,0x30,0x82,0x7,0x5d,0xa8,0xaa,0x4b,0x30,0xc0,0x69,0x8,0x5a,0x5b,0x15, + 0x96,0x8a,0x34,0x38,0x4c,0xd6,0xb6,0xe6,0x5a,0xa7,0x7b,0xd2,0x78,0xf5,0x87,0xdc, + 0x73,0x12,0xf5,0x2b,0xfe,0x79,0x1e,0x58,0x89,0x35,0x61,0x4f,0x77,0xe1,0xb,0xec, + 0xb2,0x8e,0x2d,0x23,0x71,0xe4,0x11,0xf0,0x4a,0x0,0x71,0x64,0xc1,0xc5,0xf8,0x11, + 0x6f,0xb,0x3b,0x75,0x59,0xe3,0x64,0xd1,0xb1,0x49,0x0,0x3f,0xd5,0x4c,0x2d,0x77, + 0xe9,0xb9,0x9d,0x14,0x6b,0x4e,0x29,0x74,0xdf,0x6,0xa7,0xa3,0x10,0xf2,0xc5,0xd5, + 0xbd,0x6d,0x7c,0x20,0x9e,0x98,0xf2,0x21,0x81,0x53,0x8c,0xbb,0xba,0xe2,0xb6,0xbb, + 0x9a,0x6d,0xd2,0xf2,0xdc,0x88,0x93,0x12,0xd2,0x2b,0xad,0x5,0xe,0x6e,0x48,0xc5, + 0x2e,0x69,0xd4,0x18,0xa,0x20,0x7e,0x63,0x45,0xb7,0x30,0x15,0x3d,0x96,0x67,0x64, + 0x43,0xf0,0xcd,0xd,0x5d,0x27,0x9,0xb,0xa0,0x24,0x34,0xd6,0xed,0xdf,0x70,0xef, + 0x1e,0xae,0xe2,0xcf,0xd7,0x4f,0xc1,0x9d,0x0,0x7f,0x7f,0xeb,0x5b,0xb4,0x2e,0x53, + 0x1f,0x97,0x2f,0xc7,0x1b,0xdb,0x56,0x14,0x11,0xc1,0x9f,0x1f,0x77,0x0,0xe,0x92, + 0xbf,0x11,0xee,0x55,0x42,0x2f,0x64,0xc4,0x2d,0x10,0x83,0x3c,0x88,0x32,0x63,0x92, + 0xc5,0xe2,0xa5,0x4b,0x84,0xf7,0x70,0xda,0x60,0x31,0x10,0xd9,0x57,0x2c,0x28,0x50, + 0x32,0x1,0xc0,0x5,0x3d,0x20,0x62,0xf1,0x39,0xcf,0x7c,0xf0,0xc2,0xd7,0xab,0x2d, + 0xca,0x86,0x47,0x28,0x31,0x58,0x2a,0x63,0xd3,0x8c,0x84,0x9a,0x2,0x9a,0xdf,0x20, + 0x54,0xac,0xc8,0x4a,0x2d,0x5,0xb,0xc6,0x4,0x5f,0x7c,0x68,0xc4,0xd3,0x1c,0x93, + 0x18,0x2,0x4f,0x7e,0x7f,0xa5,0x9b,0x4b,0xcf,0x8d,0x5,0xc9,0xf0,0xd8,0x95,0xce, + 0x43,0xff,0xf5,0x21,0x94,0xa5,0x90,0x68,0xc1,0xd4,0x88,0xba,0x8e,0x1c,0xbb,0xbb, + 0x6e,0x27,0x1d,0xe0,0xa3,0x29,0xd2,0x5e,0x3b,0xc1,0x76,0x9e,0x74,0x86,0x55,0x4, + 0x97,0x17,0x41,0x97,0x15,0xbe,0xcd,0xc0,0x3c,0x8d,0x13,0x5c,0xfd,0x36,0x85,0xf1, + 0xec,0x53,0x24,0x62,0x41,0xa4,0x11,0x28,0x5d,0x59,0x8a,0x42,0x22,0xb0,0x6b,0x36, + 0x67,0x4a,0x23,0xdb,0x35,0xe9,0x58,0xe4,0x67,0xb4,0xd2,0xa9,0xca,0xc7,0x38,0x33, + 0xe8,0x1e,0xe3,0xc3,0x3,0x6b,0x3f,0x1d,0x46,0xd4,0x4c,0x9c,0x52,0xef,0x7b,0xcc, + 0xb7,0x62,0x49,0xc8,0xd0,0x58,0x27,0x2e,0x3e,0xb2,0x8b,0x81,0x85,0x85,0x3,0x4f, + 0x9c,0xdd,0x81,0xa0,0x3a,0x18,0x52,0x5,0x15,0xf5,0xd,0x36,0xaa,0x86,0x70,0x62, + 0x4f,0xd3,0x29,0xb6,0x68,0xb8,0x68,0x78,0xda,0x7c,0xfa,0xf4,0x69,0x83,0xb0,0x4a, + 0xd6,0xa,0xb7,0xe9,0x93,0x20,0x22,0xfe,0x2c,0x32,0x6e,0xba,0x71,0x13,0x80,0xe1, + 0x35,0x35,0xd4,0xf1,0xc0,0x4a,0x82,0x9c,0xa5,0xeb,0xa4,0x43,0x72,0x7e,0x41,0x7e, + 0x20,0xbd,0x24,0x54,0x5d,0xd0,0x65,0x77,0xeb,0x71,0xb9,0xff,0x88,0x5b,0xea,0xcb, + 0x1,0x74,0xb7,0x51,0xb7,0x80,0x9d,0xa4,0x85,0xcb,0x97,0xb5,0x8a,0x9b,0x89,0x6e, + 0xdf,0xfe,0xcf,0x18,0xf4,0x78,0xf2,0xaa,0xf5,0x4d,0x31,0x17,0x5c,0x34,0xfb,0x69, + 0x23,0x42,0xeb,0x80,0x39,0x22,0x18,0x43,0x46,0x31,0x7b,0xbe,0xa2,0xdb,0x9b,0xd7, + 0x3c,0x4e,0x1e,0x5d,0xaa,0x65,0xc0,0x3a,0x53,0xd1,0x3d,0x80,0x18,0x90,0x47,0xc0, + 0x73,0x60,0xd7,0xad,0x6b,0x75,0xb5,0xdf,0x62,0x13,0xfc,0xcd,0x53,0xbd,0x24,0x39, + 0xeb,0x5c,0x24,0x57,0x43,0x75,0x93,0xd5,0xce,0x70,0x9f,0x53,0x21,0x79,0xbc,0xa1, + 0xaf,0x22,0xfd,0x27,0xa4,0xd9,0xe1,0xae,0x90,0xee,0x8d,0x28,0xf7,0x43,0xbd,0x35, + 0x17,0xac,0xa5,0x10,0xf7,0x91,0x85,0x87,0x26,0xa,0x5f,0x36,0x75,0x73,0x87,0xe9, + 0xb4,0x96,0xd0,0x55,0xe5,0xec,0x72,0xcc,0xd0,0x42,0xd8,0xd5,0x73,0x96,0xa3,0x2e, + 0x57,0x57,0xa2,0x23,0xa5,0xe1,0xc2,0xed,0x9f,0x2a,0x70,0x19,0x2c,0x8e,0xb2,0x50, + 0xf2,0x84,0x49,0xbd,0xbb,0x8e,0x3b,0x20,0x12,0x4d,0x4c,0x92,0xb5,0x27,0x99,0x4a, + 0x48,0x7c,0xd8,0x50,0x6a,0x27,0xa3,0x54,0xda,0xaf,0x7e,0xe2,0x34,0x2d,0x99,0xb6, + 0xcc,0xf1,0x1,0x43,0xb8,0x9d,0x8d,0x76,0xe8,0xc4,0x52,0x4c,0xac,0xda,0x5,0xa3, + 0x8f,0xe6,0x13,0x62,0xc6,0xa2,0x8,0x7f,0x36,0x82,0x6d,0xf7,0x87,0x22,0xe0,0x2e, + 0x3e,0x79,0xb,0x3e,0x1d,0x97,0x4d,0x1a,0xf,0x17,0x5a,0x4,0x3f,0x47,0x3f,0xd9, + 0x7d,0x30,0xb7,0x1b,0x80,0x84,0xf7,0x1d,0x7f,0xb4,0x7d,0x2b,0x3,0xe5,0x11,0xf8, + 0xe2,0x98,0xca,0x2d,0xda,0x43,0x3c,0xf5,0x1d,0xb6,0x8c,0xc2,0xa7,0xb6,0xf4,0xee, + 0x3,0xa8,0x40,0xe0,0x16,0x9d,0xe9,0xdd,0x6d,0x59,0xe6,0x5c,0xd9,0x5,0xba,0xf6, + 0xd1,0x87,0xd,0x12,0x43,0xd3,0x96,0xc4,0xc0,0xd,0x65,0xef,0xf5,0xe2,0x3f,0x5c, + 0x5,0xef,0x74,0x4,0xc7,0x3a,0x57,0xb7,0x44,0x9a,0x58,0xc,0x51,0xba,0x36,0xd0, + 0xd,0x4d,0x1f,0x65,0x84,0xe0,0x63,0x73,0xc0,0x3,0x7c,0x5,0x4,0x55,0xcb,0x17, + 0x84,0x3,0x88,0x8e,0xa8,0xf7,0x1,0xaa,0x4d,0xf5,0xe3,0xfb,0xa1,0xfb,0x49,0xcb, + 0x35,0x5c,0x60,0x92,0x50,0xbb,0xe3,0xf8,0x85,0xb0,0x7e,0xfc,0xe2,0x64,0x5e,0x7e, + 0xae,0x53,0xc5,0xde,0x4d,0xde,0x64,0x16,0xca,0xc9,0x3b,0xa4,0xbd,0xb9,0x5a,0xd, + 0xda,0x3c,0x58,0x8a,0x56,0xc3,0xed,0x8a,0xbe,0xae,0x46,0x2,0xe7,0x4e,0x9e,0x13, + 0xdd,0xd8,0x64,0x4,0xf0,0x1b,0xbf,0xc5,0x6d,0x4a,0xb6,0x37,0x51,0xf8,0x36,0x20, + 0x35,0x5b,0x62,0x2d,0x4,0x6d,0x85,0xe3,0x7c,0xb9,0x36,0xbe,0xf6,0xa1,0xfd,0x32, + 0x4b,0x40,0x1d,0x51,0x2d,0xde,0x58,0x37,0x50,0xdc,0xc6,0xa3,0xd7,0xf3,0x38,0xd2, + 0xd6,0x6a,0xd2,0x38,0x83,0x1e,0xe4,0xa1,0x59,0xf9,0xe0,0x51,0x9,0xb7,0xb7,0xe9, + 0x66,0x59,0x61,0x1f,0x9,0x83,0x95,0x1d,0xb4,0x74,0xa8,0x6d,0x15,0xb3,0xd6,0x3, + 0xa3,0x2f,0xf1,0x8d,0x92,0xf6,0x76,0xbc,0x9f,0x20,0x97,0x3c,0xd6,0x49,0xdb,0x37, + 0xab,0x4b,0x5c,0xe0,0x82,0xf4,0xe6,0x82,0x56,0xc,0x2e,0x7e,0xe5,0xf6,0x5b,0x91, + 0x6c,0x1b,0x64,0x2f,0xeb,0x57,0xf0,0x2b,0xd6,0x97,0x2,0xcc,0x3c,0xed,0x91,0x42, + 0x30,0xf0,0x1,0xe2,0xf9,0xd1,0xc8,0x9b,0x50,0xce,0x5b,0xab,0xb6,0x48,0x1c,0x47, + 0xf4,0x46,0xcd,0x96,0xed,0xb4,0xd5,0x97,0x12,0xd,0xa7,0x44,0x80,0xa8,0x53,0x44, + 0x36,0xa4,0x5c,0x30,0xb5,0xbf,0x91,0xed,0x3,0x61,0x7f,0xb7,0x1d,0xc0,0xae,0xe5, + 0x83,0xd2,0x30,0x45,0xe4,0x75,0x46,0xc5,0x88,0xdb,0x1,0x48,0x8b,0x5a,0x4,0x62, + 0x85,0x24,0x76,0x47,0x5c,0x85,0x3b,0xc4,0xb8,0x69,0xb3,0xe1,0x36,0xad,0xf8,0xc6, + 0x92,0xd1,0xbc,0x54,0xf9,0x42,0x5e,0x19,0xe7,0xc2,0x1,0x84,0xf8,0xf,0x5f,0xb9, + 0xe,0x99,0x2e,0x69,0x4b,0x61,0xab,0xd8,0x9e,0xcd,0xb3,0xe0,0xc2,0xe,0xe9,0xba, + 0x13,0x1c,0xff,0x83,0xea,0x48,0xb7,0xe3,0x77,0x5e,0x1d,0x2,0xdb,0x1,0x87,0x31, + 0x2d,0x80,0x3d,0x84,0xf5,0xb8,0xa0,0x94,0x1a,0xba,0x4e,0x82,0x78,0x6c,0x67,0xf8, + 0xe2,0x3f,0x68,0x39,0xa,0xff,0x52,0xe3,0x6c,0x6f,0x1b,0xd6,0xb8,0xef,0xda,0xe8, + 0x2,0xaf,0x1b,0x8a,0x2c,0xdb,0xf5,0x2f,0xa1,0xf6,0x8b,0x58,0x2c,0x93,0x35,0x56, + 0x77,0x67,0xb5,0xb7,0x37,0x1e,0xc7,0x73,0xd7,0xae,0xb6,0xf7,0x8,0x94,0x79,0x24, + 0xa1,0x8d,0x55,0x7,0x45,0x89,0x78,0x50,0xf6,0xbb,0x95,0xa2,0x74,0x91,0x38,0xd9, + 0x5b,0x51,0x44,0x2a,0xd2,0x18,0x2,0x40,0x99,0xbc,0xb1,0xc9,0x3a,0xba,0xaa,0x5b, + 0x95,0x4f,0xaf,0x5a,0x9,0x5d,0x60,0x83,0x98,0x17,0xc6,0xe9,0x5d,0x6b,0x35,0xc6, + 0xeb,0xe3,0xe,0xf8,0xa9,0x4a,0xeb,0x7d,0xe5,0xf2,0xc1,0xea,0xa,0xd9,0xd8,0x49, + 0xd6,0x2a,0xe5,0x5,0x34,0x79,0x8a,0x8,0x7e,0xc4,0x32,0x56,0x7d,0x2c,0x55,0xd9, + 0x69,0x94,0x3e,0x8a,0x74,0x4,0x62,0x50,0xd1,0xe3,0x63,0xe4,0xd9,0xb5,0x6e,0x30, + 0xec,0x24,0x6a,0x9c,0x35,0xc9,0xf6,0x66,0xa9,0x27,0x89,0x34,0xb3,0x2b,0xca,0xf0, + 0xe5,0x18,0x82,0xc7,0x80,0xa4,0x4e,0xda,0x69,0xf8,0x72,0x18,0x14,0xb5,0x1f,0xfc, + 0xf9,0x40,0x78,0xdf,0xec,0x81,0xa3,0xa5,0x28,0xbe,0x96,0x64,0xba,0x81,0xc6,0x4d, + 0xd,0x5c,0xf9,0x7f,0xe9,0x30,0x3f,0xc,0x30,0x9f,0x72,0x63,0x5a,0xfe,0x39,0x6, + 0x55,0xd3,0x81,0xb2,0x53,0x35,0xfe,0x60,0x6c,0xb9,0x4d,0xa0,0x7f,0x34,0x9c,0x62, + 0x55,0x40,0x72,0x2c,0xe0,0x9a,0xb,0x9,0x28,0xde,0x30,0x57,0xb3,0x7d,0xc3,0x22, + 0xb0,0x79,0x60,0x28,0xf0,0xb6,0xe1,0xc,0xdc,0x4c,0x17,0xc7,0x56,0x40,0x0,0x84, + 0x72,0x52,0xa2,0x28,0x64,0xba,0xf6,0x71,0x91,0x2a,0x39,0xf,0xea,0x30,0x39,0x91, + 0x68,0x66,0xb,0xab,0xc3,0xb4,0xde,0x56,0x92,0x42,0xd5,0xe,0x41,0xad,0xf5,0x34, + 0x3d,0x11,0xf6,0xe2,0x1e,0x48,0x1f,0x42,0xf7,0xe3,0x97,0x60,0x11,0x1c,0xf8,0xb1, + 0x69,0x68,0x18,0x70,0x64,0xfa,0xea,0x63,0xce,0x41,0x81,0xeb,0x9,0x77,0x1a,0xd5, + 0x77,0xe7,0xaa,0x9a,0x15,0x5c,0x88,0xd2,0x99,0xdc,0x54,0x13,0x73,0x4,0x4a,0xbf, + 0xa6,0x2e,0xf0,0x5d,0xb0,0x2f,0xe9,0xcd,0x11,0x1a,0x40,0x8c,0x9e,0x64,0xd0,0x40, + 0x6b,0x4a,0x44,0x42,0xb5,0x40,0x81,0xf8,0x2b,0x0,0x33,0x3c,0xe6,0xf6,0x6c,0x99, + 0x29,0x3d,0x9e,0xb7,0x1c,0x9d,0x86,0xcb,0xce,0xf1,0x23,0x5e,0xeb,0x86,0x1d,0xf0, + 0xf1,0x3,0xd7,0x86,0xd6,0x43,0xcf,0x66,0x9c,0xc3,0x9c,0xc6,0xea,0x48,0x9f,0x86, + 0x10,0x3c,0x24,0xb0,0xf4,0xdf,0x7d,0x6a,0xd7,0x56,0xec,0xb7,0x72,0x69,0x4b,0x1f, + 0xa4,0xe1,0xa5,0xb5,0xa8,0x31,0x18,0x11,0xbf,0x69,0x9e,0xfc,0xdd,0x7a,0xd3,0x3f, + 0x30,0x8f,0x7f,0xdc,0x79,0x0,0x31,0xc0,0x95,0x3,0xc6,0xda,0x32,0xf,0x27,0xf4, + 0xb4,0x8b,0xa2,0x9d,0x6e,0x7f,0xff,0xb6,0xc,0xc6,0x69,0xc,0xce,0x66,0x5b,0x46, + 0xf3,0xc0,0x52,0xe9,0xa2,0x1b,0x80,0xc7,0x37,0xd,0xe7,0x90,0xf1,0xf9,0x6c,0xf0, + 0xd8,0x88,0xe,0x45,0xcf,0x11,0x97,0xea,0x11,0xc8,0x1e,0x1d,0xd3,0xb9,0x51,0x74, + 0x81,0x52,0x98,0x52,0x39,0x42,0x93,0xeb,0x47,0x8b,0xd1,0x68,0x3a,0xf0,0x1b,0xe1, + 0xd3,0x2,0x36,0x89,0x3c,0x29,0xab,0xbf,0xb7,0x2e,0x4e,0x1d,0x0,0x99,0x1,0x94, + 0xad,0x0,0x3c,0x7a,0x9a,0x2d,0x2f,0x5e,0x6d,0xe6,0xe2,0xc4,0xd5,0xae,0x60,0xda, + 0x76,0xd9,0xdd,0xcd,0xd2,0xf5,0xdc,0x5d,0x60,0x69,0x2e,0x14,0xb4,0xc9,0x34,0x87, + 0xc4,0x5b,0x64,0xc5,0x93,0x26,0xd1,0x5c,0xc2,0x55,0xc8,0xc5,0x9d,0x44,0x33,0x8e, + 0xfe,0x3c,0xba,0x34,0x7e,0x17,0xd7,0x59,0xff,0x8b,0x51,0x10,0xaf,0x92,0x7c,0xba, + 0xd9,0x28,0x16,0x40,0x87,0xff,0x7f,0x5a,0xc9,0xdb,0x56,0x4a,0x1a,0xb,0x8e,0xdc, + 0xe7,0xe,0x24,0xd3,0xb1,0x5b,0x15,0xc3,0xae,0xd8,0x9c,0x62,0xba,0x62,0x10,0x2c, + 0x85,0xa7,0xde,0x16,0xca,0xe3,0xc,0x3c,0x1a,0x5f,0x37,0x6b,0xff,0x9c,0x4e,0x1d, + 0xf1,0x40,0xcc,0xbc,0x73,0xa2,0x96,0x68,0xbd,0xaa,0x9b,0x3b,0x48,0x6d,0xb3,0x80, + 0x7d,0xe,0xf,0xbd,0x8b,0x83,0x2,0x75,0xda,0xd,0xde,0xe9,0x67,0xc3,0x1,0xf4, + 0x12,0x34,0x5b,0x1f,0x1b,0xfb,0x98,0x45,0xea,0x7b,0xe2,0x94,0xf6,0xea,0xb9,0xdd, + 0x8c,0xd6,0xbf,0x90,0x85,0x47,0xd8,0x79,0xe7,0x43,0xb8,0x24,0xcb,0xe5,0xf4,0xcf, + 0xa7,0xd3,0xd1,0x1b,0x6d,0x1f,0xb9,0xbd,0x36,0x73,0xf0,0x2a,0x86,0x65,0xd4,0x5b, + 0x79,0xed,0x7a,0xe9,0x93,0xd,0xb7,0xa1,0xef,0x29,0xef,0xb9,0xac,0xb8,0x9,0xbd, + 0xe6,0x27,0xbf,0x41,0xb1,0x17,0x83,0x28,0x27,0x90,0xfd,0x62,0x65,0xdf,0x6f,0xbe, + 0x8e,0x45,0x48,0x92,0xa1,0x38,0xbd,0xc7,0x19,0x17,0x66,0xc6,0x9a,0x55,0xb5,0xa, + 0x66,0x6f,0x67,0x3e,0xaa,0x87,0xe9,0xe6,0x45,0x6d,0xd8,0xf4,0x6,0xf5,0xf2,0x3b, + 0x4b,0x71,0x56,0xa4,0x1d,0xb4,0x7d,0x53,0xab,0xf6,0x38,0xab,0x79,0x0,0x2d,0x57, + 0xe1,0x92,0x4e,0xb4,0x63,0x80,0xb5,0x81,0xdd,0xe5,0xc1,0x84,0xb5,0xaf,0xf2,0x42, + 0xb8,0x75,0x43,0x5e,0x6e,0xa0,0x32,0x10,0xa6,0x37,0x68,0x69,0x3a,0x59,0x43,0x77, + 0xe0,0xf6,0x47,0x9a,0xaf,0x90,0x2e,0x79,0x2a,0xaa,0x1e,0xa7,0x35,0x47,0x63,0x62, + 0x84,0xe9,0xdd,0xd6,0xde,0xa0,0xa0,0x8c,0x7d,0x41,0x7e,0x62,0x48,0x75,0x68,0x67, + 0xf2,0xcc,0xf8,0x4e,0x4f,0x7b,0x57,0x46,0xea,0xb4,0x51,0x41,0xbb,0xc2,0xa9,0x5f, + 0x6c,0x7e,0xda,0x91,0xf1,0xb8,0x7b,0xc9,0x2a,0x19,0xfc,0x25,0xc9,0x66,0xa4,0xab, + 0x9f,0x40,0x26,0xc0,0x48,0x4c,0xeb,0xe7,0xdf,0x4e,0x53,0xa7,0x9,0x60,0x85,0x3, + 0xdd,0x6a,0xd6,0xfd,0x5f,0x33,0x3,0x23,0xf,0xe6,0x6,0x3,0x82,0xa5,0x87,0x6e, + 0xb3,0x20,0xbc,0x46,0xd0,0xcb,0x8e,0x2,0x39,0xc,0x20,0x22,0x14,0xb7,0x73,0xa9, + 0xef,0xae,0x22,0x52,0x5,0xc2,0xe2,0x73,0x9e,0xd6,0x3d,0x62,0x41,0x77,0x3c,0xff, + 0xf,0x6d,0xd9,0xee,0x33,0x38,0x49,0xfe,0x99,0x26,0xb9,0x69,0xfc,0x66,0xfb,0xe0, + 0x15,0x98,0x9e,0x3f,0x54,0x4,0x1,0xaf,0x2f,0xe3,0xc9,0x47,0xb0,0xa6,0xe9,0xdf, + 0x3e,0x85,0xc1,0x5b,0x81,0x33,0xbd,0x63,0xbc,0xfe,0x61,0xab,0xa3,0x83,0xc1,0x1e, + 0xab,0xea,0xe,0x5e,0x37,0xc7,0x3c,0xbd,0x54,0x58,0x17,0x10,0x19,0x1a,0x87,0xe3, + 0xd4,0x78,0xc7,0x9d,0xe0,0x8f,0x4,0x9e,0x7b,0xe0,0x5e,0x5,0x9,0x1e,0x93,0x58, + 0xe9,0xe8,0xa9,0x93,0xe1,0x15,0x2,0xa1,0x81,0xdf,0xaa,0x29,0x56,0xae,0xca,0xf6, + 0x2a,0xd1,0x89,0xa0,0x1b,0x20,0xb7,0x20,0xa8,0xc9,0x13,0xd6,0x6a,0x4f,0x6c,0x5, + 0x3a,0x9a,0x9b,0x77,0xe4,0x1a,0xc,0xda,0xb7,0xc4,0xba,0x89,0x32,0x30,0x9d,0x57, + 0x33,0x2d,0x60,0xb,0x91,0xab,0x1d,0xdf,0xc,0x31,0x9c,0xd1,0x5,0xd5,0x4f,0x7e, + 0xac,0x40,0x65,0x78,0xc1,0x7a,0x1,0x3d,0x53,0xe1,0xd8,0xd8,0xc1,0x87,0x9c,0x8d, + 0x5a,0x84,0xf3,0x4f,0xbd,0x20,0xfb,0x91,0x0,0xa5,0x57,0xc1,0x7a,0x58,0x6b,0x38, + 0x66,0xf3,0xb3,0x35,0xec,0x71,0x3a,0x32,0x1a,0x6a,0x93,0x21,0xd,0xa9,0xc5,0xaf, + 0xc9,0x97,0x9c,0xa6,0x29,0x2c,0x4,0x42,0x25,0x2f,0x46,0xc4,0x6c,0x63,0xd4,0x34, + 0xd8,0xd7,0xe8,0x76,0xa8,0x52,0xf0,0x77,0xec,0x9d,0x30,0x78,0xbe,0x66,0xfd,0x22, + 0x8b,0xbb,0x7d,0x75,0x45,0x70,0x75,0x27,0x6d,0xcb,0x1b,0xa7,0xd,0x98,0x57,0x9b, + 0x4e,0x93,0xbd,0x50,0x1d,0x84,0xfb,0x71,0xfe,0xe3,0x31,0x13,0xb,0xb4,0x15,0xd0, + 0xf,0x4f,0x9d,0xd1,0x6e,0x3a,0x63,0x93,0x16,0xc6,0x58,0xc5,0x59,0xd4,0x56,0xae, + 0xf8,0x11,0x11,0x7c,0xcc,0x24,0x6a,0xd0,0x5a,0x66,0x12,0xb9,0x14,0xdc,0xd9,0x33, + 0x68,0x5c,0x71,0xe1,0x8e,0xa4,0xa7,0x11,0xc,0xf0,0x9f,0x9f,0x3d,0xf2,0xcb,0xba, + 0xe,0x3f,0x45,0x14,0x23,0xda,0xc5,0x3c,0x57,0x29,0xcf,0x1c,0x8b,0xbc,0xcf,0x9f, + 0x3c,0x69,0xce,0x31,0xa0,0xfa,0x17,0xda,0xe9,0x5b,0xe6,0xdb,0x36,0x71,0x5a,0xc0, + 0x54,0xfc,0x32,0x9c,0xc9,0x45,0x74,0x39,0xb9,0xda,0x8d,0x7d,0xef,0xa6,0x10,0x2e, + 0xa6,0x19,0xec,0x3b,0x8c,0x1,0xdb,0xbd,0x79,0x46,0xc7,0xea,0x19,0x40,0x1d,0x6a, + 0x74,0x76,0xd4,0x8b,0xd7,0xab,0x63,0xff,0x71,0x1f,0xb3,0x8f,0xa4,0x66,0x32,0xb3, + 0xaf,0xcb,0x23,0x55,0xb3,0xb7,0xf8,0xcf,0x2e,0x5d,0x45,0xe1,0x8f,0x39,0xcd,0x40, + 0x25,0x38,0xb6,0x5c,0x32,0xb5,0x6,0x54,0x7,0x7b,0x81,0x69,0xf0,0x4,0xe6,0x75, + 0x20,0xd8,0xa,0x84,0x65,0xfc,0xdd,0x16,0x1c,0x1f,0x7b,0x78,0xb1,0x56,0xb9,0xba, + 0xa5,0x7a,0x14,0x33,0xc4,0xe8,0x8c,0x80,0x10,0x23,0xf6,0x7e,0x19,0x6b,0xf6,0x8d, + 0x9a,0xe7,0x38,0xe8,0x7,0xf,0xac,0x35,0x53,0x16,0xf8,0x8f,0x86,0x10,0x31,0x83, + 0x53,0x93,0x4d,0x33,0xde,0xb6,0xa6,0xec,0xfe,0x95,0xc3,0x75,0x6,0x34,0xf,0x39, + 0x16,0xa6,0x13,0x1f,0x5,0x83,0xc2,0xc1,0x86,0xe7,0x74,0x6a,0x23,0xa,0x47,0x8e, + 0x22,0xa9,0xb3,0xe2,0xef,0xb9,0x68,0x6a,0x7c,0x5f,0xfe,0xf4,0xb3,0xd6,0xd5,0x5c, + 0x6a,0x84,0x4c,0x51,0x90,0xab,0x45,0xba,0x2f,0xf2,0xeb,0xd3,0x77,0x55,0x6,0x6c, + 0x3d,0x89,0x1d,0xbb,0x3e,0x28,0x19,0x98,0x8e,0xed,0xd9,0x89,0xb3,0x20,0x86,0xc1, + 0xdd,0xa9,0x8d,0x39,0x62,0xaa,0x2c,0x5a,0x35,0x9c,0xb6,0x6,0x1c,0xeb,0xa4,0x2c, + 0x26,0xe,0xf,0xc,0x1c,0x73,0x65,0x7b,0x5a,0xc6,0x30,0x99,0xcd,0x90,0x22,0x53, + 0xfb,0xaf,0x86,0x38,0xc6,0xb7,0xee,0xd7,0xda,0xfa,0xf8,0x9,0x25,0x3,0x3d,0xd7, + 0x6c,0x13,0x58,0x77,0xe,0x62,0xb1,0xd0,0x99,0x75,0x96,0xbd,0x75,0x8c,0xc9,0x4a, + 0x65,0xa8,0xe9,0x69,0x55,0xe7,0x99,0x26,0x53,0x35,0xfb,0x98,0x26,0x65,0xdf,0xd9, + 0xf6,0x1c,0x8d,0x46,0x31,0x78,0xce,0x10,0x74,0x36,0xbd,0xda,0xe0,0x9d,0x8,0x56, + 0x1e,0x6a,0x67,0xdc,0xa0,0x8f,0xc,0x54,0xfb,0xfb,0x32,0xeb,0xf7,0x66,0xf8,0xcb, + 0x18,0x43,0x64,0xa0,0x14,0xff,0x2f,0xae,0x89,0x8,0x77,0x52,0x74,0x84,0x62,0xf4, + 0xbf,0x79,0xec,0x93,0x4f,0xcb,0xe4,0xde,0xde,0xcb,0xd8,0xa0,0x54,0x9,0xb7,0xd3, + 0x89,0xf8,0xc,0xe8,0x2a,0xd0,0xad,0xa1,0xa7,0x39,0x11,0x63,0xc5,0x3a,0x7c,0x25, + 0xf0,0x33,0xb7,0xee,0xd8,0xe5,0xbe,0x6d,0x83,0x28,0x2d,0xe9,0xa8,0xc,0x56,0xe7, + 0x56,0xba,0xf5,0xe9,0x36,0xc5,0xe1,0x0,0xf6,0xfd,0xe1,0x66,0xdf,0x6b,0x36,0xbc, + 0x68,0xdd,0xe9,0xb0,0xf8,0x64,0x1c,0x28,0xb0,0x8e,0xaf,0x54,0xda,0x20,0x23,0x21, + 0x4b,0x6f,0xc0,0x23,0x4c,0xe9,0x34,0x19,0x3a,0x9a,0x46,0x52,0x95,0xcc,0x33,0xb0, + 0x13,0xd,0xee,0xf8,0x2f,0xf1,0x3e,0xea,0x6c,0xe1,0x1d,0xa,0x58,0xfe,0x33,0x98, + 0xf1,0x1a,0x8f,0x3b,0xf2,0x6d,0xc7,0x79,0xed,0x80,0xc6,0x8,0x68,0xf2,0x96,0x95, + 0xa,0x35,0xb4,0x4,0x99,0x99,0xb2,0x63,0xc6,0x77,0xf8,0x6a,0x3,0x74,0x11,0xef, + 0x40,0xfb,0xa8,0xa1,0xf0,0x38,0x64,0xc2,0x3a,0xe7,0xa0,0xfd,0x62,0xc4,0x2b,0xe9, + 0x2a,0x16,0x3e,0x3,0x81,0xd7,0xb,0x8,0xea,0xee,0x7a,0x1b,0xe1,0x5a,0xfd,0x47, + 0xb1,0x1e,0x7d,0xba,0x1,0xea,0x51,0x3b,0x7a,0x4,0xcc,0x95,0xfc,0x9e,0xc6,0xbb, + 0xa6,0x88,0x1d,0xd2,0x15,0xdc,0x53,0x21,0xc1,0x8b,0xdd,0x6f,0xab,0xfd,0xd3,0x6f, + 0xa1,0x66,0xc9,0x1f,0xbf,0x7a,0x95,0xc0,0x4f,0x2b,0x50,0x16,0x29,0x68,0xef,0x5a, + 0x49,0x9f,0x55,0x9a,0x1f,0xc1,0x9d,0x58,0x7e,0x1b,0xc7,0x12,0xbb,0xf,0x7a,0xa3, + 0x0,0x10,0x1b,0x6d,0xf1,0x27,0x38,0xbf,0xf5,0xce,0x2d,0xbe,0xf9,0x58,0x8b,0xf9, + 0x54,0xf7,0x54,0x89,0x84,0x48,0xfb,0x7b,0xa4,0x9f,0xe,0x89,0xb8,0x29,0x36,0xe, + 0x42,0x79,0x1c,0xc7,0xb2,0x3c,0x8,0x12,0xfe,0xf3,0xcc,0xdf,0xd3,0xa3,0x62,0xfb, + 0x72,0x5d,0x15,0x8d,0x87,0x19,0x81,0xd1,0x4a,0x0,0x0,0xe,0xce,0x49,0x44,0x41, + 0x54,0xa,0x6a,0x62,0x2f,0x12,0x33,0x19,0x6d,0x25,0xc5,0x89,0xab,0x5c,0x3f,0x71, + 0x2a,0x88,0x97,0x59,0xc7,0xa6,0xf9,0x23,0x1,0x1a,0xba,0xae,0x96,0xa3,0x1c,0xae, + 0x69,0xd1,0x5a,0x7a,0x2b,0x4d,0xae,0x2b,0x19,0xf2,0x11,0x3,0x82,0x6b,0x11,0x5a, + 0xfd,0x1c,0xac,0x1c,0xd6,0x15,0x81,0x42,0x89,0xf9,0x5d,0x3a,0xb3,0x7e,0xba,0x7b, + 0x2b,0xba,0x37,0xd8,0xdb,0xc0,0xe7,0x8d,0xfe,0xdc,0xd9,0xbf,0xed,0xf4,0x30,0x4c, + 0x67,0xb5,0x4,0x5b,0xd9,0x7a,0x67,0xad,0xf0,0x93,0xed,0xca,0x7f,0xb6,0x1d,0xa4, + 0xc4,0x39,0xaa,0x8e,0xa9,0x26,0x83,0x99,0xe,0x64,0x21,0x5e,0x20,0xb,0xdb,0xc6, + 0x94,0xb,0xb8,0xf2,0x18,0xf5,0x9c,0x50,0x2f,0x68,0xd1,0xea,0xea,0x10,0x97,0xc3, + 0x26,0x8e,0x7b,0x85,0x68,0x10,0xb6,0xc1,0xbf,0x65,0x0,0x52,0x4a,0xb,0xdc,0x71, + 0x6d,0xf,0x3e,0x32,0x93,0xd7,0x6,0x2e,0xb1,0x3,0x3e,0x6e,0xe3,0x9f,0xe5,0xc2, + 0x15,0x4b,0x96,0x15,0xef,0x3a,0x70,0xbe,0x93,0x30,0x1f,0x54,0xab,0xa8,0x80,0xf1, + 0x89,0x34,0xbc,0x7d,0x99,0xdf,0x2c,0x73,0xcf,0x7f,0x45,0xff,0xa1,0x5,0xa2,0xa2, + 0x61,0x67,0x76,0x26,0xf,0xee,0xd9,0xb6,0xfd,0xb8,0x28,0xf5,0xc0,0x53,0x3c,0x40, + 0x2e,0xb,0x82,0xe1,0x8a,0x9c,0x98,0x16,0xd,0xf6,0x9d,0xbc,0xe6,0x8b,0x84,0xea, + 0x23,0xd2,0x2b,0xc9,0x91,0xf4,0xc9,0xba,0xed,0x9f,0x53,0x87,0x39,0x0,0xc5,0x26, + 0xbf,0xad,0x61,0x9d,0xb6,0xb3,0xc3,0x6,0x4c,0x2,0x41,0x55,0x8c,0xa8,0x64,0xe6, + 0x14,0x64,0x77,0xc4,0x20,0x9b,0x7f,0xae,0x97,0xe9,0x35,0xec,0x2c,0x46,0xe6,0x9c, + 0x2e,0xf0,0x1d,0xcb,0xba,0xb3,0xe6,0xa8,0x29,0x39,0x49,0x1b,0xee,0x97,0x14,0x24, + 0x24,0x25,0x40,0x41,0xee,0xcc,0xf4,0x7f,0xcd,0x5d,0xee,0x84,0x74,0xf9,0xec,0x5c, + 0xa6,0x57,0xb0,0x1f,0x91,0xc9,0x7a,0x7c,0xfb,0x0,0xf8,0xc1,0x57,0xf0,0x6d,0x58, + 0xbb,0x68,0x8c,0xea,0xf7,0xdc,0xbd,0x70,0x77,0x6,0x56,0xdb,0x15,0xdb,0x61,0x7f, + 0xc8,0xfc,0xec,0xfd,0xe3,0x6d,0xb6,0x42,0xc1,0xcd,0xdd,0x50,0xb2,0xb5,0x6a,0xfc, + 0xb6,0x3f,0xa5,0xe1,0xab,0x7e,0x1e,0x71,0x4b,0x37,0xd9,0x9c,0x42,0xac,0x5b,0x1, + 0xd8,0x53,0x82,0x32,0xcc,0xa8,0x47,0x59,0x95,0x7a,0x46,0x37,0x3c,0x3,0x71,0x54, + 0xb0,0x21,0xaf,0xdc,0xb4,0xc3,0x8b,0x3a,0x26,0xa9,0xf3,0x88,0x52,0xd3,0xcf,0xf8, + 0x17,0xda,0x1d,0x78,0x50,0x7,0xd2,0x64,0x1b,0x42,0xe,0x55,0x97,0x95,0x63,0xcb, + 0x97,0x99,0x77,0xb8,0x1d,0x3f,0xad,0x64,0x3,0xf0,0xab,0xf9,0x56,0x12,0x27,0x11, + 0xbb,0x11,0xdc,0x6b,0x52,0xcd,0x47,0x41,0x37,0xd2,0xcf,0x5c,0x99,0xbe,0xee,0x20, + 0x13,0x88,0x53,0x39,0xe0,0x26,0x2e,0x14,0x70,0x57,0x6c,0xc0,0x5b,0x39,0x12,0x3a, + 0xd0,0x4d,0x31,0x7,0xc7,0xd3,0x29,0x73,0x5b,0x6b,0xe4,0x4a,0xb7,0xcc,0x36,0x73, + 0x79,0x8f,0xde,0x44,0xc2,0x67,0xea,0x75,0xb3,0xdc,0xb5,0xaa,0x1b,0x8a,0x9f,0x4e, + 0xe0,0x1d,0xe5,0x31,0x1a,0x2a,0x89,0x2e,0xdc,0x41,0xd5,0x47,0x90,0x7a,0x4b,0xde, + 0xaf,0x84,0x41,0xfb,0x98,0xb8,0x3e,0x68,0x3c,0x2,0x1f,0x3c,0x30,0xa,0x31,0xa3, + 0xa5,0x6f,0x81,0xc1,0xed,0xee,0x3f,0x88,0x2f,0x6b,0xd0,0xd0,0x8b,0x35,0xfd,0x65, + 0x6,0xb7,0x7f,0xad,0xed,0x54,0xfc,0x23,0xc9,0x34,0x19,0x1d,0x5b,0xed,0xae,0x67, + 0x3a,0x4b,0x66,0x43,0x41,0xe5,0x50,0xf6,0xd0,0xa6,0x72,0x22,0x89,0xa6,0x1c,0xd8, + 0xb2,0x26,0x2d,0xd9,0x61,0xf7,0x9a,0x96,0x93,0xce,0x34,0xc8,0xc4,0xb2,0x33,0xf3, + 0xb6,0x27,0xd5,0x7d,0x83,0xd1,0x5f,0xd,0x7a,0x14,0x1,0xc,0x4f,0x27,0x41,0x43, + 0x85,0xdc,0xc9,0x97,0x3d,0x1c,0x80,0x10,0x19,0x68,0x8f,0x67,0x78,0xa2,0x20,0x64, + 0xa,0xcf,0x28,0x84,0xea,0xb3,0x42,0x42,0x76,0x7b,0x11,0x8b,0x6d,0x46,0x11,0x71, + 0xa9,0x60,0xa9,0xe6,0x1a,0xe0,0x6d,0xe2,0x5d,0xed,0xc9,0xe9,0xcd,0xa3,0x44,0x67, + 0x6f,0xb4,0x17,0xdd,0x71,0x3d,0x2c,0xbd,0xe0,0x2d,0xf6,0x70,0xee,0xf9,0x6d,0xd3, + 0x62,0xeb,0xf2,0x54,0x85,0x33,0x28,0xe3,0x67,0xd3,0x6,0x88,0xef,0xf8,0x8b,0x29, + 0xd6,0xc5,0xd3,0x5b,0xd0,0x93,0x9d,0x0,0x4e,0xd3,0x66,0xd4,0x68,0x34,0xc0,0xf8, + 0x74,0xc5,0x69,0x97,0x85,0x6a,0x8d,0xb1,0x73,0x7,0xe1,0x99,0x35,0x4f,0x17,0x18, + 0xfc,0xe7,0x30,0x27,0x76,0x14,0xc1,0x63,0xcb,0xb1,0x8,0x83,0xc9,0x58,0x97,0x6, + 0x82,0xba,0xc9,0x3f,0x5d,0xf8,0x2d,0xb6,0xef,0x2,0xd7,0xbf,0x97,0x62,0x1b,0xb7, + 0x15,0x61,0x1c,0x73,0xbc,0x3a,0x3,0x12,0x60,0x81,0xea,0xbf,0x63,0xa6,0xf,0x94, + 0x27,0x4f,0xb4,0x4b,0xec,0x9d,0x79,0x6b,0x4d,0x45,0x84,0xea,0xf6,0x12,0xd,0xed, + 0xd2,0xb6,0xe,0xad,0x28,0x49,0x3b,0x2a,0xc8,0x64,0xd8,0x8b,0x98,0x79,0x89,0xde, + 0x7d,0x0,0x2d,0xec,0xb1,0xf5,0xfb,0x24,0xcd,0xec,0xe7,0x67,0x27,0x85,0xe5,0xd6, + 0xff,0x9d,0x32,0x1d,0xa6,0x83,0xca,0x71,0xdc,0xce,0xf8,0xb4,0xa6,0x4e,0x12,0xd, + 0x7f,0x46,0xa8,0xd5,0xf8,0xb3,0x1e,0xa,0x1e,0xab,0xfb,0xd0,0xa1,0x60,0xc1,0x57, + 0x14,0x2f,0xd3,0xe7,0x2b,0xf5,0xa9,0x1f,0xca,0x9f,0x8c,0xbf,0xd2,0x7f,0x37,0x7b, + 0xe7,0xae,0x16,0xe0,0xe4,0xae,0xc8,0xa4,0x8b,0x0,0xa6,0x89,0xc1,0x99,0x46,0x90, + 0x1a,0xd2,0xd,0x4d,0x90,0x44,0xf8,0xe,0xc2,0xda,0xc2,0xb3,0xa9,0x5f,0x1c,0xbd, + 0xb1,0x4a,0x69,0xd8,0x99,0x8e,0xd1,0xe4,0x8f,0x43,0x12,0xe2,0x22,0x6e,0xa,0xb8, + 0x4a,0x7f,0x2e,0x8e,0x10,0x91,0x67,0x9a,0xd1,0xa1,0x44,0x4f,0x2b,0x81,0xe2,0x1, + 0x20,0xd4,0x89,0x88,0xf8,0xb6,0xe1,0x7e,0x24,0xff,0xeb,0xf3,0x56,0x12,0x94,0x71, + 0x6f,0xc0,0x13,0x5e,0x61,0xd2,0xfd,0x81,0xf1,0xbf,0x81,0x50,0xb8,0xa7,0xde,0xc4, + 0xf4,0xe9,0x48,0x19,0x2b,0x43,0xd3,0x76,0x4a,0xe2,0xad,0xb8,0x65,0x1a,0x63,0xe, + 0xb6,0x7e,0xfb,0x1e,0x43,0xe6,0x4,0x6e,0x67,0x9e,0x89,0x13,0xcc,0x36,0x43,0x94, + 0xeb,0x51,0x4a,0x46,0xd5,0x8c,0xbe,0x7c,0x3b,0x28,0x51,0x6f,0x4d,0x2,0x56,0x8c, + 0xdb,0x42,0xdc,0xd1,0xd2,0x29,0x25,0x98,0x15,0x0,0xf0,0x1e,0xc5,0x91,0x29,0xb0, + 0x94,0x7e,0xdc,0x4c,0x76,0x74,0xc6,0xdd,0xdd,0xd2,0x72,0x10,0x2c,0x98,0x4e,0xed, + 0x35,0x54,0xca,0xfd,0x2d,0x80,0x3e,0xd5,0x28,0x40,0xf1,0x73,0x8c,0xeb,0x53,0xba, + 0xa4,0x74,0x11,0xc2,0xb0,0x60,0xe0,0xac,0xc0,0x47,0x74,0xd3,0x23,0x7c,0xa7,0xa3, + 0xb8,0x4a,0xf6,0xc1,0xe8,0xe2,0x1b,0xe5,0xe7,0x39,0x3c,0x16,0xaf,0xc2,0x1,0xcc, + 0x7d,0xc5,0x60,0xf4,0x25,0x77,0xc1,0xe,0x84,0x8d,0xf8,0xf5,0x6b,0x46,0xff,0xd0, + 0xb,0x5a,0xf8,0xe2,0xed,0x7e,0x2a,0x50,0xea,0xf1,0x78,0x11,0x27,0xbb,0x52,0xfb, + 0xb8,0xcc,0x88,0x9e,0x36,0x45,0x39,0x75,0xda,0x5,0x4,0x6b,0xea,0xf5,0xa4,0x27, + 0xee,0xe5,0x85,0x3d,0x20,0x47,0x32,0xb7,0x3,0x1f,0x52,0x1b,0xb5,0x26,0x33,0x50, + 0x6e,0x71,0x9a,0xcb,0x1a,0xf0,0x8b,0x63,0x75,0x99,0x8e,0x71,0xc9,0xe4,0xd6,0x60, + 0x80,0xdc,0xdb,0xbf,0x83,0x2f,0x31,0xe9,0xe5,0x6c,0x6e,0x21,0xbb,0x96,0xb2,0xee, + 0xd4,0xcd,0x21,0xf5,0x3f,0x3b,0x6e,0x61,0x45,0x65,0x75,0xda,0x77,0x1e,0xed,0xf0, + 0xe6,0x5,0xaf,0x3f,0x7c,0xb,0x81,0x3c,0x47,0xf4,0xde,0x2e,0xb0,0x9a,0x82,0xd7, + 0x53,0x21,0xd7,0xa,0x22,0xc3,0xc2,0xc1,0x2d,0x2f,0x9f,0x59,0x8,0x9c,0x17,0x5c, + 0x60,0x71,0x2a,0x3d,0xf4,0x3e,0x9,0x4a,0x93,0x63,0xf5,0x8a,0x8e,0x52,0x36,0x44, + 0xfe,0xee,0x52,0xc5,0x5c,0xfa,0xb7,0xd1,0xf6,0x23,0xa6,0x86,0x7a,0xaf,0x99,0xda, + 0x6b,0xe,0x74,0xae,0x9b,0xef,0xee,0x43,0x8c,0x92,0x8b,0x36,0x43,0x67,0x39,0x75, + 0xe7,0x4d,0x6c,0xfb,0x14,0x3a,0xb6,0x66,0x7a,0x6,0x74,0x60,0x52,0x14,0xf7,0xc, + 0x50,0xe1,0x7a,0x68,0x40,0x64,0x27,0xdc,0x64,0x92,0x94,0xc9,0x16,0xb7,0x2c,0xd1, + 0xa1,0x54,0xff,0x52,0x3d,0x2,0x1e,0x26,0x93,0x6c,0x1f,0x38,0x66,0x25,0xf7,0x7b, + 0xc,0xec,0xbb,0xf2,0xcf,0x45,0xa3,0x49,0x60,0xbb,0xd6,0xdb,0x26,0x9d,0xac,0xdc, + 0x1,0x14,0x32,0x58,0x18,0x76,0x1c,0x37,0xb7,0xdc,0xb3,0xbf,0x8,0x7a,0xc5,0x7c, + 0xd9,0x87,0x79,0x11,0x45,0xed,0x8,0x2f,0x90,0x1b,0xcd,0xd1,0x7f,0x2f,0x33,0x69, + 0x57,0x32,0x5,0x42,0xf5,0x27,0x97,0x18,0xf,0xd9,0x96,0xb5,0x5c,0xe5,0x67,0xc8, + 0xdc,0x42,0x6e,0x8,0x6,0xb4,0xfd,0x96,0xc7,0x6f,0xae,0xcd,0xf1,0xc7,0xd9,0xd8, + 0x5,0x4f,0xec,0xc1,0x7f,0xe6,0x78,0x46,0x7b,0x8e,0x70,0x96,0x8f,0x51,0xf3,0xb6, + 0xa5,0xd9,0x8c,0x81,0x75,0xe7,0x3f,0xd,0x74,0x87,0xd3,0x76,0xe2,0x90,0xe7,0x3b, + 0xd,0x69,0xf4,0xc,0x23,0xf6,0x38,0xa3,0xd9,0x62,0x36,0xfc,0x53,0xc0,0xef,0x20, + 0x56,0x1e,0x14,0x8d,0x2b,0x33,0x7f,0xd9,0xe1,0xea,0x1e,0x90,0x19,0x6c,0x29,0x3, + 0x15,0xd2,0xee,0x33,0x13,0x46,0xa8,0xe0,0xb7,0xdb,0x84,0xcf,0xac,0xe8,0xf9,0xba, + 0xb,0x81,0x92,0x69,0x6b,0xbc,0x71,0xba,0xcf,0x7b,0xa8,0x18,0x54,0xc5,0x45,0x79, + 0xc,0x24,0x60,0x92,0x98,0x4b,0x5e,0x30,0x9a,0x12,0x37,0x99,0xb3,0x88,0xe9,0xe9, + 0x91,0x1,0xbc,0xf3,0xb8,0xc4,0xd8,0x8e,0x5b,0x55,0xed,0x80,0x29,0xbb,0x9a,0xd1, + 0xcf,0xb4,0x86,0x36,0xc,0x99,0x26,0x80,0xbe,0xab,0x16,0xa3,0xf7,0x8a,0xca,0x22, + 0x20,0xaf,0xf0,0x2b,0x2c,0xdd,0x75,0xa7,0x67,0x4f,0x39,0x46,0xc2,0x8f,0x53,0x18, + 0x2d,0x7,0xd0,0xd,0x6f,0x51,0x7d,0xc8,0x42,0x24,0x4,0x53,0x56,0x64,0xe8,0x86, + 0xe7,0x59,0x15,0xfa,0x80,0xc,0x3d,0xa9,0x46,0xa1,0xd9,0xe1,0xe8,0xc2,0xa6,0xd7, + 0xfc,0x3,0x53,0xae,0x2b,0x32,0x64,0x18,0xa3,0x38,0xd6,0xb8,0x8b,0x15,0x84,0xd2, + 0xa6,0x77,0x88,0xb4,0xcc,0xfa,0x58,0x8f,0xf7,0xed,0xd0,0xc2,0xed,0xd2,0x6e,0xb3, + 0x68,0x9c,0x72,0x88,0xdf,0x61,0xae,0x43,0x93,0x2e,0x96,0xdc,0x6a,0x1c,0x3e,0xb2, + 0xf8,0xa7,0x11,0xec,0x8f,0xb9,0x5a,0x4f,0x63,0xa6,0xc,0xb,0xbb,0xcc,0xfb,0xe3, + 0x3e,0x5f,0xe,0x88,0xc7,0x68,0x68,0x6f,0xf5,0x50,0xcb,0x3b,0x29,0x4b,0x90,0x82, + 0xd9,0xaf,0x5e,0x33,0x96,0x4e,0x89,0x76,0xd0,0x24,0x4e,0xb1,0x21,0x3a,0x39,0xd7, + 0x67,0x7,0xa1,0xef,0x5f,0x66,0x85,0xf3,0xe6,0x2e,0x83,0x32,0x13,0x78,0x20,0x9d, + 0x3,0x7e,0x3d,0xba,0x67,0x28,0x3c,0xf9,0x18,0xc4,0xc0,0xf4,0x4c,0xea,0xfe,0x57, + 0xed,0xae,0x38,0xf3,0xdc,0xa2,0xe2,0x2b,0x55,0x4f,0x2d,0x4a,0x7d,0xf0,0x8f,0x9e, + 0x90,0x71,0xa0,0x64,0xcb,0x93,0xd8,0x32,0xf0,0xcd,0x1e,0x6,0xfd,0xb7,0x44,0xe7, + 0xe7,0xdc,0x3,0x6e,0x2f,0x2b,0x65,0xb2,0xf6,0xd3,0x22,0x74,0x9b,0xe1,0x6f,0x85, + 0x44,0x9e,0x55,0xf2,0xd7,0xa8,0x96,0x2c,0x2,0xba,0x71,0xff,0x4c,0x55,0x7f,0xe1, + 0x60,0xaf,0xce,0xf,0xcd,0xf7,0xc9,0x35,0x73,0x82,0x7d,0xec,0x28,0xa6,0xcb,0x49, + 0xa0,0x80,0x47,0x31,0xfd,0x66,0xea,0xd2,0xed,0x7d,0x83,0x1f,0xed,0x33,0x8b,0xde, + 0xee,0x98,0xb8,0x68,0xcf,0x3,0xfe,0xd1,0x83,0xc9,0xf2,0x83,0x93,0x74,0x49,0xa7, + 0x78,0x7c,0xad,0xe5,0x3b,0x33,0xeb,0x59,0x5b,0x65,0x54,0x76,0xbd,0xeb,0x4,0x3c, + 0x8d,0xc6,0x67,0xca,0x77,0x5a,0x7a,0x9d,0xe0,0x8,0xf6,0xe8,0x68,0x4a,0x83,0x8, + 0x79,0x58,0xdb,0xfb,0xfa,0x82,0x9f,0x99,0x4b,0xdc,0x16,0x5f,0x8e,0x3e,0x87,0x66, + 0xc,0x9f,0xfe,0xc3,0x42,0xf7,0x5c,0xbf,0xbe,0x5f,0xb,0xc3,0xf6,0x82,0xc6,0xda, + 0xf5,0x46,0x4,0x19,0xbf,0xbf,0xe5,0x3d,0xd7,0x3,0x69,0x23,0x35,0xd5,0x97,0xd, + 0xfa,0xfd,0xfd,0xed,0x39,0x97,0xb3,0x89,0xda,0x1c,0x2c,0x17,0x91,0xf4,0x1,0xb0, + 0xde,0xcb,0x54,0x5a,0xb,0x43,0xbc,0x6e,0xa0,0xbe,0xfa,0xc0,0x2c,0x32,0x2a,0x40, + 0x4d,0xd7,0x77,0x65,0xb,0x21,0x66,0x70,0xa5,0xd,0xef,0x58,0xe2,0xdb,0xc5,0x2a, + 0x2b,0x9c,0xc7,0x91,0x1b,0x3a,0xd1,0xda,0xb5,0xdd,0xa6,0x19,0x8f,0xc7,0x7b,0x5d, + 0xe8,0xdf,0xab,0x7a,0x78,0xe6,0x96,0xfd,0x81,0xd1,0x80,0x7c,0x93,0xce,0x99,0x47, + 0xf4,0xc,0xbe,0xf8,0xe7,0xdc,0x5c,0xad,0x93,0x5b,0x73,0x78,0x78,0x6a,0x7b,0x95, + 0x9b,0x6d,0x44,0xc1,0xf7,0xe0,0xb9,0xa5,0x31,0xa7,0xe6,0x34,0x75,0x96,0x68,0x13, + 0xd5,0x37,0xdc,0x2c,0x32,0x1f,0xf8,0x3e,0x22,0x1d,0x3a,0xc9,0xc7,0xf0,0x50,0x4c, + 0x46,0xf9,0x2a,0x53,0x17,0xf5,0xe3,0x4b,0xa5,0xc9,0x6c,0x2c,0xbc,0x7b,0xfd,0xf4, + 0x5e,0x6d,0xf8,0x7d,0x4e,0x65,0x2b,0x7b,0xa8,0x7f,0x19,0xb8,0x9b,0xd,0x22,0xf7, + 0x9,0x2,0x67,0xde,0xc7,0xbd,0x5b,0x69,0xf,0x59,0x15,0xa9,0x36,0x3d,0x8c,0xe2, + 0x3b,0xa7,0xc1,0x6c,0x44,0x9,0x8b,0x72,0x96,0xeb,0x5f,0x3d,0x92,0x9,0x8c,0x3d, + 0x9b,0xdd,0x49,0x35,0x3b,0x24,0x20,0xd1,0x12,0x9d,0x6f,0x59,0x9,0x91,0x56,0x3f, + 0xef,0x64,0xb4,0x99,0x7,0xf9,0x87,0x48,0x34,0xb4,0xd1,0x4c,0xbc,0x44,0xe3,0xf, + 0xc8,0xe8,0xfd,0xf5,0x11,0x10,0x40,0x3c,0x1e,0xa4,0x20,0xc7,0x99,0xe6,0xb3,0x36, + 0xe1,0xb7,0xf5,0xe9,0xca,0x38,0xb8,0x3,0x26,0x38,0x83,0x48,0xb1,0x52,0xbd,0x23, + 0xdf,0xea,0x49,0xaf,0xe,0x30,0x7e,0xdd,0x7f,0x9e,0x19,0x1c,0xf8,0x52,0xc1,0xe0, + 0x1f,0xb2,0x2a,0xde,0x6f,0x55,0xad,0x0,0xa5,0xae,0xcd,0xe4,0xfd,0xd9,0xa0,0xfc, + 0x6b,0xa5,0x70,0x71,0x6a,0xa8,0xc,0x34,0x22,0xfc,0x7a,0xf6,0x8a,0x61,0xc7,0xbe, + 0x2c,0x77,0x17,0x9,0x38,0x4a,0x92,0x94,0xa9,0x3a,0xba,0x57,0x27,0x73,0xea,0xee, + 0xcc,0x6a,0x68,0xd7,0xcb,0x1d,0xbf,0x47,0xd,0xc,0x1,0xe0,0x6a,0x7d,0x9e,0x73, + 0x1f,0x6b,0xb0,0xbc,0x8b,0xf,0x6a,0xa2,0x40,0xe5,0xdf,0xc0,0x1b,0x9d,0xcb,0xc9, + 0x79,0xc7,0x93,0x1,0xc0,0xef,0xef,0xaf,0xaf,0x8,0x4f,0xac,0x1a,0xda,0x4,0x42, + 0x2d,0x66,0xed,0xe3,0x6a,0x35,0xca,0x37,0xb1,0xf4,0x90,0x55,0x97,0x15,0x9,0x46, + 0x6,0xe7,0xf6,0x87,0x9a,0x1e,0x73,0xf0,0x70,0xde,0x33,0xc3,0x1c,0x3c,0x33,0xaf, + 0x30,0x6,0x2f,0x51,0xd6,0x23,0xb2,0xa,0x61,0x3a,0xe5,0xee,0x9a,0x36,0xed,0x7c, + 0x5e,0x3,0xed,0xb,0x73,0xc8,0x7c,0xd6,0x33,0x0,0x6b,0x43,0x56,0xef,0x25,0x9a, + 0x88,0xbf,0xab,0x7f,0x75,0x53,0xd0,0xd5,0x4c,0xb2,0x5f,0x32,0xbe,0xe8,0x2d,0xbe, + 0x4b,0xe,0x67,0xa,0x39,0xf6,0xea,0xc4,0xce,0x8c,0xb1,0x63,0x70,0xf1,0x9c,0x3a, + 0x3a,0x13,0xf8,0x34,0x3,0xfc,0x31,0x18,0x60,0xc6,0xc9,0xe3,0x9,0xa,0x5e,0xc8, + 0x7d,0x77,0x38,0x7d,0x89,0x84,0x71,0x90,0xee,0xde,0x7b,0xce,0xc6,0xaa,0x6e,0x3c, + 0x9c,0xa1,0xc6,0x2a,0x62,0xea,0xed,0xf,0xda,0x67,0x86,0xb8,0x71,0x6a,0xb3,0x19, + 0xcf,0xf0,0x89,0x52,0x69,0xd,0x70,0xed,0xa,0x70,0x27,0x7a,0x61,0x4f,0xf5,0x3b, + 0x9,0xe0,0x75,0xf1,0xa4,0xfc,0x2f,0xda,0x93,0xd,0x3d,0x5a,0x1e,0xd3,0xd2,0x36, + 0x4d,0x4e,0x2d,0x79,0xe5,0x7a,0xf,0x7a,0xe1,0x6,0x38,0x5a,0x20,0xf7,0x93,0x14, + 0x8f,0x65,0x9b,0x9e,0x6d,0x8f,0x94,0xab,0xc9,0xb1,0x4e,0x88,0x6c,0x27,0x7c,0xe1, + 0x6a,0x83,0x3b,0x3a,0x8f,0xc5,0x18,0x55,0x52,0xe6,0xe2,0x28,0x42,0x41,0x2d,0x1d, + 0x11,0x1,0xf7,0x6c,0x7,0x63,0xfc,0xdd,0xba,0x70,0xcd,0xfb,0xe4,0x68,0xc7,0x2a, + 0xaf,0xfa,0xd3,0x6b,0xc,0x61,0x55,0x66,0x93,0xe8,0xe3,0xfa,0x80,0xe2,0xe1,0x98, + 0xd7,0x9,0xeb,0xd3,0x2e,0xc3,0xa1,0xf6,0x98,0x32,0x50,0xae,0xe3,0x1f,0x85,0xcf, + 0x1c,0x38,0x2e,0xda,0x3b,0xe1,0x8f,0xe9,0x7f,0x17,0x1e,0x7b,0xc6,0x31,0x79,0xb, + 0xda,0x39,0xd4,0x34,0x4,0x39,0x1d,0xec,0xae,0xb3,0xf9,0xd2,0x9b,0xce,0xe0,0x5c, + 0x40,0x95,0x29,0x9c,0x81,0xbe,0x5d,0x89,0x47,0x8b,0xee,0xb9,0xb3,0x6a,0xea,0xc2, + 0x77,0x74,0x57,0x35,0x3,0x33,0x67,0xad,0xf5,0x68,0x50,0x18,0x5d,0xb7,0x74,0xa2, + 0x79,0x40,0x7a,0x73,0x8e,0x1c,0xa8,0x75,0xd4,0x69,0x74,0x7a,0x5c,0x3f,0x7f,0xfa, + 0x3c,0x30,0x20,0x81,0xa0,0x48,0x47,0x68,0x78,0x5a,0x53,0x14,0x57,0xd1,0xab,0xe8, + 0xe7,0xe7,0x27,0x16,0xa3,0x73,0x98,0x7,0xd3,0x8c,0xaf,0xcc,0x39,0x9e,0xe1,0x62, + 0x33,0x89,0x73,0x78,0x91,0xfc,0xc6,0x7e,0x2b,0x95,0x99,0x9,0x9c,0x1e,0x12,0xda, + 0xf4,0xd7,0xbc,0xae,0xdb,0x9a,0xee,0x44,0x39,0x5c,0xa4,0x9e,0x61,0xfd,0x47,0x79, + 0xa7,0xe3,0xae,0xf6,0xcb,0x18,0xf,0x3a,0xe8,0x9f,0x8a,0xf8,0x2b,0x9b,0xac,0x8c, + 0xea,0x4d,0x55,0xfe,0x44,0x2a,0x55,0x6f,0x5f,0x2a,0x79,0x7b,0x47,0x26,0xa,0x7f, + 0xae,0x42,0x50,0xad,0x5,0x66,0x19,0xbd,0x48,0x8a,0x88,0xd3,0x3f,0x39,0xcc,0x4d, + 0x44,0xfe,0x1a,0x9d,0x61,0x1f,0x3,0x7d,0x6a,0xe2,0x8d,0x3,0x7e,0x1c,0x67,0x88, + 0x5,0x48,0x64,0x4,0xc0,0x9a,0xc4,0xca,0x2c,0x57,0xd3,0x9a,0x4a,0xa1,0x8e,0x73, + 0x85,0x22,0x7f,0x70,0x87,0x9c,0x34,0x4f,0x2c,0x8d,0xbe,0x1b,0x70,0x87,0x71,0x3d, + 0xe2,0xa5,0x31,0x16,0x36,0xfc,0x85,0x8,0x9a,0xb6,0x4,0x1b,0x34,0xad,0xee,0x6e, + 0x94,0x7,0xd4,0x10,0x52,0x7d,0x1b,0x31,0x70,0x39,0x95,0xee,0xa9,0x33,0x99,0xc5, + 0x80,0x31,0xf6,0xb6,0x79,0xef,0x1b,0xe3,0xc0,0x63,0x14,0x21,0x6a,0x9f,0x9c,0xc1, + 0x1b,0xe9,0x8f,0xa8,0x50,0xcf,0xe5,0x8f,0xb0,0x9d,0xf1,0x87,0x44,0xc8,0x64,0xf0, + 0x11,0x4e,0x48,0x45,0xd9,0xb2,0x90,0xe9,0xef,0x9f,0xb3,0x64,0x16,0x64,0xa5,0x7e, + 0x5f,0xe3,0x72,0xcb,0x59,0xf5,0xd1,0xe5,0xb,0xd,0x9f,0x61,0x34,0xa3,0x4c,0x7f, + 0xc6,0xb6,0xc,0x3f,0xda,0xa6,0x95,0x49,0x66,0x4e,0xbf,0xe5,0x4e,0x0,0x84,0xf6, + 0xd5,0x2b,0xb1,0xbf,0xea,0x9c,0xce,0xc1,0x7c,0xcc,0xd1,0x96,0x51,0x95,0x4c,0x93, + 0x8c,0x2b,0xb7,0x3f,0xcb,0x7d,0x6d,0xf2,0x62,0xa9,0x60,0x9e,0xb1,0xc4,0x15,0x27, + 0x88,0x8f,0x3e,0xf,0x6b,0xd,0x1f,0x8f,0x49,0x4c,0xa3,0x76,0xd3,0x4b,0xf4,0xd8, + 0x39,0xb8,0xfb,0xa8,0xa2,0xa,0x69,0x73,0xf4,0xa4,0x5e,0x94,0x11,0x48,0xb9,0xc0, + 0x26,0x3,0xe4,0xd3,0x7c,0xe7,0xf0,0x47,0xa6,0x97,0x2f,0x6c,0x6c,0xd7,0x86,0x4d, + 0xde,0x39,0x3e,0x1d,0xd6,0x73,0x36,0x6f,0xa,0xef,0x7,0x13,0x49,0x98,0x26,0xcd, + 0x9,0xf3,0x22,0xf5,0x3a,0x7e,0x7f,0xcd,0xbd,0x1c,0xd4,0x6f,0xf,0xd6,0x98,0xc1, + 0x4d,0x73,0x83,0xc8,0x87,0x6c,0xa4,0x59,0x0,0x82,0xbf,0x6f,0xb9,0x3c,0xe6,0x71, + 0x11,0x67,0x79,0xf4,0x0,0xcb,0xd5,0xff,0xcc,0x7f,0x1c,0x25,0x13,0x17,0x6a,0xda, + 0x6c,0x86,0xfd,0x86,0x54,0xbd,0x4e,0x1d,0xed,0x99,0xae,0xd1,0x41,0xed,0x7,0x36, + 0x99,0x9b,0xd8,0x3a,0x99,0x93,0xab,0xfb,0x2b,0xe0,0x9f,0x67,0xd5,0xd4,0xec,0xf6, + 0xc,0xae,0x34,0xf7,0xd1,0x2a,0x9c,0xe1,0x5f,0x8f,0x95,0xb0,0x20,0x92,0xea,0xe0, + 0x20,0x2d,0x6a,0x3a,0xc0,0x95,0x18,0xa3,0x9b,0x3f,0xe0,0x87,0x4b,0xc8,0x42,0xd4, + 0xa9,0x53,0x2a,0xf7,0xa4,0x8f,0x7f,0x2b,0x41,0xa1,0xc2,0x3a,0x9,0xb6,0x1f,0x81, + 0x8d,0x4e,0xa6,0xc6,0x38,0xb9,0xe1,0x8c,0x66,0x94,0x50,0xb5,0x52,0x9a,0x19,0x22, + 0x6c,0x9f,0xf9,0xcd,0xe5,0x1d,0xe4,0x35,0x99,0x6d,0xcb,0x28,0xfe,0xb,0xf5,0x3a, + 0x85,0xf9,0xf4,0x20,0x6c,0xee,0xcf,0x1d,0xb6,0xf1,0x67,0xf3,0x83,0x68,0x81,0xa8, + 0x3,0x55,0x46,0x2e,0xd9,0x57,0xc2,0xb7,0xb5,0x63,0xad,0x20,0x34,0x38,0x1e,0x37, + 0x31,0x83,0x7a,0x9,0x3d,0x50,0x5a,0x69,0xfe,0xd3,0xfe,0x3a,0x7,0x8a,0x29,0xcc, + 0xb1,0xcb,0x24,0xcd,0x5d,0x12,0xc2,0x86,0xf8,0x13,0x6b,0xfe,0xde,0x9c,0x1f,0x75, + 0xd0,0x44,0x13,0x65,0xd0,0xa,0xa5,0x74,0xec,0x59,0xf,0xac,0xfb,0x23,0x77,0x16, + 0xe2,0x3,0x9b,0xf9,0xb4,0x32,0xc4,0x17,0x88,0x9c,0xa1,0x66,0x3d,0xd4,0xe9,0x34, + 0x51,0x13,0xf,0xf7,0xf1,0xf9,0x75,0xff,0xcc,0xbc,0x94,0xbd,0xe4,0x78,0x3b,0xe, + 0xed,0x5d,0xe2,0x7b,0x62,0xf,0x7,0xd3,0xe2,0xfa,0xd1,0x90,0xe4,0x1f,0x7e,0xcd, + 0xfd,0xab,0x63,0x57,0xfa,0x17,0x63,0x4d,0xb1,0xd3,0xb8,0xe,0xd3,0x50,0x90,0x41, + 0x77,0x1b,0x65,0xc0,0xd3,0xf9,0x19,0x99,0xe6,0xf3,0x1f,0xad,0x0,0xcb,0x12,0x9, + 0xd3,0x5b,0x37,0xdf,0x2d,0xbd,0xee,0xdb,0x23,0x92,0x8,0xbb,0x95,0x34,0x93,0xa7, + 0xa1,0x82,0xdd,0x8b,0xc1,0xb8,0x55,0x6a,0x7b,0x6b,0x34,0x3d,0xd6,0xd6,0x7a,0xcd, + 0x2d,0xb4,0x1f,0xfa,0x36,0xe5,0xf6,0xe2,0xf0,0xfc,0x20,0x23,0xe0,0xbe,0xed,0xc4, + 0xa5,0xdc,0xf7,0xce,0xfd,0xb5,0x32,0x8,0x32,0x2b,0x0,0x1e,0x38,0xbc,0x15,0xfd, + 0xb0,0xd3,0xa,0x80,0x6d,0x5,0x98,0x9,0x13,0x33,0x51,0xae,0x52,0x9c,0xe0,0x75, + 0x99,0xef,0xc4,0x7f,0xfe,0x23,0x76,0x1d,0x7f,0x45,0x84,0xa1,0xd1,0x1c,0xdf,0x14, + 0xf7,0x96,0xb,0x12,0x96,0x35,0x65,0x3c,0x30,0xbf,0xcb,0x8e,0x84,0x60,0x41,0x7b, + 0xe0,0xaf,0x41,0x3c,0x3e,0x6,0xbb,0x9f,0xee,0x45,0x4e,0xb7,0xec,0xc7,0x23,0xa1, + 0xe9,0x9a,0x39,0x5d,0xec,0x5a,0xb8,0x9c,0xfd,0xa6,0xfd,0x20,0x9f,0xc,0x7e,0x26, + 0x17,0x9a,0xd9,0xe3,0x42,0x7f,0x27,0x21,0xdf,0x36,0x60,0x74,0x1,0x76,0xc7,0xb6, + 0xf0,0x5f,0x7d,0x43,0xe0,0x1f,0xe4,0xdc,0x88,0x3b,0x85,0xb0,0x82,0x5a,0xfd,0xb5, + 0xb5,0xef,0x8,0x38,0xd5,0x50,0xad,0xf7,0xfa,0x83,0x27,0x4c,0xea,0x3e,0xde,0xc0, + 0xd4,0xdc,0x9e,0x2d,0x81,0x11,0x8d,0xec,0xca,0x4f,0xa8,0x16,0x92,0xbe,0x66,0xb3, + 0x90,0xc4,0x9f,0x2f,0xcb,0x2,0x7b,0x80,0x6a,0x5e,0xc5,0x16,0xb8,0xba,0x7b,0x90, + 0x6f,0x8b,0xc5,0xb4,0x94,0x41,0x90,0xa2,0x8b,0x12,0xa6,0xfd,0x64,0x2e,0xc8,0xe8, + 0x26,0x2d,0xa2,0x2c,0xd4,0x75,0x33,0xe1,0xdd,0x4b,0xda,0x53,0x26,0x44,0x25,0x95, + 0xc7,0x81,0xa,0x81,0xc6,0x1e,0xb6,0x54,0x14,0xf9,0xa0,0x16,0xb0,0x5a,0x2f,0xf3, + 0xb6,0x1c,0x38,0x21,0xb9,0x5a,0x1,0x66,0xdb,0x20,0x27,0x36,0x85,0x22,0x81,0x19, + 0x34,0x71,0xa7,0xed,0x6e,0x29,0x31,0xf5,0x2d,0xec,0x91,0x66,0x50,0xfa,0xfb,0xcd, + 0x74,0x4,0xc5,0x33,0x31,0xfb,0x5d,0xb0,0xcf,0xd4,0xae,0x5d,0x5b,0x93,0x5c,0xc3, + 0x2c,0x2,0xee,0xdc,0xf6,0x66,0xfc,0xab,0x13,0x2e,0x85,0xb9,0x70,0x3c,0x89,0xd0, + 0x7b,0x2f,0x72,0xb8,0x66,0x6f,0xeb,0x4d,0x43,0x10,0x15,0x9f,0x64,0x10,0xfb,0x7a, + 0xac,0xaf,0x3e,0xad,0x44,0x72,0x3f,0x7e,0x78,0x17,0x7c,0xfd,0x6a,0x2f,0xc2,0xd3, + 0x7,0xff,0x1a,0x66,0xc0,0x5,0xaa,0x7d,0xeb,0xda,0x2,0x50,0x45,0x97,0x38,0xfb, + 0xa7,0xc7,0x31,0x9e,0x33,0xf9,0xb7,0xb7,0x60,0xbb,0xfc,0xaf,0xb4,0x3d,0x85,0xa5, + 0xbf,0xbf,0xf1,0xb8,0x2a,0xfd,0x78,0xa5,0x26,0x6d,0xf7,0xa4,0x4c,0xd2,0xce,0xe7, + 0x82,0xb6,0x68,0x8,0xfc,0xba,0xde,0x38,0xe4,0x5b,0x23,0xe2,0x2f,0x35,0xa0,0xb8, + 0xc2,0x51,0x8d,0xaa,0xf,0xb3,0xe4,0x9c,0xf1,0xaa,0x5f,0xdc,0xc6,0xd7,0x41,0xa8, + 0x70,0x98,0x25,0xd5,0x77,0xdc,0xd1,0xfc,0xf2,0xff,0x0,0x3a,0xbf,0x20,0x3,0x59, + 0x9,0x9b,0x6b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // /usr/src/svn/Oxygen/style/imagebase/leftTile.png + 0x0,0x0,0x14,0x30, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x1,0x0,0x0,0x0,0x0,0x20,0x8,0x2,0x0,0x0,0x0,0x72,0xcb,0x31,0xb3, + 0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13, + 0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd7,0x1, + 0xd,0x14,0x26,0x24,0xe8,0x17,0x1b,0x3,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74, + 0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20, + 0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x13, + 0xaa,0x49,0x44,0x41,0x54,0x78,0xda,0x9d,0x5c,0xdb,0x92,0xec,0xb8,0xd,0x23,0x5c, + 0xf9,0xdf,0xcd,0xff,0x3f,0x34,0xf2,0x20,0x92,0x0,0x25,0xb9,0x7b,0x36,0x53,0xc9, + 0xd6,0x99,0x69,0xb7,0x2d,0x51,0xbc,0x80,0x24,0x68,0xfc,0xf7,0x9f,0x7f,0x18,0x11, + 0x88,0x20,0x22,0x8,0x20,0x82,0x11,0x41,0x46,0x0,0x60,0x10,0x81,0x20,0x19,0x40, + 0x44,0x20,0xc8,0x40,0xe4,0xff,0x11,0x11,0x41,0x32,0x22,0xea,0x1e,0x0,0x83,0x11, + 0x1,0xda,0xcd,0x82,0x88,0x75,0x69,0x20,0x10,0xc8,0x2f,0x30,0x2,0x44,0xe4,0x35, + 0x11,0xe0,0xfa,0x84,0x11,0x11,0x58,0x77,0x8f,0xe0,0x5a,0x59,0x2f,0x60,0xdd,0x25, + 0xbf,0x90,0x9f,0x46,0xde,0x33,0x1f,0x99,0x17,0xe7,0xbd,0x89,0x5c,0x4d,0x90,0xe8, + 0xb5,0xd7,0x53,0x7a,0xf9,0x81,0x5e,0x48,0xdd,0xbf,0x9e,0x1,0xfd,0x3,0x44,0x80, + 0xcc,0xab,0x11,0x11,0x60,0x2d,0x8,0xcc,0x4f,0x69,0xeb,0xb7,0xc5,0xa4,0x68,0xf2, + 0x9,0xd4,0x16,0xc2,0x3f,0xeb,0x65,0xa0,0xee,0xca,0xc8,0xa5,0x47,0xa,0xb5,0x1e, + 0x98,0x32,0xa9,0x2d,0xd4,0x79,0xd4,0xfd,0x6a,0x5,0x7d,0xbc,0x29,0xce,0xb5,0xbf, + 0x94,0x2,0x7b,0x23,0x81,0xda,0x56,0xae,0x9f,0x4b,0x5e,0x75,0xd0,0x4b,0x15,0xea, + 0x28,0xc8,0x16,0xfa,0x58,0x3f,0x50,0xc7,0x1b,0x44,0x4a,0x4e,0xfa,0x93,0x57,0x33, + 0x75,0x6e,0xdd,0x88,0x2e,0x74,0xb6,0x64,0x6b,0xfd,0xb6,0xe8,0x5a,0x58,0xb4,0x76, + 0xb1,0xbf,0x96,0xab,0x90,0xfc,0x75,0x66,0xad,0x85,0xa9,0xcc,0x26,0xe4,0xa7,0x9f, + 0xd0,0xda,0x45,0xb6,0xf6,0x93,0xe0,0xfa,0x8b,0x6e,0x12,0x20,0xa1,0xe5,0xb6,0xca, + 0xf8,0xbe,0x53,0xb1,0xc9,0x8,0xae,0x53,0x6b,0x8d,0x63,0x7e,0xcd,0x8f,0xa3,0x2f, + 0xab,0x73,0x47,0x99,0xe,0x25,0x45,0xdd,0xe,0x20,0xc1,0x75,0xee,0x79,0x7c,0xad, + 0x3d,0x4c,0x71,0xa6,0xea,0xaf,0xbf,0xd7,0x65,0x69,0x22,0xeb,0x48,0x90,0xd2,0xc7, + 0xfa,0x59,0xeb,0x43,0xe9,0x6,0xf2,0xe9,0xb9,0x91,0xb5,0x3a,0x94,0x31,0xc8,0xb0, + 0x75,0xfc,0xa9,0xe,0xac,0x1d,0x48,0xa1,0x91,0xc2,0x4f,0x5f,0xd2,0xc6,0x4f,0x69, + 0x69,0xea,0xdc,0x5a,0x52,0xa9,0xfe,0x92,0xe3,0x52,0x7f,0x94,0xc2,0xa7,0xdd,0x72, + 0xad,0x3f,0x9f,0xf,0x20,0x8d,0x2c,0x37,0x4f,0xdd,0xa1,0x8e,0xe,0x92,0x7,0x6c, + 0x1d,0x69,0x45,0xb9,0x55,0x90,0xc1,0x40,0xda,0x55,0xda,0x30,0x6a,0xbd,0xeb,0x53, + 0xf6,0xa2,0x5a,0x5e,0xeb,0xbb,0xf9,0xb,0x4b,0x5a,0x1,0xa2,0xe,0x48,0xe7,0x99, + 0x5a,0x9d,0x5a,0xbe,0x6c,0x2c,0xf5,0x7,0x69,0xde,0xeb,0xf2,0xa5,0x50,0x84,0xbe, + 0xb4,0xe,0xca,0xce,0x7a,0xc9,0xb,0x65,0xff,0xac,0x33,0xab,0x5,0xb7,0x9a,0xd5, + 0x1,0xe8,0x73,0xe6,0x99,0x3d,0xe5,0xaa,0xd0,0xfe,0x17,0xd3,0x5b,0x97,0xc2,0x84, + 0xf9,0xe6,0xd6,0xf,0xa6,0x98,0x6c,0x53,0x44,0x3f,0xa9,0x8e,0x3e,0xf2,0xa0,0xb4, + 0x34,0x73,0xb0,0xc1,0xd4,0xbf,0x7c,0x5c,0x70,0xf9,0x84,0xba,0x5e,0x1,0xc3,0x37, + 0xdf,0x77,0x21,0x0,0xb4,0x10,0xf3,0x44,0xda,0xe5,0xa0,0x6f,0x8a,0x70,0x43,0x62, + 0xde,0x96,0xa5,0x43,0x4c,0x3d,0xe8,0x53,0x2c,0x41,0x30,0x5a,0x8,0xb2,0xf6,0x72, + 0x5a,0xac,0x8,0x55,0xaa,0x5f,0xc6,0x49,0x66,0x28,0x58,0xda,0x4b,0xbb,0xc,0x50, + 0xcc,0x2b,0x2f,0xd1,0x87,0x92,0x9e,0x21,0x17,0x18,0x76,0x3d,0x41,0x39,0x91,0x76, + 0xfb,0xe6,0x46,0x96,0x72,0xe7,0xa3,0x40,0x5a,0x68,0x85,0x5c,0xa4,0x9c,0x1c,0xb8, + 0x62,0x4b,0x45,0x57,0x90,0xa0,0xdc,0xe5,0x92,0xb,0x2b,0xf0,0xd4,0x97,0x59,0x2e, + 0x82,0xf2,0x63,0x2b,0x1c,0xb0,0xdd,0x9d,0x76,0xd3,0x61,0x3e,0xad,0xd9,0x2,0x5f, + 0x74,0x20,0x20,0x4b,0xa4,0x6c,0x80,0x51,0x3e,0x53,0x87,0x1f,0xcb,0x38,0xc9,0xb4, + 0x89,0x3a,0x10,0x12,0x2c,0xe7,0x9b,0xf1,0x18,0x1c,0x86,0xcd,0x32,0x49,0x94,0x20, + 0x48,0xb0,0x76,0xf0,0xf4,0x69,0x92,0xb9,0x3b,0x9a,0x11,0x51,0x87,0x1e,0xc4,0xf2, + 0xc6,0xcc,0xc7,0xba,0xce,0x13,0xb9,0x1,0xa1,0x98,0x8a,0x50,0x8d,0x72,0x96,0x24, + 0x90,0xa7,0x9b,0xab,0x2,0x53,0xad,0xd7,0xdd,0xd3,0x68,0xb,0x86,0xb5,0xdf,0x67, + 0xa,0x60,0x89,0xa4,0x85,0x99,0xe8,0x8c,0xa1,0x2d,0x44,0xef,0x2d,0x58,0x2e,0x90, + 0xac,0x75,0x41,0xaa,0xdd,0x46,0xb6,0xbe,0xbe,0x80,0xcd,0xa,0xa1,0x6b,0xf5,0xe5, + 0x58,0xd2,0x59,0x2b,0xe6,0xb5,0xe6,0x61,0x59,0x96,0x2c,0x35,0xef,0x1,0x41,0xc0, + 0x15,0x45,0xdb,0x4b,0xb6,0x4f,0x46,0xb9,0x11,0x24,0x12,0xe0,0xe,0xbd,0x98,0xb, + 0xcb,0x33,0x48,0xaf,0x8c,0x74,0xd2,0x85,0x3a,0xd2,0x27,0xb3,0xc2,0xc7,0xf2,0x2, + 0x8,0x93,0xa1,0x61,0xb0,0x3c,0x8d,0x14,0x1f,0x1a,0x2,0x39,0x8e,0x65,0xa1,0xae, + 0xb5,0x6d,0x50,0xd8,0x24,0x9f,0xd4,0xa1,0xb,0xa5,0xc,0xa6,0xd3,0x8a,0xd5,0x65, + 0x4,0x8c,0x65,0x59,0x69,0xa3,0x69,0x75,0x75,0x86,0x68,0xa4,0xd7,0x5e,0x57,0xb8, + 0xb3,0xdd,0x35,0x7,0x78,0xc,0x3,0xb0,0x86,0x43,0x98,0x2e,0xa8,0xf7,0x9f,0x91, + 0xc9,0xd1,0x6c,0x3f,0x9,0xcb,0xe8,0xf1,0x9f,0xe1,0x8e,0xd9,0x81,0xbb,0x42,0xdc, + 0x72,0xdf,0xd,0xda,0x89,0xbe,0xa4,0x43,0xac,0xb0,0xf1,0x8,0x3a,0x94,0xfe,0xb0, + 0xe,0x59,0x39,0x40,0xc2,0x48,0x8,0xf9,0xd0,0x4f,0x3f,0xb6,0x9b,0x98,0xd3,0xec, + 0xd8,0x18,0x3,0x53,0x5b,0x78,0xa2,0xf4,0x63,0x21,0x28,0x16,0x2c,0xb4,0xac,0xa3, + 0x42,0x46,0x6d,0xa6,0x97,0x91,0x2e,0xa8,0x9c,0xaf,0xdc,0x6c,0x7a,0x55,0x3a,0x2e, + 0xcd,0xbc,0x29,0x3f,0xf1,0xd3,0x5b,0x90,0x87,0x8d,0xf2,0xfb,0x11,0xa0,0xb,0xcf, + 0xcf,0x6e,0x4,0xc7,0x84,0x25,0x6c,0xcb,0xcd,0x67,0x38,0x58,0xd7,0xad,0x2a,0x1d, + 0x72,0x60,0xea,0xf9,0x4c,0x1a,0x2d,0x6,0x16,0x48,0xa0,0xcd,0xce,0xd0,0x4c,0xf, + 0xca,0x50,0x74,0x8d,0x34,0x6f,0x41,0xe9,0x99,0x3c,0x29,0x79,0x68,0x91,0xd2,0x21, + 0x31,0xb,0x11,0x8,0xf0,0xe7,0x41,0x55,0xa0,0xcb,0x2c,0xad,0x7f,0xc9,0x35,0x2f, + 0x4b,0x4b,0xb4,0x9b,0x8e,0x9e,0xa6,0x0,0x29,0x98,0xf6,0xee,0x7d,0xfc,0xd2,0x8f, + 0xdc,0x43,0x27,0x33,0x34,0xc7,0xd5,0x39,0x40,0x7b,0x4c,0x48,0xfc,0x9d,0xa0,0xb2, + 0xd1,0x63,0xa5,0x94,0x80,0x54,0x9b,0xa,0xdd,0x79,0x2c,0x65,0x74,0x50,0xd0,0xb5, + 0x90,0x6d,0x60,0xac,0x23,0x4b,0x78,0xa6,0x9c,0x58,0x76,0x39,0xf3,0x99,0x15,0x96, + 0x5c,0x69,0xd9,0xd7,0x6,0xa8,0x58,0xbe,0xd5,0xf0,0x89,0x41,0x41,0x6c,0xc8,0x57, + 0x6,0x1b,0xee,0x64,0x94,0xdf,0xb3,0x23,0x64,0xba,0x43,0xb4,0xea,0xc1,0x40,0x8c, + 0xe1,0x11,0x76,0x82,0xda,0x5e,0x10,0x15,0x8f,0x4a,0xed,0x6a,0x8f,0x99,0xb7,0xc5, + 0xb1,0x40,0x57,0xe1,0xe5,0x3c,0x91,0x19,0x5e,0xa3,0x87,0x14,0x3e,0x39,0xf0,0x64, + 0x67,0x13,0x92,0x2f,0xa,0x49,0x11,0xee,0x31,0xca,0x8d,0x46,0xa2,0xd,0xe5,0x77, + 0xae,0x11,0x8a,0xf5,0xa9,0x43,0x79,0xde,0x1,0x5f,0x36,0x5,0xbe,0x25,0xe0,0x5a, + 0x4c,0x5,0x4,0xea,0x24,0xcc,0x76,0xb,0xed,0x41,0x49,0x1e,0x2d,0x25,0x96,0x67, + 0xa3,0xea,0x2e,0x96,0x34,0x56,0xb6,0x97,0xf6,0xc2,0x98,0x4b,0x72,0xd3,0x2e,0x93, + 0xb,0xb2,0xb3,0xa5,0x27,0x30,0x11,0x1b,0xad,0xa4,0x12,0x1d,0xf4,0x26,0xea,0x26, + 0x54,0x5b,0x30,0x88,0xc4,0xa,0x97,0xe5,0x6e,0x38,0xf3,0xc2,0xe8,0x14,0xa1,0x75, + 0x28,0xcb,0x32,0xc7,0x92,0x69,0xa7,0x9,0x5a,0x16,0x96,0xc2,0x97,0x9b,0x1c,0xc7, + 0x20,0x4c,0xe3,0x16,0x15,0x8d,0x40,0x2b,0x1f,0xee,0x4,0xb8,0x8a,0x48,0x5,0x21, + 0x54,0xe0,0x8,0x47,0xd0,0xa,0x80,0xf0,0x80,0x3f,0x4d,0xb3,0x33,0xe2,0x8e,0x90, + 0x7a,0x98,0xf0,0xac,0x72,0x70,0x2a,0x7b,0x77,0xf5,0xa9,0xd4,0xb2,0xf2,0xd8,0xd, + 0x1e,0x54,0x46,0xa0,0x7a,0x4f,0x2a,0x6e,0x1d,0x81,0x6a,0x3f,0xf9,0x60,0x90,0x9c, + 0xea,0x0,0x37,0x10,0xc6,0x94,0xe9,0xca,0x97,0xd1,0x27,0x8f,0x91,0x88,0x41,0x91, + 0x9a,0xee,0xf1,0x61,0xdb,0xc7,0x38,0x44,0x3,0xa4,0x7d,0x0,0xe9,0x96,0xfa,0x4e, + 0x28,0x8,0x21,0xf8,0x9b,0x46,0x80,0xaa,0x60,0x41,0x76,0x43,0x81,0x26,0x4c,0xe0, + 0x0,0xcf,0xec,0x43,0x41,0x21,0x25,0x41,0x4b,0x87,0x2a,0x6d,0x7a,0xe2,0xf6,0xc3, + 0x60,0xec,0xe9,0x2a,0xa6,0xeb,0x70,0x88,0xb6,0xea,0x7,0x76,0x10,0x16,0xe2,0xf5, + 0x5,0xaa,0x98,0xc6,0x5b,0xd0,0x9f,0x3f,0x9d,0x3f,0x47,0xe5,0x26,0x30,0x37,0x6b, + 0xe9,0x6c,0xbb,0x28,0xfd,0x19,0xdb,0x66,0xca,0x1c,0x3b,0xc6,0x96,0xcf,0x6e,0xdf, + 0x9d,0x11,0xaf,0x92,0xe9,0x2c,0x3d,0x56,0x6d,0xa0,0xc2,0x2c,0xa6,0x9e,0x58,0xfd, + 0xae,0xea,0x62,0x6,0x91,0x98,0xf9,0x84,0xf2,0xb3,0x76,0x13,0x5c,0xe2,0x6a,0x0, + 0x8c,0x29,0x8a,0xa,0xf4,0x9b,0xeb,0x81,0x0,0x7d,0xc6,0x16,0x19,0x48,0xa1,0x23, + 0xb0,0x93,0xab,0x75,0x28,0x88,0xe1,0x6a,0xe9,0x5a,0x4f,0xcb,0xf7,0xc3,0xa,0xd0, + 0x6e,0x86,0x18,0xf1,0x7f,0x84,0x86,0x97,0x83,0x73,0xbb,0xe1,0x76,0x21,0x62,0x38, + 0xd6,0x34,0xe9,0xc0,0xb0,0xcf,0xa,0x57,0x5,0x95,0x39,0x90,0xc4,0x48,0x3e,0x1b, + 0xeb,0x74,0x7d,0x3c,0xba,0xc,0x22,0xdd,0x57,0xe4,0xeb,0x8,0x5c,0x38,0x87,0xf1, + 0x5c,0xf6,0x82,0x2e,0xa8,0xec,0x7a,0x64,0xa6,0x6,0x5a,0x49,0x27,0x13,0x21,0x64, + 0x21,0xcd,0x23,0xc8,0x0,0xa2,0x61,0xe0,0xab,0x9e,0x71,0xc5,0xfe,0x55,0x1e,0xe7, + 0x2c,0x5f,0x97,0xaa,0x59,0x4c,0xb,0x4b,0xa1,0x42,0xd0,0x78,0x2a,0x63,0x22,0x7b, + 0xa1,0x74,0x33,0xde,0x8a,0x63,0x69,0x2,0xf2,0xf0,0x6c,0x89,0xd3,0x93,0x84,0x68, + 0x70,0xd8,0xa5,0x7a,0x6e,0x88,0x45,0x86,0x48,0xcb,0x55,0xdc,0xab,0x50,0x62,0x1b, + 0xb0,0xdf,0xb2,0x21,0xc6,0x28,0x9b,0xc8,0xfa,0x15,0x32,0xb6,0xd0,0x59,0x66,0xd5, + 0x61,0xd3,0x51,0xb8,0x57,0x82,0x78,0x1c,0xb0,0x37,0x21,0x46,0xfc,0x75,0xed,0xc5, + 0xdc,0xe7,0x30,0x5b,0xcf,0xe1,0x31,0xc5,0x75,0xd3,0x21,0x38,0x50,0x8a,0x1d,0xc4, + 0x79,0x75,0x3d,0x8b,0xaf,0x8c,0x51,0x92,0x68,0xa7,0x97,0x88,0x18,0xa7,0x6d,0x26, + 0xc6,0x35,0x7d,0xa1,0x15,0x47,0xda,0x60,0x9e,0xd3,0xed,0xa,0x62,0xc6,0xf5,0xc3, + 0x60,0xd7,0x8,0x8e,0x94,0xb5,0xcb,0x78,0xe0,0x65,0xeb,0x89,0x3a,0xb8,0x41,0x95, + 0xd1,0xf6,0xd9,0x70,0xa4,0x7c,0x69,0xa8,0x94,0x7c,0x3c,0x35,0x54,0x8c,0xe1,0xab, + 0x8b,0xe2,0xc8,0x46,0x74,0x45,0x37,0xa4,0x60,0x11,0xb4,0xb1,0x9b,0xbb,0x46,0xcb, + 0x17,0x78,0xe0,0xcc,0x5b,0x9c,0xb7,0x33,0xe5,0x25,0x36,0x9,0x54,0x2a,0x79,0xc0, + 0x16,0x81,0xbb,0xaa,0xe1,0xd7,0x67,0xb9,0xfc,0x2a,0x89,0xc6,0x30,0x2a,0x66,0xce, + 0x1c,0x4a,0xad,0x9,0x7,0x58,0x77,0xa1,0xe1,0xb8,0xfb,0xb6,0xf8,0x33,0x30,0xe0, + 0x5b,0x78,0xa8,0xc2,0x35,0xc7,0xaf,0x1e,0x54,0x5d,0x83,0x4f,0xbd,0xee,0xba,0x11, + 0xf,0xb7,0x4c,0x5b,0x2d,0x46,0x81,0x79,0x84,0xc,0x6c,0xba,0xf5,0xc4,0x66,0xe2, + 0x97,0x53,0xbd,0x84,0x0,0xbe,0x22,0x17,0x74,0xf1,0xc4,0x30,0x5c,0x5c,0x12,0xbb, + 0xb7,0x7,0x70,0xa6,0x2d,0xa5,0xd4,0xbc,0x3d,0x93,0x1e,0x31,0x1a,0x76,0x7d,0x93, + 0x7e,0xbc,0x1,0x2f,0xc7,0xc1,0xf6,0x6f,0x3f,0x2b,0xfc,0xe5,0xce,0xa7,0xb3,0xe3, + 0xe,0x4d,0x37,0xd,0x73,0xd8,0x74,0x51,0x42,0xf2,0xa6,0x66,0xdc,0xef,0x4,0xdc, + 0x10,0x8a,0x3c,0x29,0xb7,0xd2,0xf2,0xc8,0x16,0x77,0x4b,0xc0,0x50,0x64,0x9c,0x96, + 0xbb,0x21,0x55,0x5f,0x37,0xbf,0x5e,0x1a,0xdd,0xa9,0xfd,0xa1,0x4b,0x6c,0x4d,0xfc, + 0xc4,0xe8,0xd4,0x93,0x5b,0xae,0xb8,0x75,0xa9,0xf6,0xe3,0xfd,0x70,0x74,0x9f,0x18, + 0x5e,0x89,0xa,0x3c,0xe6,0x9f,0x67,0x45,0xee,0xdf,0xff,0x54,0xed,0x4a,0x6d,0x22, + 0x5e,0x8f,0xf4,0x1a,0x1b,0xde,0x8d,0xee,0x42,0x4f,0x38,0xf5,0x8c,0xe6,0x91,0xf8, + 0xfd,0x59,0xef,0xeb,0xb9,0xa4,0x3c,0x2e,0x8d,0xff,0x47,0xfd,0xf,0xe7,0xb4,0x3d, + 0xe3,0xb6,0x98,0xa3,0x5b,0xc8,0x3f,0x2c,0x81,0xf3,0xc6,0xd8,0x50,0x37,0x7f,0xac, + 0x1e,0x3,0xc7,0x4d,0x6f,0xb0,0xf9,0x86,0x17,0xaf,0x67,0x8,0xee,0x7e,0xed,0x77, + 0x49,0xe2,0x48,0x31,0x70,0x26,0xe,0x77,0x4d,0xc0,0xb1,0x66,0x7f,0xc4,0x73,0xc6, + 0x2a,0x5f,0xe9,0x73,0x88,0x1c,0xf8,0xfb,0xf9,0x4e,0xc3,0x43,0x60,0xfb,0xfd,0x65, + 0x93,0xfc,0x22,0x9c,0xe3,0xb3,0xcf,0x1,0xe8,0x63,0xd7,0x21,0xce,0x52,0xc,0xae, + 0xe1,0xf9,0xd5,0x5d,0xbe,0x1c,0x42,0x78,0x35,0x11,0x47,0xbc,0x7e,0xd5,0xd1,0xb3, + 0xa1,0x75,0xe0,0x85,0x72,0xc0,0x57,0xc,0x79,0x14,0x34,0xb6,0x8a,0xf2,0xcd,0xeb, + 0xc4,0xa1,0x7a,0x3c,0xb3,0xba,0x1f,0x26,0xbc,0x3d,0x1,0xb7,0xfd,0x20,0xf0,0xe2, + 0x23,0x39,0x32,0x9c,0xed,0x16,0xb8,0xc4,0xeb,0x9b,0x80,0x38,0xd6,0xc2,0xf9,0x60, + 0xdc,0x6e,0x64,0xbf,0x3e,0x54,0x5b,0x67,0x22,0xae,0xaf,0xde,0xe6,0xad,0xa,0xb4, + 0x1,0x9e,0xad,0x64,0x83,0x51,0xb8,0xc3,0x56,0x7b,0xc5,0x5b,0x1c,0x14,0xbb,0xe1, + 0x35,0xa4,0x5e,0x95,0x90,0x1d,0xb9,0x78,0x74,0xc9,0xa8,0xae,0x4,0x47,0x1e,0x76, + 0x2,0x6e,0x1e,0x65,0xcd,0x1b,0x8,0xe2,0x8c,0x97,0x1c,0x3b,0x84,0xb7,0xc9,0xb1, + 0xc5,0x1c,0xbe,0x23,0x69,0x86,0x6f,0x1d,0x8f,0x50,0xf8,0xe8,0x84,0x79,0x66,0x8a, + 0xdd,0xc0,0x78,0x46,0x46,0x7a,0x22,0xce,0xc0,0xb7,0xf0,0xcd,0x6b,0x7e,0x35,0x92, + 0xea,0x5f,0x61,0xae,0xa1,0xc3,0x13,0x97,0xbe,0xdd,0x25,0xdc,0xcd,0xd5,0xe2,0x16, + 0xe4,0x68,0x96,0x99,0x4d,0x6e,0xde,0x92,0xaa,0x5b,0x6c,0xe7,0x9e,0x8d,0x70,0xd6, + 0x60,0x23,0x6,0x81,0xea,0xa2,0x7a,0xe4,0x73,0x5,0x4,0x98,0x10,0xa0,0x41,0xbd, + 0x52,0x5f,0x58,0x4a,0x3d,0xba,0x38,0x4a,0xbe,0x76,0xce,0x4f,0x8a,0xe9,0x33,0xc0, + 0x2e,0xad,0x65,0xbf,0xa7,0x9a,0x97,0x26,0xaf,0xb3,0x79,0xda,0x29,0x20,0x9c,0x21, + 0xfa,0x8a,0x1c,0x9a,0x84,0x53,0xe5,0x1d,0xe1,0x3,0xe7,0x12,0xc0,0xa8,0x7a,0x86, + 0xe2,0xba,0x72,0xa6,0x3a,0x63,0x3c,0xa0,0xc8,0x73,0x5f,0xb4,0x87,0x5e,0x40,0xe8, + 0xe7,0xb1,0xf8,0xab,0xe2,0x5b,0xf2,0xa5,0xea,0x70,0xfd,0x68,0x54,0xdc,0x89,0x26, + 0x57,0xf6,0xe5,0x66,0x1e,0x38,0xef,0xdb,0x1c,0x3f,0x63,0xff,0xdd,0x22,0xe7,0x2d, + 0xf,0x66,0xb5,0x4a,0x87,0xed,0xe3,0x1a,0x5c,0x8d,0x9d,0xd8,0x8d,0x58,0x2b,0x87, + 0x63,0xcb,0x50,0xc1,0x49,0x8c,0xbd,0xdb,0xf1,0xd1,0x72,0x9,0x71,0x60,0x78,0xe4, + 0x5a,0x62,0xe,0x25,0xc1,0xa5,0x8f,0x0,0x78,0x70,0x58,0xa6,0x33,0x54,0xc3,0xbb, + 0x2a,0x33,0x36,0xd1,0x4f,0xde,0xd,0x17,0xd7,0x22,0x1d,0xc5,0xdf,0x3,0xb2,0xe6, + 0x62,0xbe,0xb0,0x77,0xdf,0x3c,0xa1,0xf1,0x7c,0xcb,0xb5,0x80,0xe9,0x29,0xb9,0x79, + 0x20,0xc,0x8,0x96,0x22,0x97,0x52,0xc0,0xb3,0xc2,0x68,0xee,0xc,0x3c,0x90,0x3f, + 0x46,0xef,0x6b,0xee,0xc7,0xcc,0x90,0xe0,0xfd,0xc4,0x10,0xf5,0x8f,0x67,0x7c,0xd3, + 0x6,0xab,0x93,0x8d,0x94,0x42,0xf7,0x75,0x6f,0xb8,0xaa,0xe9,0x74,0x34,0xba,0x21, + 0x5b,0xf7,0x1c,0x93,0x60,0x16,0x32,0xbd,0x7b,0x4e,0xaa,0xd7,0x11,0x83,0x39,0x7c, + 0x14,0x27,0x9e,0x36,0x2b,0xe0,0x8a,0xb0,0x84,0x9d,0x8d,0x44,0xe4,0xe7,0x13,0xb8, + 0x40,0x4c,0x18,0x43,0x89,0x54,0xae,0x9,0x3b,0xc4,0xd1,0x14,0x1b,0x5a,0xd5,0xf5, + 0xf,0xef,0x7e,0x59,0x97,0xab,0x8b,0x83,0xab,0x6c,0x8b,0xce,0xe0,0x93,0x9e,0xc, + 0xf8,0x9e,0xf9,0x59,0xcd,0x4f,0xb0,0x1f,0xfe,0xb8,0xf3,0x86,0x78,0x97,0xea,0x5, + 0xa0,0x65,0xd2,0x7c,0xef,0xe4,0x47,0x66,0x87,0x1d,0x40,0xc4,0x3,0xeb,0x42,0x81, + 0x68,0x32,0x66,0xfe,0xcf,0x7b,0xe6,0xfc,0x0,0x4f,0x36,0x3,0xab,0x7b,0x4c,0xb0, + 0x53,0x29,0x4,0x1e,0xe0,0xf4,0x40,0x0,0xf1,0xe0,0x63,0x94,0xde,0xe7,0xc8,0xe, + 0xc8,0xf,0x8a,0x4f,0xd,0xe3,0xf4,0xa0,0x98,0xb,0xf0,0xbc,0xc7,0xc2,0x66,0xa9, + 0x16,0xc,0x9f,0xf7,0xda,0x9f,0xe1,0x49,0x9b,0x22,0xb,0xa0,0x52,0xac,0x27,0x95, + 0xec,0xd9,0x3b,0x2,0x40,0x73,0xb4,0xb2,0xee,0x56,0xc2,0xc0,0x13,0x78,0x5c,0xd, + 0x72,0xe7,0x5,0x4e,0x9f,0x68,0xf6,0x28,0x3f,0x12,0x7c,0x36,0xa4,0x93,0x6b,0x88, + 0xec,0x68,0x67,0xb1,0x14,0x9d,0x8c,0x2e,0x21,0xc4,0x23,0xae,0x6f,0x77,0x83,0x3a, + 0xe,0x23,0x9,0x3f,0x4f,0x31,0xd,0x8a,0x65,0x2e,0x77,0xd6,0xbe,0x60,0xdd,0x75, + 0x19,0xc9,0xb3,0xba,0xf9,0xb8,0xf4,0x47,0xcb,0x68,0xcd,0x75,0x5a,0xf8,0x40,0x15, + 0x9,0xa3,0xc7,0x46,0x9a,0x8c,0x9e,0xea,0xf8,0x58,0xf9,0x10,0x88,0x7,0x91,0xff, + 0x15,0x29,0x5a,0x3d,0xaf,0x92,0xc1,0x53,0x8a,0x7,0xc7,0x41,0xab,0x14,0x2a,0x26, + 0x8,0x5a,0xad,0xd6,0x3f,0x10,0x60,0x19,0xc0,0xe2,0xaf,0x6f,0x65,0x20,0x1a,0xe5, + 0x8a,0x23,0xcc,0x7f,0xc0,0xae,0x4f,0xf3,0x43,0x1a,0x1,0x86,0x83,0x4b,0xd3,0x8c, + 0x7c,0x77,0x4f,0x3d,0x66,0x53,0x8e,0x18,0x32,0xbe,0x66,0x1f,0xb1,0x68,0xc0,0x1f, + 0x8c,0x8e,0x32,0x9f,0x6a,0x2c,0xcf,0x28,0x95,0xe7,0xf1,0x2c,0x61,0x50,0x8d,0x46, + 0x63,0x46,0x25,0x3,0xb2,0x9d,0x68,0x69,0x1b,0x45,0xaa,0x0,0x9e,0x78,0x30,0x28, + 0x83,0x84,0x17,0x7,0x1,0xb5,0x1e,0x48,0x72,0xb1,0x49,0x20,0x56,0xc2,0x93,0xb7, + 0xd2,0x40,0x11,0x8a,0xc3,0x69,0xd4,0xb8,0x52,0xb3,0xc1,0x59,0x6e,0x6,0x6a,0xb7, + 0x92,0xf0,0x3c,0x8b,0xb1,0x82,0x8,0xf2,0x23,0x72,0x37,0xf8,0x61,0xe0,0x81,0x48, + 0xce,0x15,0xeb,0x60,0x10,0x69,0x4,0xe1,0x86,0x3a,0xdd,0xff,0x49,0xcb,0x71,0x72, + 0xe,0x96,0x54,0x68,0xe1,0x73,0x96,0x2f,0x3e,0x28,0x0,0x4c,0x6,0xb0,0xf5,0x37, + 0x96,0x6c,0x1f,0x4e,0xb6,0x4a,0xef,0x4b,0x3d,0xf0,0xfa,0xde,0x27,0xcd,0x45,0xd4, + 0x79,0x69,0x2f,0x5d,0x13,0x39,0x68,0x37,0x3a,0x86,0xa2,0xe3,0x40,0x4d,0x8e,0x26, + 0x6c,0xa5,0x73,0x5e,0x7e,0x8d,0xcd,0x4c,0x79,0xd8,0xf3,0xc,0xf,0xda,0x73,0x8f, + 0x86,0x4b,0x7f,0xfd,0x24,0x2f,0x89,0x41,0x54,0x34,0xe5,0x72,0x12,0xeb,0x51,0x4f, + 0xc,0x97,0x5b,0x3e,0xbd,0x58,0xfa,0xb0,0x19,0x1,0x2c,0xad,0x4f,0xb2,0x6c,0x72, + 0xbd,0xe4,0x5b,0x6c,0xa7,0x5b,0x4a,0xbf,0xfe,0xf8,0x2c,0xfd,0x8c,0xe4,0x26,0x8a, + 0x59,0xb7,0xc8,0x70,0xc0,0x19,0x8c,0xbb,0x9a,0xc0,0xa5,0xa8,0x79,0xad,0x5f,0xc9, + 0xea,0xfc,0x76,0x42,0x0,0x6a,0x6c,0xa0,0x11,0x2d,0x23,0x1e,0x6b,0x63,0x11,0x4f, + 0xce,0xe7,0x34,0x67,0x14,0xd6,0xca,0x29,0x26,0x5,0x9a,0xbf,0x82,0xe4,0x52,0x93, + 0x9c,0x66,0x7f,0x94,0x51,0x9a,0x3c,0x8b,0x78,0xd6,0x1d,0x3f,0x11,0x64,0x3c,0x50, + 0x53,0xac,0xc7,0xe0,0x7a,0x85,0x18,0xdd,0x62,0xcc,0x86,0x46,0x1f,0x77,0x7,0x6, + 0xc8,0x17,0x1b,0x15,0x41,0x44,0x70,0xb1,0xb8,0x9f,0x28,0xe6,0xfc,0xb3,0xcd,0x63, + 0x19,0x44,0x7a,0x9e,0x9c,0xad,0x0,0x66,0x8,0x8f,0x60,0xe0,0x93,0x53,0x24,0x19, + 0x4c,0xe6,0x29,0x71,0xcc,0x56,0x89,0x9,0xae,0x4,0x96,0x22,0x33,0xa1,0xfa,0x3f, + 0xb9,0x94,0x4f,0xcf,0x39,0x25,0x4b,0x46,0x2c,0x28,0x7f,0xc4,0x93,0x5c,0x17,0x80, + 0xf1,0x94,0x87,0xc6,0xf0,0xd3,0x5d,0x74,0x1,0x9d,0x8,0x90,0x9e,0x3a,0xc9,0xff, + 0x3d,0x98,0x41,0x58,0x1,0x2,0x3d,0xd5,0x44,0xd6,0x98,0x4f,0x85,0xd4,0x7,0xec, + 0x99,0xb,0x3a,0x6c,0xac,0x18,0x62,0xcb,0xa0,0xb1,0x2c,0x20,0xf6,0xbf,0x52,0x12, + 0x35,0xfb,0x58,0x2c,0xb0,0xee,0xf4,0x8a,0xaf,0xc8,0xe4,0xbd,0x8b,0xba,0x4a,0xf1, + 0x4c,0x9a,0x60,0xa7,0x99,0x2e,0x34,0x29,0xce,0xba,0x45,0x35,0x82,0x0,0x3,0x41, + 0x93,0x37,0xc3,0x42,0x95,0x8a,0x3a,0xb0,0x2e,0xe4,0x9a,0x47,0x48,0x6e,0x8b,0xa5, + 0xd9,0x6c,0x4e,0xe9,0x84,0xcf,0xcd,0xfa,0xd7,0x68,0x6a,0xa4,0x6f,0x58,0x60,0x1d, + 0xc5,0xdb,0x44,0xe7,0x9,0x85,0x8a,0xd1,0xc4,0xf3,0x51,0x8d,0xe5,0x28,0xad,0x67, + 0x43,0x5e,0x89,0xe3,0xba,0xb,0x23,0xcc,0xf3,0x72,0xcc,0x82,0x85,0xb1,0x9a,0x93, + 0xd0,0xe4,0x11,0x38,0x35,0xa1,0xb0,0x7e,0xdd,0xb8,0x87,0xd6,0x44,0x35,0x7c,0xda, + 0xa8,0xbb,0xab,0x5d,0xc1,0xb,0x14,0x63,0x33,0xc6,0xf0,0xd0,0x98,0x7b,0xcd,0xa9, + 0x91,0xec,0xd7,0x15,0x24,0x67,0x3c,0x36,0xc0,0x37,0x8a,0x81,0xe0,0x48,0xd6,0xc5, + 0x90,0xb0,0x4e,0xb0,0x4f,0xf6,0x3a,0x47,0x1e,0x86,0x2,0x68,0xc5,0xc6,0xf4,0xbd, + 0x35,0xaa,0x62,0x79,0x4e,0xcd,0xd1,0x94,0x37,0x4c,0x38,0xda,0x25,0x29,0x73,0x51, + 0x62,0x24,0xf7,0x3c,0x27,0x44,0xf1,0x83,0x38,0x8d,0x36,0x58,0x9,0xd,0xed,0x6d, + 0xac,0x81,0xc1,0xe5,0x55,0x87,0x80,0xce,0x21,0xa0,0xe6,0x4,0x1c,0x80,0xd0,0xea, + 0xb,0x35,0xf6,0x5c,0xe,0x50,0x66,0x47,0x27,0x8a,0x68,0xea,0x30,0x99,0xcd,0x2d, + 0x11,0xa2,0xc7,0xc0,0x60,0x73,0x21,0x22,0x9e,0xae,0xec,0x84,0x70,0x61,0xf7,0xf8, + 0x49,0xfb,0x33,0xd4,0x3c,0x6,0xbb,0x9e,0x53,0xfc,0xba,0x62,0xea,0xd0,0x39,0xf5, + 0x3d,0x73,0x24,0x70,0x82,0xd9,0x96,0xd1,0xd0,0xb,0xbb,0x6a,0xc2,0x1e,0xfa,0xdb, + 0xc5,0x39,0xcb,0x3b,0x22,0x63,0x31,0xe5,0x3f,0x28,0x85,0x11,0x1a,0xd,0x53,0x54, + 0x28,0xfd,0xcf,0x21,0x2a,0x8,0x4b,0x8b,0x52,0x9c,0x84,0xc6,0xf4,0x48,0xc9,0x7f, + 0x1c,0x14,0xae,0x70,0xef,0xe2,0x55,0xc3,0x6d,0xb8,0x73,0x76,0xcf,0xd8,0x53,0x6d, + 0x2a,0xc,0x61,0x14,0x2c,0xb8,0x92,0xb8,0x82,0x7a,0x93,0x17,0xd,0xda,0x30,0xab, + 0x88,0x6,0x99,0xff,0x53,0x1e,0x75,0x79,0x3f,0x1b,0x8d,0x91,0x30,0xeb,0xf4,0xa8, + 0xde,0x30,0x46,0x11,0x18,0xa2,0x96,0xd9,0x58,0xc6,0xa8,0x83,0x82,0xa3,0xbb,0x30, + 0xe8,0x21,0x55,0xfb,0xeb,0xc,0x15,0x74,0xce,0x18,0xb6,0x1a,0x20,0xbc,0x57,0xf, + 0x4e,0x5c,0xc7,0xc1,0xf5,0x14,0x2f,0x87,0x3e,0x15,0x38,0xb0,0xd8,0xe4,0xb1,0xb5, + 0xed,0x17,0x5d,0xd9,0x38,0xb7,0xe2,0xe7,0x40,0x13,0x89,0x21,0x2e,0x7c,0x88,0xa7, + 0x3e,0xd7,0xd0,0x43,0xbe,0x74,0x65,0x60,0xcf,0xc8,0x8c,0xc4,0xc,0x3d,0x36,0x8, + 0x9f,0x33,0xf4,0x42,0x88,0xe7,0x33,0x90,0xcd,0xcf,0xc,0xed,0xc2,0xe0,0xb2,0x6f, + 0xc0,0x9c,0x58,0x40,0xb8,0xb9,0x33,0x3d,0xa6,0xea,0xc,0x62,0x8b,0xe6,0x74,0xa0, + 0xa,0x38,0x6b,0x78,0x7c,0xd5,0xda,0x60,0xd3,0xd6,0x9c,0xa5,0x57,0x50,0x13,0x4d, + 0x46,0x7f,0xd4,0x28,0xa0,0xd8,0x7,0x8b,0x79,0x5e,0x65,0x1e,0x78,0xdd,0xc8,0xb4, + 0x99,0x9d,0xb3,0x3e,0x3b,0x7f,0xac,0x67,0xfb,0x6c,0xc8,0x93,0xa2,0xb3,0xc0,0xb2, + 0x29,0xb1,0x46,0x6a,0x28,0xd2,0x87,0x2a,0x9d,0xa5,0x68,0x7a,0x3e,0x8a,0x75,0xe4, + 0x7c,0x5f,0x41,0x7b,0x61,0x50,0xc5,0xd4,0xa2,0xd4,0xc3,0xc7,0xc8,0xc9,0xd9,0x63, + 0xe4,0x24,0x83,0x4f,0x2,0xa9,0x45,0x93,0x8d,0xc4,0x56,0xf0,0x83,0x36,0x68,0x43, + 0x1b,0x79,0x31,0xe7,0x10,0x3e,0x40,0x6,0x8d,0x94,0x65,0x66,0xc0,0x9e,0x43,0x2b, + 0xff,0x36,0xc6,0x94,0x52,0x0,0xc4,0xa4,0xfb,0xc3,0x37,0xef,0x78,0x2,0xe,0x5c, + 0x31,0x2b,0xf4,0xc8,0x61,0x33,0x8c,0xc,0x3a,0x51,0x9b,0xb5,0x4c,0xd1,0xe3,0xd1, + 0x5,0xe0,0x98,0xb0,0xd4,0xd8,0xbc,0x9a,0x3f,0x50,0xbd,0x7a,0x8f,0xa3,0xf2,0x42, + 0x5d,0x65,0x47,0x99,0x72,0xd8,0x68,0xf2,0xc4,0xb3,0xc0,0xe8,0x2f,0x60,0xe3,0xf9, + 0xa1,0x2c,0x2a,0xfd,0x3f,0x34,0xd0,0x42,0xc4,0x44,0x30,0xd4,0x41,0x60,0xf0,0x84, + 0x38,0x8a,0xde,0x1e,0x3c,0x3c,0x24,0x46,0x45,0x4c,0x4d,0x1a,0x34,0xee,0x78,0xae, + 0xfd,0x1b,0xc6,0xbd,0x95,0x19,0xf6,0x2,0x8c,0x56,0x18,0xf8,0xb0,0x28,0x9b,0x70, + 0xed,0xc8,0xd,0x35,0x64,0x31,0xde,0x67,0x22,0xf1,0xec,0x63,0x48,0x5e,0xaa,0xae, + 0x79,0x18,0x8d,0x32,0x76,0x47,0x18,0x74,0x46,0x81,0xf8,0x77,0x3e,0x77,0x3b,0x88, + 0xc2,0x54,0x8,0x54,0xea,0x64,0x6f,0x7a,0xd8,0xdb,0x1e,0x5d,0x49,0x62,0xec,0xa4, + 0xb5,0x89,0x2f,0xf4,0x30,0xc6,0x14,0x89,0xbf,0x68,0x62,0x6b,0xec,0xb2,0x7,0xf5, + 0x62,0xe4,0x78,0x7a,0x31,0xc4,0xb0,0x76,0x14,0x24,0xcb,0xe9,0xb0,0xf,0xed,0x4d, + 0x2,0xc3,0x50,0x35,0x76,0x36,0xbc,0x2,0x1d,0xe0,0x32,0xac,0x36,0x81,0x18,0x5d, + 0x1d,0x2a,0x8d,0x21,0x26,0xe5,0xde,0xc0,0xa5,0x77,0x44,0xf6,0x1e,0x6a,0x8d,0xaa, + 0xf1,0xa0,0x6c,0x6f,0xa8,0x5c,0xaf,0xed,0x28,0x86,0x2b,0xd5,0x63,0xaa,0x57,0x55, + 0xc0,0x81,0x4c,0x8c,0x24,0x6b,0x53,0xd2,0x41,0xce,0xe7,0x2e,0x79,0x6c,0x10,0x27, + 0x48,0x3e,0x3b,0x41,0xf1,0x7,0x11,0x94,0x63,0x72,0xc2,0xa6,0xc3,0xbb,0x14,0x99, + 0xb3,0x25,0xdb,0x48,0x82,0x9a,0xd9,0x70,0xf4,0x33,0xb9,0xee,0xb3,0xf6,0x4f,0x91, + 0xff,0xed,0x9d,0x3a,0x7,0xd5,0x6a,0xd7,0xab,0x72,0x6e,0xf4,0x8a,0xfe,0xc8,0xab, + 0xf,0x5d,0x54,0xcd,0xad,0xca,0xa7,0x1a,0xdf,0xc1,0x2e,0x4,0x8c,0xee,0xbd,0x37, + 0xa2,0x76,0xc6,0xb3,0x70,0x28,0xfb,0x5d,0x4,0xf4,0xb1,0x9e,0x66,0xbf,0x5f,0xb8, + 0x9,0xbd,0xe9,0x9d,0x87,0xe6,0x54,0xf9,0x4e,0xb8,0x4,0xaa,0x34,0xd3,0x77,0xf2, + 0x1e,0xa0,0xe9,0x17,0x18,0x89,0xd3,0x88,0x70,0x9c,0x74,0x6,0x7f,0x56,0xbc,0x90, + 0x7a,0x2f,0xb4,0x1e,0x7,0x67,0x57,0x46,0xc5,0x56,0x1c,0x1f,0x8c,0xae,0x74,0x99, + 0x18,0xaf,0x1b,0x52,0x58,0xb3,0x9b,0xf3,0xca,0xf5,0xf0,0xc1,0xb7,0x74,0x30,0xdc, + 0xfa,0xc4,0x7e,0xf9,0x73,0x72,0xf,0xf0,0xce,0xa8,0xbc,0x30,0xee,0x38,0x18,0x12, + 0xec,0xc,0xb2,0x40,0xc0,0x31,0x4e,0xc4,0x8d,0xad,0x35,0x2d,0x4,0x63,0x82,0xa7, + 0xd3,0x50,0xbe,0x34,0xc6,0x7,0xaf,0xa7,0x27,0xd2,0x4f,0x34,0xb4,0xf3,0xc7,0x14, + 0x3a,0x78,0x29,0xe3,0x1,0xa3,0x8c,0x58,0xfd,0xa2,0x7a,0xbb,0x4e,0x84,0x71,0xed, + 0xb9,0xb3,0xc,0x38,0x27,0xd7,0xfc,0x65,0x43,0xdc,0x3d,0x87,0x58,0x8f,0x52,0x1d, + 0x4,0xb6,0x84,0xf4,0xc6,0x19,0xa7,0xa,0xb,0x57,0x9e,0xa9,0xbd,0xec,0x65,0x23, + 0x91,0x31,0xee,0xae,0x4,0x7,0x51,0xa7,0xe6,0x97,0xb8,0x4d,0x35,0x9e,0x9c,0xa, + 0xb9,0xaf,0x7e,0x1,0x14,0xff,0xc2,0x94,0xc5,0xc1,0xf8,0x99,0xc,0xf0,0x61,0x27, + 0x5a,0x84,0xde,0x87,0x86,0xb7,0x79,0x80,0x63,0x78,0xe7,0x46,0x4b,0x6,0x93,0xd6, + 0xf4,0x37,0x9e,0x2f,0xde,0x74,0xa,0xec,0x96,0xe4,0xa4,0x57,0x9d,0xa4,0x92,0xcb, + 0x93,0x3e,0x83,0x4,0x48,0xa,0x3f,0x8d,0xe1,0x42,0xc6,0x16,0x2,0x87,0x86,0xcc, + 0x81,0xc9,0xe0,0xc1,0xdc,0x7c,0x3d,0x87,0x31,0x51,0x4a,0x27,0xec,0xf8,0xcb,0x20, + 0x78,0xe1,0xcf,0x71,0xa2,0x99,0x8d,0xf6,0xb5,0x88,0xec,0xf4,0xa8,0xf9,0x93,0x7b, + 0xdd,0xef,0xf8,0xe2,0x65,0x22,0xef,0xf8,0xfe,0xe7,0x1b,0xf3,0xd,0x6,0xba,0xe3, + 0x32,0xe0,0xba,0xf1,0xb4,0x60,0xb4,0xfb,0xd,0xf8,0x7e,0xe2,0xba,0x7c,0xf9,0xac, + 0xcf,0xa8,0x1a,0xe1,0x3b,0xbf,0x3d,0x22,0x10,0x7f,0xfe,0x41,0xe0,0x9d,0x14,0x9e, + 0x8b,0xdb,0xf4,0x1,0x97,0x42,0xca,0xdb,0xd8,0x61,0xec,0x3,0x31,0x37,0x8e,0x73, + 0xdc,0xea,0xa4,0x9b,0x3b,0x1d,0x8c,0xd1,0xeb,0x29,0xc3,0xde,0xa4,0xf3,0x9e,0x5f, + 0x90,0xb1,0xbf,0xb9,0x60,0x5f,0xcb,0xf3,0x75,0x69,0x93,0x4b,0xf3,0x7d,0xb2,0x1, + 0x5f,0x55,0x72,0xc0,0x81,0xef,0x4c,0xf1,0xb,0x97,0x70,0xf3,0xa9,0xdb,0xbc,0xed, + 0xb6,0x5c,0x33,0x95,0x1,0x74,0x7e,0xd,0x2d,0xfc,0x32,0x6f,0x31,0xe4,0xf6,0x14, + 0xd5,0x5a,0x6f,0x83,0xc3,0x7b,0xac,0x6e,0xf5,0x6e,0x7e,0x38,0xc8,0x67,0xb0,0xed, + 0xc8,0x3,0x28,0xc4,0x1f,0xfc,0xd0,0x4b,0xa0,0x9b,0x79,0x8b,0x55,0xbf,0xf,0x56, + 0xa9,0xfc,0x69,0xe0,0xa4,0xcf,0x32,0xde,0xb4,0xf3,0xb1,0x2d,0xf3,0xc7,0xa,0xb7, + 0x5e,0x62,0xbc,0x51,0x37,0xef,0x54,0x63,0xa3,0x6,0xde,0xc8,0xf3,0x2,0x39,0x9b, + 0x2b,0xc2,0xcf,0x14,0x85,0x1b,0x33,0x6e,0x6b,0x4b,0x7e,0x59,0xdd,0x17,0xcf,0x78, + 0x71,0x61,0xdb,0x3b,0x43,0xfe,0x68,0x49,0xb6,0xa3,0x2a,0xdc,0x1f,0xef,0x6a,0xfa, + 0x57,0xb3,0x66,0x77,0x50,0x77,0xf8,0x48,0x1f,0x1d,0xc6,0xb1,0xdc,0x83,0x10,0x27, + 0x74,0xb1,0xd,0xa0,0xf0,0x85,0xdd,0x3f,0xbb,0x46,0xbc,0x30,0x89,0x6f,0xa7,0xf8, + 0x36,0xfd,0xc3,0x57,0x8f,0xe6,0xeb,0xbf,0x8d,0x5,0xf2,0xe5,0xdc,0x46,0x93,0x1a, + 0xaf,0x2e,0xf3,0x51,0x8d,0xe4,0xe5,0x58,0x71,0xc9,0xb3,0x55,0x75,0x3c,0x6,0xfa, + 0x5f,0x99,0xac,0xbc,0xcd,0xdf,0x9c,0xf3,0x86,0xdc,0x55,0xef,0xf5,0xf5,0x11,0xe4, + 0x51,0x42,0xda,0xaa,0x78,0xe4,0x9b,0xa3,0x44,0x63,0xab,0x8d,0xbe,0x8e,0x81,0xab, + 0xf6,0xcb,0x71,0x1b,0x39,0xe2,0x50,0x37,0x7e,0x31,0x11,0x74,0x76,0xd1,0xbe,0x52, + 0x9c,0xd4,0x6f,0xb3,0xa2,0xef,0xfe,0x94,0x5e,0x9a,0x43,0xf0,0x1e,0x20,0x2e,0xa3, + 0x4,0x27,0x94,0xb1,0x41,0xe,0x5e,0xce,0x7f,0x1b,0xbb,0xfa,0x1a,0x86,0x77,0x2e, + 0xf7,0xfe,0x2,0xdc,0xfd,0xd9,0x18,0x35,0x11,0x9e,0xb1,0x16,0x5f,0x23,0x39,0xe3, + 0x42,0x47,0x87,0x69,0xf8,0x36,0xed,0xae,0x9e,0x5d,0x12,0x1,0xff,0x10,0x92,0xee, + 0x58,0x3b,0x62,0xbc,0x75,0x63,0x83,0x34,0x3c,0xc2,0x2b,0xb9,0x95,0x24,0x2c,0x59, + 0xf3,0x8b,0x70,0x5,0xaa,0x5b,0xa,0xa0,0x77,0x78,0x5d,0xd5,0xb7,0xdb,0x18,0x7c, + 0x1d,0xa3,0xc0,0x5e,0x9c,0x56,0x2,0x75,0xf,0x18,0x9f,0xcb,0xe0,0x32,0x8f,0x97, + 0xd7,0xbc,0xc,0xdc,0x74,0x99,0x4a,0xd5,0x18,0x2,0xf1,0x36,0x2f,0xff,0xb6,0x6c, + 0x9c,0xc7,0xcf,0x98,0x14,0x62,0x8e,0x57,0x67,0x58,0x3a,0x66,0x84,0xa9,0xed,0x26, + 0xf3,0x25,0x7b,0x2f,0xc6,0x43,0xbd,0x77,0xb5,0xca,0x2b,0xc7,0xbb,0xec,0x28,0x5e, + 0xc5,0x28,0xe6,0xdf,0x6c,0x6e,0x7b,0x1f,0x1a,0x2e,0xe,0x69,0x99,0xeb,0x87,0x5f, + 0x63,0x2c,0x2e,0x4e,0xf8,0x22,0x3d,0x7a,0x1d,0xa3,0x56,0xf6,0xdc,0x9d,0xdd,0x4f, + 0xdf,0xc3,0x8b,0x77,0xb,0x27,0x1f,0x8c,0x26,0xc0,0xe7,0x68,0xab,0xec,0x95,0xcf, + 0xae,0x9c,0x7b,0x27,0xd,0x7,0x80,0xf2,0x96,0x10,0x6f,0x8e,0xc1,0x6,0xf2,0x1, + 0xb1,0x6f,0xef,0xfe,0x38,0xc6,0x8,0xce,0xfe,0x86,0xaa,0x2f,0xa9,0x8c,0x46,0xe1, + 0xb8,0xf9,0x1e,0xfa,0x8b,0x5e,0xf0,0xd2,0x53,0xf1,0xf9,0x24,0xbe,0xa8,0x3e,0xde, + 0x9d,0x20,0x5f,0x0,0x0,0x83,0x83,0x7c,0x3e,0x68,0xd6,0x5e,0xb3,0x7d,0xae,0xa0, + 0xb,0x3f,0xdd,0x60,0xbd,0xad,0x11,0xdd,0x21,0x20,0xaf,0xa3,0x36,0xc6,0xab,0x7b, + 0x31,0x25,0x8c,0x4,0x25,0xc3,0x17,0x78,0x35,0xf7,0x4b,0xb,0x5,0x7,0x85,0x5, + 0x17,0x7f,0xb9,0x83,0xc,0xd2,0xf9,0xa6,0xeb,0xe7,0x7f,0x5f,0x37,0x47,0x9f,0x30, + 0xc9,0x62,0x58,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + +}; + +static const unsigned char qt_resource_name[] = { + // glow + 0x0,0x4, + 0x0,0x6,0xe3,0x67, + 0x0,0x67, + 0x0,0x6c,0x0,0x6f,0x0,0x77, + // leftCenter + 0x0,0xa, + 0x8,0x96,0xd,0x62, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x43,0x0,0x65,0x0,0x6e,0x0,0x74,0x0,0x65,0x0,0x72, + // leftTile + 0x0,0x8, + 0xb,0xd9,0xa2,0x65, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x54,0x0,0x69,0x0,0x6c,0x0,0x65, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x1, + // :/glow + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/leftCenter + 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x3,0xec, + // :/leftTile + 0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x33,0x50, + +}; + +int qInitResources_oxygen() +{ + extern bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} +Q_CONSTRUCTOR_FUNCTION(qInitResources_oxygen) +int qCleanupResources_oxygen() +{ + extern bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} +Q_DESTRUCTOR_FUNCTION(qCleanupResources_oxygen) diff --git a/clients/oxygen/qsubcmetrics.cpp b/clients/oxygen/qsubcmetrics.cpp new file mode 100644 index 0000000000..eb4260c74e --- /dev/null +++ b/clients/oxygen/qsubcmetrics.cpp @@ -0,0 +1,520 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "oxygen.h" + +using namespace Oxygen; +extern Dpi dpi; + +QRect OxygenStyle::subControlRect ( ComplexControl control, const QStyleOptionComplex * option, SubControl subControl, const QWidget * widget) const +{ + QRect ret; + switch (control) { + case CC_SpinBox: // A spinbox, like QSpinBox + if (const QStyleOptionSpinBox *spinbox = + qstyleoption_cast(option)) { + QSize bs = spinbox->rect.size(); + bs.setHeight(bs.height()/2); + // 1.6 -approximate golden mean + bs.setWidth(qMax(dpi.$18, qMin(bs.height(), bs.width() / 4))); +// bs = bs.expandedTo(QApplication::globalStrut()); + int x = spinbox->rect.width() - bs.width(); + switch (subControl) { + case SC_SpinBoxUp: + ret = QRect(x, 0, bs.width(), bs.height()); + break; + case SC_SpinBoxDown: + ret = QRect(x, bs.height(), bs.width(), spinbox->rect.height()-bs.height()); + break; + case SC_SpinBoxEditField: { + int hfw = 0, vfw = 0; + if (spinbox->frame) { + hfw = dpi.$3; vfw = dpi.$1; + } + // in next line -1 and +2 is too offset some qt weirdness so spinbox and linedit have same height + ret = QRect(hfw, vfw-1, x-dpi.$1, spinbox->rect.height() - 2*vfw + 2); + break; + } + case SC_SpinBoxFrame: + ret = spinbox->rect; + default: + break; + } + ret = visualRect(spinbox->direction, spinbox->rect, ret); + } + case CC_ComboBox: // A combobox, like QComboBox + if (const QStyleOptionComboBox *cb = + qstyleoption_cast(option)) { + int x,y,wi,he; + cb->rect.getRect(&x,&y,&wi,&he); + int margin = 1;//(!cb->editable) ? dpi.$1 : (cb->frame ? dpi.$4 : 0); + + switch (subControl) { + case SC_ComboBoxFrame: + ret = cb->rect; + break; + case SC_ComboBoxArrow: + x += wi; wi = (int)((he - 2*margin)/1.1);//1.618 + x -= margin + wi; // golden mean +// y += margin; + ret.setRect(x, y, wi, he/* - 2*margin*/); + break; + case SC_ComboBoxEditField: + wi -= (int)((he - 2*margin)/1.1) + 3*margin; + ret.setRect(x+margin, y+margin, wi, he - 2*margin); + break; + case SC_ComboBoxListBoxPopup: + ret = cb->rect; + if (!cb->editable) { // shorten for the arrow + wi -= (int)((he - 2*margin)/1.1) + 3*margin; + ret.setRect(x+margin, y, wi, he); + } + break; + default: + break; + } + ret = visualRect(cb->direction, cb->rect, ret); + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = + qstyleoption_cast(option)) { + switch (subControl) { + case SC_GroupBoxFrame: + ret = groupBox->rect; + break; + case SC_GroupBoxContents: { + int top = dpi.$6; + if (!groupBox->text.isEmpty()) + top += groupBox->fontMetrics.height(); + ret = groupBox->rect.adjusted(dpi.$3,top,-dpi.$3,-dpi.$7); + break; + } + case SC_GroupBoxCheckBox: { + int cbsz = pixelMetric(PM_IndicatorWidth, groupBox, widget); + if (groupBox->direction == Qt::LeftToRight) { + ret = groupBox->rect.adjusted(dpi.$5,dpi.$5,0,0); + ret.setWidth(cbsz); + } + else { + ret = groupBox->rect.adjusted(0,dpi.$5,-dpi.$5,0); + ret.setLeft(ret.right()-cbsz); + } + ret.setHeight(cbsz); + break; + } + case SC_GroupBoxLabel: { + QFontMetrics fontMetrics = groupBox->fontMetrics; + int h = fontMetrics.height()+dpi.$4; + int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width(); + int marg = (groupBox->features & QStyleOptionFrameV2::Flat) ? 0 : dpi.$4; + + ret = groupBox->rect.adjusted(marg, dpi.$4, -marg, 0); + ret.setHeight(h); + + // Adjusted rect for label + indicatorWidth + indicatorSpace + ret = alignedRect(groupBox->direction, Qt::AlignHCenter, QSize(tw, h), ret); + break; + } + default: + break; + } + } + break; + case CC_ScrollBar: // A scroll bar, like QScrollBar + if (const QStyleOptionSlider *scrollbar = + qstyleoption_cast(option)) { + int sbextent = pixelMetric(PM_ScrollBarExtent, scrollbar, widget); + int maxlen = ((scrollbar->orientation == Qt::Horizontal) ? + scrollbar->rect.width() : scrollbar->rect.height()) - (sbextent * 2); + int sliderlen; + + // calculate slider length + if (scrollbar->maximum != scrollbar->minimum) { + uint range = scrollbar->maximum - scrollbar->minimum; + sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep); + + int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget); + if (sliderlen < slidermin || range > INT_MAX / 2) + sliderlen = slidermin; + if (sliderlen > maxlen) + sliderlen = maxlen; + } + else + sliderlen = maxlen; + + int sliderstart = sliderPositionFromValue(scrollbar->minimum, + scrollbar->maximum, scrollbar->sliderPosition, maxlen - sliderlen, + scrollbar->upsideDown); + switch (subControl) { + case SC_ScrollBarSubLine: // top/left button + if (scrollbar->orientation == Qt::Horizontal) { + int buttonWidth = qMin(scrollbar->rect.width() / 2, sbextent); + ret.setRect(scrollbar->rect.width() - 2*buttonWidth, 0, buttonWidth, sbextent); + } + else { + int buttonHeight = qMin(scrollbar->rect.height() / 2, sbextent); + ret.setRect(0, scrollbar->rect.height() - 2*buttonHeight, sbextent, buttonHeight); + } + break; + case SC_ScrollBarAddLine: // bottom/right button + if (scrollbar->orientation == Qt::Horizontal) { + int buttonWidth = qMin(scrollbar->rect.width()/2, sbextent); + ret.setRect(scrollbar->rect.width() - buttonWidth, 0, buttonWidth, sbextent); + } + else { + int buttonHeight = qMin(scrollbar->rect.height()/2, sbextent); + ret.setRect(0, scrollbar->rect.height() - buttonHeight, sbextent, buttonHeight); + } + break; + case SC_ScrollBarSubPage: // between top/left button and slider + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(dpi.$2, 0, sliderstart, sbextent); + else + ret.setRect(0, dpi.$2, sbextent, sliderstart); + break; + case SC_ScrollBarAddPage: // between bottom/right button and slider + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(sliderstart + sliderlen - dpi.$2, 0, + maxlen - sliderstart - sliderlen, sbextent); + else + ret.setRect(0, sliderstart + sliderlen - dpi.$3, + sbextent, maxlen - sliderstart - sliderlen); + break; + case SC_ScrollBarGroove: + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(0, 0, scrollbar->rect.width() - sbextent * 2, + scrollbar->rect.height()); + else + ret.setRect(0, 0, scrollbar->rect.width(), + scrollbar->rect.height() - sbextent * 2); + break; + case SC_ScrollBarSlider: + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(sliderstart, 0, sliderlen, sbextent); + else + ret.setRect(0, sliderstart, sbextent, sliderlen); + break; + default: + break; + } + ret = visualRect(scrollbar->direction, scrollbar->rect, ret); + } + break; +// case CC_Slider: // A slider, like QSlider + case CC_ToolButton: // A tool button, like QToolButton + if (const QStyleOptionToolButton *tb = + qstyleoption_cast(option)) { + int mbi = pixelMetric(PM_MenuButtonIndicator, tb, widget); + int fw = pixelMetric(PM_DefaultFrameWidth, tb, widget); + QRect ret = tb->rect.adjusted(fw,fw,-fw,0); + switch (subControl) { + case SC_ToolButton: + if ((tb->features + & (QStyleOptionToolButton::Menu | QStyleOptionToolButton::PopupDelay)) + == QStyleOptionToolButton::Menu) + ret.adjust(0, 0, -(mbi+fw), 0); + break; + case SC_ToolButtonMenu: + if ((tb->features + & (QStyleOptionToolButton::Menu | QStyleOptionToolButton::PopupDelay)) + == QStyleOptionToolButton::Menu) + ret.adjust(ret.width() - mbi, 0, 0, 0); + break; + default: + break; + } + return visualRect(tb->direction, tb->rect, ret); + } + break; + case CC_TitleBar: // A Title bar, like what is used in Q3Workspace + if (const QStyleOptionTitleBar *tb = + qstyleoption_cast(option)) { + const int controlMargin = 0; + const int controlHeight = tb->rect.height()/* - controlMargin *2*/; + const int delta = 8*controlHeight/5; + int offset = 0; + + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + + switch (subControl) { + case SC_TitleBarLabel: + if (tb->titleBarFlags & + (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) { + ret = tb->rect; + ret.adjust(delta, 0, 0, 0); + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + ret.adjust(delta, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + ret.adjust(delta, 0, 0, 0); + if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + ret.adjust(delta, 0, 0, 0); + if (tb->titleBarFlags & Qt::WindowShadeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + ret.adjust(0, 0, -delta, 0); + } + break; + case SC_TitleBarMaxButton: + if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarMaxButton) + break; + case SC_TitleBarMinButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarMinButton) + break; + case SC_TitleBarNormalButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarNormalButton) + break; + case SC_TitleBarCloseButton: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + offset += controlMargin; + else if (subControl == SC_TitleBarCloseButton) + break; + ret.setRect(tb->rect.left() + offset, tb->rect.top() + controlMargin, delta, controlHeight); + break; + + case SC_TitleBarContextHelpButton: + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + offset += delta; + case SC_TitleBarShadeButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarShadeButton) + break; + case SC_TitleBarUnshadeButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarUnshadeButton) + break; + case SC_TitleBarSysMenu: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + offset += delta + controlMargin; + else if (subControl == SC_TitleBarSysMenu) + break; + ret.setRect(tb->rect.right() - offset, tb->rect.top() + controlMargin, controlHeight, controlHeight); + break; + default: + break; + } + ret = visualRect(tb->direction, tb->rect, ret); + } + break; + case CC_Q3ListView: // Used for drawing the Q3ListView class + case CC_Dial: // A dial, like QDial + default: + ret = QCommonStyle::subControlRect ( control, option, subControl, widget); + } + return ret; +} + +QRect OxygenStyle::subElementRect ( SubElement element, const QStyleOption * option, const QWidget * widget) const +{ + switch (element) { + case SE_PushButtonContents: // Area containing the label (icon with text or pixmap) + return visualRect(option->direction, option->rect, + option->rect.adjusted(dpi.$4,dpi.$4,-dpi.$4,-dpi.$4)); +// case SE_PushButtonFocusRect: // Area for the focus rect (usually larger than the contents rect) +// case SE_CheckBoxIndicator: // Area for the state indicator (e.g., check mark) +// case SE_CheckBoxContents: // Area for the label (text or pixmap) +// case SE_CheckBoxFocusRect: // Area for the focus indicator +// case SE_CheckBoxClickRect: // Clickable area, defaults to SE_CheckBoxFocusRect +// case SE_RadioButtonIndicator: // Area for the state indicator +// case SE_RadioButtonContents: // Area for the label +// case SE_RadioButtonFocusRect: // Area for the focus indicator +// case SE_RadioButtonClickRect: // Clickable area, defaults to SE_RadioButtonFocusRect +// case SE_ComboBoxFocusRect: // Area for the focus indicator +// case SE_SliderFocusRect: // Area for the focus indicator +// case SE_Q3DockWindowHandleRect: // Area for the tear-off handle + case SE_ProgressBarGroove: // Area for the groove + return option->rect;//.adjusted(0,0,0,0); + case SE_ProgressBarContents: // Area for the progress indicator + case SE_ProgressBarLabel: // Area for the text label + return option->rect.adjusted(dpi.$3,dpi.$4,-dpi.$3,-dpi.$5); +// case SE_DialogButtonAccept: // Area for a dialog's accept button +// case SE_DialogButtonReject: // Area for a dialog's reject button +// case SE_DialogButtonApply: // Area for a dialog's apply button +// case SE_DialogButtonHelp: // Area for a dialog's help button +// case SE_DialogButtonAll: // Area for a dialog's all button +// case SE_DialogButtonRetry: // Area for a dialog's retry button +// case SE_DialogButtonAbort: // Area for a dialog's abort button +// case SE_DialogButtonIgnore: // Area for a dialog's ignore button +// case SE_DialogButtonCustom: // Area for a dialog's custom widget area (in the button row) + case SE_HeaderArrow: { // + int x,y,w,h; + option->rect.getRect(&x,&y,&w,&h); + int margin = dpi.$2;// ;) pixelMetric(QStyle::PM_HeaderMargin, opt, widget); + QRect r; + if (option->state & State_Horizontal) + r.setRect(x + w - 2*margin - (h / 2), y + h/4 + margin, h / 2, h/2); + else + r.setRect(x + dpi.$5, y, h / 2, h / 2 - margin * 2); + r = visualRect(option->direction, option->rect, r); + return r; + } +// case SE_HeaderLabel: // +// case SE_TabWidgetLeftCorner: // +// case SE_TabWidgetRightCorner: // + case SE_TabWidgetTabBar: // + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast(option)) { + QRect r(QPoint(0,0),twf->tabBarSize); + int off = dpi.$10; + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + // Constrain the size now, otherwise, center could get off the page + // This of course repeated for all the other directions + r.setWidth(qMin(r.width(), twf->rect.width() - 2*off + - twf->leftCornerWidgetSize.width() + - twf->rightCornerWidgetSize.width())); + switch (styleHint(SH_TabBar_Alignment, twf, widget)) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width()+off, 0)); + break; + case Qt::AlignCenter: + r.moveTopLeft(QPoint(twf->rect.center().x() - r.width() / 2, 0)); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width() - off + - twf->rightCornerWidgetSize.width(), 0)); + break; + } + r = visualRect(twf->direction, twf->rect, r); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r.setWidth(qMin(r.width(), twf->rect.width() - 2*off + - twf->leftCornerWidgetSize.width() + - twf->rightCornerWidgetSize.width())); + switch (styleHint(SH_TabBar_Alignment, twf, widget)) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width() + off, + twf->rect.height() - twf->tabBarSize.height())); + break; + case Qt::AlignCenter: + r.moveTopLeft(QPoint(twf->rect.center().x() - r.width() / 2, + twf->rect.height() - twf->tabBarSize.height())); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width() - off + - twf->rightCornerWidgetSize.width(), + twf->rect.height() - twf->tabBarSize.height())); + break; + } + r = visualRect(twf->direction, twf->rect, r); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + r.setHeight(qMin(r.height(), twf->rect.height() - 2*off + - twf->leftCornerWidgetSize.height() + - twf->rightCornerWidgetSize.height())); + switch (styleHint(SH_TabBar_Alignment, twf, widget)) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(), + twf->leftCornerWidgetSize.height() + off)); + break; + case Qt::AlignCenter: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(), + twf->rect.center().y() - r.height() / 2)); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(), + twf->rect.height() - twf->tabBarSize.height() + - twf->rightCornerWidgetSize.height() - off)); + break; + } + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + r.setHeight(qMin(r.height(), twf->rect.height() - 2*off) + - twf->leftCornerWidgetSize.height() + - twf->rightCornerWidgetSize.height()); + switch (styleHint(SH_TabBar_Alignment, twf, widget)) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(0, twf->leftCornerWidgetSize.height() + off)); + break; + case Qt::AlignCenter: + r.moveTopLeft(QPoint(0, twf->rect.center().y() - r.height() / 2)); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(0, twf->rect.height() - twf->tabBarSize.height() + - twf->rightCornerWidgetSize.height() - off)); + break; + } + break; + } + return r; + } + case SE_TabWidgetTabContents: // + if (const QStyleOptionTabWidgetFrame *twf = + qstyleoption_cast(option)) { + QRect r = option->rect; //subElementRect ( SE_TabWidgetTabPane, option, widget); +// QStyleOptionTab tabopt; +// tabopt.shape = twf->shape; + const int margin = dpi.$4; +// int baseHeight = pixelMetric(PM_TabBarBaseHeight, &tabopt, widget); + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + r.adjust(margin, margin+twf->tabBarSize.height(), -margin, -margin); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r.adjust(margin, margin, -margin, -margin-twf->tabBarSize.height()); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + r.adjust(margin, margin, -margin-twf->tabBarSize.width(), -margin); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + r.adjust(margin+twf->tabBarSize.width(), margin, -margin, -margin); + } + return r; + } + case SE_TabWidgetTabPane: // + return option->rect;//.adjusted(-10,0,10,0); + case SE_ToolBoxTabContents: // Area for a toolbox tab's icon and label + return QRect(); //kill the rect, we paint the content ourself +// case SE_ViewItemCheckIndicator: // Area for a view item's check mark +// case SE_TabBarTearIndicator: // Area for the tear indicator on a tab bar with scroll arrows. + default: + return QCommonStyle::subElementRect ( element, option, widget); + } +} diff --git a/clients/oxygen/sizefromcontents.cpp b/clients/oxygen/sizefromcontents.cpp new file mode 100644 index 0000000000..b80cd9cb4f --- /dev/null +++ b/clients/oxygen/sizefromcontents.cpp @@ -0,0 +1,168 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas L�bking thomas.luebking@web.de + * Copyright (C) 2007 by Casper Boemann cbr@boemann.dk + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include "oxygen.h" + +#include + +using namespace Oxygen; +extern Dpi dpi; + +extern Config config; +static const int windowsArrowHMargin = 6; // arrow horizontal margin + +QSize OxygenStyle::sizeFromContents ( ContentsType ct, const QStyleOption * option, const QSize & contentsSize, const QWidget * widget ) const +{ + switch ( ct ) { +// case CT_CheckBox: // A check box, like QCheckBox + case CT_ComboBox: // A combo box, like QComboBox + if (const QStyleOptionComboBox *cb = + qstyleoption_cast(option)) { + int hgt = contentsSize.height() - dpi.$1; + if(!cb->editable) + hgt += 2*dpi.$3; + + return QSize(contentsSize.width()+dpi.$10+(int)(hgt/1.1), hgt); + } +// case CT_DialogButtons: // +// return QSize((contentsSize.width()+16 < 80) ? 80 : contentsSize.width()+16, contentsSize.height()+10); +// case CT_Q3DockWindow: // + case CT_HeaderSection: // A header section, like QHeader + if (const QStyleOptionHeader *hdr = + qstyleoption_cast(option)) { + QSize sz; + int margin = dpi.$2; + int iconSize = hdr->icon.isNull() ? 0 : + pixelMetric(QStyle::PM_SmallIconSize, hdr, widget); + QSize txt = hdr->fontMetrics.size(0, hdr->text); + sz.setHeight(qMax(iconSize, txt.height()) + dpi.$4); + sz.setWidth((iconSize?margin+iconSize:0) + + (hdr->text.isNull()?0:margin+txt.width()) + + ((hdr->sortIndicator == QStyleOptionHeader::None) ? 0 : + margin+8*option->rect.height()/5) + margin); + return sz; + } + case CT_LineEdit: // A line edit, like QLineEdit + return contentsSize ;//+ QSize(dpi.$2,dpi.$2); + case CT_MenuBarItem: // A menu bar item, like the buttons in a QMenuBar + return QSize(qMax(contentsSize.width()+dpi.$18, (contentsSize.height()+dpi.$8)*8/5), contentsSize.height()+dpi.$8); + case CT_MenuItem: // A menu item, like QMenuItem + if (const QStyleOptionMenuItem *menuItem = + qstyleoption_cast(option)) { + + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) + return QSize(10, menuItem->text.isEmpty() ? + dpi.$6 : menuItem->fontMetrics.lineSpacing()); + + bool checkable = menuItem->menuHasCheckableItems; + int maxpmw = config.showMenuIcons*menuItem->maxIconWidth; + int w = contentsSize.width(); + int h = qMax(contentsSize.height()+dpi.$2, + menuItem->fontMetrics.lineSpacing()); + + if (config.showMenuIcons && !menuItem->icon.isNull()) + h = qMax(h, + menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize), + QIcon::Normal).height() + dpi.$4); + if (menuItem->text.contains('\t')) + w += dpi.$12; + if (maxpmw > 0) + w += maxpmw + dpi.$6; + if (checkable) + w += 2*(h - dpi.$4)/3 + dpi.$7; + w += (checkable + (maxpmw > 0))*dpi.$2; + w += dpi.$12; + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) + w += 2 * windowsArrowHMargin; + if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) { + // adjust the font and add the difference in size. + // it would be better if the font could be adjusted in the + // getStyleOptions qmenu func!! + QFontMetrics fm(menuItem->font); + QFont fontBold = menuItem->font; + fontBold.setBold(true); + QFontMetrics fmBold(fontBold); + w += fmBold.width(menuItem->text) - fm.width(menuItem->text); + } + return QSize(w, h); + } + break; + case CT_PushButton: // A push button, like QPushButton + if (const QStyleOptionButton *btn = + qstyleoption_cast(option)) { + if (btn->text.isEmpty()) +// 4 px for shadow & outline + 1px padding -> 5px per side + return ( QSize( contentsSize.width() + dpi.$10, contentsSize.height() + dpi.$10 ) ); + else { + QSize sz = contentsSize; + if (btn->icon.isNull()) + return QSize((sz.width()+dpi.$20 < dpi.$80) ? dpi.$80 : contentsSize.width()+dpi.$20, + contentsSize.height()+dpi.$8); + else + return QSize((sz.width()+dpi.$20 < dpi.$80) ? dpi.$80 : contentsSize.width()+dpi.$20, + contentsSize.height()+dpi.$10); + } + } +// case CT_RadioButton: // A radio button, like QRadioButton +// case CT_SizeGrip: // A size grip, like QSizeGrip + + case CT_Menu: // A menu, like QMenu + case CT_Q3Header: // A Qt 3 header section, like Q3Header + case CT_MenuBar: // A menu bar, like QMenuBar + case CT_ProgressBar: // A progress bar, like QProgressBar + case CT_Slider: // A slider, like QSlider + case CT_ScrollBar: // A scroll bar, like QScrollBar + case CT_SpinBox: // A spin box, like QSpinBox + return contentsSize; +// case CT_Splitter: // A splitter, like QSplitter + case CT_TabBarTab: // A tab on a tab bar, like QTabBar + if (const QStyleOptionTab *tab = + qstyleoption_cast(option)) { + switch (tab->shape) { + case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: + case QTabBar::RoundedSouth: case QTabBar::TriangularSouth: + return contentsSize + QSize(dpi.$8, 0); + case QTabBar::RoundedEast: case QTabBar::TriangularEast: + case QTabBar::RoundedWest: case QTabBar::TriangularWest: + return contentsSize + QSize(0, dpi.$8); + } + } + return contentsSize + QSize(dpi.$6, dpi.$6); + case CT_TabWidget: // A tab widget, like QTabWidget + return contentsSize + QSize(dpi.$8,dpi.$10); + case CT_ToolButton: { // A tool button, like QToolButton + const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(option); + // get ~goldem mean ratio + int extraH = dpi.$8; + if (toolbutton && + toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) + extraH = dpi.$10; + int w = qMax(contentsSize.width()+dpi.$6, (contentsSize.height()+extraH)*7/5); + if (toolbutton && (toolbutton->subControls & SC_ToolButtonMenu)) + w += pixelMetric(PM_MenuButtonIndicator, option, widget) + dpi.$8; + return QSize(w, contentsSize.height()+extraH); + } + default: ; + } // switch + return QCommonStyle::sizeFromContents( ct, option, contentsSize, widget ); +} diff --git a/clients/oxygen/stdpix.cpp b/clients/oxygen/stdpix.cpp new file mode 100644 index 0000000000..893cf43593 --- /dev/null +++ b/clients/oxygen/stdpix.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include "oxygen.h" + +#define COLOR(_TYPE_) pal.color(QPalette::_TYPE_) + +using namespace Oxygen; + +extern Dpi dpi; +extern Config config; + +#include "inlinehelp.cpp" + +QPixmap OxygenStyle::standardPixmap ( StandardPixmap standardPixmap, const QStyleOption * option, const QWidget * widget ) const +{ + + QRect rect; QPalette pal; QPixmap pm; + const QStyleOptionTitleBar *opt = qstyleoption_cast(option); + if (opt) { + pal = opt->palette; + rect = opt->rect; rect.moveTo(0,0); + pm = QPixmap(opt->rect.size()); + } + else { + rect = QRect(0,0,16,16); + pal = qApp->palette(); + pm = QPixmap(rect.size()); + } +#if 0 + QString key = QString::number(standardPixmap) + "@" + + QString::number(pm.width()) + "x" + QString::number(pm.height()) + ":" + + QString::number(midColor(pal.color(QPalette::WindowText), pal.color(QPalette::Window)).rgb()); + + if (QPixmapCache::find(key, pm)) + return pm; +#endif + pm.fill(Qt::transparent); // make transparent by default + QPainter painter(&pm); + bool sunken = false, isEnabled = false, hover = false; + if (option) { + sunken = option->state & State_Sunken; + isEnabled = option->state & State_Enabled; + hover = isEnabled && (option->state & State_MouseOver); + } + int sz = 2*qMin(rect.width(), rect.height())/3; + QRect rndRect(0,0,sz,sz); bool foundRect = false; + switch (standardPixmap) { + case SP_DockWidgetCloseButton: + case SP_TitleBarCloseButton: + foundRect = true; + rndRect.moveCenter(rect.center()); + case SP_TitleBarMinButton: + if (!foundRect) { + foundRect = true; + rndRect.moveBottomLeft(rect.bottomLeft()); + } + case SP_TitleBarNormalButton: + case SP_TitleBarMaxButton: + if (!foundRect) + rndRect.moveTopRight(rect.topRight()); + painter.setRenderHint ( QPainter::Antialiasing ); + painter.setPen(Qt::NoPen); + painter.setBrush(gradient(COLOR(Window), rect.height(), Qt::Vertical, GradSunken)); + painter.drawEllipse(rect); + painter.setBrush(gradient(btnBgColor(pal, isEnabled, hover), rndRect.height(), Qt::Vertical, config.gradient)); + painter.setBrushOrigin(rndRect.topLeft()); + painter.drawEllipse(rndRect); + break; + case SP_TitleBarMenuButton: { // 0 Menu button on a title bar + QFont fnt = painter.font(); + fnt.setPixelSize ( rect.height() ); + painter.setFont(fnt); + painter.setPen(pal.color(QPalette::WindowText)); + painter.drawText(rect, Qt::AlignCenter, ";)"); + break; + } + case SP_TitleBarShadeButton: // 5 Shade button on title bars + painter.drawPoint(rect.center().x(), rect.top()); + break; + case SP_TitleBarUnshadeButton: // 6 Unshade button on title bars + painter.drawPoint(rect.center().x(), rect.top()); + painter.drawPoint(rect.center()); + break; + case SP_TitleBarContextHelpButton: { // 7 The Context help button on title bars + QFont fnt = painter.font(); + fnt.setPixelSize ( rect.height() ); + painter.setFont(fnt); + painter.drawText(rect, Qt::AlignCenter, "?"); + break; + } + case SP_MessageBoxInformation: { // 9 The "information" icon + QFont fnt = painter.font(); fnt.setPixelSize ( rect.height()-2 ); painter.setFont(fnt); + painter.setRenderHint ( QPainter::Antialiasing ); + painter.drawEllipse(rect); + painter.drawText(rect, Qt::AlignHCenter | Qt::AlignBottom, "!"); + break; + } + case SP_MessageBoxWarning: { // 10 The "warning" icon + QFont fnt = painter.font(); fnt.setPixelSize ( rect.height()-2 ); painter.setFont(fnt); + painter.setRenderHint ( QPainter::Antialiasing ); + int hm = rect.x()+rect.width()/2; + const QPoint points[4] = { + QPoint(hm, rect.top()), + QPoint(rect.left(), rect.bottom()), + QPoint(rect.right(), rect.bottom()), + QPoint(hm, rect.top()) + }; + painter.drawPolyline(points, 4); + painter.drawLine(hm, rect.top()+4, hm, rect.bottom() - 6); + painter.drawPoint(hm, rect.bottom() - 3); + break; + } +// case SP_MessageBoxCritical: // 11 The "critical" icon +// QFont fnt = painter.font(); fnt.setPixelSize ( rect.height() ); painter.setFont(fnt); +// const QPoint points[3] = +// { +// QPoint(rect.width()/3, rect.top()), +// QPoint(2*rect.width()/3, rect.top()), +// QPoint(rect.right(), rect.height()/2), +// QPoint(rect.right(), rect.bottom()) +// }; +// painter.drawPolyLine(points); +// painter.drawText(rect, Qt::AlignCenter, "-"); + case SP_MessageBoxQuestion: { // 12 The "question" icon + QFont fnt = painter.font(); fnt.setPixelSize ( rect.height() ); painter.setFont(fnt); + painter.drawText(rect, Qt::AlignCenter, "?"); + break; + } +// case SP_DesktopIcon: // 13 +// case SP_TrashIcon: // 14 +// case SP_ComputerIcon: // 15 +// case SP_DriveFDIcon: // 16 +// case SP_DriveHDIcon: // 17 +// case SP_DriveCDIcon: // 18 +// case SP_DriveDVDIcon: // 19 +// case SP_DriveNetIcon: // 20 +// case SP_DirOpenIcon: // 21 +// case SP_DirClosedIcon: // 22 +// case SP_DirLinkIcon: // 23 +// case SP_FileIcon: // 24 +// case SP_FileLinkIcon: // 25 +// case SP_FileDialogStart: // 28 +// case SP_FileDialogEnd: // 29 +// case SP_FileDialogToParent: // 30 +// case SP_FileDialogNewFolder: // 31 +// case SP_FileDialogDetailedView: // 32 +// case SP_FileDialogInfoView: // 33 +// case SP_FileDialogContentsView: // 34 +// case SP_FileDialogListView: // 35 +// case SP_FileDialogBack: // 36 + /// case SP_ToolBarHorizontalExtensionButton: // 26 Extension button for horizontal toolbars + /// case SP_ToolBarVerticalExtensionButton: // 27 Extension button for vertical toolbars + default: + return QCommonStyle::standardPixmap ( standardPixmap, option, widget ); + } + painter.end(); +#if 0 + QPixmapCache::insert(key, pm); +#endif + return pm; +} + +#undef COLOR diff --git a/clients/oxygen/stylehint.cpp b/clients/oxygen/stylehint.cpp new file mode 100644 index 0000000000..6ebe5d74ea --- /dev/null +++ b/clients/oxygen/stylehint.cpp @@ -0,0 +1,152 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include "oxygen.h" + +using namespace Oxygen; + +int OxygenStyle::styleHint ( StyleHint hint, const QStyleOption * option, const QWidget * widget, QStyleHintReturn * returnData ) const { + switch (hint) { + case SH_EtchDisabledText: // Disabled text is "etched" as it is on Windows. + case SH_DitherDisabledText: // + return false; +// case SH_GUIStyle: // The GUI style to use. + case SH_ScrollBar_MiddleClickAbsolutePosition: // A boolean value. If true, middle clicking on a scroll bar causes the slider to jump to that position. If false, middle clicking is ignored. + return true; + case SH_ScrollBar_LeftClickAbsolutePosition: // A boolean value. If true, left clicking on a scroll bar causes the slider to jump to that position. If false, left clicking will behave as appropriate for each control. + return false; + case SH_ScrollBar_ScrollWhenPointerLeavesControl: // A boolean value. If true, when clicking a scroll bar SubControl, holding the mouse button down and moving the pointer outside the SubControl, the scroll bar continues to scroll. If false, the scollbar stops scrolling when the pointer leaves the SubControl. + return true; + case SH_TabBar_Alignment: // The alignment for tabs in a QTabWidget. Possible values are Qt::AlignLeft, Qt::AlignCenter and Qt::AlignRight. + return Qt::AlignLeft; + case SH_Header_ArrowAlignment: // The placement of the sorting indicator may appear in list or table headers. Possible values are Qt::Left or Qt::Right. + return Qt::AlignRight; + case SH_Slider_SnapToValue: // Sliders snap to values while moving, as they do on Windows. + return true; + case SH_Slider_SloppyKeyEvents: // Key presses handled in a sloppy manner, i.e., left on a vertical slider subtracts a line. + return true; + case SH_ProgressDialog_CenterCancelButton: // Center button on progress dialogs, like Motif, otherwise right aligned. + return false; + case SH_ProgressDialog_TextLabelAlignment: // Type Qt::Alignment. Text label alignment in progress dialogs; Qt::Center on windows, Qt::VCenter otherwise. + return Qt::AlignCenter; + case SH_PrintDialog_RightAlignButtons: // Right align buttons in the print dialog, as done on Windows. + return true; + case SH_MainWindow_SpaceBelowMenuBar: // One or two pixel space between the menubar and the dockarea, as done on Windows. + return 0; +// case SH_FontDialog_SelectAssociatedText: // Select the text in the line edit, or when selecting an item from the listbox, or when the line edit receives focus, as done on Windows. +// case SH_Menu_AllowActiveAndDisabled: // Allows disabled menu items to be active. + case SH_Menu_SpaceActivatesItem: // Pressing the space bar activates the item, as done on Motif. + return true; +// case SH_Menu_SubMenuPopupDelay: // The number of milliseconds to wait before opening a submenu (256 on windows, 96 on Motif). + case SH_Menu_Scrollable: // Whether popup menus must support scrolling. + return true; + case SH_Menu_SloppySubMenus: // Whether popupmenu's must support sloppy submenu; as implemented on Mac OS. + return true; + case SH_ScrollView_FrameOnlyAroundContents: // Whether scrollviews draw their frame only around contents (like Motif), or around contents, scroll bars and corner widgets (like Windows). + return (!(widget && widget->inherits("QComboBoxListView"))); +// return true; // find solution for round corner end + case SH_MenuBar_AltKeyNavigation: // Menu bars items are navigable by pressing Alt, followed by using the arrow keys to select the desired item. + return true; + case SH_ComboBox_ListMouseTracking: // Mouse tracking in combobox drop-down lists. + case SH_Menu_MouseTracking: // Mouse tracking in popup menus. + case SH_MenuBar_MouseTracking: // Mouse tracking in menubars. + return true; + case SH_Menu_FillScreenWithScroll: // Whether scrolling popups should fill the screen as they are scrolled. + return false; + case SH_ItemView_ChangeHighlightOnFocus: // Gray out selected items when losing focus. + return true; +// case SH_Widget_ShareActivation: // Turn on sharing activation with floating modeless dialogs. + case SH_TabBar_SelectMouseType: // Which type of mouse event should cause a tab to be selected. + return QEvent::MouseButtonRelease; +// case SH_Q3ListViewExpand_SelectMouseType: // Which type of mouse event should cause a list view expansion to be selected. + case SH_TabBar_PreferNoArrows: // Whether a tabbar should suggest a size to prevent scoll arrows. + return false; + case SH_ComboBox_Popup: // Allows popups as a combobox drop-down menu. + return false; + case SH_ComboBox_PopupFrameStyle: + return QFrame::NoFrame; //QFrame::StyledPanel | QFrame::Plain; +// case SH_Workspace_FillSpaceOnMaximize: // The workspace should maximize the client area. +// case SH_TitleBar_NoBorder: // The title bar has no border. + case SH_ScrollBar_StopMouseOverSlider: // Stops auto-repeat when the slider reaches the mouse position. + return false; + case SH_BlinkCursorWhenTextSelected: // Whether cursor should blink when text is selected. + return false; +// case SH_RichText_FullWidthSelection: // Whether richtext selections should extend to the full width of the document. + case SH_GroupBox_TextLabelVerticalAlignment: // How to vertically align a groupbox's text label. + return Qt::AlignTop; +// case SH_GroupBox_TextLabelColor: // How to paint a groupbox's text label. +// case SH_DialogButtons_DefaultButton: // Which button gets the default status in a dialog's button widget. + case SH_DialogButtonLayout: + return QDialogButtonBox::KdeLayout; //TODO: this should check what session type we are in + case SH_ToolBox_SelectedPageTitleBold: // Boldness of the selected page title in a QToolBox. + return true; + case SH_LineEdit_PasswordCharacter: // The Unicode character to be used for passwords. + return 42; +// case SH_Table_GridLineColor: // + case SH_UnderlineShortcut: // Whether shortcuts are underlined. + return true; + case SH_SpinBox_AnimateButton: // Animate a click when up or down is pressed in a spin box. + return true; +/// case SH_SpinBox_KeyPressAutoRepeatRate: // Auto-repeat interval for spinbox key presses. +/// case SH_SpinBox_ClickAutoRepeatRate: // Auto-repeat interval for spinbox mouse clicks. + case SH_ToolTipLabel_Opacity: // An integer indicating the opacity for the tip label, 0 is completely transparent, 255 is completely opaque. + return 160; + case SH_DrawMenuBarSeparator: // Indicates whether or not the menubar draws separators. + return false; + case SH_TitleBar_ModifyNotification: // Indicates if the titlebar should show a '*' for windows that are modified. + return true; + //TODO: h??? +/// case SH_Button_FocusPolicy: // The default focus policy for buttons. + case SH_MenuBar_DismissOnSecondClick: // A boolean indicating if a menu in the menubar should be dismissed when it is clicked on a second time. (Example: Clicking and releasing on the File Menu in a menubar and then immediately clicking on the File Menu again.) + return true; + //TODO: h??? +/// case SH_MessageBox_UseBorderForButtonSpacing: // A boolean indicating what the to use the border of the buttons (computed as half the button height) for the spacing of the button in a message box. + case SH_TitleBar_AutoRaise: // A boolean indicating whether controls on a title bar ought to update when the mouse is over them. + return true; + case SH_ToolButton_PopupDelay: // An int indicating the popup delay in milliseconds for menus attached to tool buttons. + return 300; +/// case SH_FocusFrame_Mask: // The mask of the focus frame. +/// case SH_RubberBand_Mask: // The mask of the rubber band. +/// case SH_WindowFrame_Mask: // The mask of the window frame. + case SH_SpinControls_DisableOnBounds: // Determines if the spin controls will shown as disabled when reaching the spin range boundary. + return true; +/// case SH_Dial_BackgroundRole: // Defines the style's preferred background role (as QPalette::ColorRole) for a dial widget. + +#warning commenting those two line to make it compile. check. +// case SH_ScrollBar_BackgroundMode: // The backgroundMode() for a scroll bar. +// return ((widget && widget->inherits("QComboBoxListView"))) ? +// Qt::PaletteBase : +// Qt::PaletteBackground; + +/// case SH_ComboBox_LayoutDirection: // The layout direction for the combo box. By default it should be the same value as the QStyleOption's direction. +/// case SH_ItemView_EllipsisLocation: // The location where ellipses should be added for item text that is too long to fit in an view item. +/// case SH_ItemView_ShowDecorationSelected: // When an item in an item view is selected, also highlight the branch or other decoration. + case SH_ItemView_ActivateItemOnSingleClick: // Emit the activated signal when the user single clicks on an item in an item in an item view. Otherwise the signal is emitted when the user double clicks on an item. + return true; + case SH_WizardStyle: + return 2;//QWizard::MacStyle; + default: + return QCommonStyle::styleHint(hint, option, widget, returnData); + } // switch +} diff --git a/clients/oxygen/t_render1.cpp b/clients/oxygen/t_render1.cpp new file mode 100644 index 0000000000..ea17f7207c --- /dev/null +++ b/clients/oxygen/t_render1.cpp @@ -0,0 +1,81 @@ + + int rOff = 0, xOff, yOff, w, h; + + r.getRect(&xOff, &yOff, &w, &h); + int tlh = height(TopLeft), blh = height(BtmLeft), + trh = height(TopRight), brh = height(BtmLeft), + tlw = width(TopLeft), blw = width(BtmLeft), + trw = width(TopRight), brw = width(BtmRight); + + if (pf & Left) + { + w -= width(TopLeft); + xOff += width(TopLeft); + if (pf & (Top | Bottom) && tlh + blh > r.height()) // vertical edge overlap + { + tlh = (tlh*r.height())/(tlh+blh); + blh = r.height() - tlh; + } + } + if (pf & Right) + { + w -= width(TopRight); + if (matches(Top | Bottom, pf) && trh + brh > r.height()) // vertical edge overlap + { + trh = (trh*r.height())/(trh+brh); + brh = r.height() - trh; + } + } + + if (pf & Top) + { + if (matches(Left | Right, pf) && w < 0) // horizontal edge overlap + { + tlw = tlw*r.width()/(tlw+trw); + trw = r.width() - tlw; + } + rOff = r.right()-trw+1; + yOff += tlh; + h -= tlh; + if (pf & Left) // upper left + DRAW_PIXMAP(r.x(),r.y(),PIXMAP(TopLeft), 0, 0, tlw, tlh); + if (pf & Right) // upper right + DRAW_PIXMAP(rOff, r.y(), PIXMAP(TopRight), width(TopRight)-trw, 0, + trw, trh); + + // upper line + if (w > 0 && !pixmap[TopMid].isNull()) + DRAW_TILED_PIXMAP(xOff, r.y(), w, tlh/*height(TopMid)*/, PIXMAP(TopMid)); + } + if (pf & Bottom) + { + if (matches(Left | Right, pf) && w < 0) // horizontal edge overlap + { + blw = (blw*r.width())/(blw+brw); + brw = r.width() - blw; + } + rOff = r.right()-brw+1; + int bOff = r.bottom()-blh+1; + h -= blh; + if (pf & Left) // lower left + DRAW_PIXMAP(r.x(), bOff, PIXMAP(BtmLeft), 0, height(BtmLeft)-blh, + blw, blh); + if (pf & Right) // lower right + DRAW_PIXMAP(rOff, bOff, PIXMAP(BtmRight), width(BtmRight)-brw, + height(BtmRight)-brh, brw, brh); + + // lower line + if (w > 0 && !pixmap[BtmMid].isNull()) + DRAW_TILED_PIXMAP(xOff, bOff, w, height(BtmMid), PIXMAP(BtmMid)); + } + + if (h > 0) + { + if ((pf & Center) && (w > 0)) // center part + DRAW_TILED_PIXMAP(xOff, yOff, w, h, pixmap[MidMid]); + if (pf & Left && !pixmap[MidLeft].isNull()) // left line + DRAW_TILED_PIXMAP(r.x(), yOff, width(MidLeft), h, PIXMAP(MidLeft)); + rOff = r.right()-width(MidRight)+1; + if (pf & Right && !pixmap[MidRight].isNull()) // right line + DRAW_TILED_PIXMAP(rOff, yOff, width(MidRight), h, PIXMAP(MidRight)); + } diff --git a/clients/oxygen/tileset.cpp b/clients/oxygen/tileset.cpp new file mode 100644 index 0000000000..1d927af6c0 --- /dev/null +++ b/clients/oxygen/tileset.cpp @@ -0,0 +1,650 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include "oxrender.h" +#include "tileset.h" + +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + +using namespace Tile; + +static QPixmap nullPix; + +static bool isEmpty(const QPixmap &pix) +{ + if (!pix.hasAlpha()) return false; + QImage img = pix.toImage(); + uint *data = ( uint * ) img.bits(); + int total = img.width() * img.height(); + for ( int current = 0 ; current < total ; ++current ) + if (qAlpha(data[ current ])) + return false; + return true; +} + +static QPixmap invertAlpha(const QPixmap & pix) +{ + if (pix.isNull()) return pix; + QImage img = pix.toImage(); + QImage *dst = new QImage(img); + uint *data = ( uint * ) img.bits(); + uint *ddata = ( uint * ) dst->bits(); + int total = img.width() * img.height(); + for ( int c = 0 ; c < total ; ++c ) + ddata[c] = qRgba( qRed(data[c]), qGreen(data[c]), qBlue(data[c]), 255-qAlpha(data[c]) ); + QPixmap ret = QPixmap::fromImage(*dst, 0); + delete dst; + return ret; +} + +Set::Set(const QPixmap &pix, int xOff, int yOff, int width, int height, int rx, int ry) +{ + if (pix.isNull()) + { + _isBitmap = false; + return; + } + _isBitmap = pix.isQBitmap(); + rxf = pix.width()*rx; + ryf = pix.height()*ry; + + int rOff = pix.width() - xOff - width; + int bOff = pix.height() - yOff - height; + int amount = 32/width+1; + int amount2 = 32/height+1; + int i; + + QPainter p; + +#define initPixmap(_SECTION_,_WIDTH_,_HEIGHT_)\ + pixmap[_SECTION_] = QPixmap(_WIDTH_, _HEIGHT_);\ + pixmap[_SECTION_].fill(Qt::transparent); p.begin(&pixmap[_SECTION_]) + +#define finishPixmap(_SECTION_)\ + p.end();\ + if (isEmpty(pixmap[_SECTION_]))\ + pixmap[_SECTION_] = QPixmap() + + initPixmap(TopLeft, xOff, yOff); + p.drawPixmap(0, 0, pix, 0, 0, xOff, yOff); + finishPixmap(TopLeft); + + initPixmap(TopMid, amount*width, yOff); + for (i = 0; i < amount; i++) + p.drawPixmap(i*width, 0, pix, xOff, 0, width, yOff); + finishPixmap(TopMid); + + initPixmap(TopRight, rOff, yOff); + p.drawPixmap(0, 0, pix, xOff+width, 0, rOff, yOff); + finishPixmap(TopRight); + + //---------------------------------- + initPixmap(MidLeft, xOff, amount2*height); + for (i = 0; i < amount2; i++) + p.drawPixmap(0, i*height, pix, 0, yOff, xOff, height); + finishPixmap(MidLeft); + + initPixmap(MidMid, amount*width, amount2*height); + for (i = 0; i < amount; i++) + for (int j = 0; j < amount2; j++) + p.drawPixmap(i*width, j*height, pix, xOff, yOff, width, height); + finishPixmap(MidMid); + + initPixmap(MidRight, rOff, amount2*height); + for (i = 0; i < amount2; i++) + p.drawPixmap(0, i*height, pix, xOff+width, yOff, rOff, height); + finishPixmap(MidRight); + + //---------------------------------- + + initPixmap(BtmLeft, xOff, bOff); + p.drawPixmap(0, 0, pix, 0, yOff+height, xOff, bOff); + finishPixmap(BtmLeft); + + initPixmap(BtmMid, amount*width, bOff); + for (i = 0; i < amount; i++) + p.drawPixmap(i*width, 0, pix, xOff, yOff+height, width, bOff); + finishPixmap(BtmMid); + + initPixmap(BtmRight, rOff, bOff); + p.drawPixmap(0, 0, pix, xOff+width, yOff+height, rOff, bOff); + finishPixmap(BtmRight); + +#undef initPixmap +#undef finishPixmap +} + +QRect Set::rect(const QRect &rect, PosFlags pf) const +{ + QRect ret = rect; + if (pf == Center) + ret.adjust(width(MidLeft),height(TopMid),-width(TopMid),-height(BtmMid)); + else if (pf == Left) + ret.setRight(ret.left()+width(MidLeft)); + else if (pf == Top) + ret.setBottom(ret.top()+height(TopMid)); + else if (pf == Right) + ret.setLeft(ret.right()-width(MidRight)); + else if (pf == Bottom) + ret.setTop(ret.bottom()-height(BtmMid)); + return ret; +} + +void Set::render(const QRect &r, QPainter *p, PosFlags pf) const +{ +#define PIXMAP(_TILE_) pixmap[_TILE_] +#define DRAW_PIXMAP p->drawPixmap +#define DRAW_TILED_PIXMAP p->drawTiledPixmap + +#include "t_render1.cpp" +#undef PIXMAP +#undef DRAW_PIXMAP +#undef DRAW_TILED_PIXMAP +} + +static Window root = RootWindow (QX11Info::display(), DefaultScreen (QX11Info::display())); + +Picture Set::render(const QSize &s, PosFlags pf) const +{ + return render(s.width(), s.height(), pf); +} + +Picture Set::render(int W, int H, PosFlags pf) const +{ + Display *dpy = QX11Info::display(); + QRect r(0,0,W,H); + Pixmap xpix = XCreatePixmap (dpy, root, W, H, 32); + if (!pixmap) + return X::None; + Picture pict = + XRenderCreatePicture (dpy, xpix, + XRenderFindStandardFormat(dpy, PictStandardARGB32), + 0, 0); + if (!pict) { + XFreePixmap (dpy, xpix); return X::None; + } + +#define PIXMAP(_TILE_) pixmap[_TILE_] +#define DRAW_PIXMAP(_DX_, _DY_, _PIX_, _SX_, _SY_, _W_, _H_) \ + XRenderComposite(dpy, PictOpSrc, _PIX_.x11PictureHandle(), X::None, pict,\ + _SX_, _SY_, 0, 0, _DX_, _DY_, _W_, _H_); +// XCopyArea( dpy, _PIX_.handle(), pix->handle(), gc, _SX_, _SY_, _W_, _H_, _DX_, _DY_ ) +#define DRAW_TILED_PIXMAP(_DX_, _DY_, _W_, _H_, _PIX_)\ + for (int x = 0; x < _W_; x += _PIX_.width())\ + for (int y = 0; y < _H_; y += _PIX_.height())\ + XRenderComposite(dpy, PictOpSrc, _PIX_.x11PictureHandle(), X::None,\ + pict, 0, 0, 0, 0, x+_DX_, y+_DY_,\ + MIN(_PIX_.width(), _W_-x),\ + MIN(_PIX_.height(), _H_-y)); + +#include "t_render1.cpp" + XFreePixmap (dpy, xpix); + return pict; +#undef PIXMAP +#undef DRAW_PIXMAP +#undef DRAW_TILED_PIXMAP +} + +void Set::outline(const QRect &r, QPainter *p, QColor c, bool strong, PosFlags pf) const +{ + p->save(); + p->setRenderHint(QPainter::Antialiasing, false); + QPen pen = p->pen(); + pen.setColor(c); pen.setWidth(1); + p->setPen(pen); + p->setBrush(Qt::NoBrush); + QRect rect = r/*.adjusted(0,0,0,-1)*/; + if (! (pf & Top)) + rect.setTop(rect.top()-100); + else if (strong) + p->drawLine(r.left()+width(TopLeft), r.top(), r.right()-width(TopRight), r.top()); + if (! (pf & Left)) + rect.setLeft(rect.left()-100); + else if (strong) + p->drawLine(r.left(), r.top()+height(TopRight), r.left(), r.bottom()-height(BtmRight)); + if (! (pf & Bottom)) + rect.setBottom(rect.bottom()+100); + else if (strong) + p->drawLine(r.left()+width(BtmLeft), r.bottom(), r.right()-width(BtmRight), r.bottom()); + if (! (pf & Right)) + rect.setRight(rect.right()+100); + else if (strong) + p->drawLine(r.right(), r.top()+height(TopRight), r.right(), r.bottom()-height(BtmRight)); + p->setClipRect(r); + p->setRenderHint(QPainter::Antialiasing); + p->drawRoundRect(rect, ceil((float)rxf/rect.width()), ceil((float)ryf/rect.height())); + p->restore(); +} + +Tile::Mask::Mask(const QPixmap &pix, int xOff, int yOff, int width, int height, + int dx1, int dy1, int dx2, int dy2, int rx, int ry): +Set(pix, xOff, yOff, width, height, rx, ry) { + _dx[0] = dx1; _dx[1] = dx2; _dy[0] = dy1; _dy[1] = dy2; + + pixmap[MidMid] = QPixmap(); + if (dx1 < 1) pixmap[MidLeft] = QPixmap(); + if (dx2 > -1) pixmap[MidRight] = QPixmap(); + if (dy1 < 1) pixmap[TopMid] = QPixmap(); + if (dy2 > -1) pixmap[BtmMid] = QPixmap(); + + for (int i = 0; i < 9; ++i) + if (i != MidMid) + inversePixmap[i] = invertAlpha(pixmap[i]); + + _hasCorners = !pix.isNull(); +} + +QRect Tile::Mask::bounds(const QRect &rect, PosFlags pf) const +{ + QRect ret = rect; + if (pf & Left) + ret.setLeft(ret.left()+_dx[0]); + if (pf & Top) + ret.setTop(ret.top()+_dy[0]); + if (pf & Right) + ret.setRight(ret.right()+_dx[1]); + if (pf & Bottom) + ret.setBottom(ret.bottom()+_dy[1]); + return ret; +} + +const QPixmap &Tile::Mask::corner(PosFlags pf, bool inverse) const +{ + const QPixmap (*pics)[9] = inverse ? &inversePixmap : &pixmap; + if (pf == (Top | Left)) + return (*pics)[TopLeft]; + if (pf == (Top | Right)) + return (*pics)[TopRight]; + if (pf == (Bottom | Right)) + return (*pics)[BtmRight]; + if (pf == (Bottom | Left)) + return (*pics)[BtmLeft]; + + qWarning("requested impossible corner %d",pf); + return nullPix; +} + +QRegion Tile::Mask::clipRegion(const QRect &rect, PosFlags pf) const +{ + QRegion ret(rect.adjusted(_dx[0], _dy[0], _dx[1], _dy[1])); + int w,h; + if (matches(Top | Left, pf)) { + ret -= QRect(rect.x(), rect.y(), width(TopLeft), height(TopLeft)); + } + if (matches(Top | Right, pf)) { + w = width(TopRight); + ret -= QRect(rect.right()-w+1, rect.y(), w, height(TopRight)); + } + if (matches(Bottom | Left, pf)) { + h = height(BtmLeft); + ret -= QRect(rect.x(), rect.bottom()-h+1, width(BtmLeft), h); + } + if (matches(Bottom | Right, pf)) { + w = width(BtmRight); h = height(BtmRight); + ret -= QRect(rect.right()-w+1, rect.bottom()-h+1, w, h); + } + return ret; +} + +void Tile::Mask::render(const QRect &r, QPainter *p, const QBrush &fill, + PosFlags oPf, bool justClip, QPoint offset, bool inverse, + const QRect *outerRect) const +{ + bool pixmode = !fill.texture().isNull(); + + if (justClip) { + p->save(); + p->setClipRegion(clipRegion(r, oPf)); + if (pixmode) + p->drawTiledPixmap(r, fill.texture(), offset); + else + p->fillRect(r, fill.color()); + p->restore(); + return; + } + // first the inner region + //NOTE: using full alphablend can become enourmously slow due to VRAM size - + // even on HW that has Render acceleration! + if (!inverse || outerRect) { + p->save(); + if (inverse) { + QRegion cr = *outerRect; cr -= r; + p->setClipRegion(cr, Qt::IntersectClip); + } + else + p->setClipRegion(clipRegion(r, oPf), Qt::IntersectClip); + if (pixmode) + p->drawTiledPixmap(outerRect ? *outerRect : r, fill.texture(), offset); + else + p->fillRect(outerRect ? *outerRect : r, fill.color()); + p->restore(); + } + if (!_hasCorners) + return; + + QPixmap filledPix; + QPainter pixPainter; + PosFlags pf = oPf & ~Center; + const QPixmap (*pics)[9] = inverse ? &inversePixmap : &pixmap; + QPoint off = r.topLeft()-offset; + +#define PIXMAP(_TILE_) (*pics)[_TILE_] + +#define MAKE_FILL(_PIX_, _OFF_)\ + filledPix = QPixmap(_PIX_.size());\ + if (pixmode) {\ + filledPix.fill(Qt::transparent);\ + pixPainter.begin(&filledPix);\ + pixPainter.drawTiledPixmap(filledPix.rect(), fill.texture(), _OFF_-off);\ + pixPainter.end();\ + }\ + else\ + filledPix.fill(fill.color());\ + filledPix = OXRender::applyAlpha(filledPix, _PIX_) + +#define DRAW_PIXMAP(_DX_, _DY_, _PIX_, _SX_, _SY_, _W_, _H_) {\ + MAKE_FILL(_PIX_, QPoint(_DX_, _DY_));\ + p->drawPixmap(_DX_, _DY_, filledPix, _SX_, _SY_, _W_, _H_);\ +}// --skip semicolon + +#define DRAW_TILED_PIXMAP(_DX_, _DY_, _W_, _H_, _PIX_) {\ + MAKE_FILL(_PIX_, QPoint(_DX_, _DY_));\ + p->drawTiledPixmap(_DX_, _DY_, _W_, _H_, filledPix);\ +}// --skip semicolon + +#include "t_render1.cpp" +#undef PIXMAP +#undef MAKE_FILL +#undef DRAW_PIXMAP +#undef DRAW_TILED_PIXMAP + +} + +Line::Line(const QPixmap &pix, Qt::Orientation o, int d1, int d2) { + _o = o; + QPainter p; + if (o == Qt::Horizontal) { + _thickness = pix.height(); + pixmap[0] = QPixmap(d1,pix.height()); + pixmap[0].fill(Qt::transparent); + p.begin(&pixmap[0]); + p.drawPixmap(0,0,pix,0,0,d1,pix.height()); + p.end(); + + int d = pix.width()-d1+d2; + pixmap[1] = QPixmap(MAX(32,d),pix.height()); + pixmap[1].fill(Qt::transparent); + p.begin(&pixmap[1]); + for (int i = 0; i+d <= width(1); i+=d) + p.drawPixmap(i,0,pix,d1,0,MIN(d,width(1)-i),pix.height()); + p.end(); + + pixmap[2] = QPixmap(-d2,pix.height()); + pixmap[2].fill(Qt::transparent); + p.begin(&pixmap[2]); + p.drawPixmap(0,0,pix,pix.width()+d2,0,-d2,pix.height()); + p.end(); + } + else { + _thickness = pix.width(); + pixmap[0] = QPixmap(pix.width(),d1); + pixmap[0].fill(Qt::transparent); + p.begin(&pixmap[0]); + p.drawPixmap(0,0,pix,0,0,pix.width(),d1); + p.end(); + + int d = pix.height()-d1+d2; + pixmap[1] = QPixmap(pix.width(), MAX(32,d)); + pixmap[1].fill(Qt::transparent); + p.begin(&pixmap[1]); + for (int i = 0; i+d < height(1); i+=d) + p.drawPixmap(0,i,pix,0,d1,pix.width(),MIN(d,height(1)-i)); + p.end(); + + pixmap[2] = QPixmap(pix.width(),-d2); + pixmap[2].fill(Qt::transparent); + p.begin(&pixmap[2]); + p.drawPixmap(0,0,pix,0,pix.height()+d2,pix.width(),-d2); + p.end(); + } +} + +void Line::render(const QRect &rect, QPainter *p, PosFlags pf, bool btmRight) const { + int d0,d2; + if (_o == Qt::Horizontal) { + int y = btmRight?rect.bottom()-_thickness-1:rect.y(); + d0 = (pf & Left) ? width(0) : 0; + d2 = (pf & Right) ? width(2) : 0; + if ((pf & Center) && rect.width() >= d0+d2) + p->drawTiledPixmap(rect.x()+d0,y, rect.width()-d0-d2, height(1), pixmap[1]); + else if (d0 || d2) { + d0 = qMin(d0,d0*rect.width()/(d0+d2)); + d2 = qMin(d2,rect.width()-d0); + } + if (pf & Left) + p->drawPixmap(rect.x(),y, pixmap[0],0,0,d0,height(0)); + if (pf & Right) + p->drawPixmap(rect.right()+1-d2,y, pixmap[2], width(2)-d2,0,d2,height(2)); + } + else { + int x = btmRight?rect.right()-_thickness-1:rect.x(); + d0 = (pf & Top) ? height(0) : 0; + d2 = (pf & Bottom) ? height(2) : 0; + if ((pf & Center) && rect.height() >= d0+d2) { + p->drawTiledPixmap(x,rect.y()+d0, width(1), rect.height()-d0-d2, pixmap[1]); + } + else if (d0 || d2) { + d0 = qMin(d0,d0*rect.height()/(d0+d2)); + d2 = qMin(d2,rect.height()-d0); + } + if (pf & Top) + p->drawPixmap(x,rect.y(),pixmap[0],0,0,width(0),d0); + if (pf & Bottom) + p->drawPixmap(x, rect.bottom()+1-d2,pixmap[2],0,height(2)-d2,width(2),d2); + } +} + +#define FILL_PIX(_NUM_)\ + pixmap[_NUM_].fill(Qt::transparent);\ + p.begin(&pixmap[_NUM_]);\ + p.fillRect(pixmap[_NUM_].rect(), lg);\ + p.end() + +#define MAKE_ARC(_NUM_,_CLR_,_X_,_Y_,_ANG_)\ + pixmap[_NUM_] = QPixmap(4,4);\ + pixmap[_NUM_].fill(Qt::transparent);\ + p.begin(&pixmap[_NUM_]);\ + p.setRenderHint(QPainter::Antialiasing);\ + p.setPen(_CLR_);\ + p.drawArc(_X_,_Y_,8,8,_ANG_<<4,90<<4);\ + p.setRenderHint(QPainter::Antialiasing, false);\ + p.end() + +#define SET_GRAD(_C1_,_C2_)\ + stops.clear();\ + stops << QGradientStop(0, QColor(_C1_,_C1_,_C1_,_alpha))\ + << QGradientStop(1, QColor(_C2_,_C2_,_C2_,_alpha));\ + lg.setStops(stops) + +#ifndef CLAMP +#define CLAMP(x,l,u) (x) < (l) ? (l) :\ +(x) > (u) ? (u) :\ +(x) +#endif + +Nuno::Nuno(int alpha) +{ + QGradientStops stops; + _alpha = alpha; + QPainter p; QPen pen = p.pen(); + MAKE_ARC(0,QColor(255,255,255,_alpha),0,0,90); //tl + QLinearGradient lg( 0, 0, 4, 4 ); + SET_GRAD(255,170); pen.setBrush(lg); + MAKE_ARC(1,pen,-4,0,0); //tr + lg.setStart(4,0); lg.setFinalStop(0,4); + SET_GRAD(107,100); pen.setBrush(lg); + MAKE_ARC(2,pen,-4,-4,270); //br + lg.setStart(0,0); lg.setFinalStop(4,4); + SET_GRAD(255,175); pen.setBrush(lg); + MAKE_ARC(3,pen,0,-4,180); //bl + + _alpha = alpha; + + lg.setStart(0,0); lg.setFinalStop(37,0); + + //bottom 1 + SET_GRAD(175,138); + pixmap[4] = QPixmap(37,1); + FILL_PIX(4); + + //bottom 2 + SET_GRAD(136,100); + pixmap[5] = QPixmap(37,1); + FILL_PIX(5); + + //right 1 + lg.setStart(1,0); lg.setFinalStop(1,31); + SET_GRAD(170,139); + pixmap[6] = QPixmap(1,31); + FILL_PIX(6); + + //right 2 + SET_GRAD(137,107); + pixmap[7] = QPixmap(1,31); + FILL_PIX(7); +} + +#undef FILL_PIX +#undef MAKE_ARC + +void Nuno::render(const QRect &r, QPainter *p, PosFlags pf) const +{ + int xOff = 0, yOff = 0, rOff = 0, bOff = 0; + + if (matches(Top|Left, pf)) + { + p->drawPixmap(r.x(),r.y(),pixmap[0]); + xOff = r.x()+width(0); yOff = r.y()+height(0); + } + + if (matches(Top|Right, pf)) + { + p->drawPixmap(r.right()-width(1)+1,r.y(),pixmap[1]); + rOff = r.right()-width(1)+1; yOff = r.y()+height(1); + } + + if (matches(Bottom|Left, pf)) + { + p->drawPixmap(r.x(),r.bottom()-height(3)+1,pixmap[3]); + xOff = r.x()+width(3); bOff = r.bottom()-height(3)+1; + } + + if (matches(Bottom|Right, pf)) + { + p->drawPixmap(r.right()-width(2)+1,r.bottom()-height(2)+1,pixmap[2]); + rOff = r.right()-width(2)+1; bOff = r.bottom()-height(2)+1; + } + p->save(); + if (xOff < rOff) + { + if (pf & Top) + { + p->setPen(QColor(255,255,255,_alpha)); + p->drawLine(xOff, r.y(), rOff, r.y()); + } + if (pf & Bottom) + { + int w = rOff-xOff; + if (w < width(4)+width(5)) + { + QHash *cache = &(const_cast( this )->_lines[0]); + QHash::const_iterator it; + it = cache->find(w); + if (it == cache->end()) + { + QPixmap pix(w,1); pix.fill(Qt::transparent); + QLinearGradient lg( 0, 1, w, 1 ); + lg.setColorAt ( 0, QColor(175,175,175,_alpha) ); + lg.setColorAt ( 1, QColor(100,100,100,_alpha) ); + QPainter p(&pix); p.fillRect(0,0,w,1,lg); p.end(); + it = cache->insert(w, pix); + } + p->drawPixmap(xOff,r.bottom(),it.value()); + } + else + { + p->drawPixmap(xOff,r.bottom(),pixmap[4]); + p->drawPixmap(rOff-width(5),r.bottom(),pixmap[5]); + if (w > width(4)+width(5)) + { + p->setPen(QColor(137,137,137,_alpha)); + p->drawLine(xOff+width(4),r.bottom(),rOff-width(5)-1,r.bottom()); + } + } + } + } + if (yOff < bOff) + { + if (pf & Left) + { + p->setPen(QColor(255,255,255,_alpha)); + p->drawLine(r.x(), yOff, r.x(), bOff); + } + if (pf & Right) + { + int h = bOff-yOff; + if (h < height(6)+height(7)) + { + QHash *cache = &(const_cast( this )->_lines[1]); + QHash::const_iterator it; + it = cache->find(h); + if (it == cache->end()) + { + QPixmap pix(1,h); + QLinearGradient lg( 1, 0, 1, h ); pix.fill(Qt::transparent); + lg.setColorAt ( 0, QColor(170,170,170,_alpha) ); + lg.setColorAt ( 1, QColor(107,107,107,_alpha) ); + QPainter p(&pix); p.fillRect(0,0,1,h,lg); p.end(); + it = cache->insert(h, pix); + } + p->drawPixmap(r.right(),yOff,it.value()); + } + else + { + p->drawPixmap(r.right(),yOff,pixmap[6]); + p->drawPixmap(r.right(),bOff-height(7),pixmap[7]); + if (h > height(6)+height(7)) + { + p->setPen(QColor(138,138,138,_alpha)); + p->drawLine(r.right(),yOff+height(6),r.right(),bOff-height(7)-1); + } + } + } + } + p->restore(); +} diff --git a/clients/oxygen/tileset.h b/clients/oxygen/tileset.h new file mode 100644 index 0000000000..9747909933 --- /dev/null +++ b/clients/oxygen/tileset.h @@ -0,0 +1,121 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Thomas Lbking * + * thomas.luebking@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef TILESET_H +#define TILESET_H + +#include +#include +#include +#include +#include +#include +#include + +namespace Tile +{ + + enum Section + { // DON'T CHANGE THE ORDER FOR NO REASON, i misuse them on the masks... + TopLeft = 0, TopRight, BtmLeft, BtmRight, + TopMid, BtmMid, MidLeft, MidMid, MidRight + }; + enum Position + { + Top = 0x1, Left=0x2, Bottom=0x4, Right=0x8, + Ring=0xf, Center=0x10, Full=0x1f + }; + + typedef uint PosFlags; + +inline static bool matches(PosFlags This, PosFlags That){return (This & That) == This;} + +class Set +{ +public: + Set(const QPixmap &pix, int xOff, int yOff, int width, int height, int rx = 0, int ry = 0); + Set(){} + void render(const QRect &rect, QPainter *p, PosFlags pf = Ring) const; + void outline(const QRect &rect, QPainter *p, QColor c, bool strong = false, + PosFlags pf = Ring) const; + Picture render(int width, int height, PosFlags pf = Ring) const; + Picture render(const QSize &size, PosFlags pf = Ring) const; + QRect rect(const QRect &rect, PosFlags pf) const; + inline int width(Section sect) const {return pixmap[sect].width();} + inline int height(Section sect) const {return pixmap[sect].height();} + inline bool isQBitmap() const {return _isBitmap;} +protected: + QPixmap pixmap[9]; +private: + int rxf, ryf; + bool _isBitmap; +}; + +class Mask : public Set +{ +public: + Mask(const QPixmap &pix, int xOff, int yOff, int width, int height, + int dx1, int dy1, int dx2, int dy2, int rx = 0, int ry = 0); + Mask(){_dx[0] = _dx[1] = _dy[0] = _dy[1] = 0; _hasCorners = false;} + void render(const QRect &rect, QPainter *p, const QBrush &fill, + PosFlags pf = Full, bool justClip = false, + QPoint offset = QPoint(), bool inverse = false, + const QRect *outerRect = 0L) const; + QRect bounds(const QRect &rect, PosFlags pf = Full) const; + const QPixmap &corner(PosFlags pf, bool inverse = false) const; + QRegion clipRegion(const QRect &rect, PosFlags pf = Ring) const; + inline bool hasCorners() const {return _hasCorners;} +private: + int _dx[2], _dy[2]; + QPixmap inversePixmap[9]; + bool _hasCorners; +}; + +class Line +{ +public: + Line(const QPixmap &pix, Qt::Orientation o, int d1, int d2); + Line(){} + void render(const QRect &rect, QPainter *p, PosFlags pf = Full, bool btmRight = false) const; + inline int thickness() const { return _thickness; } +private: + inline int width(int i) const {return pixmap[i].width();} + inline int height(int i) const {return pixmap[i].height();} + Qt::Orientation _o; + QPixmap pixmap[3]; + int _thickness; +}; + +class Nuno +{ +public: + Nuno(int alpha = 255); + void render(const QRect &rect, QPainter *p, PosFlags pf = Ring) const; +private: + inline int width(int i) const {return pixmap[i].width();} + inline int height(int i) const {return pixmap[i].height();} + QPixmap pixmap[8]; + int _alpha; + QHash _lines[2]; +}; + +} // namespace Tile + +#endif //TILESET_H