/* * 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. */ #ifndef SkPointPriv_DEFINED #define SkPointPriv_DEFINED #include "SkPoint.h" #include "SkRect.h" class SkPointPriv { public: enum Side { kLeft_Side = -1, kOn_Side = 0, kRight_Side = 1, }; static bool AreFinite(const SkPoint array[], int count) { return SkScalarsAreFinite(&array[0].fX, count << 1); } static const SkScalar* AsScalars(const SkPoint& pt) { return &pt.fX; } static bool CanNormalize(SkScalar dx, SkScalar dy) { if (!SkScalarsAreFinite(dx, dy)) { return false; } // Simple enough (and performance critical sometimes) so we inline it. return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero); } static SkScalar DistanceToLineBetweenSqd(const SkPoint& pt, const SkPoint& a, const SkPoint& b, Side* side = nullptr); static SkScalar DistanceToLineBetween(const SkPoint& pt, const SkPoint& a, const SkPoint& b, Side* side = nullptr) { return SkScalarSqrt(DistanceToLineBetweenSqd(pt, a, b, side)); } static SkScalar DistanceToLineSegmentBetweenSqd(const SkPoint& pt, const SkPoint& a, const SkPoint& b); static SkScalar DistanceToLineSegmentBetween(const SkPoint& pt, const SkPoint& a, const SkPoint& b) { return SkScalarSqrt(DistanceToLineSegmentBetweenSqd(pt, a, b)); } static SkScalar DistanceToSqd(const SkPoint& pt, const SkPoint& a) { SkScalar dx = pt.fX - a.fX; SkScalar dy = pt.fY - a.fY; return dx * dx + dy * dy; } static bool EqualsWithinTolerance(const SkPoint& p1, const SkPoint& p2) { return !CanNormalize(p1.fX - p2.fX, p1.fY - p2.fY); } static bool EqualsWithinTolerance(const SkPoint& pt, const SkPoint& p, SkScalar tol) { return SkScalarNearlyZero(pt.fX - p.fX, tol) && SkScalarNearlyZero(pt.fY - p.fY, tol); } static SkScalar LengthSqd(const SkPoint& pt) { return SkPoint::DotProduct(pt, pt); } static void Negate(SkIPoint& pt) { pt.fX = -pt.fX; pt.fY = -pt.fY; } static void RotateCCW(const SkPoint& src, SkPoint* dst) { // use a tmp in case src == dst SkScalar tmp = src.fX; dst->fX = src.fY; dst->fY = -tmp; } static void RotateCCW(SkPoint* pt) { RotateCCW(*pt, pt); } static void RotateCW(const SkPoint& src, SkPoint* dst) { // use a tmp in case src == dst SkScalar tmp = src.fX; dst->fX = -src.fY; dst->fY = tmp; } static void RotateCW(SkPoint* pt) { RotateCW(*pt, pt); } static bool SetLengthFast(SkPoint* pt, float length); static SkPoint MakeOrthog(const SkPoint& vec, Side side = kLeft_Side) { SkASSERT(side == kRight_Side || side == kLeft_Side); return (side == kRight_Side) ? SkPoint{-vec.fY, vec.fX} : SkPoint{vec.fY, -vec.fX}; } // counter-clockwise fan static void SetRectFan(SkPoint v[], SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride) { SkASSERT(stride >= sizeof(SkPoint)); ((SkPoint*)((intptr_t)v + 0 * stride))->set(l, t); ((SkPoint*)((intptr_t)v + 1 * stride))->set(l, b); ((SkPoint*)((intptr_t)v + 2 * stride))->set(r, b); ((SkPoint*)((intptr_t)v + 3 * stride))->set(r, t); } // tri strip with two counter-clockwise triangles static void SetRectTriStrip(SkPoint v[], SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride) { SkASSERT(stride >= sizeof(SkPoint)); ((SkPoint*)((intptr_t)v + 0 * stride))->set(l, t); ((SkPoint*)((intptr_t)v + 1 * stride))->set(l, b); ((SkPoint*)((intptr_t)v + 2 * stride))->set(r, t); ((SkPoint*)((intptr_t)v + 3 * stride))->set(r, b); } static void SetRectTriStrip(SkPoint v[], const SkRect& rect, size_t stride) { SetRectTriStrip(v, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, stride); } }; #endif