chromium/third_party/skia/src/core/SkMatrix.cpp

/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkMatrix.h"

#include "include/core/SkPath.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkMath.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkFloatBits.h"
#include "src/base/SkVx.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkMatrixUtils.h"
#include "src/core/SkSamplingPriv.h"

#include <algorithm>
#include <cmath>

void SkMatrix::doNormalizePerspective() {}

SkMatrix& SkMatrix::reset() {}

SkMatrix& SkMatrix::set9(const SkScalar buffer[9]) {}

SkMatrix& SkMatrix::setAffine(const SkScalar buffer[6]) {}

// this aligns with the masks, so we can compute a mask from a variable 0/1
enum {};

static const int32_t kScalar1Int =;

uint8_t SkMatrix::computePerspectiveTypeMask() const {}

uint8_t SkMatrix::computeTypeMask() const {}

///////////////////////////////////////////////////////////////////////////////

bool operator==(const SkMatrix& a, const SkMatrix& b) {}

///////////////////////////////////////////////////////////////////////////////

// helper function to determine if upper-left 2x2 of matrix is degenerate
static inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX,
                                     SkScalar skewY,  SkScalar scaleY) {}

///////////////////////////////////////////////////////////////////////////////

bool SkMatrix::isSimilarity(SkScalar tol) const {}

bool SkMatrix::preservesRightAngles(SkScalar tol) const {}

///////////////////////////////////////////////////////////////////////////////

static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {}

static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
                             SkScalar e, SkScalar f) {}

static inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {}

SkMatrix& SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {}

SkMatrix& SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {}

SkMatrix& SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {}

///////////////////////////////////////////////////////////////////////////////

SkMatrix& SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::setScale(SkScalar sx, SkScalar sy) {}

SkMatrix& SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::preScale(SkScalar sx, SkScalar sy) {}

SkMatrix& SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::postScale(SkScalar sx, SkScalar sy) {}

// this perhaps can go away, if we have a fract/high-precision way to
// scale matrices
bool SkMatrix::postIDiv(int divx, int divy) {}

////////////////////////////////////////////////////////////////////////////////////

SkMatrix& SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::setRSXform(const SkRSXform& xform) {}

SkMatrix& SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {}

SkMatrix& SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::setRotate(SkScalar degrees) {}

SkMatrix& SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::preRotate(SkScalar degrees) {}

SkMatrix& SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::postRotate(SkScalar degrees) {}

////////////////////////////////////////////////////////////////////////////////////

SkMatrix& SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::setSkew(SkScalar sx, SkScalar sy) {}

SkMatrix& SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::preSkew(SkScalar sx, SkScalar sy) {}

SkMatrix& SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {}

SkMatrix& SkMatrix::postSkew(SkScalar sx, SkScalar sy) {}

///////////////////////////////////////////////////////////////////////////////

bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit align) {}

///////////////////////////////////////////////////////////////////////////////

static inline float muladdmul(float a, float b, float c, float d) {}

static inline float rowcol3(const float row[], const float col[]) {}

static bool only_scale_and_translate(unsigned mask) {}

SkMatrix& SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {}

SkMatrix& SkMatrix::preConcat(const SkMatrix& mat) {}

SkMatrix& SkMatrix::postConcat(const SkMatrix& mat) {}

///////////////////////////////////////////////////////////////////////////////

/*  Matrix inversion is very expensive, but also the place where keeping
    precision may be most important (here and matrix concat). Hence to avoid
    bitmap blitting artifacts when walking the inverse, we use doubles for
    the intermediate math, even though we know that is more expensive.
 */

static inline SkScalar scross_dscale(SkScalar a, SkScalar b,
                                     SkScalar c, SkScalar d, double scale) {}

static inline double dcross(double a, double b, double c, double d) {}

static inline SkScalar dcross_dscale(double a, double b,
                                     double c, double d, double scale) {}

static double sk_determinant(const float mat[9], int isPerspective) {}

static double sk_inv_determinant(const float mat[9], int isPerspective) {}

void SkMatrix::SetAffineIdentity(SkScalar affine[6]) {}

bool SkMatrix::asAffine(SkScalar affine[6]) const {}

void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {}

void SkMatrix::mapXY(SkScalar x, SkScalar y, SkPoint* result) const {}

void SkMatrix::ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp) {}

bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {}

///////////////////////////////////////////////////////////////////////////////

void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {}

void SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {}

void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {}

void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
                         const SkPoint src[], int count) {}

void SkMatrix::Affine_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) {}

const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] =;

///////////////////////////////////////////////////////////////////////////////

void SkMatrixPriv::MapHomogeneousPointsWithStride(const SkMatrix& mx, SkPoint3 dst[],
                                                  size_t dstStride, const SkPoint3 src[],
                                                  size_t srcStride, int count) {}

void SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const {}

void SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint src[], int count) const {}

///////////////////////////////////////////////////////////////////////////////

void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {}

static skvx::float4 sort_as_rect(const skvx::float4& ltrb) {}

void SkMatrix::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const {}

bool SkMatrix::mapRect(SkRect* dst, const SkRect& src, SkApplyPerspectiveClip pc) const {}

SkScalar SkMatrix::mapRadius(SkScalar radius) const {}

///////////////////////////////////////////////////////////////////////////////

void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
                        SkPoint* pt) {}

void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
                           SkPoint* pt) {}

void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
                      SkPoint* pt) {}

void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
                             SkPoint* pt) {}

void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
                        SkPoint* pt) {}

void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
                        SkPoint* pt) {}

void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
                           SkPoint* pt) {}

const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] =;

///////////////////////////////////////////////////////////////////////////////
#if 0
// if its nearly zero (just made up 26, perhaps it should be bigger or smaller)
#define PerspNearlyZero

bool SkMatrix::isFixedStepInX() const {
  return PerspNearlyZero(fMat[kMPersp0]);
}

SkVector SkMatrix::fixedStepInX(SkScalar y) const {
    SkASSERT(PerspNearlyZero(fMat[kMPersp0]));
    if (PerspNearlyZero(fMat[kMPersp1]) &&
        PerspNearlyZero(fMat[kMPersp2] - 1)) {
        return SkVector::Make(fMat[kMScaleX], fMat[kMSkewY]);
    } else {
        SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2];
        return SkVector::Make(fMat[kMScaleX] / z, fMat[kMSkewY] / z);
    }
}
#endif

///////////////////////////////////////////////////////////////////////////////

static inline bool checkForZero(float x) {}

bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst) {}

bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst) {}

bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst) {}

PolyMapProc;

/*  Adapted from Rob Johnson's original sample code in QuickDraw GX
*/
bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count) {}

///////////////////////////////////////////////////////////////////////////////

enum MinMaxOrBoth {};

template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
                                                              const SkScalar m[9],
                                                              SkScalar results[/*1 or 2*/]) {}

SkScalar SkMatrix::getMinScale() const {}

SkScalar SkMatrix::getMaxScale() const {}

bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {}

const SkMatrix& SkMatrix::I() {}

const SkMatrix& SkMatrix::InvalidMatrix() {}

bool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const {}

///////////////////////////////////////////////////////////////////////////////

size_t SkMatrix::writeToMemory(void* buffer) const {}

size_t SkMatrix::readFromMemory(const void* buffer, size_t length) {}

void SkMatrix::dump() const {}

///////////////////////////////////////////////////////////////////////////////

bool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkSamplingOptions& sampling,
                     bool isAntiAlias) {}

// A square matrix M can be decomposed (via polar decomposition) into two matrices --
// an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T,
// where U is another orthogonal matrix and W is a scale matrix. These can be recombined
// to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix.
//
// The one wrinkle is that traditionally Q may contain a reflection -- the
// calculation has been rejiggered to put that reflection into W.
bool SkDecomposeUpper2x2(const SkMatrix& matrix,
                         SkPoint* rotation1,
                         SkPoint* scale,
                         SkPoint* rotation2) {}

///////////////////////////////////////////////////////////////////////////////////////////////////

SkScalar SkMatrixPriv::DifferentialAreaScale(const SkMatrix& m, const SkPoint& p) {}

bool SkMatrixPriv::NearlyAffine(const SkMatrix& m,
                                const SkRect& bounds,
                                SkScalar tolerance) {}

SkScalar SkMatrixPriv::ComputeResScaleForStroking(const SkMatrix& matrix) {}