1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "modules/skottie/src/SkottieJson.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkData.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
12cb93a386Sopenharmony_ci#include "include/core/SkPoint.h"
13cb93a386Sopenharmony_ci#include "include/core/SkScalar.h"
14cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
15cb93a386Sopenharmony_ci#include "include/core/SkString.h"
16cb93a386Sopenharmony_ci#include "modules/skottie/src/SkottieValue.h"
17cb93a386Sopenharmony_ci#include <vector>
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_cinamespace skottie {
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ciusing namespace skjson;
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_citemplate <>
24cb93a386Sopenharmony_cibool Parse<SkScalar>(const Value& v, SkScalar* s) {
25cb93a386Sopenharmony_ci    // Some versions wrap values as single-element arrays.
26cb93a386Sopenharmony_ci    if (const skjson::ArrayValue* array = v) {
27cb93a386Sopenharmony_ci        if (array->size() > 0) {
28cb93a386Sopenharmony_ci            return Parse((*array)[0], s);
29cb93a386Sopenharmony_ci        }
30cb93a386Sopenharmony_ci    }
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    if (const skjson::NumberValue* num = v) {
33cb93a386Sopenharmony_ci        *s = static_cast<SkScalar>(**num);
34cb93a386Sopenharmony_ci        return true;
35cb93a386Sopenharmony_ci    }
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci    return false;
38cb93a386Sopenharmony_ci}
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_citemplate <>
41cb93a386Sopenharmony_cibool Parse<bool>(const Value& v, bool* b) {
42cb93a386Sopenharmony_ci    switch(v.getType()) {
43cb93a386Sopenharmony_ci    case Value::Type::kNumber:
44cb93a386Sopenharmony_ci        *b = SkToBool(*v.as<NumberValue>());
45cb93a386Sopenharmony_ci        return true;
46cb93a386Sopenharmony_ci    case Value::Type::kBool:
47cb93a386Sopenharmony_ci        *b = *v.as<BoolValue>();
48cb93a386Sopenharmony_ci        return true;
49cb93a386Sopenharmony_ci    default:
50cb93a386Sopenharmony_ci        break;
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci    return false;
54cb93a386Sopenharmony_ci}
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_citemplate <typename T>
57cb93a386Sopenharmony_cibool ParseIntegral(const Value& v, T* result) {
58cb93a386Sopenharmony_ci    if (const skjson::NumberValue* num = v) {
59cb93a386Sopenharmony_ci        const auto dbl = **num;
60cb93a386Sopenharmony_ci        *result = static_cast<T>(dbl);
61cb93a386Sopenharmony_ci        return static_cast<double>(*result) == dbl;
62cb93a386Sopenharmony_ci    }
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    return false;
65cb93a386Sopenharmony_ci}
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_citemplate <>
68cb93a386Sopenharmony_cibool Parse<int>(const Value& v, int* i) {
69cb93a386Sopenharmony_ci    return ParseIntegral(v, i);
70cb93a386Sopenharmony_ci}
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_citemplate <>
73cb93a386Sopenharmony_cibool Parse<size_t>(const Value& v, size_t* sz) {
74cb93a386Sopenharmony_ci    return ParseIntegral(v, sz);
75cb93a386Sopenharmony_ci}
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_citemplate <>
78cb93a386Sopenharmony_cibool Parse<SkString>(const Value& v, SkString* s) {
79cb93a386Sopenharmony_ci    if (const skjson::StringValue* sv = v) {
80cb93a386Sopenharmony_ci        s->set(sv->begin(), sv->size());
81cb93a386Sopenharmony_ci        return true;
82cb93a386Sopenharmony_ci    }
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci    return false;
85cb93a386Sopenharmony_ci}
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_citemplate <>
88cb93a386Sopenharmony_cibool Parse<SkV2>(const Value& v, SkV2* v2) {
89cb93a386Sopenharmony_ci    if (!v.is<ArrayValue>())
90cb93a386Sopenharmony_ci        return false;
91cb93a386Sopenharmony_ci    const auto& av = v.as<ArrayValue>();
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    // We need at least two scalars (BM sometimes exports a third value == 0).
94cb93a386Sopenharmony_ci    return av.size() >= 2
95cb93a386Sopenharmony_ci        && Parse<SkScalar>(av[0], &v2->x)
96cb93a386Sopenharmony_ci        && Parse<SkScalar>(av[1], &v2->y);
97cb93a386Sopenharmony_ci}
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_citemplate <>
100cb93a386Sopenharmony_cibool Parse<SkPoint>(const Value& v, SkPoint* pt) {
101cb93a386Sopenharmony_ci    if (!v.is<ObjectValue>())
102cb93a386Sopenharmony_ci        return false;
103cb93a386Sopenharmony_ci    const auto& ov = v.as<ObjectValue>();
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci    return Parse<SkScalar>(ov["x"], &pt->fX)
106cb93a386Sopenharmony_ci        && Parse<SkScalar>(ov["y"], &pt->fY);
107cb93a386Sopenharmony_ci}
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_citemplate <>
110cb93a386Sopenharmony_cibool Parse<VectorValue>(const Value& v, VectorValue* vec) {
111cb93a386Sopenharmony_ci    if (!v.is<ArrayValue>())
112cb93a386Sopenharmony_ci        return false;
113cb93a386Sopenharmony_ci    const auto& av = v.as<ArrayValue>();
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci    vec->resize(av.size());
116cb93a386Sopenharmony_ci    for (size_t i = 0; i < av.size(); ++i) {
117cb93a386Sopenharmony_ci        if (!Parse(av[i], vec->data() + i)) {
118cb93a386Sopenharmony_ci            return false;
119cb93a386Sopenharmony_ci        }
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    return true;
123cb93a386Sopenharmony_ci}
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci} // namespace skottie
126