/** En vez de renderizar como en paint, renderizo sobre un QPai9nter en un QPixmap*/ void In2Barcode::SetPixmap() { QImage dummyImagen(boundingRect().width(),boundingRect().height(), QImage::Format_Mono); QPainter imagePainter(&dummyImagen); bc.render(imagePainter, dummyImagen.rect(), ar); qpxImagen = QPixmap::fromImage(dummyImagen); }
void KoShapeShadow::paint(KoShape *shape, QPainter &painter, const KoViewConverter &converter) { if (! d->visible) return; // So the approach we are taking here is to draw into a buffer image the size of boundingRect // We offset by the shadow offset at the time we draw into the buffer // Then we filter the image and draw it at the position of the bounding rect on canvas //the boundingRect of the shape or the KoSelection boundingRect of the group QRectF shadowRect = shape->boundingRect(); QRectF zoomedClipRegion = converter.documentToView(shadowRect); // Init the buffer image QImage sourceGraphic(zoomedClipRegion.size().toSize(), QImage::Format_ARGB32_Premultiplied); sourceGraphic.fill(qRgba(0,0,0,0)); // Init the buffer painter QPainter imagePainter(&sourceGraphic); imagePainter.setPen(Qt::NoPen); imagePainter.setBrush(Qt::NoBrush); imagePainter.setRenderHint(QPainter::Antialiasing, painter.testRenderHint(QPainter::Antialiasing)); // Since our imagebuffer and the canvas don't align we need to offset our drawings imagePainter.translate(-1.0f*converter.documentToView(shadowRect.topLeft())); // Handle the shadow offset imagePainter.translate(converter.documentToView(offset())); KoShapeGroup *group = dynamic_cast<KoShapeGroup*>(shape); if (group) { d->paintGroupShadow(group, imagePainter, converter); } else { //apply shape's transformation imagePainter.setTransform(shape->absoluteTransformation(&converter), true); d->paintShadow(shape, imagePainter, converter); } imagePainter.end(); // Blur the shadow (well the entire buffer) d->blurShadow(sourceGraphic, converter.documentToViewX(d->blur), d->color); // Paint the result painter.save(); // The painter is initialized for us with canvas transform 'plus' shape transform // we are only interested in the canvas transform so 'subtract' the shape transform part painter.setTransform(shape->absoluteTransformation(&converter).inverted() * painter.transform()); painter.drawImage(zoomedClipRegion.topLeft(), sourceGraphic); painter.restore(); }
QImage QgsComposition::printPageAsRaster( int page ) { //print out via QImage, code copied from on_mActionExportAsImage_activated int width = ( int )( printResolution() * paperWidth() / 25.4 ); int height = ( int )( printResolution() * paperHeight() / 25.4 ); QImage image( QSize( width, height ), QImage::Format_ARGB32 ); if ( !image.isNull() ) { image.setDotsPerMeterX( printResolution() / 25.4 * 1000 ); image.setDotsPerMeterY( printResolution() / 25.4 * 1000 ); image.fill( 0 ); QPainter imagePainter( &image ); renderPage( &imagePainter, page ); } return image; }
/** La misma pero con el texto*/ void In2BarcodeClass::SetPixmap(QString text) { /*bc.setText(text); QImage dummyImagen(boundingRect().width(),boundingRect().height(), QImage::Format_Mono); QPainter imagePainter(&dummyImagen); bc.render(imagePainter, dummyImagen.rect(), ar); qpxImagen = QPixmap::fromImage(dummyImagen);*/ bc.setText(text); qpxImagen=QPixmap(boundingRect().width(),boundingRect().height()); QPainter imagePainter(&qpxImagen); bc.render(imagePainter, qpxImagen.rect(), ar); imagePainter.end(); //qpxImagen.save("C:\\Barcode.bmp","BMP"); }
void SvgView::paintEvent(QPaintEvent *event) { if (m_renderer == Image) { if (m_image.size() != viewport()->size()) { m_image = QImage(viewport()->size(), QImage::Format_ARGB32_Premultiplied); } QPainter imagePainter(&m_image); QGraphicsView::render(&imagePainter); imagePainter.end(); QPainter p(viewport()); p.drawImage(0, 0, m_image); } else { QGraphicsView::paintEvent(event); } }
void MScalableImage::draw(const QRect &rect, const QPoint& pixmapOffset, const QPixmap* pixmap, QPainter *painter) const { if(!pixmap || pixmap->isNull()) { // if the pixmap is not valid, draw without filling draw(rect, painter); return; } // TODO: create HW version with proper shaders (2 textures, 2 sets of texcoords + shader) // SLOW: SW fallback, create temporary render target QImage image(rect.size(), QImage::Format_ARGB32); image.fill(Qt::transparent); // paint scalable image to target QPainter imagePainter(&image); draw(QPoint(0,0), rect.size(), &imagePainter); // post process the resulting image (add mask) QImage fillImage = pixmap->toImage(); fillImage = fillImage.convertToFormat(QImage::Format_ARGB32); int sourceWidth = fillImage.width(); int sourceHeight = fillImage.height(); int width = image.width(); int height = image.height(); for (int y = 0; y < height; ++y) { // target scanline uint* target = (uint *) image.scanLine(y); // source scanline (tiled) const uint* source = (const uint *) fillImage.scanLine((pixmapOffset.y() + y) % sourceHeight); for (int x = 0; x < width; ++x) { // tile the x coordinate uint color = *(source + ((pixmapOffset.x() + x) % sourceWidth)); // alpha comes from target, colour from source *target = ((*target) & 0xff000000) | (color & 0x00ffffff); target++; } } painter->drawImage(rect, image); }
void ImageEditor::setMultiLayer(CPyramids* pyramids,int layer_num) { parameters=NULL; int ex=(pyramids[0]._extends1.rows-pyramids[0]._vector.rows)/2; _image_layer=QImage(QSize(pyramids[0]._vector.cols,pyramids[0]._vector.rows), QImage::Format_ARGB32); for (int i=0;i<layer_num;i++) { int order=pyramids[i]._order; float alpha=(float)(order+1)/(float)layer_num; cv::Mat* extends; if(_name=='L') extends=&(pyramids[i]._extends1); else extends=&(pyramids[i]._extends2); #pragma omp parallel for for(int y=0;y<_image.height();y++) for (int x=0;x<_image.width();x++) { Vec4b color; color=extends->at<Vec4b>(y+ex,x+ex); if(color[3]==0) _image_layer.setPixel(QPoint(x,y),qRgba(color[2]*alpha,color[1]*alpha,color[0]*alpha,255)); } #pragma omp barrier } QPainter imagePainter(&_image_layer); imagePainter.setPen(Qt::red); imagePainter.setFont(QFont("Arial", 20)); for (int i=0;i<layer_num;i++) { QString str; str.sprintf("%d",pyramids[i]._order); if(_name=='L') imagePainter.drawText(QRect(pyramids[i]._p1.x(),pyramids[i]._p1.y(),pyramids[i]._p1.x()+50,pyramids[i]._p1.y()+50),str); else imagePainter.drawText(QRect(pyramids[i]._p2.x(),pyramids[i]._p2.y(),pyramids[i]._p2.x()+50,pyramids[i]._p2.y()+50),str); } }
void RatingWidget::paintEvent(QPaintEvent *event) { QPainter imagePainter(&image); QPainter widgetPainter(this); for (int i = 0; i < 5; i++) { if (i < rating) { QRect target((i +1) * 20 +2, 2, 16, 16); QRect source(0, 0, 16, 16); imagePainter.drawImage(target, starOn, source); } else { QRect target((i +1) * 20 +2, 2, 16, 16); QRect source(0, 0, 16, 16); imagePainter.drawImage(target, starOff, source); } } QRect dirtyRect = event->rect(); widgetPainter.drawImage(dirtyRect, image, dirtyRect); }
QPixmap AbstractGeoPolygonGraphicsItem::texture(const QString &texturePath, const QColor &color) const { QString const key = QString::number(color.rgba()) + '/' + texturePath; QPixmap texture; if (!QPixmapCache::find(key, texture)) { QImageReader imageReader(style()->polyStyle().resolvePath(texturePath)); texture = QPixmap::fromImageReader(&imageReader); if (texture.hasAlphaChannel()) { QPixmap pixmap (texture.size()); pixmap.fill(color); QPainter imagePainter(&pixmap); imagePainter.drawPixmap(0, 0, texture); imagePainter.end(); texture = pixmap; } QPixmapCache::insert(key, texture); } return texture; }
QImage *QgsPaintEffect::sourceAsImage( QgsRenderContext &context ) { //have we already created a source image? if so, return it if ( mSourceImage ) { return mSourceImage; } if ( !mPicture ) return nullptr; //else create it //TODO - test with premultiplied image for speed QRectF bounds = imageBoundingRect( context ); mSourceImage = new QImage( bounds.width(), bounds.height(), QImage::Format_ARGB32 ); mSourceImage->fill( Qt::transparent ); QPainter imagePainter( mSourceImage ); imagePainter.setRenderHint( QPainter::Antialiasing ); imagePainter.translate( -bounds.left(), -bounds.top() ); imagePainter.drawPicture( 0, 0, *mPicture ); imagePainter.end(); mOwnsImage = true; return mSourceImage; }
void QgsColorWheel::paintEvent( QPaintEvent *event ) { Q_UNUSED( event ); QPainter painter( this ); //draw a frame QStyleOptionFrameV3 option = QStyleOptionFrameV3(); option.initFrom( this ); option.state = this->hasFocus() ? QStyle::State_Active : QStyle::State_None; style()->drawPrimitive( QStyle::PE_Frame, &option, &painter ); if ( !mWidgetImage || !mWheelImage || !mTriangleImage ) { createImages( size() ); } //draw everything in an image mWidgetImage->fill( Qt::transparent ); QPainter imagePainter( mWidgetImage ); imagePainter.setRenderHint( QPainter::Antialiasing ); if ( mWheelDirty ) { //need to redraw the wheel image createWheel(); } //draw wheel centered on widget QPointF center = QPointF( width() / 2.0, height() / 2.0 ); imagePainter.drawImage( QPointF( center.x() - ( mWheelImage->width() / 2.0 ), center.y() - ( mWheelImage->height() / 2.0 ) ), *mWheelImage ); //draw hue marker int h = hue(); double length = mWheelImage->width() / 2.0; QLineF hueMarkerLine = QLineF( center.x(), center.y(), center.x() + length, center.y() ); hueMarkerLine.setAngle( h ); imagePainter.save(); //use sourceIn mode for nicer antialiasing imagePainter.setCompositionMode( QPainter::CompositionMode_SourceIn ); QPen pen; pen.setWidth( 2 ); //adapt pen color for hue pen.setColor( h > 20 && h < 200 ? Qt::black : Qt::white ); imagePainter.setPen( pen ); imagePainter.drawLine( hueMarkerLine ); imagePainter.restore(); //draw triangle if ( mTriangleDirty ) { createTriangle(); } imagePainter.drawImage( QPointF( center.x() - ( mWheelImage->width() / 2.0 ), center.y() - ( mWheelImage->height() / 2.0 ) ), *mTriangleImage ); //draw current color marker double triangleRadius = length - mWheelThickness - 1; //adapted from equations at https://github.com/timjb/colortriangle/blob/master/colortriangle.js by Tim Baumann double lightness = mCurrentColor.lightnessF(); double hueRadians = ( h * M_PI / 180.0 ); double hx = cos( hueRadians ) * triangleRadius; double hy = -sin( hueRadians ) * triangleRadius; double sx = -cos( -hueRadians + ( M_PI / 3.0 ) ) * triangleRadius; double sy = -sin( -hueRadians + ( M_PI / 3.0 ) ) * triangleRadius; double vx = -cos( hueRadians + ( M_PI / 3.0 ) ) * triangleRadius; double vy = sin( hueRadians + ( M_PI / 3.0 ) ) * triangleRadius; double mx = ( sx + vx ) / 2.0; double my = ( sy + vy ) / 2.0; double a = ( 1 - 2.0 * fabs( lightness - 0.5 ) ) * mCurrentColor.hslSaturationF(); double x = sx + ( vx - sx ) * lightness + ( hx - mx ) * a; double y = sy + ( vy - sy ) * lightness + ( hy - my ) * a; //adapt pen color for lightness pen.setColor( lightness > 0.7 ? Qt::black : Qt::white ); imagePainter.setPen( pen ); imagePainter.setBrush( Qt::NoBrush ); imagePainter.drawEllipse( QPointF( x + center.x(), y + center.y() ), 4.0, 4.0 ); imagePainter.end(); //draw image onto widget painter.drawImage( QPoint( 0, 0 ), *mWidgetImage ); painter.end(); }
QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const { QgsSymbol *s = mItem.symbol(); if ( !s ) { return QSizeF(); } // setup temporary render context QgsRenderContext context; context.setScaleFactor( settings.dpi() / 25.4 ); context.setRendererScale( settings.mapScale() ); context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); context.setForceVectorOutput( true ); context.setPainter( ctx ? ctx->painter : nullptr ); if ( ctx && ctx->context ) { context.setExpressionContext( ctx->context->expressionContext() ); } else { // setup a minimal expression context QgsExpressionContext expContext; expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); context.setExpressionContext( expContext ); } //Consider symbol size for point markers double height = settings.symbolSize().height(); double width = settings.symbolSize().width(); //Center small marker symbols double widthOffset = 0; double heightOffset = 0; if ( QgsMarkerSymbol *markerSymbol = dynamic_cast<QgsMarkerSymbol *>( s ) ) { // allow marker symbol to occupy bigger area if necessary double size = markerSymbol->size( context ) / context.scaleFactor(); height = size; width = size; if ( width < settings.symbolSize().width() ) { widthOffset = ( settings.symbolSize().width() - width ) / 2.0; } if ( height < settings.symbolSize().height() ) { heightOffset = ( settings.symbolSize().height() - height ) / 2.0; } } if ( ctx && ctx->painter ) { double currentXPosition = ctx->point.x(); double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2; QPainter *p = ctx->painter; //setup painter scaling to dots so that raster symbology is drawn to scale double dotsPerMM = context.scaleFactor(); int opacity = 255; if ( QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layerNode()->layer() ) ) opacity = ( 255 * vectorLayer->opacity() ); p->save(); p->setRenderHint( QPainter::Antialiasing ); p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset ); p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM ); if ( opacity != 255 && settings.useAdvancedEffects() ) { //semi transparent layer, so need to draw symbol to an image (to flatten it first) //create image which is same size as legend rect, in case symbol bleeds outside its alloted space QSize tempImageSize( width * dotsPerMM, height * dotsPerMM ); QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 ); tempImage.fill( Qt::transparent ); QPainter imagePainter( &tempImage ); context.setPainter( &imagePainter ); s->drawPreviewIcon( &imagePainter, tempImageSize, &context ); context.setPainter( ctx->painter ); //reduce opacity of image imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) ); imagePainter.end(); //draw rendered symbol image p->drawImage( 0, 0, tempImage ); } else { s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context ); } if ( !mTextOnSymbolLabel.isEmpty() ) { QFontMetricsF fm( mTextOnSymbolTextFormat.scaledFont( context ) ); qreal yBaselineVCenter = ( height * dotsPerMM + fm.ascent() - fm.descent() ) / 2; QgsTextRenderer::drawText( QPointF( width * dotsPerMM / 2, yBaselineVCenter ), 0, QgsTextRenderer::AlignCenter, QStringList() << mTextOnSymbolLabel, context, mTextOnSymbolTextFormat ); } p->restore(); } return QSizeF( std::max( width + 2 * widthOffset, static_cast< double >( settings.symbolSize().width() ) ), std::max( height + 2 * heightOffset, static_cast< double >( settings.symbolSize().height() ) ) ); }
void KisMotionBlurFilter::process(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); if (!config) config = new KisFilterConfiguration(id().id(), 1); QVariant value; config->getProperty("blurAngle", value); uint blurAngle = value.toUInt(); config->getProperty("blurLength", value); uint blurLength = value.toUInt(); if (blurLength == 0) return; QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } // convert angle to radians qreal angleRadians = blurAngle / 360.0 * 2 * M_PI; // construct image qreal halfWidth = blurLength / 2.0 * cos(angleRadians); qreal halfHeight = blurLength / 2.0 * sin(angleRadians); int kernelWidth = ceil(fabs(halfWidth)) * 2; int kernelHeight = ceil(fabs(halfHeight)) * 2; // check for zero dimensions (vertical/horizontal motion vectors) kernelWidth = (kernelWidth == 0) ? 1 : kernelWidth; kernelHeight = (kernelHeight == 0) ? 1 : kernelHeight; QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32); kernelRepresentation.fill(0); QPainter imagePainter(&kernelRepresentation); imagePainter.setRenderHint(QPainter::Antialiasing); imagePainter.setPen(QPen(QColor::fromRgb(255, 255, 255), 1.0)); imagePainter.drawLine(QPointF(kernelWidth / 2 - halfWidth, kernelHeight / 2 + halfHeight), QPointF(kernelWidth / 2 + halfWidth, kernelHeight / 2 - halfHeight)); // construct kernel from image Matrix<qreal, Dynamic, Dynamic> motionBlurKernel(kernelHeight, kernelWidth); for (int j = 0; j < kernelHeight; ++j) { for (int i = 0; i < kernelWidth; ++i) { motionBlurKernel(j, i) = qRed(kernelRepresentation.pixel(i, j)); } } // apply convolution KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(motionBlurKernel, 0, motionBlurKernel.sum()); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); }
void LibraryDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { //qDebug() << "LibraryDelegate::paint" << index; if (index.parent().isValid()) { painter->save(); // Split cell into two: // 1. Normal styled item // 2. Lozenge with item count / unread count // Get useful information from the index int item_count = index.data(LibraryModel::ItemCountRole).toInt(); int unread_item_count = index.data(LibraryModel::UnreadItemCountRole).toInt(); bool can_fetch_more = index.data(LibraryModel::CanFetchMoreRole).toBool(); AbstractBibliographicCollection::State state = index.data(LibraryModel::StateRole).value< AbstractBibliographicCollection::State >(); // Calculate the width of the Lozenge // w = width of text + lozenge + padding static const int padding = 1; static const int spacing = 1; QFont font(option.font); font.setPointSize(font.pointSize() - 3); font.setBold(true); QFontMetrics fontMetrics(font); QString item_count_text = QString::number(item_count) + (can_fetch_more ? "+" : ""); int item_count_lozenge_width = fontMetrics.width(item_count_text); int unread_item_count_lozenge_width = fontMetrics.width(QString::number(unread_item_count)); int lozenge_radius = qRound(option.fontMetrics.height() / 2.0) - spacing; int lozenge_height = 2 * lozenge_radius; int lozenge_width = padding + lozenge_radius + item_count_lozenge_width + lozenge_radius + padding; if (unread_item_count > 0) { lozenge_width += padding + lozenge_radius + unread_item_count_lozenge_width + lozenge_radius; } // Leave room for status icon to do its thing if (state == AbstractBibliographicCollection::BusyState) { lozenge_width += 20; } // Partition space QStyleOptionViewItemV4 option_left(option); option_left.rect.adjust(0, 0, -lozenge_width, 0); QStyleOptionViewItemV4 option_right(option); option_right.rect.setLeft(option_left.rect.right()); // Draw normal item const QStyleOptionViewItemV3 * optionV3 = qstyleoption_cast< const QStyleOptionViewItemV3 * >(&option); const QWidget * widget = optionV3 ? optionV3->widget : 0; QStyle * style = widget ? widget->style() : QApplication::style(); initStyleOption(&option_left, index); style->drawControl(QStyle::CE_ItemViewItem, &option_left, painter, widget); initStyleOption(&option_right, index); //option_right.icon = QIcon(); //option_right.text = QString(); //style->drawControl(QStyle::CE_ItemViewItem, &option_right, painter, widget); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option_right, painter, widget); // Draw item count lozenge int top = option.rect.top() + qRound((option.rect.height() - lozenge_height) / 2.0); int left = qRound(option_right.rect.left() + spacing); { QImage image(item_count_lozenge_width + 2 * lozenge_radius, lozenge_height, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainterPath path; path.setFillRule(Qt::WindingFill); path.addEllipse(0, 0, lozenge_height, lozenge_height); path.addEllipse(item_count_lozenge_width, 0, lozenge_height, lozenge_height); path.addRect(lozenge_radius, 0, item_count_lozenge_width, lozenge_height); QPainter imagePainter(&image); if (option.state & QStyle::State_Selected) { imagePainter.setBrush(QColor(255, 255, 255, 200)); } else { imagePainter.setBrush(QColor(0, 0, 0, 100)); } imagePainter.setRenderHints(QPainter::Antialiasing, true); imagePainter.setPen(Qt::NoPen); imagePainter.drawPath(path); imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationOut); imagePainter.setBrush(Qt::NoBrush); imagePainter.setPen(Qt::black); imagePainter.setFont(font); imagePainter.drawText(image.rect(), Qt::AlignCenter, item_count_text); painter->drawImage(left, top, image); } painter->restore(); } else if (index.isValid()) { QStyleOptionViewItem option_heading(option); option_heading.font.setPointSize(option_heading.font.pointSize() - 3); option_heading.font.setBold(true); option_heading.palette.setColor(QPalette::Text, QColor(0, 0, 0, 180)); QStyledItemDelegate::paint(painter, option_heading, index); } }
//----------------------------------------------------------------------------- void qtSqueezedLabel::paintEvent(QPaintEvent* e) { QTE_D(qtSqueezedLabel); // Do nothing if drawing background for cache if (d->cacheBackground) { return; } // If invalid, or text has changed, recalculate portion to elide const QString& text = this->text(); if (!d->isValid(text)) { d->cachedText = text; d->recalculate(this->size(), this->fontMetrics()); } // Check if text fits if (!d->elided) { // If so, let ordinary label handle the painting QLabel::paintEvent(e); return; } e->accept(); // Prepare to paint text QStyle* style = this->style(); QPainter painter(this); const Qt::Alignment align = QStyle::visualAlignment(this->layoutDirection(), this->alignment()); const QPalette::ColorRole role = this->foregroundRole(); QStyleOption opt; opt.initFrom(this); // Paint text if (d->elideMode.testFlag(ElideFade)) { const QRect rect = this->rect(); const int width = rect.width(); const QString elidedText = text.mid(d->offset, d->length); // Draw text style->drawItemText(&painter, rect, align, opt.palette, this->isEnabled(), elidedText, role); // Set up fade gradient int x1, x2; if (align.testFlag(Qt::AlignLeft)) { x1 = qMax(0, width - d->fadeWidth); x2 = width; } else { x1 = qMin(width, d->fadeWidth); x2 = 0; } QLinearGradient grad(x1, 0, x2, 0); grad.setColorAt(0.0, Qt::transparent); grad.setColorAt(0.9, Qt::black); // Fade out background for overpainting QImage fadeImage(d->background); QBrush brush(grad); QPainter imagePainter(&fadeImage); imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); imagePainter.fillRect(0, 0, rect.width(), rect.height(), brush); // Fade out text by overpainting with blended fade image painter.drawImage(rect.topLeft(), fadeImage); } else { const QString elidedText = text.mid(d->offset, d->length) + qtSqueezedLabelPrivate::ellipsis(); style->drawItemText(&painter, this->rect(), align, opt.palette, this->isEnabled(), elidedText, role); } }
/* * This implementation is from QWindowsStyle (Qt 7.2) * * It is licensed under the GPL 3: * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). * Contact: Nokia Corporation ([email protected]) */ void StyleHelper::drawArrow( QStyle::PrimitiveElement element, QPainter* p, const QStyleOption* opt ) { if ( opt->rect.width() <= 1 || opt->rect.height() <= 1 ) return; QRect r = opt->rect; int size = qMin( r.height(), r.width() ); QPixmap pixmap; QString pixmapName; pixmapName.sprintf( "arrow-%s-%d-%d-%d-%lld", "$qt_ia", uint(opt->state), element, size, opt->palette.cacheKey() ); if ( !QPixmapCache::find( pixmapName, pixmap) ) { int border = size / 5; int sqsize = 2 * ( size / 2 ); QImage image( sqsize, sqsize, QImage::Format_ARGB32 ); image.fill( 0 ); QPainter imagePainter( &image ); imagePainter.setRenderHint( QPainter::Antialiasing, true ); QPolygon a; switch ( element ) { case QStyle::PE_IndicatorArrowUp: a.setPoints( 3, border, sqsize / 2, sqsize / 2, border, sqsize - border, sqsize / 2 ); break; case QStyle::PE_IndicatorArrowDown: a.setPoints( 3, border, sqsize / 2, sqsize / 2, sqsize - border, sqsize - border, sqsize / 2 ); break; case QStyle::PE_IndicatorArrowRight: a.setPoints( 3, sqsize - border, sqsize / 2, sqsize / 2, border, sqsize / 2, sqsize - border ); break; case QStyle::PE_IndicatorArrowLeft: a.setPoints( 3, border, sqsize / 2, sqsize / 2, border, sqsize / 2, sqsize - border ); break; default: break; } int bsx = 0; int bsy = 0; if ( opt->state & QStyle::State_Sunken ) { bsx = qApp->style()->pixelMetric( QStyle::PM_ButtonShiftHorizontal ); bsy = qApp->style()->pixelMetric( QStyle::PM_ButtonShiftVertical ); } QRect bounds = a.boundingRect(); int sx = sqsize / 2 - bounds.center().x() - 1; int sy = sqsize / 2 - bounds.center().y() - 1; imagePainter.translate( sx + bsx, sy + bsy ); imagePainter.setPen( opt->palette.buttonText().color() ); imagePainter.setBrush( opt->palette.buttonText() ); if ( !( opt->state & QStyle::State_Enabled ) ) { QColor foreGround( 150, 150, 150, 150 ); imagePainter.setBrush( opt->palette.mid().color() ); imagePainter.setPen( opt->palette.mid().color() ); } else { QColor shadow( 0, 0, 0, 100 ); imagePainter.translate( 0, 1 ); imagePainter.setPen( shadow ); imagePainter.setBrush( shadow ); QColor foreGround( 255, 255, 255, 210 ); imagePainter.drawPolygon( a ); imagePainter.translate( 0, -1 ); imagePainter.setPen( foreGround ); imagePainter.setBrush( foreGround ); } imagePainter.drawPolygon( a ); imagePainter.end(); pixmap = QPixmap::fromImage( image ); QPixmapCache::insert( pixmapName, pixmap ); } int xOffset = r.x() + ( r.width() - size ) / 2; int yOffset = r.y() + ( r.height() - size ) / 2; p->drawPixmap( xOffset, yOffset, pixmap ); }
void GeoPolygonGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport ) { painter->save(); bool const isBuildingFrame = isDecoration(); bool const isBuildingRoof = !isDecoration() && !decorations().isEmpty(); QPen currentPen = painter->pen(); if ( !style() ) { painter->setPen( QPen() ); } else { if ( !style()->polyStyle().outline() || isBuildingFrame ) { currentPen.setColor( Qt::transparent ); } else { if ( currentPen.color() != style()->lineStyle().paintedColor() || currentPen.widthF() != style()->lineStyle().width() ) { currentPen.setColor( style()->lineStyle().paintedColor() ); currentPen.setWidthF( style()->lineStyle().width() ); } if ( currentPen.capStyle() != style()->lineStyle().capStyle() ) currentPen.setCapStyle( style()->lineStyle().capStyle() ); if ( currentPen.style() != style()->lineStyle().penStyle() ) currentPen.setStyle( style()->lineStyle().penStyle() ); } if ( painter->pen() != currentPen ) painter->setPen( currentPen ); if ( !style()->polyStyle().fill() ) { if ( painter->brush().color() != Qt::transparent ) painter->setBrush( QColor( Qt::transparent ) ); } else { if ( isBuildingFrame ) { painter->setBrush( style()->polyStyle().paintedColor().darker(150) ); } else if ( painter->brush().color() != style()->polyStyle().paintedColor() ) { QImage textureImage = style()->polyStyle().textureImage(); if( !textureImage.isNull()){ GeoDataCoordinates coords = latLonAltBox().center(); qreal x, y; viewport->screenCoordinates(coords, x, y); if (m_cachedTexturePath != style()->polyStyle().texturePath() || m_cachedTextureColor != style()->polyStyle().paintedColor() ) { m_cachedTexture = QImage ( textureImage.size(), QImage::Format_ARGB32_Premultiplied ); m_cachedTexture.fill(style()->polyStyle().paintedColor()); QPainter imagePainter(&m_cachedTexture ); imagePainter.drawImage(0, 0, textureImage); imagePainter.end(); m_cachedTexturePath = style()->polyStyle().texturePath(); m_cachedTextureColor = style()->polyStyle().paintedColor(); } QBrush brush; brush.setTextureImage(m_cachedTexture); QTransform transform; brush.setTransform(transform.translate(x,y)); painter->setBrush(brush); } else { painter->setBrush( style()->polyStyle().paintedColor() ); } } } } if ( isBuildingFrame || isBuildingRoof ) { bool drawAccurate3D = false; bool isCameraAboveBuilding = false; QPointF offsetAtCorner = buildingOffset(QPointF(0, 0), viewport, &isCameraAboveBuilding); qreal maxOffset = qMax( qAbs( offsetAtCorner.x() ), qAbs( offsetAtCorner.y() ) ); drawAccurate3D = painter->mapQuality() == HighQuality ? maxOffset > 5.0 : maxOffset > 8.0; // Since subtracting one fully contained polygon from another results in a single // polygon with a "connecting line" between the inner and outer part we need // to first paint the inner area with no pen and then the outlines with the correct pen. QVector<QPolygonF*> outlines; QVector<QPolygonF*> innerPolygons; QVector<QPolygonF*> polygons; bool const hasInnerBoundaries = m_polygon ? !m_polygon->innerBoundaries().isEmpty() : false; if (m_polygon) { if (hasInnerBoundaries) { screenPolygons(viewport, m_polygon, innerPolygons, outlines); } viewport->screenCoordinates(m_polygon->outerBoundary(), polygons); } else if (m_ring) { viewport->screenCoordinates(*m_ring, polygons); } if ( isBuildingFrame ) { QVector<QPolygonF*> sides = (hasInnerBoundaries && drawAccurate3D && isCameraAboveBuilding) ? outlines : polygons; foreach(QPolygonF* polygon, sides) { if (polygon->isEmpty()) { continue; } if ( drawAccurate3D && isCameraAboveBuilding ) { // draw the building sides int const size = polygon->size(); QPointF & a = (*polygon)[0]; QPointF shiftA = a + buildingOffset(a, viewport); for (int i=1; i<size; ++i) { QPointF const & b = (*polygon)[i]; QPointF const shiftB = b + buildingOffset(b, viewport); QPolygonF buildingSide = QPolygonF() << a << shiftA << shiftB << b; if (hasInnerBoundaries) { //smoothen away our loss of antialiasing due to the QRegion Qt-bug workaround painter->setPen(QPen(painter->brush().color(), 1.5)); } painter->drawPolygon(buildingSide); a = b; shiftA = shiftB; } } else { // don't draw the building sides - just draw the base frame instead if (hasInnerBoundaries) { QRegion clip(polygon->toPolygon()); foreach(QPolygonF* clipPolygon, innerPolygons) { clip-=QRegion(clipPolygon->toPolygon()); } painter->setClipRegion(clip); } painter->drawPolygon(*polygon); } } } else if (isBuildingRoof) {
QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const { QgsSymbolV2* s = mItem.symbol(); if ( !s ) { return QSizeF(); } // setup temporary render context QgsRenderContext context; context.setScaleFactor( settings.dpi() / 25.4 ); context.setRendererScale( settings.mapScale() ); context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); context.setForceVectorOutput( true ); context.setPainter( ctx ? ctx->painter : 0 ); //Consider symbol size for point markers double height = settings.symbolSize().height(); double width = settings.symbolSize().width(); double size = 0; //Center small marker symbols double widthOffset = 0; double heightOffset = 0; if ( QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s ) ) { // allow marker symbol to occupy bigger area if necessary size = markerSymbol->size() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context, s->outputUnit(), s->mapUnitScale() ) / context.scaleFactor(); height = size; width = size; if ( width < settings.symbolSize().width() ) { widthOffset = ( settings.symbolSize().width() - width ) / 2.0; } if ( height < settings.symbolSize().height() ) { heightOffset = ( settings.symbolSize().height() - height ) / 2.0; } } if ( ctx ) { double currentXPosition = ctx->point.x(); double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2; QPainter* p = ctx->painter; //setup painter scaling to dots so that raster symbology is drawn to scale double dotsPerMM = context.scaleFactor(); int opacity = 255; if ( QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( layerNode()->layer() ) ) opacity = 255 - ( 255 * vectorLayer->layerTransparency() / 100 ); p->save(); p->setRenderHint( QPainter::Antialiasing ); p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset ); p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM ); if ( opacity != 255 && settings.useAdvancedEffects() ) { //semi transparent layer, so need to draw symbol to an image (to flatten it first) //create image which is same size as legend rect, in case symbol bleeds outside its alloted space QSize tempImageSize( width * dotsPerMM, height * dotsPerMM ); QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 ); tempImage.fill( Qt::transparent ); QPainter imagePainter( &tempImage ); context.setPainter( &imagePainter ); s->drawPreviewIcon( &imagePainter, tempImageSize, &context ); context.setPainter( ctx->painter ); //reduce opacity of image imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) ); imagePainter.end(); //draw rendered symbol image p->drawImage( 0, 0, tempImage ); } else { s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context ); } p->restore(); } return QSizeF( qMax( width + 2 * widthOffset, ( double ) settings.symbolSize().width() ), qMax( height + 2 * heightOffset, ( double ) settings.symbolSize().height() ) ); }
void QgsColorWheel::createTriangle() { if ( !mWheelImage || !mTriangleImage ) { return; } QPointF center = QPointF( mWheelImage->width() / 2.0, mWheelImage->height() / 2.0 ); mTriangleImage->fill( Qt::transparent ); QPainter imagePainter( mTriangleImage ); imagePainter.setRenderHint( QPainter::Antialiasing ); int angle = hue(); double wheelRadius = mWheelImage->width() / 2.0; double triangleRadius = wheelRadius - mWheelThickness - 1; //pure version of hue (at full saturation and value) QColor pureColor = QColor::fromHsv( angle, 255, 255 ); //create copy of color but with 0 alpha QColor alphaColor = QColor( pureColor ); alphaColor.setAlpha( 0 ); //some rather ugly shortcuts to obtain corners and midpoints of triangle QLineF line1 = QLineF( center.x(), center.y(), center.x() - triangleRadius * cos( M_PI / 3.0 ), center.y() - triangleRadius * sin( M_PI / 3.0 ) ); QLineF line2 = QLineF( center.x(), center.y(), center.x() + triangleRadius, center.y() ); QLineF line3 = QLineF( center.x(), center.y(), center.x() - triangleRadius * cos( M_PI / 3.0 ), center.y() + triangleRadius * sin( M_PI / 3.0 ) ); QLineF line4 = QLineF( center.x(), center.y(), center.x() - triangleRadius * cos( M_PI / 3.0 ), center.y() ); QLineF line5 = QLineF( center.x(), center.y(), ( line2.p2().x() + line1.p2().x() ) / 2.0, ( line2.p2().y() + line1.p2().y() ) / 2.0 ); line1.setAngle( line1.angle() + angle ); line2.setAngle( line2.angle() + angle ); line3.setAngle( line3.angle() + angle ); line4.setAngle( line4.angle() + angle ); line5.setAngle( line5.angle() + angle ); QPointF p1 = line1.p2(); QPointF p2 = line2.p2(); QPointF p3 = line3.p2(); QPointF p4 = line4.p2(); QPointF p5 = line5.p2(); //inspired by Tim Baumann's work at https://github.com/timjb/colortriangle/blob/master/colortriangle.js QLinearGradient colorGrad = QLinearGradient( p4.x(), p4.y(), p2.x(), p2.y() ); colorGrad.setColorAt( 0, alphaColor ); colorGrad.setColorAt( 1, pureColor ); QLinearGradient whiteGrad = QLinearGradient( p3.x(), p3.y(), p5.x(), p5.y() ); whiteGrad.setColorAt( 0, QColor( 255, 255, 255, 255 ) ); whiteGrad.setColorAt( 1, QColor( 255, 255, 255, 0 ) ); QPolygonF triangle; triangle << p2 << p1 << p3 << p2; imagePainter.setPen( Qt::NoPen ); //start with a black triangle imagePainter.setBrush( QBrush( Qt::black ) ); imagePainter.drawPolygon( triangle ); //draw a gradient from transparent to the pure color at the triangle's tip imagePainter.setBrush( QBrush( colorGrad ) ); imagePainter.drawPolygon( triangle ); //draw a white gradient using additive composition mode imagePainter.setCompositionMode( QPainter::CompositionMode_Plus ); imagePainter.setBrush( QBrush( whiteGrad ) ); imagePainter.drawPolygon( triangle ); //above process results in some small artifacts on the edge of the triangle. Let's clear these up //use source composition mode and draw an outline using a transparent pen //this clears the edge pixels and leaves a nice smooth image imagePainter.setCompositionMode( QPainter::CompositionMode_Source ); imagePainter.setBrush( Qt::NoBrush ); imagePainter.setPen( QPen( Qt::transparent ) ); imagePainter.drawPolygon( triangle ); imagePainter.end(); mTriangleDirty = false; }
void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { if (!panelWidget(widget)) return d->style->drawPrimitive(element, option, painter, widget); bool animating = (option->state & State_Animating); int state = option->state; QRect rect = option->rect; QRect oldRect; QRect newRect; if (widget && (element == PE_PanelButtonTool) && !animating) { QWidget *w = const_cast<QWidget *> (widget); int oldState = w->property("_q_stylestate").toInt(); oldRect = w->property("_q_stylerect").toRect(); newRect = w->rect(); w->setProperty("_q_stylestate", (int)option->state); w->setProperty("_q_stylerect", w->rect()); // Determine the animated transition bool doTransition = ((state & State_On) != (oldState & State_On) || (state & State_MouseOver) != (oldState & State_MouseOver)); if (oldRect != newRect) { doTransition = false; d->animator.stopAnimation(widget); } if (doTransition) { QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); Animation *anim = d->animator.widgetAnimation(widget); QStyleOption opt = *option; opt.state = (QStyle::State)oldState; opt.state |= (State)State_Animating; startImage.fill(0); Transition *t = new Transition; t->setWidget(w); QPainter startPainter(&startImage); if (!anim) { drawPrimitive(element, &opt, &startPainter, widget); } else { anim->paint(&startPainter, &opt); d->animator.stopAnimation(widget); } QStyleOption endOpt = *option; endOpt.state |= (State)State_Animating; t->setStartImage(startImage); d->animator.startAnimation(t); endImage.fill(0); QPainter endPainter(&endImage); drawPrimitive(element, &endOpt, &endPainter, widget); t->setEndImage(endImage); t->setDuration(130); t->setStartTime(QTime::currentTime()); } } switch (element) { case PE_PanelLineEdit: { painter->save(); if (option->state & State_Enabled) drawCornerImage(d->lineeditImage, painter, option->rect, 2, 2, 2, 2); else drawCornerImage(d->lineeditImage_disabled, painter, option->rect, 2, 2, 2, 2); if (option->state & State_HasFocus || option->state & State_MouseOver) { QColor hover = StyleHelper::baseColor(); if (state & State_HasFocus) hover.setAlpha(100); else hover.setAlpha(50); painter->setPen(QPen(hover, 1)); painter->drawRect(option->rect.adjusted(1, 1, -2 ,-2)); } painter->restore(); } break; case PE_FrameStatusBarItem: break; case PE_PanelButtonTool: { Animation *anim = d->animator.widgetAnimation(widget); if (!animating && anim) { anim->paint(painter, option); } else { bool pressed = option->state & State_Sunken || option->state & State_On; QColor shadow(0, 0, 0, 30); painter->setPen(shadow); if (pressed) { QColor shade(0, 0, 0, 40); painter->fillRect(rect, shade); painter->drawLine(rect.topLeft() + QPoint(1, 0), rect.topRight() - QPoint(1, 0)); painter->drawLine(rect.topLeft(), rect.bottomLeft()); painter->drawLine(rect.topRight(), rect.bottomRight()); // painter->drawLine(rect.bottomLeft() + QPoint(1, 0), rect.bottomRight() - QPoint(1, 0)); QColor highlight(255, 255, 255, 30); painter->setPen(highlight); } else if (option->state & State_Enabled && option->state & State_MouseOver) { QColor lighter(255, 255, 255, 37); painter->fillRect(rect, lighter); } } } break; case PE_PanelStatusBar: { painter->save(); QLinearGradient grad(option->rect.topLeft(), QPoint(rect.center().x(), rect.bottom())); QColor startColor = StyleHelper::shadowColor().darker(164); QColor endColor = StyleHelper::baseColor().darker(130); grad.setColorAt(0, endColor); grad.setColorAt(1, endColor); painter->fillRect(option->rect, grad); painter->setPen(QColor(255, 255, 255, 60)); painter->drawLine(rect.topLeft() + QPoint(0,1), rect.topRight()+ QPoint(0,1)); painter->setPen(StyleHelper::borderColor().darker(110)); painter->drawLine(rect.topLeft(), rect.topRight()); painter->restore(); } break; case PE_IndicatorToolBarSeparator: { QColor separatorColor = StyleHelper::borderColor(); separatorColor.setAlpha(100); painter->setPen(separatorColor); const int margin = 3; if (option->state & State_Horizontal) { const int offset = rect.width()/2; painter->drawLine(rect.bottomLeft().x() + offset, rect.bottomLeft().y() - margin, rect.topLeft().x() + offset, rect.topLeft().y() + margin); } else { //Draw vertical separator const int offset = rect.height()/2; painter->setPen(QPen(option->palette.background().color().darker(110))); painter->drawLine(rect.topLeft().x() + margin , rect.topLeft().y() + offset, rect.topRight().x() - margin, rect.topRight().y() + offset); } } break; case PE_IndicatorToolBarHandle: { bool horizontal = option->state & State_Horizontal; painter->save(); QPainterPath path; int x = option->rect.x() + horizontal ? 2 : 6; int y = option->rect.y() + horizontal ? 6 : 2; static const int RectHeight = 2; if (horizontal) { while (y < option->rect.height() - RectHeight - 6) { path.moveTo(x, y); path.addRect(x, y, RectHeight, RectHeight); y += 6; } } else { while (x < option->rect.width() - RectHeight - 6) { path.moveTo(x, y); path.addRect(x, y, RectHeight, RectHeight); x += 6; } } painter->setPen(Qt::NoPen); QColor dark = StyleHelper::borderColor(); dark.setAlphaF(0.4); QColor light = StyleHelper::baseColor(); light.setAlphaF(0.4); painter->fillPath(path, light); painter->save(); painter->translate(1, 1); painter->fillPath(path, dark); painter->restore(); painter->translate(3, 3); painter->fillPath(path, light); painter->translate(1, 1); painter->fillPath(path, dark); painter->restore(); } break; case PE_IndicatorArrowUp: case PE_IndicatorArrowDown: case PE_IndicatorArrowRight: case PE_IndicatorArrowLeft: { // From windowsstyle but modified to enable AA if (option->rect.width() <= 1 || option->rect.height() <= 1) break; QRect r = option->rect; int size = qMin(r.height(), r.width()); QPixmap pixmap; QString pixmapName; pixmapName.sprintf("%s-%s-%d-%d-%d-%lld", "$qt_ia", metaObject()->className(), uint(option->state), element, size, option->palette.cacheKey()); if (!QPixmapCache::find(pixmapName, pixmap)) { int border = size/5; int sqsize = 2*(size/2); QImage image(sqsize, sqsize, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter imagePainter(&image); imagePainter.setRenderHint(QPainter::Antialiasing, true); imagePainter.translate(0.5, 0.5); QPolygon a; switch (element) { case PE_IndicatorArrowUp: a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize - border, sqsize/2); break; case PE_IndicatorArrowDown: a.setPoints(3, border, sqsize/2, sqsize/2, sqsize - border, sqsize - border, sqsize/2); break; case PE_IndicatorArrowRight: a.setPoints(3, sqsize - border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); break; case PE_IndicatorArrowLeft: a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); break; default: break; } int bsx = 0; int bsy = 0; if (option->state & State_Sunken) { bsx = pixelMetric(PM_ButtonShiftHorizontal); bsy = pixelMetric(PM_ButtonShiftVertical); } QRect bounds = a.boundingRect(); int sx = sqsize / 2 - bounds.center().x() - 1; int sy = sqsize / 2 - bounds.center().y() - 1; imagePainter.translate(sx + bsx, sy + bsy); if (!(option->state & State_Enabled)) { QColor foreGround(150, 150, 150, 150); imagePainter.setBrush(option->palette.mid().color()); imagePainter.setPen(option->palette.mid().color()); } else { QColor shadow(0, 0, 0, 100); imagePainter.translate(0, 1); imagePainter.setPen(shadow); imagePainter.setBrush(shadow); QColor foreGround(255, 255, 255, 210); imagePainter.drawPolygon(a); imagePainter.translate(0, -1); imagePainter.setPen(foreGround); imagePainter.setBrush(foreGround); } imagePainter.drawPolygon(a); imagePainter.end(); pixmap = QPixmap::fromImage(image); QPixmapCache::insert(pixmapName, pixmap); } int xOffset = r.x() + (r.width() - size)/2; int yOffset = r.y() + (r.height() - size)/2; painter->drawPixmap(xOffset, yOffset, pixmap); } break; default: d->style->drawPrimitive(element, option, painter, widget); break; } }
void KisLensBlurFilter::process(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); if (!config) config = new KisFilterConfiguration(id().id(), 1); QVariant value; config->getProperty("irisShape", value); QString irisShape = value.toString(); config->getProperty("irisRadius", value); uint irisRadius = value.toUInt(); config->getProperty("irisRotation", value); uint irisRotation = value.toUInt(); if (irisRadius < 1) return; QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } QPolygonF irisShapePoly; int sides = 1; qreal angle = 0; if (irisShape == "Triangle") sides = 3; else if (irisShape == "Quadrilateral (4)") sides = 4; else if (irisShape == "Pentagon (5)") sides = 5; else if (irisShape == "Hexagon (6)") sides = 6; else if (irisShape == "Heptagon (7)") sides = 7; else if (irisShape == "Octagon (8)") sides = 8; else return; for (int i = 0; i < sides; ++i) { irisShapePoly << QPointF(0.5 * cos(angle), 0.5 * sin(angle)); angle += 2 * M_PI / sides; } QTransform transform; transform.rotate(irisRotation); transform.scale(irisRadius * 2, irisRadius * 2); QPolygonF transformedIris; for (int i = 0; i < irisShapePoly.count(); ++i) { transformedIris << irisShapePoly[i] * transform; } // find extremes to determine kernel size required qreal minX = 0, maxX = 0, minY = 0, maxY = 0; for (int i = 0; i < transformedIris.count(); ++i) { if (transformedIris[i].x() < minX) minX = transformedIris[i].x(); if (transformedIris[i].x() > maxX) maxX = transformedIris[i].x(); if (transformedIris[i].y() < minY) minY = transformedIris[i].y(); if (transformedIris[i].y() > maxY) maxY = transformedIris[i].y(); } int kernelWidth = ceil(maxX) - ceil(minX); int kernelHeight = ceil(maxY) - ceil(minY); QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32); kernelRepresentation.fill(0); QPainter imagePainter(&kernelRepresentation); imagePainter.setRenderHint(QPainter::Antialiasing); imagePainter.setBrush(QColor::fromRgb(255, 255, 255)); QTransform offsetTransform; offsetTransform.translate(-minX, -minY); imagePainter.setTransform(offsetTransform); imagePainter.drawPolygon(transformedIris, Qt::WindingFill); // construct kernel from image Matrix<qreal, Dynamic, Dynamic> irisKernel(kernelHeight, kernelWidth); for (int j = 0; j < kernelHeight; ++j) { for (int i = 0; i < kernelWidth; ++i) { irisKernel(j, i) = qRed(kernelRepresentation.pixel(i, j)); } } // apply convolution KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(irisKernel, 0, irisKernel.sum()); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); }