Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2016 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 SkMatrixPriv_DEFINE
      9 #define SkMatrixPriv_DEFINE
     10 
     11 #include "SkMatrix.h"
     12 #include "SkNx.h"
     13 #include "SkPointPriv.h"
     14 
     15 class SkMatrixPriv {
     16 public:
     17     enum {
     18         // writeTo/readFromMemory will never return a value larger than this
     19         kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t),
     20     };
     21 
     22     static size_t WriteToMemory(const SkMatrix& matrix, void* buffer) {
     23         return matrix.writeToMemory(buffer);
     24     }
     25 
     26     static size_t ReadFromMemory(SkMatrix* matrix, const void* buffer, size_t length) {
     27         return matrix->readFromMemory(buffer, length);
     28     }
     29 
     30     typedef SkMatrix::MapXYProc MapXYProc;
     31     typedef SkMatrix::MapPtsProc MapPtsProc;
     32 
     33 
     34     static MapPtsProc GetMapPtsProc(const SkMatrix& matrix) {
     35         return SkMatrix::GetMapPtsProc(matrix.getType());
     36     }
     37 
     38     static MapXYProc GetMapXYProc(const SkMatrix& matrix) {
     39         return SkMatrix::GetMapXYProc(matrix.getType());
     40     }
     41 
     42     /**
     43      *  Attempt to map the rect through the inverse of the matrix. If it is not invertible,
     44      *  then this returns false and dst is unchanged.
     45      */
     46     static bool SK_WARN_UNUSED_RESULT InverseMapRect(const SkMatrix& mx,
     47                                                      SkRect* dst, const SkRect& src) {
     48         if (mx.getType() <= SkMatrix::kTranslate_Mask) {
     49             SkScalar tx = mx.getTranslateX();
     50             SkScalar ty = mx.getTranslateY();
     51             Sk4f trans(tx, ty, tx, ty);
     52             (Sk4f::Load(&src.fLeft) - trans).store(&dst->fLeft);
     53             return true;
     54         }
     55         // Insert other special-cases here (e.g. scale+translate)
     56 
     57         // general case
     58         SkMatrix inverse;
     59         if (mx.invert(&inverse)) {
     60             inverse.mapRect(dst, src);
     61             return true;
     62         }
     63         return false;
     64     }
     65 
     66     /** Maps count pts, skipping stride bytes to advance from one SkPoint to the next.
     67         Points are mapped by multiplying each SkPoint by SkMatrix. Given:
     68 
     69                      | A B C |        | x |
     70             Matrix = | D E F |,  pt = | y |
     71                      | G H I |        | 1 |
     72 
     73         each resulting pts SkPoint is computed as:
     74 
     75                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
     76             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
     77                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
     78 
     79         @param mx      matrix used to map the points
     80         @param pts     storage for mapped points
     81         @param stride  size of record starting with SkPoint, in bytes
     82         @param count   number of points to transform
     83     */
     84     static void MapPointsWithStride(const SkMatrix& mx, SkPoint pts[], size_t stride, int count) {
     85         SkASSERT(stride >= sizeof(SkPoint));
     86         SkASSERT(0 == stride % sizeof(SkScalar));
     87 
     88         SkMatrix::TypeMask tm = mx.getType();
     89 
     90         if (SkMatrix::kIdentity_Mask == tm) {
     91             return;
     92         }
     93         if (SkMatrix::kTranslate_Mask == tm) {
     94             const SkScalar tx = mx.getTranslateX();
     95             const SkScalar ty = mx.getTranslateY();
     96             Sk2s trans(tx, ty);
     97             for (int i = 0; i < count; ++i) {
     98                 (Sk2s::Load(&pts->fX) + trans).store(&pts->fX);
     99                 pts = (SkPoint*)((intptr_t)pts + stride);
    100             }
    101             return;
    102         }
    103         // Insert other special-cases here (e.g. scale+translate)
    104 
    105         // general case
    106         SkMatrix::MapXYProc proc = mx.getMapXYProc();
    107         for (int i = 0; i < count; ++i) {
    108             proc(mx, pts->fX, pts->fY, pts);
    109             pts = (SkPoint*)((intptr_t)pts + stride);
    110         }
    111     }
    112 
    113     /** Maps src SkPoint array of length count to dst SkPoint array, skipping stride bytes
    114         to advance from one SkPoint to the next.
    115         Points are mapped by multiplying each SkPoint by SkMatrix. Given:
    116 
    117                      | A B C |         | x |
    118             Matrix = | D E F |,  src = | y |
    119                      | G H I |         | 1 |
    120 
    121         each resulting dst SkPoint is computed as:
    122 
    123                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
    124             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
    125                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
    126 
    127         @param mx      matrix used to map the points
    128         @param dst     storage for mapped points
    129         @param src     points to transform
    130         @param stride  size of record starting with SkPoint, in bytes
    131         @param count   number of points to transform
    132     */
    133     static void MapPointsWithStride(const SkMatrix& mx, SkPoint dst[], size_t dstStride,
    134                                     const SkPoint src[], size_t srcStride, int count) {
    135         SkASSERT(srcStride >= sizeof(SkPoint));
    136         SkASSERT(dstStride >= sizeof(SkPoint));
    137         SkASSERT(0 == srcStride % sizeof(SkScalar));
    138         SkASSERT(0 == dstStride % sizeof(SkScalar));
    139         for (int i = 0; i < count; ++i) {
    140             mx.mapPoints(dst, src, 1);
    141             src = (SkPoint*)((intptr_t)src + srcStride);
    142             dst = (SkPoint*)((intptr_t)dst + dstStride);
    143         }
    144     }
    145 
    146     static void MapHomogeneousPointsWithStride(const SkMatrix& mx, SkPoint3 dst[], size_t dstStride,
    147                                                const SkPoint3 src[], size_t srcStride, int count);
    148 
    149     static void SetMappedRectTriStrip(const SkMatrix& mx, const SkRect& rect, SkPoint quad[4]) {
    150         SkMatrix::TypeMask tm = mx.getType();
    151         SkScalar l = rect.fLeft;
    152         SkScalar t = rect.fTop;
    153         SkScalar r = rect.fRight;
    154         SkScalar b = rect.fBottom;
    155         if (tm <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
    156             const SkScalar tx = mx.getTranslateX();
    157             const SkScalar ty = mx.getTranslateY();
    158             if (tm <= SkMatrix::kTranslate_Mask) {
    159                 l += tx;
    160                 t += ty;
    161                 r += tx;
    162                 b += ty;
    163             } else {
    164                 const SkScalar sx = mx.getScaleX();
    165                 const SkScalar sy = mx.getScaleY();
    166                 l = sx * l + tx;
    167                 t = sy * t + ty;
    168                 r = sx * r + tx;
    169                 b = sy * b + ty;
    170             }
    171            SkPointPriv::SetRectTriStrip(quad, l, t, r, b, sizeof(SkPoint));
    172         } else {
    173             SkPointPriv::SetRectTriStrip(quad, l, t, r, b, sizeof(SkPoint));
    174             mx.mapPoints(quad, quad, 4);
    175         }
    176     }
    177 };
    178 
    179 #endif
    180