1 /*
2  * Copyright (c) 2022 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 #include "printer_capability_helper.h"
16 #include "napi_print_utils.h"
17 #include "print_constant.h"
18 #include "print_log.h"
19 #include "print_utils.h"
20 #include "print_margin_helper.h"
21 #include "print_page_size_helper.h"
22 #include "print_resolution_helper.h"
23 
24 namespace OHOS::Print {
25 static constexpr const char *PARAM_CAPABILITY_COLORMODE = "colorMode";
26 static constexpr const char *PARAM_CAPABILITY_DUPLEXMODE = "duplexMode";
27 static constexpr const char *PARAM_CAPABILITY_PAGESIZE = "pageSize";
28 static constexpr const char *PARAM_CAPABILITY_RESOLUTION = "resolution";
29 static constexpr const char *PARAM_CAPABILITY_MINMARGIN = "minMargin";
30 static constexpr const char *PARAM_CAPABILITY_OPTION = "options";
31 static constexpr const char *PARAM_CAPABILITY_SUPPORTED_PAGESIZES = "supportedPageSizes";
32 static constexpr const char *PARAM_CAPABILITY_SUPPORTED_COLORMODES = "supportedColorModes";
33 static constexpr const char *PARAM_CAPABILITY_SUPPORTED_DUPLEXMODES = "supportedDuplexModes";
34 static constexpr const char *PARAM_CAPABILITY_SUPPORTED_MEDIA_TYPES = "supportedMediaTypes";
35 static constexpr const char *PARAM_CAPABILITY_SUPPORTED_QUALITIES = "supportedQualities";
36 static constexpr const char *PARAM_CAPABILITY_SUPPORTED_ORIENTATIONS = "supportedOrientations";
37 
MakeJsObject(napi_env env,const PrinterCapability & cap)38 napi_value PrinterCapabilityHelper::MakeJsObject(napi_env env, const PrinterCapability &cap)
39 {
40     napi_value jsObj = nullptr;
41     PRINT_CALL(env, napi_create_object(env, &jsObj));
42     if (jsObj == nullptr) {
43         PRINT_HILOGI("Failed to create js object");
44         return nullptr;
45     }
46     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_CAPABILITY_COLORMODE, cap.GetColorMode());
47     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_CAPABILITY_DUPLEXMODE, cap.GetDuplexMode());
48 
49     CreatePageSizeList(env, jsObj, cap);
50     if (cap.HasResolution()) {
51         CreateResolutionList(env, jsObj, cap);
52     }
53 
54     if (cap.HasSupportedColorMode()) {
55         CreateSupportedColorModeList(env, jsObj, cap);
56     }
57 
58     if (cap.HasSupportedDuplexMode()) {
59         CreateSupportedDuplexModeList(env, jsObj, cap);
60     }
61 
62     if (cap.HasSupportedMediaType()) {
63         CreateSupportedMediaTypeList(env, jsObj, cap);
64     }
65 
66     if (cap.HasSupportedQuality()) {
67         CreateSupportedQualityList(env, jsObj, cap);
68     }
69 
70     if (cap.HasSupportedOrientation()) {
71         CreateSupportedOrientationList(env, jsObj, cap);
72     }
73 
74     if (cap.HasMargin()) {
75         PrintMargin margin;
76         cap.GetMinMargin(margin);
77         napi_value jsMargin = PrintMarginHelper::MakeJsObject(env, margin);
78         PRINT_CALL(env, napi_set_named_property(env, jsObj, PARAM_CAPABILITY_MINMARGIN, jsMargin));
79     }
80 
81     if (cap.HasOption()) {
82         NapiPrintUtils::SetStringPropertyUtf8(env, jsObj, PARAM_CAPABILITY_OPTION, cap.GetOption());
83     }
84     return jsObj;
85 }
86 
87 
CreatePageSizeList(napi_env env,napi_value & jsPrinterCap,const PrinterCapability & cap)88 bool PrinterCapabilityHelper::CreatePageSizeList(napi_env env, napi_value &jsPrinterCap, const PrinterCapability &cap)
89 {
90     napi_value jsPageSizes = nullptr;
91     PRINT_CALL_BASE(env, napi_create_array(env, &jsPageSizes), false);
92     std::vector<PrintPageSize> pageSizeList;
93     cap.GetSupportedPageSize(pageSizeList);
94     uint32_t arrLength = pageSizeList.size();
95 
96     for (uint32_t index = 0; index < arrLength; index++) {
97         napi_value value = PrintPageSizeHelper::MakeJsObject(env, pageSizeList[index]);
98         PRINT_CALL_BASE(env, napi_set_element(env, jsPageSizes, index, value), false);
99     }
100     PRINT_CALL_BASE(
101         env,
102         napi_set_named_property(env, jsPrinterCap, PARAM_CAPABILITY_SUPPORTED_PAGESIZES, jsPageSizes),
103         false);
104     return true;
105 }
106 
CreateResolutionList(napi_env env,napi_value & jsPrinterCap,const PrinterCapability & cap)107 bool PrinterCapabilityHelper::CreateResolutionList(napi_env env, napi_value &jsPrinterCap, const PrinterCapability &cap)
108 {
109     napi_value jsResolutionList = nullptr;
110     PRINT_CALL_BASE(env, napi_create_array(env, &jsResolutionList), false);
111     std::vector<PrintResolution> resolutionList;
112     cap.GetResolution(resolutionList);
113     uint32_t arrLength = resolutionList.size();
114 
115     for (uint32_t index = 0; index < arrLength; index++) {
116         napi_value value = PrintResolutionHelper::MakeJsObject(env, resolutionList[index]);
117         PRINT_CALL_BASE(env, napi_set_element(env, jsResolutionList, index, value), false);
118     }
119     PRINT_CALL_BASE(env,
120         napi_set_named_property(env, jsPrinterCap, PARAM_CAPABILITY_RESOLUTION, jsResolutionList), false);
121     return true;
122 }
123 
CreateSupportedColorModeList(napi_env env,napi_value & jsPrinterCap,const PrinterCapability & cap)124 bool PrinterCapabilityHelper::CreateSupportedColorModeList(napi_env env, napi_value& jsPrinterCap,
125     const PrinterCapability& cap)
126 {
127     napi_value jsSupportedColorModeList = nullptr;
128     PRINT_CALL_BASE(env, napi_create_array(env, &jsSupportedColorModeList), false);
129     std::vector<uint32_t> supportedColorModeList;
130     cap.GetSupportedColorMode(supportedColorModeList);
131     uint32_t arrLength = static_cast<uint32_t>(supportedColorModeList.size());
132     for (uint32_t index = 0; index < arrLength; index++) {
133         napi_value value = NapiPrintUtils::CreateUint32(env, supportedColorModeList[index]);
134         PRINT_CALL_BASE(env, napi_set_element(env, jsSupportedColorModeList, index, value), false);
135     }
136     PRINT_CALL_BASE(
137         env,
138         napi_set_named_property(env, jsPrinterCap, PARAM_CAPABILITY_SUPPORTED_COLORMODES, jsSupportedColorModeList),
139         false);
140     return true;
141 }
142 
CreateSupportedDuplexModeList(napi_env env,napi_value & jsPrinterCap,const PrinterCapability & cap)143 bool PrinterCapabilityHelper::CreateSupportedDuplexModeList(napi_env env, napi_value& jsPrinterCap,
144     const PrinterCapability& cap)
145 {
146     napi_value jsSupportedDuplexModeList = nullptr;
147     PRINT_CALL_BASE(env, napi_create_array(env, &jsSupportedDuplexModeList), false);
148     std::vector<uint32_t> supportedDuplexModeList;
149     cap.GetSupportedDuplexMode(supportedDuplexModeList);
150     uint32_t arrLength = static_cast<uint32_t>(supportedDuplexModeList.size());
151     for (uint32_t index = 0; index < arrLength; index++) {
152         napi_value value = NapiPrintUtils::CreateUint32(env, supportedDuplexModeList[index]);
153         PRINT_CALL_BASE(env, napi_set_element(env, jsSupportedDuplexModeList, index, value), false);
154     }
155     PRINT_CALL_BASE(
156         env,
157         napi_set_named_property(env, jsPrinterCap, PARAM_CAPABILITY_SUPPORTED_DUPLEXMODES, jsSupportedDuplexModeList),
158         false);
159     return true;
160 }
161 
CreateSupportedMediaTypeList(napi_env env,napi_value & jsPrinterCap,const PrinterCapability & cap)162 bool PrinterCapabilityHelper::CreateSupportedMediaTypeList(napi_env env, napi_value& jsPrinterCap,
163     const PrinterCapability& cap)
164 {
165     napi_value jsSupportedMediaTypeList = nullptr;
166     PRINT_CALL_BASE(env, napi_create_array(env, &jsSupportedMediaTypeList), false);
167     std::vector<std::string> supportedMediaTypeList;
168     cap.GetSupportedMediaType(supportedMediaTypeList);
169     uint32_t arrLength = static_cast<uint32_t>(supportedMediaTypeList.size());
170     for (uint32_t index = 0; index < arrLength; index++) {
171         napi_value value = NapiPrintUtils::CreateStringUtf8(env, supportedMediaTypeList[index]);
172         PRINT_CALL_BASE(env, napi_set_element(env, jsSupportedMediaTypeList, index, value), false);
173     }
174     PRINT_CALL_BASE(
175         env,
176         napi_set_named_property(env, jsPrinterCap, PARAM_CAPABILITY_SUPPORTED_MEDIA_TYPES, jsSupportedMediaTypeList),
177         false);
178     return true;
179 }
180 
CreateSupportedQualityList(napi_env env,napi_value & jsPrinterCap,const PrinterCapability & cap)181 bool PrinterCapabilityHelper::CreateSupportedQualityList(napi_env env, napi_value& jsPrinterCap,
182     const PrinterCapability& cap)
183 {
184     napi_value jsSupportedQualitiesList = nullptr;
185     PRINT_CALL_BASE(env, napi_create_array(env, &jsSupportedQualitiesList), false);
186     std::vector<uint32_t> supportedQualitiesList;
187     cap.GetSupportedQuality(supportedQualitiesList);
188     uint32_t arrLength = static_cast<uint32_t>(supportedQualitiesList.size());
189     for (uint32_t index = 0; index < arrLength; index++) {
190         napi_value value = NapiPrintUtils::CreateUint32(env, supportedQualitiesList[index]);
191         PRINT_CALL_BASE(env, napi_set_element(env, jsSupportedQualitiesList, index, value), false);
192     }
193     PRINT_CALL_BASE(
194         env,
195         napi_set_named_property(env, jsPrinterCap, PARAM_CAPABILITY_SUPPORTED_QUALITIES, jsSupportedQualitiesList),
196         false);
197     return true;
198 }
199 
CreateSupportedOrientationList(napi_env env,napi_value & jsPrinterCap,const PrinterCapability & cap)200 bool PrinterCapabilityHelper::CreateSupportedOrientationList(napi_env env, napi_value& jsPrinterCap,
201     const PrinterCapability& cap)
202 {
203     napi_value jsSupportedOrientationList = nullptr;
204     PRINT_CALL_BASE(env, napi_create_array(env, &jsSupportedOrientationList), false);
205     std::vector<uint32_t> supportedOrientationList;
206     cap.GetSupportedQuality(supportedOrientationList);
207     uint32_t arrLength = static_cast<uint32_t>(supportedOrientationList.size());
208     for (uint32_t index = 0; index < arrLength; index++) {
209         napi_value value = NapiPrintUtils::CreateUint32(env, supportedOrientationList[index]);
210         PRINT_CALL_BASE(env, napi_set_element(env, jsSupportedOrientationList, index, value), false);
211     }
212     PRINT_CALL_BASE(
213         env,
214         napi_set_named_property(env, jsPrinterCap, PARAM_CAPABILITY_SUPPORTED_ORIENTATIONS, jsSupportedOrientationList),
215         false);
216     return true;
217 }
218 
BuildFromJs(napi_env env,napi_value jsValue)219 std::shared_ptr<PrinterCapability> PrinterCapabilityHelper::BuildFromJs(napi_env env, napi_value jsValue)
220 {
221     auto nativeObj = std::make_shared<PrinterCapability>();
222 
223     if (!ValidateProperty(env, jsValue)) {
224         PRINT_HILOGE("Invalid property of printer capability");
225         return nullptr;
226     }
227     if (!BuildSimplePropertyFromJs(env, jsValue, nativeObj)) {
228         PRINT_HILOGE("BuildSimplePropertyFromJs error");
229         return nullptr;
230     }
231     if (!BuildArrayPropertyFromJs(env, jsValue, nativeObj)) {
232         PRINT_HILOGE("BuildArrayPropertyFromJs error");
233         return nullptr;
234     }
235     PRINT_HILOGI("Build Print Capability succeed");
236     return nativeObj;
237 }
238 
BuildSimplePropertyFromJs(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)239 bool PrinterCapabilityHelper::BuildSimplePropertyFromJs(napi_env env, napi_value jsValue,
240     std::shared_ptr<PrinterCapability> nativeObj)
241 {
242     uint32_t colorMode = NapiPrintUtils::GetUint32Property(env, jsValue, PARAM_CAPABILITY_COLORMODE);
243     if (colorMode) {
244         nativeObj->SetColorMode(colorMode);
245     }
246 
247     uint32_t duplexMode = NapiPrintUtils::GetUint32Property(env, jsValue, PARAM_CAPABILITY_DUPLEXMODE);
248     if (duplexMode) {
249         nativeObj->SetDuplexMode(duplexMode);
250     }
251 
252     napi_value jsMargin = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_CAPABILITY_MINMARGIN);
253     if (jsMargin != nullptr) {
254         auto marginPtr = PrintMarginHelper::BuildFromJs(env, jsMargin);
255         if (marginPtr == nullptr) {
256             PRINT_HILOGE("Failed to build printer capability object from js");
257             return false;
258         }
259         nativeObj->SetMinMargin(*marginPtr);
260     }
261 
262     auto jsOption = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_CAPABILITY_OPTION);
263     if (jsOption != nullptr) {
264         nativeObj->SetOption(NapiPrintUtils::GetStringPropertyUtf8(env, jsValue, PARAM_CAPABILITY_OPTION));
265     }
266     return true;
267 }
268 
BuildArrayPropertyFromJs(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)269 bool PrinterCapabilityHelper::BuildArrayPropertyFromJs(napi_env env, napi_value jsValue,
270     std::shared_ptr<PrinterCapability> nativeObj)
271 {
272     if (!buildSupportedPageSizes(env, jsValue, nativeObj) ||
273         !buildSupportedResolutions(env, jsValue, nativeObj) ||
274         !buildSupportedColorModes(env, jsValue, nativeObj) ||
275         !buildSupportedDuplexModes(env, jsValue, nativeObj) ||
276         !buildSupportedQualities(env, jsValue, nativeObj) ||
277         !buildSupportedMediaTypes(env, jsValue, nativeObj) ||
278         !buildSupportedOrientations(env, jsValue, nativeObj)) {
279         return false;
280     }
281     return true;
282 }
283 
buildSupportedPageSizes(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)284 bool PrinterCapabilityHelper::buildSupportedPageSizes(napi_env env, napi_value jsValue,
285                                                       std::shared_ptr<PrinterCapability> nativeObj)
286 {
287     return ProcessJsArrayProperty<PrintPageSize>(env, jsValue, PARAM_CAPABILITY_SUPPORTED_PAGESIZES,
288         [nativeObj](const std::vector<PrintPageSize>& pageSizes) {
289             nativeObj->SetSupportedPageSize(pageSizes);
290         },
291         PrintPageSizeHelper::BuildFromJs);
292 }
293 
buildSupportedResolutions(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)294 bool PrinterCapabilityHelper::buildSupportedResolutions(napi_env env, napi_value jsValue,
295                                                         std::shared_ptr<PrinterCapability> nativeObj)
296 {
297     return ProcessJsArrayProperty<PrintResolution>(env, jsValue, PARAM_CAPABILITY_RESOLUTION,
298         [nativeObj](const std::vector<PrintResolution>& resolutions) {
299             nativeObj->SetResolution(resolutions);
300         },
301         PrintResolutionHelper::BuildFromJs);
302 }
303 
buildSupportedColorModes(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)304 bool PrinterCapabilityHelper::buildSupportedColorModes(napi_env env, napi_value jsValue,
305                                                        std::shared_ptr <PrinterCapability> nativeObj)
306 {
307     return ProcessJsArrayProperty<uint32_t>(env, jsValue, PARAM_CAPABILITY_SUPPORTED_COLORMODES,
308         [nativeObj](const std::vector<uint32_t>& colorModes) { nativeObj->SetSupportedColorMode(colorModes); },
309         [](napi_env env, napi_value jsValue) -> std::shared_ptr<uint32_t> {
310             uint32_t colorMode = NapiPrintUtils::GetUint32FromValue(env, jsValue);
311             return std::make_shared<uint32_t>(colorMode);
312         });
313 }
314 
buildSupportedDuplexModes(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)315 bool PrinterCapabilityHelper::buildSupportedDuplexModes(napi_env env, napi_value jsValue,
316                                                         std::shared_ptr<PrinterCapability> nativeObj)
317 {
318     return ProcessJsArrayProperty<uint32_t>(env, jsValue, PARAM_CAPABILITY_SUPPORTED_DUPLEXMODES,
319         [nativeObj](const std::vector<uint32_t>& duplexModes) {
320             nativeObj->SetSupportedDuplexMode(duplexModes);
321         },
322         [](napi_env env, napi_value jsValue) -> std::shared_ptr<uint32_t> {
323             return std::make_shared<uint32_t>(NapiPrintUtils::GetUint32FromValue(env, jsValue));
324         });
325 }
326 
buildSupportedQualities(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)327 bool PrinterCapabilityHelper::buildSupportedQualities(napi_env env, napi_value jsValue,
328                                                       std::shared_ptr<PrinterCapability> nativeObj)
329 {
330     return ProcessJsArrayProperty<uint32_t>(env, jsValue, PARAM_CAPABILITY_SUPPORTED_QUALITIES,
331         [nativeObj](const std::vector<uint32_t>& qualities) {
332             nativeObj->SetSupportedQuality(qualities);
333         },
334         [](napi_env env, napi_value jsValue) -> std::shared_ptr<uint32_t> {
335             return std::make_shared<uint32_t>(NapiPrintUtils::GetUint32FromValue(env, jsValue));
336         });
337 }
338 
buildSupportedMediaTypes(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)339 bool PrinterCapabilityHelper::buildSupportedMediaTypes(napi_env env, napi_value jsValue,
340                                                        std::shared_ptr<PrinterCapability> nativeObj)
341 {
342     return ProcessJsArrayProperty<std::string>(env, jsValue, PARAM_CAPABILITY_SUPPORTED_MEDIA_TYPES,
343         [nativeObj](const std::vector<std::string>& mediaTypes) {
344             nativeObj->SetSupportedMediaType(mediaTypes);
345         },
346         [](napi_env env, napi_value jsValue) -> std::shared_ptr<std::string> {
347             return std::make_shared<std::string>(NapiPrintUtils::GetStringFromValueUtf8(env, jsValue));
348         });
349 }
350 
buildSupportedOrientations(napi_env env,napi_value jsValue,std::shared_ptr<PrinterCapability> nativeObj)351 bool PrinterCapabilityHelper::buildSupportedOrientations(napi_env env, napi_value jsValue,
352                                                          std::shared_ptr<PrinterCapability> nativeObj)
353 {
354     return ProcessJsArrayProperty<uint32_t>(env, jsValue, PARAM_CAPABILITY_SUPPORTED_ORIENTATIONS,
355         [nativeObj](const std::vector<uint32_t>& orientations) {
356             nativeObj->SetSupportedOrientation(orientations);
357         },
358         [](napi_env env, napi_value jsValue) -> std::shared_ptr<uint32_t> {
359             return std::make_shared<uint32_t>(NapiPrintUtils::GetUint32FromValue(env, jsValue));
360         });
361 }
362 
ValidateProperty(napi_env env,napi_value object)363 bool PrinterCapabilityHelper::ValidateProperty(napi_env env, napi_value object)
364 {
365     std::map<std::string, PrintParamStatus> propertyList = {
366         {PARAM_CAPABILITY_COLORMODE, PRINT_PARAM_OPT},
367         {PARAM_CAPABILITY_DUPLEXMODE, PRINT_PARAM_OPT},
368         {PARAM_CAPABILITY_PAGESIZE, PRINT_PARAM_OPT},
369         {PARAM_CAPABILITY_RESOLUTION, PRINT_PARAM_OPT},
370         {PARAM_CAPABILITY_MINMARGIN, PRINT_PARAM_OPT},
371         {PARAM_CAPABILITY_OPTION, PRINT_PARAM_OPT},
372         {PARAM_CAPABILITY_SUPPORTED_PAGESIZES, PRINT_PARAM_OPT},
373         {PARAM_CAPABILITY_SUPPORTED_COLORMODES, PRINT_PARAM_OPT},
374         {PARAM_CAPABILITY_SUPPORTED_DUPLEXMODES, PRINT_PARAM_OPT},
375         {PARAM_CAPABILITY_SUPPORTED_MEDIA_TYPES, PRINT_PARAM_OPT},
376         {PARAM_CAPABILITY_SUPPORTED_QUALITIES, PRINT_PARAM_OPT},
377         {PARAM_CAPABILITY_SUPPORTED_ORIENTATIONS, PRINT_PARAM_OPT},
378     };
379 
380     auto names = NapiPrintUtils::GetPropertyNames(env, object);
381     return NapiPrintUtils::VerifyProperty(names, propertyList);
382 }
383 } // namespace OHOS::Print
384