File indexing completed on 2024-04-14 15:01:16
0001 /** 0002 This file belong to the KMPlayer project, a movie player plugin for Konqueror 0003 Copyright (C) 2008 Koos Vriezen <koos.vriezen@gmail.com> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Lesser General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Lesser General Public License for more details. 0014 0015 You should have received a copy of the GNU Lesser General Public 0016 License along with this library; if not, write to the Free Software 0017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0018 **/ 0019 0020 #include "config-kmplayer.h" 0021 0022 #ifdef KMPLAYER_WITH_CAIRO 0023 # include <cairo.h> 0024 #endif 0025 0026 #include <qwidget.h> 0027 0028 #include <kdebug.h> 0029 0030 #include "surface.h" 0031 #include "viewarea.h" 0032 0033 using namespace KMPlayer; 0034 0035 0036 KDE_NO_CDTOR_EXPORT Surface::Surface (ViewArea *widget) 0037 : bounds(SRect(0, 0, 0038 #if QT_VERSION >= 0x050600 0039 widget->width() * widget->devicePixelRatioF(), 0040 widget->height() * widget->devicePixelRatioF() 0041 #else 0042 widget->width(), widget->height() 0043 #endif 0044 )), 0045 xscale (1.0), yscale (1.0), 0046 background_color (0), 0047 #ifdef KMPLAYER_WITH_CAIRO 0048 surface (0L), 0049 #endif 0050 dirty (false), 0051 scroll (false), 0052 has_mouse (false), 0053 view_widget (widget) 0054 {} 0055 0056 Surface::~Surface() { 0057 #ifdef KMPLAYER_WITH_CAIRO 0058 if (surface) 0059 cairo_surface_destroy (surface); 0060 #endif 0061 } 0062 0063 template <> void TreeNode<Surface>::appendChild (Surface *c) { 0064 appendChildImpl (c); 0065 } 0066 0067 template <> void TreeNode<Surface>::insertBefore (Surface *c, Surface *b) { 0068 insertBeforeImpl (c, b); 0069 } 0070 0071 template <> void TreeNode<Surface>::removeChild (SurfacePtr c) { 0072 removeChildImpl (c); 0073 } 0074 0075 void Surface::clear () { 0076 m_first_child = 0L; 0077 background_color = 0; 0078 } 0079 0080 void Surface::remove () { 0081 Surface *sp = parentNode (); 0082 if (sp) { 0083 sp->markDirty (); 0084 sp->removeChild (this); 0085 } 0086 } 0087 0088 void Surface::resize (const SRect &rect, bool parent_resized) { 0089 SRect old_bounds = bounds; 0090 bounds = rect; 0091 if (parent_resized || old_bounds != rect) { 0092 0093 if (parent_resized || old_bounds.size != rect.size) { 0094 virtual_size = SSize (); //FIXME try to preserve scroll on resize 0095 markDirty (); 0096 #ifdef KMPLAYER_WITH_CAIRO 0097 if (surface) { 0098 cairo_surface_destroy (surface); 0099 surface = NULL; 0100 } 0101 #endif 0102 updateChildren (true); 0103 } else if (parentNode ()) { 0104 parentNode ()->markDirty (); 0105 } 0106 if (parentNode ()) 0107 parentNode ()->repaint (old_bounds.unite (rect)); 0108 else 0109 repaint (); 0110 } 0111 } 0112 0113 void Surface::markDirty () { 0114 for (Surface *s = this; s && !s->dirty; s = s->parentNode ()) 0115 s->dirty = true; 0116 } 0117 0118 void Surface::updateChildren (bool parent_resized) { 0119 for (Surface *c = firstChild (); c; c = c->nextSibling ()) 0120 if (c->node) 0121 c->node->message (MsgSurfaceBoundsUpdate, (void *) parent_resized); 0122 else 0123 kError () << "Surface without node"; 0124 } 0125 0126 Surface *Surface::createSurface (NodePtr owner, const SRect & rect) { 0127 Surface *surface = new Surface (view_widget); 0128 surface->node = owner; 0129 surface->bounds = rect; 0130 appendChild (surface); 0131 return surface; 0132 } 0133 0134 KDE_NO_EXPORT IRect Surface::toScreen (const SSize &size) { 0135 //FIXME: handle scroll 0136 Matrix matrix (0, 0, xscale, yscale); 0137 matrix.translate (bounds.x (), bounds.y ()); 0138 for (Surface *s = parentNode(); s; s = s->parentNode()) { 0139 matrix.transform(Matrix (0, 0, s->xscale, s->yscale)); 0140 matrix.translate (s->bounds.x (), s->bounds.y ()); 0141 } 0142 return matrix.toScreen (SRect (0, 0, size)); 0143 } 0144 0145 void Surface::setBackgroundColor (unsigned int argb) { 0146 #ifdef KMPLAYER_WITH_CAIRO 0147 if (surface && 0148 ((background_color & 0xff000000) < 0xff000000) != 0149 ((argb & 0xff000000) < 0xff000000)) { 0150 cairo_surface_destroy (surface); 0151 surface = NULL; 0152 } 0153 #endif 0154 background_color = argb; 0155 } 0156 0157 static void clipToScreen (Surface *s, Matrix &m, IRect &clip) { 0158 Surface *ps = s->parentNode (); 0159 if (!ps) { 0160 clip = IRect (s->bounds.x (), s->bounds.y (), 0161 s->bounds.width (), s->bounds.height ()); 0162 m = Matrix (s->bounds.x (), s->bounds.y (), s->xscale, s->yscale); 0163 } else { 0164 clipToScreen (ps, m, clip); 0165 IRect scr = m.toScreen (s->bounds); 0166 clip = clip.intersect (scr); 0167 Matrix m1 = m; 0168 m = Matrix (s->bounds.x (), s->bounds.y (), s->xscale, s->yscale); 0169 m.transform (m1); 0170 if (!s->virtual_size.isEmpty ()) 0171 m.translate (-s->x_scroll, -s->y_scroll); 0172 } 0173 } 0174 0175 0176 KDE_NO_EXPORT void Surface::repaint (const SRect &rect) { 0177 Matrix matrix; 0178 IRect clip; 0179 clipToScreen (this, matrix, clip); 0180 IRect scr = matrix.toScreen (rect); 0181 clip = clip.intersect (scr); 0182 if (!clip.isEmpty ()) 0183 view_widget->scheduleRepaint (clip); 0184 } 0185 0186 KDE_NO_EXPORT void Surface::repaint () { 0187 Surface *ps = parentNode (); 0188 if (ps) 0189 ps->repaint (bounds); 0190 else 0191 view_widget->scheduleRepaint (IRect (bounds.x (), bounds.y (), 0192 bounds.width (), bounds.height ())); 0193 } 0194