void Shadow::draw(QPainter* painter) { // if nothing to show outside the item, just draw source if ((blurRadius() + distance()) <= 0) { drawSource(painter); return; } PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect; QPoint offset; const QPixmap px = sourcePixmap(Qt::DeviceCoordinates, &offset, mode); // return if no source if (px.isNull()) return; // save world transform QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); // Calculate size for the background image QSize szi(px.size().width() + 2 * distance(), px.size().height() + 2 * distance()); QImage tmp(szi, QImage::Format_ARGB32_Premultiplied); QPixmap scaled = px.scaled(szi); tmp.fill(0); QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(QPointF(-distance(), -distance()), scaled); tmpPainter.end(); // blur the alpha channel QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); blurred.fill(0); QPainter blurPainter(&blurred); qt_blurImage(&blurPainter, tmp, blurRadius(), false, true); blurPainter.end(); tmp = blurred; // blacken the image... tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color()); tmpPainter.end(); // draw the blurred shadow... painter->drawImage(offset, tmp); // draw the actual pixmap... painter->drawPixmap(offset, px, QRectF()); // restore world transform painter->setWorldTransform(restoreTransform); }
// addDropShadow is inspired by QPixmapDropShadowFilter::draw in // qt/src/gui/effects/qpixmapfilter.cpp QPixmap addDropShadow( const QPixmap& source, const QSize& targetSize ) { const QPoint offset( 2, 4 ); const int radius = 4; const QColor shadowColor( 100, 100, 100, 100 ); // If there is no targetSize, then return a larger pixmap with the shadow added on // otherwise, return a bounded pixmap and shrink the source const QSize sizeToUse = targetSize.isEmpty() ? QSize( source.width() + offset.x() + radius, source.height() + offset.y() + radius ) : targetSize; const QSize shrunkToFit( sizeToUse.width() - offset.x() - radius, sizeToUse.height() - offset.y() - radius ); const QPixmap shrunk = source.scaled( shrunkToFit, Qt::KeepAspectRatio, Qt::SmoothTransformation ); QImage tmp( sizeToUse, QImage::Format_ARGB32_Premultiplied ); tmp.fill( 0 ); QPainter tmpPainter( &tmp ); tmpPainter.setCompositionMode( QPainter::CompositionMode_Source ); tmpPainter.drawPixmap( offset, shrunk ); tmpPainter.end(); // blur the alpha channel QImage blurred( sizeToUse, QImage::Format_ARGB32_Premultiplied ); blurred.fill( 0 ); QPainter blurPainter( &blurred ); qt_blurImage( &blurPainter, tmp, radius, false, true ); blurPainter.end(); // blacken the image... QPainter blackenPainter( &blurred ); blackenPainter.setCompositionMode( QPainter::CompositionMode_SourceIn ); blackenPainter.fillRect( blurred.rect(), shadowColor ); blackenPainter.end(); const QRect resultRect( shrunk.rect().united( shrunk.rect().translated( offset ).adjusted( -radius, -radius, radius, radius ) ) ); QPixmap result( resultRect.size() ); result.fill( Qt::transparent ); QPainter resultPainter( &result ); // draw the blurred drop shadow... resultPainter.drawImage( 0, 0, blurred ); // Draw the actual pixmap... resultPainter.drawPixmap( 0, 0, shrunk ); return result; }
QT_END_NAMESPACE void ShadowEffect::draw(QPainter* painter){ if((blurRadius() + distance()) <= 0){ drawSource(painter); return; } PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect; QPoint offset; const QPixmap px = sourcePixmap(Qt::DeviceCoordinates, &offset, mode); if(px.isNull()) return; QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); QSize szi(px.size().width() + 2 * distance(), px.size().height() + 2 * distance()); QImage tmp(szi, QImage::Format_ARGB32_Premultiplied); QPixmap scaled = px.scaled(szi); tmp.fill(0); QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(QPointF(-distance(), -distance()), scaled); tmpPainter.end(); QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); blurred.fill(0); QPainter blurPainter(&blurred); qt_blurImage(&blurPainter, tmp, blurRadius(), false, true); blurPainter.end(); tmp = blurred; tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color()); tmpPainter.end(); painter->drawImage(offset, tmp); painter->drawPixmap(offset, px, QRectF()); painter->setWorldTransform(restoreTransform); }
void MirrorGraphicsEffect::draw(QPainter *painter) { PixmapPadMode mode = PadToEffectiveBoundingRect; // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode); if (pixmap.isNull()) return; QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); // We'll draw widget on this image QImage tmp(pixmap.size(), QImage::Format_ARGB32_Premultiplied); tmp.fill(Qt::transparent); // We're going to draw widget on tmp image using this painter object QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(QPoint(0,0), pixmap); tmpPainter.end(); // Now we need to mirror image and put alpha channel gradient on our image of control // First mirror it by Y axis QImage mirroredImage(tmp.mirrored(false, true)); // Create gradient object QPoint p1, p2; p2.setY(mirroredImage.height()); QLinearGradient gradient(p1, p2); gradient.setColorAt(0.3, QColor(0, 0, 0, 255)); gradient.setColorAt(0.8, QColor(0, 0, 0, 0)); // With this painter we'll draw gradient on mirror image QPainter mirroredImagePainter(&mirroredImage); mirroredImagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); mirroredImagePainter.fillRect(0, 0, mirroredImage.width(), mirroredImage.height(), gradient); mirroredImagePainter.end(); // Draw reflection first painter->drawImage(offset, mirroredImage); // Draw source widget painter->drawPixmap(offset, pixmap); painter->setWorldTransform(restoreTransform); }
// Draws a cached pixmap with shadow void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, int radius, const QColor &color, const QPoint &offset) { QPixmap cache; QString pixmapName = QString("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height()); if (!QPixmapCache::find(pixmapName, cache)) { QPixmap px = icon.pixmap(rect.size()); cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)); cache.fill(Qt::transparent); QPainter cachePainter(&cache); if (iconMode == QIcon::Disabled) { QImage im = px.toImage().convertToFormat(QImage::Format_ARGB32); for (int y=0; y<im.height(); ++y) { QRgb *scanLine = (QRgb*)im.scanLine(y); for (int x=0; x<im.width(); ++x) { QRgb pixel = *scanLine; char intensity = qGray(pixel); *scanLine = qRgba(intensity, intensity, intensity, qAlpha(pixel)); ++scanLine; } } px = QPixmap::fromImage(im); } // Draw shadow QImage tmp(px.size() + QSize(radius * 2, radius * 2 + 1), QImage::Format_ARGB32_Premultiplied); tmp.fill(Qt::transparent); QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(QPoint(radius, radius), px); tmpPainter.end(); // blur the alpha channel QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); blurred.fill(Qt::transparent); QPainter blurPainter(&blurred); qt_blurImage(&blurPainter, tmp, radius, false, true); blurPainter.end(); tmp = blurred; // blacken the image... tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color); tmpPainter.end(); tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color); tmpPainter.end(); // draw the blurred drop shadow... cachePainter.drawImage(QRect(0, 0, cache.rect().width(), cache.rect().height()), tmp); // Draw the actual pixmap... cachePainter.drawPixmap(QPoint(radius, radius) + offset, px); QPixmapCache::insert(pixmapName, cache); } QRect targetRect = cache.rect(); targetRect.moveCenter(rect.center()); p->drawPixmap(targetRect.topLeft() - offset, cache); }
void CustomLabel::paintEvent(QPaintEvent *pe) { if ((!text().isEmpty()) && (textFormat() == Qt::PlainText || (textFormat() == Qt::AutoText && !Qt::mightBeRichText(text())))) { QPainter painter(this); #ifndef DEBUG_CUSTOMLABEL QRectF lr = contentsRect(); lr.moveBottom(lr.bottom() - 1); // angry and dirty hack! QStyleOption opt; opt.initFrom(this); int align = QStyle::visualAlignment(text().isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight, alignment()); int flags = align | (!text().isRightToLeft() ? Qt::TextForceLeftToRight : Qt::TextForceRightToLeft); if (wordWrap()) flags |= Qt::TextWordWrap; switch (shadowType) { case NoShadow: flags |= TF_NOSHADOW; break; case DarkShadow: flags |= TF_DARKSHADOW; break; case LightShadow: flags |= TF_LIGHTSHADOW; break; default: break; } QString textToDraw = elidedText(); style()->drawItemText(&painter, lr.toRect(), flags, opt.palette, isEnabled(), textToDraw, QPalette::WindowText); #else // DEBUG_CUSTOMLABEL QTextDocument *doc = textDocument(); QAbstractTextDocumentLayout::PaintContext ctx = textDocumentPaintContext(doc); QString shadowKey; switch (shadowType) { case DarkShadow: shadowKey = GFX_TEXTSHADOWS; break; case LightShadow: shadowKey = GFX_NOTICEWIDGET; break; case NoShadow: default: break; } // magic numbers int dx = -2; int dy = -2; // adding margins dx += contentsMargins().left(); dy += contentsMargins().top(); # if 1 // for debug set 0 QGraphicsDropShadowEffect *shadow = qobject_cast<QGraphicsDropShadowEffect *>(GraphicsEffectsStorage::staticStorage(RSR_STORAGE_GRAPHICSEFFECTS)->getFirstEffect(shadowKey)); # else // debug shadow QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect; shadow->setColor(Qt::red); shadow->setOffset(1, 1); # endif if (shadow) { # if 0 // for "image method" set 1 QImage shadowedText(size(), QImage::Format_ARGB32_Premultiplied); # if defined(Q_WS_MAC) && !defined(__MAC_OS_X_NATIVE_FULLSCREEN) // TODO: fix that shadowedText.fill(Qt::red); // DUNNO WHY!!! # else shadowedText.fill(Qt::transparent); # endif QPainter tmpPainter(&shadowedText); tmpPainter.setRenderHint(QPainter::Antialiasing); tmpPainter.setRenderHint(QPainter::HighQualityAntialiasing); tmpPainter.setRenderHint(QPainter::TextAntialiasing); tmpPainter.setRenderHint(QPainter::SmoothPixmapTransform); tmpPainter.translate(dx, dy); doc->documentLayout()->draw(&tmpPainter, ctx); painter.drawImage(0, 0, shadowedText); # else // text method QPalette origPal = ctx.palette; ctx.palette.setColor(QPalette::Text, shadow->color()); // draw shadow painter.save(); painter.translate(dx + shadow->xOffset(), dy + shadow->yOffset()); doc->documentLayout()->draw(&painter, ctx); painter.restore(); ctx.palette = origPal; // draw text painter.save(); painter.translate(dx, dy); doc->documentLayout()->draw(&painter, ctx); painter.restore(); # endif // shadow method } else { painter.save(); painter.translate(dx, dy); doc->documentLayout()->draw(&painter, ctx); painter.restore(); } doc->deleteLater(); #endif // DEBUG_CUSTOMLABEL } else QLabel::paintEvent(pe); }
// Draws a cached pixmap with shadow void FancyTabBar::drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, int dipRadius, const QColor &color, const QPoint &dipOffset) { QPixmap cache; QString pixmapName = QString::fromLatin1("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height()); if (!QPixmapCache::find(pixmapName, cache)) { // High-dpi support: The in parameters (rect, radius, offset) are in // device-independent pixels. The call to QIcon::pixmap() below might // return a high-dpi pixmap, which will in that case have a devicePixelRatio // different than 1. The shadow drawing caluculations are done in device // pixels. QPixmap px = icon.pixmap(rect.size()); //jassuncao int devicePixelRatio = qCeil(px.devicePixelRatio()); int devicePixelRatio = 1; int radius = dipRadius * devicePixelRatio; QPoint offset = dipOffset * devicePixelRatio; cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)); cache.fill(Qt::transparent); QPainter cachePainter(&cache); if (iconMode == QIcon::Disabled) { QImage im = px.toImage().convertToFormat(QImage::Format_ARGB32); for (int y=0; y<im.height(); ++y) { QRgb *scanLine = (QRgb*)im.scanLine(y); for (int x=0; x<im.width(); ++x) { QRgb pixel = *scanLine; char intensity = qGray(pixel); *scanLine = qRgba(intensity, intensity, intensity, qAlpha(pixel)); ++scanLine; } } px = QPixmap::fromImage(im); } // Draw shadow QImage tmp(px.size() + QSize(radius * 2, radius * 2 + 1), QImage::Format_ARGB32_Premultiplied); tmp.fill(Qt::transparent); QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(QRect(radius, radius, px.width(), px.height()), px); tmpPainter.end(); // blur the alpha channel QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); blurred.fill(Qt::transparent); QPainter blurPainter(&blurred); qt_blurImage(&blurPainter, tmp, radius, false, true); blurPainter.end(); tmp = blurred; // blacken the image... tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color); tmpPainter.end(); tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), color); tmpPainter.end(); // draw the blurred drop shadow... cachePainter.drawImage(QRect(0, 0, cache.rect().width(), cache.rect().height()), tmp); // Draw the actual pixmap... cachePainter.drawPixmap(QRect(QPoint(radius, radius) + offset, QSize(px.width(), px.height())), px); //jassuncao: cache.setDevicePixelRatio(devicePixelRatio); QPixmapCache::insert(pixmapName, cache); } QRect targetRect = cache.rect(); //jassuncao targetRect.setSize(targetRect.size() / cache.devicePixelRatio()); targetRect.moveCenter(rect.center() - dipOffset); p->drawPixmap(targetRect, cache); }
void MapGraphicsView::setStatusMessage(QString msg) { if(msg.isEmpty()) { m_statusLabel->setPixmap(QPixmap()); m_statusLabel->hide(); return; } m_statusLabel->show(); if(Qt::mightBeRichText(msg)) { QTextDocument doc; doc.setHtml(msg); msg = doc.toPlainText(); } QImage tmp(1,1,QImage::Format_ARGB32_Premultiplied); QPainter tmpPainter(&tmp); QFont font("");//"", 20); tmpPainter.setFont(font); QRectF maxRect(0, 0, (qreal)width(), (qreal)height() * .25); QRectF boundingRect = tmpPainter.boundingRect(maxRect, Qt::TextWordWrap | Qt::AlignHCenter, msg); boundingRect.adjust(0, 0, tmpPainter.font().pointSizeF() * 3, tmpPainter.font().pointSizeF() * 1.25); QImage labelImage(boundingRect.size().toSize(), QImage::Format_ARGB32_Premultiplied); memset(labelImage.bits(), 0, labelImage.byteCount()); QPainter p(&labelImage); QColor bgColor(0, 127, 254, 180); #ifdef Q_OS_ANDROID bgColor = bgColor.lighter(300); #endif p.setPen(QPen(Qt::white, 2.5)); p.setBrush(bgColor); p.drawRoundedRect(labelImage.rect().adjusted(0,0,-1,-1), 3., 3.); QImage txtImage(boundingRect.size().toSize(), QImage::Format_ARGB32_Premultiplied); memset(txtImage.bits(), 0, txtImage.byteCount()); QPainter tp(&txtImage); tp.setPen(Qt::white); tp.setFont(font); tp.drawText(QRectF(QPointF(0,0), boundingRect.size()), Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter, msg); tp.end(); double ss = 8.; p.drawImage((int)-ss,(int)-ss, ImageUtils::addDropShadow(txtImage, ss)); p.end(); #ifdef Q_OS_ANDROID m_statusLabel->setPixmap(QPixmap::fromImage(labelImage)); #else m_statusLabel->setPixmap(QPixmap::fromImage(ImageUtils::addDropShadow(labelImage, ss))); #endif }
QImage RichTextRenderer::renderText() { // qDebug()<<itemName()<<"TextBoxWarmingThread::run(): htmlCode:"<<htmlCode; //qDebug() << "RichTextRenderer::renderText(): HTML:"<<html(); //qDebug() << "RichTextRenderer::update(): Update Start..."; //qDebug() << "RichTextRenderer::renderText(): \t in thread:"<<QThread::currentThreadId(); if(m_updateTimer.isActive()) m_updateTimer.stop(); QTime renderTime; renderTime.start(); QTextDocument doc; QTextDocument shadowDoc; if (Qt::mightBeRichText(html())) { doc.setHtml(html()); shadowDoc.setHtml(html()); } else { doc.setPlainText(html()); shadowDoc.setPlainText(html()); } int textWidth = m_textWidth; doc.setTextWidth(textWidth); shadowDoc.setTextWidth(textWidth); // Apply outline pen to the html QTextCursor cursor(&doc); cursor.select(QTextCursor::Document); QTextCharFormat format; QPen p(Qt::NoPen); if(outlineEnabled()) { p = outlinePen(); p.setJoinStyle(Qt::MiterJoin); } format.setTextOutline(p); //format.setForeground(fillEnabled() ? fillBrush() : Qt::NoBrush); //Qt::white); cursor.mergeCharFormat(format); // Setup the shadow text formatting if enabled if(shadowEnabled()) { if(shadowBlurRadius() <= 0.05) { QTextCursor cursor(&shadowDoc); cursor.select(QTextCursor::Document); QTextCharFormat format; format.setTextOutline(Qt::NoPen); format.setForeground(shadowBrush()); cursor.mergeCharFormat(format); } } QSizeF shadowSize = shadowEnabled() ? QSizeF(shadowOffsetX(),shadowOffsetY()) : QSizeF(0,0); QSizeF docSize = doc.size(); QSizeF padSize(12.,12.); QSizeF sumSize = (docSize + shadowSize + padSize);//.toSize(); QSizeF scaledSize = QSizeF(sumSize.width() * m_scaling.x(), sumSize.height() * m_scaling.y()); if(m_scaling.x() != 1. || m_scaling.y() != 1.) { //qDebug() << "RichTextRenderer::renderText(): Orig size:"<<sumSize<<", scaled size:"<<scaledSize<<", scaling:"<<m_scaling; m_rawSize = sumSize; } //qDebug() << "RichTextRenderer::update(): textWidth: "<<textWidth<<", shadowSize:"<<shadowSize<<", docSize:"<<docSize<<", sumSize:"<<sumSize; QImage cache(scaledSize.toSize(),QImage::Format_ARGB32); //_Premultiplied); memset(cache.scanLine(0),0,cache.byteCount()); double padSizeHalfX = padSize.width() / 2; double padSizeHalfY = padSize.height() / 2; QPainter textPainter(&cache); textPainter.scale(m_scaling.x(), m_scaling.y()); //textPainter.fillRect(cache.rect(),Qt::transparent); QAbstractTextDocumentLayout::PaintContext pCtx; //qDebug() << "RichTextRenderer::renderText(): shadowEnabled():"<<shadowEnabled()<<", shadowBlurRadius():"<<shadowBlurRadius(); if(shadowEnabled()) { if(shadowBlurRadius() <= 0.05) { // render a "cheap" version of the shadow using the shadow text document textPainter.save(); textPainter.translate(shadowOffsetX(),shadowOffsetY()); shadowDoc.documentLayout()->draw(&textPainter, pCtx); textPainter.restore(); } else { double radius = shadowBlurRadius(); // create temporary pixmap to hold a copy of the text QSizeF blurSize = ImageFilters::blurredSizeFor(doc.size(), (int)radius); QSizeF scaledBlurSize = QSize(blurSize.width() * m_scaling.x(), blurSize.height() * m_scaling.y()); //QSize docSize = doc.size(); //qDebug() << "RichTextRenderer::renderText(): [shadow] radius:"<<radius<<" blurSize:"<<blurSize<<", scaling:"<<m_scaling<<", scaledBlurSize:"<<scaledBlurSize; //qDebug() << "Blur size:"<<blurSize<<", doc:"<<doc.size()<<", radius:"<<radius; QImage tmpImage(scaledBlurSize.toSize(),QImage::Format_ARGB32_Premultiplied); memset(tmpImage.scanLine(0),0,tmpImage.byteCount()); // render the text QPainter tmpPainter(&tmpImage); tmpPainter.scale(m_scaling.x(), m_scaling.y()); tmpPainter.save(); tmpPainter.translate(radius + padSizeHalfX, radius + padSizeHalfY); doc.documentLayout()->draw(&tmpPainter, pCtx); tmpPainter.restore(); // blacken the text by applying a color to the copy using a QPainter::CompositionMode_DestinationIn operation. // This produces a homogeneously-colored pixmap. QRect rect = tmpImage.rect(); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(rect, shadowBrush().color()); tmpPainter.end(); // blur the colored text ImageFilters::blurImage(tmpImage, (int)radius); // render the blurred text at an offset into the cache textPainter.save(); textPainter.translate(shadowOffsetX() - radius, shadowOffsetY() - radius); textPainter.drawImage(0, 0, tmpImage); textPainter.restore(); } } textPainter.translate(padSizeHalfX, padSizeHalfY); doc.documentLayout()->draw(&textPainter, pCtx); textPainter.end(); m_image = cache.convertToFormat(QImage::Format_ARGB32); emit textRendered(m_image); //qDebug() << "RichTextRenderer::renderText(): Render finished, elapsed:"<<renderTime.elapsed()<<"ms"; //m_image.save("debug-text.png"); return m_image; }
void GLImageDrawable::updateShadow() { if(!m_shadowDrawable) return; QImage sourceImg = m_imageWithBorder.isNull() ? m_image : m_imageWithBorder; QSizeF originalSizeWithBorder = sourceImg.size(); QPointF scale = m_glw ? QPointF(m_glw->transform().m11(), m_glw->transform().m22()) : QPointF(1.,1.); if(scale.x() < 1.25 && scale.y() < 1.25) scale = QPointF(1,1); double radius = m_shadowBlurRadius; // create temporary pixmap to hold a copy of the text double radiusSpacing = radius;// / 1.75;// * 1.5; double radius2 = radius * 2; // double offx = 0; //fabs(m_shadowOffset.x()); // double offy = 0; //fabs(m_shadowOffset.y()); double newWidth = originalSizeWithBorder.width() + radius2 * scale.x();// blur on both sides //+ offx * scale.x(); double newHeight = originalSizeWithBorder.height() + radius2 * scale.y();// blur on both sides //+ offy * scale.y(); QSizeF blurSize(newWidth,newHeight); // blurSize.rwidth() *= scale.x(); // blurSize.rheight() *= scale.y(); //qDebug() << "GLImageDrawable::applyBorderAndShadow(): Blur size:"<<blurSize<<", originalSizeWithBorder:"<<originalSizeWithBorder<<", radius:"<<radius<<", radius2:"<<radius2<<", m_shadowOffset:"<<m_shadowOffset<<", offx:"<<offx<<", offy:"<<offy<<", scale:"<<scale; QImage tmpImage(blurSize.toSize(),QImage::Format_ARGB32_Premultiplied); memset(tmpImage.scanLine(0),0,tmpImage.byteCount()); // render the source image into a temporary buffer for bluring QPainter tmpPainter(&tmpImage); //tmpPainter.scale(scale.x(),scale.y()); tmpPainter.save(); QPointF translate1(radiusSpacing, radiusSpacing); translate1.rx() *= scale.x(); translate1.ry() *= scale.y(); //qDebug() << "stage1: radiusSpacing:"<<radiusSpacing<<", m_shadowOffset:"<<m_shadowOffset<<", translate1:"<<translate1; //qDebug() << "GLImageDrawable::updateShadow(): translate1:"<<translate1<<", scale:"<<scale; tmpPainter.translate(translate1); tmpPainter.drawImage(0,0,sourceImg); tmpPainter.restore(); // color the orignal image by applying a color to the copy using a QPainter::CompositionMode_DestinationIn operation. // This produces a homogeneously-colored pixmap. QRect imgRect = tmpImage.rect(); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); QColor color = m_shadowColor; // clamp m_shadowOpacity to 1.0 because we handle values >1.0 by repainting the blurred image over itself (m_shadowOpacity-1) times. color.setAlpha((int)(255.0 * (m_shadowOpacity > 1.0 ? 1.0 : m_shadowOpacity))); tmpPainter.fillRect(imgRect, color); tmpPainter.end(); // blur the colored text ImageFilters::blurImage(tmpImage, (int)(radius * scale.x())); if(m_shadowOpacity > 1.0) { QPainter painter2(&tmpImage); int times = (int)(m_shadowOpacity - 1.0); // Cap at 10 - an arbitrary cap just to prevent the user from taxing the CPU too much. if(times > 10) times = 10; double finalOpacity = m_shadowOpacity - ((int)m_shadowOpacity); if(finalOpacity < 0.001) finalOpacity = 1.0; QImage copy = tmpImage.copy(); for(int i=0; i<times-1; i++) painter2.drawImage(0,0,copy); //qDebug() << "Overpaint feature: times:"<<times<<", finalOpacity:"<<finalOpacity; painter2.setOpacity(finalOpacity); painter2.drawImage(0,0,copy); painter2.setOpacity(1.0); } // { // QPainter painter2(&tmpImage); // painter2.setPen(Qt::yellow); // // QPointF translate1(radiusSpacing, // radiusSpacing); // translate1.rx() *= scale.x(); // translate1.ry() *= scale.y(); // //qDebug() << "stage1: radiusSpacing:"<<radiusSpacing<<", m_shadowOffset:"<<m_shadowOffset<<", translate1:"<<translate1; // //qDebug() << "GLImageDrawable::updateShadow(): translate1:"<<translate1<<", scale:"<<scale; // // painter2.translate(translate1); // painter2.drawImage(0,0,sourceImg); // painter2.drawRect(sourceImg.rect()); // // } // Notice: Older versions of this shadow code drew the sourceImg back on top of the shadow - // Since we are drawaing the drop shadow as a separate texture below the real image in the // m_shadowDrawable, we are not going to draw the sourceImg on top now. //qDebug() << "GLImageDrawable::updateShadow(): shadow location:"<<point<<", size:"<<tmpImage.size()<<", rect().topLeft():"<<rect().topLeft()<<", m_shadowOffset:"<<m_shadowOffset<<", radiusSpacing:"<<radiusSpacing; bool scaleFlag = dynamic_cast<GLTextDrawable*>(this) == NULL; // double scale_w = scaleFlag ? fabs((double)(rect().width() - sourceImg.width())) / sourceImg.width() : 1.0; // double scale_h = scaleFlag ? fabs((double)(rect().height() - sourceImg.height())) / sourceImg.height() : 1.0; double scale_w = scaleFlag ? m_targetRect.width() / m_sourceRect.width() : 1.0; double scale_h = scaleFlag ? m_targetRect.height() / m_sourceRect.height() : 1.0; // scale_w *= 2; // scale_h *= 2; QSizeF size(((double)tmpImage.width()) * scale_w, ((double)tmpImage.height()) * scale_h); QPointF point = rect().topLeft() + QPointF(m_shadowOffset.x() * scale_w, m_shadowOffset.y() * scale_h) - QPointF(m_shadowBlurRadius * scale_w,m_shadowBlurRadius * scale_h); //qDebug() << "GLImageDrawable::updateShadow: "<<(QObject*)this<<" m_targetRect:"<<m_targetRect.size()<<", m_sourceRect:"<<m_sourceRect.size()<<", scale:"<<scale_w<<"x"<<scale_h<<", tmpImage:"<<tmpImage.size()<<", new size:"<<size<<", point:"<<point; m_shadowDrawable->setRect(QRectF(point, size)); m_shadowDrawable->setImage(tmpImage); //updateGL(); }
void TextBoxContent::renderShadow(QPainter *painter, QAbstractTextDocumentLayout::PaintContext *pCtx) { AbstractVisualItem *model = modelItem(); if(qFuzzyIsNull(model->shadowBlurRadius())) { // render a "cheap" version of the shadow using the shadow text document painter->save(); painter->translate(model->shadowOffsetX(),model->shadowOffsetY()); m_shadowText->documentLayout()->draw(painter, *pCtx); painter->restore(); } else { // double radius = model->shadowBlurRadius(); // double radiusSquared = radius*radius; // // // create temporary pixmap to hold a copy of the text // double blurSize = (int)(radiusSquared*2); // QSize shadowSize(blurSize,blurSize); // QPixmap tmpPx(contentsRect().size()+shadowSize); // tmpPx.fill(Qt::transparent); // // // render the text // QPainter tmpPainter(&tmpPx); // tmpPainter.save(); // tmpPainter.translate(radiusSquared, radiusSquared); // m_text->documentLayout()->draw(&tmpPainter, *pCtx); // tmpPainter.restore(); // // // blacken the text by applying a color to the copy using a QPainter::CompositionMode_DestinationIn operation. // // This produces a homogeneously-colored pixmap. // QRect rect = QRect(0, 0, tmpPx.width(), tmpPx.height()); // tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); // tmpPainter.fillRect(rect, model->shadowBrush().color()); // tmpPainter.end(); // // // blur the colored text // QImage orignalImage = tmpPx.toImage(); // QImage blurredImage = ImageFilters::blurred(orignalImage, rect, (int)radius); // QPixmap blurredPixmap = QPixmap::fromImage(blurredImage); // // // render the blurred text at an offset into the cache // painter->save(); // painter->translate(model->shadowOffsetX() - radiusSquared, // model->shadowOffsetY() - radiusSquared); // painter->drawPixmap(0, 0, blurredPixmap); // painter->restore(); // New method of rendering shadows double radius = model->shadowBlurRadius(); // create temporary pixmap to hold a copy of the text QSizeF blurSize = ImageFilters::blurredSizeFor(model->contentsRect().size(), (int)radius); //qDebug() << "Blur size:"<<blurSize<<", doc:"<<doc.size()<<", radius:"<<radius; QImage tmpImage(blurSize.toSize(),QImage::Format_ARGB32_Premultiplied); memset(tmpImage.scanLine(0),0,tmpImage.byteCount()); // render the text QPainter tmpPainter(&tmpImage); tmpPainter.save(); tmpPainter.translate(radius, radius); m_text->documentLayout()->draw(&tmpPainter, *pCtx); tmpPainter.restore(); // blacken the text by applying a color to the copy using a QPainter::CompositionMode_DestinationIn operation. // This produces a homogeneously-colored pixmap. QRect rect = tmpImage.rect(); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(rect, model->shadowBrush().color()); tmpPainter.end(); // blur the colored text ImageFilters::blurImage(tmpImage, (int)radius); // render the blurred text at an offset into the cache painter->save(); painter->translate(model->shadowOffsetX() - radius, model->shadowOffsetY() - radius); painter->drawImage(0, 0, tmpImage); painter->restore(); } }
void TextBoxWarmingThread::run() { if(!m_model) { qDebug()<<"TextBoxWarmingThread::run(): m_model is null"; return; } //qDebug()<<"TextBoxWarmingThread::run(): model ptr:"<<m_model<<", attempting to dynamic cast"; TextBoxItem * model = dynamic_cast<TextBoxItem*>((AbstractVisualItem*)m_model); //int sleepTime = (int)(((float)qrand()) / ((float)RAND_MAX) * 10000.0 + 2000.0); //qDebug()<<"TextBoxWarmingThread::run(): modelItem:"<<model->itemName();//<<": Cache redraw, sleep: "<<sleepTime; // Sleep doesnt work - if I sleep, then it seems the cache is never updated! //sleep((unsigned long)sleepTime); //sleep(1000); QString htmlCode = model->text(); // qDebug()<<model->itemName()<<"TextBoxWarmingThread::run(): htmlCode:"<<htmlCode; QTextDocument doc; QTextDocument shadowDoc; doc.setHtml(htmlCode); shadowDoc.setHtml(htmlCode); int textWidth = model->contentsRect().toRect().width(); doc.setTextWidth(textWidth); shadowDoc.setTextWidth(textWidth); // Apply outline pen to the html QTextCursor cursor(&doc); cursor.select(QTextCursor::Document); QTextCharFormat format; QPen p(Qt::NoPen); if(model && model->outlineEnabled()) { p = model->outlinePen(); p.setJoinStyle(Qt::MiterJoin); } format.setTextOutline(p); format.setForeground(model && model->fillType() == AbstractVisualItem::Solid ? model->fillBrush() : Qt::NoBrush); //Qt::white); cursor.mergeCharFormat(format); #if QT46_SHADOW_ENAB == 0 // Setup the shadow text formatting if enabled if(model && model->shadowEnabled()) { if(qFuzzyIsNull(model->shadowBlurRadius())) { QTextCursor cursor(&shadowDoc); cursor.select(QTextCursor::Document); QTextCharFormat format; format.setTextOutline(Qt::NoPen); format.setForeground(model ? model->shadowBrush() : Qt::black); cursor.mergeCharFormat(format); } } #endif QSizeF shadowSize = model->shadowEnabled() ? QSizeF(model->shadowOffsetX(),model->shadowOffsetY()) : QSizeF(0,0); QImage *cache = new QImage((model->contentsRect().size()+shadowSize).toSize(),QImage::Format_ARGB32_Premultiplied); memset(cache->scanLine(0),0,cache->byteCount()); QPainter textPainter(cache); textPainter.fillRect(cache->rect(),Qt::transparent); QAbstractTextDocumentLayout::PaintContext pCtx; #if QT46_SHADOW_ENAB == 0 if(model->shadowEnabled()) { if(qFuzzyIsNull(model->shadowBlurRadius())) { // render a "cheap" version of the shadow using the shadow text document textPainter.save(); textPainter.translate(model->shadowOffsetX(),model->shadowOffsetY()); shadowDoc.documentLayout()->draw(&textPainter, pCtx); textPainter.restore(); } else { // double radius = model->shadowBlurRadius(); // double radiusSquared = radius*radius; // // // create temporary pixmap to hold a copy of the text // double blurSize = (int)(radiusSquared*2); // QSize shadowSize(blurSize,blurSize); // QImage tmpImage((model->contentsRect().size()+shadowSize).toSize(),QImage::Format_ARGB32); // memset(tmpImage.scanLine(0),0,tmpImage.byteCount()); // // // render the text // QPainter tmpPainter(&tmpImage); // tmpPainter.fillRect(tmpImage.rect(),Qt::transparent); // // tmpPainter.save(); // tmpPainter.translate(radiusSquared, radiusSquared); // doc.documentLayout()->draw(&tmpPainter, pCtx); // tmpPainter.restore(); // // // blacken the text by applying a color to the copy using a QPainter::CompositionMode_DestinationIn operation. // // This produces a homogeneously-colored pixmap. // QRect rect = tmpImage.rect(); // tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); // tmpPainter.fillRect(rect, model->shadowBrush().color()); // tmpPainter.end(); // // // blur the colored text // QImage blurredImage = ImageFilters::blurred(tmpImage, rect, (int)radius); // // // render the blurred text at an offset into the cache // textPainter.save(); // textPainter.translate(model->shadowOffsetX() - radiusSquared, // model->shadowOffsetY() - radiusSquared); // textPainter.drawImage(0, 0, blurredImage.copy(blurredImage.rect())); // textPainter.restore(); // New method of rendering shadows double radius = model->shadowBlurRadius(); // create temporary pixmap to hold a copy of the text QSizeF blurSize = ImageFilters::blurredSizeFor(model->contentsRect().size(), (int)radius); //qDebug() << "Blur size:"<<blurSize<<", doc:"<<doc.size()<<", radius:"<<radius; QImage tmpImage(blurSize.toSize(),QImage::Format_ARGB32_Premultiplied); memset(tmpImage.scanLine(0),0,tmpImage.byteCount()); // render the text QPainter tmpPainter(&tmpImage); tmpPainter.save(); tmpPainter.translate(radius, radius); doc.documentLayout()->draw(&tmpPainter, pCtx); tmpPainter.restore(); // blacken the text by applying a color to the copy using a QPainter::CompositionMode_DestinationIn operation. // This produces a homogeneously-colored pixmap. QRect rect = tmpImage.rect(); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(rect, model->shadowBrush().color()); tmpPainter.end(); // blur the colored text ImageFilters::blurImage(tmpImage, (int)radius); // render the blurred text at an offset into the cache textPainter.save(); textPainter.translate(model->shadowOffsetX() - radius, model->shadowOffsetY() - radius); textPainter.drawImage(0, 0, tmpImage); textPainter.restore(); } } #endif doc.documentLayout()->draw(&textPainter, pCtx); textPainter.end(); emit renderDone(cache); }