bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size) { if (multisample()) { int maxSampleCount = 0; m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); int sampleCount = std::min(4, maxSampleCount); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, m_internalRenderbufferFormat, size.width(), size.height()); if (m_context->getError() == GraphicsContext3D::OUT_OF_MEMORY) return false; m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); resizeDepthStencil(size, sampleCount); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) return false; } return true; }
void FEConvolveMatrix::apply() { if (hasResult()) return; FilterEffect* in = inputEffect(0); in->apply(); if (!in->hasResult()) return; ByteArray* resultImage; if (m_preserveAlpha) resultImage = createUnmultipliedImageResult(); else resultImage = createPremultipliedImageResult(); if (!resultImage) return; IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); RefPtr<ByteArray> srcPixelArray; if (m_preserveAlpha) srcPixelArray = in->asUnmultipliedImage(effectDrawingRect); else srcPixelArray = in->asPremultipliedImage(effectDrawingRect); IntSize paintSize = absolutePaintRect().size(); PaintingData paintingData; paintingData.srcPixelArray = srcPixelArray.get(); paintingData.dstPixelArray = resultImage; paintingData.width = paintSize.width(); paintingData.height = paintSize.height(); paintingData.bias = m_bias * 255; // Drawing fully covered pixels int clipRight = paintSize.width() - m_kernelSize.width(); int clipBottom = paintSize.height() - m_kernelSize.height(); if (clipRight >= 0 && clipBottom >= 0) { #if ENABLE(PARALLEL_JOBS) int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension; if (optimalThreadNumber > 1) { ParallelJobs<InteriorPixelParameters> parallelJobs(&WebCore::FEConvolveMatrix::setInteriorPixelsWorker, optimalThreadNumber); const int numOfThreads = parallelJobs.numberOfJobs(); const int heightPerThread = clipBottom / numOfThreads; int startY = 0; for (int job = 0; job < numOfThreads; ++job) { InteriorPixelParameters& param = parallelJobs.parameter(job); param.filter = this; param.paintingData = &paintingData; param.clipRight = clipRight; param.clipBottom = clipBottom; param.yStart = startY; if (job < numOfThreads - 1) { startY += heightPerThread; param.yEnd = startY - 1; } else param.yEnd = clipBottom; } parallelJobs.execute(); } else // Fallback to the default setInteriorPixels call. #endif setInteriorPixels(paintingData, clipRight, clipBottom, 0, clipBottom); clipRight += m_targetOffset.x() + 1; clipBottom += m_targetOffset.y() + 1; if (m_targetOffset.y() > 0) setOuterPixels(paintingData, 0, 0, paintSize.width(), m_targetOffset.y()); if (clipBottom < paintSize.height()) setOuterPixels(paintingData, 0, clipBottom, paintSize.width(), paintSize.height()); if (m_targetOffset.x() > 0) setOuterPixels(paintingData, 0, m_targetOffset.y(), m_targetOffset.x(), clipBottom); if (clipRight < paintSize.width()) setOuterPixels(paintingData, clipRight, m_targetOffset.y(), paintSize.width(), clipBottom); } else { // Rare situation, not optimizied for speed setOuterPixels(paintingData, 0, 0, paintSize.width(), paintSize.height()); } }
void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride) { const int channels[4] = { 3, 0, 1, 3 }; int lobes[3][2]; // indexed by pass, and left/right lobe calculateLobes(lobes, m_blurRadius.width(), m_shadowsIgnoreTransforms); // First pass is horizontal. int stride = 4; int delta = rowStride; int final = size.height(); int dim = size.width(); // Two stages: horizontal and vertical for (int pass = 0; pass < 2; ++pass) { unsigned char* pixels = imageData; if (!pass && !m_blurRadius.width()) final = 0; // Do no work if horizonal blur is zero. for (int j = 0; j < final; ++j, pixels += delta) { // For each step, we blur the alpha in a channel and store the result // in another channel for the subsequent step. // We use sliding window algorithm to accumulate the alpha values. // This is much more efficient than computing the sum of each pixels // covered by the box kernel size for each x. for (int step = 0; step < 3; ++step) { int side1 = lobes[step][leftLobe]; int side2 = lobes[step][rightLobe]; int pixelCount = side1 + 1 + side2; int invCount = ((1 << blurSumShift) + pixelCount - 1) / pixelCount; int ofs = 1 + side2; int alpha1 = pixels[channels[step]]; int alpha2 = pixels[(dim - 1) * stride + channels[step]]; unsigned char* ptr = pixels + channels[step + 1]; unsigned char* prev = pixels + stride + channels[step]; unsigned char* next = pixels + ofs * stride + channels[step]; int i; int sum = side1 * alpha1 + alpha1; int limit = (dim < side2 + 1) ? dim : side2 + 1; for (i = 1; i < limit; ++i, prev += stride) sum += *prev; if (limit <= side2) sum += (side2 - limit + 1) * alpha2; limit = (side1 < dim) ? side1 : dim; for (i = 0; i < limit; ptr += stride, next += stride, ++i, ++ofs) { *ptr = (sum * invCount) >> blurSumShift; sum += ((ofs < dim) ? *next : alpha2) - alpha1; } prev = pixels + channels[step]; for (; ofs < dim; ptr += stride, prev += stride, next += stride, ++i, ++ofs) { *ptr = (sum * invCount) >> blurSumShift; sum += (*next) - (*prev); } for (; i < dim; ptr += stride, prev += stride, ++i) { *ptr = (sum * invCount) >> blurSumShift; sum += alpha2 - (*prev); } } } // Last pass is vertical. stride = rowStride; delta = 4; final = size.width(); dim = size.height(); if (!m_blurRadius.height()) break; if (m_blurRadius.width() != m_blurRadius.height()) calculateLobes(lobes, m_blurRadius.height(), m_shadowsIgnoreTransforms); }
void WebMediaPlayerClientImpl::setSize(const IntSize& size) { if (m_webMediaPlayer.get()) m_webMediaPlayer->setSize(WebSize(size.width(), size.height())); }
IntSize ScrollableArea::totalContentsSize() const { IntSize totalContentsSize = contentsSize(); totalContentsSize.setHeight(totalContentsSize.height() + headerHeight() + footerHeight()); return totalContentsSize; }
void FEConvolveMatrix::setKernelSize(const IntSize& kernelSize) { ASSERT(kernelSize.width() > 0); ASSERT(kernelSize.height() > 0); m_kernelSize = kernelSize; }
bool GraphicsContext3D::reshapeFBOs(const IntSize& size) { const int width = size.width(); const int height = size.height(); GLuint colorFormat, internalDepthStencilFormat = 0; if (m_attrs.alpha) { m_internalColorFormat = GL_RGBA8; colorFormat = GL_RGBA; } else { m_internalColorFormat = GL_RGB8; colorFormat = GL_RGB; } if (m_attrs.stencil || m_attrs.depth) { // We don't allow the logic where stencil is required and depth is not. // See GraphicsContext3D::validateAttributes. Extensions3D* extensions = getExtensions(); // Use a 24 bit depth buffer where we know we have it. if (extensions->supports("GL_EXT_packed_depth_stencil")) internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; else #if PLATFORM(IOS) internalDepthStencilFormat = GL_DEPTH_COMPONENT16; #else internalDepthStencilFormat = GL_DEPTH_COMPONENT; #endif } // Resize multisample FBO. if (m_attrs.antialias) { GLint maxSampleCount; ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); GLint sampleCount = std::min(8, maxSampleCount); if (sampleCount > maxSampleCount) sampleCount = maxSampleCount; ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, m_internalColorFormat, width, height); ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height); if (m_attrs.stencil) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); if (m_attrs.depth) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); } ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { // FIXME: cleanup. notImplemented(); } } // resize regular FBO ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); ASSERT(m_texture); #if PLATFORM(IOS) ::glBindRenderbuffer(GL_RENDERBUFFER, m_texture); ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_texture); setRenderbufferStorageFromDrawable(m_currentWidth, m_currentHeight); #else ::glBindTexture(GL_TEXTURE_2D, m_texture); ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); if (m_compositorTexture) { ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); ::glBindTexture(GL_TEXTURE_2D, 0); } #endif if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); if (m_attrs.stencil) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); if (m_attrs.depth) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { // FIXME: cleanup notImplemented(); } bool mustRestoreFBO = true; if (m_attrs.antialias) { ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); if (m_state.boundFBO == m_multisampleFBO) mustRestoreFBO = false; } else { if (m_state.boundFBO == m_fbo) mustRestoreFBO = false; } return mustRestoreFBO; }
ImageData::ImageData(const IntSize& size, PassRefPtr<Uint8ClampedArray> byteArray) : m_size(size) , m_data(byteArray) { ASSERT_WITH_SECURITY_IMPLICATION(static_cast<unsigned>(size.width() * size.height() * 4) <= m_data->length()); }
DragImageRef WebDragClient::createDragImageForLink(KURL& url, const String& inLabel, Frame* frame) { // This is more or less an exact match for the Mac OS X code. const Font* labelFont; const Font* urlFont; if (frame->settings() && frame->settings()->fontRenderingMode() == AlternateRenderingMode) { static const Font alternateRenderingModeLabelFont = dragLabelFont(DRAG_LINK_LABEL_FONT_SIZE, true, AlternateRenderingMode); static const Font alternateRenderingModeURLFont = dragLabelFont(DRAG_LINK_URL_FONT_SIZE, false, AlternateRenderingMode); labelFont = &alternateRenderingModeLabelFont; urlFont = &alternateRenderingModeURLFont; } else { static const Font normalRenderingModeLabelFont = dragLabelFont(DRAG_LINK_LABEL_FONT_SIZE, true, NormalRenderingMode); static const Font normalRenderingModeURLFont = dragLabelFont(DRAG_LINK_URL_FONT_SIZE, false, NormalRenderingMode); labelFont = &normalRenderingModeLabelFont; urlFont = &normalRenderingModeURLFont; } bool drawURLString = true; bool clipURLString = false; bool clipLabelString = false; String urlString = url.string(); String label = inLabel; if (label.isEmpty()) { drawURLString = false; label = urlString; } //First step in drawing the link drag image width TextRun labelRun(label.impl()); TextRun urlRun(urlString.impl()); IntSize labelSize(labelFont->width(labelRun), labelFont->ascent() + labelFont->descent()); if (labelSize.width() > MAX_DRAG_LABEL_STRING_WIDTH){ labelSize.setWidth(MAX_DRAG_LABEL_STRING_WIDTH); clipLabelString = true; } IntSize urlStringSize; IntSize imageSize(labelSize.width() + DRAG_LABEL_BORDER_X * 2, labelSize.height() + DRAG_LABEL_BORDER_Y * 2); if (drawURLString) { urlStringSize.setWidth(urlFont->width(urlRun)); urlStringSize.setHeight(urlFont->ascent() + urlFont->descent()); imageSize.setHeight(imageSize.height() + urlStringSize.height()); if (urlStringSize.width() > MAX_DRAG_LABEL_STRING_WIDTH) { imageSize.setWidth(MAX_DRAG_LABEL_WIDTH); clipURLString = true; } else { imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + DRAG_LABEL_BORDER_X * 2); } } // We now know how big the image needs to be, so we create and // fill the background HBITMAP image = 0; HDC dc = GetDC(0); HDC workingDC = CreateCompatibleDC(dc); if (!workingDC) { ReleaseDC(0, dc); return 0; } PlatformGraphicsContext* contextRef; image = allocImage(workingDC, imageSize, &contextRef); if (!image) { DeleteDC(workingDC); ReleaseDC(0, dc); return 0; } ::SelectObject(workingDC, image); GraphicsContext context(contextRef); // On Mac alpha is {0.7, 0.7, 0.7, 0.8}, however we can't control alpha // for drag images on win, so we use 1 static const Color backgroundColor(140, 140, 140); static const IntSize radii(DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS); IntRect rect(0, 0, imageSize.width(), imageSize.height()); context.fillRoundedRect(rect, radii, radii, radii, radii, backgroundColor, DeviceColorSpace); // Draw the text static const Color topColor(0, 0, 0, 255); //original alpha = 0.75 static const Color bottomColor(255, 255, 255, 127); //original alpha = 0.5 if (drawURLString) { if (clipURLString) urlString = StringTruncator::rightTruncate(urlString, imageSize.width() - (DRAG_LABEL_BORDER_X * 2.0f), *urlFont, false); IntPoint textPos(DRAG_LABEL_BORDER_X, imageSize.height() - (DRAG_LABEL_BORDER_Y_OFFSET + urlFont->descent())); WebCoreDrawDoubledTextAtPoint(context, urlString, textPos, *urlFont, topColor, bottomColor); } if (clipLabelString) label = StringTruncator::rightTruncate(label, imageSize.width() - (DRAG_LABEL_BORDER_X * 2.0f), *labelFont, false); IntPoint textPos(DRAG_LABEL_BORDER_X, DRAG_LABEL_BORDER_Y + labelFont->pixelSize()); WebCoreDrawDoubledTextAtPoint(context, label, textPos, *labelFont, topColor, bottomColor); deallocContext(contextRef); DeleteDC(workingDC); ReleaseDC(0, dc); return image; }
static double area(WebFrame* frame) { IntSize size = frame->visibleContentBoundsExcludingScrollbars().size(); return static_cast<double>(size.height()) * size.width(); }
ImageData::ImageData(const IntSize& size) : m_size(size) , m_data(Uint8ClampedArray::create(size.width() * size.height() * 4)) { }
bool DrawingBuffer::reset(const IntSize& newSize) { if (!m_context) return false; m_context->makeContextCurrent(); int maxTextureSize = 0; m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); if (newSize.height() > maxTextureSize || newSize.width() > maxTextureSize) { clear(); return false; } int pixelDelta = newSize.width() * newSize.height(); if (!m_size.isEmpty()) pixelDelta -= m_size.width() * m_size.height(); if (s_maximumResourceUsePixels && (s_currentResourceUsePixels + pixelDelta) > s_maximumResourceUsePixels) { clear(); return false; } s_currentResourceUsePixels += pixelDelta; const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes(); if (newSize != m_size) { m_size = newSize; unsigned long internalColorFormat, colorFormat, internalRenderbufferFormat; if (attributes.alpha) { internalColorFormat = GraphicsContext3D::RGBA; colorFormat = GraphicsContext3D::RGBA; internalRenderbufferFormat = Extensions3D::RGBA8_OES; } else { internalColorFormat = GraphicsContext3D::RGB; colorFormat = GraphicsContext3D::RGB; internalRenderbufferFormat = Extensions3D::RGB8_OES; } // resize multisample FBO if (multisample()) { int maxSampleCount = 0; m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); int sampleCount = std::min(8, maxSampleCount); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); resizeDepthStencil(sampleCount); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { // Cleanup clear(); return false; } } // resize regular FBO m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); if (!multisample()) resizeDepthStencil(0); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { // Cleanup clear(); return false; } } clearFramebuffer(); return true; }
int DrawingBuffer::pixelDelta(const IntSize& size) { return (max(0, size.width()) * max(0, size.height())) - (max(0, m_size.width()) * max(0, m_size.height())); }
void DrawingBuffer::resizeDepthStencil(const IntSize& size, int sampleCount) { if (m_attributes.depth && m_attributes.stencil && m_packedDepthStencilExtensionSupported) { if (!m_depthStencilBuffer) m_depthStencilBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); if (multisample()) m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, Extensions3D::DEPTH24_STENCIL8, size.width(), size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, Extensions3D::DEPTH24_STENCIL8, size.width(), size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); } else { if (m_attributes.depth) { if (!m_depthBuffer) m_depthBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); if (multisample()) m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::DEPTH_COMPONENT16, size.width(), size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, size.width(), size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); } if (m_attributes.stencil) { if (!m_stencilBuffer) m_stencilBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); if (multisample()) m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::STENCIL_INDEX8, size.width(), size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, size.width(), size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); } } m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); }
void NativeImageSkia::drawPattern( GraphicsContext* context, const FloatRect& floatSrcRect, const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, WebBlendMode blendMode, const IntSize& repeatSpacing) const { FloatRect normSrcRect = floatSrcRect; normSrcRect.intersect(FloatRect(0, 0, bitmap().width(), bitmap().height())); if (destRect.isEmpty() || normSrcRect.isEmpty()) return; // nothing to draw SkMatrix totalMatrix = context->getTotalMatrix(); AffineTransform ctm = context->getCTM(); SkScalar ctmScaleX = ctm.xScale(); SkScalar ctmScaleY = ctm.yScale(); totalMatrix.preScale(scale.width(), scale.height()); // Figure out what size the bitmap will be in the destination. The // destination rect is the bounds of the pattern, we need to use the // matrix to see how big it will be. SkRect destRectTarget; totalMatrix.mapRect(&destRectTarget, normSrcRect); float destBitmapWidth = SkScalarToFloat(destRectTarget.width()); float destBitmapHeight = SkScalarToFloat(destRectTarget.height()); bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap()); // Compute the resampling mode. InterpolationQuality resampling; if (context->isAccelerated()) resampling = InterpolationLow; else if (isLazyDecoded) resampling = InterpolationHigh; else resampling = computeInterpolationQuality(totalMatrix, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight, isDataComplete()); resampling = limitInterpolationQuality(context, resampling); SkMatrix localMatrix; // We also need to translate it such that the origin of the pattern is the // origin of the destination rect, which is what WebKit expects. Skia uses // the coordinate system origin as the base for the pattern. If WebKit wants // a shifted image, it will shift it from there using the localMatrix. const float adjustedX = phase.x() + normSrcRect.x() * scale.width(); const float adjustedY = phase.y() + normSrcRect.y() * scale.height(); localMatrix.setTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY)); RefPtr<SkShader> shader; SkFilterQuality filterLevel = static_cast<SkFilterQuality>(resampling); // Bicubic filter is only applied to defer-decoded images, see // NativeImageSkia::draw for details. if (resampling == InterpolationHigh && !isLazyDecoded) { // Do nice resampling. filterLevel = kNone_SkFilterQuality; float scaleX = destBitmapWidth / normSrcRect.width(); float scaleY = destBitmapHeight / normSrcRect.height(); SkRect scaledSrcRect; // Since we are resizing the bitmap, we need to remove the scale // applied to the pixels in the bitmap shader. This means we need // CTM * localMatrix to have identity scale. Since we // can't modify CTM (or the rectangle will be drawn in the wrong // place), we must set localMatrix's scale to the inverse of // CTM scale. localMatrix.preScale(ctmScaleX ? 1 / ctmScaleX : 1, ctmScaleY ? 1 / ctmScaleY : 1); // The image fragment generated here is not exactly what is // requested. The scale factor used is approximated and image // fragment is slightly larger to align to integer // boundaries. SkBitmap resampled = extractScaledImageFragment(normSrcRect, scaleX, scaleY, &scaledSrcRect); if (repeatSpacing.isZero()) { shader = adoptRef(SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } else { shader = adoptRef(SkShader::CreateBitmapShader( createBitmapWithSpace(resampled, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } } else { // Because no resizing occurred, the shader transform should be // set to the pattern's transform, which just includes scale. localMatrix.preScale(scale.width(), scale.height()); // No need to resample before drawing. SkBitmap srcSubset; bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect)); if (repeatSpacing.isZero()) { shader = adoptRef(SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } else { shader = adoptRef(SkShader::CreateBitmapShader( createBitmapWithSpace(srcSubset, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } } SkPaint paint; paint.setShader(shader.get()); paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode)); paint.setColorFilter(context->colorFilter()); paint.setFilterQuality(filterLevel); context->drawRect(destRect, paint); }
void MediaPlayerPrivateAVFoundation::setNaturalSize(IntSize size) { LOG(Media, "MediaPlayerPrivateAVFoundation:setNaturalSize(%p) - size = %d x %d", this, size.width(), size.height()); IntSize oldSize = m_cachedNaturalSize; m_cachedNaturalSize = size; if (oldSize != m_cachedNaturalSize) m_player->sizeChanged(); }
void FEConvolveMatrix::applySoftware() { FilterEffect* in = inputEffect(0); Uint8ClampedArray* resultImage; if (m_preserveAlpha) resultImage = createUnmultipliedImageResult(); else resultImage = createPremultipliedImageResult(); if (!resultImage) return; IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); RefPtr<Uint8ClampedArray> srcPixelArray; if (m_preserveAlpha) srcPixelArray = in->asUnmultipliedImage(effectDrawingRect); else srcPixelArray = in->asPremultipliedImage(effectDrawingRect); IntSize paintSize = absolutePaintRect().size(); PaintingData paintingData; paintingData.srcPixelArray = srcPixelArray.get(); paintingData.dstPixelArray = resultImage; paintingData.width = paintSize.width(); paintingData.height = paintSize.height(); paintingData.bias = m_bias * 255; // Drawing fully covered pixels int clipRight = paintSize.width() - m_kernelSize.width(); int clipBottom = paintSize.height() - m_kernelSize.height(); if (clipRight >= 0 && clipBottom >= 0) { int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension; if (optimalThreadNumber > 1) { ParallelJobs<InteriorPixelParameters> parallelJobs(&FEConvolveMatrix::setInteriorPixelsWorker, optimalThreadNumber); const int numOfThreads = parallelJobs.numberOfJobs(); // Split the job into "heightPerThread" jobs but there a few jobs that need to be slightly larger since // heightPerThread * jobs < total size. These extras are handled by the remainder "jobsWithExtra". const int heightPerThread = clipBottom / numOfThreads; const int jobsWithExtra = clipBottom % numOfThreads; int startY = 0; for (int job = 0; job < numOfThreads; ++job) { InteriorPixelParameters& param = parallelJobs.parameter(job); param.filter = this; param.paintingData = &paintingData; param.clipRight = clipRight; param.clipBottom = clipBottom; param.yStart = startY; startY += job < jobsWithExtra ? heightPerThread + 1 : heightPerThread; param.yEnd = startY; } parallelJobs.execute(); } else { // Fallback to single threaded mode. setInteriorPixels(paintingData, clipRight, clipBottom, 0, clipBottom); } clipRight += m_targetOffset.x() + 1; clipBottom += m_targetOffset.y() + 1; if (m_targetOffset.y() > 0) setOuterPixels(paintingData, 0, 0, paintSize.width(), m_targetOffset.y()); if (clipBottom < paintSize.height()) setOuterPixels(paintingData, 0, clipBottom, paintSize.width(), paintSize.height()); if (m_targetOffset.x() > 0) setOuterPixels(paintingData, 0, m_targetOffset.y(), m_targetOffset.x(), clipBottom); if (clipRight < paintSize.width()) setOuterPixels(paintingData, clipRight, m_targetOffset.y(), paintSize.width(), clipBottom); } else { // Rare situation, not optimizied for speed setOuterPixels(paintingData, 0, 0, paintSize.width(), paintSize.height()); } }
void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { const PaintPhase paintPhase = paintInfo.phase; if (shouldPaintSelfBlockBackground(paintPhase)) { if (m_layoutBlock.style()->visibility() == EVisibility::Visible && m_layoutBlock.hasBoxDecorationBackground()) m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset); // We're done. We don't bother painting any children. if (paintPhase == PaintPhaseSelfBlockBackgroundOnly) return; } if (paintInfo.paintRootBackgroundOnly()) return; if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == EVisibility::Visible) { m_layoutBlock.paintMask(paintInfo, paintOffset); return; } if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibility() == EVisibility::Visible) { BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset); return; } if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting()) ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset); if (paintPhase != PaintPhaseSelfOutlineOnly) { Optional<ScopedPaintChunkProperties> m_scopedScrollProperty; Optional<ScrollRecorder> scrollRecorder; Optional<PaintInfo> scrolledPaintInfo; if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { const auto* objectProperties = m_layoutBlock.paintProperties(); if (auto* scroll = objectProperties ? objectProperties->scroll() : nullptr) { PaintChunkProperties properties(paintInfo.context.getPaintController() .currentPaintChunkProperties()); auto* scrollTranslation = objectProperties->scrollTranslation(); DCHECK(scrollTranslation); properties.transform = scrollTranslation; properties.scroll = scroll; m_scopedScrollProperty.emplace( paintInfo.context.getPaintController(), m_layoutBlock, DisplayItem::paintPhaseToDrawingType(paintPhase), properties); scrolledPaintInfo.emplace(paintInfo); scrolledPaintInfo->updateCullRect( scrollTranslation->matrix().toAffineTransform()); } } else if (m_layoutBlock.hasOverflowClip()) { IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) { scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPhase, scrollOffset); scrolledPaintInfo.emplace(paintInfo); AffineTransform transform; transform.translate(-scrollOffset.width(), -scrollOffset.height()); scrolledPaintInfo->updateCullRect(transform); } } const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintInfo : paintInfo; if (m_layoutBlock.isLayoutBlockFlow()) { BlockFlowPainter blockFlowPainter(toLayoutBlockFlow(m_layoutBlock)); blockFlowPainter.paintContents(contentsPaintInfo, paintOffset); if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) blockFlowPainter.paintFloats(contentsPaintInfo, paintOffset); } else { paintContents(contentsPaintInfo, paintOffset); } } if (shouldPaintSelfOutline(paintPhase)) ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset); // If the caret's node's layout object's containing block is this block, and // the paint action is PaintPhaseForeground, then paint the caret. if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret()) paintCarets(paintInfo, paintOffset); }
void WebChromeClient::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect& clipRect) { ASSERT(core(m_webView->topLevelFrame())); m_webView->scrollBackingStore(core(m_webView->topLevelFrame())->view(), delta.width(), delta.height(), scrollViewRect, clipRect); }
void ChromeClientEfl::contentsSizeChanged(Frame* frame, const IntSize& size) const { ewk_frame_contents_size_changed(kit(frame), size.width(), size.height()); if (ewk_view_frame_main_get(m_view) == kit(frame)) ewk_view_contents_size_changed(m_view, size.width(), size.height()); }
unsigned ImageSource::frameBytesAtIndex(size_t index) const { IntSize frameSize = frameSizeAtIndex(index, ImageOrientationDescription(RespectImageOrientation)); return frameSize.width() * frameSize.height() * 4; }
static sk_sp<SkSurface> createSkSurface(IntSize size) { return SkSurface::MakeRaster( SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType)); }
bool ScrollableArea::isPinnedInBothDirections(const IntSize& scrollDelta) const { return isPinnedHorizontallyInDirection(scrollDelta.width()) && isPinnedVerticallyInDirection(scrollDelta.height()); }
void ScrollableAreaPainter::drawPlatformResizerImage(GraphicsContext* context, IntRect resizerCornerRect) { float deviceScaleFactor = blink::deviceScaleFactor(scrollableArea().box().frame()); RefPtr<Image> resizeCornerImage; IntSize cornerResizerSize; if (deviceScaleFactor >= 2) { DEFINE_STATIC_REF(Image, resizeCornerImageHiRes, (Image::loadPlatformResource("textAreaResizeCorner@2x"))); resizeCornerImage = resizeCornerImageHiRes; cornerResizerSize = resizeCornerImage->size(); cornerResizerSize.scale(0.5f); } else { DEFINE_STATIC_REF(Image, resizeCornerImageLoRes, (Image::loadPlatformResource("textAreaResizeCorner"))); resizeCornerImage = resizeCornerImageLoRes; cornerResizerSize = resizeCornerImage->size(); } if (scrollableArea().box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) { context->save(); context->translate(resizerCornerRect.x() + cornerResizerSize.width(), resizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height()); context->scale(-1.0, 1.0); context->drawImage(resizeCornerImage.get(), IntRect(IntPoint(), cornerResizerSize)); context->restore(); return; } IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, cornerResizerSize); context->drawImage(resizeCornerImage.get(), imageRect); }
void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { Node* node = o->node(); if (!isHTMLInputElement(node)) return; HTMLInputElement* input = toHTMLInputElement(node); if (!input->isRangeControl()) return; HTMLDataListElement* dataList = input->dataList(); if (!dataList) return; double min = input->minimum(); double max = input->maximum(); ControlPart part = o->style()->appearance(); // We don't support ticks on alternate sliders like MediaVolumeSliders. if (part != SliderHorizontalPart && part != SliderVerticalPart) return; bool isHorizontal = part == SliderHorizontalPart; IntSize thumbSize; RenderObject* thumbRenderer = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderThumb())->renderer(); if (thumbRenderer) { RenderStyle* thumbStyle = thumbRenderer->style(); int thumbWidth = thumbStyle->width().intValue(); int thumbHeight = thumbStyle->height().intValue(); thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight); thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth); } IntSize tickSize = sliderTickSize(); float zoomFactor = o->style()->effectiveZoom(); FloatRect tickRect; int tickRegionSideMargin = 0; int tickRegionWidth = 0; IntRect trackBounds; RenderObject* trackRenderer = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderTrack())->renderer(); // We can ignoring transforms because transform is handled by the graphics context. if (trackRenderer) trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms(); IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms(); // Make position relative to the transformed ancestor element. trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x()); trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y()); if (isHorizontal) { tickRect.setWidth(floor(tickSize.width() * zoomFactor)); tickRect.setHeight(floor(tickSize.height() * zoomFactor)); tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; tickRegionWidth = trackBounds.width() - thumbSize.width(); } else { tickRect.setWidth(floor(tickSize.height() * zoomFactor)); tickRect.setHeight(floor(tickSize.width() * zoomFactor)); tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; tickRegionWidth = trackBounds.height() - thumbSize.width(); } RefPtrWillBeRawPtr<HTMLCollection> options = dataList->options(); GraphicsContextStateSaver stateSaver(*paintInfo.context); paintInfo.context->setFillColor(o->resolveColor(CSSPropertyColor)); for (unsigned i = 0; Element* element = options->item(i); i++) { ASSERT(isHTMLOptionElement(*element)); HTMLOptionElement& optionElement = toHTMLOptionElement(*element); String value = optionElement.value(); if (!input->isValidValue(value)) continue; double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value)); double tickFraction = (parsedValue - min) / (max - min); double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction; double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio); if (isHorizontal) tickRect.setX(tickPosition); else tickRect.setY(tickPosition); paintInfo.context->fillRect(tickRect); } }
void LayerTextureSubImage::uploadWithTexSubImage(const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset, GC3Denum format, WebGraphicsContext3D* context) { TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithTexSubImage"); // Offset from image-rect to source-rect. IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); const uint8_t* pixelSource; if (imageRect.width() == sourceRect.width() && !offset.x()) pixelSource = &image[4 * offset.y() * imageRect.width()]; else { size_t neededSize = 4 * sourceRect.width() * sourceRect.height(); if (m_subImageSize < neededSize) { m_subImage = adoptArrayPtr(new uint8_t[neededSize]); m_subImageSize = neededSize; } // Strides not equal, so do a row-by-row memcpy from the // paint results into a temp buffer for uploading. for (int row = 0; row < sourceRect.height(); ++row) memcpy(&m_subImage[sourceRect.width() * 4 * row], &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], sourceRect.width() * 4); pixelSource = &m_subImage[0]; } GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, pixelSource)); }
bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) { if (!m_image) return false; // We need this to stay in scope because the native image is just a shallow copy of the data. m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied); if (!m_decoder) return false; ImageSource& decoder = *m_decoder; m_alphaOp = AlphaDoNothing; if (m_image->data()) { decoder.setData(m_image->data(), true); if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) return false; m_imageSurface = decoder.createFrameAtIndex(0); } else { m_imageSurface = m_image->nativeImageForCurrentFrame(); // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel, // which is true at present and may be changed in the future and needs adjustment accordingly. // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port, // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false. if (!premultiplyAlpha && m_imageHtmlDomSource != HtmlDomVideo) m_alphaOp = AlphaDoUnmultiply; // if m_imageSurface is not an image, extract a copy of the surface if (m_imageSurface && cairo_surface_get_type(m_imageSurface.get()) != CAIRO_SURFACE_TYPE_IMAGE) { RefPtr<cairo_surface_t> tmpSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_imageWidth, m_imageHeight)); copyRectFromOneSurfaceToAnother(m_imageSurface.get(), tmpSurface.get(), IntSize(), IntRect(0, 0, m_imageWidth, m_imageHeight), IntSize(), CAIRO_OPERATOR_SOURCE); m_imageSurface = tmpSurface.release(); } } if (!m_imageSurface) return false; ASSERT(cairo_surface_get_type(m_imageSurface.get()) == CAIRO_SURFACE_TYPE_IMAGE); IntSize imageSize = cairoSurfaceSize(m_imageSurface.get()); m_imageWidth = imageSize.width(); m_imageHeight = imageSize.height(); if (!m_imageWidth || !m_imageHeight) return false; if (cairo_image_surface_get_format(m_imageSurface.get()) != CAIRO_FORMAT_ARGB32) return false; unsigned int srcUnpackAlignment = 1; size_t bytesPerRow = cairo_image_surface_get_stride(m_imageSurface.get()); size_t bitsPerPixel = 32; unsigned padding = bytesPerRow - bitsPerPixel / 8 * m_imageWidth; if (padding) { srcUnpackAlignment = padding + 1; while (bytesPerRow % srcUnpackAlignment) ++srcUnpackAlignment; } m_imagePixelData = cairo_image_surface_get_data(m_imageSurface.get()); m_imageSourceFormat = DataFormatBGRA8; m_imageSourceUnpackAlignment = srcUnpackAlignment; return true; }
void LayerTextureSubImage::uploadWithMapTexSubImage(const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset, GC3Denum format, WebGraphicsContext3D* context) { TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithMapTexSubImage"); // Offset from image-rect to source-rect. IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); // Upload tile data via a mapped transfer buffer uint8_t* pixelDest = static_cast<uint8_t*>(context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY)); if (!pixelDest) { uploadWithTexSubImage(image, imageRect, sourceRect, destOffset, format, context); return; } unsigned int componentsPerPixel = 0; switch (format) { case GraphicsContext3D::RGBA: case Extensions3D::BGRA_EXT: componentsPerPixel = 4; break; case GraphicsContext3D::LUMINANCE: componentsPerPixel = 1; break; default: ASSERT_NOT_REACHED(); } unsigned int bytesPerComponent = 1; if (imageRect.width() == sourceRect.width() && !offset.x()) memcpy(pixelDest, &image[offset.y() * imageRect.width() * componentsPerPixel * bytesPerComponent], imageRect.width() * sourceRect.height() * componentsPerPixel * bytesPerComponent); else { // Strides not equal, so do a row-by-row memcpy from the // paint results into the pixelDest for (int row = 0; row < sourceRect.height(); ++row) memcpy(&pixelDest[sourceRect.width() * row * componentsPerPixel * bytesPerComponent], &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], sourceRect.width() * componentsPerPixel * bytesPerComponent); } GLC(context, context->unmapTexSubImage2DCHROMIUM(pixelDest)); }
bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size) { ASSERT(bmp); BITMAP bmpInfo; GetObject(bmp, sizeof(BITMAP), &bmpInfo); // If this is a 32bpp bitmap, which it always should be, we'll clear it so alpha-wise it will be visible if (bmpInfo.bmBitsPixel == 32) { int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight; memset(bmpInfo.bmBits, 255, bufferSize); } cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)bmpInfo.bmBits, CAIRO_FORMAT_ARGB32, bmpInfo.bmWidth, bmpInfo.bmHeight, bmpInfo.bmWidthBytes); cairo_t* targetRef = cairo_create(image); cairo_surface_destroy(image); GraphicsContext gc(targetRef); IntSize imageSize = BitmapImage::size(); if (size) drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), ColorSpaceDeviceRGB, CompositeCopy); else draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), ColorSpaceDeviceRGB, CompositeCopy); // Do cleanup cairo_destroy(targetRef); return true; }
bool DrawingBuffer::resizeFramebuffer(const IntSize& size) { // resize regular FBO m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContext3D::UNSIGNED_BYTE); if (m_lastColorBuffer) m_lastColorBuffer->size = m_size; m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); if (!multisample()) resizeDepthStencil(size, 0); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) return false; return true; }