1a39667c848146d9070e1a45662fb292d8e6bb8fbreed/*
2a39667c848146d9070e1a45662fb292d8e6bb8fbreed * Copyright 2016 Google Inc.
3a39667c848146d9070e1a45662fb292d8e6bb8fbreed *
4a39667c848146d9070e1a45662fb292d8e6bb8fbreed * Use of this source code is governed by a BSD-style license that can be
5a39667c848146d9070e1a45662fb292d8e6bb8fbreed * found in the LICENSE file.
6a39667c848146d9070e1a45662fb292d8e6bb8fbreed */
7a39667c848146d9070e1a45662fb292d8e6bb8fbreed
8a39667c848146d9070e1a45662fb292d8e6bb8fbreed#ifndef SkMatrixPriv_DEFINE
9a39667c848146d9070e1a45662fb292d8e6bb8fbreed#define SkMatrixPriv_DEFINE
10a39667c848146d9070e1a45662fb292d8e6bb8fbreed
11a39667c848146d9070e1a45662fb292d8e6bb8fbreed#include "SkMatrix.h"
12a39667c848146d9070e1a45662fb292d8e6bb8fbreed#include "SkNx.h"
13a39667c848146d9070e1a45662fb292d8e6bb8fbreed
14a39667c848146d9070e1a45662fb292d8e6bb8fbreedclass SkMatrixPriv {
15a39667c848146d9070e1a45662fb292d8e6bb8fbreedpublic:
16a39667c848146d9070e1a45662fb292d8e6bb8fbreed    /**
17a39667c848146d9070e1a45662fb292d8e6bb8fbreed     *  Attempt to map the rect through the inverse of the matrix. If it is not invertible,
18a39667c848146d9070e1a45662fb292d8e6bb8fbreed     *  then this returns false and dst is unchanged.
19a39667c848146d9070e1a45662fb292d8e6bb8fbreed     */
20a39667c848146d9070e1a45662fb292d8e6bb8fbreed    static bool SK_WARN_UNUSED_RESULT InverseMapRect(const SkMatrix& mx,
21a39667c848146d9070e1a45662fb292d8e6bb8fbreed                                                     SkRect* dst, const SkRect& src) {
22a39667c848146d9070e1a45662fb292d8e6bb8fbreed        if (mx.getType() <= SkMatrix::kTranslate_Mask) {
23a39667c848146d9070e1a45662fb292d8e6bb8fbreed            SkScalar tx = mx.getTranslateX();
24a39667c848146d9070e1a45662fb292d8e6bb8fbreed            SkScalar ty = mx.getTranslateY();
25a39667c848146d9070e1a45662fb292d8e6bb8fbreed            Sk4f trans(tx, ty, tx, ty);
26a39667c848146d9070e1a45662fb292d8e6bb8fbreed            (Sk4f::Load(&src.fLeft) - trans).store(&dst->fLeft);
27a39667c848146d9070e1a45662fb292d8e6bb8fbreed            return true;
28a39667c848146d9070e1a45662fb292d8e6bb8fbreed        }
29a39667c848146d9070e1a45662fb292d8e6bb8fbreed        // Insert other special-cases here (e.g. scale+translate)
30a39667c848146d9070e1a45662fb292d8e6bb8fbreed
31a39667c848146d9070e1a45662fb292d8e6bb8fbreed        // general case
32a39667c848146d9070e1a45662fb292d8e6bb8fbreed        SkMatrix inverse;
33a39667c848146d9070e1a45662fb292d8e6bb8fbreed        if (mx.invert(&inverse)) {
34a39667c848146d9070e1a45662fb292d8e6bb8fbreed            inverse.mapRect(dst, src);
35a39667c848146d9070e1a45662fb292d8e6bb8fbreed            return true;
36a39667c848146d9070e1a45662fb292d8e6bb8fbreed        }
37a39667c848146d9070e1a45662fb292d8e6bb8fbreed        return false;
38a39667c848146d9070e1a45662fb292d8e6bb8fbreed    }
39a39667c848146d9070e1a45662fb292d8e6bb8fbreed
40a39667c848146d9070e1a45662fb292d8e6bb8fbreed    static void MapPointsWithStride(const SkMatrix& mx, SkPoint pts[], size_t stride, int count) {
41a39667c848146d9070e1a45662fb292d8e6bb8fbreed        SkASSERT(stride >= sizeof(SkPoint));
42a39667c848146d9070e1a45662fb292d8e6bb8fbreed        SkASSERT(0 == stride % sizeof(SkScalar));
43a39667c848146d9070e1a45662fb292d8e6bb8fbreed
44a39667c848146d9070e1a45662fb292d8e6bb8fbreed        SkMatrix::TypeMask tm = mx.getType();
45a39667c848146d9070e1a45662fb292d8e6bb8fbreed
46a39667c848146d9070e1a45662fb292d8e6bb8fbreed        if (SkMatrix::kIdentity_Mask == tm) {
47a39667c848146d9070e1a45662fb292d8e6bb8fbreed            return;
48a39667c848146d9070e1a45662fb292d8e6bb8fbreed        }
49a39667c848146d9070e1a45662fb292d8e6bb8fbreed        if (SkMatrix::kTranslate_Mask == tm) {
50a39667c848146d9070e1a45662fb292d8e6bb8fbreed            const SkScalar tx = mx.getTranslateX();
51a39667c848146d9070e1a45662fb292d8e6bb8fbreed            const SkScalar ty = mx.getTranslateY();
52a39667c848146d9070e1a45662fb292d8e6bb8fbreed            Sk2s trans(tx, ty);
53a39667c848146d9070e1a45662fb292d8e6bb8fbreed            for (int i = 0; i < count; ++i) {
54a39667c848146d9070e1a45662fb292d8e6bb8fbreed                (Sk2s::Load(&pts->fX) + trans).store(&pts->fX);
55a39667c848146d9070e1a45662fb292d8e6bb8fbreed                pts = (SkPoint*)((intptr_t)pts + stride);
56a39667c848146d9070e1a45662fb292d8e6bb8fbreed            }
57a39667c848146d9070e1a45662fb292d8e6bb8fbreed            return;
58a39667c848146d9070e1a45662fb292d8e6bb8fbreed        }
59a39667c848146d9070e1a45662fb292d8e6bb8fbreed        // Insert other special-cases here (e.g. scale+translate)
60a39667c848146d9070e1a45662fb292d8e6bb8fbreed
61a39667c848146d9070e1a45662fb292d8e6bb8fbreed        // general case
62a39667c848146d9070e1a45662fb292d8e6bb8fbreed        SkMatrix::MapXYProc proc = mx.getMapXYProc();
63a39667c848146d9070e1a45662fb292d8e6bb8fbreed        for (int i = 0; i < count; ++i) {
64a39667c848146d9070e1a45662fb292d8e6bb8fbreed            proc(mx, pts->fX, pts->fY, pts);
65a39667c848146d9070e1a45662fb292d8e6bb8fbreed            pts = (SkPoint*)((intptr_t)pts + stride);
66a39667c848146d9070e1a45662fb292d8e6bb8fbreed        }
67a39667c848146d9070e1a45662fb292d8e6bb8fbreed    }
686a88206b2ece8b64534c87fca156e5fe161f884ereed
696a88206b2ece8b64534c87fca156e5fe161f884ereed    static void SetMappedRectFan(const SkMatrix& mx, const SkRect& rect, SkPoint quad[4]) {
706a88206b2ece8b64534c87fca156e5fe161f884ereed        SkMatrix::TypeMask tm = mx.getType();
716a88206b2ece8b64534c87fca156e5fe161f884ereed        SkScalar l = rect.fLeft;
726a88206b2ece8b64534c87fca156e5fe161f884ereed        SkScalar t = rect.fTop;
736a88206b2ece8b64534c87fca156e5fe161f884ereed        SkScalar r = rect.fRight;
746a88206b2ece8b64534c87fca156e5fe161f884ereed        SkScalar b = rect.fBottom;
756a88206b2ece8b64534c87fca156e5fe161f884ereed        if (tm <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
766a88206b2ece8b64534c87fca156e5fe161f884ereed            const SkScalar tx = mx.getTranslateX();
776a88206b2ece8b64534c87fca156e5fe161f884ereed            const SkScalar ty = mx.getTranslateY();
786a88206b2ece8b64534c87fca156e5fe161f884ereed            if (tm <= SkMatrix::kTranslate_Mask) {
796a88206b2ece8b64534c87fca156e5fe161f884ereed                l += tx;
806a88206b2ece8b64534c87fca156e5fe161f884ereed                t += ty;
816a88206b2ece8b64534c87fca156e5fe161f884ereed                r += tx;
826a88206b2ece8b64534c87fca156e5fe161f884ereed                b += ty;
836a88206b2ece8b64534c87fca156e5fe161f884ereed            } else {
846a88206b2ece8b64534c87fca156e5fe161f884ereed                const SkScalar sx = mx.getScaleX();
856a88206b2ece8b64534c87fca156e5fe161f884ereed                const SkScalar sy = mx.getScaleY();
866a88206b2ece8b64534c87fca156e5fe161f884ereed                l = sx * l + tx;
876a88206b2ece8b64534c87fca156e5fe161f884ereed                t = sy * t + ty;
886a88206b2ece8b64534c87fca156e5fe161f884ereed                r = sx * r + tx;
896a88206b2ece8b64534c87fca156e5fe161f884ereed                b = sy * b + ty;
906a88206b2ece8b64534c87fca156e5fe161f884ereed            }
916a88206b2ece8b64534c87fca156e5fe161f884ereed            quad[0].set(l, t);
926a88206b2ece8b64534c87fca156e5fe161f884ereed            quad[1].set(l, b);
936a88206b2ece8b64534c87fca156e5fe161f884ereed            quad[2].set(r, b);
946a88206b2ece8b64534c87fca156e5fe161f884ereed            quad[3].set(r, t);
956a88206b2ece8b64534c87fca156e5fe161f884ereed        } else {
966a88206b2ece8b64534c87fca156e5fe161f884ereed            quad[0].setRectFan(l, t, r, b);
976a88206b2ece8b64534c87fca156e5fe161f884ereed            mx.mapPoints(quad, quad, 4);
986a88206b2ece8b64534c87fca156e5fe161f884ereed        }
996a88206b2ece8b64534c87fca156e5fe161f884ereed    }
100a39667c848146d9070e1a45662fb292d8e6bb8fbreed};
101a39667c848146d9070e1a45662fb292d8e6bb8fbreed
102a39667c848146d9070e1a45662fb292d8e6bb8fbreed#endif
103