diff --git a/assets/CourierPrime-Regular.ttf b/assets/CourierPrime-Regular.ttf deleted file mode 100644 index 2a0f8bd..0000000 Binary files a/assets/CourierPrime-Regular.ttf and /dev/null differ diff --git a/assets/Cousine-Regular.ttf b/assets/Cousine-Regular.ttf new file mode 100644 index 0000000..e01ff6f Binary files /dev/null and b/assets/Cousine-Regular.ttf differ diff --git a/src/components/Viewfinder.tsx b/src/components/Viewfinder.tsx index f86c0c0..44218ab 100644 --- a/src/components/Viewfinder.tsx +++ b/src/components/Viewfinder.tsx @@ -100,7 +100,7 @@ export default function Viewfinder({ const skiaImage = useImage(libraryImageUri || ''); const customFont = useFont( - require('../../assets/CourierPrime-Regular.ttf'), + require('../../assets/Cousine-Regular.ttf'), Math.round(vw * 0.032) ); // Monochrome Noto Emoji subset (📍 U+1F4CD, 📷 U+1F4F7) for the watermark @@ -518,10 +518,24 @@ export default function Viewfinder({ const pad = (n: number) => String(n).padStart(2, '0'); const timestampStr = `${pad(d.getDate())}/${pad(d.getMonth() + 1)}/${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}`; - // Baseline above the bottom chrome (shutter rail) so the watermark stays - // readable; polaroid frames push it further up onto the white area edge. - const yOffset = vh - (selectedFrame === 'polaroid' ? vh * 0.18 + 24 : 150); - const xOffset = selectedFrame === 'polaroid' ? vw * 0.08 : 16; + // Anchor to the PHOTO, not the screen. In camera mode the photo fills the + // screen (area = full canvas). In library mode the photo is contain-fitted + // with black letterbox — a screen-bottom baseline used to land below the + // photo on the letterbox, off the image, so users could not see it. Compute + // inside the fitted rect (imageFitRect) so the mark sits at the photo's + // bottom-left corner; keep it above the bottom chrome/shutter rail. + const area = + mode === 'library' && imageFitRect + ? imageFitRect + : { dx: 0, dy: 0, dw: vw, dh: vh }; + const padBottom = + selectedFrame === 'polaroid' ? area.dh * 0.18 + 24 : Math.min(150, area.dh * 0.2); + const yOffset = + mode === 'library' + ? Math.min(area.dy + area.dh - padBottom, vh - 190) // never under the deck + : area.dy + area.dh - padBottom; + const xOffset = + area.dx + (selectedFrame === 'polaroid' ? area.dw * 0.08 : Math.min(16, area.dw * 0.04)); const gap = (rect: { width?: number } | null) => Math.round((rect?.width ?? Math.round(vw * 0.032)) + vw * 0.012); const pinW = iconFont.measureText('📍'); diff --git a/src/utils/exportEngine.ts b/src/utils/exportEngine.ts index ec2a518..a20c1ca 100644 --- a/src/utils/exportEngine.ts +++ b/src/utils/exportEngine.ts @@ -261,7 +261,7 @@ export async function processAndExportPhoto( // 8. Render GPS Geotag Watermark if (useGeotag && gpsInfo) { - const fontAsset = Asset.fromModule(require('../../assets/CourierPrime-Regular.ttf')); + const fontAsset = Asset.fromModule(require('../../assets/Cousine-Regular.ttf')); const iconFontAsset = Asset.fromModule(require('../../assets/NotoEmoji-GPS.ttf')); await Promise.all([fontAsset.downloadAsync(), iconFontAsset.downloadAsync()]); const [fontData, iconFontData] = await Promise.all([