1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
109da0cea3a32e274ad8b40174a25e5f8c532fbd9bcaryclark@google.com// FIXME: needs to be in a header
119da0cea3a32e274ad8b40174a25e5f8c532fbd9bcaryclark@google.combool SkSetPoly3To3_D(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]);
129da0cea3a32e274ad8b40174a25e5f8c532fbd9bcaryclark@google.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef int64_t SkDScalar;
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkScalar SkDScalar_toScalar(SkDScalar value) {
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDScalar result = (value + (1 << 15)) >> 16;
178e06dabfe643b483fd59eb0a511b4b23ba640ba7bsalomon@google.com    SkDEBUGCODE(int top = static_cast<int>(result >> 31);)
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(top == 0 || top == -1);
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (SkScalar)result;
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkDScalar SkDScalar_setMul(SkScalar a, SkScalar b) {
239da0cea3a32e274ad8b40174a25e5f8c532fbd9bcaryclark@google.com    return (SkDScalar) ((SkDScalar) a * (SkDScalar) b);
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void computeOuterProduct(SkMatrix* matrix,
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPoint pts0[3], const SkPoint& ave0,
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPoint pts1[3], const SkPoint& ave1) {
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDScalar tmp[4];
304516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com    sk_bzero(tmp, sizeof(tmp));
31d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = 0; i < 3; i++) {
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar x0 = pts0[i].fX - ave0.fX;
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar y0 = pts0[i].fY - ave0.fY;
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar x1 = pts1[i].fX - ave1.fX;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar y1 = pts1[i].fY - ave1.fY;
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp[0] += SkDScalar_setMul(x0, x1);
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp[1] += SkDScalar_setMul(x0, y1);
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp[2] += SkDScalar_setMul(y0, x1);
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp[3] += SkDScalar_setMul(y0, y1);
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->reset();
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->setScaleX(SkDScalar_toScalar(tmp[0]));
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->setSkewY( SkDScalar_toScalar(tmp[1]));
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->setSkewX( SkDScalar_toScalar(tmp[2]));
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->setScaleY(SkDScalar_toScalar(tmp[3]));
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) {
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDScalar_toScalar(SkDScalar_setMul(ax, bx) +
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkDScalar_setMul(ay, by));
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.combool SkSetPoly3To3_D(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) {
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPoint& srcAve = src[0];
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPoint& dstAve = dst[0];
57d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix srcOP, dstOP;
59d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    computeOuterProduct(&srcOP, src, srcAve, src, srcAve);
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!srcOP.invert(&srcOP)) {
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    computeOuterProduct(&dstOP, src, srcAve, dst, dstAve);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->setConcat(dstOP, srcOP);
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY,
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    matrix->getScaleX(), matrix->getSkewX()));
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY,
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    matrix->getSkewY(), matrix->getScaleY()));
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
75