1/* 2 * Copyright (c) 2023-2023 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 */ 15import print from '@ohos.print'; 16import { BusinessError } from '@ohos.base'; 17import CheckEmptyUtils from '../utils/CheckEmptyUtils'; 18import { Log } from '../utils/Log'; 19import { PrintUtil } from '../utils/PrintUtil'; 20import { CustomPrintJobState } from '../model/PrintBean'; 21import { StringUtil } from '../utils/StringUtil'; 22 23const TAG: string = 'print_fwk'; 24/** 25 * defines print margin. 26 */ 27export class PrintMargin implements print.PrintMargin { 28 top?: number; 29 bottom?: number; 30 left?: number; 31 right?: number; 32 33 constructor(top: number, bottom: number, left: number, right: number) { 34 this.top = top; 35 this.bottom = bottom; 36 this.left = left; 37 this.right = right; 38 } 39} 40 41/** 42 * defines print range. 43 */ 44export class PrinterRange implements print.PrinterRange { 45 startPage?: number; 46 endPage?: number; 47 pages?: Array<number>; 48 49 constructor(startPage: number, endPage: number, pages: Array<number>) { 50 this.startPage = startPage; 51 this.endPage = endPage; 52 this.pages = pages; 53 } 54} 55 56/** 57 * defines print preview attribute. 58 */ 59export class PreviewAttribute implements print.PreviewAttribute { 60 previewRange: PrinterRange; 61 result?: number; 62 63 constructor(previewRange: PrinterRange, result: number) { 64 this.previewRange = previewRange; 65 this.result = result; 66 } 67} 68 69/** 70 * defines print resolution. 71 */ 72export class PrintResolution implements print.PrintResolution { 73 id: string; 74 horizontalDpi: number; 75 verticalDpi: number; 76} 77 78export class PrintPageSize implements print.PrintPageSize { 79 id: string; 80 name: string; 81 width: number; 82 height: number; 83 84 constructor(id: string, name: string, width: number, height: number) { 85 this.id = id; 86 this.name = name; 87 this.width = width; 88 this.height = height; 89 } 90} 91 92/** 93 * defines print capability. 94 */ 95export class PrinterCapability implements print.PrinterCapability { 96 colorMode: number; 97 duplexMode: number; 98 pageSize: Array<PrintPageSize>; 99 resolution?: Array<PrintResolution>; 100 minMargin?: PrintMargin; 101 options?: string; /* Change Type*/ 102} 103 104/** 105 * defines print info. 106 */ 107export class PrinterInfo implements print.PrinterInfo { 108 printerId: string; 109 printerName: string; 110 printerState: print.PrinterState; 111 printerIcon?: number; 112 description?: string; 113 capability?: PrinterCapability; 114 options?: string; 115 116 constructor(printerId: string, printerName: string, printerState: print.PrinterState, printerIcon?: number, description?: string, 117 capability?: PrinterCapability, options?: string) { 118 this.printerId = printerId; 119 this.printerName = printerName; 120 this.printerState = printerState; 121 if (printerIcon) { 122 this.printerIcon = printerIcon; 123 } 124 if (description) { 125 this.description = description; 126 } 127 if (capability) { 128 this.capability = capability; 129 } 130 if (options) { 131 this.options = options; 132 } 133 } 134 135 toString(): string { 136 return '[PrinterInfo printerId:' + StringUtil.splitMac(this.printerId) + 137 ' ,printerName:' + StringUtil.encodeCommonString(this.printerName) + 138 ' , printerState:' + this.printerState + ']'; 139 } 140} 141 142/** 143 * PrinterInfo.options数据结构 144 */ 145export class PrinterCapsOptions { 146 supportedMediaTypes: number[]; 147 supportedQualities: number[]; 148 make: string; 149 printerUri: string; 150} 151 152/** 153 * defines print job 154 */ 155export class PrintJob implements print.PrintJob { 156 jobFiles: Array<string>; /* Add a Variable */ 157 fdList: Array<number>; 158 jobId: string; 159 printerId: string; 160 jobState: print.PrintJobState; 161 jobSubstate: print.PrintJobSubState; 162 copyNumber: number; 163 pageRange: PrinterRange; 164 isSequential: boolean; 165 pageSize: PrintPageSize; 166 isLandscape: boolean; 167 colorMode: number; 168 duplexMode: number; 169 margin: PrintMargin; 170 preview: PreviewAttribute; 171 options: string; /* Change Type */ 172 173 constructor(jobFiles: Array<string>, fdList: Array<number>, jobId: string, printerId: string, jobState: print.PrintJobState, 174 jobSubstate: print.PrintJobSubState, copyNumber: number, pageRange: PrinterRange, isSequential: boolean, 175 pageSize: PrintPageSize, isLandscape: boolean, colorMode: number, duplexMode: number, margin: PrintMargin, 176 preview: PreviewAttribute, options: string) { 177 this.jobFiles = jobFiles; 178 this.fdList = fdList; 179 this.jobId = jobId; 180 this.printerId = printerId; 181 this.jobState = jobState; 182 this.jobSubstate = jobSubstate; 183 this.copyNumber = copyNumber; 184 this.pageRange = pageRange; 185 this.isSequential = isSequential; 186 this.pageSize = pageSize; 187 this.isLandscape = isLandscape; 188 this.colorMode = colorMode; 189 this.duplexMode = duplexMode; 190 this.margin = margin; 191 this.preview = preview; 192 this.options = options; 193 } 194} 195 196export class PrinterExtensionInfo implements print.PrinterExtensionInfo { 197 extensionId: string; // extension id of printer extension 198 vendorId: string; // vendor id of extension 199 vendorName: string; // vendor name 200 vendorIcon: number; // resource id of vendor 201 version: string; // version of current printer extension 202 constructor(extensionId: string, vendorId: string, vendorName: string, vendorIcon: number, version: string) { 203 this.extensionId = extensionId; 204 this.vendorId = vendorId; 205 this.vendorName = vendorName; 206 this.vendorIcon = vendorIcon; 207 this.version = version; 208 } 209} 210 211/** 212 * PrintJob.options数据结构 213 */ 214export class PrintJobOptions { 215 jobName: string; 216 jobNum: number; 217 jobDescription: string; 218 mediaType: string; 219 documentCategory: number; 220 printQuality: string; 221 printerName: string; 222 printerUri: string; 223 documentFormat: string; 224 files: string[]; 225} 226export function startPrintJob(printJobInfo: PrintJob): Promise<boolean> { 227 Log.info(TAG, 'startPrintJob enter.'); 228 return new Promise((resolve) => { 229 if (CheckEmptyUtils.isEmpty(printJobInfo)) { 230 Log.info(TAG, 'startPrintJob, printJobInfo invalid.'); 231 return resolve(false); 232 } 233 let printJob: print.PrintJob = convertToFwkPrintJob(printJobInfo); 234 Log.info(TAG, 'startPrintJob, jobId =' + JSON.stringify(printJobInfo.jobId)); 235 print.startPrintJob(printJob).then(() => { 236 Log.info(TAG, 'start print success.'); 237 resolve(true); 238 }).catch((err: BusinessError) => { 239 Log.error(TAG, 'failed to start Print because ' + JSON.stringify(err)); 240 return resolve(false); 241 }); 242 }); 243} 244 245export function queryAllPrintJobs(printerId?: string): Promise<Array<PrintJob>> { 246 return new Promise((resolve, reject) => { 247 print.queryPrintJobList().then((data: Array<print.PrintJob>) => { 248 Log.info(TAG, `queryAllPrintJobs data.length:${data.length}`); 249 let retPrintJobs: Array<PrintJob> = []; 250 for (let printJob of data) { 251 Log.debug(TAG, `queryAllPrintJobs printJob:${JSON.stringify(printJob)}`); 252 let printJobInfo = convertToSpoolerPrintJob(printJob); 253 if (CheckEmptyUtils.isEmpty(printJobInfo)) { 254 Log.warn(TAG, 'queryAllPrintJobs invalid job.'); 255 continue; 256 } 257 if (CheckEmptyUtils.checkStrIsEmpty(printerId) || printJobInfo.printerId === printerId) { 258 retPrintJobs.push(printJobInfo); 259 } 260 } 261 Log.info(TAG, `queryAllPrintJobs retPrintJobs.length: ${retPrintJobs.length}`); 262 resolve(retPrintJobs); 263 }).catch((err: BusinessError) => { 264 Log.error(TAG, `failed to queryAllPrintJobs Cause: ${JSON.stringify(err)}`); 265 return reject(err); 266 }); 267 }); 268} 269 270export function cancelPrintJob(jobId: string): void { 271 Log.info(TAG, 'cancelPrintJob enter.'); 272 if (CheckEmptyUtils.checkStrIsEmpty(jobId)) { 273 Log.info(TAG, 'cancelPrintJob, jobId is empty.'); 274 return; 275 } 276 Log.info(TAG, 'cancelPrintJob jobId=' + jobId); 277 print.cancelPrintJob(jobId).then((data) => { 278 Log.info(TAG, 'cancel print success data: ' + JSON.stringify(data)); 279 }).catch((error: BusinessError) => { 280 Log.error(TAG, 'cancel print failed, because: ' + JSON.stringify(error)); 281 }); 282 Log.info(TAG, 'cancelPrintJob end.'); 283} 284 285export function isValidPrintJob(job: print.PrintJob): boolean { 286 if (CheckEmptyUtils.isEmpty(job)) { 287 Log.info(TAG, 'isValidPrintJob job is empty.'); 288 return false; 289 } 290 if (CheckEmptyUtils.checkStrIsEmpty(job.printerId) || CheckEmptyUtils.checkStrIsEmpty(job.jobId) || 291 !(PrintUtil.isValueInEnum(job.jobState, print.PrintJobState) || PrintUtil.isValueInEnum(job.jobState, CustomPrintJobState)) || 292 !PrintUtil.isValueInEnum(job.jobSubstate, print.PrintJobSubState)) { 293 return false; 294 } 295 return true; 296} 297 298export function convertToSpoolerPrintJob(job: print.PrintJob): PrintJob { 299 if (!isValidPrintJob(job)) { 300 return null; 301 } 302 return new PrintJob([], job.fdList, job.jobId, job.printerId, job.jobState as print.PrintJobState, job.jobSubstate, 303 job.copyNumber, job.pageRange, job.isSequential, job.pageSize, job.isLandscape, job.colorMode, 304 job.duplexMode, job.margin, job.preview, job.options as string); 305} 306 307export function convertToFwkPrintJob(printJobInfo: PrintJob): print.PrintJob { 308 let pageRangeInfo: PrinterRange; 309 if (printJobInfo.pageRange.pages.length === 0) { 310 pageRangeInfo = { startPage: printJobInfo.pageRange.startPage, endPage: printJobInfo.pageRange.endPage }; 311 } else { 312 pageRangeInfo = { pages: printJobInfo.pageRange.pages }; 313 } 314 // remove: preview, jobFiles 315 let printJob: print.PrintJob = { 316 fdList: printJobInfo.fdList, 317 jobId: printJobInfo.jobId, 318 printerId: printJobInfo.printerId, 319 jobState: printJobInfo.jobState, 320 jobSubstate: printJobInfo.jobSubstate, 321 copyNumber: printJobInfo.copyNumber, 322 pageRange: pageRangeInfo, 323 isSequential: printJobInfo.isSequential, 324 pageSize: printJobInfo.pageSize, 325 isLandscape: printJobInfo.isLandscape, 326 colorMode: printJobInfo.colorMode, 327 duplexMode: printJobInfo.duplexMode, 328 margin: printJobInfo.margin, 329 options: printJobInfo.options 330 }; 331 return printJob; 332} 333 334export function convertToPrinterInfo(info: print.PrinterInfo): PrinterInfo { 335 if (CheckEmptyUtils.isEmpty(info)) { 336 return null; 337 } 338 let printerInfo: PrinterInfo = new PrinterInfo(info.printerId, info.printerName, info.printerState, info.printerIcon, info.description, 339 info.capability as PrinterCapability, info.options as string); 340 return printerInfo; 341} 342