QModelIndex HistogramView::indexAt(const QPoint &point)const
{
    QPoint newPoint(point.x(),point.y());
    QRegion region;
    foreach(region,MRegionList)				// 男 列
    {
        if (region.contains(newPoint))
        {
            int row = MRegionList.indexOf(region);
            QModelIndex index = model()->index(row,1,rootIndex());
            return index;
        }
    }
    foreach(region,FRegionList)				// 女 列
    {
        if (region.contains(newPoint))
        {
            int row = FRegionList.indexOf(region);
            QModelIndex index = model()->index(row,2,rootIndex());
            return index;
        }
    }
    foreach(region,SRegionList)				// 合计 列
    {
        if (region.contains(newPoint))
        {
            int row = SRegionList.indexOf(region);
            QModelIndex index = model()->index(row,3,rootIndex());
            return index;
        }
    }
    return QModelIndex();
}
Ejemplo n.º 2
0
void tst_QRegion::polygonRegion()
{
    QPolygon pa;
    {
	QRegion region ( pa );
	QVERIFY( region.isEmpty() );
    }
    {
	pa.setPoints( 8, 10, 10, //  a____________b
			 40, 10, //  |            |
			 40, 20, //  |___      ___|
			 30, 20, //      |    |
			 30, 40, //      |    |
			 20, 40, //      |    |
			 20, 20, //      |____c
			 10, 20 );

	QRegion region ( pa );
	QVERIFY( !region.isEmpty() );

	// These should not be inside the circle
	QVERIFY( !region.contains( QPoint(  9,  9 ) ) );
	QVERIFY( !region.contains( QPoint( 30, 41 ) ) );
	QVERIFY( !region.contains( QPoint( 41, 10 ) ) );
	QVERIFY( !region.contains( QPoint( 31, 21 ) ) );

	// These should be inside
	QVERIFY( region.contains( QPoint( 10, 10 ) ) ); // Upper-left  (a)

    }
}
Ejemplo n.º 3
0
/*
 * Pr黤t, ob ein Element in einem anderen liegt. Dabei nehmen wir an, dass GRASS eine
 * Fehlermeldung ausgibt, wenn sich zwei Elemente schneiden. Somit reicht es hier aus,
 * nur einen Punkt zu pr黤en.
 */
void proofeIntersections(QList<struct element>* eList)
{
  warning("Pr黤e 躡erschneidungen ...");

  QList<QRegion> regList;

  for(unsigned int loop = 0; loop < eList->count() - 1; loop++)
    {
      struct element* elA = eList->at(loop);

      QPointArray pArray(elA->pointList.count());

      for(unsigned int pLoop = 0; pLoop < elA->pointList.count(); pLoop++)
	{
	  pArray.setPoint(pLoop, QPoint(elA->pointList.at(pLoop)->latitude / 2000,
					elA->pointList.at(pLoop)->longitude / 2000));
	}

      for(unsigned int regLoop = 0; regLoop < regList.count(); regLoop++)
	{
	  QRegion* testReg = regList.at(regLoop);

	  if(testReg->contains(pArray.point(0)))
	    {
	      // Element ist in fr黨erer Region enthalten ...
	      elA->isValley = !eList->at(regLoop)->isValley;
	      elA->sortID++;
	    }
	}

      regList.append(new QRegion(pArray));
    }

  warning("   ... fertig");
}
Ejemplo n.º 4
0
//
// Paint all channel labels
//
void Monitor::paintChannelLabelAll(QRegion region, int x_offset, int y_offset,
				   int unitW, int unitH, int unitsX)
{
	int x = 0;
	int y = 0;
	int i = 0;
	QString s;
	
	for (i = 0; i < 512; i++)
	{
		// Calculate x and y positions for this channel
		x = ((i % unitsX) * (unitW));
		x += x_offset;
		
		y = unitH + static_cast<int> 
			(floor((i / unitsX)) * (unitH * 3));
		y += y_offset;
		
		if (region.contains(QRect(x, y, unitW, unitH)))
		{
			// Paint channel label
			paintChannelLabel(x, y, unitW, unitH,
					  s.sprintf("%.3d", i + 1));
		}
	}
}
Ejemplo n.º 5
0
//
// Paint all visible fixture labels
//
void Monitor::paintFixtureLabelAll(QRegion region, int x_offset, int y_offset,
				   int unitW, int unitH, int unitsX)
{
	int x = 0;
	int y = 0;
	int w = 0;
	int wcur = 0;
	int h = 0;
	
	t_fixture_id id = KNoID;
	Fixture* fxi = NULL;
	
	// Draw fixture names and their channel spaces
	for (id = 0; id < KFixtureArraySize; id++)
	{
		fxi = _app->doc()->fixture(id);
		if (fxi == NULL) continue;
		if (fxi->universe() != m_universe) continue;
		
		// Calculate x and y positions for this fixture label
		x = ((fxi->address() % unitsX) * unitW);
		x += x_offset;
		
		y = static_cast<int> 
			(floor((fxi->address() / unitsX)) * (unitH * 3));
		y += y_offset;
		
		// Get width and height for this fixture label
		w = (fxi->channels() * unitW) - X_OFFSET;
		h = unitH;
			
		// Check if this label needs to be painted at all
		if (region.contains(QRect(x, y, w, h)) == false)
			continue;

		if ((x + w + X_OFFSET) <= width())
		{
			// The label fits to one line, just draw it
			paintFixtureLabel(x, y, w, h, fxi->name());
		}
		else
		{
			// The label needs to be drawn on at least two lines
			while (w > 0)
			{	
				wcur = MIN(w, (unitsX * unitW) - (x));
				
				// Draw the label
				paintFixtureLabel(x, y, wcur, h, fxi->name());
			
				// Calculate remaining width
				w = w - wcur - X_OFFSET;
				
				// Next line
				y += (unitH * 3);
				x = x_offset;
			}
		}
	}
}
Ejemplo n.º 6
0
void QWidget::updateCursor( const QRegion &r ) const
{
    if ( qt_last_x && (!QWidget::mouseGrabber() || QWidget::mouseGrabber() == this) &&
	    qt_last_cursor != (WId)cursor().handle() && !qws_overrideCursor ) {
	QSize s( qt_screen->width(), qt_screen->height() );
	QPoint pos = qt_screen->mapToDevice(QPoint(*qt_last_x, *qt_last_y), s);
	if ( r.contains(pos) )
	    qwsDisplay()->selectCursor((QWidget*)this, (unsigned int)cursor().handle());
    }
}
Ejemplo n.º 7
0
void LDesktop::UpdateDesktopPluginArea(){
  QRegion visReg( bgWindow->geometry() ); //visible region (not hidden behind a panel)
  QRect rawRect = visReg.boundingRect(); //initial value (screen size)
  for(int i=0; i<PANELS.length(); i++){
    QRegion shifted = visReg;
    QString loc = settings->value(PANELS[i]->prefix()+"location","top").toString().toLower();
    int vis = PANELS[i]->visibleWidth();
    if(loc=="top"){ 
      if(!shifted.contains(QRect(rawRect.x(), rawRect.y(), rawRect.width(), vis))){ continue; }
      shifted.translate(0, (rawRect.top()+vis)-shifted.boundingRect().top() ); 
    }else if(loc=="bottom"){
      if(!shifted.contains(QRect(rawRect.x(), rawRect.bottom()-vis, rawRect.width(), vis))){ continue; }	    
      shifted.translate(0, (rawRect.bottom()-vis)-shifted.boundingRect().bottom()); 
    }else if(loc=="left"){ 
      if( !shifted.contains(QRect(rawRect.x(), rawRect.y(), vis,rawRect.height())) ){ continue; }
      shifted.translate((rawRect.left()+vis)-shifted.boundingRect().left() ,0); 
    }else{  //right
      if(!shifted.contains(QRect(rawRect.right()-vis, rawRect.y(), vis,rawRect.height())) ){ continue; }
      shifted.translate((rawRect.right()-vis)-shifted.boundingRect().right(),0); 
    }
    visReg = visReg.intersected( shifted );
  }
  //Now make sure the desktop plugin area is only the visible area
  QRect rec = visReg.boundingRect();
  //LSession::handle()->XCB->SetScreenWorkArea((unsigned int) desktopnumber, rec);
  //Now remove the X offset to place it on the current screen (needs widget-coords, not global)
  globalWorkRect = rec; //save this for later
  rec.moveTopLeft( QPoint( rec.x()-desktop->screenGeometry(desktopnumber).x() , rec.y() ) );
  //qDebug() << "DPlug Area:" << rec.x() << rec.y() << rec.width() << rec.height();
  if(rec == bgDesktop->geometry()){return; } //nothing changed
  bgDesktop->setGeometry( rec );
  bgDesktop->setBackground( QBrush(Qt::NoBrush) );
  bgDesktop->update();
  //Re-paint the panels (just in case a plugin was underneath it and the panel is transparent)
  for(int i=0; i<PANELS.length(); i++){ PANELS[i]->update(); }
  //Also need to re-arrange any desktop plugins to ensure that nothing is out of the screen area
  AlignDesktopPlugins();
  //Make sure to re-disable any WM control flags
  LSession::handle()->XCB->SetDisableWMActions(bgWindow->winId());
}
Ejemplo n.º 8
0
/*!
  See QwtAbstractSlider::getScrollMode()

  \param pos point where the mouse was pressed
  \retval scrollMode The scrolling mode
  \retval direction  direction: 1, 0, or -1.

  \sa QwtAbstractSlider::getScrollMode()
*/
void QwtDial::getScrollMode( const QPoint &pos,
    QwtAbstractSlider::ScrollMode &scrollMode, int &direction ) const
{
    direction = 0;
    scrollMode = QwtAbstractSlider::ScrNone;

    const QRegion region( innerRect().toRect(), QRegion::Ellipse );
    if ( region.contains( pos ) && pos != innerRect().center() )
    {
        scrollMode = QwtAbstractSlider::ScrMouse;
        d_data->previousDir = -1.0;
    }
}
Ejemplo n.º 9
0
void Document::paintEvent(QPaintEvent *event)
{
    QRegion paintRegion = event->region();
    QPainter painter(this);
    QPalette pal = palette();

    for (int i = 0; i < m_shapeList.count(); ++i) {
        const Shape &shape = m_shapeList.at(i);

        if (!paintRegion.contains(shape.rect()))
            continue;

        QPen pen = pal.text().color();
        pen.setWidth(i == m_currentIndex ? 2 : 1);
        painter.setPen(pen);
        painter.setBrush(gradient(shape.color(), shape.rect()));

        QRect rect = shape.rect();
        rect.adjust(1, 1, -resizeHandleWidth/2, -resizeHandleWidth/2);

        // paint the shape
        switch (shape.type()) {
            case Shape::Rectangle:
                painter.drawRect(rect);
                break;
            case Shape::Circle:
                painter.setRenderHint(QPainter::Antialiasing);
                painter.drawEllipse(rect);
                painter.setRenderHint(QPainter::Antialiasing, false);
                break;
            case Shape::Triangle:
                painter.setRenderHint(QPainter::Antialiasing);
                painter.drawPolygon(triangle(rect));
                painter.setRenderHint(QPainter::Antialiasing, false);
                break;
        }

        // paint the resize handle
        painter.setPen(pal.text().color());
        painter.setBrush(Qt::white);
        painter.drawRect(shape.resizeHandle().adjusted(0, 0, -1, -1));

        // paint the shape name
        painter.setBrush(pal.text());
        if (shape.type() == Shape::Triangle)
            rect.adjust(0, rect.height()/2, 0, 0);
        painter.drawText(rect, Qt::AlignCenter, shape.name());
    }
}
Ejemplo n.º 10
0
QModelIndex PieView::indexAt(const QPoint &point) const
{
    QPoint newPoint(point.x(),point.y());
    QRegion region;
    foreach(region,RegionList)				// 销售数量 列
    {
        if (region.contains(newPoint))
        {
            int row = RegionList.indexOf(region);
            QModelIndex index = model()->index(row,1,rootIndex());
            return index;
        }
    }
    return QModelIndex();
}
Ejemplo n.º 11
0
WangId WangFiller::wangIdFromSurroundings(const TileLayer &back,
                                          const QRegion &fillRegion,
                                          QPoint point) const
{
    Cell surroundingCells[8];

    QPoint adjacentPoints[8];
    getSurroundingPoints(point, mStaggeredRenderer, mStaggerAxis, adjacentPoints);

    for (int i = 0; i < 8; ++i) {
        if (!fillRegion.contains(adjacentPoints[i]))
            surroundingCells[i] = back.cellAt(adjacentPoints[i]);
    }

    return mWangSet->wangIdFromSurrounding(surroundingCells);
}
Ejemplo n.º 12
0
void ThumbnailAsideEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
    {
    effects->paintScreen( mask, region, data );
    foreach( const Data& d, windows )
        {
        if( region.contains( d.rect ))
            {
            WindowPaintData data( d.window );
            data.opacity = opacity;
            QRect region;
            setPositionTransformations( data, region, d.window, d.rect, Qt::KeepAspectRatio );
            effects->drawWindow( d.window, PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_TRANSFORMED,
                region, data );
            }
        }
    }
Ejemplo n.º 13
0
const QList<MapObject*> objectsInRegion(const ObjectGroup *layer,
                                        const QRegion &where)
{
    QList<MapObject*> ret;
    for (MapObject *obj : layer->objects()) {
        // TODO: we are checking bounds, which is only correct for rectangles and
        // tile objects. polygons and polylines are not covered correctly by this
        // erase method (we are in fact deleting too many objects)
        // TODO2: toAlignedRect may even break rects.
        const QRect rect = obj->boundsUseTile().toAlignedRect();

        // QRegion::intersects() returns false for empty regions even if they are
        // contained within the region, so we also check for containment of the
        // top left to include the case of zero size objects.
        if (where.intersects(rect) || where.contains(rect.topLeft()))
            ret += obj;
    }
    return ret;
}
Ejemplo n.º 14
0
//
// Paint all channel values
//
void Monitor::paintChannelValueAll(QRegion region, int x_offset, int y_offset,
				   int unitW, int unitH, int unitsX,
				   bool onlyDelta)
{
	int x = 0;
	int y = 0;
	int value = 0;
	int i = 0;
	
	QString s;

	// Set normal text color to painter
	m_painter.setPen(palette().color(QPalette::Text));
	
	for (i = 0; i < 512; i++)
	{
		// Lock value array
		m_valueMutex.lock();
	
		if (onlyDelta && m_oldValues[i] == m_newValues[i])
		{
			m_valueMutex.unlock();
			continue;
		}
		
		m_oldValues[i] = m_newValues[i];

		// Get channel value from array;
		value = m_newValues[i];
		
		// Unlock array
		m_valueMutex.unlock();
		
		// Calculate xy position for this channel
		x = ((i % unitsX) * (unitW));
		x += x_offset;
		
		y = (unitH * 2) + 
		    static_cast<int> (floor((i / unitsX)) * (unitH * 3));
		y += y_offset;
		
		// If all values must be drawn, draw only those that are
		// inside the invalidated area, otherwise draw the delta values
		if (!onlyDelta && !region.contains(QRect(x, y, unitW, unitH)))
			continue;
		
		// Draw only those values that are visible
		if (y < height())
		{
			// Convert the value to a string
			s.sprintf("%.3d", value);
		
			// Paint the value
			paintChannelValue(x, y, unitW, unitH, s);

			/* Update the biggest visible channel number only,
			   when the visibility of all channels is being
			   checked */
			if (onlyDelta == false)
				m_visibleMax = i;
		}
		else
		{
			// Rest of the values are not visible either
			break;
		}
	}
}
Ejemplo n.º 15
0
void SlideEffect::desktopChanged( int old )
    {
    if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
        return;
    
    if( slide ) // old slide still in progress
        {
        QPoint diffPos = desktopRect( old ).topLeft() - slide_start_pos;
        int w = 0;
        int h = 0;
        if( effects->optionRollOverDesktops())
            {
            w = effects->workspaceWidth();
            h = effects->workspaceHeight();
            // wrap around if shorter
            if( diffPos.x() > 0 && diffPos.x() > w / 2 )
                diffPos.setX( diffPos.x() - w );
            if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 )
                diffPos.setX( diffPos.x() + w );
            if( diffPos.y() > 0 && diffPos.y() > h / 2 )
                diffPos.setY( diffPos.y() - h );
            if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 )
                diffPos.setY( diffPos.y() + h );
            }
        QPoint currentPos = slide_start_pos + mTimeLine.value() * diffPos;
        QRegion currentRegion = QRect( currentPos, QSize( displayWidth(), displayHeight()));
        if( effects->optionRollOverDesktops())
            {
            currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 );
            currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h );
            currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 );
            currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h );
            }
        QRect rect = desktopRect( effects->currentDesktop() );
        if( currentRegion.contains( rect ))
            { // current position is in new current desktop (e.g. quickly changing back),
              // don't do full progress
            if( abs( currentPos.x() - rect.x()) > abs( currentPos.y() - rect.y()))
                mTimeLine.setProgress(1 - abs( currentPos.x() - rect.x()) / double( displayWidth()));
            else
                mTimeLine.setProgress(1 - abs( currentPos.y() - rect.y()) / double( displayHeight()));
            }
        else // current position is not on current desktop, do full progress
            mTimeLine.setProgress(0);
        diffPos = rect.topLeft() - currentPos;
        if( mTimeLine.value() <= 0 )
            {
            // Compute starting point for this new move (given current and end positions)
            slide_start_pos = rect.topLeft() - diffPos * 1 / ( 1 - mTimeLine.value() );
            }
        else
            { // at the end, stop
            slide = false;
            mTimeLine.setProgress(0);
            effects->setActiveFullScreenEffect( NULL );
            }
        }
    else
        {
        if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
            return;
        mTimeLine.setProgress(0);
        slide_start_pos = desktopRect( old ).topLeft();
        slide = true;
        effects->setActiveFullScreenEffect( this );
        }
    effects->addRepaintFull();
    }
Ejemplo n.º 16
0
void SlideEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
    {
    if( mTimeLine.value() == 0 )
        {
        effects->paintScreen( mask, region, data );
        return;
        }
    
    /*
     Transformations are done by remembering starting position of the change and the progress
     of it, the destination is computed from the current desktop. Positions of desktops
     are done using their topleft corner.
    */
    QPoint destPos = desktopRect( effects->currentDesktop() ).topLeft();
    QPoint diffPos = destPos - slide_start_pos;
    int w = 0;
    int h = 0;
    if( effects->optionRollOverDesktops())
        {
        w = effects->workspaceWidth();
        h = effects->workspaceHeight();
        // wrap around if shorter
        if( diffPos.x() > 0 && diffPos.x() > w / 2 )
            diffPos.setX( diffPos.x() - w );
        if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 )
            diffPos.setX( diffPos.x() + w );
        if( diffPos.y() > 0 && diffPos.y() > h / 2 )
            diffPos.setY( diffPos.y() - h );
        if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 )
            diffPos.setY( diffPos.y() + h );
        }
    QPoint currentPos = slide_start_pos + mTimeLine.value() * diffPos;
    QSize displaySize( displayWidth(), displayHeight());
    QRegion currentRegion = QRect( currentPos, displaySize );
    if( effects->optionRollOverDesktops())
        {
        currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 );
        currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h );
        currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 );
        currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h );
        }
    bool do_sticky = true;
    for( int desktop = 1;
         desktop <= effects->numberOfDesktops();
         ++desktop )
        {
        QRect rect = desktopRect( desktop );
        if( currentRegion.contains( rect )) // part of the desktop needs painting
            {
            painting_desktop = desktop;
            slide_painting_sticky = do_sticky;
            slide_painting_diff = rect.topLeft() - currentPos;
            if( effects->optionRollOverDesktops())
                {
                if( slide_painting_diff.x() > displayWidth())
                    slide_painting_diff.setX( slide_painting_diff.x() - w );
                if( slide_painting_diff.x() < -displayWidth())
                    slide_painting_diff.setX( slide_painting_diff.x() + w );
                if( slide_painting_diff.y() > displayHeight())
                    slide_painting_diff.setY( slide_painting_diff.y() - h );
                if( slide_painting_diff.y() < -displayHeight())
                    slide_painting_diff.setY( slide_painting_diff.y() + h );
                }
            do_sticky = false; // paint on-all-desktop windows only once
            ScreenPaintData d = data;
            d.xTranslate += slide_painting_diff.x();
            d.yTranslate += slide_painting_diff.y();
            // TODO mask parts that are not visible?
            effects->paintScreen( mask, region, d );
            }
        }
    }
Ejemplo n.º 17
0
void PlastikClient::paintEvent(QPaintEvent *e)
{
    QRegion region = e->region();

    PlastikHandler *handler = Handler();

    if(oldCaption != caption())
        clearCaptionPixmaps();

    bool active = isActive();
    bool toolWindow = isToolWindow();

    QPainter painter(widget());

    // often needed coordinates
    QRect r = widget()->rect();

    int r_w = r.width();
    //     int r_h = r.height();
    int r_x, r_y, r_x2, r_y2;
    r.coords(&r_x, &r_y, &r_x2, &r_y2);
    const int borderLeft = layoutMetric(LM_BorderLeft);
    const int borderRight = layoutMetric(LM_BorderRight);
    const int borderBottom = layoutMetric(LM_BorderBottom);
    const int titleHeight = layoutMetric(LM_TitleHeight);
    const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
    const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
    const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
    const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);

    const int borderBottomTop = r_y2 - borderBottom + 1;
    const int borderLeftRight = r_x + borderLeft - 1;
    const int borderRightLeft = r_x2 - borderRight + 1;
    const int titleEdgeBottomBottom = r_y + titleEdgeTop + titleHeight + titleEdgeBottom - 1;

    const int sideHeight = borderBottomTop - titleEdgeBottomBottom - 1;

    QRect Rtitle =
        QRect(r_x + titleEdgeLeft + buttonsLeftWidth(), r_y + titleEdgeTop,
              r_x2 - titleEdgeRight - buttonsRightWidth() - (r_x + titleEdgeLeft + buttonsLeftWidth()), titleEdgeBottomBottom - (r_y + titleEdgeTop));

    QRect tempRect;

    // topSpacer
    if(titleEdgeTop > 0)
    {
        tempRect.setRect(r_x + 2, r_y, r_w - 2 * 2, titleEdgeTop);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarTileTop, active, toolWindow));
        }
    }

    // leftTitleSpacer
    int titleMarginLeft = 0;
    int titleMarginRight = 0;
    if(titleEdgeLeft > 0)
    {
        tempRect.setRect(r_x, r_y, borderLeft, titleEdgeTop + titleHeight + titleEdgeBottom);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarLeft, active, toolWindow));
            titleMarginLeft = borderLeft;
        }
    }

    // rightTitleSpacer
    if(titleEdgeRight > 0)
    {
        tempRect.setRect(borderRightLeft, r_y, borderRight, titleEdgeTop + titleHeight + titleEdgeBottom);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarRight, active, toolWindow));
            titleMarginRight = borderRight;
        }
    }

    // titleSpacer
    const QPixmap &caption = captionPixmap();
    if(Rtitle.width() > 0)
    {
        m_captionRect = captionRect(); // also update m_captionRect!
        if(m_captionRect.isValid() && region.contains(m_captionRect))
        {
            painter.drawTiledPixmap(m_captionRect, caption);
        }

        // left to the title
        tempRect.setRect(r_x + titleMarginLeft, m_captionRect.top(), m_captionRect.left() - (r_x + titleMarginLeft), m_captionRect.height());
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarTile, active, toolWindow));
        }

        // right to the title
        tempRect.setRect(m_captionRect.right() + 1, m_captionRect.top(), (r_x2 - titleMarginRight) - m_captionRect.right(), m_captionRect.height());
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(TitleBarTile, active, toolWindow));
        }
    }

    // leftSpacer
    if(borderLeft > 0 && sideHeight > 0)
    {
        tempRect.setCoords(r_x, titleEdgeBottomBottom + 1, borderLeftRight, borderBottomTop - 1);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(BorderLeftTile, active, toolWindow));
        }
    }

    // rightSpacer
    if(borderRight > 0 && sideHeight > 0)
    {
        tempRect.setCoords(borderRightLeft, titleEdgeBottomBottom + 1, r_x2, borderBottomTop - 1);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(BorderRightTile, active, toolWindow));
        }
    }

    // bottomSpacer
    if(borderBottom > 0)
    {
        int l = r_x;
        int r = r_x2;

        tempRect.setRect(r_x, borderBottomTop, borderLeft, borderBottom);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(BorderBottomLeft, active, toolWindow));
            l = tempRect.right() + 1;
        }

        tempRect.setRect(borderRightLeft, borderBottomTop, borderLeft, borderBottom);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(BorderBottomRight, active, toolWindow));
            r = tempRect.left() - 1;
        }

        tempRect.setCoords(l, borderBottomTop, r, r_y2);
        if(tempRect.isValid() && region.contains(tempRect))
        {
            painter.drawTiledPixmap(tempRect, handler->pixmap(BorderBottomTile, active, toolWindow));
        }
    }
}
Ejemplo n.º 18
0
std::unique_ptr<TileLayer> WangFiller::fillRegion(const TileLayer &back,
                                                  const QRegion &fillRegion) const
{
    Q_ASSERT(mWangSet);

    const QRect boundingRect = fillRegion.boundingRect();

    std::unique_ptr<TileLayer> tileLayer { new TileLayer(QString(),
                                                         boundingRect.x(),
                                                         boundingRect.y(),
                                                         boundingRect.width(),
                                                         boundingRect.height()) };

    QVector<WangId> wangIds(tileLayer->width() * tileLayer->height(), 0);
#if QT_VERSION < 0x050800
    const auto rects = fillRegion.rects();
    for (const QRect &rect : rects) {
#else
    for (const QRect &rect : fillRegion) {
#endif
        for (int x = rect.left(); x <= rect.right(); ++x) {
            int index = x - tileLayer->x() + (rect.top() - tileLayer->y()) * tileLayer->width();
            wangIds[index] = wangIdFromSurroundings(back,
                                                    fillRegion,
                                                    QPoint(x, rect.top()));

            index = x - tileLayer->x() + (rect.bottom() - tileLayer->y()) * tileLayer->width();
            wangIds[index] = wangIdFromSurroundings(back,
                                                    fillRegion,
                                                    QPoint(x, rect.bottom()));
        }
        for (int y = rect.top() + 1; y < rect.bottom(); ++y) {
            int index = rect.left() - tileLayer->x() + (y - tileLayer->y()) * tileLayer->width();
            wangIds[index] = wangIdFromSurroundings(back,
                                                    fillRegion,
                                                    QPoint(rect.left(), y));

            index = rect.right() - tileLayer->x() + (y - tileLayer->y()) * tileLayer->width();
            wangIds[index] = wangIdFromSurroundings(back,
                                                    fillRegion,
                                                    QPoint(rect.right(), y));
        }
    }

#if QT_VERSION < 0x050800
    for (const QRect &rect : rects) {
#else
    for (const QRect &rect : fillRegion) {
#endif
        for (int y = rect.top(); y <= rect.bottom(); ++y) {
            for (int x = rect.left(); x <= rect.right(); ++x) {
                QPoint currentPoint(x, y);
                int currentIndex = (currentPoint.y() - tileLayer->y()) * tileLayer->width() + (currentPoint.x() - tileLayer->x());

                QList<WangTile> wangTilesList = mWangSet->findMatchingWangTiles(wangIds[currentIndex]);
                RandomPicker<WangTile> wangTiles;

                for (const WangTile &wangTile : wangTilesList)
                    wangTiles.add(wangTile, mWangSet->wangTileProbability(wangTile));

                while (!wangTiles.isEmpty()) {
                    WangTile wangTile = wangTiles.take();

                    bool fill = true;
                    if (!mWangSet->isComplete()) {
                        QPoint adjacentPoints[8];
                        getSurroundingPoints(currentPoint, mStaggeredRenderer, mStaggerAxis, adjacentPoints);

                        for (int i = 0; i < 8; ++i) {
                            QPoint p = adjacentPoints[i];
                            if (!fillRegion.contains(p) || !tileLayer->cellAt(p - tileLayer->position()).isEmpty())
                                continue;
                            p -= tileLayer->position();
                            int index = p.y() * tileLayer->width() + p.x();

                            WangId adjacentWangId = wangIds[index];
                            adjacentWangId.updateToAdjacent(wangTile.wangId(), (i + 4) % 8);

                            if (!mWangSet->wildWangIdIsUsed(adjacentWangId)) {
                                fill = wangTiles.isEmpty();

                                break;
                            }
                        }
                    }

                    if (fill) {
                        tileLayer->setCell(currentPoint.x() - tileLayer->x(),
                                           currentPoint.y() - tileLayer->y(),
                                           wangTile.makeCell());
                        QPoint adjacentPoints[8];
                        getSurroundingPoints(currentPoint, mStaggeredRenderer, mStaggerAxis, adjacentPoints);
                        for (int i = 0; i < 8; ++i) {
                            QPoint p = adjacentPoints[i];
                            if (!fillRegion.contains(p) || !tileLayer->cellAt(p - tileLayer->position()).isEmpty())
                                continue;
                            p -= tileLayer->position();
                            int index = p.y() * tileLayer->width() + p.x();
                            wangIds[index].updateToAdjacent(wangTile.wangId(), (i + 4) % 8);
                        }
                        break;
                    }
                }
            }
        }
    }

    return tileLayer;
}

const Cell &WangFiller::getCell(const TileLayer &back,
                                const TileLayer &front,
                                const QRegion &fillRegion,
                                QPoint point) const
{
    if (!fillRegion.contains(point))
        return back.cellAt(point);
    else
        return front.cellAt(point.x() - front.x(), point.y() - front.y());
}


WangId WangFiller::wangIdFromSurroundings(const TileLayer &back,
                                          const TileLayer &front,
                                          const QRegion &fillRegion,
                                          QPoint point) const
{
    Cell surroundingCells[8];
    QPoint adjacentPoints[8];
    getSurroundingPoints(point, mStaggeredRenderer, mStaggerAxis, adjacentPoints);

    for (int i = 0; i < 8; ++i)
        surroundingCells[i] = getCell(back, front, fillRegion, adjacentPoints[i]);

    return mWangSet->wangIdFromSurrounding(surroundingCells);
}

WangId WangFiller::wangIdFromSurroundings(const TileLayer &back,
                                          const QRegion &fillRegion,
                                          QPoint point) const
{
    Cell surroundingCells[8];

    QPoint adjacentPoints[8];
    getSurroundingPoints(point, mStaggeredRenderer, mStaggerAxis, adjacentPoints);

    for (int i = 0; i < 8; ++i) {
        if (!fillRegion.contains(adjacentPoints[i]))
            surroundingCells[i] = back.cellAt(adjacentPoints[i]);
    }

    return mWangSet->wangIdFromSurrounding(surroundingCells);
}
Ejemplo n.º 19
0
void TextLayer::recreateTexture(VidgfxContext *gfx)
{
	if(!m_isTexDirty)
		return; // Don't waste any time if it hasn't changed
	m_isTexDirty = false;

	// Delete existing texture if one exists
	if(m_texture != NULL)
		vidgfx_context_destroy_tex(gfx, m_texture);
	m_texture = NULL;

	// Determine texture size. We need to keep in mind that the text in the
	// document might extend outside of the layer's bounds.
	m_document.setTextWidth(m_rect.width());
	QSize size(
		(int)ceilf(m_document.size().width()),
		(int)ceilf(m_document.size().height()));

	if(m_document.isEmpty() || size.isEmpty()) {
		// Nothing to display
		return;
	}

	// Create temporary canvas. We need to be careful here as text is rendered
	// differently on premultiplied vs non-premultiplied pixel formats. On a
	// premultiplied format text is rendered with subpixel rendering enabled
	// while on a non-premultiplied format it is not. As we don't want subpixel
	// rendering we use the standard ARGB32 format.
	QSize imgSize(
		size.width() + m_strokeSize * 2, size.height() + m_strokeSize * 2);
	QImage img(imgSize, QImage::Format_ARGB32);
	img.fill(Qt::transparent);
	QPainter p(&img);
	p.setRenderHint(QPainter::Antialiasing, true);

	// Render text
	//m_document.drawContents(&p);

	// Render stroke
	if(m_strokeSize > 0) {
#define STROKE_TECHNIQUE 0
#if STROKE_TECHNIQUE == 0
		// Technique 0: Use QTextDocument's built-in text outliner
		//quint64 timeStart = App->getUsecSinceExec();

		QTextDocument *outlineDoc = m_document.clone(this);

		QTextCharFormat format;
		QPen pen(m_strokeColor, (double)(m_strokeSize * 2));
		pen.setJoinStyle(Qt::RoundJoin);
		format.setTextOutline(pen);
		QTextCursor cursor(outlineDoc);
		cursor.select(QTextCursor::Document);
		cursor.mergeCharFormat(format);

		// Take into account the stroke offset
		p.translate(m_strokeSize, m_strokeSize);

		//quint64 timePath = App->getUsecSinceExec();
		outlineDoc->drawContents(&p);
		delete outlineDoc;

		//quint64 timeEnd = App->getUsecSinceExec();
		//appLog() << "Path time = " << (timePath - timeStart) << " usec";
		//appLog() << "Render time = " << (timeEnd - timePath) << " usec";
		//appLog() << "Full time = " << (timeEnd - timeStart) << " usec";
#elif STROKE_TECHNIQUE == 1
		// Technique 1: Create a text QPainterPath and stroke it
		quint64 timeStart = App->getUsecSinceExec();

		// Create the path for the text's stroke
		QPainterPath path;
		QTextBlock &block = m_document.firstBlock();
		int numBlocks = m_document.blockCount();
		for(int i = 0; i < numBlocks; i++) {
			QTextLayout *layout = block.layout();
			for(int j = 0; j < layout->lineCount(); j++) {
				QTextLine &line = layout->lineAt(j);
				const QString text = block.text().mid(
					line.textStart(), line.textLength());
				QPointF pos = layout->position() + line.position();
				pos.ry() += line.ascent();
				//appLog() << pos << ": " << text;
				path.addText(pos, block.charFormat().font(), text);
			}
			block = block.next();
		}

		quint64 timePath = App->getUsecSinceExec();
		path = path.simplified(); // Fixes gaps with large stroke sizes
		quint64 timeSimplify = App->getUsecSinceExec();

		// Render the path
		//p.strokePath(path, QPen(m_strokeColor, m_strokeSize));

		// Convert it to a stroke
		QPainterPathStroker stroker;
		stroker.setWidth(m_strokeSize);
		//stroker.setCurveThreshold(2.0);
		stroker.setJoinStyle(Qt::RoundJoin);
		path = stroker.createStroke(path);

		// Render the path
		p.fillPath(path, m_strokeColor);

		quint64 timeEnd = App->getUsecSinceExec();
		appLog() << "Path time = " << (timePath - timeStart) << " usec";
		appLog() << "Simplify time = " << (timeSimplify - timePath) << " usec";
		appLog() << "Render time = " << (timeEnd - timeSimplify) << " usec";
		appLog() << "Full time = " << (timeEnd - timeStart) << " usec";
#elif STROKE_TECHNIQUE == 2
		// Technique 2: Similar to technique 1 but do each block separately
		quint64 timeStart = App->getUsecSinceExec();
		quint64 timeTotalSimplify = 0;
		quint64 timeTotalRender = 0;

		// Create the path for the text's stroke
		QTextBlock &block = m_document.firstBlock();
		int numBlocks = m_document.blockCount();
		for(int i = 0; i < numBlocks; i++) {
			// Convert this block to a painter path
			QPainterPath path;
			QTextLayout *layout = block.layout();
			for(int j = 0; j < layout->lineCount(); j++) {
				QTextLine &line = layout->lineAt(j);
				const QString text = block.text().mid(
					line.textStart(), line.textLength());
				QPointF pos = layout->position() + line.position() +
					QPointF(m_strokeSize, m_strokeSize);
				pos.ry() += line.ascent();
				//appLog() << pos << ": " << text;
				path.addText(pos, block.charFormat().font(), text);
			}

			// Prevent gaps appearing at larger stroke sizes
			quint64 timeA = App->getUsecSinceExec();
			path = path.simplified();
			quint64 timeB = App->getUsecSinceExec();
			timeTotalSimplify += timeB - timeA;

			// Render the path
			QPen pen(m_strokeColor, m_strokeSize * 2);
			pen.setJoinStyle(Qt::RoundJoin);
			p.strokePath(path, pen);
			timeA = App->getUsecSinceExec();
			timeTotalRender += timeA - timeB;

			// Iterate
			block = block.next();
		}

		// Make the final draw take into account the stroke offset
		p.translate(m_strokeSize, m_strokeSize);

		quint64 timeEnd = App->getUsecSinceExec();
		appLog() << "Simplify time = " << timeTotalSimplify << " usec";
		appLog() << "Render time = " << timeTotalRender << " usec";
		appLog() << "Full time = " << (timeEnd - timeStart) << " usec";
#elif STROKE_TECHNIQUE == 3
		// Technique 3: Raster brute-force where for each destination pixel
		// we measure the distance to the closest opaque source pixel
		quint64 timeStart = App->getUsecSinceExec();

		// Get bounding region based on text line bounding rects
		QRegion region;
		QTextBlock &block = m_document.firstBlock();
		int numBlocks = m_document.blockCount();
		for(int i = 0; i < numBlocks; i++) {
			QTextLayout *layout = block.layout();
			for(int j = 0; j < layout->lineCount(); j++) {
				QTextLine &line = layout->lineAt(j);
				const QString text = block.text().mid(
					line.textStart(), line.textLength());
				QRect rect = line.naturalTextRect()
					.translated(layout->position()).toAlignedRect();
				if(rect.isEmpty())
					continue; // Don't add empty rectangles
				rect.adjust(0, 0, 1, 0); // QTextLine is incorrect?
				rect.adjust(
					-m_strokeSize, -m_strokeSize,
					m_strokeSize, m_strokeSize);
				//appLog() << rect;
				region += rect;
			}

			// Iterate
			block = block.next();
		}
		quint64 timeRegion = App->getUsecSinceExec();

#if 0
		// Debug bounding region
		QPainterPath regionPath;
		regionPath.addRegion(region);
		regionPath.setFillRule(Qt::WindingFill);
		p.fillPath(regionPath, QColor(255, 0, 0, 128));
#endif // 0

		// We cannot read and write to the same image at the same time so
		// create a second one. Note that this is not premultiplied.
		QImage imgOut(size, QImage::Format_ARGB32);
		imgOut.fill(Qt::transparent);

		// Do distance calculation. We assume that non-fully transparent
		// pixels are always next to a fully opaque one so if the closest
		// "covered" pixel is not fully opaque then we can use that pixel's
		// opacity to determine the distance to the shape's edge.
		for(int y = 0; y < img.height(); y++) {
			for(int x = 0; x < img.width(); x++) {
				if(!region.contains(QPoint(x, y)))
					continue;
				float dist = getDistance(img, x, y, m_strokeSize);

				// We fake antialiasing by blurring the edge by 1px
				float outEdge = (float)m_strokeSize;
				if(dist >= outEdge)
					continue; // Outside stroke completely
				float opacity = qMin(1.0f, outEdge - dist);
				QColor col = m_strokeColor;
				col.setAlphaF(col.alphaF() * opacity);

				// Blend the stroke so that it appears under the existing
				// pixel data
				QRgb origRgb = img.pixel(x, y);
				QColor origCol(origRgb);
				origCol.setAlpha(qAlpha(origRgb));
				col = blendColors(col, origCol, 1.0f);
				imgOut.setPixel(x, y, col.rgba());
			}
		}
		quint64 timeRender = App->getUsecSinceExec();

		// Swap image data
		p.end();
		img = imgOut;
		p.begin(&img);

		quint64 timeEnd = App->getUsecSinceExec();
		appLog() << "Region time = " << (timeRegion - timeStart) << " usec";
		appLog() << "Render time = " << (timeRender - timeRegion) << " usec";
		appLog() << "Swap time = " << (timeEnd - timeRender) << " usec";
		appLog() << "Full time = " << (timeEnd - timeStart) << " usec";
#endif // STROKE_TECHNIQUE
	}

	// Render text
	m_document.drawContents(&p);

	// Convert the image to a GPU texture
	m_texture = vidgfx_context_new_tex(gfx, img);

	// Preview texture for debugging
	//img.save(App->getDataDirectory().filePath("Preview.png"));
}
QT_BEGIN_NAMESPACE

/*!
    \class QDecoration
    \ingroup qws

    \brief The QDecoration class is a base class for window
    decorations in Qt for Embedded Linux

    Note that this class is non-portable and only available in
    \l{Qt for Embedded Linux}.

    \l{Qt for Embedded Linux} provides window management of top level windows
    and several ready made decorations (i.e., \c Default, \c Styled
    and \c Windows). Custom decorations can be implemented by
    subclassing the QDecoration class and creating a decoration plugin
    (derived from QDecorationPlugin). The default
    implementation of the QDecorationFactory class will automatically
    detect the plugin, and load the decoration into the application at
    run-time using Qt's \l {How to Create Qt Plugins}{plugin
    system}. To actually apply a decoration, use the
    QApplication::qwsSetDecoration() function.

    When creating a custom decoration, implement the paint() function
    to paint the border and title decoration, and the region()
    function to return the regions the decoration
    occupies. Reimplement the regionClicked() and
    regionDoubleClicked() functions to respond to mouse clicks (the
    default implementations responds to (single) clicks on items in a
    widget's system menu and double clicks on a widget's title).

    QDecoration provides the DecorationRegion enum that describes the
    various regions of the window decoration, and the regionAt()
    function to determine the region containing a given point. The
    QDecoration class also provides the DecorationState enum
    describing the state of a given region, e.g. whether it is active
    or not.

    In addition, it is possible to build the system menu for a given
    top level widget using the buildSysMenu() function; whenever an
    action in this menu is triggered, the menuTriggered() function is
    called automatically.

    Finally, the QDecoration class provides a couple of static
    functions, startMove() and startResize(), which start a move or
    resize action by making the appropriate decoration region active
    and grabbing the mouse input.

    \sa QDecorationFactory, QDecorationPlugin, {Qt for Embedded Linux
    Architecture}
*/

/*!
    \fn QDecoration::QDecoration()

    Constructs a decoration object.
*/

/*!
    \fn QDecoration::~QDecoration()

    Destroys this decoration object.
*/

/*!
    \enum QDecoration::DecorationRegion

    This enum describes the various regions of the window decoration.

    \value All The entire region used by the window decoration.

    \value Top    The top border used to vertically resize the window.
    \value Bottom The bottom border used to vertically resize the window.
    \value Left   The left border used to horizontally resize the window.
    \value Right  The right border used to horizontally resize the window.
    \value TopLeft    The top-left corner of the window used to resize the
                      window both horizontally and vertically.
    \value TopRight   The top-right corner of the window used to resize the
                      window both horizontally and vertically.
    \value BottomLeft The bottom-left corner of the window used to resize the
                      window both horizontally and vertically.
    \value BottomRight The bottom-right corner of the window used to resize the
                      window both horizontally and vertically.
    \value Borders    All the regions used to describe the window's borders.

    \value Title    The region containing the window title, used
                    to move the window by dragging with the mouse cursor.
    \value Close    The region occupied by the close button. Clicking in this
                    region closes the window.
    \value Minimize The region occupied by the minimize button. Clicking in
                    this region minimizes the window.
    \value Maximize The region occupied by the maximize button. Clicking in
                    this region maximizes the window.
    \value Normalize The region occupied by a button used to restore a window's
                     normal size. Clicking in this region restores a maximized
                     window to its previous size. The region used for this
                     button is often also the Maximize region.
    \value Menu     The region occupied by the window's menu button. Clicking
                    in this region opens the window operations (system) menu.
    \value Help     The region occupied by the window's help button. Clicking
                    in this region causes the context-sensitive help function
                    to be enabled.
    \value Resize   The region used to resize the window.
    \value Move     The region used to move the window.
    \value None      No region.

    \sa region(), regionAt(), DecorationState
*/

/*!
    \enum QDecoration::DecorationState

    This enum describes the various states of a decoration region.

    \value Normal The region is active
    \value Disabled The region is inactive.
    \value Hover The cursor is hovering over the region.
    \value Pressed The region is pressed.

    \sa paint(), DecorationRegion
*/

/*!
    \fn QRegion QDecoration::region(const QWidget *widget, const QRect & rectangle, int decorationRegion)

    Implement this function to return the region specified by \a
    decorationRegion for the given top level \a widget.

    The \a rectangle parameter specifies the rectangle the decoration
    is wrapped around. The \a decorationRegion is a bitmask of the
    values described by the DecorationRegion enum.

    \sa regionAt(), paint()
*/

/*!
    \fn QRegion QDecoration::region(const QWidget *widget, int decorationRegion)
    \overload
*/

/*!
    \fn bool QDecoration::paint(QPainter *painter, const QWidget *widget, int decorationRegion,
                                DecorationState state)

    Implement this function to paint the border and title decoration
    for the specified top level \a widget using the given \a painter
    and decoration \a state. The specified \a decorationRegion is a
    bitmask of the values described by the DecorationRegion enum.

    Note that \l{Qt for Embedded Linux} expects this function to return true if
    any of the widget's decorations are repainted; otherwise it should
    return false.

    \sa region()
*/

/*!
    \fn int QDecoration::regionAt(const QWidget *widget, const QPoint &point)

    Returns the type of the first region of the specified top level \a
    widget containing the given \a point.

    The return value is one of the DecorationRegion enum's values. Use
    the region() function to retrieve the actual region. If none of
    the widget's regions contain the point, this function returns \l
    None.

    \sa region()
*/
int QDecoration::regionAt(const QWidget *w, const QPoint &point)
{
    int regions[] = {
        TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight, // Borders first
        Menu, Title, Help, Minimize, Normalize, Maximize, Close,                         // then buttons
        None
    };

//     char *regions_str[] = {
//         "TopLeft", "Top", "TopRight", "Left", "Right", "BottomLeft", "Bottom", "BottomRight",
//         "Menu", "Title", "Help", "Minimize", "Normalize", "Maximize", "Close",
//         "None"
//     };

    // First check to see if within all regions at all
    QRegion reg = region(w, w->geometry(), All);
    if (!reg.contains(point)) {
        return None;
    }

    int i = 0;
    while (regions[i]) {
        reg = region(w, w->geometry(), regions[i]);
        if (reg.contains(point)) {
//            qDebug("In region %s", regions_str[i]);
            return regions[i];
        }
        ++i;
    }
    return None;
}
Ejemplo n.º 21
0
/*!
    \internal
*/
void QDeclarativePaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
    Q_D(QDeclarativePaintedItem);
    const QRect content = boundingRect().toRect();
    if (content.width() <= 0 || content.height() <= 0)
        return;

    ++inpaint;

    const QTransform &x = p->deviceTransform();
    QTransform xinv = x.inverted();
    QRegion effectiveClip;
    QRegion sysClip = p->paintEngine()->systemClip();
    if (xinv.type() <= QTransform::TxScale && sysClip.numRects() < 5) {
        // simple transform, region gets no more complicated...
        effectiveClip = xinv.map(sysClip);
    } else {
        // do not make complicated regions...
        effectiveClip = xinv.mapRect(sysClip.boundingRect());
    }

    QRegion topaint = p->clipRegion();
    if (topaint.isEmpty()) {
        if (effectiveClip.isEmpty())
            topaint = QRect(0,0,p->device()->width(),p->device()->height());
        else
            topaint = effectiveClip;
    } else if (!effectiveClip.isEmpty()) {
        topaint &= effectiveClip;
    }

    topaint &= content;
    QRegion uncached(content);
    p->setRenderHints(QPainter::SmoothPixmapTransform, d->smooth);

    int cachesize=0;
    for (int i=0; i<d->imagecache.count(); ++i) {
        QRect area = d->imagecache[i]->area;
        if (topaint.contains(area)) {
            QRectF target(area.x(), area.y(), area.width(), area.height());
            if (!d->cachefrozen) {
                if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) {
#ifdef Q_WS_MAC
                    bool oldSmooth = qt_applefontsmoothing_enabled;
                    qt_applefontsmoothing_enabled = false;
#endif
                    QPainter qp(&d->imagecache[i]->image);
#ifdef Q_WS_MAC
                    qt_applefontsmoothing_enabled = oldSmooth;
#endif
                    qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);
                    qp.translate(-area.x(), -area.y());
                    qp.scale(d->contentsScale,d->contentsScale);
                    QRect clip = d->imagecache[i]->dirty;
                    QRect sclip(qFloor(clip.x()/d->contentsScale),
                            qFloor(clip.y()/d->contentsScale),
                            qCeil(clip.width()/d->contentsScale+clip.x()/d->contentsScale-qFloor(clip.x()/d->contentsScale)),
                            qCeil(clip.height()/d->contentsScale+clip.y()/d->contentsScale-qFloor(clip.y()/d->contentsScale)));
                    qp.setClipRect(sclip);
                    if (d->fillColor.isValid()){
                        if(d->fillColor.alpha() < 255){
                            // ### Might not work outside of raster paintengine
                            QPainter::CompositionMode prev = qp.compositionMode();
                            qp.setCompositionMode(QPainter::CompositionMode_Source);
                            qp.fillRect(sclip,d->fillColor);
                            qp.setCompositionMode(prev);
                        }else{
                            qp.fillRect(sclip,d->fillColor);
                        }
                    }
                    drawContents(&qp, sclip);
                    d->imagecache[i]->dirty = QRect();
                }
            }
            p->drawPixmap(target.toRect(), d->imagecache[i]->image);
            topaint -= area;
            d->imagecache[i]->age=0;
        } else {
            d->imagecache[i]->age++;
        }
        cachesize += area.width()*area.height();
        uncached -= area;
    }

    if (!topaint.isEmpty()) {
        if (!d->cachefrozen) {
            // Find a sensible larger area, otherwise will paint lots of tiny images.
            QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
            cachesize += biggerrect.width() * biggerrect.height();
            while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
                int oldest=-1;
                int age=-1;
                for (int i=0; i<d->imagecache.count(); ++i) {
                    int a = d->imagecache[i]->age;
                    if (a > age) {
                        oldest = i;
                        age = a;
                    }
                }
                cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
                uncached += d->imagecache[oldest]->area;
                delete d->imagecache.takeAt(oldest);
            }
            const QRegion bigger = QRegion(biggerrect) & uncached;
            const QVector<QRect> rects = bigger.rects();
            for (int i = 0; i < rects.count(); ++i) {
                const QRect &r = rects.at(i);
                QPixmap img(r.size());
                if (d->fillColor.isValid())
                    img.fill(d->fillColor);
                {
#ifdef Q_WS_MAC
                    bool oldSmooth = qt_applefontsmoothing_enabled;
                    qt_applefontsmoothing_enabled = false;
#endif
                    QPainter qp(&img);
#ifdef Q_WS_MAC
                    qt_applefontsmoothing_enabled = oldSmooth;
#endif
                    qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);

                    qp.translate(-r.x(),-r.y());
                    qp.scale(d->contentsScale,d->contentsScale);
                    QRect sclip(qFloor(r.x()/d->contentsScale),
                            qFloor(r.y()/d->contentsScale),
                            qCeil(r.width()/d->contentsScale+r.x()/d->contentsScale-qFloor(r.x()/d->contentsScale)),
                            qCeil(r.height()/d->contentsScale+r.y()/d->contentsScale-qFloor(r.y()/d->contentsScale)));
                    drawContents(&qp, sclip);
                }
                QDeclarativePaintedItemPrivate::ImageCacheItem *newitem = new QDeclarativePaintedItemPrivate::ImageCacheItem;
                newitem->area = r;
                newitem->image = img;
                d->imagecache.append(newitem);
                p->drawPixmap(r, newitem->image);
            }
        } else {
            const QVector<QRect> rects = uncached.rects();
            for (int i = 0; i < rects.count(); ++i)
                p->fillRect(rects.at(i), Qt::lightGray);
        }
    }

    if (inpaint_clearcache) {
        clearCache();
        inpaint_clearcache = 0;
    }

    --inpaint;
}