1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkTextMapStateProc_DEFINED
9#define SkTextMapStateProc_DEFINED
10
11#include "SkPoint.h"
12#include "SkMatrixPriv.h"
13
14class SkTextMapStateProc {
15public:
16    SkTextMapStateProc(const SkMatrix& matrix, const SkPoint& offset, int scalarsPerPosition)
17        : fMatrix(matrix)
18        , fProc(SkMatrixPriv::GetMapXYProc(matrix))
19        , fOffset(offset)
20        , fScaleX(fMatrix.getScaleX()) {
21        SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
22        if (1 == scalarsPerPosition) {
23            unsigned mtype = fMatrix.getType();
24            if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
25                fMapCase = kX;
26            } else {
27                // Bake the matrix scale/translation components into fOffset,
28                // to expedite proc computations.
29                fOffset.set(offset.x() * fMatrix.getScaleX() + fMatrix.getTranslateX(),
30                            offset.y() * fMatrix.getScaleY() + fMatrix.getTranslateY());
31
32                if (mtype & SkMatrix::kScale_Mask) {
33                    fMapCase = kOnlyScaleX;
34                } else {
35                    fMapCase = kOnlyTransX;
36                }
37            }
38        } else {
39            fMapCase = kXY;
40        }
41    }
42
43    void operator()(const SkScalar pos[], SkPoint* loc) const;
44
45private:
46    const SkMatrix& fMatrix;
47    enum {
48        kXY,
49        kOnlyScaleX,
50        kOnlyTransX,
51        kX
52    } fMapCase;
53    const SkMatrixPriv::MapXYProc fProc;
54    SkPoint  fOffset; // In kOnly* mode, this includes the matrix translation component.
55    SkScalar fScaleX; // This is only used by kOnly... cases.
56};
57
58inline void SkTextMapStateProc::operator()(const SkScalar pos[], SkPoint* loc) const {
59    switch(fMapCase) {
60    case kXY:
61        fProc(fMatrix, pos[0] + fOffset.x(), pos[1] + fOffset.y(), loc);
62        break;
63    case kOnlyScaleX:
64        loc->set(fScaleX * *pos + fOffset.x(), fOffset.y());
65        break;
66    case kOnlyTransX:
67        loc->set(*pos + fOffset.x(), fOffset.y());
68        break;
69    default:
70        SkASSERT(false);
71    case kX:
72        fProc(fMatrix, *pos + fOffset.x(), fOffset.y(), loc);
73        break;
74    }
75}
76
77#endif
78