Beispiel #1
0
DisplayListPattern::DisplayListPattern(PassRefPtr<DisplayList> displayList, RepeatMode mode)
    : Pattern(mode)
    , m_tileDisplayList(displayList)
{
    // All current clients use RepeatModeXY, so we only support this mode for now.
    ASSERT(isRepeatXY());

    // FIXME: we don't have a good way to account for DL memory utilization.
}
PicturePattern::PicturePattern(PassRefPtr<const SkPicture> picture, RepeatMode mode)
    : Pattern(mode)
    , m_tilePicture(picture)
{
    // All current clients use RepeatModeXY, so we only support this mode for now.
    ASSERT(isRepeatXY());

    // FIXME: we don't have a good way to account for DL memory utilization.
}
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();
}
Beispiel #4
0
sk_sp<SkShader> ImagePattern::createShader(const SkMatrix& localMatrix) {
  if (!m_tileImage)
    return SkShader::MakeColorShader(SK_ColorTRANSPARENT);

  if (isRepeatXY()) {
    // Fast path: for repeatXY we just return a shader from the original image.
    return m_tileImage->makeShader(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 borderPixelX = isRepeatX() ? 0 : 1;
  int borderPixelY = isRepeatY() ? 0 : 1;

  // Create a transparent image 2 pixels wider and/or taller than the
  // original, then copy the orignal into the middle of it.
  // FIXME: Is there a better way to pad (not scale) an image in skia?
  sk_sp<SkSurface> surface =
      SkSurface::MakeRasterN32Premul(m_tileImage->width() + 2 * borderPixelX,
                                     m_tileImage->height() + 2 * borderPixelY);
  if (!surface)
    return SkShader::MakeColorShader(SK_ColorTRANSPARENT);

  SkPaint paint;
  paint.setBlendMode(SkBlendMode::kSrc);
  surface->getCanvas()->drawImage(m_tileImage, borderPixelX, borderPixelY,
                                  &paint);

  m_previousLocalMatrix = localMatrix;
  SkMatrix adjustedMatrix(localMatrix);
  adjustedMatrix.postTranslate(-borderPixelX, -borderPixelY);

  return surface->makeImageSnapshot()->makeShader(tileModeX, tileModeY,
                                                  &adjustedMatrix);
}
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));
}
Beispiel #6
0
bool ImagePattern::isLocalMatrixChanged(const SkMatrix& localMatrix) const {
  if (isRepeatXY())
    return Pattern::isLocalMatrixChanged(localMatrix);
  return localMatrix != m_previousLocalMatrix;
}