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 */ 870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com#include "SkLineClipper.h" 970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 10bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.comtemplate <typename T> T pin_unsorted(T value, T limit0, T limit1) { 11bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com if (limit1 < limit0) { 12bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com SkTSwap(limit0, limit1); 13bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com } 14bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com // now the limits are sorted 15bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com SkASSERT(limit0 <= limit1); 16bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com 17bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com if (value < limit0) { 18bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com value = limit0; 19bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com } else if (value > limit1) { 20bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com value = limit1; 21bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com } 22bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com return value; 23bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com} 24bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com 2570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com// return X coordinate of intersection with horizontal line at Y 2670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.comstatic SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) { 2770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com SkScalar dy = src[1].fY - src[0].fY; 2870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (SkScalarNearlyZero(dy)) { 2970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com return SkScalarAve(src[0].fX, src[1].fX); 3070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 31160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com // need the extra precision so we don't compute a value that exceeds 32160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com // our original limits 33160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double X0 = src[0].fX; 34160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double Y0 = src[0].fY; 35160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double X1 = src[1].fX; 36160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double Y1 = src[1].fY; 37160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double result = X0 + ((double)Y - Y0) * (X1 - X0) / (Y1 - Y0); 38fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 39bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com // The computed X value might still exceed [X0..X1] due to quantum flux 40bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com // when the doubles were added and subtracted, so we have to pin the 41bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com // answer :( 42bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com return (float)pin_unsorted(result, X0, X1); 4370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 4470149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com} 4570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 4670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com// return Y coordinate of intersection with vertical line at X 4770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.comstatic SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) { 4870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com SkScalar dx = src[1].fX - src[0].fX; 4970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (SkScalarNearlyZero(dx)) { 5070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com return SkScalarAve(src[0].fY, src[1].fY); 5170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 52160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com // need the extra precision so we don't compute a value that exceeds 53160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com // our original limits 54160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double X0 = src[0].fX; 55160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double Y0 = src[0].fY; 56160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double X1 = src[1].fX; 57160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double Y1 = src[1].fY; 58160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0); 59160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com return (float)result; 6070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 6170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com} 6270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 63e28ff55d980d2992618b6b721c848aba96cf759areed@android.com/////////////////////////////////////////////////////////////////////////////// 64e28ff55d980d2992618b6b721c848aba96cf759areed@android.com 65a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.comstatic inline bool nestedLT(SkScalar a, SkScalar b, SkScalar dim) { 66a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com return a <= b && (a < b || dim > 0); 67a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com} 68a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com 69a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com// returns true if outer contains inner, even if inner is empty. 70a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com// note: outer.contains(inner) always returns false if inner is empty. 71a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.comstatic inline bool containsNoEmptyCheck(const SkRect& outer, 72a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com const SkRect& inner) { 73a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com return outer.fLeft <= inner.fLeft && outer.fTop <= inner.fTop && 74a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com outer.fRight >= inner.fRight && outer.fBottom >= inner.fBottom; 75a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com} 76a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com 77e28ff55d980d2992618b6b721c848aba96cf759areed@android.combool SkLineClipper::IntersectLine(const SkPoint src[2], const SkRect& clip, 78e28ff55d980d2992618b6b721c848aba96cf759areed@android.com SkPoint dst[2]) { 79e28ff55d980d2992618b6b721c848aba96cf759areed@android.com SkRect bounds; 80fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 81e28ff55d980d2992618b6b721c848aba96cf759areed@android.com bounds.set(src, 2); 82a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com if (containsNoEmptyCheck(clip, bounds)) { 83e28ff55d980d2992618b6b721c848aba96cf759areed@android.com if (src != dst) { 84e28ff55d980d2992618b6b721c848aba96cf759areed@android.com memcpy(dst, src, 2 * sizeof(SkPoint)); 85e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 86e28ff55d980d2992618b6b721c848aba96cf759areed@android.com return true; 87e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 88a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com // check for no overlap, and only permit coincident edges if the line 89a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com // and the edge are colinear 90a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com if (nestedLT(bounds.fRight, clip.fLeft, bounds.width()) || 91a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com nestedLT(clip.fRight, bounds.fLeft, bounds.width()) || 92a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com nestedLT(bounds.fBottom, clip.fTop, bounds.height()) || 93a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com nestedLT(clip.fBottom, bounds.fTop, bounds.height())) { 94a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com return false; 95a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com } 96e28ff55d980d2992618b6b721c848aba96cf759areed@android.com 97e28ff55d980d2992618b6b721c848aba96cf759areed@android.com int index0, index1; 98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 99e28ff55d980d2992618b6b721c848aba96cf759areed@android.com if (src[0].fY < src[1].fY) { 100e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index0 = 0; 101e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index1 = 1; 102e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } else { 103e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index0 = 1; 104e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index1 = 0; 105e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 106e28ff55d980d2992618b6b721c848aba96cf759areed@android.com 107e28ff55d980d2992618b6b721c848aba96cf759areed@android.com SkPoint tmp[2]; 108e28ff55d980d2992618b6b721c848aba96cf759areed@android.com memcpy(tmp, src, sizeof(tmp)); 109e28ff55d980d2992618b6b721c848aba96cf759areed@android.com 110e28ff55d980d2992618b6b721c848aba96cf759areed@android.com // now compute Y intersections 111e28ff55d980d2992618b6b721c848aba96cf759areed@android.com if (tmp[index0].fY < clip.fTop) { 112e28ff55d980d2992618b6b721c848aba96cf759areed@android.com tmp[index0].set(sect_with_horizontal(src, clip.fTop), clip.fTop); 113e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 114e28ff55d980d2992618b6b721c848aba96cf759areed@android.com if (tmp[index1].fY > clip.fBottom) { 115e28ff55d980d2992618b6b721c848aba96cf759areed@android.com tmp[index1].set(sect_with_horizontal(src, clip.fBottom), clip.fBottom); 116e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 118e28ff55d980d2992618b6b721c848aba96cf759areed@android.com if (tmp[0].fX < tmp[1].fX) { 119e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index0 = 0; 120e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index1 = 1; 121e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } else { 122e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index0 = 1; 123e28ff55d980d2992618b6b721c848aba96cf759areed@android.com index1 = 0; 124e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 125e28ff55d980d2992618b6b721c848aba96cf759areed@android.com 126e28ff55d980d2992618b6b721c848aba96cf759areed@android.com // check for quick-reject in X again, now that we may have been chopped 127a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com if ((tmp[index1].fX <= clip.fLeft || tmp[index0].fX >= clip.fRight) && 128a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com tmp[index0].fX < tmp[index1].fX) { 129a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com // only reject if we have a non-zero width 130e28ff55d980d2992618b6b721c848aba96cf759areed@android.com return false; 131e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 132e28ff55d980d2992618b6b721c848aba96cf759areed@android.com 133e28ff55d980d2992618b6b721c848aba96cf759areed@android.com if (tmp[index0].fX < clip.fLeft) { 134e28ff55d980d2992618b6b721c848aba96cf759areed@android.com tmp[index0].set(clip.fLeft, sect_with_vertical(src, clip.fLeft)); 135e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 136e28ff55d980d2992618b6b721c848aba96cf759areed@android.com if (tmp[index1].fX > clip.fRight) { 137e28ff55d980d2992618b6b721c848aba96cf759areed@android.com tmp[index1].set(clip.fRight, sect_with_vertical(src, clip.fRight)); 138e28ff55d980d2992618b6b721c848aba96cf759areed@android.com } 139a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com#ifdef SK_DEBUG 140a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com bounds.set(tmp, 2); 141a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com SkASSERT(containsNoEmptyCheck(clip, bounds)); 142a3d901099d7d295cd7d9df4114e874d9ccfff447reed@android.com#endif 143e28ff55d980d2992618b6b721c848aba96cf759areed@android.com memcpy(dst, tmp, sizeof(tmp)); 144e28ff55d980d2992618b6b721c848aba96cf759areed@android.com return true; 145e28ff55d980d2992618b6b721c848aba96cf759areed@android.com} 146e28ff55d980d2992618b6b721c848aba96cf759areed@android.com 147160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com#ifdef SK_DEBUG 148160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com// return value between the two limits, where the limits are either ascending 149160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com// or descending. 150160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.comstatic bool is_between_unsorted(SkScalar value, 151160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com SkScalar limit0, SkScalar limit1) { 152160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com if (limit0 < limit1) { 153160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com return limit0 <= value && value <= limit1; 154160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com } else { 155160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com return limit1 <= value && value <= limit0; 156160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com } 157160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com} 158160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com#endif 159160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com 1600e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com#ifdef SK_DEBUG 161bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com// This is an example of why we need to pin the result computed in 162bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com// sect_with_horizontal. If we didn't explicitly pin, is_between_unsorted would 163bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com// fail. 164bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com// 165bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.comstatic void sect_with_horizontal_test_for_pin_results() { 166bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com const SkPoint pts[] = { 167fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { -540000, -720000 }, 1684b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org { -9.10000017e-05f, 9.99999996e-13f } 169bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com }; 170bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com float x = sect_with_horizontal(pts, 0); 171bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com SkASSERT(is_between_unsorted(x, pts[0].fX, pts[1].fX)); 172bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com} 173bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com#endif 174bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com 17570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.comint SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, 17670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com SkPoint lines[]) { 177bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com#ifdef SK_DEBUG 178bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com { 179bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com static bool gOnce; 180bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com if (!gOnce) { 181bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com sect_with_horizontal_test_for_pin_results(); 182bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com gOnce = true; 183bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com } 184bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com } 185bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com#endif 186bddbc45b0b7e279a3e6f151638dfbf3c4e4ad3c1reed@google.com 18770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com int index0, index1; 18870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 18970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (pts[0].fY < pts[1].fY) { 19070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index0 = 0; 19170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index1 = 1; 19270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 19370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index0 = 1; 19470149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index1 = 0; 19570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 19670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 19770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com // Check if we're completely clipped out in Y (above or below 19870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 19970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (pts[index1].fY <= clip.fTop) { // we're above the clip 20070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com return 0; 20170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 20270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (pts[index0].fY >= clip.fBottom) { // we're below the clip 20370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com return 0; 20470149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 205fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 20670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com // Chop in Y to produce a single segment, stored in tmp[0..1] 20770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 20870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com SkPoint tmp[2]; 20970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com memcpy(tmp, pts, sizeof(tmp)); 21070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 21170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com // now compute intersections 21270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (pts[index0].fY < clip.fTop) { 21370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com tmp[index0].set(sect_with_horizontal(pts, clip.fTop), clip.fTop); 214160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com SkASSERT(is_between_unsorted(tmp[index0].fX, pts[0].fX, pts[1].fX)); 21570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 21670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (tmp[index1].fY > clip.fBottom) { 21770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com tmp[index1].set(sect_with_horizontal(pts, clip.fBottom), clip.fBottom); 218160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com SkASSERT(is_between_unsorted(tmp[index1].fX, pts[0].fX, pts[1].fX)); 21970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 22070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 22170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com // Chop it into 1..3 segments that are wholly within the clip in X. 22270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 22370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com // temp storage for up to 3 segments 22470149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com SkPoint resultStorage[kMaxPoints]; 22570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com SkPoint* result; // points to our results, either tmp or resultStorage 22670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com int lineCount = 1; 227e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com bool reverse; 22870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 22970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (pts[0].fX < pts[1].fX) { 23070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index0 = 0; 23170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index1 = 1; 232e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com reverse = false; 23370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 23470149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index0 = 1; 23570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com index1 = 0; 236e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com reverse = true; 23770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 238e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com 23970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (tmp[index1].fX <= clip.fLeft) { // wholly to the left 24070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com tmp[0].fX = tmp[1].fX = clip.fLeft; 24170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com result = tmp; 242e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com reverse = false; 24370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else if (tmp[index0].fX >= clip.fRight) { // wholly to the right 24470149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com tmp[0].fX = tmp[1].fX = clip.fRight; 24570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com result = tmp; 246e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com reverse = false; 24770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 24870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com result = resultStorage; 24970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com SkPoint* r = result; 250fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 25170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (tmp[index0].fX < clip.fLeft) { 25270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com r->set(clip.fLeft, tmp[index0].fY); 25370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com r += 1; 254160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com r->set(clip.fLeft, sect_with_vertical(tmp, clip.fLeft)); 255160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY)); 25670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 25770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com *r = tmp[index0]; 25870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 25970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com r += 1; 26070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 26170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com if (tmp[index1].fX > clip.fRight) { 262160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com r->set(clip.fRight, sect_with_vertical(tmp, clip.fRight)); 263160f2c0e1724003767dbbea05bc8046ac5dd78d4reed@google.com SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY)); 26470149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com r += 1; 26570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com r->set(clip.fRight, tmp[index1].fY); 26670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 26770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com *r = tmp[index1]; 26870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 26970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 270a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org lineCount = SkToInt(r - result); 27170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 27270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com 27370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com // Now copy the results into the caller's lines[] parameter 274e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com if (reverse) { 27570149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com // copy the pts in reverse order to maintain winding order 27670149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com for (int i = 0; i <= lineCount; i++) { 27770149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com lines[lineCount - i] = result[i]; 27870149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 27970149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } else { 28070149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com memcpy(lines, result, (lineCount + 1) * sizeof(SkPoint)); 28170149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com } 28270149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com return lineCount; 28370149060a74bb212e67eb140be7cbf97a7cd36a8reed@android.com} 284