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

Side by Side Diff: services/view_manager/scheduled_animation_group.cc

Issue 1531403003: Delete the ViewManager and WindowManager services. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-3
Patch Set: rebase Created 4 years, 10 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
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/view_manager/scheduled_animation_group.h"
6
7 #include <set>
8
9 #include "mojo/converters/geometry/geometry_type_converters.h"
10 #include "services/view_manager/server_view.h"
11
12 using mojo::AnimationProperty;
13
14 namespace view_manager {
15 namespace {
16
17 using Sequences = std::vector<ScheduledAnimationSequence>;
18
19 // Gets the value of |property| from |view| into |value|.
20 void GetValueFromView(const ServerView* view,
21 AnimationProperty property,
22 ScheduledAnimationValue* value) {
23 switch (property) {
24 case AnimationProperty::NONE:
25 NOTREACHED();
26 break;
27 case AnimationProperty::OPACITY:
28 value->float_value = view->opacity();
29 break;
30 case AnimationProperty::TRANSFORM:
31 value->transform = view->transform();
32 break;
33 }
34 }
35
36 // Sets the value of |property| from |value| into |view|.
37 void SetViewPropertyFromValue(ServerView* view,
38 AnimationProperty property,
39 const ScheduledAnimationValue& value) {
40 switch (property) {
41 case AnimationProperty::NONE:
42 break;
43 case AnimationProperty::OPACITY:
44 view->SetOpacity(value.float_value);
45 break;
46 case AnimationProperty::TRANSFORM:
47 view->SetTransform(value.transform);
48 break;
49 }
50 }
51
52 // Sets the value of |property| into |view| between two points.
53 void SetViewPropertyFromValueBetween(ServerView* view,
54 AnimationProperty property,
55 double value,
56 gfx::Tween::Type tween_type,
57 const ScheduledAnimationValue& start,
58 const ScheduledAnimationValue& target) {
59 const double tween_value = gfx::Tween::CalculateValue(tween_type, value);
60 switch (property) {
61 case AnimationProperty::NONE:
62 break;
63 case AnimationProperty::OPACITY:
64 view->SetOpacity(gfx::Tween::FloatValueBetween(
65 tween_value, start.float_value, target.float_value));
66 break;
67 case AnimationProperty::TRANSFORM:
68 view->SetTransform(gfx::Tween::TransformValueBetween(
69 tween_value, start.transform, target.transform));
70 break;
71 }
72 }
73
74 gfx::Tween::Type AnimationTypeToTweenType(mojo::AnimationTweenType type) {
75 switch (type) {
76 case mojo::AnimationTweenType::LINEAR:
77 return gfx::Tween::LINEAR;
78 case mojo::AnimationTweenType::EASE_IN:
79 return gfx::Tween::EASE_IN;
80 case mojo::AnimationTweenType::EASE_OUT:
81 return gfx::Tween::EASE_OUT;
82 case mojo::AnimationTweenType::EASE_IN_OUT:
83 return gfx::Tween::EASE_IN_OUT;
84 }
85 return gfx::Tween::LINEAR;
86 }
87
88 void ConvertToScheduledValue(const mojo::AnimationValue& transport_value,
89 ScheduledAnimationValue* value) {
90 value->float_value = transport_value.float_value;
91 value->transform = transport_value.transform.To<gfx::Transform>();
92 }
93
94 void ConvertToScheduledElement(const mojo::AnimationElement& transport_element,
95 ScheduledAnimationElement* element) {
96 element->property = transport_element.property;
97 element->duration =
98 base::TimeDelta::FromMicroseconds(transport_element.duration);
99 element->tween_type = AnimationTypeToTweenType(transport_element.tween_type);
100 if (transport_element.property != AnimationProperty::NONE) {
101 if (transport_element.start_value.get()) {
102 element->is_start_valid = true;
103 ConvertToScheduledValue(*transport_element.start_value,
104 &(element->start_value));
105 } else {
106 element->is_start_valid = false;
107 }
108 ConvertToScheduledValue(*transport_element.target_value,
109 &(element->target_value));
110 }
111 }
112
113 bool IsAnimationValueValid(AnimationProperty property,
114 const mojo::AnimationValue& value) {
115 switch (property) {
116 case AnimationProperty::NONE:
117 NOTREACHED();
118 return false;
119 case AnimationProperty::OPACITY:
120 return value.float_value >= 0.f && value.float_value <= 1.f;
121 case AnimationProperty::TRANSFORM:
122 return value.transform.get() && value.transform->matrix.size() == 16u;
123 }
124 return false;
125 }
126
127 bool IsAnimationElementValid(const mojo::AnimationElement& element) {
128 if (element.property == AnimationProperty::NONE)
129 return true; // None is a pause and doesn't need any values.
130 if (element.start_value.get() &&
131 !IsAnimationValueValid(element.property, *element.start_value))
132 return false;
133 // For all other properties we require a target.
134 return element.target_value.get() &&
135 IsAnimationValueValid(element.property, *element.target_value);
136 }
137
138 bool IsAnimationSequenceValid(const mojo::AnimationSequence& sequence) {
139 if (sequence.elements.size() == 0u)
140 return false;
141
142 for (size_t i = 0; i < sequence.elements.size(); ++i) {
143 if (!IsAnimationElementValid(*sequence.elements[i]))
144 return false;
145 }
146 return true;
147 }
148
149 bool IsAnimationGroupValid(const mojo::AnimationGroup& transport_group) {
150 if (transport_group.sequences.size() == 0u)
151 return false;
152 for (size_t i = 0; i < transport_group.sequences.size(); ++i) {
153 if (!IsAnimationSequenceValid(*transport_group.sequences[i]))
154 return false;
155 }
156 return true;
157 }
158
159 // If the start value for |element| isn't valid, the value for the property
160 // is obtained from |view| and placed into |element|.
161 void GetStartValueFromViewIfNecessary(const ServerView* view,
162 ScheduledAnimationElement* element) {
163 if (element->property != AnimationProperty::NONE &&
164 !element->is_start_valid) {
165 GetValueFromView(view, element->property, &(element->start_value));
166 }
167 }
168
169 void GetScheduledAnimationProperties(const Sequences& sequences,
170 std::set<AnimationProperty>* properties) {
171 for (const ScheduledAnimationSequence& sequence : sequences) {
172 for (const ScheduledAnimationElement& element : sequence.elements)
173 properties->insert(element.property);
174 }
175 }
176
177 void SetPropertyToTargetProperty(ServerView* view,
178 mojo::AnimationProperty property,
179 const Sequences& sequences) {
180 // NOTE: this doesn't deal with |cycle_count| quite right, but I'm honestly
181 // not sure we really want to support the same property in multiple sequences
182 // animating at once so I'm not dealing.
183 base::TimeDelta max_end_duration;
184 scoped_ptr<ScheduledAnimationValue> value;
185 for (const ScheduledAnimationSequence& sequence : sequences) {
186 base::TimeDelta duration;
187 for (const ScheduledAnimationElement& element : sequence.elements) {
188 if (element.property != property)
189 continue;
190
191 duration += element.duration;
192 if (duration > max_end_duration) {
193 max_end_duration = duration;
194 value.reset(new ScheduledAnimationValue(element.target_value));
195 }
196 }
197 }
198 if (value.get())
199 SetViewPropertyFromValue(view, property, *value);
200 }
201
202 void ConvertSequenceToScheduled(
203 const mojo::AnimationSequence& transport_sequence,
204 base::TimeTicks now,
205 ScheduledAnimationSequence* sequence) {
206 sequence->run_until_stopped = transport_sequence.cycle_count == 0u;
207 sequence->cycle_count = transport_sequence.cycle_count;
208 DCHECK_NE(0u, transport_sequence.elements.size());
209 sequence->elements.resize(transport_sequence.elements.size());
210
211 base::TimeTicks element_start_time = now;
212 for (size_t i = 0; i < transport_sequence.elements.size(); ++i) {
213 ConvertToScheduledElement(*(transport_sequence.elements[i].get()),
214 &(sequence->elements[i]));
215 sequence->elements[i].start_time = element_start_time;
216 sequence->duration += sequence->elements[i].duration;
217 element_start_time += sequence->elements[i].duration;
218 }
219 }
220
221 bool AdvanceSequence(ServerView* view,
222 ScheduledAnimationSequence* sequence,
223 base::TimeTicks now) {
224 ScheduledAnimationElement* element =
225 &(sequence->elements[sequence->current_index]);
226 while (element->start_time + element->duration < now) {
227 SetViewPropertyFromValue(view, element->property, element->target_value);
228 if (++sequence->current_index == sequence->elements.size()) {
229 if (!sequence->run_until_stopped && --sequence->cycle_count == 0) {
230 SetViewPropertyFromValue(view, element->property,
231 element->target_value);
232 return false;
233 }
234
235 sequence->current_index = 0;
236 }
237 sequence->elements[sequence->current_index].start_time =
238 element->start_time + element->duration;
239 element = &(sequence->elements[sequence->current_index]);
240 GetStartValueFromViewIfNecessary(view, element);
241
242 // It's possible for the delta between now and |last_tick_time_| to be very
243 // big (could happen if machine sleeps and is woken up much later). Normally
244 // the repeat count is smallish, so we don't bother optimizing it. OTOH if
245 // a sequence repeats forever we optimize it lest we get stuck in this loop
246 // for a very long time.
247 if (sequence->run_until_stopped && sequence->current_index == 0) {
248 element->start_time =
249 now - base::TimeDelta::FromMicroseconds(
250 (now - element->start_time).InMicroseconds() %
251 sequence->duration.InMicroseconds());
252 }
253 }
254 return true;
255 }
256
257 } // namespace
258
259 ScheduledAnimationValue::ScheduledAnimationValue() {
260 }
261 ScheduledAnimationValue::~ScheduledAnimationValue() {
262 }
263
264 ScheduledAnimationElement::ScheduledAnimationElement()
265 : property(AnimationProperty::OPACITY),
266 tween_type(gfx::Tween::EASE_IN),
267 is_start_valid(false) {
268 }
269 ScheduledAnimationElement::~ScheduledAnimationElement() {
270 }
271
272 ScheduledAnimationSequence::ScheduledAnimationSequence()
273 : run_until_stopped(false), cycle_count(0), current_index(0u) {
274 }
275 ScheduledAnimationSequence::~ScheduledAnimationSequence() {
276 }
277
278 ScheduledAnimationGroup::~ScheduledAnimationGroup() {
279 }
280
281 // static
282 scoped_ptr<ScheduledAnimationGroup> ScheduledAnimationGroup::Create(
283 ServerView* view,
284 base::TimeTicks now,
285 uint32_t id,
286 const mojo::AnimationGroup& transport_group) {
287 if (!IsAnimationGroupValid(transport_group))
288 return nullptr;
289
290 scoped_ptr<ScheduledAnimationGroup> group(
291 new ScheduledAnimationGroup(view, id, now));
292 group->sequences_.resize(transport_group.sequences.size());
293 for (size_t i = 0; i < transport_group.sequences.size(); ++i) {
294 const mojo::AnimationSequence& transport_sequence(
295 *(transport_group.sequences[i]));
296 DCHECK_NE(0u, transport_sequence.elements.size());
297 ConvertSequenceToScheduled(transport_sequence, now, &group->sequences_[i]);
298 }
299 return group;
300 }
301
302 void ScheduledAnimationGroup::ObtainStartValues() {
303 for (ScheduledAnimationSequence& sequence : sequences_)
304 GetStartValueFromViewIfNecessary(view_, &(sequence.elements[0]));
305 }
306
307 void ScheduledAnimationGroup::SetValuesToTargetValuesForPropertiesNotIn(
308 const ScheduledAnimationGroup& other) {
309 std::set<AnimationProperty> our_properties;
310 GetScheduledAnimationProperties(sequences_, &our_properties);
311
312 std::set<AnimationProperty> other_properties;
313 GetScheduledAnimationProperties(other.sequences_, &other_properties);
314
315 for (AnimationProperty property : our_properties) {
316 if (other_properties.count(property) == 0 &&
317 property != AnimationProperty::NONE) {
318 SetPropertyToTargetProperty(view_, property, sequences_);
319 }
320 }
321 }
322
323 bool ScheduledAnimationGroup::Tick(base::TimeTicks time) {
324 for (Sequences::iterator i = sequences_.begin(); i != sequences_.end();) {
325 if (!AdvanceSequence(view_, &(*i), time)) {
326 i = sequences_.erase(i);
327 continue;
328 }
329 const ScheduledAnimationElement& active_element(
330 i->elements[i->current_index]);
331 const double percent =
332 (time - active_element.start_time).InMillisecondsF() /
333 active_element.duration.InMillisecondsF();
334 SetViewPropertyFromValueBetween(
335 view_, active_element.property, percent, active_element.tween_type,
336 active_element.start_value, active_element.target_value);
337 ++i;
338 }
339 return sequences_.empty();
340 }
341
342 ScheduledAnimationGroup::ScheduledAnimationGroup(ServerView* view,
343 uint32_t id,
344 base::TimeTicks time_scheduled)
345 : view_(view), id_(id), time_scheduled_(time_scheduled) {
346 }
347
348 } // namespace view_manager
OLDNEW
« no previous file with comments | « services/view_manager/scheduled_animation_group.h ('k') | services/view_manager/scheduled_animation_group_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698