void CanvasRenderingContext2DState::clipPath(const SkPath& path, AntiAliasingMode antiAliasingMode)
{
    m_clipList.clipPath(path, antiAliasingMode, affineTransformToSkMatrix(m_transform));
    m_hasClip = true;
    if (!path.isRect(0))
        m_hasComplexClip = true;
}
PassRefPtr<SkShader> PicturePattern::createShader()
{
    SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformation);
    SkRect tileBounds = m_tilePicture->cullRect();

    return adoptRef(SkShader::CreatePictureShader(m_tilePicture.get(),
        SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix, &tileBounds));
}
Beispiel #3
0
void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTransformation)
{
    if (m_gradientSpaceTransformation == gradientSpaceTransformation)
        return;

    m_gradientSpaceTransformation = gradientSpaceTransformation;
    if (m_gradient)
        m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTransformation));
}
Beispiel #4
0
PassRefPtr<SkShader> DisplayListPattern::createShader()
{
    SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformation);
    SkRect tileBounds = SkRect::MakeWH(m_tileDisplayList->bounds().width(),
        m_tileDisplayList->bounds().height());

    return adoptRef(SkShader::CreatePictureShader(m_tileDisplayList->picture().get(),
        SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix, &tileBounds));
}
PassRefPtr<SkShader> BitmapPattern::createShader()
{
    if (m_tileImage.isNull()) {
        return adoptRef(SkShader::CreateColorShader(SK_ColorTRANSPARENT));
    }

    SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformation);

    if (isRepeatXY()) {
        return adoptRef(SkShader::CreateBitmapShader(m_tileImage, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
    }

    return BitmapPatternBase::createShader();
}
void BitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum shouldRespectImageOrientation, ImageClampingMode clampMode)
{
    TRACE_EVENT0("skia", "BitmapImage::draw");

    RefPtr<SkImage> image = imageForCurrentFrame();
    if (!image)
        return; // It's too early and we don't have an image yet.

    FloatRect adjustedSrcRect = srcRect;
    adjustedSrcRect.intersect(FloatRect(0, 0, image->width(), image->height()));

    if (adjustedSrcRect.isEmpty() || dstRect.isEmpty())
        return; // Nothing to draw.

    ImageOrientation orientation = DefaultImageOrientation;
    if (shouldRespectImageOrientation == RespectImageOrientation)
        orientation = frameOrientationAtIndex(m_currentFrame);

    int initialSaveCount = canvas->getSaveCount();
    FloatRect adjustedDstRect = dstRect;
    if (orientation != DefaultImageOrientation) {
        canvas->save();

        // ImageOrientation expects the origin to be at (0, 0)
        canvas->translate(adjustedDstRect.x(), adjustedDstRect.y());
        adjustedDstRect.setLocation(FloatPoint());

        canvas->concat(affineTransformToSkMatrix(orientation.transformFromDefault(adjustedDstRect.size())));

        if (orientation.usesWidthAsHeight()) {
            // The destination rect 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.
            adjustedDstRect = FloatRect(adjustedDstRect.x(), adjustedDstRect.y(), adjustedDstRect.height(), adjustedDstRect.width());
        }
    }

    SkRect skSrcRect = adjustedSrcRect;
    canvas->drawImageRect(image.get(), skSrcRect, adjustedDstRect, &paint,
        WebCoreClampingModeToSkiaRectConstraint(clampMode));
    canvas->restoreToCount(initialSaveCount);

    if (currentFrameIsLazyDecoded())
        PlatformInstrumentation::didDrawLazyPixelRef(image->uniqueID());

    if (ImageObserver* observer = imageObserver())
        observer->didDraw(this);

    startAnimation();
}
Beispiel #7
0
PassOwnPtr<DragImage> DragImage::create(Image* image, RespectImageOrientationEnum shouldRespectImageOrientation, float deviceScaleFactor)
{
    if (!image)
        return nullptr;

    RefPtr<NativeImageSkia> bitmap = image->nativeImageForCurrentFrame();
    if (!bitmap)
        return nullptr;

    if (image->isBitmapImage()) {
        ImageOrientation orientation = DefaultImageOrientation;
        BitmapImage* bitmapImage = toBitmapImage(image);
        IntSize sizeRespectingOrientation = bitmapImage->sizeRespectingOrientation();

        if (shouldRespectImageOrientation == RespectImageOrientation)
            orientation = bitmapImage->currentFrameOrientation();

        if (orientation != DefaultImageOrientation) {
            FloatRect destRect(FloatPoint(), sizeRespectingOrientation);
            if (orientation.usesWidthAsHeight())
                destRect = destRect.transposedRect();

            SkBitmap skBitmap;
            skBitmap.setConfig(
                SkBitmap::kARGB_8888_Config, sizeRespectingOrientation.width(), sizeRespectingOrientation.height());
            if (!skBitmap.allocPixels())
                return nullptr;

            SkCanvas canvas(skBitmap);
            canvas.concat(affineTransformToSkMatrix(orientation.transformFromDefault(sizeRespectingOrientation)));
            canvas.drawBitmapRect(bitmap->bitmap(), 0, destRect);

            return adoptPtr(new DragImage(skBitmap, deviceScaleFactor));
        }
    }

    SkBitmap skBitmap;
#if defined(SBROWSER_GPU_RASTERIZATION_ENABLE)
    if (!bitmap->bitmap().copyTo(&skBitmap, kPMColor_SkColorType))
#else
    if (!bitmap->bitmap().copyTo(&skBitmap, SkBitmap::kARGB_8888_Config))
#endif
        return nullptr;
    return adoptPtr(new DragImage(skBitmap, deviceScaleFactor));
}
PassRefPtr<SkShader> ImagePattern::createShader()
{
    if (!m_tileImage)
        return adoptRef(SkShader::CreateColorShader(SK_ColorTRANSPARENT));

    SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformation);

    if (isRepeatXY()) {
        // Fast path: for repeatXY we just return a shader from the original image.
        return adoptRef(m_tileImage->newShader(SkShader::kRepeat_TileMode,
            SkShader::kRepeat_TileMode, &localMatrix));
    }

    // Skia does not have a "draw the tile only once" option. Clamp_TileMode
    // repeats the last line of the image after drawing one tile. To avoid
    // filling the space with arbitrary pixels, this workaround forces the
    // image to have a line of transparent pixels on the "repeated" edge(s),
    // thus causing extra space to be transparent filled.
    SkShader::TileMode tileModeX = isRepeatX()
        ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
    SkShader::TileMode tileModeY = isRepeatY()
        ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
    int expandW = isRepeatX() ? 0 : 1;
    int expandH = isRepeatY() ? 0 : 1;

    // Create a transparent image 1 pixel wider and/or taller than the
    // original, then copy the orignal into it.
    // FIXME: Is there a better way to pad (not scale) an image in skia?
    RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(
        m_tileImage->width() + expandW, m_tileImage->height() + expandH));
    if (!surface)
        return adoptRef(SkShader::CreateColorShader(SK_ColorTRANSPARENT));

    surface->getCanvas()->clear(SK_ColorTRANSPARENT);
    SkPaint paint;
    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    surface->getCanvas()->drawImage(m_tileImage.get(), 0, 0, &paint);
    RefPtr<SkImage> expandedImage = adoptRef(surface->newImageSnapshot());

    return adoptRef(expandedImage->newShader(tileModeX, tileModeY, &localMatrix));
}
PassRefPtr<SkImage> DragImage::resizeAndOrientImage(PassRefPtr<SkImage> image, ImageOrientation orientation,
    FloatSize imageScale, float opacity, InterpolationQuality interpolationQuality)
{
    IntSize size(image->width(), image->height());
    size.scale(imageScale.width(), imageScale.height());
    AffineTransform transform;
    if (orientation != DefaultImageOrientation) {
        if (orientation.usesWidthAsHeight())
            size = size.transposedSize();
        transform *= orientation.transformFromDefault(size);
    }
    transform.scaleNonUniform(imageScale.width(), imageScale.height());

    if (size.isEmpty())
        return nullptr;

    if (transform.isIdentity() && opacity == 1) {
        // Nothing to adjust, just use the original.
        ASSERT(image->width() == size.width());
        ASSERT(image->height() == size.height());
        return image;
    }

    RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(size.width(), size.height()));
    if (!surface)
        return nullptr;

    SkPaint paint;
    ASSERT(opacity >= 0 && opacity <= 1);
    paint.setAlpha(opacity * 255);
    paint.setFilterQuality(interpolationQuality == InterpolationNone
        ? kNone_SkFilterQuality : kHigh_SkFilterQuality);

    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(SK_ColorTRANSPARENT);
    canvas->concat(affineTransformToSkMatrix(transform));
    canvas->drawImage(image.get(), 0, 0, &paint);

    return adoptRef(surface->newImageSnapshot());
}
Beispiel #10
0
SkShader* Pattern::shader()
{
    if (m_pattern)
        return m_pattern.get();

    // If we don't have a bitmap, return a transparent shader.
    if (!m_tileImage)
        m_pattern = adoptRef(new SkColorShader(SK_ColorTRANSPARENT));
    else if (m_repeatX && m_repeatY)
        m_pattern = adoptRef(SkShader::CreateBitmapShader(m_tileImage->bitmap(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
    else {
		SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
		SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
		int expandW = m_repeatX ? 0 : 1;
		int expandH = m_repeatY ? 0 : 1;

		// Create a transparent bitmap 1 pixel wider and/or taller than the
		// original, then copy the orignal into it.
		// FIXME: Is there a better way to pad (not scale) an image in skia?
		SkImageInfo info = m_tileImage->bitmap().info();
		info.fWidth += expandW;
		info.fHeight += expandH;
		// we explicitly require non-opaquness, since we are going to add a transparent strip.
		info.fAlphaType = kPremul_SkAlphaType;

		SkBitmap bm2;
		bm2.allocPixels(info);
		bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
		SkCanvas canvas(bm2);
		canvas.drawBitmap(m_tileImage->bitmap(), 0, 0);
		bm2.setImmutable();
		m_pattern = adoptRef(SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY));

		// Clamp to int, since that's what the adjust function takes.
		m_externalMemoryAllocated = static_cast<int>(std::min(static_cast<size_t>(INT_MAX), bm2.getSafeSize()));
    }
    m_pattern->setLocalMatrix(affineTransformToSkMatrix(m_patternSpaceTransformation));
    return m_pattern.get();
}
Beispiel #11
0
PassOwnPtr<DragImage> DragImage::create(Image* image, RespectImageOrientationEnum shouldRespectImageOrientation, float deviceScaleFactor)
{
    if (!image)
        return nullptr;

    RefPtr<NativeImageSkia> bitmap = image->nativeImageForCurrentFrame();
    if (!bitmap)
        return nullptr;

    if (image->isBitmapImage()) {
        ImageOrientation orientation = DefaultImageOrientation;
        BitmapImage* bitmapImage = toBitmapImage(image);
        IntSize sizeRespectingOrientation = bitmapImage->sizeRespectingOrientation();

        if (shouldRespectImageOrientation == RespectImageOrientation)
            orientation = bitmapImage->currentFrameOrientation();

        if (orientation != DefaultImageOrientation) {
            FloatRect destRect(FloatPoint(), sizeRespectingOrientation);
            if (orientation.usesWidthAsHeight())
                destRect = destRect.transposedRect();

            SkBitmap skBitmap;
            if (!skBitmap.tryAllocN32Pixels(sizeRespectingOrientation.width(), sizeRespectingOrientation.height()))
                return nullptr;

            SkCanvas canvas(skBitmap);
            canvas.concat(affineTransformToSkMatrix(orientation.transformFromDefault(sizeRespectingOrientation)));
            canvas.drawBitmapRect(bitmap->bitmap(), 0, destRect);

            return adoptPtr(new DragImage(skBitmap, deviceScaleFactor));
        }
    }

    SkBitmap skBitmap;
    if (!bitmap->bitmap().copyTo(&skBitmap, kN32_SkColorType))
        return nullptr;
    return adoptPtr(new DragImage(skBitmap, deviceScaleFactor));
}
Beispiel #12
0
void Pattern::setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation)
{
    m_patternSpaceTransformation = patternSpaceTransformation;
    if (m_pattern)
        m_pattern->setLocalMatrix(affineTransformToSkMatrix(m_patternSpaceTransformation));
}
sk_sp<SkShader> Gradient::createShader()
{
    sortStopsIfNecessary();
    ASSERT(m_stopsSorted);

    size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size());
    ASSERT(countUsed >= 2);
    ASSERT(countUsed >= m_stops.size());

    ColorStopOffsetVector pos(countUsed);
    ColorStopColorVector colors(countUsed);
    fillStops(m_stops.data(), m_stops.size(), pos, colors);

    SkShader::TileMode tile = SkShader::kClamp_TileMode;
    switch (m_spreadMethod) {
    case SpreadMethodReflect:
        tile = SkShader::kMirror_TileMode;
        break;
    case SpreadMethodRepeat:
        tile = SkShader::kRepeat_TileMode;
        break;
    case SpreadMethodPad:
        tile = SkShader::kClamp_TileMode;
        break;
    }

    sk_sp<SkShader> shader;
    uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0;
    if (m_radial) {
        if (aspectRatio() != 1) {
            // CSS3 elliptical gradients: apply the elliptical scaling at the
            // gradient center point.
            m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y());
            m_gradientSpaceTransformation.scale(1, 1 / aspectRatio());
            m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y());
            ASSERT(m_p0 == m_p1);
        }
        SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation);

        // Since the two-point radial gradient is slower than the plain radial,
        // only use it if we have to.
        if (m_p0 == m_p1 && m_r0 <= 0.0f) {
            shader = SkGradientShader::MakeRadial(m_p1.data(), m_r1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix);
        } else {
            // The radii we give to Skia must be positive. If we're given a
            // negative radius, ask for zero instead.
            SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0;
            SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
            shader = SkGradientShader::MakeTwoPointConical(m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix);
        }
    } else {
        SkPoint pts[2] = { m_p0.data(), m_p1.data() };
        SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation);
        shader = SkGradientShader::MakeLinear(pts, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix);
    }

    if (!shader) {
        // use last color, since our "geometry" was degenerate (e.g. radius==0)
        shader = SkShader::MakeColorShader(colors[countUsed - 1]);
    }

    return shader;
}
Beispiel #14
0
void Path::transform(const AffineTransform& xform) {
  m_path.transform(affineTransformToSkMatrix(xform));
}
Beispiel #15
0
SkShader* Gradient::shader()
{
    if (m_gradient)
        return m_gradient.get();

    sortStopsIfNecessary();
    ASSERT(m_stopsSorted);

    size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size());
    ASSERT(countUsed >= 2);
    ASSERT(countUsed >= m_stops.size());

    // FIXME: Why is all this manual pointer math needed?!
    SkAutoMalloc storage(countUsed * (sizeof(SkColor) + sizeof(SkScalar)));
    SkColor* colors = (SkColor*)storage.get();
    SkScalar* pos = (SkScalar*)(colors + countUsed);

    fillStops(m_stops.data(), m_stops.size(), pos, colors);

    SkShader::TileMode tile = SkShader::kClamp_TileMode;
    switch (m_spreadMethod) {
    case SpreadMethodReflect:
        tile = SkShader::kMirror_TileMode;
        break;
    case SpreadMethodRepeat:
        tile = SkShader::kRepeat_TileMode;
        break;
    case SpreadMethodPad:
        tile = SkShader::kClamp_TileMode;
        break;
    }

    uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0;
    if (m_radial) {
        // Since the two-point radial gradient is slower than the plain radial,
        // only use it if we have to.
        if (m_p0 == m_p1 && m_r0 <= 0.0f) {
            m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1, m_r1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
        } else {
            // The radii we give to Skia must be positive. If we're given a
            // negative radius, ask for zero instead.
            SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0;
            SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
            m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0, radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
        }

        if (aspectRatio() != 1) {
            // CSS3 elliptical gradients: apply the elliptical scaling at the
            // gradient center point.
            m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y());
            m_gradientSpaceTransformation.scale(1, 1 / aspectRatio());
            m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y());
            ASSERT(m_p0 == m_p1);
        }
    } else {
        SkPoint pts[2] = { m_p0, m_p1 };
        m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
    }

    if (!m_gradient) {
        // use last color, since our "geometry" was degenerate (e.g. radius==0)
        m_gradient = adoptRef(new SkColorShader(colors[countUsed - 1]));
    } else {
        m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTransformation));
    }
    return m_gradient.get();
}
void BeginTransformDisplayItem::appendToWebDisplayItemList(WebDisplayItemList* list) const
{
    list->appendTransformItem(affineTransformToSkMatrix(m_transform));
}
PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::buildTransform(const AffineTransform& transform, SkImageFilter* input)
{
    return adoptRef(SkImageFilter::CreateMatrixFilter(affineTransformToSkMatrix(transform), kHigh_SkFilterQuality, input));
}
Beispiel #18
0
void Path::addPath(const Path& src, const AffineTransform& transform) {
  m_path.addPath(src.getSkPath(), affineTransformToSkMatrix(transform));
}
PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::buildTransform(const AffineTransform& transform, SkImageFilter* input)
{
    return adoptRef(SkMatrixImageFilter::Create(affineTransformToSkMatrix(transform), SkPaint::kHigh_FilterLevel, input));
}