OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. | 2 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above | 8 * 1. Redistributions of source code must retain the above |
9 * copyright notice, this list of conditions and the following | 9 * copyright notice, this list of conditions and the following |
10 * disclaimer. | 10 * disclaimer. |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "wtf/MathExtras.h" | 33 #include "wtf/MathExtras.h" |
34 | 34 |
35 namespace WebCore { | 35 namespace WebCore { |
36 | 36 |
37 static inline float ellipseXIntercept(float y, float rx, float ry) | 37 static inline float ellipseXIntercept(float y, float rx, float ry) |
38 { | 38 { |
39 ASSERT(ry > 0); | 39 ASSERT(ry > 0); |
40 return rx * sqrt(1 - (y * y) / (ry * ry)); | 40 return rx * sqrt(1 - (y * y) / (ry * ry)); |
41 } | 41 } |
42 | 42 |
43 static inline float ellipseYIntercept(float x, float rx, float ry) | |
44 { | |
45 ASSERT(rx > 0); | |
46 return ry * sqrt(1 - (x * x) / (rx * rx)); | |
47 } | |
48 | |
49 FloatRect RectangleShape::shapePaddingBounds() const | |
50 { | |
51 ASSERT(shapePadding() >= 0); | |
52 if (!shapePadding() || isEmpty()) | |
53 return m_bounds; | |
54 | |
55 float boundsX = x() + std::min(width() / 2, shapePadding()); | |
56 float boundsY = y() + std::min(height() / 2, shapePadding()); | |
57 float boundsWidth = std::max(0.0f, width() - shapePadding() * 2); | |
58 float boundsHeight = std::max(0.0f, height() - shapePadding() * 2); | |
59 | |
60 return FloatRect(boundsX, boundsY, boundsWidth, boundsHeight); | |
61 } | |
62 | |
63 FloatRect RectangleShape::shapeMarginBounds() const | 43 FloatRect RectangleShape::shapeMarginBounds() const |
64 { | 44 { |
65 ASSERT(shapeMargin() >= 0); | 45 ASSERT(shapeMargin() >= 0); |
66 if (!shapeMargin()) | 46 if (!shapeMargin()) |
67 return m_bounds; | 47 return m_bounds; |
68 | 48 |
69 float boundsX = x() - shapeMargin(); | 49 float boundsX = x() - shapeMargin(); |
70 float boundsY = y() - shapeMargin(); | 50 float boundsY = y() - shapeMargin(); |
71 float boundsWidth = width() + shapeMargin() * 2; | 51 float boundsWidth = width() + shapeMargin() * 2; |
72 float boundsHeight = height() + shapeMargin() * 2; | 52 float boundsHeight = height() + shapeMargin() * 2; |
(...skipping 28 matching lines...) Expand all Loading... |
101 float yi = y1 - (bounds.maxY() - marginRadiusY); | 81 float yi = y1 - (bounds.maxY() - marginRadiusY); |
102 float xi = ellipseXIntercept(yi, marginRadiusX, marginRadiusY); | 82 float xi = ellipseXIntercept(yi, marginRadiusX, marginRadiusY); |
103 x1 = bounds.x() + marginRadiusX - xi; | 83 x1 = bounds.x() + marginRadiusX - xi; |
104 x2 = bounds.maxX() - marginRadiusX + xi; | 84 x2 = bounds.maxX() - marginRadiusX + xi; |
105 } | 85 } |
106 } | 86 } |
107 | 87 |
108 result.append(LineSegment(x1, x2)); | 88 result.append(LineSegment(x1, x2)); |
109 } | 89 } |
110 | 90 |
111 void RectangleShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logi
calHeight, SegmentList& result) const | |
112 { | |
113 const FloatRect& bounds = shapePaddingBounds(); | |
114 if (bounds.isEmpty()) | |
115 return; | |
116 | |
117 float y1 = logicalTop.toFloat(); | |
118 float y2 = (logicalTop + logicalHeight).toFloat(); | |
119 | |
120 if (y1 < bounds.y() || y2 > bounds.maxY()) | |
121 return; | |
122 | |
123 float x1 = bounds.x(); | |
124 float x2 = bounds.maxX(); | |
125 | |
126 float paddingRadiusX = std::max(0.0f, rx() - shapePadding()); | |
127 float paddingRadiusY = std::max(0.0f, ry() - shapePadding()); | |
128 | |
129 if (paddingRadiusX > 0) { | |
130 bool y1InterceptsCorner = y1 < bounds.y() + paddingRadiusY; | |
131 bool y2InterceptsCorner = y2 > bounds.maxY() - paddingRadiusY; | |
132 float xi = 0; | |
133 | |
134 if (y1InterceptsCorner && y2InterceptsCorner) { | |
135 if (y1 < bounds.height() + 2 * bounds.y() - y2) { | |
136 float yi = y1 - bounds.y() - paddingRadiusY; | |
137 xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY); | |
138 } else { | |
139 float yi = y2 - (bounds.maxY() - paddingRadiusY); | |
140 xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY); | |
141 } | |
142 } else if (y1InterceptsCorner) { | |
143 float yi = y1 - bounds.y() - paddingRadiusY; | |
144 xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY); | |
145 } else if (y2InterceptsCorner) { | |
146 float yi = y2 - (bounds.maxY() - paddingRadiusY); | |
147 xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY); | |
148 } | |
149 | |
150 if (y1InterceptsCorner || y2InterceptsCorner) { | |
151 x1 = bounds.x() + paddingRadiusX - xi; | |
152 x2 = bounds.maxX() - paddingRadiusX + xi; | |
153 } | |
154 } | |
155 | |
156 result.append(LineSegment(x1, x2)); | |
157 } | |
158 | |
159 static FloatPoint cornerInterceptForWidth(float width, float widthAtIntercept, f
loat rx, float ry) | |
160 { | |
161 float xi = (width - widthAtIntercept) / 2; | |
162 float yi = ry - ellipseYIntercept(rx - xi, rx, ry); | |
163 return FloatPoint(xi, yi); | |
164 } | |
165 | |
166 bool RectangleShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalInterv
alTop, const FloatSize& minLogicalIntervalSize, LayoutUnit& result) const | |
167 { | |
168 float minIntervalTop = minLogicalIntervalTop.toFloat(); | |
169 float minIntervalHeight = minLogicalIntervalSize.height(); | |
170 float minIntervalWidth = minLogicalIntervalSize.width(); | |
171 | |
172 const FloatRect& bounds = shapePaddingBounds(); | |
173 if (bounds.isEmpty() || minIntervalWidth > bounds.width()) | |
174 return false; | |
175 | |
176 // FIXME: Shapes should be made to use LayoutUnits to avoid broken construct
s like this. | |
177 float minY = LayoutUnit::fromFloatCeil(std::max(bounds.y(), minIntervalTop))
.toFloat(); | |
178 float maxY = minY + minIntervalHeight; | |
179 | |
180 if (maxY > bounds.maxY()) | |
181 return false; | |
182 | |
183 float paddingRadiusX = std::max(0.0f, rx() - shapePadding()); | |
184 float paddingRadiusY = std::max(0.0f, ry() - shapePadding()); | |
185 | |
186 bool intervalOverlapsMinCorner = minY < bounds.y() + paddingRadiusY; | |
187 bool intervalOverlapsMaxCorner = maxY > bounds.maxY() - paddingRadiusY; | |
188 | |
189 if (!intervalOverlapsMinCorner && !intervalOverlapsMaxCorner) { | |
190 result = minY; | |
191 return true; | |
192 } | |
193 | |
194 float centerY = bounds.y() + bounds.height() / 2; | |
195 bool minCornerDefinesX = fabs(centerY - minY) > fabs(centerY - maxY); | |
196 bool intervalFitsWithinCorners = minIntervalWidth + 2 * paddingRadiusX <= bo
unds.width(); | |
197 FloatPoint cornerIntercept = cornerInterceptForWidth(bounds.width(), minInte
rvalWidth, paddingRadiusX, paddingRadiusY); | |
198 | |
199 if (intervalOverlapsMinCorner && (!intervalOverlapsMaxCorner || minCornerDef
inesX)) { | |
200 if (intervalFitsWithinCorners || bounds.y() + cornerIntercept.y() < minY
) { | |
201 result = minY; | |
202 return true; | |
203 } | |
204 if (minIntervalHeight < bounds.height() - (2 * cornerIntercept.y())) { | |
205 result = LayoutUnit::fromFloatCeil(bounds.y() + cornerIntercept.y())
; | |
206 return true; | |
207 } | |
208 } | |
209 | |
210 if (intervalOverlapsMaxCorner && (!intervalOverlapsMinCorner || !minCornerDe
finesX)) { | |
211 if (intervalFitsWithinCorners || minY <= bounds.maxY() - cornerIntercep
t.y() - minIntervalHeight) { | |
212 result = minY; | |
213 return true; | |
214 } | |
215 } | |
216 | |
217 return false; | |
218 } | |
219 | |
220 } // namespace WebCore | 91 } // namespace WebCore |
OLD | NEW |