File indexing completed on 2023-11-26 07:31:36
0001 /* 0002 * This file is part of the KDE libraries 0003 * 0004 * Copyright (C) 2007 Germain Garand <germain@ebooksfrance.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 // The PaintBuffer class provides a shared buffer for efficient repetitive painting. 0024 // 0025 // It will grow to encompass the biggest size encountered, in order to avoid 0026 // constantly resizing. 0027 // When it grows over maxPixelBuffering, it periodically checks if such a size 0028 // is still needed. If not, it shrinks down to the biggest size < maxPixelBuffering 0029 // that was requested during the overflow lapse. 0030 0031 #ifndef html_paintbuffer_h 0032 #define html_paintbuffer_h 0033 0034 #include <QPixmap> 0035 #include <QStack> 0036 #include <QPainter> 0037 #include <QPaintEngine> 0038 #include <assert.h> 0039 0040 namespace khtml 0041 { 0042 0043 class BufferedPainter; 0044 class BufferSweeper; 0045 0046 class PaintBuffer: public QObject 0047 { 0048 friend class khtml::BufferSweeper; 0049 0050 Q_OBJECT 0051 0052 public: 0053 static const int maxPixelBuffering; 0054 static const int leaseTime; 0055 static const int cleanupTime; 0056 static const int maxBuffers; 0057 0058 static QPixmap *grab(QSize s = QSize()); 0059 static void release(QPixmap *p); 0060 0061 static void cleanup(); 0062 0063 PaintBuffer(); 0064 void reset(); 0065 void timerEvent(QTimerEvent *e) override; 0066 0067 private: 0068 QPixmap *getBuf(QSize S); 0069 0070 static QStack<PaintBuffer *> *s_avail; 0071 static QStack<PaintBuffer *> *s_grabbed; 0072 static QStack<QPixmap *> *s_full; 0073 static BufferSweeper *s_sweeper; 0074 0075 QPixmap m_buf; 0076 bool m_overflow; 0077 bool m_grabbed; 0078 bool m_renewTimer; 0079 int m_timer; 0080 int m_resetWidth; 0081 int m_resetHeight; 0082 }; 0083 0084 class BufferedPainter 0085 { 0086 public: 0087 BufferedPainter(QPixmap *px, QPainter *&p, const QRegion &rr, bool replacePainter) 0088 { 0089 QRect br = rr.boundingRect(); 0090 m_rect = br; 0091 bool doFill = 1 || !px->hasAlphaChannel(); // shared pixmaps aren't properly cleared 0092 // with Qt 4 + NVidia proprietary driver. 0093 // So we can't use this optimization until 0094 // we can detect this defect. 0095 if (doFill) { 0096 px->fill(Qt::transparent); 0097 } 0098 m_painter.begin(px); 0099 0100 m_off = br.topLeft() + QPoint(static_cast<int>(p->worldTransform().dx()), 0101 static_cast<int>(p->worldTransform().dy())); 0102 m_painter.setWorldTransform(p->worldTransform()); 0103 m_painter.translate(-m_off); 0104 m_painter.setClipRegion(m_region = rr); 0105 //foreach(QRect rrr, m_region.rects()) 0106 // qCDebug(KHTML_LOG) << rrr; 0107 0108 if (!doFill) { 0109 m_painter.setCompositionMode(QPainter::CompositionMode_Source); 0110 m_painter.fillRect(br, Qt::transparent); 0111 } 0112 0113 m_painter.setCompositionMode(p->compositionMode()); 0114 m_buf = px; 0115 0116 m_painter.setFont(p->font()); 0117 m_painter.setBrush(p->brush()); 0118 m_painter.setPen(p->pen()); 0119 m_painter.setBackground(p->background()); 0120 m_painter.setRenderHints(p->renderHints()); 0121 // ### what else? 0122 0123 m_origPainter = p; 0124 if (replacePainter) { 0125 p = &m_painter; 0126 } 0127 m_paused = false; 0128 } 0129 0130 void transfer(float opacity) 0131 { 0132 // ### when using DestinationIn with an alpha above 0.99, the resulting buffer ends up black in Qt 4.5.1 0133 bool constantOpacity = (opacity > 0.99) || (m_origPainter->paintEngine() && m_origPainter->paintEngine()->hasFeature(QPaintEngine::ConstantOpacity)); 0134 if (!constantOpacity) { 0135 QColor color; 0136 color.setAlphaF(opacity); 0137 m_painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); 0138 m_painter.fillRect(m_rect, color); 0139 } 0140 m_painter.end(); 0141 QTransform t = m_origPainter->worldTransform(); 0142 QPoint trans(static_cast<int>(t.dx()), static_cast<int>(t.dy())); 0143 m_origPainter->save(); 0144 m_origPainter->resetTransform(); 0145 m_origPainter->setClipRegion(trans.isNull() ? m_region : m_region.translated(trans)); 0146 m_origPainter->setWorldTransform(t); 0147 if (constantOpacity) { 0148 m_origPainter->setOpacity(opacity); 0149 } 0150 m_origPainter->drawPixmap(m_off - trans, *m_buf, QRect(0, 0, m_rect.width(), m_rect.height())); 0151 m_origPainter->restore(); 0152 } 0153 0154 static BufferedPainter *start(QPainter *&, const QRegion &); 0155 static void end(QPainter *&, BufferedPainter *bp, float opacity = 1.0); 0156 0157 const QPainter *painter() const 0158 { 0159 return &m_painter; 0160 } 0161 QPainter *originalPainter() const 0162 { 0163 return m_origPainter; 0164 } 0165 QPixmap *buffer() const 0166 { 0167 return m_buf; 0168 } 0169 private: 0170 bool m_paused; 0171 QRect m_rect; 0172 QRegion m_region; 0173 QPoint m_off; 0174 QPainter m_painter; 0175 QPixmap *m_buf; 0176 QPainter *m_origPainter; 0177 }; 0178 0179 } 0180 #endif