void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator op, BlendMode) { if (!m_document || m_currentPage == -1) return; { GraphicsContextStateSaver stateSaver(*context); context->setCompositeOperation(op); float hScale = dstRect.width() / srcRect.width(); float vScale = dstRect.height() / srcRect.height(); // Scale and translate so the document is rendered in the correct location, // including accounting for the fact that a GraphicsContext is always flipped // and doing appropriate flipping. CGContextTranslateCTM(context->platformContext(), dstRect.x() - srcRect.x() * hScale, dstRect.y() - srcRect.y() * vScale); CGContextScaleCTM(context->platformContext(), hScale, vScale); CGContextScaleCTM(context->platformContext(), 1, -1); CGContextTranslateCTM(context->platformContext(), 0, -srcRect.height()); CGContextClipToRect(context->platformContext(), CGRectIntegral(srcRect)); // Rotate translate image into position according to doc properties. adjustCTM(context); CGContextTranslateCTM(context->platformContext(), -m_mediaBox.x(), -m_mediaBox.y()); CGContextDrawPDFPage(context->platformContext(), CGPDFDocumentGetPage(m_document, m_currentPage + 1)); } if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::cacheFrame(size_t index) { size_t numFrames = frameCount(); if (m_frames.size() < numFrames) m_frames.grow(numFrames); int deltaBytes = totalFrameBytes(); // We are caching frame snapshots. This is OK even for partially decoded frames, // as they are cleared by dataChanged() when new data arrives. m_frames[index].m_frame = m_source.createFrameAtIndex(index); m_frames[index].m_orientation = m_source.orientationAtIndex(index); m_frames[index].m_haveMetadata = true; m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); if (repetitionCount(false) != cAnimationNone) m_frames[index].m_duration = m_source.frameDurationAtIndex(index); m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); if (frameSize != m_size) m_hasUniformFrameSize = false; // We need to check the total bytes before and after the decode call, not // just the current frame size, because some multi-frame images may require // decoding multiple frames to decode the current frame. deltaBytes = totalFrameBytes() - deltaBytes; if (deltaBytes && imageObserver()) imageObserver()->decodedSizeChanged(this, deltaBytes); }
void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op) { if (!m_document || m_currentPage == -1) return; context->save(); context->setCompositeOperation(op); float hScale = dstRect.width() / srcRect.width(); float vScale = dstRect.height() / srcRect.height(); // Scale and translate so the document is rendered in the correct location, // including accounting for the fact that a GraphicsContext is always flipped // and doing appropriate flipping. CGContextTranslateCTM(context->platformContext(), dstRect.x() - srcRect.x() * hScale, dstRect.y() - srcRect.y() * vScale); CGContextScaleCTM(context->platformContext(), hScale, vScale); CGContextScaleCTM(context->platformContext(), 1, -1); CGContextTranslateCTM(context->platformContext(), 0, -srcRect.height()); CGContextClipToRect(context->platformContext(), CGRectIntegral(srcRect)); // Rotate translate image into position according to doc properties. adjustCTM(context); // Media box may have non-zero origin which we ignore. Pass 1 for the page number. CGContextDrawPDFDocument(context->platformContext(), FloatRect(FloatPoint(), m_mediaBox.size()), m_document, m_currentPage + 1); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::destroyDecodedData(bool incremental) { // Destroy the cached images and release them. if (m_frames.size()) { int sizeChange = 0; int frameSize = m_size.width() * m_size.height() * 4; for (unsigned i = incremental ? m_frames.size() - 1 : 0; i < m_frames.size(); i++) { if (m_frames[i].m_frame) { sizeChange -= frameSize; m_frames[i].clear(); } } // We just always invalidate our platform data, even in the incremental case. // This could be better, but it's not a big deal. m_isSolidColor = false; invalidatePlatformData(); if (sizeChange) { m_decodedSize += sizeChange; if (imageObserver()) imageObserver()->decodedSizeChanged(this, sizeChange); } if (!incremental) { // Reset the image source, since Image I/O has an underlying cache that it uses // while animating that it seems to never clear. m_source.clear(); m_source.setData(m_data.get(), m_allDataReceived); } } }
void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp) { if (!m_frame) return; context->save(); context->setCompositeOperation(compositeOp); context->clip(enclosingIntRect(dstRect)); if (compositeOp != CompositeSourceOver) context->beginTransparencyLayer(1.0f); context->translate(dstRect.location().x(), dstRect.location().y()); context->scale(FloatSize(dstRect.width()/srcRect.width(), dstRect.height()/srcRect.height())); if (m_frame->view()->needsLayout()) m_frame->view()->layout(); m_frame->paint(context, enclosingIntRect(srcRect)); if (compositeOp != CompositeSourceOver) context->endTransparencyLayer(); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
// Drawing Routines void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op) { startAnimation(); QPixmap* image = nativeImageForCurrentFrame(); if (!image) return; if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dst, solidColor(), op); return; } IntSize selfSize = size(); ctxt->save(); // Set the compositing operation. ctxt->setCompositeOperation(op); QPainter* painter(ctxt->platformContext()); if (!image->hasAlpha() && painter->compositionMode() == QPainter::CompositionMode_SourceOver) painter->setCompositionMode(QPainter::CompositionMode_Source); // Test using example site at // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html painter->drawPixmap(dst, *image, src); ctxt->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) { QPixmap* framePixmap = nativeImageForCurrentFrame(); if (!framePixmap) // If it's too early we won't have an image yet. return; QPixmap pixmap = *framePixmap; QRect tr = QRectF(tileRect).toRect(); if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) pixmap = pixmap.copy(tr); QBrush b(pixmap); b.setTransform(patternTransform); ctxt->save(); ctxt->setCompositeOperation(op); QPainter* p = ctxt->platformContext(); if (!pixmap.hasAlpha() && p->compositionMode() == QPainter::CompositionMode_SourceOver) p->setCompositionMode(QPainter::CompositionMode_Source); p->setBrushOrigin(phase); p->fillRect(destRect, b); ctxt->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void PDFDocumentImage::updateCachedImageIfNeeded(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect) { // If we have an existing image, reuse it if we're doing a low-quality paint, even if cache parameters don't match; // we'll rerender when we do the subsequent high-quality paint. InterpolationQuality interpolationQuality = context->imageInterpolationQuality(); bool useLowQualityInterpolation = interpolationQuality == InterpolationNone || interpolationQuality == InterpolationLow; if (!m_cachedImageBuffer || (!cacheParametersMatch(context, dstRect, srcRect) && !useLowQualityInterpolation)) { m_cachedImageBuffer = context->createCompatibleBuffer(enclosingIntRect(dstRect).size()); if (!m_cachedImageBuffer) return; GraphicsContext* bufferContext = m_cachedImageBuffer->context(); if (!bufferContext) { m_cachedImageBuffer = nullptr; return; } transformContextForPainting(bufferContext, dstRect, srcRect); drawPDFPage(bufferContext); m_cachedTransform = context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale); m_cachedDestinationSize = dstRect.size(); m_cachedSourceRect = srcRect; IntSize internalSize = m_cachedImageBuffer->internalSize(); size_t oldCachedBytes = m_cachedBytes; m_cachedBytes = internalSize.width() * internalSize.height() * 4; if (imageObserver()) imageObserver()->decodedSizeChanged(this, safeCast<int>(m_cachedBytes) - safeCast<int>(oldCachedBytes)); } }
void BitmapImage::cacheFrame(size_t index) { size_t numFrames = frameCount(); ASSERT(m_decodedSize == 0 || numFrames > 1); if (m_frames.size() < numFrames) m_frames.grow(numFrames); m_frames[index].m_frame = m_source.createFrameAtIndex(index); if (numFrames == 1 && m_frames[index].m_frame) checkForSolidColor(); m_frames[index].m_haveMetadata = true; m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); if (repetitionCount(false) != cAnimationNone) m_frames[index].m_duration = m_source.frameDurationAtIndex(index); m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); if (frameSize != m_size) m_hasUniformFrameSize = false; if (m_frames[index].m_frame) { const int deltaBytes = frameBytes(frameSize); m_decodedSize += deltaBytes; if (imageObserver()) imageObserver()->decodedSizeChanged(this, deltaBytes); } }
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { FloatRect srcRect(src); FloatRect dstRect(dst); if (dstRect.width() == 0.0f || dstRect.height() == 0.0f || srcRect.width() == 0.0f || srcRect.height() == 0.0f) return; startAnimation(); cairo_surface_t* image = frameAtIndex(m_currentFrame); if (!image) // If it's too early we won't have an image yet. return; if (mayFillWithSolidColor()) { fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op); return; } context->save(); // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); context->platformContext()->drawSurfaceToContext(image, dstRect, srcRect, context); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op) { FloatRect srcRect(src); FloatRect dstRect(dst); if (dstRect.width() == 0.0f || dstRect.height() == 0.0f || srcRect.width() == 0.0f || srcRect.height() == 0.0f) return; startAnimation(); cairo_surface_t* image = frameAtIndex(m_currentFrame); if (!image) // If it's too early we won't have an image yet. return; if (mayFillWithSolidColor()) { fillWithSolidColor(context, dstRect, solidColor(), op); return; } IntSize selfSize = size(); cairo_t* cr = context->platformContext(); cairo_save(cr); // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); // If we're drawing a sub portion of the image or scaling then create // a pattern transformation on the image and draw the transformed pattern. // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); // To avoid the unwanted gradient effect (#14017) we use // CAIRO_FILTER_NEAREST now, but the real fix will be to have // CAIRO_EXTEND_PAD implemented for surfaces in Cairo allowing us to still // use bilinear filtering cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); float scaleX = srcRect.width() / dstRect.width(); float scaleY = srcRect.height() / dstRect.height(); cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() }; cairo_pattern_set_matrix(pattern, &matrix); // Draw the image. cairo_translate(cr, dstRect.x(), dstRect.y()); cairo_set_source(cr, pattern); cairo_pattern_destroy(pattern); cairo_rectangle(cr, 0, 0, dstRect.width(), dstRect.height()); cairo_clip(cr); cairo_paint_with_alpha(cr, context->getAlpha()); cairo_restore(cr); if (imageObserver()) imageObserver()->didDraw(this); }
void Image::drawImage(GraphicsContext *gc, const FloatRect &dstRect, const FloatRect &srcRect, ColorSpace, CompositeOperator, BlendMode) { JNIEnv* env = WebCore_GetJavaEnv(); if (!gc || gc->paintingDisabled()) { return; } NativeImagePtr currFrame = nativeImageForCurrentFrame(); if (!currFrame) { return; } gc->platformContext()->rq().freeSpace(72) << (jint)com_sun_webkit_graphics_GraphicsDecoder_DRAWIMAGE << currFrame << dstRect.x() << dstRect.y() << dstRect.width() << dstRect.height() << srcRect.x() << srcRect.y() << srcRect.width() << srcRect.height(); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::cacheFrame(size_t index) { size_t numFrames = frameCount(); ASSERT(m_decodedSize == 0 || numFrames > 1); if (m_frames.size() < numFrames) m_frames.grow(numFrames); m_frames[index].m_frame = m_source.createFrameAtIndex(index); if (numFrames == 1 && m_frames[index].m_frame) checkForSolidColor(); m_frames[index].m_orientation = m_source.orientationAtIndex(index); m_frames[index].m_haveMetadata = true; m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); if (repetitionCount(false) != cAnimationNone) m_frames[index].m_duration = m_source.frameDurationAtIndex(index); m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); if (frameSize != m_size) m_hasUniformFrameSize = false; if (m_frames[index].m_frame) { int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes); m_decodedSize += deltaBytes; // The fully-decoded frame will subsume the partially decoded data used // to determine image properties. deltaBytes -= m_decodedPropertiesSize; m_decodedPropertiesSize = 0; if (imageObserver()) imageObserver()->decodedSizeChanged(this, deltaBytes); } }
void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp) { if (!m_page) return; FrameView* view = m_page->mainFrame()->view(); context->save(); context->setCompositeOperation(compositeOp); context->clip(enclosingIntRect(dstRect)); if (compositeOp != CompositeSourceOver) context->beginTransparencyLayer(1); context->translate(dstRect.location().x(), dstRect.location().y()); context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height())); view->resize(size()); if (view->needsLayout()) view->layout(); view->paint(context, IntRect(0, 0, view->width(), view->height())); if (compositeOp != CompositeSourceOver) context->endTransparencyLayer(); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void Image::cacheFrame(size_t index) { size_t numFrames = frameCount(); ASSERT(m_decodedSize == 0 || numFrames > 1); if (!m_frames.size() && shouldAnimate()) { // Snag the repetition count. m_repetitionCount = m_source.repetitionCount(); if (m_repetitionCount == cAnimationNone) m_animatingImageType = false; } if (m_frames.size() < numFrames) m_frames.resize(numFrames); m_frames[index].m_frame = m_source.createFrameAtIndex(index); if (numFrames == 1 && m_frames[index].m_frame) checkForSolidColor(); if (shouldAnimate()) m_frames[index].m_duration = m_source.frameDurationAtIndex(index); m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); int sizeChange = m_frames[index].m_frame ? m_size.width() * m_size.height() * 4 : 0; if (sizeChange) { if (imageObserver()) imageObserver()->decodedSizeChanging(this, sizeChange); m_decodedSize += sizeChange; if (imageObserver()) imageObserver()->decodedSizeChanged(this, sizeChange); } }
NativeImagePtr BitmapImage::frameImageAtIndex(size_t index, float presentationScaleHint) { if (index >= frameCount()) return nullptr; SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(presentationScaleHint); // We may have cached a frame with a higher subsampling level, in which case we need to // re-decode with a lower level. if (index < m_frames.size() && m_frames[index].m_image && subsamplingLevel < m_frames[index].m_subsamplingLevel) { // If the image is already cached, but at too small a size, re-decode a larger version. int sizeChange = -m_frames[index].m_frameBytes; m_frames[index].clear(true); invalidatePlatformData(); m_decodedSize += sizeChange; if (imageObserver()) imageObserver()->decodedSizeChanged(this, sizeChange); } // If we haven't fetched a frame yet, do so. if (index >= m_frames.size() || !m_frames[index].m_image) cacheFrame(index, subsamplingLevel, CacheMetadataAndFrame); return m_frames[index].m_image; }
void BitmapImage::cacheFrame(size_t index) { size_t numFrames = frameCount(); ASSERT(m_decodedSize == 0 || numFrames > 1); if (m_frames.size() < numFrames) m_frames.grow(numFrames); m_frames[index].m_frame = m_source.createFrameAtIndex(index); if (numFrames == 1 && m_frames[index].m_frame) checkForSolidColor(); m_frames[index].m_haveMetadata = true; m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); if (repetitionCount(false) != cAnimationNone) m_frames[index].m_duration = m_source.frameDurationAtIndex(index); m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); int sizeChange; if (index) { IntSize frameSize = m_source.frameSizeAtIndex(index); if (frameSize != m_size) m_hasUniformFrameSize = false; sizeChange = m_frames[index].m_frame ? frameSize.width() * frameSize.height() * 4 : 0; } else sizeChange = m_frames[index].m_frame ? m_size.width() * m_size.height() * 4 : 0; if (sizeChange) { m_decodedSize += sizeChange; if (imageObserver()) imageObserver()->decodedSizeChanged(this, sizeChange); } }
void Image::drawPattern(GraphicsContext& context, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode) { context.drawPattern(*this, destRect, tileRect, patternTransform, phase, spacing, op, blendMode); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::destroyMetadataAndNotify(size_t frameBytesCleared) { m_isSolidColor = false; m_checkedForSolidColor = false; if (frameBytesCleared && imageObserver()) imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesCleared)); }
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) { FloatRect srcRect(src); FloatRect dstRect(dst); if (dstRect.width() == 0.0f || dstRect.height() == 0.0f || srcRect.width() == 0.0f || srcRect.height() == 0.0f) return; startAnimation(); cairo_surface_t* image = frameAtIndex(m_currentFrame); if (!image) // If it's too early we won't have an image yet. return; //+EAWebKitChange //5/30/2012 #if ENABLE(IMAGE_COMPRESSION) // Check if this is a compressed surface. const void* pCompressedSurfaceUserData = cairo_surface_get_user_data (image, (cairo_user_data_key_t*) ImageCompressionGetUserDataKey()); #endif //-EAWebKitChange if (mayFillWithSolidColor()) { fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op); //+EAWebKitChange //5/30/2012 #if ENABLE(IMAGE_COMPRESSION) if (pCompressedSurfaceUserData) cairo_surface_destroy(image); #endif //-EAWebKitChange return; } context->save(); // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); context->platformContext()->drawSurfaceToContext(image, dstRect, srcRect, context); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); //+EAWebKitChange //5/30/2012 #if ENABLE(IMAGE_COMPRESSION) if (pCompressedSurfaceUserData) cairo_surface_destroy(image); #endif //-EAWebKitChange }
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; // Qt interprets 0 width/height as full width/height so just short circuit. QRectF dr = QRectF(destRect).normalized(); QRect tr = QRectF(tileRect).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); }
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); }
void PDFDocumentImage::destroyDecodedData(bool) { m_cachedImageBuffer = nullptr; if (imageObserver()) imageObserver()->decodedSizeChanged(this, -safeCast<int>(m_cachedBytes)); m_cachedBytes = 0; }
void BitmapImage::destroyMetadataAndNotify(int framesCleared) { m_isSolidColor = false; invalidatePlatformData(); const int deltaBytes = framesCleared * -frameBytes(m_size); m_decodedSize += deltaBytes; if (deltaBytes && imageObserver()) imageObserver()->decodedSizeChanged(this, deltaBytes); }
void Image::drawPattern(GraphicsContext& ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode) { if (!nativeImageForCurrentFrame()) return; ctxt.drawPattern(*this, tileRect, patternTransform, phase, spacing, op, destRect, blendMode); if (imageObserver()) imageObserver()->didDraw(this); }
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator op, const FloatRect& destRect) { cairo_surface_t* image = nativeImageForCurrentFrame(); if (!image) // If it's too early we won't have an image yet. return; cairo_t* cr = context->platformContext()->cr(); drawPatternToCairoContext(cr, image, size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp) { CGImageRef image = frameAtIndex(m_currentFrame); if (!image) // If it's too early we won't have an image yet. return; if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), compositeOp); return; } CGContextRef context = ctxt->platformContext(); ctxt->save(); // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image // and then set a clip to the portion that we want to display. CGSize selfSize = size(); FloatRect adjustedDestRect = destRect; if (srcRect.width() != selfSize.width || srcRect.height() != selfSize.height) { // A subportion of the image is drawing. Adjust the destination rect to // account for this. float xScale = srcRect.width() / destRect.width(); float yScale = srcRect.height() / destRect.height(); adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale)); adjustedDestRect.setSize(FloatSize(size().width() / xScale, size().height() / yScale)); CGContextClipToRect(context, destRect); } // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly. float currHeight = CGImageGetHeight(image); if (currHeight < selfSize.height) adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height); // Flip the coords. ctxt->setCompositeOperation(compositeOp); CGContextTranslateCTM(context, adjustedDestRect.x(), adjustedDestRect.bottom()); CGContextScaleCTM(context, 1, -1); adjustedDestRect.setLocation(FloatPoint()); // Draw the image. CGContextDrawImage(context, adjustedDestRect, image); ctxt->restore(); startAnimation(); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::destroyMetadataAndNotify(int framesCleared) { m_isSolidColor = false; m_checkedForSolidColor = false; invalidatePlatformData(); int deltaBytes = framesCleared * -frameBytes(m_size); m_decodedSize += deltaBytes; if (framesCleared > 0) { deltaBytes -= m_decodedPropertiesSize; m_decodedPropertiesSize = 0; } if (deltaBytes && imageObserver()) imageObserver()->decodedSizeChanged(this, deltaBytes); }
void BitmapImage::destroyMetadataAndNotify(unsigned frameBytesCleared) { m_isSolidColor = false; m_checkedForSolidColor = false; invalidatePlatformData(); ASSERT(m_decodedSize >= frameBytesCleared); m_decodedSize -= frameBytesCleared; if (frameBytesCleared > 0) { frameBytesCleared += m_decodedPropertiesSize; m_decodedPropertiesSize = 0; } if (frameBytesCleared && imageObserver()) imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesCleared)); }