Edit the watermark in place, rotate the frame photo, place a custom watermark
Watermark editing no longer covers the photo: the preview letterboxes the image inside its fit rect while the deck is open, and the idle hint is gone. The FRAME tab can rotate a library photo 90 degrees clockwise. Rotation swaps the pixel dimensions instead of the frame, so the polaroid/wall window keeps its aspect and every consumer (cover crop, watermark area, export) picks up the new orientation from width()/height() with no extra layout branch. The rotate surface is CPU-backed on purpose - a GPU snapshot loses its pixels before the next frame and renders the photo black. Custom watermark text can now be dragged anywhere on the photo, double-tapped to re-edit, and is only baked into the file once ACCEPT is pressed; the export engine takes the same position. It also gained COLOR/SIZE/FONT chips, with the font list read from the OS via Skia's FontMgr so any installed family can be used.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { Skia, type SkImage } from '@shopify/react-native-skia';
|
||||
|
||||
// Turn a decoded image 90deg clockwise into a fresh SkImage. Used by the FRAME
|
||||
// tab so a library photo can go landscape <-> portrait before it enters a frame:
|
||||
// every consumer reads width()/height(), so the pixel-dimension swap carries the
|
||||
// new orientation through the polaroid window aspect, the cover crop and the
|
||||
// watermark areas without a single extra layout branch.
|
||||
// ponytail: offscreen surface, same fallback as exportEngine.createSurface; a
|
||||
// matrix-based draw would avoid the copy if this ever shows up in a profile.
|
||||
export function rotateSkImage90(image: SkImage | null): SkImage | null {
|
||||
if (!image) return null;
|
||||
const w = image.width();
|
||||
const h = image.height();
|
||||
if (!(w > 0 && h > 0)) return null;
|
||||
// CPU-backed on purpose: a GPU (MakeOffscreen) snapshot keeps its pixels in a
|
||||
// context texture that is gone by the time the <Canvas> draws a frame later —
|
||||
// the preview then renders the photo completely black. Raster pixels survive
|
||||
// the trip to the render thread.
|
||||
const surface = Skia.Surface.Make(h, w);
|
||||
if (!surface) return image; // keep the unrotated photo on allocation failure
|
||||
const canvas = surface.getCanvas();
|
||||
canvas.clear(Skia.Color('transparent'));
|
||||
canvas.translate(h, 0);
|
||||
canvas.rotate(90, 0, 0);
|
||||
canvas.drawImage(image, 0, 0);
|
||||
return surface.makeImageSnapshot() ?? image;
|
||||
}
|
||||
Reference in New Issue
Block a user