Esempio n. 1
0
void GrDrawContext::drawPaint(GrRenderTarget* rt,
                              const GrClip& clip,
                              const GrPaint& origPaint,
                              const SkMatrix& viewMatrix) {
    RETURN_IF_ABANDONED
    // set rect to be big enough to fill the space, but not super-huge, so we
    // don't overflow fixed-point implementations
    SkRect r;
    r.setLTRB(0, 0,
              SkIntToScalar(rt->width()),
              SkIntToScalar(rt->height()));
    SkTCopyOnFirstWrite<GrPaint> paint(origPaint);

    // by definition this fills the entire clip, no need for AA
    if (paint->isAntiAlias()) {
        paint.writable()->setAntiAlias(false);
    }

    bool isPerspective = viewMatrix.hasPerspective();

    // We attempt to map r by the inverse matrix and draw that. mapRect will
    // map the four corners and bound them with a new rect. This will not
    // produce a correct result for some perspective matrices.
    if (!isPerspective) {
        SkMatrix inverse;
        if (!viewMatrix.invert(&inverse)) {
            SkDebugf("Could not invert matrix\n");
            return;
        }
        inverse.mapRect(&r);
        this->drawRect(rt, clip, *paint, viewMatrix, r);
    } else {
        SkMatrix localMatrix;
        if (!viewMatrix.invert(&localMatrix)) {
            SkDebugf("Could not invert matrix\n");
            return;
        }

        AutoCheckFlush acf(fContext);
        if (!this->prepareToDraw(rt)) {
            return;
        }

        GrPipelineBuilder pipelineBuilder(*paint, rt, clip);
        fDrawTarget->drawBWRect(pipelineBuilder,
                                paint->getColor(),
                                SkMatrix::I(),
                                r,
                                NULL,
                                &localMatrix);
    }
}
Esempio n. 2
0
bool Surface::paint(SkCanvas* canvas)
{
    if (singleLayer()) {
        getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers);

        // TODO: double buffer by disabling SurfaceCollection swaps and position
        // updates until painting complete

        // In single surface mode, draw layer content onto the base layer
        if (isBase()
            && getFirstLayer()->countChildren()
            && getFirstLayer()->state()->isSingleSurfaceRenderingMode()) {
            for (int i = 0; i < getFirstLayer()->countChildren(); i++)
                getFirstLayer()->getChild(i)->drawCanvas(canvas, true, Layer::FlattenedLayers);
        }
    } else {
        SkAutoCanvasRestore acr(canvas, true);
        SkMatrix matrix;
        GLUtils::toSkMatrix(matrix, m_drawTransform);

        SkMatrix inverse;
        inverse.reset();
        matrix.invert(&inverse);

        SkMatrix canvasMatrix = canvas->getTotalMatrix();
        inverse.postConcat(canvasMatrix);
        canvas->setMatrix(inverse);

        for (unsigned int i=0; i<m_layers.size(); i++)
            m_layers[i]->drawCanvas(canvas, false, Layer::MergedLayers);
    }
    return true;
}
Esempio n. 3
0
void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
                                              GrDrawTarget* target,
                                              GrPipelineBuilder* pipelineBuilder,
                                              GrColor color,
                                              const SkMatrix& viewMatrix,
                                              const SkIRect& rect) {
    SkMatrix invert;
    if (!viewMatrix.invert(&invert)) {
        return;
    }
    GrPipelineBuilder::AutoRestoreFragmentProcessors arfp(pipelineBuilder);

    SkRect dstRect = SkRect::MakeLTRB(SK_Scalar1 * rect.fLeft,
                                      SK_Scalar1 * rect.fTop,
                                      SK_Scalar1 * rect.fRight,
                                      SK_Scalar1 * rect.fBottom);

    // We use device coords to compute the texture coordinates. We take the device coords and apply
    // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling
    // matrix to normalized coords.
    SkMatrix maskMatrix;
    maskMatrix.setIDiv(texture->width(), texture->height());
    maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop));

    pipelineBuilder->addCoverageProcessor(
                         GrSimpleTextureEffect::Create(texture,
                                                       maskMatrix,
                                                       GrTextureParams::kNone_FilterMode,
                                                       kDevice_GrCoordSet))->unref();

    target->drawRect(pipelineBuilder, color, SkMatrix::I(), dstRect, NULL, &invert);
}
 SkPoint invertPt(SkScalar x, SkScalar y) {
     SkPoint pt;
     SkMatrix m;
     fMatrix.invert(&m);
     m.mapXY(x, y, &pt);
     return pt;
 }
Esempio n. 5
0
void GrSWMaskHelper::DrawToTargetWithShapeMask(sk_sp<GrTextureProxy> proxy,
                                               GrRenderTargetContext* renderTargetContext,
                                               GrPaint&& paint,
                                               const GrUserStencilSettings& userStencilSettings,
                                               const GrClip& clip,
                                               const SkMatrix& viewMatrix,
                                               const SkIPoint& textureOriginInDeviceSpace,
                                               const SkIRect& deviceSpaceRectToDraw) {
    SkMatrix invert;
    if (!viewMatrix.invert(&invert)) {
        return;
    }

    GrResourceProvider* resourceProvider = renderTargetContext->resourceProvider();

    SkRect dstRect = SkRect::Make(deviceSpaceRectToDraw);

    // We use device coords to compute the texture coordinates. We take the device coords and apply
    // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling
    // matrix to normalized coords.
    SkMatrix maskMatrix = SkMatrix::MakeTrans(SkIntToScalar(-textureOriginInDeviceSpace.fX),
                                              SkIntToScalar(-textureOriginInDeviceSpace.fY));
    maskMatrix.preConcat(viewMatrix);
    std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill(
            paint.getColor(), SkMatrix::I(), dstRect, nullptr, &invert);
    paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(
            resourceProvider, std::move(proxy), nullptr, maskMatrix,
            GrSamplerParams::kNone_FilterMode));
    GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
    pipelineBuilder.setUserStencil(&userStencilSettings);
    renderTargetContext->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
}
Esempio n. 6
0
static bool inverse_transform_bbox(const SkMatrix& matrix, SkRect* bbox) {
    SkMatrix inverse;
    if (!matrix.invert(&inverse)) {
        return false;
    }
    inverse.mapRect(bbox);
    return true;
}
Esempio n. 7
0
Boolean Matrix::NativeInvert(
    /* [in] */ Int64 matrixHandle,
    /* [in] */ Int64 inverseHandle)
{
    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
    SkMatrix* inverse = reinterpret_cast<SkMatrix*>(inverseHandle);
    return matrix->invert(inverse);
}
    virtual void onDraw(SkCanvas* canvas) {
        SkMatrix m;
        m.reset();
        m.setRotate(33 * SK_Scalar1);
        m.postScale(3000 * SK_Scalar1, 3000 * SK_Scalar1);
        m.postTranslate(6000 * SK_Scalar1, -5000 * SK_Scalar1);
        canvas->concat(m);

        SkPaint paint;
        paint.setColor(SK_ColorRED);
        paint.setAntiAlias(true);

        bool success = m.invert(&m);
        SkASSERT(success);
        (void) success; // silence compiler :(

        SkPath path;

        SkPoint pt = {10 * SK_Scalar1, 10 * SK_Scalar1};
        SkScalar small = 1 / (500 * SK_Scalar1);

        m.mapPoints(&pt, 1);
        path.addCircle(pt.fX, pt.fY, small);
        canvas->drawPath(path, paint);

        pt.set(30 * SK_Scalar1, 10 * SK_Scalar1);
        m.mapPoints(&pt, 1);
        SkRect rect = {pt.fX - small, pt.fY - small,
                       pt.fX + small, pt.fY + small};
        canvas->drawRect(rect, paint);

        SkBitmap bmp;
        bmp.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
        bmp.allocPixels();
        bmp.lockPixels();
        uint32_t* pixels = reinterpret_cast<uint32_t*>(bmp.getPixels());
        pixels[0] = SkPackARGB32(0xFF, 0xFF, 0x00, 0x00);
        pixels[1] = SkPackARGB32(0xFF, 0x00, 0xFF, 0x00);
        pixels[2] = SkPackARGB32(0x80, 0x00, 0x00, 0x00);
        pixels[3] = SkPackARGB32(0xFF, 0x00, 0x00, 0xFF);
        bmp.unlockPixels();
        pt.set(30 * SK_Scalar1, 30 * SK_Scalar1);
        m.mapPoints(&pt, 1);
        SkShader* shader = SkShader::CreateBitmapShader(
                                            bmp,
                                            SkShader::kRepeat_TileMode,
                                            SkShader::kRepeat_TileMode);
        SkMatrix s;
        s.reset();
        s.setScale(SK_Scalar1 / 1000, SK_Scalar1 / 1000);
        shader->setLocalMatrix(s);
        paint.setShader(shader)->unref();
        paint.setAntiAlias(false);
        paint.setFilterLevel(SkPaint::kLow_FilterLevel);
        rect.setLTRB(pt.fX - small, pt.fY - small,
                     pt.fX + small, pt.fY + small);
        canvas->drawRect(rect, paint);
    }
Esempio n. 9
0
sk_sp<SkNormalSource> SkNormalSource::MakeFromNormalMap(sk_sp<SkShader> map, const SkMatrix& ctm) {
    SkMatrix invCTM;

    if (!ctm.invert(&invCTM) || !map) {
        return nullptr;
    }

    return sk_make_sp<SkNormalMapSourceImpl>(std::move(map), invCTM);
}
Esempio n. 10
0
bool SkNormalMapSourceImpl::computeNormTotalInverse(const SkShaderBase::ContextRec& rec,
                                                    SkMatrix* normTotalInverse) const {
    SkMatrix total = SkMatrix::Concat(*rec.fMatrix, fMapShader->getLocalMatrix());
    if (rec.fLocalMatrix) {
        total.preConcat(*rec.fLocalMatrix);
    }

    return total.invert(normTotalInverse);
}
bool GrAAHairLinePathRenderer::createGeom(
            const SkPath& path,
            GrDrawTarget* target,
            int* lineCnt,
            int* quadCnt,
            GrDrawTarget::AutoReleaseGeometry* arg) {
    const GrDrawState& drawState = target->getDrawState();
    int rtHeight = drawState.getRenderTarget()->height();

    GrIRect devClipBounds;
    target->getClip()->getConservativeBounds(drawState.getRenderTarget(),
                                             &devClipBounds);

    GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit;
    SkMatrix viewM = drawState.getViewMatrix();

    PREALLOC_PTARRAY(128) lines;
    PREALLOC_PTARRAY(128) quads;
    IntArray qSubdivs;
    *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds,
                                        &lines, &quads, &qSubdivs);

    *lineCnt = lines.count() / 2;
    int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;

    GrAssert(sizeof(Vertex) == GrDrawState::VertexSize(layout));

    if (!arg->set(target, layout, vertCnt, 0)) {
        return false;
    }

    Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices());

    const SkMatrix* toDevice = NULL;
    const SkMatrix* toSrc = NULL;
    SkMatrix ivm;

    if (viewM.hasPerspective()) {
        if (viewM.invert(&ivm)) {
            toDevice = &viewM;
            toSrc = &ivm;
        }
    }

    for (int i = 0; i < *lineCnt; ++i) {
        add_line(&lines[2*i], rtHeight, toSrc, &verts);
    }

    int unsubdivQuadCnt = quads.count() / 3;
    for (int i = 0; i < unsubdivQuadCnt; ++i) {
        GrAssert(qSubdivs[i] >= 0);
        add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts);
    }

    return true;
}
Esempio n. 12
0
void draw(SkCanvas* canvas) {
    SkMatrix matrix;
    matrix.setAll(1, 0, 0,  0, 1, 0,   0, 0, 0);
    if (matrix.invert(&matrix)) {
        SkScalar factor[2] = {2, 2};
        bool result = matrix.getMinMaxScales(factor);
        SkDebugf("matrix.getMinMaxScales() %s %g %g\n",
                result ? "true" : "false", factor[0], factor[1]);
    }
}
static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env,
        jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) {
    // load transform matrix
    android_view_RenderNode_getTransformMatrix(env, clazz, renderNodePtr, outMatrixPtr);
    SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);

    // return it inverted
    if (!outMatrix->invert(outMatrix)) {
        // failed to load inverse, pass back identity
        outMatrix->setIdentity();
    }
}
Esempio n. 14
0
SkGLDevice::TexCache* SkGLDevice::setupGLPaintShader(const SkPaint& paint) {
    SkGL::SetPaint(paint);
    
    SkShader* shader = paint.getShader();
    if (NULL == shader) {
        return NULL;
    }
    
    if (!shader->setContext(this->accessBitmap(false), paint, this->matrix())) {
        return NULL;
    }
    
    SkBitmap bitmap;
    SkMatrix matrix;
    SkShader::TileMode tileModes[2];
    if (!shader->asABitmap(&bitmap, &matrix, tileModes)) {
        return NULL;
    }
    
    bitmap.lockPixels();
    if (!bitmap.readyToDraw()) {
        return NULL;
    }
    
    // see if we've already cached the bitmap from the shader
    SkPoint max;
    GLuint name;
    TexCache* cache = SkGLDevice::LockTexCache(bitmap, &name, &max);
    // the lock has already called glBindTexture for us
    SkGL::SetTexParams(paint.isFilterBitmap(), tileModes[0], tileModes[1]);
    
    // since our texture coords will be in local space, we wack the texture
    // matrix to map them back into 0...1 before we load it
    SkMatrix localM;
    if (shader->getLocalMatrix(&localM)) {
        SkMatrix inverse;
        if (localM.invert(&inverse)) {
            matrix.preConcat(inverse);
        }
    }
    
    matrix.postScale(max.fX / bitmap.width(), max.fY / bitmap.height());
    glMatrixMode(GL_TEXTURE);
    SkGL::LoadMatrix(matrix);
    glMatrixMode(GL_MODELVIEW);
    
    // since we're going to use a shader/texture, we don't want the color,
    // just its alpha
    SkGL::SetAlpha(paint.getAlpha());
    // report that we have setup the texture
    return cache;
}
Esempio n. 15
0
bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const {
    if (local) {
        SkMatrix m;
        this->localToGlobal(&m);
        if (!m.invert(&m)) {
            return false;
        }
        SkPoint p;
        m.mapXY(x, y, &p);
        local->set(p.fX, p.fY);
    }

    return true;
}
Esempio n. 16
0
// Solves linear system to extract klm
// P.K = k (similarly for l, m)
// Where P is matrix of control points
// K is coefficients for the line K
// k is vector of values of K evaluated at the control points
// Solving for K, thus K = P^(-1) . k
static void calc_cubic_klm(const SkPoint p[4], const SkScalar controlK[4],
                           const SkScalar controlL[4], const SkScalar controlM[4],
                           SkScalar k[3], SkScalar l[3], SkScalar m[3]) {
    SkMatrix matrix;
    matrix.setAll(p[0].fX, p[0].fY, 1.f,
                  p[1].fX, p[1].fY, 1.f,
                  p[2].fX, p[2].fY, 1.f);
    SkMatrix inverse;
    if (matrix.invert(&inverse)) {
       inverse.mapHomogeneousPoints(k, controlK, 1);
       inverse.mapHomogeneousPoints(l, controlL, 1);
       inverse.mapHomogeneousPoints(m, controlM, 1);
    }

}
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;
}
Esempio n. 18
0
/*
 [0]	9.9999997e-005	float
 [1]	9.0000003e-006	float
 [2]	7.0000001e-006	float
 [3]	1000000.0	float
 [4]	90639.000	float
 [5]	70000.000	float
 [6]	0.00000000	float
 [7]	0.00000000	float
 [8]	1.0000000	float
 */
static void testinvert2() {
    const float val[] = {
        9.9999997e-005, 9.0000003e-006, 7.0000001e-006,
        1000000.0, 90639.000, 70000.000
    };
    SkMatrix matrix;
    setmatrix6(&matrix, val);
    matrix.dump();

    SkMatrix inverse;
    matrix.invert(&inverse);
    inverse.dump();

    matrix.preConcat(inverse);
    matrix.dump();
    // result is that matrix[3] is 49550 instead of 0 :(
}
Esempio n. 19
0
// Draw a mask using the supplied paint. Since the coverage/geometry
// is already burnt into the mask this boils down to a rect draw.
// Return true if the mask was successfully drawn.
static bool draw_mask(GrDrawContext* drawContext,
                      const GrClip& clip,
                      const SkMatrix& viewMatrix,
                      const SkRect& maskRect,
                      GrPaint* grp,
                      GrTexture* mask) {
    SkMatrix matrix;
    matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop);
    matrix.postIDiv(mask->width(), mask->height());

    grp->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(mask, matrix,
                                                                    kDevice_GrCoordSet))->unref();

    SkMatrix inverse;
    if (!viewMatrix.invert(&inverse)) {
        return false;
    }
    drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), maskRect, inverse);
    return true;
}
sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace(
                                                                     const Color& color,
                                                                     const Coverage& coverage,
                                                                     const LocalCoords& localCoords,
                                                                     const SkMatrix& viewMatrix) {
    SkMatrix invert = SkMatrix::I();
    if (LocalCoords::kUnused_Type != localCoords.fType) {
        SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType);
        if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
            return nullptr;
        }

        if (localCoords.hasLocalMatrix()) {
            invert.preConcat(*localCoords.fMatrix);
        }
    }

    LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
    return Make(color, coverage, inverted, SkMatrix::I());
}
Esempio n. 21
0
// Draw a mask using the supplied paint. Since the coverage/geometry
// is already burnt into the mask this boils down to a rect draw.
// Return true if the mask was successfully drawn.
static bool draw_mask(GrDrawContext* drawContext,
                      const GrClip& clip,
                      const SkMatrix& viewMatrix,
                      const SkIRect& maskRect,
                      GrPaint* grp,
                      GrTexture* mask) {
    SkMatrix matrix;
    matrix.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop));
    matrix.postIDiv(mask->width(), mask->height());
    matrix.preConcat(viewMatrix);
    grp->addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(mask, nullptr, matrix));

    SkMatrix inverse;
    if (!viewMatrix.invert(&inverse)) {
        return false;
    }
    drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), SkRect::Make(maskRect),
                                         inverse);
    return true;
}
Esempio n. 22
0
    WarpView() {
        SkBitmap bm;
//        SkImageDecoder::DecodeFile("/skimages/marker.png", &bm);
        SkImageDecoder::DecodeFile("/skimages/logo.gif", &bm);
   //     SkImageDecoder::DecodeFile("/beach_shot.JPG", &bm);
        fBitmap = bm;

        SkRect bounds, texture;
        texture.set(0, 0, SkIntToScalar(fBitmap.width()),
                    SkIntToScalar(fBitmap.height()));
        bounds = texture;

//        fMesh.init(bounds, fBitmap.width() / 40, fBitmap.height() / 40, texture);
        fMesh.init(bounds, fBitmap.width()/16, fBitmap.height()/16, texture);
        fOrig = fMesh;

        fP0.set(0, 0);
        fP1 = fP0;

        fMatrix.setScale(2, 2);
        fMatrix.invert(&fInverse);
    }
Esempio n. 23
0
void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
                                              GrDrawContext* drawContext,
                                              const GrPaint* paint,
                                              const GrUserStencilSettings* userStencilSettings,
                                              const GrClip& clip,
                                              GrColor color,
                                              const SkMatrix& viewMatrix,
                                              const SkIRect& rect) {
    SkMatrix invert;
    if (!viewMatrix.invert(&invert)) {
        return;
    }

    SkRect dstRect = SkRect::MakeLTRB(SK_Scalar1 * rect.fLeft,
                                      SK_Scalar1 * rect.fTop,
                                      SK_Scalar1 * rect.fRight,
                                      SK_Scalar1 * rect.fBottom);

    // We use device coords to compute the texture coordinates. We take the device coords and apply
    // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling
    // matrix to normalized coords.
    SkMatrix maskMatrix;
    maskMatrix.setIDiv(texture->width(), texture->height());
    maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop));

    GrPipelineBuilder pipelineBuilder(*paint, drawContext->isUnifiedMultisampled());
    pipelineBuilder.setRenderTarget(drawContext->accessRenderTarget());
    pipelineBuilder.setUserStencil(userStencilSettings);

    pipelineBuilder.addCoverageFragmentProcessor(
                         GrSimpleTextureEffect::Create(texture,
                                                       maskMatrix,
                                                       GrTextureParams::kNone_FilterMode,
                                                       kDevice_GrCoordSet))->unref();

    SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(),
                                                                        dstRect, nullptr, &invert));
    drawContext->drawBatch(pipelineBuilder, clip, batch);
}
Esempio n. 24
0
void GrSoftwarePathRenderer::DrawAroundInvPath(GrDrawContext* drawContext,
                                               const GrPaint* paint,
                                               const GrUserStencilSettings* userStencilSettings,
                                               const GrClip& clip,
                                               GrColor color,
                                               const SkMatrix& viewMatrix,
                                               const SkIRect& devClipBounds,
                                               const SkIRect& devPathBounds) {
    SkMatrix invert;
    if (!viewMatrix.invert(&invert)) {
        return;
    }

    SkRect rect;
    if (devClipBounds.fTop < devPathBounds.fTop) {
        rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
                  devClipBounds.fRight, devPathBounds.fTop);
        DrawNonAARect(drawContext, paint, userStencilSettings, clip, color,
                      SkMatrix::I(), rect, invert);
    }
    if (devClipBounds.fLeft < devPathBounds.fLeft) {
        rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
                  devPathBounds.fLeft, devPathBounds.fBottom);
        DrawNonAARect(drawContext, paint, userStencilSettings, clip, color,
                      SkMatrix::I(), rect, invert);
    }
    if (devClipBounds.fRight > devPathBounds.fRight) {
        rect.iset(devPathBounds.fRight, devPathBounds.fTop,
                  devClipBounds.fRight, devPathBounds.fBottom);
        DrawNonAARect(drawContext, paint, userStencilSettings, clip, color,
                      SkMatrix::I(), rect, invert);
    }
    if (devClipBounds.fBottom > devPathBounds.fBottom) {
        rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
                  devClipBounds.fRight, devClipBounds.fBottom);
        DrawNonAARect(drawContext, paint, userStencilSettings, clip, color,
                      SkMatrix::I(), rect, invert);
    }
}
Esempio n. 25
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;
}
// This test case including path coords and matrix taken from crbug.com/627443.
// Because of inaccuracies in large floating point values this causes the
// the path renderer to attempt to add a path DF to its atlas that is larger
// than the plot size which used to crash rather than fail gracefully.
static void test_far_from_origin(GrDrawContext* drawContext, GrPathRenderer* pr,
                                 GrResourceProvider* rp) {
    SkPath path;
    path.lineTo(49.0255089839f, 0.473541f);
    static constexpr SkScalar mvals[] = {14.0348252854f, 2.13026182736f,
                                         13.6122547187f, 118.309922702f,
                                         1912337682.09f, 2105391889.87f};
    SkMatrix matrix;
    matrix.setAffine(mvals);
    SkMatrix inverse;
    SkAssertResult(matrix.invert(&inverse));
    path.transform(inverse);

    SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
    rec.setStrokeStyle(1.f);
    rec.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 1.f);
    GrStyle style(rec, nullptr);

    GrShape shape(path, style);
    shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, 1.f);

    GrPaint paint;
    paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));

    GrNoClip noClip;
    GrPathRenderer::DrawPathArgs args;
    args.fPaint = &paint;
    args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
    args.fDrawContext = drawContext;
    args.fClip = &noClip;
    args.fResourceProvider = rp;
    args.fViewMatrix = &matrix;
    args.fShape = &shape;
    args.fAntiAlias = true;
    args.fGammaCorrect = false;
    args.fColor = 0x0;
    pr->drawPath(args);
}
Esempio n. 27
0
static void testinvert() {
    SkMatrix matrix;

    const float vals[] = { 0,9,.000001,10000,0,0 };
    setmatrix6(&matrix, vals);

    const float vals2[] = { 0,100,71,9,0,7 };
    SkMatrix tmp;
    setmatrix6(&tmp, vals2);
    
    matrix.preConcat(tmp);
    matrix.dump();

    SkMatrix inverse;
    matrix.invert(&inverse);
    inverse.dump();
    
    matrix.preConcat(inverse);
    matrix.dump();

//    o2dContext.setTransform(0,9,.000001,10000,0,0);
//    o2dContext.transform(0,100,71,9,0,7);
//    o2dContext.setTransform(0,6,95,4,1,0);
}
// Attempt to trim the line to minimally cover the cull rect (currently
// only works for horizontal and vertical lines).
// Return true if processing should continue; false otherwise.
static bool cull_line(SkPoint* pts, const SkStrokeRec& rec,
                      const SkMatrix& ctm, const SkRect* cullRect,
                      const SkScalar intervalLength) {
    if (nullptr == cullRect) {
        SkASSERT(false); // Shouldn't ever occur in practice
        return false;
    }

    SkScalar dx = pts[1].x() - pts[0].x();
    SkScalar dy = pts[1].y() - pts[0].y();

    if ((dx && dy) || (!dx && !dy)) {
        return false;
    }

    SkRect bounds = *cullRect;
    outset_for_stroke(&bounds, rec);

    // cullRect is in device space while pts are in the local coordinate system
    // defined by the ctm. We want our answer in the local coordinate system.

    SkASSERT(ctm.rectStaysRect());
    SkMatrix inv;
    if (!ctm.invert(&inv)) {
        return false;
    }

    inv.mapRect(&bounds);

    if (dx) {
        SkASSERT(dx && !dy);
        SkScalar minX = pts[0].fX;
        SkScalar maxX = pts[1].fX;

        if (dx < 0) {
            SkTSwap(minX, maxX);
        }

        SkASSERT(minX < maxX);
        if (maxX <= bounds.fLeft || minX >= bounds.fRight) {
            return false;
        }

        // Now we actually perform the chop, removing the excess to the left and
        // right of the bounds (keeping our new line "in phase" with the dash,
        // hence the (mod intervalLength).

        if (minX < bounds.fLeft) {
            minX = bounds.fLeft - SkScalarMod(bounds.fLeft - minX, intervalLength);
        }
        if (maxX > bounds.fRight) {
            maxX = bounds.fRight + SkScalarMod(maxX - bounds.fRight, intervalLength);
        }

        SkASSERT(maxX > minX);
        if (dx < 0) {
            SkTSwap(minX, maxX);
        }
        pts[0].fX = minX;
        pts[1].fX = maxX;
    } else {
        SkASSERT(dy && !dx);
        SkScalar minY = pts[0].fY;
        SkScalar maxY = pts[1].fY;

        if (dy < 0) {
            SkTSwap(minY, maxY);
        }

        SkASSERT(minY < maxY);
        if (maxY <= bounds.fTop || minY >= bounds.fBottom) {
            return false;
        }

        // Now we actually perform the chop, removing the excess to the top and
        // bottom of the bounds (keeping our new line "in phase" with the dash,
        // hence the (mod intervalLength).

        if (minY < bounds.fTop) {
            minY = bounds.fTop - SkScalarMod(bounds.fTop - minY, intervalLength);
        }
        if (maxY > bounds.fBottom) {
            maxY = bounds.fBottom + SkScalarMod(maxY - bounds.fBottom, intervalLength);
        }

        SkASSERT(maxY > minY);
        if (dy < 0) {
            SkTSwap(minY, maxY);
        }
        pts[0].fY = minY;
        pts[1].fY = maxY;
    }

    return true;
}
Esempio n. 29
0
void GrBitmapTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
                                     const GrPaint& paint, const SkPaint& skPaint,
                                     const SkMatrix& viewMatrix,
                                     const char text[], size_t byteLength,
                                     SkScalar x, SkScalar y) {
    SkASSERT(byteLength == 0 || text != NULL);

    // nothing to draw
    if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
        return;
    }

    this->init(rt, clip, paint, skPaint);

    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();

    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, &viewMatrix);
    SkGlyphCache*       cache = autoCache.getCache();
    GrFontScaler*       fontScaler = GetGrFontScaler(cache);

    // transform our starting point
    {
        SkPoint loc;
        viewMatrix.mapXY(x, y, &loc);
        x = loc.fX;
        y = loc.fY;
    }

    // need to measure first
    int numGlyphs;
    if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
        SkVector    stopVector;
        numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector);

        SkScalar    stopX = stopVector.fX;
        SkScalar    stopY = stopVector.fY;

        if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
            stopX = SkScalarHalf(stopX);
            stopY = SkScalarHalf(stopY);
        }
        x -= stopX;
        y -= stopY;
    } else {
        numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
    }
    fTotalVertexCount = kVerticesPerGlyph*numGlyphs;

    const char* stop = text + byteLength;

    SkAutoKern autokern;

    SkFixed fxMask = ~0;
    SkFixed fyMask = ~0;
    SkScalar halfSampleX, halfSampleY;
    if (cache->isSubpixel()) {
        halfSampleX = halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
        if (kX_SkAxisAlignment == baseline) {
            fyMask = 0;
            halfSampleY = SK_ScalarHalf;
        } else if (kY_SkAxisAlignment == baseline) {
            fxMask = 0;
            halfSampleX = SK_ScalarHalf;
        }
    } else {
        halfSampleX = halfSampleY = SK_ScalarHalf;
    }

    Sk48Dot16 fx = SkScalarTo48Dot16(x + halfSampleX);
    Sk48Dot16 fy = SkScalarTo48Dot16(y + halfSampleY);

    // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix, but for
    // performance reasons we just invert here instead
    if (!viewMatrix.invert(&fLocalMatrix)) {
        SkDebugf("Cannot invert viewmatrix\n");
        return;
    }

    while (text < stop) {
        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);

        fx += autokern.adjust(glyph);

        if (glyph.fWidth) {
            this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
                                            glyph.getSubXFixed(),
                                            glyph.getSubYFixed(),
                                            GrGlyph::kCoverage_MaskStyle),
                              Sk48Dot16FloorToInt(fx),
                              Sk48Dot16FloorToInt(fy),
                              fontScaler);
        }

        fx += glyph.fAdvanceX;
        fy += glyph.fAdvanceY;
    }

    this->finish();
}
Esempio n. 30
0
void GrBitmapTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
                                        const GrPaint& paint, const SkPaint& skPaint,
                                        const SkMatrix& viewMatrix,
                                        const char text[], size_t byteLength,
                                        const SkScalar pos[], int scalarsPerPosition,
                                        const SkPoint& offset) {
    SkASSERT(byteLength == 0 || text != NULL);
    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);

    // nothing to draw
    if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
        return;
    }

    this->init(rt, clip, paint, skPaint);

    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();

    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, &viewMatrix);
    SkGlyphCache*       cache = autoCache.getCache();
    GrFontScaler*       fontScaler = GetGrFontScaler(cache);

    // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix, but for
    // performance reasons we just invert here instead
    if (!viewMatrix.invert(&fLocalMatrix)) {
        SkDebugf("Cannot invert viewmatrix\n");
        return;
    }

    int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
    fTotalVertexCount = kVerticesPerGlyph*numGlyphs;

    const char*        stop = text + byteLength;
    SkTextAlignProc    alignProc(fSkPaint.getTextAlign());
    SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition);
    SkScalar halfSampleX = 0, halfSampleY = 0;

    if (cache->isSubpixel()) {
        // maybe we should skip the rounding if linearText is set
        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);

        SkFixed fxMask = ~0;
        SkFixed fyMask = ~0;
        if (kX_SkAxisAlignment == baseline) {
            fyMask = 0;
            halfSampleY = SK_ScalarHalf;
        } else if (kY_SkAxisAlignment == baseline) {
            fxMask = 0;
            halfSampleX = SK_ScalarHalf;
        }

        if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
            while (text < stop) {
                SkPoint tmsLoc;
                tmsProc(pos, &tmsLoc);
                Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + halfSampleX);
                Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + halfSampleY);

                const SkGlyph& glyph = glyphCacheProc(cache, &text,
                                                      fx & fxMask, fy & fyMask);

                if (glyph.fWidth) {
                    this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
                                                    glyph.getSubXFixed(),
                                                    glyph.getSubYFixed(),
                                                    GrGlyph::kCoverage_MaskStyle),
                                      Sk48Dot16FloorToInt(fx),
                                      Sk48Dot16FloorToInt(fy),
                                      fontScaler);
                }
                pos += scalarsPerPosition;
            }
        } else {
            while (text < stop) {
                const char* currentText = text;
                const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);

                if (metricGlyph.fWidth) {
                    SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
                    SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
                    SkPoint tmsLoc;
                    tmsProc(pos, &tmsLoc);
                    SkPoint alignLoc;
                    alignProc(tmsLoc, metricGlyph, &alignLoc);

                    Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + halfSampleX);
                    Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + halfSampleY);

                    // have to call again, now that we've been "aligned"
                    const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
                                                          fx & fxMask, fy & fyMask);
                    // the assumption is that the metrics haven't changed
                    SkASSERT(prevAdvX == glyph.fAdvanceX);
                    SkASSERT(prevAdvY == glyph.fAdvanceY);
                    SkASSERT(glyph.fWidth);

                    this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
                                                    glyph.getSubXFixed(),
                                                    glyph.getSubYFixed(),
                                                    GrGlyph::kCoverage_MaskStyle),
                                      Sk48Dot16FloorToInt(fx),
                                      Sk48Dot16FloorToInt(fy),
                                      fontScaler);
                }