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
22ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    const unsigned maxX = s.fPixmap.width() - 1;
23d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt fx;
24d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    {
25b3a835891cf221bdf4c6eeb4cf404b374955015ffmalita        const SkBitmapProcStateAutoMapper mapper(s, x, y);
26ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed        const unsigned maxY = s.fPixmap.height() - 1;
27be5cfa9a9e1cfb77beba27727df7149ab5e7d422fmalita        *xy++ = TileProc::Y(s, mapper.fixedY(), maxY);
28be5cfa9a9e1cfb77beba27727df7149ab5e7d422fmalita        fx = mapper.fractionalIntX();
29d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
30d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
31d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (0 == maxX) {
32d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        // all of the following X values must be 0
33d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        memset(xy, 0, count * sizeof(uint16_t));
34d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        return;
35d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
36d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
37d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    const SkFractionalInt dx = s.fInvSxFractionalInt;
38d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
399953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita    if (tryDecal) {
409953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        const SkFixed fixedFx = SkFractionalIntToFixed(fx);
419953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        const SkFixed fixedDx = SkFractionalIntToFixed(dx);
429953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita
439953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        if (can_truncate_to_fixed_for_decal(fixedFx, fixedDx, count, maxX)) {
449953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita            decal_nofilter_scale(xy, fixedFx, fixedDx, count);
459953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita            return;
469953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        }
479953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita    }
489953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita
499953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita    int i;
509953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita    for (i = (count >> 2); i > 0; --i) {
519953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        unsigned a, b;
529953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
539953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
54d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#ifdef SK_CPU_BENDIAN
559953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        *xy++ = (a << 16) | b;
56d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#else
579953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        *xy++ = (b << 16) | a;
58d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#endif
599953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
609953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
61d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#ifdef SK_CPU_BENDIAN
629953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        *xy++ = (a << 16) | b;
63d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#else
649953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        *xy++ = (b << 16) | a;
65d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#endif
669953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita    }
679953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita    uint16_t* xx = (uint16_t*)xy;
689953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita    for (i = (count & 3); i > 0; --i) {
699953737bcf885a52c08ade6c503f2202e4dd9aa5Florin Malita        *xx++ = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
70d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
71d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
72d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
73d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com// note: we could special-case on a matrix which is skewed in X but not Y.
74d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com// this would require a more general setup thatn SCALE does, but could use
75d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com// SCALE's inner loop that only looks at dx
76d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
77d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comtemplate <typename TileProc>
78d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[],
79d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                         int count, int x, int y) {
80d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
81d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
82d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                             SkMatrix::kScale_Mask |
83d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                             SkMatrix::kAffine_Mask)) == 0);
84d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
85b3a835891cf221bdf4c6eeb4cf404b374955015ffmalita    const SkBitmapProcStateAutoMapper mapper(s, x, y);
863e6be16e6d4dda6a27f0e1dbfe7c87fecfbf5577fmalita
87be5cfa9a9e1cfb77beba27727df7149ab5e7d422fmalita    SkFractionalInt fx = mapper.fractionalIntX();
88be5cfa9a9e1cfb77beba27727df7149ab5e7d422fmalita    SkFractionalInt fy = mapper.fractionalIntY();
89d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt dx = s.fInvSxFractionalInt;
90d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkFractionalInt dy = s.fInvKyFractionalInt;
91ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    int maxX = s.fPixmap.width() - 1;
92ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    int maxY = s.fPixmap.height() - 1;
93d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
94d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    for (int i = count; i > 0; --i) {
95d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        *xy++ = (TileProc::Y(s, SkFractionalIntToFixed(fy), maxY) << 16) |
96d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                 TileProc::X(s, SkFractionalIntToFixed(fx), maxX);
97d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        fx += dx; fy += dy;
98d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
99d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
100d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
101d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comtemplate <typename TileProc>
102d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid NoFilterProc_Persp(const SkBitmapProcState& s, uint32_t* SK_RESTRICT xy,
103d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                        int count, int x, int y) {
104d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
105d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
106ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    int maxX = s.fPixmap.width() - 1;
107ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    int maxY = s.fPixmap.height() - 1;
108d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
109d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    SkPerspIter   iter(s.fInvMatrix,
110d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                       SkIntToScalar(x) + SK_ScalarHalf,
111d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                       SkIntToScalar(y) + SK_ScalarHalf, count);
112d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
113d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    while ((count = iter.next()) != 0) {
114d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        const SkFixed* SK_RESTRICT srcXY = iter.getXY();
115d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        while (--count >= 0) {
116d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            *xy++ = (TileProc::Y(s, srcXY[1], maxY) << 16) |
117d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                     TileProc::X(s, srcXY[0], maxX);
118d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com            srcXY += 2;
119d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        }
120d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
121d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
122d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
123d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#endif
124