Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. 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 are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 | 92 |
| 93 ConstIterator begin() const { return ConstIterator(values_.begin()); } | 93 ConstIterator begin() const { return ConstIterator(values_.begin()); } |
| 94 ConstIterator end() const { return ConstIterator(values_.end()); } | 94 ConstIterator end() const { return ConstIterator(values_.end()); } |
| 95 | 95 |
| 96 void Append(ItemPropertyType* new_item) { | 96 void Append(ItemPropertyType* new_item) { |
| 97 DCHECK(new_item); | 97 DCHECK(new_item); |
| 98 values_.push_back(new_item); | 98 values_.push_back(new_item); |
| 99 new_item->SetOwnerList(this); | 99 new_item->SetOwnerList(this); |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool operator==(const Derived&) const; | 102 bool operator==(const Derived& other) const { |
| 103 return values_ == other.values_; | |
| 104 } | |
| 103 bool operator!=(const Derived& other) const { return !(*this == other); } | 105 bool operator!=(const Derived& other) const { return !(*this == other); } |
| 104 | 106 |
| 105 bool IsEmpty() const { return !length(); } | 107 bool IsEmpty() const { return !length(); } |
| 106 | 108 |
| 107 virtual Derived* Clone() { | 109 virtual Derived* Clone() { |
| 108 Derived* svg_list = Derived::Create(); | 110 Derived* svg_list = Derived::Create(); |
| 109 svg_list->DeepCopy(static_cast<Derived*>(this)); | 111 svg_list->DeepCopy(static_cast<Derived*>(this)); |
| 110 return svg_list; | 112 return svg_list; |
| 111 } | 113 } |
| 112 | 114 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 135 Derived* to_list, | 137 Derived* to_list, |
| 136 float percentage, | 138 float percentage, |
| 137 AnimationMode); | 139 AnimationMode); |
| 138 | 140 |
| 139 virtual ItemPropertyType* CreatePaddingItem() const { | 141 virtual ItemPropertyType* CreatePaddingItem() const { |
| 140 return ItemPropertyType::Create(); | 142 return ItemPropertyType::Create(); |
| 141 } | 143 } |
| 142 | 144 |
| 143 private: | 145 private: |
| 144 inline bool CheckIndexBound(size_t, ExceptionState&); | 146 inline bool CheckIndexBound(size_t, ExceptionState&); |
| 145 size_t FindItem(ItemPropertyType*); | |
| 146 | 147 |
| 147 HeapVector<Member<ItemPropertyType>> values_; | 148 HeapVector<Member<ItemPropertyType>> values_; |
| 148 }; | 149 }; |
| 149 | 150 |
| 150 template <typename Derived, typename ItemProperty> | 151 template <typename Derived, typename ItemProperty> |
| 151 bool SVGListPropertyHelper<Derived, ItemProperty>::operator==( | 152 void SVGListPropertyHelper<Derived, ItemProperty>::Clear() { |
| 152 const Derived& other) const { | 153 // Detach all list items as they are no longer part of this list. |
| 153 if (length() != other.length()) | 154 for (auto& value : values_) { |
| 154 return false; | 155 DCHECK_EQ(value->OwnerList(), this); |
| 155 | 156 value->SetOwnerList(nullptr); |
| 156 size_t size = length(); | |
| 157 for (size_t i = 0; i < size; ++i) { | |
| 158 if (*at(i) != *other.at(i)) | |
| 159 return false; | |
| 160 } | 157 } |
| 161 | |
| 162 return true; | |
| 163 } | |
| 164 | |
| 165 template <typename Derived, typename ItemProperty> | |
| 166 void SVGListPropertyHelper<Derived, ItemProperty>::Clear() { | |
| 167 // detach all list items as they are no longer part of this list | |
| 168 typename HeapVector<Member<ItemPropertyType>>::const_iterator it = | |
| 169 values_.begin(); | |
| 170 typename HeapVector<Member<ItemPropertyType>>::const_iterator it_end = | |
| 171 values_.end(); | |
| 172 for (; it != it_end; ++it) { | |
| 173 DCHECK_EQ((*it)->OwnerList(), this); | |
| 174 (*it)->SetOwnerList(nullptr); | |
| 175 } | |
| 176 | |
| 177 values_.clear(); | 158 values_.clear(); |
| 178 } | 159 } |
| 179 | 160 |
| 180 template <typename Derived, typename ItemProperty> | 161 template <typename Derived, typename ItemProperty> |
| 181 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::Initialize( | 162 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::Initialize( |
| 182 ItemProperty* new_item) { | 163 ItemProperty* new_item) { |
| 183 // Spec: Clears all existing current items from the list and re-initializes | 164 // Spec: Clears all existing current items from the list and re-initializes |
| 184 // the list to hold the single item specified by the parameter. | 165 // the list to hold the single item specified by the parameter. |
| 185 Clear(); | 166 Clear(); |
| 186 Append(new_item); | 167 Append(new_item); |
| 187 return new_item; | 168 return new_item; |
| 188 } | 169 } |
| 189 | 170 |
| 190 template <typename Derived, typename ItemProperty> | 171 template <typename Derived, typename ItemProperty> |
| 191 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::GetItem( | 172 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::GetItem( |
| 192 size_t index, | 173 size_t index, |
| 193 ExceptionState& exception_state) { | 174 ExceptionState& exception_state) { |
| 194 if (!CheckIndexBound(index, exception_state)) | 175 if (!CheckIndexBound(index, exception_state)) |
| 195 return nullptr; | 176 return nullptr; |
| 196 | 177 return at(index); |
| 197 DCHECK_LT(index, values_.size()); | |
| 198 DCHECK_EQ(values_.at(index)->OwnerList(), this); | |
| 199 return values_.at(index); | |
| 200 } | 178 } |
| 201 | 179 |
| 202 template <typename Derived, typename ItemProperty> | 180 template <typename Derived, typename ItemProperty> |
| 203 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::InsertItemBefore( | 181 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::InsertItemBefore( |
| 204 ItemProperty* new_item, | 182 ItemProperty* new_item, |
| 205 size_t index) { | 183 size_t index) { |
| 206 // Spec: If the index is greater than or equal to length, then the new item is | 184 // Spec: If the index is greater than or equal to length, then the new item is |
| 207 // appended to the end of the list. | 185 // appended to the end of the list. |
| 208 if (index > values_.size()) | 186 if (index > values_.size()) |
| 209 index = values_.size(); | 187 index = values_.size(); |
| 210 | 188 |
| 211 // Spec: Inserts a new item into the list at the specified position. The index | 189 // Spec: Inserts a new item into the list at the specified position. The index |
| 212 // of the item before which the new item is to be inserted. The first item is | 190 // of the item before which the new item is to be inserted. The first item is |
| 213 // number 0. If the index is equal to 0, then the new item is inserted at the | 191 // number 0. If the index is equal to 0, then the new item is inserted at the |
| 214 // front of the list. | 192 // front of the list. |
| 215 values_.insert(index, new_item); | 193 values_.insert(index, new_item); |
| 216 new_item->SetOwnerList(this); | 194 new_item->SetOwnerList(this); |
| 217 | |
| 218 return new_item; | 195 return new_item; |
| 219 } | 196 } |
| 220 | 197 |
| 221 template <typename Derived, typename ItemProperty> | 198 template <typename Derived, typename ItemProperty> |
| 222 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::RemoveItem( | 199 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::RemoveItem( |
| 223 size_t index, | 200 size_t index, |
| 224 ExceptionState& exception_state) { | 201 ExceptionState& exception_state) { |
| 225 if (index >= values_.size()) { | 202 if (!CheckIndexBound(index, exception_state)) |
| 226 exception_state.ThrowDOMException( | |
| 227 kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound( | |
| 228 "index", index, values_.size())); | |
| 229 return nullptr; | 203 return nullptr; |
| 230 } | 204 |
| 231 DCHECK_EQ(values_.at(index)->OwnerList(), this); | 205 DCHECK_EQ(values_.at(index)->OwnerList(), this); |
| 232 ItemPropertyType* old_item = values_.at(index); | 206 ItemPropertyType* old_item = values_.at(index); |
| 233 values_.erase(index); | 207 values_.erase(index); |
| 234 old_item->SetOwnerList(0); | 208 old_item->SetOwnerList(nullptr); |
| 235 return old_item; | 209 return old_item; |
| 236 } | 210 } |
| 237 | 211 |
| 238 template <typename Derived, typename ItemProperty> | 212 template <typename Derived, typename ItemProperty> |
| 239 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::AppendItem( | 213 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::AppendItem( |
| 240 ItemProperty* new_item) { | 214 ItemProperty* new_item) { |
| 241 // Append the value and wrapper at the end of the list. | 215 // Append the value and wrapper at the end of the list. |
| 242 Append(new_item); | 216 Append(new_item); |
| 243 | |
| 244 return new_item; | 217 return new_item; |
| 245 } | 218 } |
| 246 | 219 |
| 247 template <typename Derived, typename ItemProperty> | 220 template <typename Derived, typename ItemProperty> |
| 248 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::ReplaceItem( | 221 ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::ReplaceItem( |
| 249 ItemProperty* new_item, | 222 ItemProperty* new_item, |
| 250 size_t index, | 223 size_t index, |
| 251 ExceptionState& exception_state) { | 224 ExceptionState& exception_state) { |
| 252 if (!CheckIndexBound(index, exception_state)) | 225 if (!CheckIndexBound(index, exception_state)) |
| 253 return nullptr; | 226 return nullptr; |
| 254 | 227 |
| 255 if (values_.IsEmpty()) { | 228 if (values_.IsEmpty()) { |
| 256 // 'newItem' already lived in our list, we removed it, and now we're empty, | 229 // 'newItem' already lived in our list, we removed it, and now we're empty, |
| 257 // which means there's nothing to replace. | 230 // which means there's nothing to replace. |
| 231 // TODO(fs): This should not cause us to throw an exception. | |
|
pdr.
2017/06/04 17:05:08
Is this actually deadcode due to the CheckIndexBou
fs
2017/06/04 17:11:27
Yes, it certainly looks that way. Should check tha
| |
| 258 exception_state.ThrowDOMException( | 232 exception_state.ThrowDOMException( |
| 259 kIndexSizeError, | 233 kIndexSizeError, |
| 260 String::Format("Failed to replace the provided item at index %zu.", | 234 String::Format("Failed to replace the provided item at index %zu.", |
| 261 index)); | 235 index)); |
| 262 return nullptr; | 236 return nullptr; |
| 263 } | 237 } |
| 264 | 238 |
| 265 // Update the value at the desired position 'index'. | 239 // Update the value at the desired position 'index'. |
| 266 Member<ItemPropertyType>& position = values_[index]; | 240 Member<ItemPropertyType>& position = values_[index]; |
| 267 DCHECK_EQ(position->OwnerList(), this); | 241 DCHECK_EQ(position->OwnerList(), this); |
| 268 position->SetOwnerList(0); | 242 position->SetOwnerList(nullptr); |
| 269 position = new_item; | 243 position = new_item; |
| 270 new_item->SetOwnerList(this); | 244 new_item->SetOwnerList(this); |
| 271 | |
| 272 return new_item; | 245 return new_item; |
| 273 } | 246 } |
| 274 | 247 |
| 275 template <typename Derived, typename ItemProperty> | 248 template <typename Derived, typename ItemProperty> |
| 276 bool SVGListPropertyHelper<Derived, ItemProperty>::CheckIndexBound( | 249 bool SVGListPropertyHelper<Derived, ItemProperty>::CheckIndexBound( |
| 277 size_t index, | 250 size_t index, |
| 278 ExceptionState& exception_state) { | 251 ExceptionState& exception_state) { |
| 279 if (index >= values_.size()) { | 252 if (index >= values_.size()) { |
| 280 exception_state.ThrowDOMException( | 253 exception_state.ThrowDOMException( |
| 281 kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound( | 254 kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound( |
| 282 "index", index, values_.size())); | 255 "index", index, values_.size())); |
| 283 return false; | 256 return false; |
| 284 } | 257 } |
| 285 | |
| 286 return true; | 258 return true; |
| 287 } | 259 } |
| 288 | 260 |
| 289 template <typename Derived, typename ItemProperty> | 261 template <typename Derived, typename ItemProperty> |
| 290 size_t SVGListPropertyHelper<Derived, ItemProperty>::FindItem( | |
| 291 ItemPropertyType* item) { | |
| 292 return values_.Find(item); | |
| 293 } | |
| 294 | |
| 295 template <typename Derived, typename ItemProperty> | |
| 296 void SVGListPropertyHelper<Derived, ItemProperty>::DeepCopy(Derived* from) { | 262 void SVGListPropertyHelper<Derived, ItemProperty>::DeepCopy(Derived* from) { |
| 297 Clear(); | 263 Clear(); |
| 298 typename HeapVector<Member<ItemPropertyType>>::const_iterator it = | 264 for (const auto& from_value : from->values_) |
| 299 from->values_.begin(); | 265 Append(from_value->Clone()); |
| 300 typename HeapVector<Member<ItemPropertyType>>::const_iterator it_end = | |
| 301 from->values_.end(); | |
| 302 for (; it != it_end; ++it) { | |
| 303 Append((*it)->Clone()); | |
| 304 } | |
| 305 } | 266 } |
| 306 | 267 |
| 307 template <typename Derived, typename ItemProperty> | 268 template <typename Derived, typename ItemProperty> |
| 308 bool SVGListPropertyHelper<Derived, ItemProperty>::AdjustFromToListValues( | 269 bool SVGListPropertyHelper<Derived, ItemProperty>::AdjustFromToListValues( |
| 309 Derived* from_list, | 270 Derived* from_list, |
| 310 Derived* to_list, | 271 Derived* to_list, |
| 311 float percentage, | 272 float percentage, |
| 312 AnimationMode mode) { | 273 AnimationMode mode) { |
| 313 // If no 'to' value is given, nothing to animate. | 274 // If no 'to' value is given, nothing to animate. |
| 314 size_t to_list_size = to_list->length(); | 275 size_t to_list_size = to_list->length(); |
| 315 if (!to_list_size) | 276 if (!to_list_size) |
| 316 return false; | 277 return false; |
| 317 | 278 |
| 318 // If the 'from' value is given and it's length doesn't match the 'to' value | 279 // If the 'from' value is given and it's length doesn't match the 'to' value |
| 319 // list length, fallback to a discrete animation. | 280 // list length, fallback to a discrete animation. |
| 320 size_t from_list_size = from_list->length(); | 281 size_t from_list_size = from_list->length(); |
| 321 if (from_list_size != to_list_size && from_list_size) { | 282 if (from_list_size != to_list_size && from_list_size) { |
| 322 if (percentage < 0.5) { | 283 if (percentage < 0.5) { |
| 323 if (mode != kToAnimation) | 284 if (mode != kToAnimation) |
| 324 DeepCopy(from_list); | 285 DeepCopy(from_list); |
| 325 } else { | 286 } else { |
| 326 DeepCopy(to_list); | 287 DeepCopy(to_list); |
| 327 } | 288 } |
| 328 | |
| 329 return false; | 289 return false; |
| 330 } | 290 } |
| 331 | 291 |
| 332 DCHECK(!from_list_size || from_list_size == to_list_size); | 292 DCHECK(!from_list_size || from_list_size == to_list_size); |
| 333 if (length() < to_list_size) { | 293 for (size_t i = length(); i < to_list_size; ++i) |
| 334 size_t padding_count = to_list_size - length(); | 294 Append(CreatePaddingItem()); |
| 335 for (size_t i = 0; i < padding_count; ++i) | |
| 336 Append(CreatePaddingItem()); | |
| 337 } | |
| 338 | 295 |
| 339 return true; | 296 return true; |
| 340 } | 297 } |
| 341 | 298 |
| 342 } // namespace blink | 299 } // namespace blink |
| 343 | 300 |
| 344 #endif // SVGListPropertyHelper_h | 301 #endif // SVGListPropertyHelper_h |
| OLD | NEW |