void GradientGeneratedImage::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const FloatSize& scale,
    const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, WebBlendMode blendMode, const IntSize& repeatSpacing)
{
    float stepX = srcRect.width() + repeatSpacing.width();
    float stepY = srcRect.height() + repeatSpacing.height();
    int firstColumn = static_cast<int>(floorf((((destRect.x() - phase.x()) / scale.width()) - srcRect.x()) / srcRect.width()));
    int firstRow = static_cast<int>(floorf((((destRect.y() - phase.y()) / scale.height())  - srcRect.y()) / srcRect.height()));
    for (int i = firstColumn; ; ++i) {
        float dstX = (srcRect.x() + i * stepX) * scale.width() + phase.x();
        // assert that first column encroaches left edge of dstRect.
        ASSERT(i > firstColumn || dstX <= destRect.x());
        ASSERT(i == firstColumn || dstX > destRect.x());

        if (dstX >= destRect.maxX())
            break;
        float dstMaxX = dstX + srcRect.width() * scale.width();
        if (dstX < destRect.x())
            dstX = destRect.x();
        if (dstMaxX > destRect.maxX())
            dstMaxX = destRect.maxX();
        if (dstX >= dstMaxX)
            continue;

        FloatRect visibleSrcRect;
        FloatRect tileDstRect;
        tileDstRect.setX(dstX);
        tileDstRect.setWidth(dstMaxX - dstX);
        visibleSrcRect.setX((tileDstRect.x() - phase.x()) / scale.width() - i * stepX);
        visibleSrcRect.setWidth(tileDstRect.width() / scale.width());

        for (int j = firstRow; ; j++) {
            float dstY = (srcRect.y() + j * stepY) * scale.height() + phase.y();
            // assert that first row encroaches top edge of dstRect.
            ASSERT(j > firstRow || dstY <= destRect.y());
            ASSERT(j == firstRow || dstY > destRect.y());

            if (dstY >= destRect.maxY())
                break;
            float dstMaxY = dstY + srcRect.height() * scale.height();
            if (dstY < destRect.y())
                dstY = destRect.y();
            if (dstMaxY > destRect.maxY())
                dstMaxY = destRect.maxY();
            if (dstY >= dstMaxY)
                continue;

            tileDstRect.setY(dstY);
            tileDstRect.setHeight(dstMaxY - dstY);
            visibleSrcRect.setY((tileDstRect.y() - phase.y()) / scale.height() - j * stepY);
            visibleSrcRect.setHeight(tileDstRect.height() / scale.height());
            draw(destContext, tileDstRect, visibleSrcRect, compositeOp, blendMode);
        }
    }
}
void RenderSVGResourceMasker::drawMaskForRenderer(RenderElement& renderer, const BackgroundImageGeometry& geometry, GraphicsContext* context, CompositeOperator compositeOp)
{
    if (context->paintingDisabled())
        return;

    if (!applySVGMask(renderer, context, false))
        return;

    MaskerData* maskerData = maskerDataForRenderer(renderer);
    ASSERT(maskerData);

    FloatRect oneTileRect;
    FloatSize actualTileSize(geometry.tileSize().width() + geometry.spaceSize().width(), geometry.tileSize().height() + geometry.spaceSize().height());
    oneTileRect.setX(geometry.destRect().x() + fmodf(fmodf(-geometry.phase().width(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width()));
    oneTileRect.setY(geometry.destRect().y() + fmodf(fmodf(-geometry.phase().height(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height()));
    oneTileRect.setSize(geometry.tileSize());
    
    FloatSize intrinsicTileSize = maskerData->maskImage->logicalSize();
    FloatSize scale(geometry.tileSize().width() / intrinsicTileSize.width(), geometry.tileSize().height() / intrinsicTileSize.height());
    
    FloatRect visibleSrcRect;
    visibleSrcRect.setX((geometry.destRect().x() - oneTileRect.x()) / scale.width());
    visibleSrcRect.setY((geometry.destRect().y() - oneTileRect.y()) / scale.height());
    visibleSrcRect.setWidth(geometry.destRect().width() / scale.width());
    visibleSrcRect.setHeight(geometry.destRect().height() / scale.height());
    context->drawImageBuffer(maskerData->maskImage.get(), ColorSpaceDeviceRGB, geometry.destRect(), visibleSrcRect, compositeOp);
}
Example #3
0
Vector<FloatQuad> RenderTextLineBoxes::absoluteQuadsForRange(const RenderText& renderer, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const
{
    Vector<FloatQuad> quads;
    for (auto box = m_first; box; box = box->nextTextBox()) {
        // Note: box->end() returns the index of the last character, not the index past it
        if (start <= box->start() && box->end() < end) {
            FloatRect boundaries = box->calculateBoundaries();
            if (useSelectionHeight) {
                LayoutRect selectionRect = box->localSelectionRect(start, end);
                if (box->isHorizontal()) {
                    boundaries.setHeight(selectionRect.height());
                    boundaries.setY(selectionRect.y());
                } else {
                    boundaries.setWidth(selectionRect.width());
                    boundaries.setX(selectionRect.x());
                }
            }
            quads.append(renderer.localToAbsoluteQuad(boundaries, 0, wasFixed));
            continue;
        }
        FloatRect rect = localQuadForTextBox(*box, start, end, useSelectionHeight);
        if (!rect.isZero())
            quads.append(renderer.localToAbsoluteQuad(rect, 0, wasFixed));
    }
    return quads;
}
Example #4
0
Vector<IntRect> RenderTextLineBoxes::absoluteRectsForRange(const RenderText& renderer, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const
{
    Vector<IntRect> rects;
    for (auto box = m_first; box; box = box->nextTextBox()) {
        // Note: box->end() returns the index of the last character, not the index past it
        if (start <= box->start() && box->end() < end) {
            FloatRect boundaries = box->calculateBoundaries();
            if (useSelectionHeight) {
                LayoutRect selectionRect = box->localSelectionRect(start, end);
                if (box->isHorizontal()) {
                    boundaries.setHeight(selectionRect.height());
                    boundaries.setY(selectionRect.y());
                } else {
                    boundaries.setWidth(selectionRect.width());
                    boundaries.setX(selectionRect.x());
                }
            }
            rects.append(renderer.localToAbsoluteQuad(boundaries, 0, wasFixed).enclosingBoundingBox());
            continue;
        }
        // FIXME: This code is wrong. It's converting local to absolute twice. http://webkit.org/b/65722
        FloatRect rect = localQuadForTextBox(*box, start, end, useSelectionHeight);
        if (!rect.isZero())
            rects.append(renderer.localToAbsoluteQuad(rect, 0, wasFixed).enclosingBoundingBox());
    }
    return rects;
}
Example #5
0
FloatRect FilterEffect::getSourceRect(const FloatRect& destRect, const FloatRect& destClipRect)
{
    FloatRect sourceRect = mapRect(destRect, false);
    FloatRect sourceClipRect = mapRect(destClipRect, false);

    FloatRect boundaries = filter()->mapLocalRectToAbsoluteRect(effectBoundaries());
    if (hasX())
        sourceClipRect.setX(boundaries.x());
    if (hasY())
        sourceClipRect.setY(boundaries.y());
    if (hasWidth())
        sourceClipRect.setWidth(boundaries.width());
    if (hasHeight())
        sourceClipRect.setHeight(boundaries.height());

    FloatRect result;
    if (m_inputEffects.size() > 0) {
        result = m_inputEffects.at(0)->getSourceRect(sourceRect, sourceClipRect);
        for (unsigned i = 1; i < m_inputEffects.size(); ++i)
            result.unite(m_inputEffects.at(i)->getSourceRect(sourceRect, sourceClipRect));
    } else {
        result = sourceRect;
        result.intersect(sourceClipRect);
    }
    return result;
}
Example #6
0
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, SkXfermode::Mode op, const IntSize& repeatSpacing)
{
    FloatSize intrinsicTileSize = size();
    if (hasRelativeWidth())
        intrinsicTileSize.setWidth(scaledTileSize.width());
    if (hasRelativeHeight())
        intrinsicTileSize.setHeight(scaledTileSize.height());

    FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
                    scaledTileSize.height() / intrinsicTileSize.height());

    FloatSize actualTileSize(scaledTileSize.width() + repeatSpacing.width(), scaledTileSize.height() + repeatSpacing.height());
    FloatRect oneTileRect;
    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width()));
    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height()));
    oneTileRect.setSize(scaledTileSize);

    // Check and see if a single draw of the image can cover the entire area we are supposed to tile.
    if (oneTileRect.contains(destRect)) {
        FloatRect visibleSrcRect;
        visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
        visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
        visibleSrcRect.setWidth(destRect.width() / scale.width());
        visibleSrcRect.setHeight(destRect.height() / scale.height());
        ctxt->drawImage(this, destRect, visibleSrcRect, op, DoNotRespectImageOrientation);
        return;
    }

    FloatRect tileRect(FloatPoint(), intrinsicTileSize);
    drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, repeatSpacing);

    startAnimation();
}
Example #7
0
SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) const
{
    FloatRect rect = filter()->filterRegion();
    uint32_t flags = 0;
    FloatRect boundaries = effectBoundaries();
    boundaries.move(cropOffset);
    if (hasX()) {
        rect.setX(boundaries.x());
        flags |= SkImageFilter::CropRect::kHasLeft_CropEdge;
        flags |= SkImageFilter::CropRect::kHasRight_CropEdge;
    }
    if (hasY()) {
        rect.setY(boundaries.y());
        flags |= SkImageFilter::CropRect::kHasTop_CropEdge;
        flags |= SkImageFilter::CropRect::kHasBottom_CropEdge;
    }
    if (hasWidth()) {
        rect.setWidth(boundaries.width());
        flags |= SkImageFilter::CropRect::kHasRight_CropEdge;
    }
    if (hasHeight()) {
        rect.setHeight(boundaries.height());
        flags |= SkImageFilter::CropRect::kHasBottom_CropEdge;
    }
    rect.scale(filter()->absoluteTransform().a(), filter()->absoluteTransform().d());
    return SkImageFilter::CropRect(rect, flags);
}
void PlatformCALayerWinInternal::setNeedsDisplayInRect(const FloatRect& dirtyRect)
{
    if (!owner())
        return;

    ASSERT(owner()->layerType() != PlatformCALayer::LayerTypeTiledBackingLayer);

    if (owner()->owner()) {
        if (owner()->owner()->platformCALayerShowRepaintCounter(owner())) {
            FloatRect layerBounds = owner()->bounds();
            FloatRect repaintCounterRect = layerBounds;

            // We assume a maximum of 4 digits and a font size of 18.
            repaintCounterRect.setWidth(80);
            repaintCounterRect.setHeight(22);
            if (owner()->owner()->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown)
                repaintCounterRect.setY(layerBounds.height() - (layerBounds.y() + repaintCounterRect.height()));
            internalSetNeedsDisplay(&repaintCounterRect);
        }
        if (owner()->owner()->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
            FloatRect flippedDirtyRect = dirtyRect;
            flippedDirtyRect.setY(owner()->bounds().height() - (flippedDirtyRect.y() + flippedDirtyRect.height()));
            internalSetNeedsDisplay(&flippedDirtyRect);
            return;
        }
    }

    internalSetNeedsDisplay(&dirtyRect);

    owner()->setNeedsCommit();
}
Example #9
0
SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) const
{
    FloatRect rect;
    uint32_t flags = 0;
    if (!hasConnectedInput() && !filter()->filterRegion().isEmpty()) {
        rect = filter()->filterRegion();
        flags = SkImageFilter::CropRect::kHasAll_CropEdge;
    }
    FloatRect boundaries = effectBoundaries();
    boundaries.move(cropOffset);
    if (hasX()) {
        rect.setX(boundaries.x());
        flags |= SkImageFilter::CropRect::kHasLeft_CropEdge;
    }
    if (hasY()) {
        rect.setY(boundaries.y());
        flags |= SkImageFilter::CropRect::kHasTop_CropEdge;
    }
    if (hasWidth()) {
        rect.setWidth(boundaries.width());
        flags |= SkImageFilter::CropRect::kHasWidth_CropEdge;
    }
    if (hasHeight()) {
        rect.setHeight(boundaries.height());
        flags |= SkImageFilter::CropRect::kHasHeight_CropEdge;
    }
    rect.scale(filter()->scale());
    return SkImageFilter::CropRect(rect, flags);
}
Example #10
0
void SVGFilter::calculateEffectSubRegion(FilterEffect* effect)
{
    FloatRect subRegionBBox = effect->effectBoundaries();
    FloatRect useBBox = effect->unionOfChildEffectSubregions();
    FloatRect newSubRegion = subRegionBBox;

    if (m_effectBBoxMode) {
        newSubRegion = useBBox;

        if (effect->hasX())
            newSubRegion.setX(m_itemBox.x() + subRegionBBox.x() * m_itemBox.width());

        if (effect->hasY())
            newSubRegion.setY(m_itemBox.y() + subRegionBBox.y() * m_itemBox.height());

        if (effect->hasWidth())
            newSubRegion.setWidth(subRegionBBox.width() * m_itemBox.width());

        if (effect->hasHeight())
            newSubRegion.setHeight(subRegionBBox.height() * m_itemBox.height());
    } else {
        if (!effect->hasX())
            newSubRegion.setX(useBBox.x());

        if (!effect->hasY())
            newSubRegion.setY(useBBox.y());

        if (!effect->hasWidth())
            newSubRegion.setWidth(useBBox.width());

        if (!effect->hasHeight())
            newSubRegion.setHeight(useBBox.height());
    }

    // clip every filter effect to the filter region
    newSubRegion.intersect(m_filterRect);

    effect->setSubRegion(newSubRegion);
    newSubRegion.scale(filterResolution().width(), filterResolution().height());
    effect->setScaledSubRegion(newSubRegion);
    m_maxImageSize = m_maxImageSize.expandedTo(newSubRegion.size()); 
}
Example #11
0
static void heightAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.SVGRect.height._set");
    V8SVGPODTypeWrapper<FloatRect>* wrapper = V8SVGPODTypeWrapper<FloatRect>::toNative(info.Holder());
    FloatRect impInstance = *wrapper;
    FloatRect* imp = &impInstance;
    float v = static_cast<float>(value->NumberValue());
    imp->setHeight(v);
    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));
    return;
}
Example #12
0
void ShadowList::adjustRectForShadow(FloatRect& rect) const {
  float shadowLeft = 0;
  float shadowRight = 0;
  float shadowTop = 0;
  float shadowBottom = 0;
  calculateShadowExtent(this, shadowLeft, shadowRight, shadowTop, shadowBottom);

  rect.move(shadowLeft, shadowTop);
  rect.setWidth(rect.width() - shadowLeft + shadowRight);
  rect.setHeight(rect.height() - shadowTop + shadowBottom);
}
static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const IntRect& contentsRect)
{
    if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
        rect.setX(contentsRect.x());
        rect.setWidth(contentsRect.width());
    }

    if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
        rect.setY(contentsRect.y());
        rect.setHeight(contentsRect.height());
    }
}
Example #14
0
FloatRect SVGImageBufferTools::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
{
    FloatRect clampedAbsoluteTargetRect = absoluteTargetRect;

    if (clampedAbsoluteTargetRect.width() > kMaxImageBufferSize)
        clampedAbsoluteTargetRect.setWidth(kMaxImageBufferSize);

    if (clampedAbsoluteTargetRect.height() > kMaxImageBufferSize)
        clampedAbsoluteTargetRect.setHeight(kMaxImageBufferSize);

    return clampedAbsoluteTargetRect;
}
Example #15
0
void ShadowData::adjustRectForShadow(FloatRect& rect, int additionalOutlineSize) const
{
    int shadowLeft = 0;
    int shadowRight = 0;
    int shadowTop = 0;
    int shadowBottom = 0;
    calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);

    rect.move(shadowLeft, shadowTop);
    rect.setWidth(rect.width() - shadowLeft + shadowRight);
    rect.setHeight(rect.height() - shadowTop + shadowBottom);
}
Example #16
0
FloatRect Image::adjustForNegativeSize(const FloatRect& rect)
{
    FloatRect norm = rect;
    if (norm.width() < 0) {
        norm.setX(norm.x() + norm.width());
        norm.setWidth(-norm.width());
    }
    if (norm.height() < 0) {
        norm.setY(norm.y() + norm.height());
        norm.setHeight(-norm.height());
    }
    return norm;
}
Example #17
0
// A helper method for translating negative width and height values.
FloatRect normalizeRect(const FloatRect& rect)
{
    FloatRect norm = rect;
    if (norm.width() < 0) {
        norm.setX(norm.x() + norm.width());
        norm.setWidth(-norm.width());
    }
    if (norm.height() < 0) {
        norm.setY(norm.y() + norm.height());
        norm.setHeight(-norm.height());
    }
    return norm;
}
Example #18
0
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);
}
Example #19
0
static FloatRect getRect(FilterEffect* effect)
{
    FloatRect result = effect->filter()->filterRegion();
    FloatRect boundaries = effect->effectBoundaries();
    if (effect->hasX())
        result.setX(boundaries.x());
    if (effect->hasY())
        result.setY(boundaries.y());
    if (effect->hasWidth())
        result.setWidth(boundaries.width());
    if (effect->hasHeight())
        result.setHeight(boundaries.height());
    return result;
}
// 3/13/09 CSidhall - Added to get easy access to the current clip rectangle in screen space
FloatRect GraphicsContext::getClip() const
{
     FloatRect rect;

    // Note: seems m_data might be decrepated eventually
    if((m_data) && (m_data->surface))
    {
        rect.setX( (float) m_data->surface->GetClipRect().x);
        rect.setY((float) m_data->surface->GetClipRect().y);
        rect.setWidth(m_data->surface->GetClipRect().width());
        rect.setHeight(m_data->surface->GetClipRect().height());
    }
    return rect;
}
FloatRect FloatRect::normalized() const
{
    FloatRect normalizedRect = *this;

    if (width() < 0) {
        normalizedRect.setX(x() + width());
        normalizedRect.setWidth(-width());
    }
    if (height() < 0) {
        normalizedRect.setY(y() + height());
        normalizedRect.setHeight(-height());
    }
    return normalizedRect;
}
Example #22
0
FloatRect Image::computeSubsetForTile(const FloatRect& tile,
                                      const FloatRect& dest,
                                      const FloatSize& imageSize) {
  DCHECK(tile.contains(dest));

  const FloatSize scale(tile.width() / imageSize.width(),
                        tile.height() / imageSize.height());

  FloatRect subset = dest;
  subset.setX((dest.x() - tile.x()) / scale.width());
  subset.setY((dest.y() - tile.y()) / scale.height());
  subset.setWidth(dest.width() / scale.width());
  subset.setHeight(dest.height() / scale.height());

  return subset;
}
Example #23
0
FloatRect FilterEffect::determineFilterPrimitiveSubregion(DetermineSubregionFlags flags)
{
    Filter* filter = this->filter();
    ASSERT(filter);

    // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
    FloatRect subregion;
    if (unsigned numberOfInputEffects = inputEffects().size()) {
        subregion = inputEffect(0)->determineFilterPrimitiveSubregion(flags);
        for (unsigned i = 1; i < numberOfInputEffects; ++i)
            subregion.unite(inputEffect(i)->determineFilterPrimitiveSubregion(flags));
    } else {
        subregion = filter->filterRegion();
    }

    // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
    if (filterEffectType() == FilterEffectTypeTile)
        subregion = filter->filterRegion();

    if (flags & MapRectForward) {
        // mapRect works on absolute rectangles.
        subregion = filter->mapAbsoluteRectToLocalRect(mapRect(
            filter->mapLocalRectToAbsoluteRect(subregion)));
    }

    FloatRect boundaries = effectBoundaries();
    if (hasX())
        subregion.setX(boundaries.x());
    if (hasY())
        subregion.setY(boundaries.y());
    if (hasWidth())
        subregion.setWidth(boundaries.width());
    if (hasHeight())
        subregion.setHeight(boundaries.height());

    setFilterPrimitiveSubregion(subregion);

    FloatRect absoluteSubregion = filter->mapLocalRectToAbsoluteRect(subregion);

    // Clip every filter effect to the filter region.
    if (flags & ClipToFilterRegion) {
        absoluteSubregion.intersect(filter->absoluteFilterRegion());
    }

    setMaxEffectRect(absoluteSubregion);
    return subregion;
}
PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(RenderObject* object,
                                                                  const PatternAttributes& attributes,
                                                                  const FloatRect& tileBoundaries,
                                                                  const FloatRect& absoluteTileBoundaries,
                                                                  const AffineTransform& tileImageTransform) const
{
    ASSERT(object);

    // Clamp tile image size against SVG viewport size, as last resort, to avoid allocating huge image buffers.
    FloatRect contentBoxRect = SVGRenderSupport::findTreeRootObject(object)->contentBoxRect();

    FloatRect clampedAbsoluteTileBoundaries = absoluteTileBoundaries;
    if (clampedAbsoluteTileBoundaries.width() > contentBoxRect.width())
        clampedAbsoluteTileBoundaries.setWidth(contentBoxRect.width());

    if (clampedAbsoluteTileBoundaries.height() > contentBoxRect.height())
        clampedAbsoluteTileBoundaries.setHeight(contentBoxRect.height());

    OwnPtr<ImageBuffer> tileImage;

    if (!SVGImageBufferTools::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB))
        return PassOwnPtr<ImageBuffer>();

    GraphicsContext* tileImageContext = tileImage->context();
    ASSERT(tileImageContext);

    // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation).
    tileImageContext->scale(FloatSize(absoluteTileBoundaries.width() / tileBoundaries.width(),
                                      absoluteTileBoundaries.height() / tileBoundaries.height()));

    // Apply tile image transformations.
    if (!tileImageTransform.isIdentity())
        tileImageContext->concatCTM(tileImageTransform);

    AffineTransform contentTransformation;
    if (attributes.boundingBoxModeContent())
        contentTransformation = tileImageTransform;

    // Draw the content into the ImageBuffer.
    for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) {
        if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !node->renderer())
            continue;
        SVGImageBufferTools::renderSubtreeToImageBuffer(tileImage.get(), node->renderer(), contentTransformation);
    }

    return tileImage.release();
}
Example #25
0
void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& dstRect, const FloatRect& srcRect,
                       CompositeOperator op, bool useLowQualityScale)
{
    if (m_data.m_tiledImage && context != m_context.get()) {
        FloatRect src = srcRect;
        if (src.width() == -1)
            src.setWidth(m_data.m_tiledImage->size().width());
        if (src.height() == -1)
            src.setHeight(m_data.m_tiledImage->size().height());

        ASSERT(context->platformContext()->activePainter());
        context->platformContext()->activePainter()->drawImage(m_data.m_tiledImage.get(), dstRect, src);
        return;
    }

    RefPtr<Image> imageCopy = copyImage();
    context->drawImage(imageCopy.get(), styleColorSpace, dstRect, srcRect, op, useLowQualityScale);
}
Example #26
0
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
{
    FloatRect result;

    wxCoord x = (wxCoord)frect.x();
    wxCoord y = (wxCoord)frect.y();

    x = m_data->context->LogicalToDeviceX(x);
    y = m_data->context->LogicalToDeviceY(y);
    result.setX((float)x);
    result.setY((float)y);
    x = (wxCoord)frect.width();
    y = (wxCoord)frect.height();
    x = m_data->context->LogicalToDeviceXRel(x);
    y = m_data->context->LogicalToDeviceYRel(y);
    result.setWidth((float)x);
    result.setHeight((float)y);
    return result; 
}
Example #27
0
Vector<FloatQuad> RenderTextLineBoxes::absoluteQuads(const RenderText& renderer, bool* wasFixed, ClippingOption option) const
{
    Vector<FloatQuad> quads;
    for (auto box = m_first; box; box = box->nextTextBox()) {
        FloatRect boundaries = box->calculateBoundaries();

        // Shorten the width of this text box if it ends in an ellipsis.
        // FIXME: ellipsisRectForBox should switch to return FloatRect soon with the subpixellayout branch.
        IntRect ellipsisRect = (option == ClipToEllipsis) ? ellipsisRectForBox(*box, 0, renderer.textLength()) : IntRect();
        if (!ellipsisRect.isEmpty()) {
            if (renderer.style().isHorizontalWritingMode())
                boundaries.setWidth(ellipsisRect.maxX() - boundaries.x());
            else
                boundaries.setHeight(ellipsisRect.maxY() - boundaries.y());
        }
        quads.append(renderer.localToAbsoluteQuad(boundaries, 0, wasFixed));
    }
    return quads;
}
Example #28
0
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, ColorSpace styleColorSpace, CompositeOperator op)
{    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, op);
        return;
    }

    // See <https://webkit.org/b/59043>.
#if !PLATFORM(WX)
    ASSERT(!isBitmapImage() || notSolidColor());
#endif

    FloatSize intrinsicTileSize = size();
    if (hasRelativeWidth())
        intrinsicTileSize.setWidth(scaledTileSize.width());
    if (hasRelativeHeight())
        intrinsicTileSize.setHeight(scaledTileSize.height());

    FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
                    scaledTileSize.height() / intrinsicTileSize.height());

    FloatRect oneTileRect;
    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height()));
    oneTileRect.setSize(scaledTileSize);
    
    // Check and see if a single draw of the image can cover the entire area we are supposed to tile.    
    if (oneTileRect.contains(destRect)) {
        FloatRect visibleSrcRect;
        visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
        visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
        visibleSrcRect.setWidth(destRect.width() / scale.width());
        visibleSrcRect.setHeight(destRect.height() / scale.height());
        draw(ctxt, destRect, visibleSrcRect, styleColorSpace, op);
        return;
    }

    AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height());
    FloatRect tileRect(FloatPoint(), intrinsicTileSize);    
    drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect);
    
    startAnimation();
}
Example #29
0
void TileCoverageMap::update()
{
    FloatRect containerBounds = m_controller.bounds();
    FloatRect visibleRect = m_controller.visibleRect();
    visibleRect.contract(4, 4); // Layer is positioned 2px from top and left edges.
    visibleRect.setHeight(visibleRect.height() - m_controller.topContentInset());

    float widthScale = 1;
    float scale = 1;
    if (!containerBounds.isEmpty()) {
        widthScale = std::min<float>(visibleRect.width() / containerBounds.width(), 0.1);
        scale = std::min(widthScale, visibleRect.height() / containerBounds.height());
    }

    float indicatorScale = scale * m_controller.tileGrid().scale();
    FloatRect mapBounds = containerBounds;
    mapBounds.scale(indicatorScale, indicatorScale);

    m_layer.get().setPosition(m_position + FloatPoint(2, 2));
    m_layer.get().setBounds(mapBounds);
    m_layer.get().setNeedsDisplay();

    visibleRect.scale(indicatorScale, indicatorScale);
    visibleRect.expand(2, 2);
    m_visibleRectIndicatorLayer->setPosition(visibleRect.location());
    m_visibleRectIndicatorLayer->setBounds(FloatRect(FloatPoint(), visibleRect.size()));

    Color visibleRectIndicatorColor;
    switch (m_controller.indicatorMode()) {
    case SynchronousScrollingBecauseOfStyleIndication:
        visibleRectIndicatorColor = Color(255, 0, 0);
        break;
    case SynchronousScrollingBecauseOfEventHandlersIndication:
        visibleRectIndicatorColor = Color(255, 255, 0);
        break;
    case AsyncScrollingIndication:
        visibleRectIndicatorColor = Color(0, 200, 0);
        break;
    }

    m_visibleRectIndicatorLayer.get().setBorderColor(visibleRectIndicatorColor);
}
Example #30
0
FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect)
{
    SVGFilter* filter = static_cast<SVGFilter*>(effect->filter());
    ASSERT(filter);

    // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
    FloatRect subregion;
    if (unsigned numberOfInputEffects = effect->inputEffects().size()) {
        subregion = determineFilterPrimitiveSubregion(effect->inputEffect(0));
        for (unsigned i = 1; i < numberOfInputEffects; ++i)
            subregion.unite(determineFilterPrimitiveSubregion(effect->inputEffect(i)));
    } else
        subregion = filter->filterRegionInUserSpace();

    // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
    if (effect->filterEffectType() == FilterEffectTypeTile)
        subregion = filter->filterRegionInUserSpace();

    FloatRect effectBoundaries = effect->effectBoundaries();
    if (effect->hasX())
        subregion.setX(effectBoundaries.x());
    if (effect->hasY())
        subregion.setY(effectBoundaries.y());
    if (effect->hasWidth())
        subregion.setWidth(effectBoundaries.width());
    if (effect->hasHeight())
        subregion.setHeight(effectBoundaries.height());

    effect->setFilterPrimitiveSubregion(subregion);

    FloatRect absoluteSubregion = filter->absoluteTransform().mapRect(subregion);
    FloatSize filterResolution = filter->filterResolution();
    absoluteSubregion.scale(filterResolution.width(), filterResolution.height());

    // Clip every filter effect to the filter region.
    FloatRect absoluteScaledFilterRegion = filter->filterRegion();
    absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height());
    absoluteSubregion.intersect(absoluteScaledFilterRegion);

    effect->setMaxEffectRect(absoluteSubregion);
    return subregion;
}