void SkPictureImageFilter::drawPictureAtLocalResolution(SkSpecialImage* source,
                                                        SkCanvas* canvas,
                                                        const SkIRect& deviceBounds,
                                                        const Context& ctx) const {
    SkMatrix inverseCtm;
    if (!ctx.ctm().invert(&inverseCtm)) {
        return;
    }

    SkRect localBounds = SkRect::Make(ctx.clipBounds());
    inverseCtm.mapRect(&localBounds);
    if (!localBounds.intersect(fCropRect)) {
        return;
    }
    SkIRect localIBounds = localBounds.roundOut();

    sk_sp<SkSpecialImage> localImg;
    {                                                            
        const SkImageInfo info = SkImageInfo::MakeN32(localIBounds.width(), localIBounds.height(),
                                                      kPremul_SkAlphaType);

        sk_sp<SkSpecialSurface> localSurface(source->makeSurface(info));
        if (!localSurface) {
            return;
        }

        SkCanvas* localCanvas = localSurface->getCanvas();
        SkASSERT(localCanvas);

        localCanvas->translate(-SkIntToScalar(localIBounds.fLeft),
                               -SkIntToScalar(localIBounds.fTop));
        localCanvas->drawPicture(fPicture);

        localImg = localSurface->makeImageSnapshot();
        SkASSERT(localImg);
    }

    {
        canvas->translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop));
        canvas->concat(ctx.ctm());
        SkPaint paint;
        paint.setFilterQuality(fFilterQuality);

        localImg->draw(canvas,
                       SkIntToScalar(localIBounds.fLeft),
                       SkIntToScalar(localIBounds.fTop),
                       &paint);
    }
}
Beispiel #2
0
void ClipRectToCanvas(const SkCanvas& canvas, const SkRect& srcRect, SkRect* destRect) {
    // Translate into the canvas' coordinate space. This is where the clipping
    // region applies.
    SkRect transformedSrc;
    canvas.getTotalMatrix().mapRect(&transformedSrc, srcRect);

    // Do the intersection.
    SkRect transformedDest;
    IntersectRectAndRegion(canvas.getTotalClip(), transformedSrc, &transformedDest);

    // Now transform it back into world space.
    SkMatrix inverseTransform;
    canvas.getTotalMatrix().invert(&inverseTransform);
    inverseTransform.mapRect(destRect, transformedDest);
}
Beispiel #3
0
void GrLayerHoister::FindLayersToHoist(GrContext* context,
                                       const SkPicture* topLevelPicture,
                                       const SkMatrix& initialMat,
                                       const SkRect& query,
                                       SkTDArray<GrHoistedLayer>* needRendering,
                                       SkTDArray<GrHoistedLayer>* recycled,
                                       int numSamples) {
    GrLayerCache* layerCache = context->getLayerCache();

    layerCache->processDeletedPictures();

    SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();

    const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
    if (!topLevelData) {
        return;
    }

    const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
    if (0 == topLevelGPUData->numBlocks()) {
        return;
    }

    // Find and prepare for hoisting all the layers that intersect the query rect
    for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
        const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
        if (info.fIsNested) {
            // Parent layers are currently hoisted while nested layers are not.
            continue;
        }

        SkRect layerRect;
        initialMat.mapRect(&layerRect, info.fBounds);
        if (!layerRect.intersect(query)) {
            continue;
        }

        const SkIRect dstIR = layerRect.roundOut();

        SkIRect srcIR;
        if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) {
            continue;
        }

        prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcIR, dstIR,
                             needRendering, recycled, false, numSamples);
    }
}
Beispiel #4
0
void GrDrawTarget::drawPath(const GrPath* path, GrPathRendering::FillType fill) {
    // TODO: extract portions of checkDraw that are relevant to path rendering.
    SkASSERT(path);
    SkASSERT(this->caps()->pathRenderingSupport());

    SkRect devBounds = path->getBounds();
    SkMatrix viewM = this->drawState()->getViewMatrix();
    viewM.mapRect(&devBounds);

    GrDeviceCoordTexture dstCopy;
    if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
        return;
    }

    this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
}
FloatRect FEBoxReflect::mapRect(const FloatRect& rect, bool forward)
{
    SkMatrix flipMatrix = SkiaImageFilterBuilder().matrixForBoxReflectFilter(
        m_reflectionDirection, m_offset);
    if (!forward) {
        bool inverted = flipMatrix.invert(&flipMatrix);
        DCHECK(inverted) << "box reflect matrix must be invertible";
    }

    SkRect reflection(rect);
    flipMatrix.mapRect(&reflection);

    FloatRect result = rect;
    result.unite(reflection);
    return result;
}
 void performTest() override {
     if (fFlags & kUncachedTypeMask_Flag) {
         // This will invalidate the typemask without
         // changing the matrix.
         fMatrix.setPerspX(fMatrix.getPerspX());
     }
     SkMatrix inv;
     bool invertible = fMatrix.invert(&inv);
     SkASSERT(invertible);
     SkRect transformedRect;
     // an arbitrary, small, non-zero rect to transform
     SkRect srcRect = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
     if (invertible) {
         inv.mapRect(&transformedRect, srcRect);
     }
 }
static bool can_ignore_bilerp_constraint(const GrTextureProducer& producer,
                                         const SkRect& srcRect,
                                         const SkMatrix& srcRectToDeviceSpace,
                                         bool isMSAA) {
    if (srcRectToDeviceSpace.rectStaysRect()) {
        // sampling is axis-aligned
        SkRect transformedRect;
        srcRectToDeviceSpace.mapRect(&transformedRect, srcRect);

        if (has_aligned_samples(srcRect, transformedRect) ||
            !may_color_bleed(srcRect, transformedRect, srcRectToDeviceSpace, isMSAA)) {
            return true;
        }
    }
    return false;
}
Beispiel #8
0
// Draws the given bitmap to the given canvas. The subset of the source bitmap
// identified by src_rect is drawn to the given destination rect. The bitmap
// will be resampled to resample_width * resample_height (this is the size of
// the whole image, not the subset). See shouldResampleBitmap for more.
//
// This does a lot of computation to resample only the portion of the bitmap
// that will only be drawn. This is critical for performance since when we are
// scrolling, for example, we are only drawing a small strip of the image.
// Resampling the whole image every time is very slow, so this speeds up things
// dramatically.
//
// Note: this code is only used when the canvas transformation is limited to
// scaling or translation.
static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkIRect& srcIRect, const SkRect& destRect)
{
#if PLATFORM(CHROMIUM)
    TRACE_EVENT0("skia", "drawResampledBitmap");
#endif
    // Apply forward transform to destRect to estimate required size of
    // re-sampled bitmap, and use only in calls required to resize, or that
    // check for the required size.
    SkRect destRectTransformed;
    canvas.getTotalMatrix().mapRect(&destRectTransformed, destRect);
    SkIRect destRectTransformedRounded;
    destRectTransformed.round(&destRectTransformedRounded);

    // Compute the visible portion of our rect.
    SkRect destRectVisibleSubset;
    ClipRectToCanvas(canvas, destRect, &destRectVisibleSubset);
    // ClipRectToCanvas often overshoots, resulting in a larger region than our
    // original destRect. Intersecting gets us back inside.
    if (!destRectVisibleSubset.intersect(destRect))
        return; // Nothing visible in destRect.

    // Compute the image-relative (bitmap space) subset.
    SkRect destBitmapSubset = destRectVisibleSubset;
    destBitmapSubset.offset(-destRect.x(), -destRect.y());

    // Scale the subset to the requested size. The canvas scale can be negative,
    // but the resampling code is only interested in positive scaling in its normal space.
    SkMatrix subsetTransform;
    subsetTransform.setScale(SkScalarAbs(canvas.getTotalMatrix().getScaleX()),
                             SkScalarAbs(canvas.getTotalMatrix().getScaleY()));
    SkRect destBitmapSubsetTransformed;
    subsetTransform.mapRect(&destBitmapSubsetTransformed, destBitmapSubset);
    SkIRect destBitmapSubsetTransformedRounded;
    destBitmapSubsetTransformed.round(&destBitmapSubsetTransformedRounded);

    // Transforms above plus rounding may cause destBitmapSubsetTransformedRounded
    // to go outside the image, so need to clip to avoid problems.
    if (!destBitmapSubsetTransformedRounded.intersect(
            0, 0, destRectTransformedRounded.width(), destRectTransformedRounded.height()))
        return; // Image is not visible.

    SkBitmap resampled = bitmap.resizedBitmap(srcIRect,
                                              destRectTransformedRounded.width(),
                                              destRectTransformedRounded.height(),
                                              destBitmapSubsetTransformedRounded);
    canvas.drawBitmapRect(resampled, 0, destRectVisibleSubset, &paint);
}
Beispiel #9
0
void SkConservativeClip::opRect(const SkRect& localRect, const SkMatrix& ctm,
                                const SkIRect& devBounds, SkRegion::Op op, bool doAA) {
    SkIRect ir;
    switch (mutate_conservative_op(&op, false)) {
        case kDoNothing_MutateResult:
            return;
        case kReplaceClippedAgainstGlobalBounds_MutateResult:
            ir = devBounds;
            break;
        case kContinue_MutateResult: {
            SkRect devRect;
            ctm.mapRect(&devRect, localRect);
            ir = doAA ? devRect.roundOut() : devRect.round();
        } break;
    }
    this->opIRect(ir, op);
}
std::unique_ptr<GrDrawOp> MakeAAFillWithLocalRect(GrContext* context,
                                                  GrPaint&& paint,
                                                  const SkMatrix& viewMatrix,
                                                  const SkRect& rect,
                                                  const SkRect& localRect) {
    if (!view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
        return nullptr;
    }
    SkRect devRect;
    viewMatrix.mapRect(&devRect, rect);
    SkMatrix localMatrix;
    if (!localMatrix.setRectToRect(rect, localRect, SkMatrix::kFill_ScaleToFit)) {
        return nullptr;
    }
    return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, devRect,
                              &localMatrix, nullptr);
}
Beispiel #11
0
void SkConservativeClip::opPath(const SkPath& path, const SkMatrix& ctm, const SkIRect& devBounds,
                                SkRegion::Op op, bool doAA) {
    SkIRect ir;
    switch (mutate_conservative_op(&op, path.isInverseFillType())) {
        case kDoNothing_MutateResult:
            return;
        case kReplaceClippedAgainstGlobalBounds_MutateResult:
            ir = devBounds;
            break;
        case kContinue_MutateResult: {
            SkRect bounds = path.getBounds();
            ctm.mapRect(&bounds);
            ir = bounds.roundOut();
            break;
        }
    }
    return this->opIRect(ir, op);
}
bool SkMatrixImageFilter::onFilterImage(Proxy* proxy,
                                        const SkBitmap& source,
                                        const Context& ctx,
                                        SkBitmap* result,
                                        SkIPoint* offset) const {
    SkBitmap src = source;
    SkIPoint srcOffset = SkIPoint::Make(0, 0);
    if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
        return false;
    }

    SkRect dstRect;
    SkIRect srcBounds, dstBounds;
    src.getBounds(&srcBounds);
    srcBounds.offset(srcOffset);
    SkRect srcRect = SkRect::Make(srcBounds);
    SkMatrix matrix;
    if (!ctx.ctm().invert(&matrix)) {
        return false;
    }
    matrix.postConcat(fTransform);
    matrix.postConcat(ctx.ctm());
    matrix.mapRect(&dstRect, srcRect);
    dstRect.roundOut(&dstBounds);

    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
    if (NULL == device.get()) {
        return false;
    }

    SkCanvas canvas(device.get());
    canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
    canvas.concat(matrix);
    SkPaint paint;

    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    paint.setFilterLevel(fFilterLevel);
    canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint);

    *result = device.get()->accessBitmap(false);
    offset->fX = dstBounds.fLeft;
    offset->fY = dstBounds.fTop;
    return true;
}
void GradientGeneratedImage::draw(SkCanvas* canvas,
                                  const SkPaint& paint,
                                  const FloatRect& destRect,
                                  const FloatRect& srcRect,
                                  RespectImageOrientationEnum,
                                  ImageClampingMode) {
  SkRect visibleSrcRect = srcRect;
  if (!visibleSrcRect.intersect(
          SkRect::MakeIWH(m_size.width(), m_size.height())))
    return;

  const SkMatrix transform =
      SkMatrix::MakeRectToRect(srcRect, destRect, SkMatrix::kFill_ScaleToFit);
  SkRect visibleDestRect;
  transform.mapRect(&visibleDestRect, visibleSrcRect);

  SkPaint gradientPaint(paint);
  m_gradient->applyToPaint(gradientPaint, transform);
  canvas->drawRect(visibleDestRect, gradientPaint);
}
Beispiel #14
0
// FIXME: Remove this code when SkCanvas accepts SkRect as source rectangle.
// See crbug.com/117597 for background.
//
// WebKit wants to draw a sub-rectangle (FloatRect) in a bitmap and scale it to
// another FloatRect. However Skia only allows bitmap to be addressed by a
// IntRect. This function computes the appropriate IntRect that encloses the
// source rectangle and the corresponding enclosing destination rectangle,
// while maintaining the scale factor.
//
// |srcRect| is the source rectangle in the bitmap. Return true if fancy
// alignment is required. User of this function needs to clip to |dstRect|.
// Return false if clipping is not needed.
//
// |dstRect| is the input rectangle that |srcRect| is scaled to.
//
// |outSrcRect| and |outDstRect| are the corresponding output rectangles.
//
// ALGORITHM
//
// The objective is to (a) find an enclosing IntRect for the source rectangle
// and (b) the corresponding FloatRect in destination space.
//
// These are the steps performed:
//
// 1. IntRect enclosingSrcRect = enclosingIntRect(srcRect)
//
//    Compute the enclosing IntRect for |srcRect|. This ensures the bitmap
//    image is addressed with integer boundaries.
//
// 2. FloatRect enclosingDestRect = mapSrcToDest(enclosingSrcRect)
//
//    Map the enclosing source rectangle to destination coordinate space.
//
// The output will be enclosingSrcRect and enclosingDestRect from the
// algorithm above.
static bool computeBitmapDrawRects(const SkISize& bitmapSize, const SkRect& srcRect, const SkRect& dstRect, SkIRect* outSrcRect, SkRect* outDstRect)
{
    if (areBoundariesIntegerAligned(srcRect)) {
        *outSrcRect = roundedIntRect(srcRect);
        *outDstRect = dstRect;
        return false;
    }

    SkIRect bitmapRect = SkIRect::MakeSize(bitmapSize);
    SkIRect enclosingSrcRect = enclosingIntRect(srcRect);
    enclosingSrcRect.intersect(bitmapRect); // Clip to bitmap rectangle.
    SkRect enclosingDstRect;
    enclosingDstRect.set(enclosingSrcRect);
    SkMatrix transform;
    transform.setRectToRect(srcRect, dstRect, SkMatrix::kFill_ScaleToFit);
    transform.mapRect(&enclosingDstRect);
    *outSrcRect = enclosingSrcRect;
    *outDstRect = enclosingDstRect;
    return true;
}
Beispiel #15
0
// This function is used to scale an image and extract a scaled fragment.
//
// ALGORITHM
//
// Because the scaled image size has to be integers, we approximate the real
// scale with the following formula (only X direction is shown):
//
// scaledImageWidth = round(scaleX * imageRect.width())
// approximateScaleX = scaledImageWidth / imageRect.width()
//
// With this method we maintain a constant scale factor among fragments in
// the scaled image. This allows fragments to stitch together to form the
// full scaled image. The downside is there will be a small difference
// between |scaleX| and |approximateScaleX|.
//
// A scaled image fragment is identified by:
//
// - Scaled image size
// - Scaled image fragment rectangle (IntRect)
//
// Scaled image size has been determined and the next step is to compute the
// rectangle for the scaled image fragment which needs to be an IntRect.
//
// scaledSrcRect = srcRect * (approximateScaleX, approximateScaleY)
// enclosingScaledSrcRect = enclosingIntRect(scaledSrcRect)
//
// Finally we extract the scaled image fragment using
// (scaledImageSize, enclosingScaledSrcRect).
//
static SkBitmap extractScaledImageFragment(const NativeImageSkia& bitmap, const SkRect& srcRect, float scaleX, float scaleY, SkRect* scaledSrcRect, SkIRect* enclosingScaledSrcRect)
{
    SkISize imageSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height());
    SkISize scaledImageSize = SkISize::Make(clampToInteger(roundf(imageSize.width() * scaleX)),
        clampToInteger(roundf(imageSize.height() * scaleY)));

    SkRect imageRect = SkRect::MakeWH(imageSize.width(), imageSize.height());
    SkRect scaledImageRect = SkRect::MakeWH(scaledImageSize.width(), scaledImageSize.height());

    SkMatrix scaleTransform;
    scaleTransform.setRectToRect(imageRect, scaledImageRect, SkMatrix::kFill_ScaleToFit);
    scaleTransform.mapRect(scaledSrcRect, srcRect);

    scaledSrcRect->intersect(scaledImageRect);
    *enclosingScaledSrcRect = enclosingIntRect(*scaledSrcRect);

    // |enclosingScaledSrcRect| can be larger than |scaledImageSize| because
    // of float inaccuracy so clip to get inside.
    enclosingScaledSrcRect->intersect(SkIRect::MakeSize(scaledImageSize));
    return bitmap.resizedBitmap(scaledImageSize, *enclosingScaledSrcRect);
}
Beispiel #16
0
static bool legacy_shader_can_handle(const SkMatrix& inv) {
    if (!inv.isScaleTranslate()) {
        return false;
    }

    // legacy code uses SkFixed 32.32, so ensure the inverse doesn't map device coordinates
    // out of range.
    const SkScalar max_dev_coord = 32767.0f;
    SkRect src;
    SkAssertResult(inv.mapRect(&src, SkRect::MakeWH(max_dev_coord, max_dev_coord)));

    // take 1/4 of max signed 32bits so we have room to subtract local values
    const SkScalar max_fixed32dot32 = SK_MaxS32 * 0.25f;
    if (!SkRect::MakeLTRB(-max_fixed32dot32, -max_fixed32dot32,
                           max_fixed32dot32, max_fixed32dot32).contains(src)) {
        return false;
    }

    // legacy shader impl should be able to handle these matrices
    return true;
}
Beispiel #17
0
void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target,
                                         GrDrawState* drawState,
                                         GrColor color,
                                         const SkRect rects[2],
                                         const SkMatrix& combinedMatrix) {
    SkASSERT(combinedMatrix.rectStaysRect());
    SkASSERT(!rects[1].isEmpty());

    SkRect devOutside, devOutsideAssist, devInside;
    combinedMatrix.mapRect(&devOutside, rects[0]);
    // can't call mapRect for devInside since it calls sort
    combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);

    if (devInside.isEmpty()) {
        this->fillAARect(target, drawState, color, devOutside, SkMatrix::I(), devOutside);
        return;
    }

    this->geometryStrokeAARect(target, drawState, color, devOutside, devOutsideAssist, devInside,
                               true);
}
// This function is a mirror of SkCanvas::getClipBounds except that it does
// not outset the edge of the clip to account for anti-aliasing. There is
// a skia bug to investigate pushing this logic into back into skia.
// (see https://code.google.com/p/skia/issues/detail?id=1303)
bool SkiaCanvas::getClipBounds(SkRect* outRect) const {
    SkIRect ibounds;
    if (!mCanvas->getClipDeviceBounds(&ibounds)) {
        return false;
    }

    SkMatrix inverse;
    // if we can't invert the CTM, we can't return local clip bounds
    if (!mCanvas->getTotalMatrix().invert(&inverse)) {
        if (outRect) {
            outRect->setEmpty();
        }
        return false;
    }

    if (NULL != outRect) {
        SkRect r = SkRect::Make(ibounds);
        inverse.mapRect(outRect, r);
    }
    return true;
}
Beispiel #19
0
    void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint, SkScalar scale, const SkIRect& cropRect) {
        canvas->save();
        SkRect clipRect = SkRect::MakeWH(
            SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
        canvas->clipRect(clipRect);
        canvas->scale(scale, scale);
        canvas->drawBitmap(bitmap, 0, 0, &paint);
        canvas->restore();
        SkPaint strokePaint;
        strokePaint.setStyle(SkPaint::kStroke_Style);
        strokePaint.setColor(SK_ColorRED);

        // Draw a boundary rect around the intersection of the clip rect
        // and crop rect.
        SkMatrix scaleMatrix;
        scaleMatrix.setScale(scale, scale);
        SkRect cropRectFloat;
        scaleMatrix.mapRect(&cropRectFloat, SkRect::Make(cropRect));
        clipRect.intersect(cropRectFloat);
        canvas->drawRect(clipRect, strokePaint);
    }
Beispiel #20
0
void SkGLDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
    TRACE_DRAW("coreDrawPaint", this, draw);
    
    AutoPaintShader   shader(this, paint);
    SkGLVertex        vertex[4];
    const SkGLVertex* texs = shader.useTex() ? vertex : NULL;
    
    // set vert to be big enough to fill the space, but not super-huge, to we
    // don't overflow fixed-point implementations
    {
        SkRect r;
        r.set(this->clip().getBounds());
        SkMatrix inverse;
        if (draw.fMatrix->invert(&inverse)) {
            inverse.mapRect(&r);
        }
        vertex->setRectFan(r);
    }
    
    SkGL::DrawVertices(4, GL_TRIANGLE_FAN, vertex, texs, NULL, NULL,
                       this->updateMatrixClip());
}
Beispiel #21
0
bool SkMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
                                         SkIRect* dst) const {
    SkMatrix transformInverse;
    if (!fTransform.invert(&transformInverse)) {
        return false;
    }
    SkMatrix matrix;
    if (!ctm.invert(&matrix)) {
        return false;
    }
    matrix.postConcat(transformInverse);
    matrix.postConcat(ctm);
    SkRect floatBounds;
    matrix.mapRect(&floatBounds, SkRect::Make(src));
    SkIRect bounds = floatBounds.roundOut();
    if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
        return false;
    }

    *dst = bounds;
    return true;
}
Beispiel #22
0
bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkIRect& devBounds,
                      SkRegion::Op op, bool doAA) {
    AUTO_RASTERCLIP_VALIDATE(*this);
    SkRect devRect;

    const bool isScaleTrans = matrix.isScaleTranslate();
    if (!isScaleTrans) {
        SkPath path;
        path.addRect(localRect);
        path.setIsVolatile(true);
        return this->op(path, matrix, devBounds, op, doAA);
    }

    matrix.mapRect(&devRect, localRect);

    if (fIsBW && doAA) {
        // check that the rect really needs aa, or is it close enought to
        // integer boundaries that we can just treat it as a BW rect?
        if (nearly_integral(devRect.fLeft) && nearly_integral(devRect.fTop) &&
            nearly_integral(devRect.fRight) && nearly_integral(devRect.fBottom)) {
            doAA = false;
        }
    }

    if (fIsBW && !doAA) {
        SkIRect ir;
        devRect.round(&ir);
        this->applyClipRestriction(op, &ir);
        (void)fBW.op(ir, op);
    } else {
        if (fIsBW) {
            this->convertToAA();
        }
        this->applyClipRestriction(op, &devRect);
        (void)fAA.op(devRect, op, doAA);
    }
    return this->updateCacheAndReturnNonEmpty();
}
Beispiel #23
0
void GradientGeneratedImage::draw(SkCanvas* canvas,
                                  const SkPaint& paint,
                                  const FloatRect& destRect,
                                  const FloatRect& srcRect,
                                  RespectImageOrientationEnum,
                                  ImageClampingMode,
                                  const ColorBehavior& colorBehavior) {
  // TODO(ccameron): This function should not ignore |colorBehavior|.
  // https://crbug.com/672306
  SkRect visibleSrcRect = srcRect;
  if (!visibleSrcRect.intersect(
          SkRect::MakeIWH(m_size.width(), m_size.height())))
    return;

  const SkMatrix transform =
      SkMatrix::MakeRectToRect(srcRect, destRect, SkMatrix::kFill_ScaleToFit);
  SkRect visibleDestRect;
  transform.mapRect(&visibleDestRect, visibleSrcRect);

  SkPaint gradientPaint(paint);
  m_gradient->applyToPaint(gradientPaint, transform);
  canvas->drawRect(visibleDestRect, gradientPaint);
}
    DEFINE_BATCH_CLASS_ID

    AAFlatteningConvexPathBatch(GrColor color,
                                const SkMatrix& viewMatrix,
                                const SkPath& path,
                                SkScalar strokeWidth,
                                SkPaint::Join join,
                                SkScalar miterLimit) : INHERITED(ClassID()) {
        fGeoData.emplace_back(Geometry{color, viewMatrix, path, strokeWidth, join, miterLimit});

        // compute bounds
        fBounds = path.getBounds();
        SkScalar w = strokeWidth;
        if (w > 0) {
            w /= 2;
            // If the half stroke width is < 1 then we effectively fallback to bevel joins.
            if (SkPaint::kMiter_Join == join && w > 1.f) {
                w *= miterLimit;
            }
            fBounds.outset(w, w);
        }
        viewMatrix.mapRect(&fBounds);
    }
 TessellatingPathBatch(const GrColor& color,
                       const SkPath& path,
                       const GrStyle& style,
                       const SkMatrix& viewMatrix,
                       const SkRect& clipBounds)
   : INHERITED(ClassID())
   , fColor(color)
   , fPath(path)
   , fStyle(style)
   , fViewMatrix(viewMatrix) {
     const SkRect& pathBounds = path.getBounds();
     fClipBounds = clipBounds;
     // Because the clip bounds are used to add a contour for inverse fills, they must also
     // include the path bounds.
     fClipBounds.join(pathBounds);
     if (path.isInverseFillType()) {
         fBounds = fClipBounds;
     } else {
         fBounds = path.getBounds();
     }
     style.adjustBounds(&fBounds, fBounds);
     viewMatrix.mapRect(&fBounds);
 }
Beispiel #26
0
static bool apply_aa_to_rect(GrDrawTarget* target,
                             GrPipelineBuilder* pipelineBuilder,
                             SkRect* devBoundRect,
                             const SkRect& rect,
                             SkScalar strokeWidth,
                             const SkMatrix& combinedMatrix,
                             GrColor color) {
    if (pipelineBuilder->getRenderTarget()->isUnifiedMultisampled() ||
        !combinedMatrix.preservesAxisAlignment()) {
        return false;
    }

    combinedMatrix.mapRect(devBoundRect, rect);
    if (!combinedMatrix.rectStaysRect()) {
        return true;
    }

    if (strokeWidth < 0) {
        return !is_irect(*devBoundRect);
    }

    return true;
}
Beispiel #27
0
void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
    // TODO: extract portions of checkDraw that are relevant to path rendering.
    SkASSERT(NULL != path);
    SkASSERT(this->caps()->pathRenderingSupport());
    const GrDrawState* drawState = &getDrawState();

    SkRect devBounds;
    if (SkPath::IsInverseFillType(fill)) {
        devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
                                   SkIntToScalar(drawState->getRenderTarget()->height()));
    } else {
        devBounds = path->getBounds();
    }
    SkMatrix viewM = drawState->getViewMatrix();
    viewM.mapRect(&devBounds);

    GrDeviceCoordTexture dstCopy;
    if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
        return;
    }

    this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
}
Beispiel #28
0
void SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds,
                                      const SkMatrix& ctm,
                                      bool embiggen,
                                      SkIRect* cropped) const {
    *cropped = imageBounds;
    if (fFlags) {
        SkRect devCropR;
        ctm.mapRect(&devCropR, fRect);
        SkIRect devICropR = devCropR.roundOut();

        // Compute the left/top first, in case we need to modify the right/bottom for a missing edge
        if (fFlags & kHasLeft_CropEdge) {
            if (embiggen || devICropR.fLeft > cropped->fLeft) {
                cropped->fLeft = devICropR.fLeft;
            }
        } else {
            devICropR.fRight = cropped->fLeft + devICropR.width();
        }
        if (fFlags & kHasTop_CropEdge) {
            if (embiggen || devICropR.fTop > cropped->fTop) {
                cropped->fTop = devICropR.fTop;
            }
        } else {
            devICropR.fBottom = cropped->fTop + devICropR.height();
        }
        if (fFlags & kHasWidth_CropEdge) {
            if (embiggen || devICropR.fRight < cropped->fRight) {
                cropped->fRight = devICropR.fRight;
            }
        }
        if (fFlags & kHasHeight_CropEdge) {
            if (embiggen || devICropR.fBottom < cropped->fBottom) {
                cropped->fBottom = devICropR.fBottom;
            }
        }
    }
}
static bool apply_aa_to_rect(GrDrawTarget* target,
                             GrPipelineBuilder* pipelineBuilder,
                             SkRect* devBoundRect,
                             const SkRect& rect,
                             SkScalar strokeWidth,
                             const SkMatrix& combinedMatrix,
                             GrColor color) {
    if (pipelineBuilder->getRenderTarget()->isUnifiedMultisampled()) {
        return false;
    }

#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
    if (strokeWidth >= 0) {
#endif
        if (!combinedMatrix.preservesAxisAlignment()) {
            return false;
        }

#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
    } else {
        if (!combinedMatrix.preservesRightAngles()) {
            return false;
        }
    }
#endif

    combinedMatrix.mapRect(devBoundRect, rect);
    if (!combinedMatrix.rectStaysRect()) {
        return true;
    }

    if (strokeWidth < 0) {
        return !is_irect(*devBoundRect);
    }

    return true;
}
Beispiel #30
0
void SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds,
                                      const SkMatrix& ctm,
                                      SkIRect* cropped) const {
    *cropped = imageBounds;
    if (fFlags) {
        SkRect devCropR;
        ctm.mapRect(&devCropR, fRect);
        const SkIRect devICropR = devCropR.roundOut();

        // Compute the left/top first, in case we have to read them to compute right/bottom
        if (fFlags & kHasLeft_CropEdge) {
            cropped->fLeft = devICropR.fLeft;
        }
        if (fFlags & kHasTop_CropEdge) {
            cropped->fTop = devICropR.fTop;
        }
        if (fFlags & kHasWidth_CropEdge) {
            cropped->fRight = cropped->fLeft + devICropR.width();
        }
        if (fFlags & kHasHeight_CropEdge) {
            cropped->fBottom = cropped->fTop + devICropR.height();
        }
    }
}