void QPainterFilterContext::drawImage(const QRectF &target, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags) { if (!prepare()) return; if (source.isNull()) painter->drawImage(target, image, QRectF(0, 0, image.width(), image.height()), flags); else painter->drawImage(target, image, source, flags); painter->restore(); }
void BlurItem::reload(const QPixmap &pixmap) { const QRectF r = rect(); if (r.isNull() && !r.isValid()) return; QTransform t = sceneTransform(); t.translate(qAbs(scene()->sceneRect().left()), qAbs(scene()->sceneRect().top())); m_item->setPixmap(pixmap.copy(t.mapRect(r).toRect())); }
void QPainterFilterContext::drawPlainText(const QRectF &rect, int flags, const QString &text) { if (!prepare()) return; if (rect.isNull()) painter->drawText(rect.topLeft(), text); else painter->drawText(rect, flags, text); painter->restore(); }
void OrthogonalRenderer::drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed) const { const QTransform savedTransform = painter->transform(); const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); const QPointF layerPos(layer->x() * tileWidth, layer->y() * tileHeight); painter->translate(layerPos); int startX = 0; int startY = 0; int endX = layer->width(); int endY = layer->height(); if (!exposed.isNull()) { QMargins drawMargins = layer->drawMargins(); drawMargins.setTop(drawMargins.top() - tileHeight); drawMargins.setRight(drawMargins.right() - tileWidth); QRectF rect = exposed.adjusted(-drawMargins.right(), -drawMargins.bottom(), drawMargins.left(), drawMargins.top()); rect.translate(-layerPos); startX = qMax((int) rect.x() / tileWidth, 0); startY = qMax((int) rect.y() / tileHeight, 0); endX = qMin((int) std::ceil(rect.right()) / tileWidth + 1, endX); endY = qMin((int) std::ceil(rect.bottom()) / tileHeight + 1, endY); } CellRenderer renderer(painter); for (int y = startY; y < endY; ++y) { for (int x = startX; x < endX; ++x) { const Cell &cell = layer->cellAt(x, y); if (cell.isEmpty()) continue; renderer.render(cell, QPointF(x * tileWidth, (y + 1) * tileHeight), CellRenderer::BottomLeft); } } renderer.flush(); painter->setTransform(savedTransform); }
QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const { const QRectF bounds = object->bounds(); const QRectF rect(tileToPixelCoords(bounds.topLeft()), tileToPixelCoords(bounds.bottomRight())); QRectF boundingRect; if (!object->cell().isEmpty()) { const QPointF bottomLeft = rect.topLeft(); const Tile *tile = object->cell().tile; const QSize imgSize = tile->image().size(); const QPoint tileOffset = tile->tileset()->tileOffset(); boundingRect = QRectF(bottomLeft.x() + tileOffset.x(), bottomLeft.y() + tileOffset.y() - imgSize.height(), imgSize.width(), imgSize.height()).adjusted(-1, -1, 1, 1); } else { const qreal extraSpace = qMax(objectLineWidth() / 2, qreal(1)); switch (object->shape()) { case MapObject::Ellipse: case MapObject::Rectangle: if (rect.isNull()) { boundingRect = rect.adjusted(-10 - extraSpace, -10 - extraSpace, 10 + extraSpace + 1, 10 + extraSpace + 1); } else { const int nameHeight = object->name().isEmpty() ? 0 : 15; boundingRect = rect.adjusted(-extraSpace, -nameHeight - extraSpace, extraSpace + 1, extraSpace + 1); } break; case MapObject::Polygon: case MapObject::Polyline: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); QPolygonF screenPolygon = tileToPixelCoords(polygon); boundingRect = screenPolygon.boundingRect().adjusted(-extraSpace, -extraSpace, extraSpace + 1, extraSpace + 1); break; } } } return boundingRect; }
QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const { const QRectF bounds = object->bounds(); const QRectF rect(tileToPixelCoords(bounds.topLeft()), tileToPixelCoords(bounds.bottomRight())); // The -2 and +3 are to account for the pen width and shadow if (rect.isNull()) return rect.adjusted(-15 - 2, -25 - 2, 10 + 3, 10 + 3); else return rect.adjusted(-2, -15 - 2, 3, 3); }
qreal PathView::contentsScale() const { QRectF br = _tr | _rr | _wr; if (br.isNull()) return mapScale(ZOOM_MAX); QPointF sc(br.width() / (viewport()->width() - MARGIN/2), br.height() / (viewport()->height() - MARGIN/2)); return qMax(sc.x(), sc.y()); }
QRectF PathView::contentsSceneRect() const { qreal scale = mapScale(_zoom); QRectF br = scaled(_tr | _rr | _wr, 1.0/scale); if (br.isNull()) return QRectF(QPointF(_wp.x() / scale - Tile::size()/2, _wp.y() /scale - Tile::size()/2), QSizeF(Tile::size(), Tile::size())); else return br.adjusted(-Tile::size(), -Tile::size(), Tile::size(), Tile::size()); }
bool BubbleAnimation::nextFrame( QColor const& head_color, QColor const& tail_color, QPaintDevice* pd, QRectF rect) { if (rect.isNull()) { rect = QRectF(0.0, 0.0, pd->width(), pd->height()); } QPainter painter(pd); return nextFrame(head_color, tail_color, &painter, rect); }
void QVGPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const { if (src.isNull()) return; if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) { // The pixmap data is not an instance of QVGPixmapData, so fall // back to the default blur filter implementation. QPixmapBlurFilter::draw(painter, dest, src, srcRect); return; } QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData()); VGImage srcImage = pd->toVGImage(); if (srcImage == VG_INVALID_HANDLE) return; QSize size = pd->size(); VGImage dstImage = QVGImagePool::instance()->createTemporaryImage (VG_sARGB_8888_PRE, size.width(), size.height(), VG_IMAGE_QUALITY_FASTER, pd); if (dstImage == VG_INVALID_HANDLE) return; // Clamp the radius range. We divide by 2 because the OpenVG blur // is "too blurry" compared to the default raster implementation. VGfloat maxRadius = VGfloat(vgGeti(VG_MAX_GAUSSIAN_STD_DEVIATION)); VGfloat radiusF = VGfloat(radius()) / 2.0f; if (radiusF < 0.001f) radiusF = 0.001f; else if (radiusF > maxRadius) radiusF = maxRadius; vgGaussianBlur(dstImage, srcImage, radiusF, radiusF, VG_TILE_PAD); VGImage child = VG_INVALID_HANDLE; if (srcRect.isNull() || (srcRect.topLeft().isNull() && srcRect.size() == size)) { child = dstImage; } else { QRect src = srcRect.toRect(); child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height()); } qt_vg_drawVGImage(painter, dest, child); if(child != dstImage) vgDestroyImage(child); QVGImagePool::instance()->releaseImage(0, dstImage); }
bool OLSAdaptiveNodeTextAreaVisualizer::tryPerformAdaptableVisualization(OLSOntologyGraphNodeItem *nodeToVisualize, OLSOntologyGraphNodeItem *nodeWithVisualizeInfo, QPainter *) { if (nodeToVisualize == nullptr) return false; QRectF rect = enlargeRect(nodeToVisualize->textRect(), getParameterValueOrDefaultDouble(m_offsetStr, nodeWithVisualizeInfo, m_offset)); if (!rect.isNull()) nodeToVisualize->setRect(rect); else nodeToVisualize->setRect(nodeToVisualize->textRect()); qDebug() << "OLSAdaptiveNodeTextAreaVisualizer"; return true; }
QPainterPath OrthogonalRenderer::shape(const MapObject *object) const { const QRectF bounds = object->bounds(); const QRectF rect(tileToPixelCoords(bounds.topLeft()), tileToPixelCoords(bounds.bottomRight())); QPainterPath path; if (rect.isNull()) path.addEllipse(rect.topLeft(), 20, 20); else path.addRoundedRect(rect, 10, 10); return path; }
void PrintBedView::drawGrid(QPainter *painter, const QRectF &rect) { double gridDensity = 10; int thickLineWidth = 3; double thickLineSceneWidth = thickLineWidth / transform().m11(); QRectF toDraw = m_gridRect.intersected(rect.adjusted(-thickLineSceneWidth, -thickLineSceneWidth, thickLineSceneWidth, thickLineSceneWidth)); if (toDraw.isNull()) { return; } QPen defaultPen = painter->pen(); QPen thickPen = defaultPen; thickPen.setWidth(thickLineWidth); thickPen.setCosmetic(true); int lineNo = static_cast<int>(toDraw.left() / gridDensity); if (toDraw.left() > 0) { ++lineNo; } for (double x = lineNo * gridDensity; x <= toDraw.right(); x += gridDensity, ++lineNo) { if (lineNo % 5 == 0) { painter->setPen(thickPen); painter->drawLine(QPointF(x, toDraw.top()), QPointF(x, toDraw.bottom())); painter->setPen(defaultPen); } else { painter->drawLine(QPointF(x, toDraw.top()), QPointF(x, toDraw.bottom())); } } lineNo = static_cast<int>(toDraw.top() / gridDensity); if (toDraw.top() > 0) { ++lineNo; } for (double y = lineNo * gridDensity; y <= toDraw.bottom(); y += gridDensity, ++lineNo) { if (lineNo % 5 == 0) { painter->setPen(thickPen); painter->drawLine(QPointF(toDraw.left(), y), QPointF(toDraw.right(), y)); painter->setPen(defaultPen); } else { painter->drawLine(QPointF(toDraw.left(), y), QPointF(toDraw.right(), y)); } } }
QRectF boundsOfChildren( QGraphicsItem const * qgi ) { typedef QList<QGraphicsItem*> QGIL; QGIL ch( qboard::childItems(qgi) ); QRectF r; for( QGIL::const_iterator it = ch.begin(); ch.end() != it; ++it ) { QGraphicsItem const * x = *it; QRectF r2( x->mapToParent(x->pos()), x->boundingRect().size() ); r = r.unite( r2 ); } if(1 && ! r.isNull() ) qDebug() << "bounds of children ="<<r; return r; }
void BoxTextGraphicsItem::updateRect(const QRectF &rect) { QRectF r = rect; if (!r.isNull() && r.isValid()) { if (r.height() < m_gi->boundingRect().height()+18) { r.setHeight(m_gi->boundingRect().height()+18); } if (r.width() < MINTEXTWIDTH) { r.setWidth(MINTEXTWIDTH); } m_gi->show(); adaptTextItemWidth(r); setRect(r); updateHandlesPosition(); } }
static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, QRectF gradientRect = QRectF())//copy from QPlainTextEditor from 4.8.1 { p->save(); if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) { if (!gradientRect.isNull()) { QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top()); m.scale(gradientRect.width(), gradientRect.height()); brush.setTransform(m); const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode); } } else { p->setBrushOrigin(rect.topLeft()); } p->fillRect(rect, brush); p->restore(); }
void SymbolDataEditor::setSymbolData(const QPointF _inPoint, const QPointF _outPoint, const QRectF _limits) { if (scene->items().isEmpty()) return; QRectF symbolRect = scene->items(Qt::AscendingOrder).at(Item::SymbolItem)->boundingRect(); symbolRect.moveTopLeft(scene->items(Qt::AscendingOrder).at(Item::SymbolItem)->pos()); symbolRect.adjust(symbolRect.width() / 4, symbolRect.height() / 4, -symbolRect.width() / 4, -symbolRect.height() / 4); //try to set data automatically if they're not set if (_inPoint.isNull()) { if (setupPoints) inPoint = getBeginPoint(); else { inPoint = symbolRect.topLeft(); inPoint.ry() += symbolRect.height() / 2; } } else inPoint = fromStored(_inPoint); if (_outPoint.isNull()) { if (setupPoints) outPoint = getEndPoint(); else { outPoint = symbolRect.topRight(); outPoint.ry() += symbolRect.height() / 2; } } else outPoint = fromStored(_outPoint); if (_limits.isNull()) limits = symbolRect; else limits = QRectF(fromStored(_limits.topLeft()), fromStored(_limits.bottomRight())); correctLimits(); addDataItems(); }
void DemoItem::setPosUsingSheepDog(const QPointF &dest, const QRectF &sceneFence) { this->setPos(dest); if (sceneFence.isNull()) return; // I agree. This is not the optimal way of doing it. // But don't want for use time on it now.... float itemWidth = this->boundingRect().width(); float itemHeight = this->boundingRect().height(); float fenceRight = sceneFence.x() + sceneFence.width(); float fenceBottom = sceneFence.y() + sceneFence.height(); if (this->scenePos().x() < sceneFence.x()) this->moveBy(this->mapFromScene(QPointF(sceneFence.x(), 0)).x(), 0); if (this->scenePos().x() > fenceRight - itemWidth) this->moveBy(this->mapFromScene(QPointF(fenceRight - itemWidth, 0)).x(), 0); if (this->scenePos().y() < sceneFence.y()) this->moveBy(0, this->mapFromScene(QPointF(0, sceneFence.y())).y()); if (this->scenePos().y() > fenceBottom - itemHeight) this->moveBy(0, this->mapFromScene(QPointF(0, fenceBottom - itemHeight)).y()); }
void OrthogonalRenderer::drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); const QPointF layerPos(layer->x() * tileWidth, layer->y() * tileHeight); painter->translate(layerPos); int startX = 0; int startY = 0; int endX = layer->width(); int endY = layer->height(); if (!exposed.isNull()) { const QSize maxTileSize = layer->maxTileSize(); const int extraWidth = maxTileSize.width() - tileWidth; const int extraHeight = maxTileSize.height() - tileHeight; QRectF rect = exposed.adjusted(-extraWidth, 0, 0, extraHeight); rect.translate(-layerPos); startX = qMax((int) rect.x() / tileWidth, 0); startY = qMax((int) rect.y() / tileHeight, 0); endX = qMin((int) std::ceil(rect.right()) / tileWidth + 1, endX); endY = qMin((int) std::ceil(rect.bottom()) / tileHeight + 1, endY); } for (int y = startY; y < endY; ++y) { for (int x = startX; x < endX; ++x) { const Tile *tile = layer->tileAt(x, y); if (!tile) continue; const QPixmap &img = tile->image(); painter->drawPixmap(x * tileWidth, (y + 1) * tileHeight - img.height(), img); } } painter->translate(-layerPos); }
QPainterPath OrthogonalRenderer::shape(const MapObject *object) const { QPainterPath path; if (object->tile()) { path.addRect(boundingRect(object)); } else { switch (object->shape()) { case MapObject::Rectangle: { const QRectF bounds = object->bounds(); const QRectF rect(tileToPixelCoords(bounds.topLeft()), tileToPixelCoords(bounds.bottomRight())); if (rect.isNull()) { path.addEllipse(rect.topLeft(), 20, 20); } else { path.addRoundedRect(rect, 10, 10); } break; } case MapObject::Polygon: case MapObject::Polyline: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); const QPolygonF screenPolygon = tileToPixelCoords(polygon); if (object->shape() == MapObject::Polygon) { path.addPolygon(screenPolygon); } else { for (int i = 1; i < screenPolygon.size(); ++i) { path.addPolygon(lineToPolygon(screenPolygon[i - 1], screenPolygon[i])); } path.setFillRule(Qt::WindingFill); } break; } } } return path; }
QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const { const QRectF bounds = object->bounds(); const QRectF rect(tileToPixelCoords(bounds.topLeft()), tileToPixelCoords(bounds.bottomRight())); QRectF boundingRect; if (object->tile()) { const QPointF bottomLeft = rect.topLeft(); const QPixmap &img = object->tile()->image(); boundingRect = QRectF(bottomLeft.x(), bottomLeft.y() - img.height(), img.width(), img.height()).adjusted(-1, -1, 1, 1); } else { // The -2 and +3 are to account for the pen width and shadow switch (object->shape()) { case MapObject::Ellipse: case MapObject::Rectangle: if (rect.isNull()) { boundingRect = rect.adjusted(-10 - 2, -10 - 2, 10 + 3, 10 + 3); } else { const int nameHeight = object->name().isEmpty() ? 0 : 15; boundingRect = rect.adjusted(-2, -nameHeight - 2, 3, 3); } break; case MapObject::Polygon: case MapObject::Polyline: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); QPolygonF screenPolygon = tileToPixelCoords(polygon); boundingRect = screenPolygon.boundingRect().adjusted(-2, -2, 3, 3); break; } } } return boundingRect; }
static inline QPainterPath headerPath( const QRectF& r, int roundness, int headerHeight = 10 ) { QPainterPath path; int xRnd = roundness; int yRnd = roundness; if( r.width() > r.height() ) { xRnd = int ( roundness * r.height() / r.width() ); } else { yRnd = int ( roundness * r.width() / r.height() ); } if( xRnd >= 100 ) // fix ranges { xRnd = 99; } if( yRnd >= 100 ) { yRnd = 99; } if( xRnd <= 0 || yRnd <= 0 ) // add normal rectangle { path.addRect( r ); return path; } QRectF rect = r.normalized(); if( rect.isNull() ) { return path; } qreal x = rect.x(); qreal y = rect.y(); qreal w = rect.width(); qreal h = rect.height(); qreal rxx = w * xRnd / 200; qreal ryy = h * yRnd / 200; // were there overflows? if( rxx < 0 ) { rxx = w / 200 * xRnd; } if( ryy < 0 ) { ryy = h / 200 * yRnd; } qreal rxx2 = 2 * rxx; qreal ryy2 = 2 * ryy; path.arcMoveTo( x, y, rxx2, ryy2, 90 ); path.arcTo( x, y, rxx2, ryy2, 90, 90 ); QPointF pt = path.currentPosition(); path.lineTo( x, pt.y() + headerHeight ); path.lineTo( x + w, pt.y() + headerHeight ); path.lineTo( x + w, pt.y() ); path.arcTo( x + w - rxx2, y, rxx2, ryy2, 0, 90 ); path.closeSubpath(); return path; }
void OrthogonalRenderer::drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed) const { QTransform savedTransform = painter->transform(); const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); const QPointF layerPos(layer->x() * tileWidth, layer->y() * tileHeight); painter->translate(layerPos); int startX = 0; int startY = 0; int endX = layer->width(); int endY = layer->height(); if (!exposed.isNull()) { QMargins drawMargins = layer->drawMargins(); drawMargins.setTop(drawMargins.top() - tileHeight); drawMargins.setRight(drawMargins.right() - tileWidth); QRectF rect = exposed.adjusted(-drawMargins.right(), -drawMargins.bottom(), drawMargins.left(), drawMargins.top()); rect.translate(-layerPos); startX = qMax((int) rect.x() / tileWidth, 0); startY = qMax((int) rect.y() / tileHeight, 0); endX = qMin((int) std::ceil(rect.right()) / tileWidth + 1, endX); endY = qMin((int) std::ceil(rect.bottom()) / tileHeight + 1, endY); } QTransform baseTransform = painter->transform(); for (int y = startY; y < endY; ++y) { for (int x = startX; x < endX; ++x) { const Cell &cell = layer->cellAt(x, y); if (cell.isEmpty()) continue; const QPixmap &img = cell.tile->image(); const QPoint offset = cell.tile->tileset()->tileOffset(); qreal m11 = 1; // Horizontal scaling factor qreal m12 = 0; // Vertical shearing factor qreal m21 = 0; // Horizontal shearing factor qreal m22 = 1; // Vertical scaling factor qreal dx = offset.x() + x * tileWidth; qreal dy = offset.y() + (y + 1) * tileHeight - img.height(); if (cell.flippedAntiDiagonally) { // Use shearing to swap the X/Y axis m11 = 0; m12 = 1; m21 = 1; m22 = 0; // Compensate for the swap of image dimensions dy += img.height() - img.width(); } if (cell.flippedHorizontally) { m11 = -m11; m21 = -m21; dx += cell.flippedAntiDiagonally ? img.height() : img.width(); } if (cell.flippedVertically) { m12 = -m12; m22 = -m22; dy += cell.flippedAntiDiagonally ? img.width() : img.height(); } const QTransform transform(m11, m12, m21, m22, dx, dy); painter->setTransform(transform * baseTransform); painter->drawPixmap(0, 0, img); } } painter->setTransform(savedTransform); }
void drawTexture(const QRectF &target, const QSizeF &viewport, GLuint texture, qreal alpha, const QRectF &source) { static QOpenGLShaderProgram *program = 0; static int vertexAttr; static int texCoordAttr; static int opacityUniform; if (program == 0) { program = generateShaderProgram(0, drawTextureVertexSrc, drawTextureFragmentSrc); vertexAttr = program->attributeLocation("vertexAttr"); texCoordAttr = program->attributeLocation("texCoordAttr"); opacityUniform = program->uniformLocation("alpha"); } qreal xmin = -1 + 2 * (target.left() / viewport.width()); qreal xmax = -1 + 2 * (target.right() / viewport.width()); qreal ymin = -1 + 2 * (viewport.height() - target.top()) / viewport.height(); qreal ymax = -1 + 2 * (viewport.height() - target.bottom()) / viewport.height(); QVector2D va(xmin, ymin); QVector2D vb(xmax, ymin); QVector2D vc(xmax, ymax); QVector2D vd(xmin, ymax); QVector2D vertexCoords[] = { va, vb, vd, vd, vb, vc }; QVector2D ta, tb, tc, td; QRectF s = source; if (s.isNull()) { s = QRectF(0, 0, 1, 1); ta = QVector2D(s.left(), s.top()); tb = QVector2D(s.right(), s.top()); tc = QVector2D(s.right(), s.bottom()); td = QVector2D(s.left(), s.bottom()); } else { ta = QVector2D(s.left(), s.top()); tb = QVector2D(s.right(), s.top()); tc = QVector2D(s.right(), s.bottom()); td = QVector2D(s.left(), s.bottom()); } QVector2D texCoords[] = { ta, tb, td, td, tb, tc }; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); program->bind(); program->setUniformValue(opacityUniform, GLfloat(alpha)); program->enableAttributeArray(vertexAttr); program->setAttributeArray(vertexAttr, vertexCoords); program->enableAttributeArray(texCoordAttr); program->setAttributeArray(texCoordAttr, texCoords); glDrawArrays(GL_TRIANGLES, 0, 6); program->disableAttributeArray(vertexAttr); program->disableAttributeArray(texCoordAttr); }
void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int height, double position, int force_refresh ) { // Obtain the producer mlt_producer producer = &self->parent; mlt_profile profile = mlt_service_profile ( MLT_PRODUCER_SERVICE( producer ) ) ; mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); pthread_mutex_lock( &self->mutex ); // Check if user wants us to reload the image if ( mlt_properties_get( producer_props, "_animated" ) != NULL || force_refresh == 1 || width != self->current_width || height != self->current_height || mlt_properties_get( producer_props, "_endrect" ) != NULL ) { //mlt_cache_item_close( self->image_cache ); self->current_image = NULL; mlt_properties_set_data( producer_props, "cached_image", NULL, 0, NULL, NULL ); mlt_properties_set_int( producer_props, "force_reload", 0 ); } if (self->current_image == NULL) { // restore QGraphicsScene QGraphicsScene *scene = static_cast<QGraphicsScene *> (mlt_properties_get_data( producer_props, "qscene", NULL )); if ( force_refresh == 1 && scene ) { scene = NULL; mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL ); } if ( scene == NULL ) { int argc = 1; char* argv[1]; argv[0] = (char*) "xxx"; // Warning: all Qt graphic objects (QRect, ...) must be initialized AFTER // the QApplication is created, otherwise their will be NULL if ( app == NULL ) { if ( qApp ) { app = qApp; } else { #ifdef linux if ( getenv("DISPLAY") == 0 ) { mlt_log_panic( MLT_PRODUCER_SERVICE( producer ), "Error, cannot render titles without an X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" ); pthread_mutex_unlock( &self->mutex ); return; } #endif app = new QApplication( argc, argv ); const char *localename = mlt_properties_get_lcnumeric( MLT_SERVICE_PROPERTIES( MLT_PRODUCER_SERVICE( producer ) ) ); QLocale::setDefault( QLocale( localename ) ); } qRegisterMetaType<QTextCursor>( "QTextCursor" ); } scene = new QGraphicsScene(); scene->setItemIndexMethod( QGraphicsScene::NoIndex ); scene->setSceneRect(0, 0, mlt_properties_get_int( properties, "width" ), mlt_properties_get_int( properties, "height" )); if ( mlt_properties_get( producer_props, "resource" ) && mlt_properties_get( producer_props, "resource" )[0] != '\0' ) { // The title has a resource property, so we read all properties from the resource. // Do not serialize the xmldata loadFromXml( producer, scene, mlt_properties_get( producer_props, "_xmldata" ), mlt_properties_get( producer_props, "templatetext" ) ); } else { // The title has no resource, all data should be serialized loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ) ); } mlt_properties_set_data( producer_props, "qscene", scene, 0, ( mlt_destructor )qscene_delete, NULL ); } QRectF start = stringToRect( QString( mlt_properties_get( producer_props, "_startrect" ) ) ); QRectF end = stringToRect( QString( mlt_properties_get( producer_props, "_endrect" ) ) ); int originalWidth = mlt_properties_get_int( producer_props, "_original_width" ); int originalHeight= mlt_properties_get_int( producer_props, "_original_height" ); const QRectF source( 0, 0, width, height ); if (start.isNull()) { start = QRectF( 0, 0, originalWidth, originalHeight ); } // Effects QList <QGraphicsItem *> items = scene->items(); QGraphicsTextItem *titem = NULL; for (int i = 0; i < items.count(); i++) { titem = static_cast <QGraphicsTextItem*> ( items.at( i ) ); if (titem && !titem->data( 0 ).isNull()) { QStringList params = titem->data( 0 ).toStringList(); if (params.at( 0 ) == "typewriter" ) { // typewriter effect has 2 param values: // the keystroke delay and a start offset, both in frames QStringList values = params.at( 2 ).split( ";" ); int interval = qMax( 0, ( ( int ) position - values.at( 1 ).toInt()) / values.at( 0 ).toInt() ); QTextCursor cursor = titem->textCursor(); cursor.movePosition(QTextCursor::EndOfBlock); // get the font format QTextCharFormat format = cursor.charFormat(); cursor.select(QTextCursor::Document); QString txt = params.at( 1 ).left( interval ); // If the string to insert is empty, insert a space / linebreak so that we don't loose // formatting infos for the next iterations int lines = params.at( 1 ).count( '\n' ); QString empty = " "; for (int i = 0; i < lines; i++) empty.append( "\n " ); cursor.insertText( txt.isEmpty() ? empty : txt, format ); if ( !titem->data( 1 ).isNull() ) titem->setTextWidth( titem->data( 1 ).toDouble() ); } } } //must be extracted from kdenlive title QImage img( width, height, QImage::Format_ARGB32 ); img.fill( 0 ); QPainter p1; p1.begin( &img ); p1.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing ); //| QPainter::SmoothPixmapTransform ); mlt_position anim_out = mlt_properties_get_position( producer_props, "_animation_out" ); if (end.isNull()) { scene->render( &p1, source, start, Qt::IgnoreAspectRatio ); } else if ( position > anim_out ) { scene->render( &p1, source, end, Qt::IgnoreAspectRatio ); } else { double percentage = 0; if ( position && anim_out ) percentage = position / anim_out; QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * percentage; QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * percentage; const QRectF r1( topleft, bottomRight ); scene->render( &p1, source, r1, Qt::IgnoreAspectRatio ); if ( profile && !profile->progressive ){ int line=0; double percentage_next_filed = ( position + 0.5 ) / anim_out; QPointF topleft_next_field = start.topLeft() + ( end.topLeft() - start.topLeft() ) * percentage_next_filed; QPointF bottomRight_next_field = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * percentage_next_filed; const QRectF r2( topleft_next_field, bottomRight_next_field ); QImage img1( width, height, QImage::Format_ARGB32 ); img1.fill( 0 ); QPainter p2; p2.begin(&img1); p2.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing ); scene->render(&p2,source,r2, Qt::IgnoreAspectRatio ); p2.end(); int next_field_line = ( mlt_properties_get_int( producer_props, "top_field_first" ) ? 1 : 0 ); for (line = next_field_line ;line<height;line+=2){ memcpy(img.scanLine(line),img1.scanLine(line),img.bytesPerLine()); } } } p1.end(); int size = width * height * 4; uint8_t *pointer=img.bits(); QRgb* src = ( QRgb* ) pointer; self->current_image = ( uint8_t * )mlt_pool_alloc( size ); uint8_t *dst = self->current_image; for ( int i = 0; i < width * height * 4; i += 4 ) { *dst++=qRed( *src ); *dst++=qGreen( *src ); *dst++=qBlue( *src ); *dst++=qAlpha( *src ); src++; } mlt_properties_set_data( producer_props, "cached_image", self->current_image, size, mlt_pool_release, NULL ); self->current_width = width; self->current_height = height; } pthread_mutex_unlock( &self->mutex ); mlt_properties_set_int( properties, "width", self->current_width ); mlt_properties_set_int( properties, "height", self->current_height ); }
void QQuickTextNodeEngine::processCurrentLine() { // No glyphs, do nothing if (m_currentLineTree.isEmpty()) return; // 1. Go through current line and get correct decoration position for each node based on // neighbouring decorations. Add decoration to global list // 2. Create clip nodes for all selected text. Try to merge as many as possible within // the line. // 3. Add QRects to a list of selection rects. // 4. Add all nodes to a global processed list QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes); Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size()); SelectionState currentSelectionState = Unselected; QRectF currentRect; QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration; qreal underlineOffset = 0.0; qreal underlineThickness = 0.0; qreal overlineOffset = 0.0; qreal overlineThickness = 0.0; qreal strikeOutOffset = 0.0; qreal strikeOutThickness = 0.0; QRectF decorationRect = currentRect; QColor lastColor; QColor lastBackgroundColor; QVarLengthArray<TextDecoration> pendingUnderlines; QVarLengthArray<TextDecoration> pendingOverlines; QVarLengthArray<TextDecoration> pendingStrikeOuts; if (!sortedIndexes.isEmpty()) { QQuickDefaultClipNode *currentClipNode = m_hasSelection ? new QQuickDefaultClipNode(QRectF()) : 0; bool currentClipNodeUsed = false; for (int i=0; i<=sortedIndexes.size(); ++i) { BinaryTreeNode *node = 0; if (i < sortedIndexes.size()) { int sortedIndex = sortedIndexes.at(i); Q_ASSERT(sortedIndex < m_currentLineTree.size()); node = m_currentLineTree.data() + sortedIndex; } if (i == 0) currentSelectionState = node->selectionState; // Update decorations if (currentDecorations != QQuickTextNode::NoDecoration) { decorationRect.setY(m_position.y() + m_currentLine.y()); decorationRect.setHeight(m_currentLine.height()); if (node != 0) decorationRect.setRight(node->boundingRect.left()); TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor); if (currentDecorations & QQuickTextNode::Underline) pendingUnderlines.append(textDecoration); if (currentDecorations & QQuickTextNode::Overline) pendingOverlines.append(textDecoration); if (currentDecorations & QQuickTextNode::StrikeOut) pendingStrikeOuts.append(textDecoration); if (currentDecorations & QQuickTextNode::Background) m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor)); } // If we've reached an unselected node from a selected node, we add the // selection rect to the graph, and we add decoration every time the // selection state changes, because that means the text color changes if (node == 0 || node->selectionState != currentSelectionState) { currentRect.setY(m_position.y() + m_currentLine.y()); currentRect.setHeight(m_currentLine.height()); if (currentSelectionState == Selected) m_selectionRects.append(currentRect); if (currentClipNode != 0) { if (!currentClipNodeUsed) { delete currentClipNode; } else { currentClipNode->setIsRectangular(true); currentClipNode->setRect(currentRect); currentClipNode->update(); } } if (node != 0 && m_hasSelection) currentClipNode = new QQuickDefaultClipNode(QRectF()); else currentClipNode = 0; currentClipNodeUsed = false; if (node != 0) { currentSelectionState = node->selectionState; currentRect = node->boundingRect; // Make sure currentRect is valid, otherwise the unite won't work if (currentRect.isNull()) currentRect.setSize(QSizeF(1, 1)); } } else { if (currentRect.isNull()) currentRect = node->boundingRect; else currentRect = currentRect.united(node->boundingRect); } if (node != 0) { if (node->selectionState == Selected) { node->clipNode = currentClipNode; currentClipNodeUsed = true; } decorationRect = node->boundingRect; // If previous item(s) had underline and current does not, then we add the // pending lines to the lists and likewise for overlines and strikeouts if (!pendingUnderlines.isEmpty() && !(node->decorations & QQuickTextNode::Underline)) { addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness); pendingUnderlines.clear(); underlineOffset = 0.0; underlineThickness = 0.0; } // ### Add pending when overlineOffset/thickness changes to minimize number of // nodes if (!pendingOverlines.isEmpty()) { addTextDecorations(pendingOverlines, overlineOffset, overlineThickness); pendingOverlines.clear(); overlineOffset = 0.0; overlineThickness = 0.0; } // ### Add pending when overlineOffset/thickness changes to minimize number of // nodes if (!pendingStrikeOuts.isEmpty()) { addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness); pendingStrikeOuts.clear(); strikeOutOffset = 0.0; strikeOutThickness = 0.0; } // Merge current values with previous. Prefer greatest thickness QRawFont rawFont = node->glyphRun.rawFont(); if (node->decorations & QQuickTextNode::Underline) { if (rawFont.lineThickness() > underlineThickness) { underlineThickness = rawFont.lineThickness(); underlineOffset = rawFont.underlinePosition(); } } if (node->decorations & QQuickTextNode::Overline) { overlineOffset = -rawFont.ascent(); overlineThickness = rawFont.lineThickness(); } if (node->decorations & QQuickTextNode::StrikeOut) { strikeOutThickness = rawFont.lineThickness(); strikeOutOffset = rawFont.ascent() / -3.0; } currentDecorations = node->decorations; lastColor = node->color; lastBackgroundColor = node->backgroundColor; m_processedNodes.append(*node); } } if (!pendingUnderlines.isEmpty()) addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness); if (!pendingOverlines.isEmpty()) addTextDecorations(pendingOverlines, overlineOffset, overlineThickness); if (!pendingStrikeOuts.isEmpty()) addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness); } m_currentLineTree.clear(); m_currentLine = QTextLine(); m_hasSelection = false; }
static void qtmDrawRoundedRect(QPainter *p, const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode) { QRectF r = rect.normalized(); if (r.isNull()) return; if (mode == Qt::AbsoluteSize) { qreal w = r.width() / 2; qreal h = r.height() / 2; xRadius = 100 * qMin(xRadius, w) / w; yRadius = 100 * qMin(yRadius, h) / h; } else { if (xRadius > 100) // fix ranges xRadius = 100; if (yRadius > 100) yRadius = 100; } QPainterPath path; if (xRadius <= 0 || yRadius <= 0) { // add normal rectangle path.addRect(r); } else { qreal x = r.x(); qreal y = r.y(); qreal w = r.width(); qreal h = r.height(); qreal rxx2 = w*xRadius/100; qreal ryy2 = h*yRadius/100; #ifdef Q_WS_X11 // There is a bug (probably in arcTo) for small sizes. // We use a rough linear approx. rxx2 /= 4; ryy2 /= 4; path.moveTo(x+rxx2,y); path.lineTo(x+w-rxx2, y); path.lineTo(x+w, y+ryy2); path.lineTo(x+w, y+h-ryy2); path.lineTo(x+w-rxx2, y+h); path.lineTo(x+rxx2, y+h); path.lineTo(x, y+h-ryy2); path.lineTo(x, y+ryy2); path.closeSubpath(); #else path.moveTo(x+rxx2,y); path.arcMoveTo(x, y, rxx2, ryy2, 90); path.arcTo(x, y, rxx2, ryy2, 90, 90); path.arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90); path.arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 3*90, 90); path.arcTo(x+w-rxx2, y, rxx2, ryy2, 0, 90); path.closeSubpath(); #endif } p->drawPath(path); }
void OrthogonalRenderer::drawMapObject(QPainter *painter, const MapObject *object, const QColor &color) const { painter->save(); QColor brushColor = color; brushColor.setAlpha(50); QBrush brush(brushColor); QPen pen(Qt::black); pen.setWidth(3); pen.setJoinStyle(Qt::RoundJoin); // Make sure the line aligns nicely on the pixels if (pen.width() % 2) painter->translate(0.5, 0.5); painter->setPen(pen); painter->setRenderHint(QPainter::Antialiasing); const QFontMetrics fm = painter->fontMetrics(); const QRectF bounds = object->bounds(); const QRectF rect(tileToPixelCoords(bounds.topLeft()), tileToPixelCoords(bounds.bottomRight())); painter->translate(rect.topLeft()); if (rect.isNull()) { QString name = fm.elidedText(object->name(), Qt::ElideRight, 30); // Draw the shadow painter->drawEllipse(QRect(- 10 + 1, - 10 + 1, 20, 20)); painter->drawText(QPoint(-15 + 1, -15 + 1), name); pen.setColor(color); painter->setPen(pen); painter->setBrush(brush); painter->drawEllipse(QRect(-10, -10, 20, 20)); painter->drawText(QPoint(-15, -15), name); } else { QString name = fm.elidedText(object->name(), Qt::ElideRight, rect.width() + 2); // Draw the shadow painter->drawRoundedRect(QRectF(QPointF(1, 1), rect.size()), 10.0, 10.0); painter->drawText(QPoint(1, -5 + 1), name); pen.setColor(color); painter->setPen(pen); painter->setBrush(brush); painter->drawRoundedRect(QRectF(QPointF(0, 0), rect.size()), 10.0, 10.0); painter->drawText(QPoint(0, -5), name); } painter->restore(); }
void QVGPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const { if (src.isNull()) return; if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) { // The pixmap data is not an instance of QVGPixmapData, so fall // back to the default colorize filter implementation. QPixmapColorizeFilter::draw(painter, dest, src, srcRect); return; } QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData()); VGImage srcImage = pd->toVGImage(); if (srcImage == VG_INVALID_HANDLE) return; QSize size = pd->size(); VGImage dstImage = QVGImagePool::instance()->createTemporaryImage (VG_sARGB_8888_PRE, size.width(), size.height(), VG_IMAGE_QUALITY_FASTER, pd); if (dstImage == VG_INVALID_HANDLE) return; // Determine the weights for the matrix from the color and strength. QColor c = color(); VGfloat strength = this->strength(); VGfloat weights[3]; VGfloat invweights[3]; VGfloat alpha = c.alphaF(); weights[0] = c.redF() * alpha; weights[1] = c.greenF() * alpha; weights[2] = c.blueF() * alpha; invweights[0] = (1.0f - weights[0]) * strength; invweights[1] = (1.0f - weights[1]) * strength; invweights[2] = (1.0f - weights[2]) * strength; // Grayscale weights. static const VGfloat redGray = 11.0f / 32.0f; static const VGfloat greenGray = 16.0f / 32.0f; static const VGfloat blueGray = 1.0f - (redGray + greenGray); VGfloat matrix[5][4]; matrix[0][0] = redGray * invweights[0] + (1.0f - strength); matrix[0][1] = redGray * invweights[1]; matrix[0][2] = redGray * invweights[2]; matrix[0][3] = 0.0f; matrix[1][0] = greenGray * invweights[0]; matrix[1][1] = greenGray * invweights[1] + (1.0f - strength); matrix[1][2] = greenGray * invweights[2]; matrix[1][3] = 0.0f; matrix[2][0] = blueGray * invweights[0]; matrix[2][1] = blueGray * invweights[1]; matrix[2][2] = blueGray * invweights[2] + (1.0f - strength); matrix[2][3] = 0.0f; matrix[3][0] = 0.0f; matrix[3][1] = 0.0f; matrix[3][2] = 0.0f; matrix[3][3] = 1.0f; matrix[4][0] = weights[0] * strength; matrix[4][1] = weights[1] * strength; matrix[4][2] = weights[2] * strength; matrix[4][3] = 0.0f; vgColorMatrix(dstImage, srcImage, matrix[0]); VGImage child = VG_INVALID_HANDLE; if (srcRect.isNull() || (srcRect.topLeft().isNull() && srcRect.size() == size)) { child = dstImage; } else { QRect src = srcRect.toRect(); child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height()); } qt_vg_drawVGImage(painter, dest, child); if(child != dstImage) vgDestroyImage(child); QVGImagePool::instance()->releaseImage(0, dstImage); }
void QVGPixmapConvolutionFilter::draw (QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const { if (src.isNull()) return; if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) { // The pixmap data is not an instance of QVGPixmapData, so fall // back to the default convolution filter implementation. QPixmapConvolutionFilter::draw(painter, dest, src, srcRect); return; } QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData()); VGImage srcImage = pd->toVGImage(); if (srcImage == VG_INVALID_HANDLE) return; QSize size = pd->size(); VGImage dstImage = QVGImagePool::instance()->createTemporaryImage (VG_sARGB_8888_PRE, size.width(), size.height(), VG_IMAGE_QUALITY_FASTER, pd); if (dstImage == VG_INVALID_HANDLE) return; int kernelWidth = rows(); int kernelHeight = columns(); const qreal *kern = convolutionKernel(); QVarLengthArray<VGshort> kernel; for (int i = 0; i < kernelWidth; ++i) { for (int j = 0; j < kernelHeight; ++j) { kernel.append((VGshort)(kern[j * kernelWidth + i] * 1024.0f)); } } VGfloat values[4]; values[0] = 0.0f; values[1] = 0.0f; values[2] = 0.0f; values[3] = 0.0f; vgSetfv(VG_TILE_FILL_COLOR, 4, values); vgConvolve(dstImage, srcImage, kernelWidth, kernelHeight, 0, 0, kernel.constData(), 1.0f / 1024.0f, 0.0f, VG_TILE_FILL); VGImage child = VG_INVALID_HANDLE; if (srcRect.isNull() || (srcRect.topLeft().isNull() && srcRect.size() == size)) { child = dstImage; } else { QRect src = srcRect.toRect(); child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height()); } qt_vg_drawVGImage(painter, dest, child); if(child != dstImage) vgDestroyImage(child); QVGImagePool::instance()->releaseImage(0, dstImage); }