qt5-ukui-platformtheme/ukui-styles/qt5-style-ukui/breezeboxshadowrenderer.h

269 lines
6.3 KiB
C++

/*
* Copyright (C) 2018 Vlad Zagorodniy <vlad.zahorodnii@kde.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
// own
// Qt
#include <QEvent>
/*
#include <QMainWindow>
#include <QWidget>
#include <QMenu>
#include <QPushButton>
#include <QIcon>
#include <QListWidget>
#include <QTabWidget>
#include <QToolTip>
#include <QAction>
#include <QTreeView>
#include <QLabel>
#include <QPalette>
#include <QColor>
#include <QDebug>
#include <QPainter>
#include <QPixmap>
#include <QStyle>
#include <QLineEdit>
#include <QToolBar>
#include <QToolButton>
#include <QCheckBox>
#include <QLabel>
#include <QThread>
#include <QScrollBar>
#include <QVBoxLayout>
#include <QContextMenuEvent>
#include <QMenu>
*/
//#include <KWindowEffects>
#include <xcb/xproto.h>
#include <qdebug.h>
#include <QVector4D>
//#include <QTimer>
#include <xcb/xcb.h>
//#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QColor>
#include <QImage>
#include <QPoint>
#include <QSize>
#include <QScopedPointer>
#include <QWeakPointer>
template <typename T> using ScopedPointer = QScopedPointer<T, QScopedPointerPodDeleter>;
class BoxShadowRenderer
{
public:
// Compiler generated constructors & destructor are fine.
/**
* Set the size of the box.
* @param size The size of the box.
**/
void setBoxSize(const QSize &size);
/**
* Set the radius of box' corners.
* @param radius The border radius, in pixels.
**/
void setBorderRadius(qreal radius);
/**
* Set the device pixel ratio of the resulting shadow texture.
* @param dpr The device pixel ratio.
**/
void setDevicePixelRatio(qreal dpr);
/**
* Add a shadow.
* @param offset The offset of the shadow.
* @param radius The blur radius.
* @param color The color of the shadow.
**/
void addShadow(const QPoint &offset, int radius, const QColor &color);
/**
* Render the shadow.
**/
QImage render() const;
/**
* Calculate the minimum size of the box.
*
* This helper computes the minimum size of the box so the shadow behind it has
* full its strength.
*
* @param radius The blur radius of the shadow.
**/
static QSize calculateMinimumBoxSize(int radius);
/**
* Calculate the minimum size of the shadow texture.
*
* This helper computes the minimum size of the resulting texture so the shadow
* is not clipped.
*
* @param boxSize The size of the box.
* @param radius The blur radius.
* @param offset The offset of the shadow.
**/
static QSize calculateMinimumShadowTextureSize(const QSize &boxSize, int radius, const QPoint &offset);
private:
QSize m_boxSize;
qreal m_borderRadius = 0.0;
qreal m_dpr = 1.0;
struct Shadow {
QPoint offset;
int radius;
QColor color;
};
QVector<Shadow> m_shadows;
};
class TileSet
{
public:
/**
Create a TileSet from a pixmap. The size of the bottom/right chunks is
whatever is left over from the other chunks, whose size is specified
in the required parameters.
@param w1 width of the left chunks
@param h1 height of the top chunks
@param w2 width of the not-left-or-right chunks
@param h2 height of the not-top-or-bottom chunks
*/
TileSet(const QPixmap&, int w1, int h1, int w2, int h2 );
//* empty constructor
TileSet();
//* destructor
virtual ~TileSet()
{}
/**
Flags specifying what sides to draw in ::render. Corners are drawn when
the sides forming that corner are drawn, e.g. Top|Left draws the
top-center, center-left, and top-left chunks. The center-center chunk is
only drawn when Center is requested.
*/
enum Tile {
Top = 0x1,
Left = 0x2,
Bottom = 0x4,
Right = 0x8,
Center = 0x10,
TopLeft = Top|Left,
TopRight = Top|Right,
BottomLeft = Bottom|Left,
BottomRight = Bottom|Right,
Ring = Top|Left|Bottom|Right,
Horizontal = Left|Right|Center,
Vertical = Top|Bottom|Center,
Full = Ring|Center
};
Q_DECLARE_FLAGS(Tiles, Tile)
/**
Fills the specified rect with tiled chunks. Corners are never tiled,
edges are tiled in one direction, and the center chunk is tiled in both
directions. Partial tiles are used as needed so that the entire rect is
perfectly filled. Filling is performed as if all chunks are being drawn.
*/
void render(const QRect&, QPainter*, Tiles = Ring) const;
//* return size associated to this tileset
QSize size() const
{ return QSize( _w1 + _w3, _h1 + _h3 ); }
//* is valid
bool isValid() const
{ return _pixmaps.size() == 9; }
//* returns pixmap for given index
QPixmap pixmap( int index ) const
{ return _pixmaps[index]; }
protected:
//* shortcut to pixmap list
using PixmapList = QVector<QPixmap>;
//* initialize pixmap
void initPixmap( PixmapList&, const QPixmap&, int w, int h, const QRect& );
private:
//* pixmap arry
PixmapList _pixmaps;
// dimensions
int _w1;
int _h1;
int _w3;
int _h3;
};
class BreezeShadowHelper: public QObject
{
Q_OBJECT
public:
//* constructor
BreezeShadowHelper( QObject*/*, Helper& */);
//* destructor
~BreezeShadowHelper() override;
//* event filter
bool eventFilter( QObject*, QEvent* ) override;
const QVector<quint32>& createPixmapHandles();
quint32 createPixmap( const QPixmap& source );
bool installShadows( const QWidget * );
private:
QVector<quint32> _pixmaps;
TileSet _shadowTiles;
xcb_atom_t _atom = 0;
};