Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: third_party/WebKit/Source/core/css/CSSGradientValue.cpp

Issue 2392343005: Reflow comments in core/css (Closed)
Patch Set: Revert clang-format Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2015 Google Inc. All rights reserved. 3 * Copyright (C) 2015 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 PassRefPtr<Image> CSSGradientValue::image(const LayoutObject& layoutObject, 71 PassRefPtr<Image> CSSGradientValue::image(const LayoutObject& layoutObject,
72 const IntSize& size) { 72 const IntSize& size) {
73 if (size.isEmpty()) 73 if (size.isEmpty())
74 return nullptr; 74 return nullptr;
75 75
76 bool cacheable = isCacheable(); 76 bool cacheable = isCacheable();
77 if (cacheable) { 77 if (cacheable) {
78 if (!clients().contains(&layoutObject)) 78 if (!clients().contains(&layoutObject))
79 return nullptr; 79 return nullptr;
80 80
81 // Need to look up our size. Create a string of width*height to use as a ha sh key. 81 // Need to look up our size. Create a string of width*height to use as a
82 // hash key.
82 Image* result = getImage(&layoutObject, size); 83 Image* result = getImage(&layoutObject, size);
83 if (result) 84 if (result)
84 return result; 85 return result;
85 } 86 }
86 87
87 // We need to create an image. 88 // We need to create an image.
88 RefPtr<Gradient> gradient; 89 RefPtr<Gradient> gradient;
89 90
90 const ComputedStyle* rootStyle = 91 const ComputedStyle* rootStyle =
91 layoutObject.document().documentElement()->computedStyle(); 92 layoutObject.document().documentElement()->computedStyle();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 GradientStop() : offset(0), specified(false) {} 124 GradientStop() : offset(0), specified(false) {}
124 }; 125 };
125 126
126 static void replaceColorHintsWithColorStops( 127 static void replaceColorHintsWithColorStops(
127 Vector<GradientStop>& stops, 128 Vector<GradientStop>& stops,
128 const HeapVector<CSSGradientColorStop, 2>& cssGradientStops) { 129 const HeapVector<CSSGradientColorStop, 2>& cssGradientStops) {
129 // This algorithm will replace each color interpolation hint with 9 regular 130 // This algorithm will replace each color interpolation hint with 9 regular
130 // color stops. The color values for the new color stops will be calculated 131 // color stops. The color values for the new color stops will be calculated
131 // using the color weighting formula defined in the spec. The new color 132 // using the color weighting formula defined in the spec. The new color
132 // stops will be positioned in such a way that all the pixels between the two 133 // stops will be positioned in such a way that all the pixels between the two
133 // user defined color stops have color values close to the interpolation curve . 134 // user defined color stops have color values close to the interpolation
135 // curve.
134 // If the hint is closer to the left color stop, add 2 stops to the left and 136 // If the hint is closer to the left color stop, add 2 stops to the left and
135 // 6 to the right, else add 6 stops to the left and 2 to the right. 137 // 6 to the right, else add 6 stops to the left and 2 to the right.
136 // The color stops on the side with more space start midway because 138 // The color stops on the side with more space start midway because
137 // the curve approximates a line in that region. 139 // the curve approximates a line in that region.
138 // Using this aproximation, it is possible to discern the color steps when 140 // Using this aproximation, it is possible to discern the color steps when
139 // the gradient is large. If this becomes an issue, we can consider improving 141 // the gradient is large. If this becomes an issue, we can consider improving
140 // the algorithm, or adding support for color interpolation hints to skia shad ers. 142 // the algorithm, or adding support for color interpolation hints to skia
143 // shaders.
141 144
142 int indexOffset = 0; 145 int indexOffset = 0;
143 146
144 // The first and the last color stops cannot be color hints. 147 // The first and the last color stops cannot be color hints.
145 for (size_t i = 1; i < cssGradientStops.size() - 1; ++i) { 148 for (size_t i = 1; i < cssGradientStops.size() - 1; ++i) {
146 if (!cssGradientStops[i].isHint()) 149 if (!cssGradientStops[i].isHint())
147 continue; 150 continue;
148 151
149 // The current index of the stops vector. 152 // The current index of the stops vector.
150 size_t x = i + indexOffset; 153 size_t x = i + indexOffset;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 newStops[7].offset = offset + rightDist / 3; 193 newStops[7].offset = offset + rightDist / 3;
191 newStops[8].offset = offset + rightDist * 2 / 3; 194 newStops[8].offset = offset + rightDist * 2 / 3;
192 } else { 195 } else {
193 newStops[0].offset = offsetLeft + leftDist / 3; 196 newStops[0].offset = offsetLeft + leftDist / 3;
194 newStops[1].offset = offsetLeft + leftDist * 2 / 3; 197 newStops[1].offset = offsetLeft + leftDist * 2 / 3;
195 for (size_t y = 0; y < 7; ++y) 198 for (size_t y = 0; y < 7; ++y)
196 newStops[y + 2].offset = offset + rightDist * y / 13; 199 newStops[y + 2].offset = offset + rightDist * y / 13;
197 } 200 }
198 201
199 // calculate colors for the new color hints. 202 // calculate colors for the new color hints.
200 // The color weighting for the new color stops will be pointRelativeOffset^( ln(0.5)/ln(hintRelativeOffset)). 203 // The color weighting for the new color stops will be
204 // pointRelativeOffset^(ln(0.5)/ln(hintRelativeOffset)).
201 float hintRelativeOffset = leftDist / totalDist; 205 float hintRelativeOffset = leftDist / totalDist;
202 for (size_t y = 0; y < 9; ++y) { 206 for (size_t y = 0; y < 9; ++y) {
203 float pointRelativeOffset = (newStops[y].offset - offsetLeft) / totalDist; 207 float pointRelativeOffset = (newStops[y].offset - offsetLeft) / totalDist;
204 float weighting = 208 float weighting =
205 powf(pointRelativeOffset, logf(.5f) / logf(hintRelativeOffset)); 209 powf(pointRelativeOffset, logf(.5f) / logf(hintRelativeOffset));
206 newStops[y].color = blend(leftColor, rightColor, weighting); 210 newStops[y].color = blend(leftColor, rightColor, weighting);
207 } 211 }
208 212
209 // Replace the color hint with the new color stops. 213 // Replace the color hint with the new color stops.
210 stops.remove(x); 214 stops.remove(x);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 if (gradient->spreadMethod() == SpreadMethodRepeat) 256 if (gradient->spreadMethod() == SpreadMethodRepeat)
253 return true; 257 return true;
254 258
255 // Degenerate stops 259 // Degenerate stops
256 if (stops.first().offset < 0 || stops.last().offset > 1) 260 if (stops.first().offset < 0 || stops.last().offset > 1)
257 return true; 261 return true;
258 262
259 return false; 263 return false;
260 } 264 }
261 265
262 // Redistribute the stops such that they fully cover [0 , 1] and add them to the gradient. 266 // Redistribute the stops such that they fully cover [0 , 1] and add them to the
267 // gradient.
263 static bool normalizeAndAddStops(const Vector<GradientStop>& stops, 268 static bool normalizeAndAddStops(const Vector<GradientStop>& stops,
264 Gradient* gradient) { 269 Gradient* gradient) {
265 ASSERT(stops.size() > 1); 270 ASSERT(stops.size() > 1);
266 271
267 const float firstOffset = stops.first().offset; 272 const float firstOffset = stops.first().offset;
268 const float lastOffset = stops.last().offset; 273 const float lastOffset = stops.last().offset;
269 const float span = lastOffset - firstOffset; 274 const float span = lastOffset - firstOffset;
270 275
271 if (fabs(span) < std::numeric_limits<float>::epsilon()) { 276 if (fabs(span) < std::numeric_limits<float>::epsilon()) {
272 // All stops are coincident -> use a single clamped offset value. 277 // All stops are coincident -> use a single clamped offset value.
273 const float clampedOffset = std::min(std::max(firstOffset, 0.f), 1.f); 278 const float clampedOffset = std::min(std::max(firstOffset, 0.f), 1.f);
274 279
275 // For repeating gradients, a coincident stop set defines a solid-color imag e with the color 280 // For repeating gradients, a coincident stop set defines a solid-color
276 // of the last color-stop in the rule. 281 // image with the color of the last color-stop in the rule.
277 // For non-repeating gradients, both the first color and the last color can be significant 282 // For non-repeating gradients, both the first color and the last color can
278 // (padding on both sides of the offset). 283 // be significant (padding on both sides of the offset).
279 if (gradient->spreadMethod() != SpreadMethodRepeat) 284 if (gradient->spreadMethod() != SpreadMethodRepeat)
280 gradient->addColorStop(clampedOffset, stops.first().color); 285 gradient->addColorStop(clampedOffset, stops.first().color);
281 gradient->addColorStop(clampedOffset, stops.last().color); 286 gradient->addColorStop(clampedOffset, stops.last().color);
282 287
283 return false; 288 return false;
284 } 289 }
285 290
286 ASSERT(span > 0); 291 ASSERT(span > 0);
287 292
288 for (size_t i = 0; i < stops.size(); ++i) { 293 for (size_t i = 0; i < stops.size(); ++i) {
289 const float normalizedOffset = (stops[i].offset - firstOffset) / span; 294 const float normalizedOffset = (stops[i].offset - firstOffset) / span;
290 295
291 // stop offsets should be monotonically increasing in [0 , 1] 296 // stop offsets should be monotonically increasing in [0 , 1]
292 ASSERT(normalizedOffset >= 0 && normalizedOffset <= 1); 297 ASSERT(normalizedOffset >= 0 && normalizedOffset <= 1);
293 ASSERT(i == 0 || 298 ASSERT(i == 0 ||
294 normalizedOffset >= (stops[i - 1].offset - firstOffset) / span); 299 normalizedOffset >= (stops[i - 1].offset - firstOffset) / span);
295 300
296 gradient->addColorStop(normalizedOffset, stops[i].color); 301 gradient->addColorStop(normalizedOffset, stops[i].color);
297 } 302 }
298 303
299 return true; 304 return true;
300 } 305 }
301 306
302 // Collapse all negative-offset stops to 0 and compute an interpolated color val ue for that point. 307 // Collapse all negative-offset stops to 0 and compute an interpolated color
308 // value for that point.
303 static void clampNegativeOffsets(Vector<GradientStop>& stops) { 309 static void clampNegativeOffsets(Vector<GradientStop>& stops) {
304 float lastNegativeOffset = 0; 310 float lastNegativeOffset = 0;
305 311
306 for (size_t i = 0; i < stops.size(); ++i) { 312 for (size_t i = 0; i < stops.size(); ++i) {
307 const float currentOffset = stops[i].offset; 313 const float currentOffset = stops[i].offset;
308 if (currentOffset >= 0) { 314 if (currentOffset >= 0) {
309 if (i > 0) { 315 if (i > 0) {
310 // We found the negative -> positive offset transition: compute an inter polated 316 // We found the negative -> positive offset transition: compute an
311 // color value for 0 and use it with the last clamped stop. 317 // interpolated color value for 0 and use it with the last clamped stop.
312 ASSERT(lastNegativeOffset < 0); 318 ASSERT(lastNegativeOffset < 0);
313 float lerpRatio = 319 float lerpRatio =
314 -lastNegativeOffset / (currentOffset - lastNegativeOffset); 320 -lastNegativeOffset / (currentOffset - lastNegativeOffset);
315 stops[i - 1].color = 321 stops[i - 1].color =
316 blend(stops[i - 1].color, stops[i].color, lerpRatio); 322 blend(stops[i - 1].color, stops[i].color, lerpRatio);
317 } 323 }
318 324
319 break; 325 break;
320 } 326 }
321 327
(...skipping 27 matching lines...) Expand all
349 ASSERT(firstOffset <= lastOffset); 355 ASSERT(firstOffset <= lastOffset);
350 356
351 // Radial offsets are relative to the [0 , endRadius] segment. 357 // Radial offsets are relative to the [0 , endRadius] segment.
352 float adjustedR0 = gradient->endRadius() * firstOffset; 358 float adjustedR0 = gradient->endRadius() * firstOffset;
353 float adjustedR1 = gradient->endRadius() * lastOffset; 359 float adjustedR1 = gradient->endRadius() * lastOffset;
354 ASSERT(adjustedR0 <= adjustedR1); 360 ASSERT(adjustedR0 <= adjustedR1);
355 361
356 // Unlike linear gradients (where we can adjust the points arbitrarily), 362 // Unlike linear gradients (where we can adjust the points arbitrarily),
357 // we cannot let our radii turn negative here. 363 // we cannot let our radii turn negative here.
358 if (adjustedR0 < 0) { 364 if (adjustedR0 < 0) {
359 // For the non-repeat case, this can never happen: clampNegativeOffsets() en sures we don't 365 // For the non-repeat case, this can never happen: clampNegativeOffsets()
360 // have to deal with negative offsets at this point. 366 // ensures we don't have to deal with negative offsets at this point.
361 ASSERT(gradient->spreadMethod() == SpreadMethodRepeat); 367 ASSERT(gradient->spreadMethod() == SpreadMethodRepeat);
362 368
363 // When in repeat mode, we deal with it by repositioning both radii in the p ositive domain - 369 // When in repeat mode, we deal with it by repositioning both radii in the
364 // shifting them by a multiple of the radius span (which is the period of ou r repeating 370 // positive domain - shifting them by a multiple of the radius span (which
365 // gradient -> hence no visible side effects). 371 // is the period of our repeating gradient -> hence no visible side
372 // effects).
366 const float radiusSpan = adjustedR1 - adjustedR0; 373 const float radiusSpan = adjustedR1 - adjustedR0;
367 const float shiftToPositive = radiusSpan * ceilf(-adjustedR0 / radiusSpan); 374 const float shiftToPositive = radiusSpan * ceilf(-adjustedR0 / radiusSpan);
368 adjustedR0 += shiftToPositive; 375 adjustedR0 += shiftToPositive;
369 adjustedR1 += shiftToPositive; 376 adjustedR1 += shiftToPositive;
370 } 377 }
371 ASSERT(adjustedR0 >= 0); 378 ASSERT(adjustedR0 >= 0);
372 ASSERT(adjustedR1 >= adjustedR0); 379 ASSERT(adjustedR1 >= adjustedR0);
373 380
374 gradient->setStartRadius(adjustedR0); 381 gradient->setStartRadius(adjustedR0);
375 gradient->setEndRadius(adjustedR1); 382 gradient->setEndRadius(adjustedR1);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 length = stop.m_position->cssCalcValue() 426 length = stop.m_position->cssCalcValue()
420 ->toCalcValue(conversionData) 427 ->toCalcValue(conversionData)
421 ->evaluate(gradientLength); 428 ->evaluate(gradientLength);
422 stops[i].offset = (gradientLength > 0) ? length / gradientLength : 0; 429 stops[i].offset = (gradientLength > 0) ? length / gradientLength : 0;
423 } else { 430 } else {
424 ASSERT_NOT_REACHED(); 431 ASSERT_NOT_REACHED();
425 stops[i].offset = 0; 432 stops[i].offset = 0;
426 } 433 }
427 stops[i].specified = true; 434 stops[i].specified = true;
428 } else { 435 } else {
429 // If the first color-stop does not have a position, its position defaults to 0%. 436 // If the first color-stop does not have a position, its position defaults
430 // If the last color-stop does not have a position, its position defaults to 100%. 437 // to 0%. If the last color-stop does not have a position, its position
438 // defaults to 100%.
431 if (!i) { 439 if (!i) {
432 stops[i].offset = 0; 440 stops[i].offset = 0;
433 stops[i].specified = true; 441 stops[i].specified = true;
434 } else if (numStops > 1 && i == numStops - 1) { 442 } else if (numStops > 1 && i == numStops - 1) {
435 stops[i].offset = 1; 443 stops[i].offset = 1;
436 stops[i].specified = true; 444 stops[i].specified = true;
437 } 445 }
438 } 446 }
439 447
440 // If a color-stop has a position that is less than the specified position o f any 448 // If a color-stop has a position that is less than the specified position
441 // color-stop before it in the list, its position is changed to be equal to the 449 // of any color-stop before it in the list, its position is changed to be
442 // largest specified position of any color-stop before it. 450 // equal to the largest specified position of any color-stop before it.
443 if (stops[i].specified && i > 0) { 451 if (stops[i].specified && i > 0) {
444 size_t prevSpecifiedIndex; 452 size_t prevSpecifiedIndex;
445 for (prevSpecifiedIndex = i - 1; prevSpecifiedIndex; 453 for (prevSpecifiedIndex = i - 1; prevSpecifiedIndex;
446 --prevSpecifiedIndex) { 454 --prevSpecifiedIndex) {
447 if (stops[prevSpecifiedIndex].specified) 455 if (stops[prevSpecifiedIndex].specified)
448 break; 456 break;
449 } 457 }
450 458
451 if (stops[i].offset < stops[prevSpecifiedIndex].offset) 459 if (stops[i].offset < stops[prevSpecifiedIndex].offset)
452 stops[i].offset = stops[prevSpecifiedIndex].offset; 460 stops[i].offset = stops[prevSpecifiedIndex].offset;
453 } 461 }
454 } 462 }
455 463
456 ASSERT(stops.first().specified && stops.last().specified); 464 ASSERT(stops.first().specified && stops.last().specified);
457 465
458 // If any color-stop still does not have a position, then, for each run of adj acent 466 // If any color-stop still does not have a position, then, for each run of
459 // color-stops without positions, set their positions so that they are evenly spaced 467 // adjacent color-stops without positions, set their positions so that they
460 // between the preceding and following color-stops with positions. 468 // are evenly spaced between the preceding and following color-stops with
469 // positions.
461 if (numStops > 2) { 470 if (numStops > 2) {
462 size_t unspecifiedRunStart = 0; 471 size_t unspecifiedRunStart = 0;
463 bool inUnspecifiedRun = false; 472 bool inUnspecifiedRun = false;
464 473
465 for (size_t i = 0; i < numStops; ++i) { 474 for (size_t i = 0; i < numStops; ++i) {
466 if (!stops[i].specified && !inUnspecifiedRun) { 475 if (!stops[i].specified && !inUnspecifiedRun) {
467 unspecifiedRunStart = i; 476 unspecifiedRunStart = i;
468 inUnspecifiedRun = true; 477 inUnspecifiedRun = true;
469 } else if (stops[i].specified && inUnspecifiedRun) { 478 } else if (stops[i].specified && inUnspecifiedRun) {
470 size_t unspecifiedRunEnd = i; 479 size_t unspecifiedRunEnd = i;
(...skipping 12 matching lines...) Expand all
483 inUnspecifiedRun = false; 492 inUnspecifiedRun = false;
484 } 493 }
485 } 494 }
486 } 495 }
487 496
488 ASSERT(stops.size() == m_stops.size()); 497 ASSERT(stops.size() == m_stops.size());
489 if (hasHints) { 498 if (hasHints) {
490 replaceColorHintsWithColorStops(stops, m_stops); 499 replaceColorHintsWithColorStops(stops, m_stops);
491 } 500 }
492 501
493 // At this point we have a fully resolved set of stops. Time to perform adjust ments for 502 // At this point we have a fully resolved set of stops. Time to perform
494 // repeat gradients and degenerate values if needed. 503 // adjustments for repeat gradients and degenerate values if needed.
495 if (requiresStopsNormalization(stops, gradient)) { 504 if (requiresStopsNormalization(stops, gradient)) {
496 // Negative offsets are only an issue for non-repeating radial gradients: li near gradient 505 // Negative offsets are only an issue for non-repeating radial gradients:
497 // points can be repositioned arbitrarily, and for repeating radial gradient s we shift 506 // linear gradient points can be repositioned arbitrarily, and for repeating
498 // the radii into equivalent positive values. 507 // radial gradients we shift the radii into equivalent positive values.
499 if (isRadialGradientValue() && !m_repeating) 508 if (isRadialGradientValue() && !m_repeating)
500 clampNegativeOffsets(stops); 509 clampNegativeOffsets(stops);
501 510
502 if (normalizeAndAddStops(stops, gradient)) { 511 if (normalizeAndAddStops(stops, gradient)) {
503 if (isLinearGradientValue()) { 512 if (isLinearGradientValue()) {
504 adjustGradientPointsForOffsetRange(gradient, stops.first().offset, 513 adjustGradientPointsForOffsetRange(gradient, stops.first().offset,
505 stops.last().offset); 514 stops.last().offset);
506 } else { 515 } else {
507 adjustGradientRadiiForOffsetRange(gradient, stops.first().offset, 516 adjustGradientRadiiForOffsetRange(gradient, stops.first().offset,
508 stops.last().offset); 517 stops.last().offset);
509 } 518 }
510 } else { 519 } else {
511 // Normalization failed because the stop set is coincident. 520 // Normalization failed because the stop set is coincident.
512 } 521 }
513 } else { 522 } else {
514 // No normalization required, just add the current stops. 523 // No normalization required, just add the current stops.
515 for (const auto& stop : stops) 524 for (const auto& stop : stops)
516 gradient->addColorStop(stop.offset, stop.color); 525 gradient->addColorStop(stop.offset, stop.color);
517 } 526 }
518 } 527 }
519 528
520 static float positionFromValue(const CSSValue* value, 529 static float positionFromValue(const CSSValue* value,
521 const CSSToLengthConversionData& conversionData, 530 const CSSToLengthConversionData& conversionData,
522 const IntSize& size, 531 const IntSize& size,
523 bool isHorizontal) { 532 bool isHorizontal) {
524 int origin = 0; 533 int origin = 0;
525 int sign = 1; 534 int sign = 1;
526 int edgeDistance = isHorizontal ? size.width() : size.height(); 535 int edgeDistance = isHorizontal ? size.width() : size.height();
527 536
528 // In this case the center of the gradient is given relative to an edge in the form of: 537 // In this case the center of the gradient is given relative to an edge in the
529 // [ top | bottom | right | left ] [ <percentage> | <length> ]. 538 // form of: [ top | bottom | right | left ] [ <percentage> | <length> ].
530 if (value->isValuePair()) { 539 if (value->isValuePair()) {
531 const CSSValuePair& pair = toCSSValuePair(*value); 540 const CSSValuePair& pair = toCSSValuePair(*value);
532 CSSValueID originID = toCSSIdentifierValue(pair.first()).getValueID(); 541 CSSValueID originID = toCSSIdentifierValue(pair.first()).getValueID();
533 value = &pair.second(); 542 value = &pair.second();
534 543
535 if (originID == CSSValueRight || originID == CSSValueBottom) { 544 if (originID == CSSValueRight || originID == CSSValueBottom) {
536 // For right/bottom, the offset is relative to the far edge. 545 // For right/bottom, the offset is relative to the far edge.
537 origin = edgeDistance; 546 origin = edgeDistance;
538 sign = -1; 547 sign = -1;
539 } 548 }
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 result.append(' '); 732 result.append(' ');
724 if (stop.m_position) 733 if (stop.m_position)
725 result.append(stop.m_position->cssText()); 734 result.append(stop.m_position->cssText());
726 } 735 }
727 } 736 }
728 737
729 result.append(')'); 738 result.append(')');
730 return result.toString(); 739 return result.toString();
731 } 740 }
732 741
733 // Compute the endpoints so that a gradient of the given angle covers a box of t he given size. 742 // Compute the endpoints so that a gradient of the given angle covers a box of
743 // the given size.
734 static void endPointsFromAngle(float angleDeg, 744 static void endPointsFromAngle(float angleDeg,
735 const IntSize& size, 745 const IntSize& size,
736 FloatPoint& firstPoint, 746 FloatPoint& firstPoint,
737 FloatPoint& secondPoint, 747 FloatPoint& secondPoint,
738 CSSGradientType type) { 748 CSSGradientType type) {
739 // Prefixed gradients use "polar coordinate" angles, rather than "bearing" ang les. 749 // Prefixed gradients use "polar coordinate" angles, rather than "bearing"
750 // angles.
740 if (type == CSSPrefixedLinearGradient) 751 if (type == CSSPrefixedLinearGradient)
741 angleDeg = 90 - angleDeg; 752 angleDeg = 90 - angleDeg;
742 753
743 angleDeg = fmodf(angleDeg, 360); 754 angleDeg = fmodf(angleDeg, 360);
744 if (angleDeg < 0) 755 if (angleDeg < 0)
745 angleDeg += 360; 756 angleDeg += 360;
746 757
747 if (!angleDeg) { 758 if (!angleDeg) {
748 firstPoint.set(0, size.height()); 759 firstPoint.set(0, size.height());
749 secondPoint.set(0, 0); 760 secondPoint.set(0, 0);
(...skipping 15 matching lines...) Expand all
765 if (angleDeg == 270) { 776 if (angleDeg == 270) {
766 firstPoint.set(size.width(), 0); 777 firstPoint.set(size.width(), 0);
767 secondPoint.set(0, 0); 778 secondPoint.set(0, 0);
768 return; 779 return;
769 } 780 }
770 781
771 // angleDeg is a "bearing angle" (0deg = N, 90deg = E), 782 // angleDeg is a "bearing angle" (0deg = N, 90deg = E),
772 // but tan expects 0deg = E, 90deg = N. 783 // but tan expects 0deg = E, 90deg = N.
773 float slope = tan(deg2rad(90 - angleDeg)); 784 float slope = tan(deg2rad(90 - angleDeg));
774 785
775 // We find the endpoint by computing the intersection of the line formed by th e slope, 786 // We find the endpoint by computing the intersection of the line formed by
776 // and a line perpendicular to it that intersects the corner. 787 // the slope, and a line perpendicular to it that intersects the corner.
777 float perpendicularSlope = -1 / slope; 788 float perpendicularSlope = -1 / slope;
778 789
779 // Compute start corner relative to center, in Cartesian space (+y = up). 790 // Compute start corner relative to center, in Cartesian space (+y = up).
780 float halfHeight = size.height() / 2; 791 float halfHeight = size.height() / 2;
781 float halfWidth = size.width() / 2; 792 float halfWidth = size.width() / 2;
782 FloatPoint endCorner; 793 FloatPoint endCorner;
783 if (angleDeg < 90) 794 if (angleDeg < 90)
784 endCorner.set(halfWidth, halfHeight); 795 endCorner.set(halfWidth, halfHeight);
785 else if (angleDeg < 180) 796 else if (angleDeg < 180)
786 endCorner.set(halfWidth, -halfHeight); 797 endCorner.set(halfWidth, -halfHeight);
787 else if (angleDeg < 270) 798 else if (angleDeg < 270)
788 endCorner.set(-halfWidth, -halfHeight); 799 endCorner.set(-halfWidth, -halfHeight);
789 else 800 else
790 endCorner.set(-halfWidth, halfHeight); 801 endCorner.set(-halfWidth, halfHeight);
791 802
792 // Compute c (of y = mx + c) using the corner point. 803 // Compute c (of y = mx + c) using the corner point.
793 float c = endCorner.y() - perpendicularSlope * endCorner.x(); 804 float c = endCorner.y() - perpendicularSlope * endCorner.x();
794 float endX = c / (slope - perpendicularSlope); 805 float endX = c / (slope - perpendicularSlope);
795 float endY = perpendicularSlope * endX + c; 806 float endY = perpendicularSlope * endX + c;
796 807
797 // We computed the end point, so set the second point, 808 // We computed the end point, so set the second point, taking into account the
798 // taking into account the moved origin and the fact that we're in drawing spa ce (+y = down). 809 // moved origin and the fact that we're in drawing space (+y = down).
799 secondPoint.set(halfWidth + endX, halfHeight - endY); 810 secondPoint.set(halfWidth + endX, halfHeight - endY);
800 // Reflect around the center for the start point. 811 // Reflect around the center for the start point.
801 firstPoint.set(halfWidth - endX, halfHeight + endY); 812 firstPoint.set(halfWidth - endX, halfHeight + endY);
802 } 813 }
803 814
804 PassRefPtr<Gradient> CSSLinearGradientValue::createGradient( 815 PassRefPtr<Gradient> CSSLinearGradientValue::createGradient(
805 const CSSToLengthConversionData& conversionData, 816 const CSSToLengthConversionData& conversionData,
806 const IntSize& size, 817 const IntSize& size,
807 const LayoutObject& object) { 818 const LayoutObject& object) {
808 ASSERT(!size.isEmpty()); 819 ASSERT(!size.isEmpty());
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 else 1096 else
1086 result = radius->computeLength<float>(conversionData); 1097 result = radius->computeLength<float>(conversionData);
1087 1098
1088 return clampTo<float>(std::max(result, 0.0f)); 1099 return clampTo<float>(std::max(result, 0.0f));
1089 } 1100 }
1090 1101
1091 namespace { 1102 namespace {
1092 1103
1093 enum EndShapeType { CircleEndShape, EllipseEndShape }; 1104 enum EndShapeType { CircleEndShape, EllipseEndShape };
1094 1105
1095 // Compute the radius to the closest/farthest side (depending on the compare fun ctor). 1106 // Compute the radius to the closest/farthest side (depending on the compare
1107 // functor).
1096 FloatSize radiusToSide(const FloatPoint& point, 1108 FloatSize radiusToSide(const FloatPoint& point,
1097 const FloatSize& size, 1109 const FloatSize& size,
1098 EndShapeType shape, 1110 EndShapeType shape,
1099 bool (*compare)(float, float)) { 1111 bool (*compare)(float, float)) {
1100 float dx1 = clampTo<float>(fabs(point.x())); 1112 float dx1 = clampTo<float>(fabs(point.x()));
1101 float dy1 = clampTo<float>(fabs(point.y())); 1113 float dy1 = clampTo<float>(fabs(point.y()));
1102 float dx2 = clampTo<float>(fabs(point.x() - size.width())); 1114 float dx2 = clampTo<float>(fabs(point.x() - size.width()));
1103 float dy2 = clampTo<float>(fabs(point.y() - size.height())); 1115 float dy2 = clampTo<float>(fabs(point.y() - size.height()));
1104 1116
1105 float dx = compare(dx1, dx2) ? dx1 : dx2; 1117 float dx = compare(dx1, dx2) ? dx1 : dx2;
1106 float dy = compare(dy1, dy2) ? dy1 : dy2; 1118 float dy = compare(dy1, dy2) ? dy1 : dy2;
1107 1119
1108 if (shape == CircleEndShape) 1120 if (shape == CircleEndShape)
1109 return compare(dx, dy) ? FloatSize(dx, dx) : FloatSize(dy, dy); 1121 return compare(dx, dy) ? FloatSize(dx, dx) : FloatSize(dy, dy);
1110 1122
1111 ASSERT(shape == EllipseEndShape); 1123 ASSERT(shape == EllipseEndShape);
1112 return FloatSize(dx, dy); 1124 return FloatSize(dx, dy);
1113 } 1125 }
1114 1126
1115 // Compute the radius of an ellipse with center at 0,0 which passes through p, a nd has 1127 // Compute the radius of an ellipse with center at 0,0 which passes through p,
1116 // width/height given by aspectRatio. 1128 // and has width/height given by aspectRatio.
1117 inline FloatSize ellipseRadius(const FloatPoint& p, float aspectRatio) { 1129 inline FloatSize ellipseRadius(const FloatPoint& p, float aspectRatio) {
1118 // If the aspectRatio is 0 or infinite, the ellipse is completely flat. 1130 // If the aspectRatio is 0 or infinite, the ellipse is completely flat.
1119 // TODO(sashab): Implement Degenerate Radial Gradients, see crbug.com/635727. 1131 // TODO(sashab): Implement Degenerate Radial Gradients, see crbug.com/635727.
1120 if (aspectRatio == 0 || std::isinf(aspectRatio)) 1132 if (aspectRatio == 0 || std::isinf(aspectRatio))
1121 return FloatSize(0, 0); 1133 return FloatSize(0, 0);
1122 1134
1123 // x^2/a^2 + y^2/b^2 = 1 1135 // x^2/a^2 + y^2/b^2 = 1
1124 // a/b = aspectRatio, b = a/aspectRatio 1136 // a/b = aspectRatio, b = a/aspectRatio
1125 // a = sqrt(x^2 + y^2/(1/r^2)) 1137 // a = sqrt(x^2 + y^2/(1/r^2))
1126 float a = sqrtf(p.x() * p.x() + p.y() * p.y() * aspectRatio * aspectRatio); 1138 float a = sqrtf(p.x() * p.x() + p.y() * p.y() * aspectRatio * aspectRatio);
1127 return FloatSize(clampTo<float>(a), clampTo<float>(a / aspectRatio)); 1139 return FloatSize(clampTo<float>(a), clampTo<float>(a / aspectRatio));
1128 } 1140 }
1129 1141
1130 // Compute the radius to the closest/farthest corner (depending on the compare f unctor). 1142 // Compute the radius to the closest/farthest corner (depending on the compare
1143 // functor).
1131 FloatSize radiusToCorner(const FloatPoint& point, 1144 FloatSize radiusToCorner(const FloatPoint& point,
1132 const FloatSize& size, 1145 const FloatSize& size,
1133 EndShapeType shape, 1146 EndShapeType shape,
1134 bool (*compare)(float, float)) { 1147 bool (*compare)(float, float)) {
1135 const FloatRect rect(FloatPoint(), size); 1148 const FloatRect rect(FloatPoint(), size);
1136 const FloatPoint corners[] = {rect.minXMinYCorner(), rect.maxXMinYCorner(), 1149 const FloatPoint corners[] = {rect.minXMinYCorner(), rect.maxXMinYCorner(),
1137 rect.maxXMaxYCorner(), rect.minXMaxYCorner()}; 1150 rect.maxXMaxYCorner(), rect.minXMaxYCorner()};
1138 1151
1139 unsigned cornerIndex = 0; 1152 unsigned cornerIndex = 0;
1140 float distance = (point - corners[cornerIndex]).diagonalLength(); 1153 float distance = (point - corners[cornerIndex]).diagonalLength();
1141 for (unsigned i = 1; i < WTF_ARRAY_LENGTH(corners); ++i) { 1154 for (unsigned i = 1; i < WTF_ARRAY_LENGTH(corners); ++i) {
1142 float newDistance = (point - corners[i]).diagonalLength(); 1155 float newDistance = (point - corners[i]).diagonalLength();
1143 if (compare(newDistance, distance)) { 1156 if (compare(newDistance, distance)) {
1144 cornerIndex = i; 1157 cornerIndex = i;
1145 distance = newDistance; 1158 distance = newDistance;
1146 } 1159 }
1147 } 1160 }
1148 1161
1149 if (shape == CircleEndShape) 1162 if (shape == CircleEndShape)
1150 return FloatSize(distance, distance); 1163 return FloatSize(distance, distance);
1151 1164
1152 ASSERT(shape == EllipseEndShape); 1165 ASSERT(shape == EllipseEndShape);
1153 // If the end shape is an ellipse, the gradient-shape has the same ratio of wi dth to height 1166 // If the end shape is an ellipse, the gradient-shape has the same ratio of
1154 // that it would if closest-side or farthest-side were specified, as appropria te. 1167 // width to height that it would if closest-side or farthest-side were
1168 // specified, as appropriate.
1155 const FloatSize sideRadius = 1169 const FloatSize sideRadius =
1156 radiusToSide(point, size, EllipseEndShape, compare); 1170 radiusToSide(point, size, EllipseEndShape, compare);
1157 1171
1158 return ellipseRadius(FloatPoint(corners[cornerIndex] - point), 1172 return ellipseRadius(FloatPoint(corners[cornerIndex] - point),
1159 sideRadius.aspectRatio()); 1173 sideRadius.aspectRatio());
1160 } 1174 }
1161 1175
1162 } // anonymous namespace 1176 } // anonymous namespace
1163 1177
1164 PassRefPtr<Gradient> CSSRadialGradientValue::createGradient( 1178 PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1303 visitor->trace(m_firstRadius); 1317 visitor->trace(m_firstRadius);
1304 visitor->trace(m_secondRadius); 1318 visitor->trace(m_secondRadius);
1305 visitor->trace(m_shape); 1319 visitor->trace(m_shape);
1306 visitor->trace(m_sizingBehavior); 1320 visitor->trace(m_sizingBehavior);
1307 visitor->trace(m_endHorizontalSize); 1321 visitor->trace(m_endHorizontalSize);
1308 visitor->trace(m_endVerticalSize); 1322 visitor->trace(m_endVerticalSize);
1309 CSSGradientValue::traceAfterDispatch(visitor); 1323 CSSGradientValue::traceAfterDispatch(visitor);
1310 } 1324 }
1311 1325
1312 } // namespace blink 1326 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/css/CSSGradientValue.h ('k') | third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698