From 6027210676b77ad812677d9b477747e1fb4d3861 Mon Sep 17 00:00:00 2001 From: Dmitry Kuzin Date: Wed, 18 Oct 2023 19:55:04 +0400 Subject: [PATCH] Work for #283: do not throw exception if image could not be loaded. Use getCorrectedImageSize from survey helper in file --- src/doc_controller.ts | 2 +- src/flat_layout/flat_file.ts | 37 ++++++------------- src/helper_survey.ts | 12 +++---- src/pdf_render/pdf_brick.ts | 2 +- tests/flat_file.test.ts | 69 +++++++++++++++++++++--------------- 5 files changed, 60 insertions(+), 62 deletions(-) diff --git a/src/doc_controller.ts b/src/doc_controller.ts index 64ff91c..9dec331 100644 --- a/src/doc_controller.ts +++ b/src/doc_controller.ts @@ -211,7 +211,7 @@ export interface IDocOptions { isRTL?: boolean; /** * Specifies whether to include only selected choices when PDF Generator renders a [Multi-Select Dropdown (Tag Box)](https://surveyjs.io/form-library/examples/how-to-create-multiselect-tag-box/) question. - * + * * Default value: `false` (include all choices) */ tagboxSelectedChoicesOnly?: boolean; diff --git a/src/flat_layout/flat_file.ts b/src/flat_layout/flat_file.ts index caac556..d87513f 100644 --- a/src/flat_layout/flat_file.ts +++ b/src/flat_layout/flat_file.ts @@ -19,21 +19,14 @@ export class FlatFile extends FlatQuestion { this.question = question; } private async generateFlatItem(point: IPoint, item: { - name: string, type: string, content: string, + name: string, type: string, content: string, imageSize?: ISize, }): Promise { const compositeFlat: CompositeBrick = new CompositeBrick(await SurveyHelper.createLinkFlat( point, this.question, this.controller, item.name === undefined ? 'image' : item.name, item.content)); if (SurveyHelper.canPreviewImage(this.question, item, item.content)) { - const imageSize: ISize = await SurveyHelper.getImageSize(item.content); - if (this.question.imageWidth) { - imageSize.width = SurveyHelper.parseWidth(this.question.imageWidth, SurveyHelper.getPageAvailableWidth(this.controller)); - } - if (this.question.imageHeight) { - imageSize.height = SurveyHelper.parseWidth(this.question.imageHeight, Number.MAX_VALUE); - } const imagePoint: IPoint = SurveyHelper.createPoint(compositeFlat); imagePoint.yTop += this.controller.unitHeight * FlatFile.IMAGE_GAP_SCALE; - compositeFlat.addBrick(await SurveyHelper.createImageFlat(imagePoint, this.question, this.controller, item.content, imageSize.width, imageSize.height, FlatFile.DEFAULT_IMAGE_FIT)); + compositeFlat.addBrick(await SurveyHelper.createImageFlat(imagePoint, this.question, this.controller, item.content, item.imageSize.width, item.imageSize.height, FlatFile.DEFAULT_IMAGE_FIT)); } return compositeFlat; } @@ -46,20 +39,8 @@ export class FlatFile extends FlatQuestion { } } - private async getImagePreviewContentWidth(item: { name: string, type: string, content: string }, availableWidth: number) { - let contentWidth = (await SurveyHelper.getImageSize(item.content)).width; - if(!!contentWidth) { - contentWidth = SurveyHelper.parseWidth(contentWidth + 'pt', availableWidth); - } - if (!!this.question.imageWidth) { - contentWidth = SurveyHelper.parseWidth(this.question.imageWidth, availableWidth); - } else if(this.controller.applyImageFit) { - contentWidth = availableWidth; - } - if(contentWidth === undefined) { - contentWidth = 0; - } - return Math.max(contentWidth, FlatFile.TEXT_MIN_SCALE * this.controller.unitWidth); + private async getImagePreviewContentWidth(item: { name: string, type: string, content: string, imageSize?: ISize }) { + return Math.max(item.imageSize.width, FlatFile.TEXT_MIN_SCALE * this.controller.unitWidth); } public async generateFlatsContent(point: IPoint): Promise { if (this.question.previewValue.length === 0) { @@ -72,11 +53,15 @@ export class FlatFile extends FlatQuestion { const fullAvailableWidth = this.controller.paperWidth - this.controller.margins.right - currPoint.xLeft; for (let i: number = 0; i < this.question.previewValue.length; i++) { - const item: { name: string, type: string, content: string } = this.question.previewValue[i]; + let item: { name: string, type: string, content: string, imageSize?: ISize } = { ...this.question.previewValue[i] }; + const canPreviewImage = SurveyHelper.canPreviewImage(this.question, item, item.content); + if (canPreviewImage) { + item.imageSize = await SurveyHelper.getCorrectedImageSize(this.controller, { imageWidth: this.question.imageWidth, imageHeight: this.question.imageHeight, imageLink: this.question.previewValue[i].content }); + } const availableWidth: number = this.controller.paperWidth - this.controller.margins.right - currPoint.xLeft; - if (SurveyHelper.canPreviewImage(this.question, item, item.content)) { - const compositeWidth = await this.getImagePreviewContentWidth(item, fullAvailableWidth); + if (canPreviewImage) { + const compositeWidth = await this.getImagePreviewContentWidth(item); if (availableWidth < compositeWidth) { currPoint.xLeft = point.xLeft; currPoint.yTop = yBot; diff --git a/src/helper_survey.ts b/src/helper_survey.ts index 6d05ba2..8303c02 100644 --- a/src/helper_survey.ts +++ b/src/helper_survey.ts @@ -739,18 +739,18 @@ export class SurveyHelper { if(!SurveyHelper.isSizeEmpty(imageWidth)) { if(imageSize && imageSize.width) { heightPt = imageSize.height * widthPt / imageSize.width; - } else { - heightPt = 0; } } - if(!SurveyHelper.isHeightEmpty(imageHeight)) { + else if(!SurveyHelper.isHeightEmpty(imageHeight)) { if(imageSize && imageSize.height) { widthPt = imageSize.width * heightPt / imageSize.height; - } else { - widthPt = 0; } } + else if(imageSize && imageSize.height && imageSize.width) { + heightPt = SurveyHelper.parseWidth(imageSize.height.toString(), SurveyHelper.getPageAvailableWidth(controller), 1, 'px'); + widthPt = SurveyHelper.parseWidth(imageSize.width.toString(), SurveyHelper.getPageAvailableWidth(controller), 1, 'px'); + } } - return { width: widthPt, height: heightPt }; + return { width: widthPt || 0, height: heightPt || 0 }; } } \ No newline at end of file diff --git a/src/pdf_render/pdf_brick.ts b/src/pdf_render/pdf_brick.ts index a17df6f..fea0a6f 100644 --- a/src/pdf_render/pdf_brick.ts +++ b/src/pdf_render/pdf_brick.ts @@ -66,7 +66,7 @@ export class PdfBrick implements IPdfBrick { public fontSize: number; /** * The color of text within the brick. - * + * * Default value: `"#404040"` */ public textColor: string = SurveyHelper.TEXT_COLOR; diff --git a/tests/flat_file.test.ts b/tests/flat_file.test.ts index 990f071..95e88ee 100644 --- a/tests/flat_file.test.ts +++ b/tests/flat_file.test.ts @@ -160,9 +160,9 @@ test('Check one image 16x16px file', async () => { controller.margins.left += controller.unitWidth; const assumeFile: IRect = { xLeft: controller.leftTopPoint.xLeft, - xRight: controller.leftTopPoint.xLeft + imageSize.width, + xRight: controller.leftTopPoint.xLeft + SurveyHelper.pxToPt(imageSize.width), yTop: controller.leftTopPoint.yTop, - yBot: controller.leftTopPoint.yTop + imageSize.height + + yBot: controller.leftTopPoint.yTop + SurveyHelper.pxToPt(imageSize.height) + controller.unitHeight * (1.0 + FlatFile.IMAGE_GAP_SCALE) }; TestHelper.equalRect(expect, flats[0][0], assumeFile); @@ -201,7 +201,7 @@ test('Check one image 16x16px file shorter than text', async () => { xLeft: controller.leftTopPoint.xLeft, xRight: controller.leftTopPoint.xLeft + controller.measureText(json.elements[0].defaultValue[0].name).width, yTop: controller.leftTopPoint.yTop, - yBot: controller.leftTopPoint.yTop + imageSize.height + + yBot: controller.leftTopPoint.yTop + SurveyHelper.pxToPt(imageSize.height) + controller.unitHeight * (1.0 + FlatFile.IMAGE_GAP_SCALE) }; TestHelper.equalRect(expect, flats[0][0], assumeFile); @@ -266,7 +266,7 @@ test('Check one image 16x16px file server-side', async () => { { name: 'cat.png', type: 'image/png', - content: TestHelper.BASE64_IMAGE_16PX + content: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAA3NCSVQICAjb4U/gAAAAt1BMVEVHcExTXGROYmJIT1ZPXmVJV11ES1JYZ24+SE5JU1s+R0xVYmtYZW1ETlRRXWVUYWpKV1xZZ25YZW5YanNrfIdTYWlaZ29nd4JUYmhIU1lHUVtRXWQ+SlA6QkouNzpFT1ZCS1JSXWVxhI98kp53iZZSXmVcaXE5QkdCTFNndn9WY2tZZm5canJfbXVbZ29hcHlXZGxtfYVNWmFRXWVCTFNKVl04QEdoeINnZGxrc3uAk6Fzb3dxg43scHiMAAAAKnRSTlMALwQXZU4MImyJQbCrPOPZRdOHx4X4t2fR0SfsoHhYseyioqbHwOy+59gMe1UiAAAAuElEQVQYlU2P5xKCQAyEI1gABVSKUu3tOgL2938u74Ybx/2xk3yT2SQAPw2Yb8KfRp6VzAxVDDVwYej1ZbHbG9tQTy030sJP+1po4MfSZs+qsrp+KubSg8e7Wq8mk/E44LinwqJr22IskCA4UgBiUqueUUqJ2gLzO0MCC8Ypx1MFXEIEqhFGjB/0zTXNbPvcXOkx7YjFbYDydsq7DIAeKyS9mSYadGBR51A0JVwy/dcyScFxwLAdgC+IFhIbrHyDqAAAAABJRU5ErkJggg==' } ] } @@ -281,7 +281,6 @@ test('Check one image 16x16px file server-side', async () => { const imageBrick: IPdfBrick = (flats[0][0]).bricks[0].bricks[1]; expect(imageBrick instanceof ImageBrick).toBeTruthy(); - expect(imageBrick.isPageBreak).toBeTruthy(); controller.margins.left += controller.unitWidth; const assumeFile: IRect = { @@ -352,36 +351,50 @@ test('Test file question getImagePreviewContentWidth ', async () => { const controller: DocController = new DocController(TestHelper.defaultOptions); const flatFile = new FlatFile(survey, question, controller); - let width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file' }, 200); + let width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file', imageSize: { width: 150, height: 50 } }); expect(width).toBe(FlatFile.TEXT_MIN_SCALE * controller.unitWidth); - controller['_applyImageFit'] = true; - width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file' }, 200); - expect(width).toBe(200); - - question.imageWidth = '250px'; - width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file' }, 300); - expect(width).toBe(SurveyHelper.parseWidth(question.imageWidth, 300)); + width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file', imageSize: { width: 300, height: 50 } }); + expect(width).toBe(300); +}); - SurveyHelper.inBrowser = true; - const oldImageSize = SurveyHelper.getImageSize; - SurveyHelper.getImageSize = async (url: string) => { - return { width: 200, height: 0 }; +test('Test file question doesnt throw exception if could not load image preview', async () => { + SurveyHelper.getImageSize = async (url: string) => { return null as any; }; + const json: any = { + elements: [ + { + type: 'file', + name: 'faqueoneimgwithsz', + titleLocation: 'hidden', + allowImagesPreview: true, + defaultValue: [ + { + name: 'cat.png', + type: 'image/png', + content: 'some url' + } + ], + } + ] }; - question.imageWidth = undefined; - controller['_applyImageFit'] = false; - width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file' }, 300); - expect(width).toBe(200); + const survey: SurveyPDF = new SurveyPDF(json, TestHelper.defaultOptions); + const controller: DocController = new DocController(TestHelper.defaultOptions); + const flats: IPdfBrick[][] = await FlatSurvey.generateFlats(survey, controller); + expect(flats.length).toBe(1); + expect(flats[0].length).toBe(1); - controller['_applyImageFit'] = true; - width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file' }, 200); - expect(width).toBe(200); + const imageBrick: IPdfBrick = (flats[0][0]).bricks[0].bricks[1]; + expect(imageBrick instanceof ImageBrick).toBeTruthy(); - question.imageWidth = '250px'; - width = await flatFile['getImagePreviewContentWidth']({ content: '', type: 'image', name: 'file' }, 300); - expect(width).toBe(SurveyHelper.parseWidth(question.imageWidth, 300)); + controller.margins.left += controller.unitWidth; - SurveyHelper.getImageSize = oldImageSize; + const assumeFile: IRect = { + xLeft: controller.leftTopPoint.xLeft, + xRight: controller.leftTopPoint.xLeft + controller.measureText(json.elements[0].defaultValue[0].name).width, + yTop: controller.leftTopPoint.yTop, + yBot: controller.leftTopPoint.yTop + controller.unitHeight * (1.0 + FlatFile.IMAGE_GAP_SCALE) + }; + TestHelper.equalRect(expect, flats[0][0], assumeFile); }); test('Test file question getImagePreviewContentWidth always return correct image width', async () => {