| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/css/properties/CSSPropertyShapeUtils.h" | 5 #include "core/css/properties/CSSPropertyShapeUtils.h" |
| 6 | 6 |
| 7 #include "core/css/CSSBasicShapeValues.h" | 7 #include "core/css/CSSBasicShapeValues.h" |
| 8 #include "core/css/parser/CSSParserContext.h" | 8 #include "core/css/parser/CSSParserContext.h" |
| 9 #include "core/css/parser/CSSParserMode.h" | 9 #include "core/css/parser/CSSParserMode.h" |
| 10 #include "core/css/parser/CSSParserTokenRange.h" | 10 #include "core/css/parser/CSSParserTokenRange.h" |
| 11 #include "core/css/parser/CSSPropertyParserHelpers.h" | 11 #include "core/css/parser/CSSPropertyParserHelpers.h" |
| 12 | 12 |
| 13 namespace blink { | 13 namespace blink { |
| 14 | 14 |
| 15 using namespace CSSPropertyParserHelpers; | 15 using namespace CSSPropertyParserHelpers; |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 static CSSValue* ConsumeShapeRadius(CSSParserTokenRange& args, | 19 static CSSValue* ConsumeShapeRadius(CSSParserTokenRange& args, |
| 20 CSSParserMode css_parser_mode) { | 20 CSSParserMode css_parser_mode) { |
| 21 if (IdentMatches<CSSValueClosestSide, CSSValueFarthestSide>(args.Peek().Id())) | 21 if (IdentMatches<CSSValueClosestSide, CSSValueFarthestSide>(args.Peek().Id())) |
| 22 return ConsumeIdent(args); | 22 return ConsumeIdent(args); |
| 23 return ConsumeLengthOrPercent(args, css_parser_mode, kValueRangeNonNegative); | 23 return ConsumeLengthOrPercent(args, css_parser_mode, kValueRangeNonNegative); |
| 24 } | 24 } |
| 25 | 25 |
| 26 static CSSBasicShapeCircleValue* ConsumeBasicShapeCircle( | 26 static CSSBasicShapeCircleValue* ConsumeBasicShapeCircle( |
| 27 CSSParserTokenRange& args, | 27 CSSParserTokenRange& args, |
| 28 const CSSParserContext* context) { | 28 const CSSParserContext& context) { |
| 29 // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes | 29 // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes |
| 30 // circle( [<shape-radius>]? [at <position>]? ) | 30 // circle( [<shape-radius>]? [at <position>]? ) |
| 31 CSSBasicShapeCircleValue* shape = CSSBasicShapeCircleValue::Create(); | 31 CSSBasicShapeCircleValue* shape = CSSBasicShapeCircleValue::Create(); |
| 32 if (CSSValue* radius = ConsumeShapeRadius(args, context->Mode())) | 32 if (CSSValue* radius = ConsumeShapeRadius(args, context.Mode())) |
| 33 shape->SetRadius(radius); | 33 shape->SetRadius(radius); |
| 34 if (ConsumeIdent<CSSValueAt>(args)) { | 34 if (ConsumeIdent<CSSValueAt>(args)) { |
| 35 CSSValue* center_x = nullptr; | 35 CSSValue* center_x = nullptr; |
| 36 CSSValue* center_y = nullptr; | 36 CSSValue* center_y = nullptr; |
| 37 if (!ConsumePosition(args, context->Mode(), UnitlessQuirk::kForbid, | 37 if (!ConsumePosition(args, context.Mode(), UnitlessQuirk::kForbid, center_x, |
| 38 center_x, center_y)) | 38 center_y)) |
| 39 return nullptr; | 39 return nullptr; |
| 40 shape->SetCenterX(center_x); | 40 shape->SetCenterX(center_x); |
| 41 shape->SetCenterY(center_y); | 41 shape->SetCenterY(center_y); |
| 42 } | 42 } |
| 43 return shape; | 43 return shape; |
| 44 } | 44 } |
| 45 | 45 |
| 46 static CSSBasicShapeEllipseValue* ConsumeBasicShapeEllipse( | 46 static CSSBasicShapeEllipseValue* ConsumeBasicShapeEllipse( |
| 47 CSSParserTokenRange& args, | 47 CSSParserTokenRange& args, |
| 48 const CSSParserContext* context) { | 48 const CSSParserContext& context) { |
| 49 // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes | 49 // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes |
| 50 // ellipse( [<shape-radius>{2}]? [at <position>]? ) | 50 // ellipse( [<shape-radius>{2}]? [at <position>]? ) |
| 51 CSSBasicShapeEllipseValue* shape = CSSBasicShapeEllipseValue::Create(); | 51 CSSBasicShapeEllipseValue* shape = CSSBasicShapeEllipseValue::Create(); |
| 52 if (CSSValue* radius_x = ConsumeShapeRadius(args, context->Mode())) { | 52 if (CSSValue* radius_x = ConsumeShapeRadius(args, context.Mode())) { |
| 53 shape->SetRadiusX(radius_x); | 53 shape->SetRadiusX(radius_x); |
| 54 if (CSSValue* radius_y = ConsumeShapeRadius(args, context->Mode())) | 54 if (CSSValue* radius_y = ConsumeShapeRadius(args, context.Mode())) |
| 55 shape->SetRadiusY(radius_y); | 55 shape->SetRadiusY(radius_y); |
| 56 } | 56 } |
| 57 if (ConsumeIdent<CSSValueAt>(args)) { | 57 if (ConsumeIdent<CSSValueAt>(args)) { |
| 58 CSSValue* center_x = nullptr; | 58 CSSValue* center_x = nullptr; |
| 59 CSSValue* center_y = nullptr; | 59 CSSValue* center_y = nullptr; |
| 60 if (!ConsumePosition(args, context->Mode(), UnitlessQuirk::kForbid, | 60 if (!ConsumePosition(args, context.Mode(), UnitlessQuirk::kForbid, center_x, |
| 61 center_x, center_y)) | 61 center_y)) |
| 62 return nullptr; | 62 return nullptr; |
| 63 shape->SetCenterX(center_x); | 63 shape->SetCenterX(center_x); |
| 64 shape->SetCenterY(center_y); | 64 shape->SetCenterY(center_y); |
| 65 } | 65 } |
| 66 return shape; | 66 return shape; |
| 67 } | 67 } |
| 68 | 68 |
| 69 static CSSBasicShapePolygonValue* ConsumeBasicShapePolygon( | 69 static CSSBasicShapePolygonValue* ConsumeBasicShapePolygon( |
| 70 CSSParserTokenRange& args, | 70 CSSParserTokenRange& args, |
| 71 const CSSParserContext* context) { | 71 const CSSParserContext& context) { |
| 72 CSSBasicShapePolygonValue* shape = CSSBasicShapePolygonValue::Create(); | 72 CSSBasicShapePolygonValue* shape = CSSBasicShapePolygonValue::Create(); |
| 73 if (IdentMatches<CSSValueEvenodd, CSSValueNonzero>(args.Peek().Id())) { | 73 if (IdentMatches<CSSValueEvenodd, CSSValueNonzero>(args.Peek().Id())) { |
| 74 shape->SetWindRule(args.ConsumeIncludingWhitespace().Id() == CSSValueEvenodd | 74 shape->SetWindRule(args.ConsumeIncludingWhitespace().Id() == CSSValueEvenodd |
| 75 ? RULE_EVENODD | 75 ? RULE_EVENODD |
| 76 : RULE_NONZERO); | 76 : RULE_NONZERO); |
| 77 if (!ConsumeCommaIncludingWhitespace(args)) | 77 if (!ConsumeCommaIncludingWhitespace(args)) |
| 78 return nullptr; | 78 return nullptr; |
| 79 } | 79 } |
| 80 | 80 |
| 81 do { | 81 do { |
| 82 CSSPrimitiveValue* x_length = | 82 CSSPrimitiveValue* x_length = |
| 83 ConsumeLengthOrPercent(args, context->Mode(), kValueRangeAll); | 83 ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll); |
| 84 if (!x_length) | 84 if (!x_length) |
| 85 return nullptr; | 85 return nullptr; |
| 86 CSSPrimitiveValue* y_length = | 86 CSSPrimitiveValue* y_length = |
| 87 ConsumeLengthOrPercent(args, context->Mode(), kValueRangeAll); | 87 ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll); |
| 88 if (!y_length) | 88 if (!y_length) |
| 89 return nullptr; | 89 return nullptr; |
| 90 shape->AppendPoint(x_length, y_length); | 90 shape->AppendPoint(x_length, y_length); |
| 91 } while (ConsumeCommaIncludingWhitespace(args)); | 91 } while (ConsumeCommaIncludingWhitespace(args)); |
| 92 return shape; | 92 return shape; |
| 93 } | 93 } |
| 94 | 94 |
| 95 static CSSBasicShapeInsetValue* ConsumeBasicShapeInset( | 95 static CSSBasicShapeInsetValue* ConsumeBasicShapeInset( |
| 96 CSSParserTokenRange& args, | 96 CSSParserTokenRange& args, |
| 97 const CSSParserContext* context) { | 97 const CSSParserContext& context) { |
| 98 CSSBasicShapeInsetValue* shape = CSSBasicShapeInsetValue::Create(); | 98 CSSBasicShapeInsetValue* shape = CSSBasicShapeInsetValue::Create(); |
| 99 CSSPrimitiveValue* top = | 99 CSSPrimitiveValue* top = |
| 100 ConsumeLengthOrPercent(args, context->Mode(), kValueRangeAll); | 100 ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll); |
| 101 if (!top) | 101 if (!top) |
| 102 return nullptr; | 102 return nullptr; |
| 103 CSSPrimitiveValue* right = | 103 CSSPrimitiveValue* right = |
| 104 ConsumeLengthOrPercent(args, context->Mode(), kValueRangeAll); | 104 ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll); |
| 105 CSSPrimitiveValue* bottom = nullptr; | 105 CSSPrimitiveValue* bottom = nullptr; |
| 106 CSSPrimitiveValue* left = nullptr; | 106 CSSPrimitiveValue* left = nullptr; |
| 107 if (right) { | 107 if (right) { |
| 108 bottom = ConsumeLengthOrPercent(args, context->Mode(), kValueRangeAll); | 108 bottom = ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll); |
| 109 if (bottom) | 109 if (bottom) |
| 110 left = ConsumeLengthOrPercent(args, context->Mode(), kValueRangeAll); | 110 left = ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll); |
| 111 } | 111 } |
| 112 if (left) | 112 if (left) |
| 113 shape->UpdateShapeSize4Values(top, right, bottom, left); | 113 shape->UpdateShapeSize4Values(top, right, bottom, left); |
| 114 else if (bottom) | 114 else if (bottom) |
| 115 shape->UpdateShapeSize3Values(top, right, bottom); | 115 shape->UpdateShapeSize3Values(top, right, bottom); |
| 116 else if (right) | 116 else if (right) |
| 117 shape->UpdateShapeSize2Values(top, right); | 117 shape->UpdateShapeSize2Values(top, right); |
| 118 else | 118 else |
| 119 shape->UpdateShapeSize1Value(top); | 119 shape->UpdateShapeSize1Value(top); |
| 120 | 120 |
| 121 if (ConsumeIdent<CSSValueRound>(args)) { | 121 if (ConsumeIdent<CSSValueRound>(args)) { |
| 122 CSSValue* horizontal_radii[4] = {0}; | 122 CSSValue* horizontal_radii[4] = {0}; |
| 123 CSSValue* vertical_radii[4] = {0}; | 123 CSSValue* vertical_radii[4] = {0}; |
| 124 if (!CSSPropertyShapeUtils::ConsumeRadii(horizontal_radii, vertical_radii, | 124 if (!CSSPropertyShapeUtils::ConsumeRadii(horizontal_radii, vertical_radii, |
| 125 args, context->Mode(), false)) | 125 args, context.Mode(), false)) |
| 126 return nullptr; | 126 return nullptr; |
| 127 shape->SetTopLeftRadius( | 127 shape->SetTopLeftRadius( |
| 128 CSSValuePair::Create(horizontal_radii[0], vertical_radii[0], | 128 CSSValuePair::Create(horizontal_radii[0], vertical_radii[0], |
| 129 CSSValuePair::kDropIdenticalValues)); | 129 CSSValuePair::kDropIdenticalValues)); |
| 130 shape->SetTopRightRadius( | 130 shape->SetTopRightRadius( |
| 131 CSSValuePair::Create(horizontal_radii[1], vertical_radii[1], | 131 CSSValuePair::Create(horizontal_radii[1], vertical_radii[1], |
| 132 CSSValuePair::kDropIdenticalValues)); | 132 CSSValuePair::kDropIdenticalValues)); |
| 133 shape->SetBottomRightRadius( | 133 shape->SetBottomRightRadius( |
| 134 CSSValuePair::Create(horizontal_radii[2], vertical_radii[2], | 134 CSSValuePair::Create(horizontal_radii[2], vertical_radii[2], |
| 135 CSSValuePair::kDropIdenticalValues)); | 135 CSSValuePair::kDropIdenticalValues)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 if (!vertical_radii[0] || !range.AtEnd()) | 181 if (!vertical_radii[0] || !range.AtEnd()) |
| 182 return false; | 182 return false; |
| 183 } | 183 } |
| 184 Complete4Sides(horizontal_radii); | 184 Complete4Sides(horizontal_radii); |
| 185 Complete4Sides(vertical_radii); | 185 Complete4Sides(vertical_radii); |
| 186 return true; | 186 return true; |
| 187 } | 187 } |
| 188 | 188 |
| 189 CSSValue* CSSPropertyShapeUtils::ConsumeBasicShape( | 189 CSSValue* CSSPropertyShapeUtils::ConsumeBasicShape( |
| 190 CSSParserTokenRange& range, | 190 CSSParserTokenRange& range, |
| 191 const CSSParserContext* context) { | 191 const CSSParserContext& context) { |
| 192 CSSValue* shape = nullptr; | 192 CSSValue* shape = nullptr; |
| 193 if (range.Peek().GetType() != kFunctionToken) | 193 if (range.Peek().GetType() != kFunctionToken) |
| 194 return nullptr; | 194 return nullptr; |
| 195 CSSValueID id = range.Peek().FunctionId(); | 195 CSSValueID id = range.Peek().FunctionId(); |
| 196 CSSParserTokenRange range_copy = range; | 196 CSSParserTokenRange range_copy = range; |
| 197 CSSParserTokenRange args = ConsumeFunction(range_copy); | 197 CSSParserTokenRange args = ConsumeFunction(range_copy); |
| 198 if (id == CSSValueCircle) | 198 if (id == CSSValueCircle) |
| 199 shape = ConsumeBasicShapeCircle(args, context); | 199 shape = ConsumeBasicShapeCircle(args, context); |
| 200 else if (id == CSSValueEllipse) | 200 else if (id == CSSValueEllipse) |
| 201 shape = ConsumeBasicShapeEllipse(args, context); | 201 shape = ConsumeBasicShapeEllipse(args, context); |
| 202 else if (id == CSSValuePolygon) | 202 else if (id == CSSValuePolygon) |
| 203 shape = ConsumeBasicShapePolygon(args, context); | 203 shape = ConsumeBasicShapePolygon(args, context); |
| 204 else if (id == CSSValueInset) | 204 else if (id == CSSValueInset) |
| 205 shape = ConsumeBasicShapeInset(args, context); | 205 shape = ConsumeBasicShapeInset(args, context); |
| 206 if (!shape || !args.AtEnd()) | 206 if (!shape || !args.AtEnd()) |
| 207 return nullptr; | 207 return nullptr; |
| 208 range = range_copy; | 208 range = range_copy; |
| 209 return shape; | 209 return shape; |
| 210 } | 210 } |
| 211 | 211 |
| 212 } // namespace blink | 212 } // namespace blink |
| OLD | NEW |