1d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com/*
2d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com * Copyright 2013 Google Inc.
3d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com *
4d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com * Use of this source code is governed by a BSD-style license that can be
5d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com * found in the LICENSE file.
6d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com */
7d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
8d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#ifndef SkBitmapProcState_MatrixTemplates_DEFINED
9d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#define SkBitmapProcState_MatrixTemplates_DEFINED
10d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
11d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#include "SkMath.h"
12d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#include "SkMathPriv.h"
13d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
14d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comtemplate <typename TileProc, bool tryDecal>
15d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid NoFilterProc_Scale(const SkBitmapProcState& s, uint32_t xy[],
16d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                        int count, int x, int y) {
17d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
18d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                             SkMatrix::kScale_Mask)) == 0);
19d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
20d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    // we store y, x, x, x, x, x
21d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
22d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    const unsigned maxX = s.fBitmap->width() - 1;
23d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt fx;
24d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    {
25d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        SkPoint pt;
26d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
27d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                                  SkIntToScalar(y) + SK_ScalarHalf, &pt);
28d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        fx = SkScalarToFractionalInt(pt.fY);
29d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        const unsigned maxY = s.fBitmap->height() - 1;
30d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        *xy++ = TileProc::Y(s, SkFractionalIntToFixed(fx), maxY);
31d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        fx = SkScalarToFractionalInt(pt.fX);
32d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
33d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
34d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (0 == maxX) {
35d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        // all of the following X values must be 0
36d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        memset(xy, 0, count * sizeof(uint16_t));
37d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        return;
38d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
39d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
40d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    const SkFractionalInt dx = s.fInvSxFractionalInt;
41d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
42d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (tryDecal && can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
43d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        decal_nofilter_scale(xy, SkFractionalIntToFixed(fx),
44d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                             SkFractionalIntToFixed(dx), count);
45d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    } else {
46d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        int i;
47d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        for (i = (count >> 2); i > 0; --i) {
48d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            unsigned a, b;
49d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
50d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
51d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#ifdef SK_CPU_BENDIAN
52d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            *xy++ = (a << 16) | b;
53d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#else
54d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            *xy++ = (b << 16) | a;
55d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#endif
56d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
57d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
58d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#ifdef SK_CPU_BENDIAN
59d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            *xy++ = (a << 16) | b;
60d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#else
61d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            *xy++ = (b << 16) | a;
62d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#endif
63d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        }
64d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        uint16_t* xx = (uint16_t*)xy;
65d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        for (i = (count & 3); i > 0; --i) {
66d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            *xx++ = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
67d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        }
68d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
69d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
70d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
71d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com// note: we could special-case on a matrix which is skewed in X but not Y.
72d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com// this would require a more general setup thatn SCALE does, but could use
73d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com// SCALE's inner loop that only looks at dx
74d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
75d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comtemplate <typename TileProc>
76d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[],
77d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                         int count, int x, int y) {
78d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
79d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
80d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                             SkMatrix::kScale_Mask |
81d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                             SkMatrix::kAffine_Mask)) == 0);
82d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
83d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkPoint srcPt;
84d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    s.fInvProc(s.fInvMatrix,
85d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com               SkIntToScalar(x) + SK_ScalarHalf,
86d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com               SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
87d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
88d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX);
89d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY);
90d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt dx = s.fInvSxFractionalInt;
91d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt dy = s.fInvKyFractionalInt;
92d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    int maxX = s.fBitmap->width() - 1;
93d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    int maxY = s.fBitmap->height() - 1;
94d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
95d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    for (int i = count; i > 0; --i) {
96d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        *xy++ = (TileProc::Y(s, SkFractionalIntToFixed(fy), maxY) << 16) |
97d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                 TileProc::X(s, SkFractionalIntToFixed(fx), maxX);
98d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        fx += dx; fy += dy;
99d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
100d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
101d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
102d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comtemplate <typename TileProc>
103d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid NoFilterProc_Persp(const SkBitmapProcState& s, uint32_t* SK_RESTRICT xy,
104d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                        int count, int x, int y) {
105d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
106d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
107d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    int maxX = s.fBitmap->width() - 1;
108d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    int maxY = s.fBitmap->height() - 1;
109d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
110d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkPerspIter   iter(s.fInvMatrix,
111d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                       SkIntToScalar(x) + SK_ScalarHalf,
112d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                       SkIntToScalar(y) + SK_ScalarHalf, count);
113d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
114d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    while ((count = iter.next()) != 0) {
115d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        const SkFixed* SK_RESTRICT srcXY = iter.getXY();
116d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        while (--count >= 0) {
117d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            *xy++ = (TileProc::Y(s, srcXY[1], maxY) << 16) |
118d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                     TileProc::X(s, srcXY[0], maxX);
119d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            srcXY += 2;
120d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        }
121d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
122d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
123d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
124d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#endif
125