Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | |
michael@0 | 2 | /* |
michael@0 | 3 | * Copyright 2006 The Android Open Source Project |
michael@0 | 4 | * |
michael@0 | 5 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 6 | * found in the LICENSE file. |
michael@0 | 7 | */ |
michael@0 | 8 | |
michael@0 | 9 | |
michael@0 | 10 | #include "SkStrokerPriv.h" |
michael@0 | 11 | #include "SkGeometry.h" |
michael@0 | 12 | #include "SkPath.h" |
michael@0 | 13 | |
michael@0 | 14 | static void ButtCapper(SkPath* path, const SkPoint& pivot, |
michael@0 | 15 | const SkVector& normal, const SkPoint& stop, |
michael@0 | 16 | SkPath*) |
michael@0 | 17 | { |
michael@0 | 18 | path->lineTo(stop.fX, stop.fY); |
michael@0 | 19 | } |
michael@0 | 20 | |
michael@0 | 21 | static void RoundCapper(SkPath* path, const SkPoint& pivot, |
michael@0 | 22 | const SkVector& normal, const SkPoint& stop, |
michael@0 | 23 | SkPath*) |
michael@0 | 24 | { |
michael@0 | 25 | SkScalar px = pivot.fX; |
michael@0 | 26 | SkScalar py = pivot.fY; |
michael@0 | 27 | SkScalar nx = normal.fX; |
michael@0 | 28 | SkScalar ny = normal.fY; |
michael@0 | 29 | SkScalar sx = SkScalarMul(nx, CUBIC_ARC_FACTOR); |
michael@0 | 30 | SkScalar sy = SkScalarMul(ny, CUBIC_ARC_FACTOR); |
michael@0 | 31 | |
michael@0 | 32 | path->cubicTo(px + nx + CWX(sx, sy), py + ny + CWY(sx, sy), |
michael@0 | 33 | px + CWX(nx, ny) + sx, py + CWY(nx, ny) + sy, |
michael@0 | 34 | px + CWX(nx, ny), py + CWY(nx, ny)); |
michael@0 | 35 | path->cubicTo(px + CWX(nx, ny) - sx, py + CWY(nx, ny) - sy, |
michael@0 | 36 | px - nx + CWX(sx, sy), py - ny + CWY(sx, sy), |
michael@0 | 37 | stop.fX, stop.fY); |
michael@0 | 38 | } |
michael@0 | 39 | |
michael@0 | 40 | static void SquareCapper(SkPath* path, const SkPoint& pivot, |
michael@0 | 41 | const SkVector& normal, const SkPoint& stop, |
michael@0 | 42 | SkPath* otherPath) |
michael@0 | 43 | { |
michael@0 | 44 | SkVector parallel; |
michael@0 | 45 | normal.rotateCW(¶llel); |
michael@0 | 46 | |
michael@0 | 47 | if (otherPath) |
michael@0 | 48 | { |
michael@0 | 49 | path->setLastPt(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY); |
michael@0 | 50 | path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY); |
michael@0 | 51 | } |
michael@0 | 52 | else |
michael@0 | 53 | { |
michael@0 | 54 | path->lineTo(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY); |
michael@0 | 55 | path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY); |
michael@0 | 56 | path->lineTo(stop.fX, stop.fY); |
michael@0 | 57 | } |
michael@0 | 58 | } |
michael@0 | 59 | |
michael@0 | 60 | ///////////////////////////////////////////////////////////////////////////// |
michael@0 | 61 | |
michael@0 | 62 | static bool is_clockwise(const SkVector& before, const SkVector& after) |
michael@0 | 63 | { |
michael@0 | 64 | return SkScalarMul(before.fX, after.fY) - SkScalarMul(before.fY, after.fX) > 0; |
michael@0 | 65 | } |
michael@0 | 66 | |
michael@0 | 67 | enum AngleType { |
michael@0 | 68 | kNearly180_AngleType, |
michael@0 | 69 | kSharp_AngleType, |
michael@0 | 70 | kShallow_AngleType, |
michael@0 | 71 | kNearlyLine_AngleType |
michael@0 | 72 | }; |
michael@0 | 73 | |
michael@0 | 74 | static AngleType Dot2AngleType(SkScalar dot) |
michael@0 | 75 | { |
michael@0 | 76 | // need more precise fixed normalization |
michael@0 | 77 | // SkASSERT(SkScalarAbs(dot) <= SK_Scalar1 + SK_ScalarNearlyZero); |
michael@0 | 78 | |
michael@0 | 79 | if (dot >= 0) // shallow or line |
michael@0 | 80 | return SkScalarNearlyZero(SK_Scalar1 - dot) ? kNearlyLine_AngleType : kShallow_AngleType; |
michael@0 | 81 | else // sharp or 180 |
michael@0 | 82 | return SkScalarNearlyZero(SK_Scalar1 + dot) ? kNearly180_AngleType : kSharp_AngleType; |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | static void HandleInnerJoin(SkPath* inner, const SkPoint& pivot, const SkVector& after) |
michael@0 | 86 | { |
michael@0 | 87 | #if 1 |
michael@0 | 88 | /* In the degenerate case that the stroke radius is larger than our segments |
michael@0 | 89 | just connecting the two inner segments may "show through" as a funny |
michael@0 | 90 | diagonal. To pseudo-fix this, we go through the pivot point. This adds |
michael@0 | 91 | an extra point/edge, but I can't see a cheap way to know when this is |
michael@0 | 92 | not needed :( |
michael@0 | 93 | */ |
michael@0 | 94 | inner->lineTo(pivot.fX, pivot.fY); |
michael@0 | 95 | #endif |
michael@0 | 96 | |
michael@0 | 97 | inner->lineTo(pivot.fX - after.fX, pivot.fY - after.fY); |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | static void BluntJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal, |
michael@0 | 101 | const SkPoint& pivot, const SkVector& afterUnitNormal, |
michael@0 | 102 | SkScalar radius, SkScalar invMiterLimit, bool, bool) |
michael@0 | 103 | { |
michael@0 | 104 | SkVector after; |
michael@0 | 105 | afterUnitNormal.scale(radius, &after); |
michael@0 | 106 | |
michael@0 | 107 | if (!is_clockwise(beforeUnitNormal, afterUnitNormal)) |
michael@0 | 108 | { |
michael@0 | 109 | SkTSwap<SkPath*>(outer, inner); |
michael@0 | 110 | after.negate(); |
michael@0 | 111 | } |
michael@0 | 112 | |
michael@0 | 113 | outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY); |
michael@0 | 114 | HandleInnerJoin(inner, pivot, after); |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | static void RoundJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal, |
michael@0 | 118 | const SkPoint& pivot, const SkVector& afterUnitNormal, |
michael@0 | 119 | SkScalar radius, SkScalar invMiterLimit, bool, bool) |
michael@0 | 120 | { |
michael@0 | 121 | SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal); |
michael@0 | 122 | AngleType angleType = Dot2AngleType(dotProd); |
michael@0 | 123 | |
michael@0 | 124 | if (angleType == kNearlyLine_AngleType) |
michael@0 | 125 | return; |
michael@0 | 126 | |
michael@0 | 127 | SkVector before = beforeUnitNormal; |
michael@0 | 128 | SkVector after = afterUnitNormal; |
michael@0 | 129 | SkRotationDirection dir = kCW_SkRotationDirection; |
michael@0 | 130 | |
michael@0 | 131 | if (!is_clockwise(before, after)) |
michael@0 | 132 | { |
michael@0 | 133 | SkTSwap<SkPath*>(outer, inner); |
michael@0 | 134 | before.negate(); |
michael@0 | 135 | after.negate(); |
michael@0 | 136 | dir = kCCW_SkRotationDirection; |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | SkPoint pts[kSkBuildQuadArcStorage]; |
michael@0 | 140 | SkMatrix matrix; |
michael@0 | 141 | matrix.setScale(radius, radius); |
michael@0 | 142 | matrix.postTranslate(pivot.fX, pivot.fY); |
michael@0 | 143 | int count = SkBuildQuadArc(before, after, dir, &matrix, pts); |
michael@0 | 144 | SkASSERT((count & 1) == 1); |
michael@0 | 145 | |
michael@0 | 146 | if (count > 1) |
michael@0 | 147 | { |
michael@0 | 148 | for (int i = 1; i < count; i += 2) |
michael@0 | 149 | outer->quadTo(pts[i].fX, pts[i].fY, pts[i+1].fX, pts[i+1].fY); |
michael@0 | 150 | |
michael@0 | 151 | after.scale(radius); |
michael@0 | 152 | HandleInnerJoin(inner, pivot, after); |
michael@0 | 153 | } |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | #define kOneOverSqrt2 (0.707106781f) |
michael@0 | 157 | |
michael@0 | 158 | static void MiterJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal, |
michael@0 | 159 | const SkPoint& pivot, const SkVector& afterUnitNormal, |
michael@0 | 160 | SkScalar radius, SkScalar invMiterLimit, |
michael@0 | 161 | bool prevIsLine, bool currIsLine) |
michael@0 | 162 | { |
michael@0 | 163 | // negate the dot since we're using normals instead of tangents |
michael@0 | 164 | SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal); |
michael@0 | 165 | AngleType angleType = Dot2AngleType(dotProd); |
michael@0 | 166 | SkVector before = beforeUnitNormal; |
michael@0 | 167 | SkVector after = afterUnitNormal; |
michael@0 | 168 | SkVector mid; |
michael@0 | 169 | SkScalar sinHalfAngle; |
michael@0 | 170 | bool ccw; |
michael@0 | 171 | |
michael@0 | 172 | if (angleType == kNearlyLine_AngleType) |
michael@0 | 173 | return; |
michael@0 | 174 | if (angleType == kNearly180_AngleType) |
michael@0 | 175 | { |
michael@0 | 176 | currIsLine = false; |
michael@0 | 177 | goto DO_BLUNT; |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | ccw = !is_clockwise(before, after); |
michael@0 | 181 | if (ccw) |
michael@0 | 182 | { |
michael@0 | 183 | SkTSwap<SkPath*>(outer, inner); |
michael@0 | 184 | before.negate(); |
michael@0 | 185 | after.negate(); |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | /* Before we enter the world of square-roots and divides, |
michael@0 | 189 | check if we're trying to join an upright right angle |
michael@0 | 190 | (common case for stroking rectangles). If so, special case |
michael@0 | 191 | that (for speed an accuracy). |
michael@0 | 192 | Note: we only need to check one normal if dot==0 |
michael@0 | 193 | */ |
michael@0 | 194 | if (0 == dotProd && invMiterLimit <= kOneOverSqrt2) |
michael@0 | 195 | { |
michael@0 | 196 | mid.set(SkScalarMul(before.fX + after.fX, radius), |
michael@0 | 197 | SkScalarMul(before.fY + after.fY, radius)); |
michael@0 | 198 | goto DO_MITER; |
michael@0 | 199 | } |
michael@0 | 200 | |
michael@0 | 201 | /* midLength = radius / sinHalfAngle |
michael@0 | 202 | if (midLength > miterLimit * radius) abort |
michael@0 | 203 | if (radius / sinHalf > miterLimit * radius) abort |
michael@0 | 204 | if (1 / sinHalf > miterLimit) abort |
michael@0 | 205 | if (1 / miterLimit > sinHalf) abort |
michael@0 | 206 | My dotProd is opposite sign, since it is built from normals and not tangents |
michael@0 | 207 | hence 1 + dot instead of 1 - dot in the formula |
michael@0 | 208 | */ |
michael@0 | 209 | sinHalfAngle = SkScalarSqrt(SkScalarHalf(SK_Scalar1 + dotProd)); |
michael@0 | 210 | if (sinHalfAngle < invMiterLimit) |
michael@0 | 211 | { |
michael@0 | 212 | currIsLine = false; |
michael@0 | 213 | goto DO_BLUNT; |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | // choose the most accurate way to form the initial mid-vector |
michael@0 | 217 | if (angleType == kSharp_AngleType) |
michael@0 | 218 | { |
michael@0 | 219 | mid.set(after.fY - before.fY, before.fX - after.fX); |
michael@0 | 220 | if (ccw) |
michael@0 | 221 | mid.negate(); |
michael@0 | 222 | } |
michael@0 | 223 | else |
michael@0 | 224 | mid.set(before.fX + after.fX, before.fY + after.fY); |
michael@0 | 225 | |
michael@0 | 226 | mid.setLength(SkScalarDiv(radius, sinHalfAngle)); |
michael@0 | 227 | DO_MITER: |
michael@0 | 228 | if (prevIsLine) |
michael@0 | 229 | outer->setLastPt(pivot.fX + mid.fX, pivot.fY + mid.fY); |
michael@0 | 230 | else |
michael@0 | 231 | outer->lineTo(pivot.fX + mid.fX, pivot.fY + mid.fY); |
michael@0 | 232 | |
michael@0 | 233 | DO_BLUNT: |
michael@0 | 234 | after.scale(radius); |
michael@0 | 235 | if (!currIsLine) |
michael@0 | 236 | outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY); |
michael@0 | 237 | HandleInnerJoin(inner, pivot, after); |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | ///////////////////////////////////////////////////////////////////////////// |
michael@0 | 241 | |
michael@0 | 242 | SkStrokerPriv::CapProc SkStrokerPriv::CapFactory(SkPaint::Cap cap) |
michael@0 | 243 | { |
michael@0 | 244 | static const SkStrokerPriv::CapProc gCappers[] = { |
michael@0 | 245 | ButtCapper, RoundCapper, SquareCapper |
michael@0 | 246 | }; |
michael@0 | 247 | |
michael@0 | 248 | SkASSERT((unsigned)cap < SkPaint::kCapCount); |
michael@0 | 249 | return gCappers[cap]; |
michael@0 | 250 | } |
michael@0 | 251 | |
michael@0 | 252 | SkStrokerPriv::JoinProc SkStrokerPriv::JoinFactory(SkPaint::Join join) |
michael@0 | 253 | { |
michael@0 | 254 | static const SkStrokerPriv::JoinProc gJoiners[] = { |
michael@0 | 255 | MiterJoiner, RoundJoiner, BluntJoiner |
michael@0 | 256 | }; |
michael@0 | 257 | |
michael@0 | 258 | SkASSERT((unsigned)join < SkPaint::kJoinCount); |
michael@0 | 259 | return gJoiners[join]; |
michael@0 | 260 | } |