OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkGeometry.h" | 8 #include "SkGeometry.h" |
9 #include "SkMatrix.h" | 9 #include "SkMatrix.h" |
10 | 10 |
(...skipping 1537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1548 | 1548 |
1549 matrix.mapHomogeneousPoints(&dst[0].fX, &src[0].fX, 3); | 1549 matrix.mapHomogeneousPoints(&dst[0].fX, &src[0].fX, 3); |
1550 | 1550 |
1551 // w' = sqrt(w1*w1/w0*w2) | 1551 // w' = sqrt(w1*w1/w0*w2) |
1552 SkScalar w0 = dst[0].fZ; | 1552 SkScalar w0 = dst[0].fZ; |
1553 SkScalar w1 = dst[1].fZ; | 1553 SkScalar w1 = dst[1].fZ; |
1554 SkScalar w2 = dst[2].fZ; | 1554 SkScalar w2 = dst[2].fZ; |
1555 w = SkScalarSqrt((w1 * w1) / (w0 * w2)); | 1555 w = SkScalarSqrt((w1 * w1) / (w0 * w2)); |
1556 return w; | 1556 return w; |
1557 } | 1557 } |
| 1558 |
| 1559 int SkConic::BuildUnitArc(const SkVector& uStart, const SkVector& uStop, SkRotat
ionDirection dir, |
| 1560 const SkMatrix* userMatrix, SkConic dst[kMaxConicsForA
rc]) { |
| 1561 // rotate by x,y so that uStart is (1.0) |
| 1562 SkScalar x = SkPoint::DotProduct(uStart, uStop); |
| 1563 SkScalar y = SkPoint::CrossProduct(uStart, uStop); |
| 1564 |
| 1565 SkScalar absY = SkScalarAbs(y); |
| 1566 |
| 1567 // check for (effectively) coincident vectors |
| 1568 // this can happen if our angle is nearly 0 or nearly 180 (y == 0) |
| 1569 // ... we use the dot-prod to distinguish between 0 and 180 (x > 0) |
| 1570 if (absY <= SK_ScalarNearlyZero && x > 0 && ((y >= 0 && kCW_SkRotationDirect
ion == dir) || |
| 1571 (y <= 0 && kCCW_SkRotationDirec
tion == dir))) { |
| 1572 return 0; |
| 1573 } |
| 1574 |
| 1575 if (dir == kCCW_SkRotationDirection) { |
| 1576 y = -y; |
| 1577 } |
| 1578 |
| 1579 // We decide to use 1-conic per quadrant of a circle. What quadrant does [xy
] lie in? |
| 1580 // 0 == [0 .. 90) |
| 1581 // 1 == [90 ..180) |
| 1582 // 2 == [180..270) |
| 1583 // 3 == [270..360) |
| 1584 // |
| 1585 int quadrant = 0; |
| 1586 if (0 == y) { |
| 1587 quadrant = 2; // 180 |
| 1588 SkASSERT(SkScalarAbs(x + SK_Scalar1) <= SK_ScalarNearlyZero); |
| 1589 } else if (0 == x) { |
| 1590 SkASSERT(absY - SK_Scalar1 <= SK_ScalarNearlyZero); |
| 1591 quadrant = y > 0 ? 1 : 3; // 90 : 270 |
| 1592 } else { |
| 1593 if (y < 0) { |
| 1594 quadrant += 2; |
| 1595 } |
| 1596 if ((x < 0) != (y < 0)) { |
| 1597 quadrant += 1; |
| 1598 } |
| 1599 } |
| 1600 |
| 1601 const SkPoint quadrantPts[] = { |
| 1602 { 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 }, { 0, -1
}, { 1, -1 } |
| 1603 }; |
| 1604 const SkScalar quadrantWeight = SK_ScalarRoot2Over2; |
| 1605 |
| 1606 int conicCount = quadrant; |
| 1607 for (int i = 0; i < conicCount; ++i) { |
| 1608 dst[i].set(&quadrantPts[i * 2], quadrantWeight); |
| 1609 } |
| 1610 |
| 1611 // Now compute any remaing (sub-90-degree) arc for the last conic |
| 1612 const SkPoint finalP = { x, y }; |
| 1613 const SkPoint& lastQ = quadrantPts[quadrant * 2]; // will already be a unit
-vector |
| 1614 const SkScalar dot = SkVector::DotProduct(lastQ, finalP); |
| 1615 SkASSERT(0 <= dot && dot <= SK_Scalar1); |
| 1616 |
| 1617 if (dot < 1 - SK_ScalarNearlyZero) { |
| 1618 SkVector offCurve = { lastQ.x() + x, lastQ.y() + y }; |
| 1619 // compute the bisector vector, and then rescale to be the off-curve poi
nt. |
| 1620 // we compute its length from cos(theta/2) = length / 1, using half-angl
e identity we get |
| 1621 // length = sqrt(2 / (1 + cos(theta)). We already have cos() when to com
puted the dot. |
| 1622 // This is nice, since our computed weight is cos(theta/2) as well! |
| 1623 // |
| 1624 const SkScalar cosThetaOver2 = SkScalarSqrt((1 + dot) / 2); |
| 1625 offCurve.setLength(SkScalarInvert(cosThetaOver2)); |
| 1626 dst[conicCount].set(lastQ, offCurve, finalP, cosThetaOver2); |
| 1627 conicCount += 1; |
| 1628 } |
| 1629 |
| 1630 // now handle counter-clockwise and the initial unitStart rotation |
| 1631 SkMatrix matrix; |
| 1632 matrix.setSinCos(uStart.fY, uStart.fX); |
| 1633 if (dir == kCCW_SkRotationDirection) { |
| 1634 matrix.preScale(SK_Scalar1, -SK_Scalar1); |
| 1635 } |
| 1636 if (userMatrix) { |
| 1637 matrix.postConcat(*userMatrix); |
| 1638 } |
| 1639 for (int i = 0; i < conicCount; ++i) { |
| 1640 matrix.mapPoints(dst[i].fPts, 3); |
| 1641 } |
| 1642 return conicCount; |
| 1643 } |
OLD | NEW |