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); } }
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); }
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); } }
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; }
// 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); }
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); }
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); }
// 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; }
// 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); }
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; }
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; }
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); }
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()); }
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; }
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(); }
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); }
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; }
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); }
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; }
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(); } } }