void drawNativeImage(const NativeImagePtr& image, GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, const IntSize&, CompositeOperator op, BlendMode mode, const ImageOrientation& orientation) { context.save(); // Set the compositing operation. if (op == CompositeSourceOver && mode == BlendModeNormal && !nativeImageHasAlpha(image)) context.setCompositeOperation(CompositeCopy); else context.setCompositeOperation(op, mode); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) IntSize scaledSize = nativeImageSize(image); FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(srcRect, scaledSize); #else FloatRect adjustedSrcRect(srcRect); #endif FloatRect adjustedDestRect = destRect; if (orientation != DefaultImageOrientation) { // ImageOrientation expects the origin to be at (0, 0). context.translate(destRect.x(), destRect.y()); adjustedDestRect.setLocation(FloatPoint()); context.concatCTM(orientation.transformFromDefault(adjustedDestRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rectangle will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. adjustedDestRect.setSize(adjustedDestRect.size().transposedSize()); } } context.platformContext()->drawSurfaceToContext(image.get(), adjustedDestRect, adjustedSrcRect, context); context.restore(); }
void BitmapImage::draw(GraphicsContext& context, const FloatRect& dst, const FloatRect& src, CompositeOperator op, BlendMode blendMode, ImageOrientationDescription description) { if (!dst.width() || !dst.height() || !src.width() || !src.height()) return; startAnimation(); auto surface = frameImageAtIndex(m_currentFrame); if (!surface) // If it's too early we won't have an image yet. return; Color color = singlePixelSolidColor(); if (color.isValid()) { fillWithSolidColor(context, dst, color, op); return; } context.save(); // Set the compositing operation. if (op == CompositeSourceOver && blendMode == BlendModeNormal && !frameHasAlphaAtIndex(m_currentFrame)) context.setCompositeOperation(CompositeCopy); else context.setCompositeOperation(op, blendMode); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) IntSize scaledSize = cairoSurfaceSize(surface.get()); FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize); #else FloatRect adjustedSrcRect(src); #endif ImageOrientation frameOrientation(description.imageOrientation()); if (description.respectImageOrientation() == RespectImageOrientation) frameOrientation = frameOrientationAtIndex(m_currentFrame); FloatRect dstRect = dst; if (frameOrientation != DefaultImageOrientation) { // ImageOrientation expects the origin to be at (0, 0). context.translate(dstRect.x(), dstRect.y()); dstRect.setLocation(FloatPoint()); context.concatCTM(frameOrientation.transformFromDefault(dstRect.size())); if (frameOrientation.usesWidthAsHeight()) { // The destination rectangle will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width()); } } context.platformContext()->drawSurfaceToContext(surface.get(), dstRect, adjustedSrcRect, context); context.restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op, BlendMode, RespectImageOrientationEnum shouldRespectImageOrientation) { if (!dst.width() || !dst.height() || !src.width() || !src.height()) return; startAnimation(); NativeImageCairo* nativeImage = frameAtIndex(m_currentFrame); if (!nativeImage) // If it's too early we won't have an image yet. return; if (mayFillWithSolidColor()) { fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op); return; } context->save(); // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) cairo_surface_t* surface = nativeImage->surface(); IntSize scaledSize(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize); #else FloatRect adjustedSrcRect(src); #endif ImageOrientation orientation = DefaultImageOrientation; if (shouldRespectImageOrientation == RespectImageOrientation) orientation = frameOrientationAtIndex(m_currentFrame); FloatRect dstRect = dst; if (orientation != DefaultImageOrientation) { // ImageOrientation expects the origin to be at (0, 0). context->translate(dstRect.x(), dstRect.y()); dstRect.setLocation(FloatPoint()); context->concatCTM(orientation.transformFromDefault(dstRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rectangle will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width()); } } context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, adjustedSrcRect, context); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
// Drawing Routines void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { QRectF normalizedDst = dst.normalized(); QRectF normalizedSrc = src.normalized(); startAnimation(); if (normalizedSrc.isEmpty() || normalizedDst.isEmpty()) return; QPixmap* image = nativeImageForCurrentFrame(); if (!image) return; if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, normalizedDst, solidColor(), styleColorSpace, op); return; } #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) normalizedSrc = adjustSourceRectForDownSampling(normalizedSrc, image->size()); #endif CompositeOperator previousOperator = ctxt->compositeOperation(); ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op); if (ctxt->hasShadow()) { ShadowBlur* shadow = ctxt->shadowBlur(); GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst); if (shadowContext) { QPainter* shadowPainter = shadowContext->platformContext(); shadowPainter->drawPixmap(normalizedDst, *image, normalizedSrc); shadow->endShadowLayer(ctxt); } } ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc); ctxt->setCompositeOperation(previousOperator); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { if (dst.isEmpty() || src.isEmpty()) return; NativeImagePtr image = nativeImageForCurrentFrame(); if (!image) return; startAnimation(); if (mayFillWithSolidColor()) { fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op); return; } context->save(); // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) FloatRect srcRectLocal = adjustSourceRectForDownSampling(src, image->size()); #else FloatRect srcRectLocal(src); #endif context->platformContext()->activePainter()->drawImage(image, dst, srcRectLocal); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect) { QPixmap* framePixmap = nativeImageForCurrentFrame(); if (!framePixmap) // If it's too early we won't have an image yet. return; #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) FloatRect tileRectAdjusted = adjustSourceRectForDownSampling(tileRect, framePixmap->size()); #else FloatRect tileRectAdjusted = tileRect; #endif // Qt interprets 0 width/height as full width/height so just short circuit. QRectF dr = QRectF(destRect).normalized(); QRect tr = QRectF(tileRectAdjusted).toRect().normalized(); if (!dr.width() || !dr.height() || !tr.width() || !tr.height()) return; QPixmap pixmap = *framePixmap; if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) pixmap = pixmap.copy(tr); CompositeOperator previousOperator = ctxt->compositeOperation(); ctxt->setCompositeOperation(!pixmap.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op); QPainter* p = ctxt->platformContext(); QTransform transform(patternTransform); // If this would draw more than one scaled tile, we scale the pixmap first and then use the result to draw. if (transform.type() == QTransform::TxScale) { QRectF tileRectInTargetCoords = (transform * QTransform().translate(phase.x(), phase.y())).mapRect(tr); bool tileWillBePaintedOnlyOnce = tileRectInTargetCoords.contains(dr); if (!tileWillBePaintedOnlyOnce) { QSizeF scaledSize(float(pixmap.width()) * transform.m11(), float(pixmap.height()) * transform.m22()); QPixmap scaledPixmap(scaledSize.toSize()); if (pixmap.hasAlpha()) scaledPixmap.fill(Qt::transparent); { QPainter painter(&scaledPixmap); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.setRenderHints(p->renderHints()); painter.drawPixmap(QRect(0, 0, scaledPixmap.width(), scaledPixmap.height()), pixmap); } pixmap = scaledPixmap; transform = QTransform::fromTranslate(transform.dx(), transform.dy()); } } /* Translate the coordinates as phase is not in world matrix coordinate space but the tile rect origin is. */ transform *= QTransform().translate(phase.x(), phase.y()); transform.translate(tr.x(), tr.y()); QBrush b(pixmap); b.setTransform(transform); p->fillRect(dr, b); ctxt->setCompositeOperation(previousOperator); if (imageObserver()) imageObserver()->didDraw(this); }