import 'reflect-metadata'; import { CanvasUtilitiesService, } from './canvas-utilities.service'; import { testBorder } from '../../../test-utils/border-test-helpers.spec'; import { BorderUnit, CM_PER_INCH, CoordsInterface, DimensionsInterface, MaskImageMapInterface, PIGPrintGuideAreaInterface, } from './../../../models/index'; const initCanvasUtilitiesService = () => { return new CanvasUtilitiesService(); }; describe('getScaledEnclosingQuad', () => { const getDefaultScaledEnclosingQuadValues = () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); const containerDimensions = { height: 5, width: 5, } as DimensionsInterface; const maskImageMap = { imageEditorImage: { borderWidth: 0, borderUnit: BorderUnit.None, }, mask: { enclosing_quadrilateral: { size: { width: 10, height: 10, }, }, bleed_area: { heightAdjustedForNegativeBleed: 10, widthAdjustedForNegativeBleed: 10, points: [[{ x: 0, y: 0, }, { x: 10, y: 0, }, { x: 10, y: 10, }, { x: 0, y: 10, }]], }, }, } as MaskImageMapInterface; const maskImageDimensions = { height: 10, width: 5, } as DimensionsInterface; return { canvasGuideAreaComponent, containerDimensions, maskImageMap, maskImageDimensions, assetSize: {} as DimensionsInterface, dpi: 300, }; }; test('Scales correctly if the bleed area is larger than the mask dimensions and it is scaled more by width', () => { const { canvasGuideAreaComponent, containerDimensions, maskImageMap, maskImageDimensions, assetSize, dpi, } = getDefaultScaledEnclosingQuadValues(); const result = canvasGuideAreaComponent.getScaledEnclosingQuad( containerDimensions, maskImageDimensions, maskImageMap, assetSize, dpi, ); expect(result).toEqual({ bottomLeft: {x: 0, y: 5}, bottomRight: {x: 5, y: 5}, size: { height: 5, width: 5, }, topLeft: {x: 0, y: 0}, topRight: {x: 5, y: 0}, borderInPx: 0, }); }); test('Scales correctly if the bleed area is larger than the mask dimensions and it is scaled more by height', () => { const { canvasGuideAreaComponent, containerDimensions, maskImageMap, assetSize, dpi, } = getDefaultScaledEnclosingQuadValues(); const result = canvasGuideAreaComponent.getScaledEnclosingQuad( containerDimensions, { height: 5, width: 10, }, maskImageMap, assetSize, dpi, ); expect(result).toEqual({ bottomLeft: {x: 0, y: 5}, bottomRight: {x: 5, y: 5}, size: { height: 5, width: 5, }, topLeft: {x: 0, y: 0}, topRight: {x: 5, y: 0}, borderInPx: 0, }); }); test('Scales correctly if the bleed area is smaller than the mask dimensions and it is scaled more by width', () => { const { canvasGuideAreaComponent, maskImageMap, assetSize, dpi, } = getDefaultScaledEnclosingQuadValues(); const result = canvasGuideAreaComponent.getScaledEnclosingQuad( { height: 10, width: 5, }, { height: 20, width: 20, }, maskImageMap, assetSize, dpi, ); expect(result).toEqual({ bottomLeft: {x: 0, y: 5}, bottomRight: {x: 2.5, y: 5}, size: { height: 2.5, width: 2.5, }, topLeft: {x: 0, y: 2.5}, topRight: {x: 2.5, y: 2.5}, borderInPx: 0, }); }); test('Scales correctly if the bleed area is smaller than the mask dimensions and it is scaled more by height', () => { const { canvasGuideAreaComponent, maskImageMap, assetSize, dpi, } = getDefaultScaledEnclosingQuadValues(); const result = canvasGuideAreaComponent.getScaledEnclosingQuad( { height: 5, width: 10, }, { height: 20, width: 20, }, maskImageMap, assetSize, dpi, ); expect(result).toEqual({ bottomLeft: {x: 2.5, y: 2.5}, bottomRight: {x: 5, y: 2.5}, size: { height: 2.5, width: 2.5, }, topLeft: {x: 2.5, y: 0}, topRight: {x: 5, y: 0}, borderInPx: 0, }); }); test('Translates the items by maxX and by maxY if maxX is larger than the max width', () => { const { canvasGuideAreaComponent, maskImageMap, assetSize, dpi, } = getDefaultScaledEnclosingQuadValues(); const result = canvasGuideAreaComponent.getScaledEnclosingQuad( { height: 5, width: 10, }, { height: 20, width: 5, }, maskImageMap, assetSize, dpi, ); expect(result).toEqual({ bottomLeft: {x: 2.5, y: 5}, bottomRight: {x: 7.5, y: 5}, size: { height: 5, width: 5, }, topLeft: {x: 2.5, y: 0}, topRight: {x: 7.5, y: 0}, borderInPx: 0, }); }); test('Translates the items by maxY and maxX if maxY is larger than the max height', () => { const { canvasGuideAreaComponent, maskImageMap, assetSize, dpi, } = getDefaultScaledEnclosingQuadValues(); const result = canvasGuideAreaComponent.getScaledEnclosingQuad( { height: 5, width: 10, }, { height: 5, width: 20, }, maskImageMap, assetSize, dpi, ); expect(result).toEqual({ bottomLeft: {x: 2.5, y: 5}, bottomRight: {x: 7.5, y: 5}, size: { height: 5, width: 5, }, topLeft: {x: 2.5, y: 0}, topRight: {x: 7.5, y: 0}, borderInPx: 0, }); }); test(`If the bleed area width and height is smaller than the maskImageDimensions width and height adjust the quad to center by the maskImageDimensions`, () => { const { canvasGuideAreaComponent, maskImageMap, dpi, assetSize } = getDefaultScaledEnclosingQuadValues(); maskImageMap.mask = { ...maskImageMap.mask, bleed_area: { ...maskImageMap.mask.bleed_area, points: [ [{ x: 15, y: 15, }, { x: 20, y: 15, }, { x: 20, y: 20, }, { x: 15, y: 20, }], ], }, }; const result = canvasGuideAreaComponent.getScaledEnclosingQuad( { height: 10, width: 10, }, { height: 10, width: 10, }, maskImageMap, assetSize, dpi, ); expect(result).toEqual({ bottomLeft: {x: 15, y: 20}, bottomRight: {x: 20, y: 20}, size: { height: 5, width: 5, }, topLeft: {x: 15, y: 15}, topRight: {x: 20, y: 15}, borderInPx: 0, }); }); test(`given a 1 inch border, a mask 3 times smaller than the asset, and a scale 1, when calculating a border width in px for a product with 300 dpi, then the result should be 100px`, () => { testBorder() .width(1) .unit(BorderUnit.Inch) .assetSize({ width: 2400, height: 1800 }) .maskSize({ width: 800, height: 600 }) .dpi(300) .containerToMaskScale(1) .expectBorderInPxToBe(100); }); test(`given a 2.54 cm border (1 inch), a mask 3 times smaller than the asset, and a scale 1, when calculating a border width in px for a product with 300 dpi, then the result should be 100px`, () => { testBorder() .width(CM_PER_INCH) .unit(BorderUnit.Cm) .assetSize({ width: 2400 , height: 1800 }) .maskSize({ width: 800, height: 600 }) .dpi(300) .containerToMaskScale(1) .expectBorderInPxToBe(100); }); test(`given a 0.8 inch border, a mask 2 times smaller than the asset, and a scale 1, when calculating a border width in px for a product with 150 dpi, then the result should be 60px`, () => { testBorder() .width(0.8) .unit(BorderUnit.Inch) .assetSize({ width: 2400, height: 3000 }) .maskSize({ width: 1200, height: 1500 }) .dpi(150) .containerToMaskScale(1) .expectBorderInPxToBe(60); }); test(`given a 1 inch border, a mask 3 times smaller than the asset, and a scale 0.25, when calculating a border width in px for a product with 300 dpi, then the result should be 25px`, () => { testBorder() .width(1) .unit(BorderUnit.Inch) .assetSize({ width: 1800, height: 2400 }) .maskSize({ width: 600, height: 800 }) .dpi(300) .containerToMaskScale(0.25) .expectBorderInPxToBe(25); }); test(`given a 3 inch border, a mask with the same size as the asset, and a scale 1, when calculating a border width in px for a 6x8in product with 300 dpi (1800x2400px), then the result should equal a half of the product's width`, () => { testBorder() .width(3) .unit(BorderUnit.Inch) .assetSize({ width: 1800, height: 2400 }) .maskSize({ width: 1800, height: 2400 }) .dpi(300) .containerToMaskScale(1) .expectBorderInPxToBe(900); }); }); describe('getImageQuadCoords', () => { const initGetImageQuadCoordsData = ({ userImageDimensions = { height: 200, width: 400, }, }: { userImageDimensions?: DimensionsInterface, } = {}) => { const canvasUtilitiesService = initCanvasUtilitiesService(); const containerDimension = { height: 100, width: 100, } as DimensionsInterface; const imageScale = 2; const maskImageMap = { imageEditorImage: { scale: imageScale, tx: 10, ty: 50, } as unknown, } as MaskImageMapInterface; const maskImageDimensions = {} as DimensionsInterface; const userImageTranslations = { x: 10, y: 50, } as CoordsInterface; const assetDimensions = { height: 1000, width: 1000, }; canvasUtilitiesService.getScaledEnclosingQuad = jest.fn() .mockReturnValue({ size: { height: 50, width: 50, }, topLeft: { x: 10, y: 10}, borderInPx: 0, }); return { assetDimensions, canvasUtilitiesService, containerDimension, imageScale, maskImageMap, maskImageDimensions, userImageDimensions, userImageTranslations, dpi: 300, }; }; const initAndRunGetImageQuadCoords = (options: { userImageDimensions?: DimensionsInterface, } = {}) => { const data = initGetImageQuadCoordsData(options); const result = data.canvasUtilitiesService.getImageQuadCoords( data.containerDimension, data.maskImageDimensions, data.userImageDimensions, data.assetDimensions, data.maskImageMap, data.dpi, ); return { ...data, result, }; }; test('Gets the scaled quad of the mask', () => { const { containerDimension, canvasUtilitiesService, maskImageDimensions, maskImageMap, assetDimensions, dpi, } = initAndRunGetImageQuadCoords(); expect(canvasUtilitiesService.getScaledEnclosingQuad) .toHaveBeenCalledWith( containerDimension, maskImageDimensions, maskImageMap, assetDimensions, dpi, ); }); test('Returns the expected result', () => { const { result, } = initAndRunGetImageQuadCoords(); expect(result).toEqual([{ x: -64.5, y: -12.5, }, { x: 135.5, y: -12.5, }, { x: 135.5, y: 87.5, }, { x: -64.5, y: 87.5, }]); }); test('Returns the correct value if the image has a larger width to height ratio than the container', () => { const { result, } = initAndRunGetImageQuadCoords({ userImageDimensions: { height: 400, width: 200, }, }); expect(result).toEqual([{ x: -14.5, y: -62.5, }, { x: 85.5, y: -62.5, }, { x: 85.5, y: 137.5, }, { x: -14.5, y: 137.5, }]); }); }); describe('toCanvasCoordinateSystem', () => { test('Calls getScaledEnclosingQuad with the correct values', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); canvasGuideAreaComponent.getScaledEnclosingQuad = jest.fn().mockReturnValue({ borderInPx: 0, size: { height: 10, width: 10 }}); const containerDimensions = {} as DimensionsInterface; const mask = {} as MaskImageMapInterface; const maskImageDimensions = {} as DimensionsInterface; const dpi = 300; canvasGuideAreaComponent.toCanvasCoordinateSystem( containerDimensions, 5, mask, maskImageDimensions, {} as DimensionsInterface, dpi, ); expect(canvasGuideAreaComponent.getScaledEnclosingQuad) .toHaveBeenCalledWith( containerDimensions, mask, maskImageDimensions, {}, dpi, ); }); test('Returns the correctly scaled version if the asset has been scaled more in the x direction', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); canvasGuideAreaComponent.getScaledEnclosingQuad = jest.fn().mockReturnValue({ borderInPx: 0, size: { height: 50, width: 200 }}); const result = canvasGuideAreaComponent.toCanvasCoordinateSystem( {} as DimensionsInterface, 5, {} as MaskImageMapInterface, {} as DimensionsInterface, { height: 10, width: 10, } as DimensionsInterface, 300, ); expect(result).toBe(100); }); test('Returns the correctly scaled version if the asset has been scaled more in the y direction', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); canvasGuideAreaComponent.getScaledEnclosingQuad = jest.fn().mockReturnValue({ borderInPx: 0, size: { height: 200, width: 50 }}); const result = canvasGuideAreaComponent.toCanvasCoordinateSystem( {} as DimensionsInterface, 5, {} as MaskImageMapInterface, {} as DimensionsInterface, { height: 10, width: 10, } as DimensionsInterface, 300, ); expect(result).toBe(100); }); }); describe('toPrintImageCoordinateSystem', () => { test('Calls getScaledEnclosingQuad with the correct values', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); canvasGuideAreaComponent.getScaledEnclosingQuad = jest.fn().mockReturnValue({ borderInPx: 0, size: { height: 10, width: 10 }}); const containerDimensions = {} as DimensionsInterface; const mask = {} as MaskImageMapInterface; const maskImageDimensions = {} as DimensionsInterface; const dpi = 300; canvasGuideAreaComponent.toPrintImageCoordinateSystem( containerDimensions, 5, mask, maskImageDimensions, {} as DimensionsInterface, dpi, ); expect(canvasGuideAreaComponent.getScaledEnclosingQuad) .toHaveBeenCalledWith( containerDimensions, mask, maskImageDimensions, {}, dpi, ); }); test('Returns the correctly scaled version if the asset has been scaled more in the x direction', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); canvasGuideAreaComponent.getScaledEnclosingQuad = jest.fn().mockReturnValue({ borderInPx: 0, size: { height: 10, width: 10 }}); const result = canvasGuideAreaComponent.toPrintImageCoordinateSystem( {} as DimensionsInterface, 5, {} as MaskImageMapInterface, {} as DimensionsInterface, { height: 50, width: 200, } as DimensionsInterface, 300, ); expect(result).toBe(25); }); test('Returns the correctly scaled version if the asset has been scaled more in the y direction', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); canvasGuideAreaComponent.getScaledEnclosingQuad = jest.fn().mockReturnValue({ borderInPx: 0, size: { height: 10, width: 10 }}); const result = canvasGuideAreaComponent.toPrintImageCoordinateSystem( {} as DimensionsInterface, 5, {} as MaskImageMapInterface, {} as DimensionsInterface, { height: 200, width: 50, } as DimensionsInterface, 300, ); expect(result).toBe(25); }); }); describe('getAdjustedGuideAreaPoints', () => { test('Converts the printable area points into the expected points', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); const printGuideArea = { points: [[{ x: 1, y: 2, }, { x: 15, y: 15, }]], } as PIGPrintGuideAreaInterface; const results = canvasGuideAreaComponent.getAdjustedGuideAreaPoints( printGuideArea, 15, 20, 30, 30, ); expect(results).toEqual([[{ x: 0.5, y: 3.5, }, { x: 7.5, y: 10, }]]); }); }); describe('getImageWithUrl', () => { test('Returns the image where the src matches the url', () => { const canvasGuideAreaComponent = initCanvasUtilitiesService(); const images = [{ src: 'abc', }, { src: 'efg', }, { src: 'xyz', }] as HTMLImageElement[]; const result = canvasGuideAreaComponent.getImageWithUrl( images, 'efg', ); expect(result).toBe(images[1]); }); });