// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "flutter/flow/raster_cache_util.h" namespace flutter { bool RasterCacheUtil::ComputeIntegralTransCTM(const SkMatrix& in, SkMatrix* out) { // Avoid integral snapping if the matrix has complex transformation to avoid // the artifact observed in https://github.com/flutter/flutter/issues/41654. if (!in.isScaleTranslate()) { return false; } SkScalar in_tx = in.getTranslateX(); SkScalar in_ty = in.getTranslateY(); SkScalar out_tx = SkScalarRoundToScalar(in_tx); SkScalar out_ty = SkScalarRoundToScalar(in_ty); if (out_tx != in_tx || out_ty != in_ty) { // As a side effect of those tests we also know that neither translation // component was a NaN *out = in; (*out)[SkMatrix::kMTransX] = out_tx; (*out)[SkMatrix::kMTransY] = out_ty; return true; } return false; } bool RasterCacheUtil::ComputeIntegralTransCTM(const SkM44& in, SkM44* out) { // Avoid integral snapping if the matrix has complex transformation to avoid // the artifact observed in https://github.com/flutter/flutter/issues/41654. if (in.rc(0, 1) != 0 || in.rc(0, 2) != 0) { // X multiplied by either Y or Z return false; } if (in.rc(1, 0) != 0 || in.rc(1, 2) != 0) { // Y multiplied by either X or Z return false; } if (in.rc(3, 0) != 0 || in.rc(3, 1) != 0 || in.rc(3, 2) != 0 || in.rc(3, 3) != 1) { // W not identity row, therefore perspective is applied return false; } // We do not need to worry about the Z row unless the W row // has perspective entries, which we've just eliminated... SkScalar in_tx = in.rc(0, 3); SkScalar in_ty = in.rc(1, 3); SkScalar out_tx = SkScalarRoundToScalar(in_tx); SkScalar out_ty = SkScalarRoundToScalar(in_ty); if (out_tx != in_tx || out_ty != in_ty) { // As a side effect of those tests we also know that neither translation // component was a NaN *out = in; out->setRC(0, 3, out_tx); out->setRC(1, 3, out_ty); // No need to worry about Z translation because it has no effect // without perspective entries... return true; } return false; } } // namespace flutter