| // Copyright 2015 The Cobalt Authors. All Rights Reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include "cobalt/css_parser/position_parse_structures.h" | |
| #include "cobalt/cssom/keyword_value.h" | |
| namespace cobalt { | |
| namespace css_parser { | |
| namespace { | |
| enum Direction { | |
| kHorizontal, | |
| kVertical, | |
| kCenter, | |
| kNone, | |
| }; | |
| Direction ConvertToDirection( | |
| const scoped_refptr<cssom::PropertyValue>& element) { | |
| if (element == cssom::KeywordValue::GetLeft() || | |
| element == cssom::KeywordValue::GetRight()) { | |
| return kHorizontal; | |
| } else if (element == cssom::KeywordValue::GetTop() || | |
| element == cssom::KeywordValue::GetBottom()) { | |
| return kVertical; | |
| } else if (element == cssom::KeywordValue::GetCenter()) { | |
| return kCenter; | |
| } else { | |
| return kNone; | |
| } | |
| } | |
| } // namespace | |
| PositionParseStructure::PositionParseStructure() | |
| : is_horizontal_specified_(false), | |
| is_vertical_specified_(false), | |
| previous_is_non_center_keyword_(false), | |
| number_of_center_keyword_(0) { | |
| position_builder_.reserve(4); | |
| } | |
| bool PositionParseStructure::PushBackElement( | |
| const scoped_refptr<cssom::PropertyValue>& element) { | |
| Direction direction = ConvertToDirection(element); | |
| switch (direction) { | |
| case kHorizontal: { | |
| if (is_horizontal_specified_) { | |
| // Horizontal value has been specified. | |
| return false; | |
| } | |
| is_horizontal_specified_ = true; | |
| previous_is_non_center_keyword_ = true; | |
| break; | |
| } | |
| case kVertical: { | |
| if (is_vertical_specified_) { | |
| // Vertical value has been specified. | |
| return false; | |
| } | |
| is_vertical_specified_ = true; | |
| previous_is_non_center_keyword_ = true; | |
| break; | |
| } | |
| case kCenter: { | |
| if (number_of_center_keyword_ >= 2) { | |
| // More than 2 center keywords. | |
| return false; | |
| } | |
| ++number_of_center_keyword_; | |
| previous_is_non_center_keyword_ = false; | |
| break; | |
| } | |
| case kNone: { | |
| switch (position_builder_.size()) { | |
| case 0: { | |
| // A length or percentage as the first value represents the horizontal | |
| // position (or offset). | |
| is_horizontal_specified_ = true; | |
| break; | |
| } | |
| case 1: { | |
| if (!previous_is_non_center_keyword_) { | |
| // A length or percentage as the second value represents the | |
| // vertical position (or offset). | |
| is_vertical_specified_ = true; | |
| } | |
| previous_is_non_center_keyword_ = false; | |
| break; | |
| } | |
| case 2: // fall-through | |
| case 3: { | |
| if (!previous_is_non_center_keyword_) { | |
| // The offset should be specified for a non center keyword. | |
| return false; | |
| } | |
| previous_is_non_center_keyword_ = false; | |
| break; | |
| } | |
| default: | |
| // Position value couldn't take more than 4 elements. | |
| return false; | |
| } | |
| break; | |
| } | |
| default: | |
| NOTREACHED(); | |
| return false; | |
| } | |
| position_builder_.push_back(element); | |
| return true; | |
| } | |
| bool PositionParseStructure::IsPositionValidOnSizeTwo() { | |
| // Check for the special case that a pair of keywords can be reordered while | |
| // a combination of keyword and length or percentage cannot. eg. 'top center' | |
| // is valid while 'top 50%' is not. | |
| DCHECK_EQ(size_t(2), position_builder_.size()); | |
| Direction first_direction = ConvertToDirection(position_builder_[0]); | |
| Direction second_direction = ConvertToDirection(position_builder_[1]); | |
| // If two values have one center keyword, the other value can be any | |
| // keyword, length or percentage. | |
| if (first_direction == kCenter || second_direction == kCenter) { | |
| return true; | |
| } | |
| if (first_direction == kVertical && !is_horizontal_specified_) { | |
| return false; | |
| } | |
| if (second_direction == kHorizontal && !is_vertical_specified_) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| } // namespace css_parser | |
| } // namespace cobalt |