import { type RetryPolicy } from './retry.js'; /** * Load an image, repeating a failed attempt under the shared policy * (`@polotno/core/retry`). This is the canvas-side counterpart of * `fetchWithRetry`: the editor's own hook does the same thing for the React * tree, and every converter that draws a bitmap comes through here. * * The element is built through the platform seam, so a Node consumer can * inject its own factory. */ export declare function loadImage(url: string, policy?: RetryPolicy): Promise; export declare function getImageSize(url: string): Promise; interface CropElementLike { stretchEnabled?: boolean; cropX: number; cropY: number; cropWidth: number; cropHeight: number; width: number; height: number; } /** * How far inside its box an element must stop PAINTING, so an opaque inside * border alone draws the outer edge — otherwise the picture antialiases there * too and survives the border's blend as `colour * a * (1 - a)`, leaving a line * of itself outside a border that should be solid. Clip to it; shrinking the * box would scale the picture. * * Zero unless the border COLOUR is provably opaque — a translucent border shows * the picture by design, and a gradient reaches tinycolor as unparseable — and * zero for a border at least as thick as the box, where the border rect is * itself degenerate and paints nothing, so clipping would erase the element. */ export declare function getBorderInset(element: { borderSize?: number; borderColor?: string; width: number; height: number; }): number; /** * The crop rectangle in SOURCE pixels — the kernel every renderer crops * with (editor canvas, svg/html/pdf export, page backgrounds, videos). * `cropX/Y/Width/Height` are 0-1 fractions of the source; the region is * aspect-fitted to the element box unless the element stretches. */ export declare function getCropRect(element: CropElementLike, sourceSize: { width: number; height: number; }): { x: number; y: number; width: number; height: number; }; interface CropTransformElementLike extends CropElementLike { flipX?: boolean; flipY?: boolean; } /** * The same crop rect, anchored from the opposite edge on each mirrored axis — * the region to sample when the mirror is applied AFTER the crop. * * The canvas mirrors the source bitmap and crops the result, so it reads the * far end of the source. A renderer that instead crops first and mirrors the * finished picture (an svg/CSS transform, a PowerPoint picture frame) has to * ask for that far end itself, or it draws the correct region reversed at the * wrong end of the image. * * The anchor comes off the ASPECT-FITTED rect. Deriving it from * `cropWidth/Height` instead is the bug this exists to stop: that is the window * before the fit trimmed it, so the two agree until the fit trims that axis and * then anchor from opposite ends. */ export declare function getFlippedCropRect(element: CropTransformElementLike, sourceSize: { width: number; height: number; }): { x: number; y: number; width: number; height: number; }; /** * The scaled placement a crop-then-mirror renderer draws the source with — svg, * html and pdf's vector path: how big the full image is on screen * (`cropScaledWidth/Height`) and how far it shifts so the crop region lands in * the element box (`cropScaledX/Y`). * * A mirrored offset presumes its pivot: the caller mirrors about the ELEMENT * BOX. Mirroring about the drawn image instead lands back on the near end of * the source — the bug `getFlippedCropRect` exists to stop. */ export declare function getCropTransform(element: CropTransformElementLike, imageSize: { width: number; height: number; }): { scaleX: number; scaleY: number; cropScaledX: number; cropScaledY: number; cropScaledWidth: number; cropScaledHeight: number; }; export declare function cropImage(src: any, element: any, preloaded?: HTMLImageElement): Promise; type Size = { width: number; height: number; }; /** * The size an image takes when scaled UNIFORMLY until it fills `box`, so it * overflows on the long axis and the box clips it. CSS `background-size: cover`. * * The third fit in this file, and the one renderers keep confusing with the * other two. To pick: * * - `getCropRect` — the region of the SOURCE to read, aspect-fit and anchored * at `cropX/cropY`. What the canvas crops with. * - `getFlippedCropRect` — the same region, anchored from the far edge on a * mirrored axis. For a renderer that crops first and mirrors afterwards. * - `getCrop` — the same region, CENTRED, as 0-1 fractions. For a mask fill. * - `coverSize` — the size to DRAW at, in destination pixels. For a mask shape, * which keeps its own aspect and lets the box clip the overflow. * * A flip belongs to the mask SHAPE and never to the fill: the canvas mirrors * `element.src` — which on a `maskSrc` element IS the shape — and then * composites the fill into the result unmirrored, so a mirrored element shows a * mirrored silhouette holding upright artwork. The shape mirrors BEFORE the box * clips it, so a `coverSize` shape keeps its FAR end: the same anchoring * `getFlippedCropRect` applies to a crop. Each converter reproduces that in its * own idiom — no shared code can emit a CSS wrapper, an SVG transform and a * canvas matrix at once — and svg, html and pdf do. pptx still mirrors the * finished composite, so it moves shape and fill together. * * Returns whole pixels: every caller rasterizes at this size, and a fractional * canvas dimension is silently floored anyway. A degenerate image (either axis * zero — a viewBox-only SVG that never got an intrinsic size) falls back to the * box, which is what the callers hand-rolled as a guard. */ export declare function coverSize(box: Size, image: Size): Size; /** * The CENTRED cover-crop, as 0-1 fractions: the region of the source with the * element box's aspect ratio, taken from the middle. CSS `object-fit: cover`. * * Deliberately different from `getCropRect`, which anchors at `cropX/cropY` * (top-left for an uncropped element). Reach for this when the source is * content a user placed and expects to stay centred — notably a MASK FILL, the * image dropped onto a shape, where anchoring top-left crops the subject out. * The editor canvas has always centred that (`getCrop` in image-element.tsx). * * Fractions rather than pixels on purpose: they feed straight into any * renderer's existing `cropX/cropY/cropWidth/cropHeight` pipeline, so nobody * has to grow a second copy of the arithmetic. The returned region already has * the box's aspect ratio, so stretching vs aspect-fitting it afterwards is * immaterial. */ export declare function getCrop(elementSize: Size, originalImageSize: Size): { cropX: number; cropY: number; cropWidth: number; cropHeight: number; }; export {};