{"version":3,"file":"offscreenRenderer-C-bgFCIB.js","sources":["../../../app/javascript/utils/photobookDefaultText.js","../../../app/javascript/utils/blobber.js","../../../app/javascript/utils/findBestTemplate.js","../../../app/javascript/utils/offscreenRenderer.js"],"sourcesContent":["const defaultCaption = \"Add photo caption here\\nor delete if you prefer\";\nconst defaultTextPageText =\n  \"ADD TITLE HERE\\nWrite a few words, a fun subtitle\\nor quote of your choice\";\n\nexport { defaultCaption, defaultTextPageText };\n","export default class Blobber {\n  static base64ToBlob(base64) {\n    const [typePart, base64Data] = base64.split(\",\");\n    const byteCharacters = atob(base64Data); // Decodes Base64 string into a string of bytes\n    const byteNumbers = new Array(byteCharacters.length);\n\n    for (let i = 0; i < byteCharacters.length; i += 1) {\n      byteNumbers[i] = byteCharacters.charCodeAt(i);\n    }\n\n    const byteArray = new Uint8Array(byteNumbers);\n    const type = typePart.split(\":\")[1].split(\";\")[0];\n    const blob = new Blob([byteArray], { type });\n\n    return URL.createObjectURL(blob);\n  }\n\n  static async blobUrlToBase64(url) {\n    const data = await fetch(url);\n    const blob = await data.blob();\n\n    return new Promise(resolve => {\n      const reader = new FileReader();\n      reader.onloadend = () => {\n        resolve(reader.result);\n      };\n      reader.readAsDataURL(blob);\n    });\n  }\n}\n","export default function findBestTemplate(\n  image,\n  alternativeSheets,\n  nextImage = undefined,\n  allowMultipleImages = false\n) {\n  // we want to choose a template with a similar aspect ratio to the image\n  // and one which has only one imageframe\n\n  return new Promise(resolve => {\n    if (!image) {\n      resolve(null);\n      return;\n    }\n\n    let bestTemplate = null;\n\n    const loaderImage = new Image();\n    loaderImage.onload = () => {\n      const imageAspectRatio = loaderImage.width / loaderImage.height;\n      if (nextImage && allowMultipleImages) {\n        const nextLoaderImage = new Image();\n        nextLoaderImage.onload = () => {\n          const nextImageAspectRatio =\n            nextLoaderImage.width / nextLoaderImage.height;\n\n          let smallestDifference = Infinity;\n\n          if (Math.abs(nextImageAspectRatio - imageAspectRatio) < 0.1) {\n            alternativeSheets.forEach(sheet => {\n              if (!sheet.fabric) return;\n\n              const { objects } = JSON.parse(sheet.fabric);\n              const imageframes = objects.filter(\n                obj => obj.type === \"imageframe\"\n              );\n\n              if (imageframes.length === 2 && sheet.autofillable) {\n                const [frame] = imageframes;\n                const frameAspectRatio = frame.width / frame.height;\n                const difference = Math.abs(\n                  imageAspectRatio - frameAspectRatio\n                );\n\n                if (difference < smallestDifference) {\n                  smallestDifference = difference;\n                  if (smallestDifference < 0.2) {\n                    bestTemplate = sheet;\n                  }\n                }\n              }\n            });\n            if (bestTemplate) {\n              resolve(bestTemplate);\n              return;\n            }\n          }\n          alternativeSheets.forEach(sheet => {\n            if (!sheet.fabric) return;\n\n            const { objects } = JSON.parse(sheet.fabric);\n            const imageframes = objects.filter(\n              obj => obj.type === \"imageframe\"\n            );\n\n            if (imageframes.length === 1 && sheet.autofillable) {\n              const [frame] = imageframes;\n              const frameAspectRatio = frame.width / frame.height;\n              const difference = Math.abs(imageAspectRatio - frameAspectRatio);\n\n              if (difference < smallestDifference) {\n                smallestDifference = difference;\n                bestTemplate = sheet;\n              }\n            }\n          });\n\n          resolve(bestTemplate);\n        };\n\n        nextLoaderImage.onerror = () => {\n          resolve(null);\n        };\n\n        nextLoaderImage.src = nextImage.url;\n      } else {\n        let smallestDifference = Infinity;\n\n        alternativeSheets.forEach(sheet => {\n          if (!sheet.fabric) return;\n\n          const { objects } = JSON.parse(sheet.fabric);\n          const imageframes = objects.filter(obj => obj.type === \"imageframe\");\n\n          if (imageframes.length === 1 && sheet.autofillable) {\n            const [frame] = imageframes;\n            const frameAspectRatio = frame.width / frame.height;\n            const difference = Math.abs(imageAspectRatio - frameAspectRatio);\n\n            if (difference < smallestDifference) {\n              smallestDifference = difference;\n              bestTemplate = sheet;\n            }\n          }\n        });\n\n        resolve(bestTemplate);\n      }\n    };\n\n    loaderImage.onerror = () => {\n      resolve(null);\n    };\n\n    loaderImage.src = image.url;\n  });\n}\n","import { Brut } from \"@/components/brut/src/index.ts\";\nimport { isEqual, findIndex } from \"lodash-es\";\nimport { defaultCaption, defaultTextPageText } from \"./photobookDefaultText\";\nimport Blobber from \"./blobber\";\nimport swapper from \"./swapTemplate\";\nimport findBestTemplate from \"./findBestTemplate\";\n\nconst buildCanvas = (\n  sheet,\n  {\n    reassignCanvasDimensions = false,\n    perspectiveCanvasRequired = false,\n    foilCanvasRequired = false\n  } = {}\n) => {\n  let element;\n\n  if (\"OffscreenCanvas\" in window) {\n    element = new OffscreenCanvas(100, 100);\n  } else {\n    element = document.createElement(\"canvas\");\n    element.width = 100;\n    element.height = 100;\n  }\n\n  /* eslint-disable no-param-reassign */\n  if (reassignCanvasDimensions) {\n    element.width = sheet.width;\n    element.height = sheet.height;\n  }\n\n  const renderer = new Brut(element, {\n    offscreen: true,\n    compressImage: true,\n    perspectiveCanvasRequired: perspectiveCanvasRequired || foilCanvasRequired,\n    foilCanvasRequired\n  });\n  renderer.init();\n  return renderer;\n};\n\nconst reinsertExtractedImagesOffscreen = (\n  canvas,\n  images,\n  { shouldRecenter, selectImage }\n) => {\n  const promises = canvas.imageObjects().map((object, index) => {\n    return new Promise(resolve => {\n      if (images[index]) {\n        const { image, imageOptions, userRotation } = images[index];\n        canvas.setImageframeImage(\n          object,\n          image.url,\n          image,\n          {\n            shouldRecenter,\n            selectImage,\n            imageOptions,\n            userRotation\n          },\n          () => {\n            canvas.checkObjectEdited(object);\n            resolve();\n          }\n        );\n      } else {\n        resolve();\n      }\n    });\n  });\n\n  return Promise.all(promises);\n};\n\nconst reinsertExtractedCaptionsOffscreen = (canvas, captions) => {\n  const promises = canvas.textObjects().map((object, index) => {\n    return new Promise(resolve => {\n      if (captions[index]) {\n        canvas.setActiveObject(object);\n        canvas.selectedTextbox = object;\n        captions[index].forEach(caption => {\n          canvas.updatePredefinedString(caption);\n          const i = findIndex(\n            object.predefinedStrings,\n            string => string.key === caption.key\n          );\n          if (i === -1) {\n            return;\n          }\n          caption.style = object.predefinedStrings[i].style;\n          caption.textBox = object;\n          object.predefinedStrings[i] = caption;\n        });\n        canvas.checkObjectEdited(object);\n        resolve();\n      } else {\n        resolve();\n      }\n    });\n  });\n\n  return Promise.all(promises);\n};\n\n// This method removes the temporarily created foil canvases from the DOM to avoid memory consumption\n// The foil canvases are added to the DOM when the foil canvas is required\n// for rendering the template with the correct font-feature-settings\n// https://github.com/papier-ltd/website/pull/9693/\nconst deleteTemporarilyOnscreenFoilCanvases = () => {\n  const canvases = document.getElementsByClassName(\n    \"temporarily-onscreen-foil-canvas\"\n  );\n\n  [...canvases].forEach(canvas => {\n    canvas.remove();\n  });\n};\n\nexport default {\n  renderCanvas(sheet, foilCanvasRequired = false) {\n    let renderer = buildCanvas(sheet, {\n      reassignCanvasDimensions: true,\n      foilCanvasRequired\n    });\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(sheet.fabric, async () => {\n        const base64 = await renderer.offscreenImageRepresentation();\n        sheet.preview = Blobber.base64ToBlob(base64);\n        sheet.svg = renderer.svgRepresentation();\n        sheet.skodix_svg = renderer.skodixSvgRepresentation();\n        renderer.dispose();\n        renderer = null;\n\n        if (foilCanvasRequired) {\n          deleteTemporarilyOnscreenFoilCanvases();\n        }\n\n        resolve();\n      });\n    });\n  },\n\n  renderAndReturnImage(sheet, foilCanvasRequired = false) {\n    let renderer = buildCanvas(sheet, {\n      reassignCanvasDimensions: true,\n      foilCanvasRequired\n    });\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(sheet.fabric, async () => {\n        const preview = await renderer.offscreenImageRepresentation(\n          undefined,\n          true\n        );\n        renderer.dispose();\n        renderer = null;\n        resolve(preview);\n      });\n    });\n  },\n\n  renderAndReturnSvg(sheet, text) {\n    let renderer = buildCanvas(sheet, { reassignCanvasDimensions: true });\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(sheet.fabric, () => {\n        const [papierBox] = renderer.textObjects();\n        papierBox.replaceText(text);\n        const svg = renderer.svgRepresentation();\n        renderer.dispose();\n        renderer = null;\n        resolve(svg);\n      });\n    });\n  },\n\n  renderPreviewTemplateCanvas(sheet, images) {\n    let renderer = buildCanvas(sheet, {\n      reassignCanvasDimensions: true,\n      perspectiveCanvasRequired: true\n    });\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(sheet.fabric, () => {\n        const perspectiveImages = renderer.perspectiveImages();\n\n        if (perspectiveImages.length !== images.length) {\n          // We should not render the preview template if the number of images\n          // does not match the number of perspective images\n          // This is to prevent the preview template's stock product from showing in the image\n          // We resolve null as this is the default value for the preview store's 'templatedPreviewImage' property\n          // which is updated with the result of this function\n          renderer.dispose();\n          resolve(null);\n        }\n\n        const promises = images.map((image, index) =>\n          perspectiveImages[index].setImageUrl(image)\n        );\n\n        Promise.all(promises).then(async () => {\n          renderer.renderAll();\n          const previewImage = await renderer.offscreenImageRepresentation(\n            false,\n            true\n          );\n          renderer.dispose();\n          renderer = null;\n          resolve(previewImage);\n        });\n      });\n    });\n  },\n\n  removeDefaultText(sheet) {\n    let renderer = buildCanvas(sheet);\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(sheet.fabric, async () => {\n        const textboxes = renderer.textObjects();\n\n        textboxes.forEach(textbox => {\n          if ([defaultCaption, defaultTextPageText].includes(textbox.text)) {\n            textbox.clearText();\n          }\n        });\n        renderer.renderAll();\n        const previewImage = await renderer.offscreenImageRepresentation();\n        const fabric = renderer.jsonRepresentation();\n        const svg = renderer.svgRepresentation();\n        const skodixSvg = renderer.skodixSvgRepresentation();\n        renderer.dispose();\n        renderer = null;\n        resolve({ previewImage, fabric, svg, skodixSvg, index: sheet.index });\n      });\n    });\n  },\n\n  getImageFrameCoordinates(sheet) {\n    let renderer = buildCanvas(sheet);\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(sheet.fabric, () => {\n        const imageFrames = renderer.nonLogoImageObjects();\n        const coordinates = imageFrames.map(imageFrame => ({\n          ...imageFrame.boundingBox.toJSON(),\n          userRotation: imageFrame.userRotation,\n          scale: imageFrame.imageOptions.scale\n        }));\n        renderer.dispose();\n        renderer = null;\n        resolve({ coordinates, index: sheet.index });\n      });\n    });\n  },\n\n  async renderCanvasAndCaptureData(renderer, sheet, resolve) {\n    renderer.renderAll();\n    const previewImage = await renderer.offscreenImageRepresentation();\n    const fabric = renderer.jsonRepresentation();\n    const svg = renderer.svgRepresentation();\n    const skodixSvg = renderer.skodixSvgRepresentation();\n    const images = renderer.imageArrayRepresentation();\n    renderer.dispose();\n    renderer = null;\n\n    resolve({\n      previewImage,\n      fabric,\n      svg,\n      skodixSvg,\n      images,\n      index: sheet.index,\n      id: sheet.id\n    });\n  },\n\n  async updateImageFramesFromDropPanes({\n    sheet,\n    primaryPaneData,\n    secondaryPaneData = null,\n    chooseBetterTemplate = false,\n    alternativeSheets = []\n  }) {\n    const sheetToUse = sheet;\n    let sheetIsSwapped = false;\n\n    const { objects } = JSON.parse(sheet.fabric);\n\n    if (\n      objects.filter(obj => obj.type === \"imageframe\").length === 1 &&\n      chooseBetterTemplate\n    ) {\n      const bestTemplate = await findBestTemplate(\n        primaryPaneData.photo,\n        alternativeSheets\n      );\n      if (bestTemplate) {\n        swapper.setupBackgroundTemplateSwap({\n          sheet: sheetToUse,\n          template: bestTemplate,\n          fromAutofill: true\n        });\n        sheetIsSwapped = true;\n      }\n    }\n\n    const renderer = buildCanvas(sheetToUse, {\n      reassignCanvasDimensions: true\n    });\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(sheetToUse.fabric, async () => {\n        const imageFrames = renderer.nonLogoImageObjects();\n        let [frame] = imageFrames;\n\n        if (!sheetIsSwapped) {\n          frame = imageFrames.find(imageFrame => {\n            const { userRotation, scale, ...adjustedRect } =\n              primaryPaneData.rect;\n            return isEqual(imageFrame.boundingBox.toJSON(), adjustedRect);\n          });\n        }\n\n        let secondFrame;\n\n        if (secondaryPaneData?.rect) {\n          secondFrame = imageFrames.find(imageFrame => {\n            const { userRotation, scale, ...adjustedRect } =\n              secondaryPaneData.rect;\n            return isEqual(imageFrame.boundingBox.toJSON(), adjustedRect);\n          });\n        }\n\n        if (primaryPaneData.photo) {\n          // when we are adding an image to the main imageframe\n          renderer.setImageframeImage(\n            frame,\n            primaryPaneData.photo.url,\n            primaryPaneData.photo,\n            {\n              userRotation: primaryPaneData.userRotation || 0,\n              scale: primaryPaneData.scale || 1\n            },\n            async () => {\n              // when we have also provided a second imageframe to update\n              if (secondFrame && secondaryPaneData) {\n                // when the second imageframe should be cleared as no swapBackPhoto is provided\n                if (!secondaryPaneData.photo) {\n                  secondFrame.clearImage();\n                  await this.renderCanvasAndCaptureData(\n                    renderer,\n                    sheetToUse,\n                    resolve\n                  );\n                } else {\n                  // when we have an image to swap back to the second imageframe\n                  renderer.setImageframeImage(\n                    secondFrame,\n                    secondaryPaneData.photo.url,\n                    secondaryPaneData.photo,\n                    {\n                      userRotation: secondaryPaneData.userRotation || 0,\n                      scale: secondaryPaneData.scale || 1\n                    },\n                    async () => {\n                      await this.renderCanvasAndCaptureData(\n                        renderer,\n                        sheetToUse,\n                        resolve\n                      );\n                    }\n                  );\n                }\n              } else {\n                // if we don't have a second imageframe to update\n                // we just render the canvas for the main imageframe update (assigning the image)\n                await this.renderCanvasAndCaptureData(\n                  renderer,\n                  sheetToUse,\n                  resolve\n                );\n              }\n            }\n          );\n        } else {\n          // when we don't have an image to add to the main imageframe\n          frame.clearImage();\n          if (secondFrame && secondaryPaneData) {\n            // when we have been provided a second imageframe to update\n            if (!secondaryPaneData.photo) {\n              // if we are not provided a swapBackPhoto, we clear the second imageframe\n              secondFrame.clearImage();\n              await this.renderCanvasAndCaptureData(\n                renderer,\n                sheetToUse,\n                resolve\n              );\n            } else {\n              // if we have a swapBackPhoto, we update the second imageframe to have that image\n              renderer.setImageframeImage(\n                secondFrame,\n                secondaryPaneData.photo.url,\n                secondaryPaneData.photo,\n                {\n                  userRotation: secondaryPaneData.userRotation || 0,\n                  scale: secondaryPaneData.scale || 1\n                },\n                async () => {\n                  await this.renderCanvasAndCaptureData(\n                    renderer,\n                    sheetToUse,\n                    resolve\n                  );\n                }\n              );\n            }\n          } else {\n            // if we don't have a second imageframe to update\n            // we just render the canvas for the main imageframe update (clearing the image)\n            await this.renderCanvasAndCaptureData(\n              renderer,\n              sheetToUse,\n              resolve\n            );\n          }\n        }\n      });\n    });\n  },\n\n  extractImagesAndCaptions(coverSheet) {\n    const renderer = buildCanvas(coverSheet);\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(coverSheet.fabric, () => {\n        const images = swapper.extractImages(renderer);\n        const captions = swapper.extractCaptions(renderer);\n        renderer.dispose();\n        resolve({ images, captions });\n      });\n    });\n  },\n\n  swapTemplateOffscreen(template, options) {\n    const renderer = buildCanvas(template, {\n      reassignCanvasDimensions: true,\n      foilCanvasRequired: options.foilCanvasRequired\n    });\n\n    return new Promise(resolve => {\n      renderer.loadOffscreen(template.fabric, async () => {\n        await reinsertExtractedImagesOffscreen(\n          renderer,\n          options.images,\n          options\n        );\n        await reinsertExtractedCaptionsOffscreen(renderer, options.captions);\n        const previewImage = await renderer.offscreenImageRepresentation();\n        const fabric = renderer.jsonRepresentation();\n        const svg = renderer.svgRepresentation();\n        const skodixSvg = renderer.skodixSvgRepresentation();\n        const images = renderer.imageArrayRepresentation();\n        renderer.dispose();\n        resolve({ previewImage, fabric, svg, images, skodixSvg });\n      });\n    });\n  }\n};\n"],"names":["defaultCaption","defaultTextPageText","Blobber","base64","typePart","base64Data","byteCharacters","byteNumbers","i","byteArray","type","blob","url","resolve","reader","findBestTemplate","image","alternativeSheets","nextImage","allowMultipleImages","bestTemplate","loaderImage","imageAspectRatio","nextLoaderImage","nextImageAspectRatio","smallestDifference","sheet","objects","imageframes","obj","frame","frameAspectRatio","difference","buildCanvas","reassignCanvasDimensions","perspectiveCanvasRequired","foilCanvasRequired","element","renderer","Brut","reinsertExtractedImagesOffscreen","canvas","images","shouldRecenter","selectImage","promises","object","index","imageOptions","userRotation","reinsertExtractedCaptionsOffscreen","captions","caption","findIndex","string","deleteTemporarilyOnscreenFoilCanvases","preview","text","papierBox","svg","perspectiveImages","previewImage","textbox","fabric","skodixSvg","coordinates","imageFrame","primaryPaneData","secondaryPaneData","chooseBetterTemplate","sheetToUse","sheetIsSwapped","swapper","imageFrames","scale","adjustedRect","isEqual","secondFrame","coverSheet","template","options"],"mappings":"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"}