• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "stylemgr/app_style_sheet.h"
17 #include "condition_arbitrator.h"
18 #include "js_fwk_common.h"
19 #include "scope_js_value.h"
20 
21 namespace OHOS {
22 namespace ACELite {
Reset()23 void AppStyleSheet::Reset()
24 {
25     if (idSelectors_ != nullptr) {
26         idSelectors_->Reset();
27         delete idSelectors_;
28         idSelectors_ = nullptr;
29     }
30 
31     if (classSelectors_ != nullptr) {
32         classSelectors_->Reset();
33         delete classSelectors_;
34         classSelectors_ = nullptr;
35     }
36 
37     if (keyFrameSelectors_ != nullptr) {
38         keyFrameSelectors_->Reset();
39         delete keyFrameSelectors_;
40         keyFrameSelectors_ = nullptr;
41     }
42 }
43 
InitSheet(jerry_value_t styleSheetObj)44 void AppStyleSheet::InitSheet(jerry_value_t styleSheetObj)
45 {
46     if (jerry_value_is_undefined(styleSheetObj)) {
47         return;
48     }
49 
50     // clear previous style sheet list
51     Reset();
52 
53     // initializa all media query selectors first, as all media query selectors have higher priority
54     InitMediaSelectors(styleSheetObj);
55 
56     // initialize all other normal selectors
57     InitNormalSelectors(styleSheetObj);
58 }
59 
InitMediaSelectors(const jerry_value_t styleSheetObj)60 void AppStyleSheet::InitMediaSelectors(const jerry_value_t styleSheetObj)
61 {
62     // check if media query exists in style sheet
63     const char * const mediaQueryArrayKeyName = "@media";
64     jerry_value_t propNameV =
65             jerry_create_string(reinterpret_cast<jerry_char_t *>(const_cast<char *>(mediaQueryArrayKeyName)));
66     ScopeJSValue propNameP(propNameV);
67     if (!HasOwnProperty(styleSheetObj, propNameV)) {
68         // no media querry items
69         return;
70     }
71 
72     ScopeJSValue mediaQueryArrayValue(jerry_get_property(styleSheetObj, propNameV));
73     if (!jerry_value_is_array(mediaQueryArrayValue.Obain())) {
74         return;
75     }
76 
77     uint32_t conditionCounts = jerry_get_array_length(mediaQueryArrayValue.Obain());
78     const uint32_t maxConditionCount = 256;
79     if (conditionCounts == 0 || conditionCounts > maxConditionCount) {
80         return;
81     }
82     for (uint32_t index = 0; index < conditionCounts; index++) {
83         // get the array item @ index position
84         jerry_value_t mediaArrayItemV = jerry_get_property_by_index(mediaQueryArrayValue.Obain(), index);
85         ScopeJSValue mediaArrayItemP(mediaArrayItemV);
86         // handle single one
87         HandleSingleMediaItem(mediaArrayItemV);
88     }
89 }
90 
HandleSingleMediaItem(const jerry_value_t mediaItem)91 void AppStyleSheet::HandleSingleMediaItem(const jerry_value_t mediaItem)
92 {
93     const char * const conditionKeyName = "condition";
94     jerry_value_t conditionKeyV = jerry_create_string(reinterpret_cast<const jerry_char_t *>(conditionKeyName));
95     ScopeJSValue conditionKeyP(conditionKeyV);
96     if (!JerryHasProperty(mediaItem, conditionKeyV)) {
97         return;
98     }
99     // get condition string
100     jerry_value_t conditionStrJSValue = jerry_get_property(mediaItem, conditionKeyV);
101     ScopeJSValue autoReleaseV(conditionStrJSValue);
102     char *conditionStr = MallocStringOf(conditionStrJSValue);
103     if (conditionStr == nullptr) {
104         return;
105     }
106     ConditionArbitrator arbitrator;
107     bool isMatched = arbitrator.Decide(conditionStr);
108     ace_free(conditionStr);
109     conditionStr = nullptr;
110     if (!isMatched) {
111         // the current media item is not matching with current device environment
112         return;
113     }
114 
115     // matched, parse the item through normal way
116     InitNormalSelectors(mediaItem, true);
117 }
118 
InitNormalSelectors(const jerry_value_t styleSheetObj,bool overwrite)119 void AppStyleSheet::InitNormalSelectors(const jerry_value_t styleSheetObj, bool overwrite)
120 {
121     // init all id selectors
122     const char * const attrIdSelectors = "idSelectors";
123     jerry_value_t propName = jerry_create_string(reinterpret_cast<jerry_char_t *>(const_cast<char *>(attrIdSelectors)));
124     jerry_value_t propValue = UNDEFINED;
125     if (HasOwnProperty(styleSheetObj, propName)) {
126         propValue = jerry_get_property(styleSheetObj, propName);
127         InitSelectors(&idSelectors_, propValue, false, overwrite);
128         jerry_release_value(propValue);
129     }
130     jerry_release_value(propName);
131 
132     // init all class selectors
133     const char * const attrClassSelectors = "classSelectors";
134     propName = jerry_create_string(reinterpret_cast<jerry_char_t *>(const_cast<char *>(attrClassSelectors)));
135     if (HasOwnProperty(styleSheetObj, propName)) {
136         propValue = jerry_get_property(styleSheetObj, propName);
137         InitSelectors(&classSelectors_, propValue, false, overwrite);
138         jerry_release_value(propValue);
139     }
140     jerry_release_value(propName);
141 
142     // init styleSheet
143     const char * const keyFrames = "@keyframes";
144     propName = jerry_create_string(reinterpret_cast<jerry_char_t *>(const_cast<char *>(keyFrames)));
145     if (HasOwnProperty(styleSheetObj, propName)) {
146         propValue = jerry_get_property(styleSheetObj, propName);
147         InitSelectors(&keyFrameSelectors_, propValue, true, overwrite);
148         jerry_release_value(propValue);
149     }
150     jerry_release_value(propName);
151 }
152 
InitSelectors(AppStyleList ** selectorsList,jerry_value_t selectorsObj,bool isKeyFrames,bool overwrite)153 void AppStyleSheet::InitSelectors(AppStyleList **selectorsList, jerry_value_t selectorsObj,
154                                   bool isKeyFrames, bool overwrite)
155 {
156     if (jerry_value_is_undefined(selectorsObj)) {
157         return;
158     }
159 
160     if ((*selectorsList) == nullptr) {
161         (*selectorsList) = new AppStyleList();
162         if ((*selectorsList) == nullptr) {
163             // malloc failed
164             return;
165         }
166     }
167 
168     jerry_value_t styleKeys = jerry_get_object_keys(selectorsObj);
169     uint16_t styleKeySize = jerry_get_array_length(styleKeys);
170     for (uint16_t index = 0; index < styleKeySize; index++) {
171         /* convert style key into char */
172         jerry_value_t styleKey = jerry_get_property_by_index(styleKeys, index);
173         jerry_value_t styleValue = jerry_get_property(selectorsObj, styleKey);
174         AppStyle *newStyle = AppStyle::GenerateFromJS(styleKey, styleValue, isKeyFrames);
175         if (newStyle != nullptr) {
176             AppStyle *existOne = (*selectorsList)->GetExistStyle(newStyle->GetStyleName());
177             if (existOne != nullptr) {
178                 AppStyle::CombineStyles(*existOne, *newStyle, overwrite);
179                 delete newStyle; // combined to exist one, no used
180                 newStyle = nullptr;
181             } else {
182                 (*selectorsList)->AddStyle(newStyle);
183             }
184         }
185         ReleaseJerryValue(styleKey, styleValue, VA_ARG_END_FLAG);
186     }
187 
188     jerry_release_value(styleKeys);
189 }
190 
GetStyleFromIDSelectors(const char * const name) const191 AppStyle *AppStyleSheet::GetStyleFromIDSelectors(const char * const name) const
192 {
193     return GetStyleFromSelectors(idSelectors_, name);
194 }
195 
GetStyleFromClassSelectors(const char * const name) const196 AppStyle *AppStyleSheet::GetStyleFromClassSelectors(const char * const name) const
197 {
198     return GetStyleFromSelectors(classSelectors_, name);
199 }
200 
GetStyleFromKeyFramesSelectors(const char * const name) const201 AppStyle *AppStyleSheet::GetStyleFromKeyFramesSelectors(const char * const name) const
202 {
203     return GetStyleFromSelectors(keyFrameSelectors_, name);
204 }
205 
GetStyleFromSelectors(AppStyleList * selectors,const char * const name) const206 AppStyle *AppStyleSheet::GetStyleFromSelectors(AppStyleList *selectors, const char * const name) const
207 {
208     if ((selectors == nullptr) || (name == nullptr) || strlen(name) == 0) {
209         return nullptr;
210     }
211 
212     AppStyle *first = const_cast<AppStyle *>(selectors->GetFirst());
213     while (first != nullptr) {
214         const char *styleName = first->GetStyleName();
215         if (styleName != nullptr && !strcmp(name, styleName)) {
216             return first;
217         }
218         first = const_cast<AppStyle *>(first->GetNext());
219     }
220 
221     return first;
222 }
223 } // namespace ACELite
224 } // namespace OHOS
225