fixes
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Caratteri di terze parti inclusi in pi-imgen
|
# Caratteri di terze parti inclusi in pi-imgen
|
||||||
|
|
||||||
Generato da `scripts/fetch-fonts.sh` il 2026-08-27 07:43 UTC. Non modificare a mano.
|
Generato da `scripts/fetch-fonts.sh` il 2026-08-27 12:28 UTC. Non modificare a mano.
|
||||||
|
|
||||||
I file dei caratteri stanno in `vendor/fonts/<id>/` e **non** sono versionati.
|
I file dei caratteri stanno in `vendor/fonts/<id>/` e **non** sono versionati.
|
||||||
Ogni cartella contiene il file `LICENSE` originale.
|
Ogni cartella contiene il file `LICENSE` originale.
|
||||||
|
|||||||
@@ -724,7 +724,12 @@ export class DrawThingsBackend implements Backend {
|
|||||||
this.offline = opts.offline ?? process.env.IMGEN_OFFLINE === "1";
|
this.offline = opts.offline ?? process.env.IMGEN_OFFLINE === "1";
|
||||||
this.timeoutMs = opts.timeoutMs ?? 0;
|
this.timeoutMs = opts.timeoutMs ?? 0;
|
||||||
this.upscaleSteps = opts.upscaleSteps ?? 12;
|
this.upscaleSteps = opts.upscaleSteps ?? 12;
|
||||||
this.upscaleStrength = opts.upscaleStrength ?? 0.25;
|
// 0.4 (up from 0.25) is the floor for going from a 768px draft to a 3579px A3 print
|
||||||
|
// target: at the lower strength SeedVR2 essentially echoes the bicubic resample,
|
||||||
|
// which is what was shipping as a "sgranata" final poster. 0.4 is past the point
|
||||||
|
// where the upscaler invents detail instead of restoring it, while still leaving
|
||||||
|
// the prompt's composition alone.
|
||||||
|
this.upscaleStrength = opts.upscaleStrength ?? 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- probe ---------------------------------------------------------------
|
// -- probe ---------------------------------------------------------------
|
||||||
|
|||||||
@@ -256,15 +256,46 @@ function resolveConfig(deps: LogoDeps): ImgenConfig {
|
|||||||
return typeof deps.config === "function" ? deps.config() : deps.config;
|
return typeof deps.config === "function" ? deps.config() : deps.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** `setStatus` is a no-op on some surfaces; guarded anyway — belt and braces. */
|
/**
|
||||||
|
* `setStatus` is a no-op on some surfaces; guarded anyway — belt and braces.
|
||||||
|
*
|
||||||
|
* Drives the working spinner too: `setStatus` alone redraws nothing on its own, and a
|
||||||
|
* generation that updates only the status line looks frozen during a multi-minute model
|
||||||
|
* run. `setWorkingVisible(true)` keeps the spinner up while we are talking to a model,
|
||||||
|
* and `setWorkingMessage` is the text it shows next to the spinner dots.
|
||||||
|
*/
|
||||||
function status(ctx: ExtensionContext, text: string | undefined): void {
|
function status(ctx: ExtensionContext, text: string | undefined): void {
|
||||||
try {
|
try {
|
||||||
ctx.ui.setStatus("imgen", text);
|
ctx.ui.setStatus("imgen", text);
|
||||||
|
const ui = ctx.ui as unknown as {
|
||||||
|
setWorkingMessage?: (t: string | undefined) => void;
|
||||||
|
setWorkingVisible?: (b: boolean) => void;
|
||||||
|
setWorkingIndicator?: (kind: string | undefined) => void;
|
||||||
|
};
|
||||||
|
ui.setWorkingMessage?.(text);
|
||||||
|
ui.setWorkingVisible?.(Boolean(text));
|
||||||
|
ui.setWorkingIndicator?.(text ? "dots" : undefined);
|
||||||
} catch {
|
} catch {
|
||||||
/* a status line is never worth failing a job over */
|
/* a status line is never worth failing a job over */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Kill the spinner if the command exits through a path that did not already clear it. */
|
||||||
|
function clearWorking(ctx: ExtensionContext): void {
|
||||||
|
try {
|
||||||
|
const ui = ctx.ui as unknown as {
|
||||||
|
setWorkingVisible?: (b: boolean) => void;
|
||||||
|
setWorkingIndicator?: (kind: string | undefined) => void;
|
||||||
|
setWorkingMessage?: (t: string | undefined) => void;
|
||||||
|
};
|
||||||
|
ui.setWorkingVisible?.(false);
|
||||||
|
ui.setWorkingIndicator?.(undefined);
|
||||||
|
ui.setWorkingMessage?.(undefined);
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function notify(ctx: ExtensionContext, message: string, kind: "info" | "warning" | "error" = "info"): void {
|
function notify(ctx: ExtensionContext, message: string, kind: "info" | "warning" | "error" = "info"): void {
|
||||||
try {
|
try {
|
||||||
ctx.ui.notify(message, kind);
|
ctx.ui.notify(message, kind);
|
||||||
|
|||||||
@@ -172,17 +172,26 @@ const RESULT_MESSAGE = "imgen-poster";
|
|||||||
* Draft artwork: small and few steps. Its only job is to let him judge composition and
|
* Draft artwork: small and few steps. Its only job is to let him judge composition and
|
||||||
* colour, and it must come back fast enough that the refinement loop feels like a
|
* colour, and it must come back fast enough that the refinement loop feels like a
|
||||||
* conversation rather than a render farm.
|
* conversation rather than a render farm.
|
||||||
|
*
|
||||||
|
* 768px on the long edge — not 512 — because the final pass upsamples this image to
|
||||||
|
* print resolution. 512px → ~3579px A3 is a 7× stretch through any upscaler, and the
|
||||||
|
* texture collapses before the upscale can save it. 768px halves that stretch and keeps
|
||||||
|
* enough pixels (~96px/tile on the WCAG tile grid in contrast.ts) for the contrast
|
||||||
|
* measurement to read the artwork faithfully instead of returning a flat average.
|
||||||
*/
|
*/
|
||||||
const DRAFT_LONG_EDGE = 512;
|
const DRAFT_LONG_EDGE = 768;
|
||||||
const DRAFT_STEPS = 4;
|
const DRAFT_STEPS = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Final artwork: the full local cap (see render/formats.ts) and enough steps to hold up in
|
* Final artwork: the full local cap (see render/formats.ts) and enough steps to hold up in
|
||||||
* print. Reached ONLY when there is no approved draft to enlarge — i.e. the headless
|
* print. Reached ONLY when there is no approved draft to enlarge — i.e. the headless
|
||||||
* pipeline. In the interactive command a second generation would be a different picture,
|
* pipeline. In the interactive command a second generation would be a different picture,
|
||||||
* so the final comes from the draft: see `PaintOptions.from`.
|
* so the final comes from the draft: see `PaintOptions.from`.
|
||||||
|
*
|
||||||
|
* 16 steps (up from 8) is the honest floor for z_image_turbo on a print poster: anything
|
||||||
|
* lower trades away the texture the upscale is supposed to amplify, not invent.
|
||||||
*/
|
*/
|
||||||
const FINAL_STEPS = 8;
|
const FINAL_STEPS = 16;
|
||||||
|
|
||||||
/** Preview render resolution during the draft loop. A terminal cell is not 300 dpi. */
|
/** Preview render resolution during the draft loop. A terminal cell is not 300 dpi. */
|
||||||
const DRAFT_PPI = 72;
|
const DRAFT_PPI = 72;
|
||||||
@@ -263,17 +272,60 @@ function isAbort(e: unknown): boolean {
|
|||||||
return e instanceof Error && (e.name === "AbortError" || e.name === "TimeoutError");
|
return e instanceof Error && (e.name === "AbortError" || e.name === "TimeoutError");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Status line writer that never explodes in a mode without a footer. */
|
/**
|
||||||
|
* Status line writer that also drives the working spinner and its message. `setStatus`
|
||||||
|
* alone redraws nothing on its own; `setWorkingMessage` is what the working indicator
|
||||||
|
* shows, and `setWorkingVisible(true)` is what forces it to stay up while we are
|
||||||
|
* talking to a model. The spinner is the thing he sees during a multi-minute diffusion
|
||||||
|
* run; without it the footer looks frozen between status updates and he does not know
|
||||||
|
* whether the command is still alive.
|
||||||
|
*
|
||||||
|
* Every call is wrapped — `setStatus` and the working-indicator setters are no-ops on
|
||||||
|
* headless surfaces, and a missing method must never abort a generation.
|
||||||
|
*/
|
||||||
function statusWriter(ctx: ExtensionContext): (text: string | undefined) => void {
|
function statusWriter(ctx: ExtensionContext): (text: string | undefined) => void {
|
||||||
|
let lastVisible = false;
|
||||||
return (text) => {
|
return (text) => {
|
||||||
try {
|
try {
|
||||||
ctx.ui.setStatus(STATUS_KEY, text);
|
ctx.ui.setStatus(STATUS_KEY, text);
|
||||||
|
const ui = ctx.ui as unknown as {
|
||||||
|
setWorkingMessage?: (t: string | undefined) => void;
|
||||||
|
setWorkingVisible?: (b: boolean) => void;
|
||||||
|
setWorkingIndicator?: (kind: string | undefined) => void;
|
||||||
|
};
|
||||||
|
ui.setWorkingMessage?.(text);
|
||||||
|
const wantVisible = Boolean(text);
|
||||||
|
if (wantVisible !== lastVisible) {
|
||||||
|
ui.setWorkingVisible?.(wantVisible);
|
||||||
|
ui.setWorkingIndicator?.(wantVisible ? "dots" : undefined);
|
||||||
|
lastVisible = wantVisible;
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
/* headless surface without a status bar */
|
/* headless surface without a footer */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure the working indicator is OFF when the command returns, no matter which path
|
||||||
|
* returned. `statusWriter` toggles it on/off on every status call, but any thrown branch
|
||||||
|
* that bypasses the writer would leave the spinner spinning forever.
|
||||||
|
*/
|
||||||
|
function clearWorkingIndicator(ctx: ExtensionContext): void {
|
||||||
|
try {
|
||||||
|
const ui = ctx.ui as unknown as {
|
||||||
|
setWorkingVisible?: (b: boolean) => void;
|
||||||
|
setWorkingIndicator?: (kind: string | undefined) => void;
|
||||||
|
setWorkingMessage?: (t: string | undefined) => void;
|
||||||
|
};
|
||||||
|
ui.setWorkingVisible?.(false);
|
||||||
|
ui.setWorkingIndicator?.(undefined);
|
||||||
|
ui.setWorkingMessage?.(undefined);
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function notify(ctx: ExtensionContext, message: string, kind: "info" | "warning" | "error" = "info"): void {
|
function notify(ctx: ExtensionContext, message: string, kind: "info" | "warning" | "error" = "info"): void {
|
||||||
try {
|
try {
|
||||||
ctx.ui.notify(message, kind);
|
ctx.ui.notify(message, kind);
|
||||||
@@ -1299,6 +1351,8 @@ export function registerPoster(pi: ExtensionAPI, deps: PosterDeps): void {
|
|||||||
} finally {
|
} finally {
|
||||||
// Never leave the footer claiming we are still working.
|
// Never leave the footer claiming we are still working.
|
||||||
status(undefined);
|
status(undefined);
|
||||||
|
// And kill the working spinner regardless of which branch returned.
|
||||||
|
clearWorkingIndicator(ctx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1397,7 +1451,7 @@ async function posterCommand(
|
|||||||
status(S.progress.draft);
|
status(S.progress.draft);
|
||||||
draftArt = await paintArt(deps, job, spec, "draft", {
|
draftArt = await paintArt(deps, job, spec, "draft", {
|
||||||
signal: ctx.signal,
|
signal: ctx.signal,
|
||||||
onProgress: (_m, fraction) => status(withPercent(S.progress.generating, fraction)),
|
onProgress: (message, fraction) => status(withPercent(S.progress.generating, fraction, message)),
|
||||||
onWarning: (w) => notify(ctx, w, "warning"),
|
onWarning: (w) => notify(ctx, w, "warning"),
|
||||||
});
|
});
|
||||||
status(S.progress.typesetting);
|
status(S.progress.typesetting);
|
||||||
@@ -1464,7 +1518,7 @@ async function posterCommand(
|
|||||||
status(S.progress.generating);
|
status(S.progress.generating);
|
||||||
draftArt = await paintArt(deps, job, spec, "draft", {
|
draftArt = await paintArt(deps, job, spec, "draft", {
|
||||||
signal: ctx.signal,
|
signal: ctx.signal,
|
||||||
onProgress: (_m, fraction) => status(withPercent(S.progress.generating, fraction)),
|
onProgress: (message, fraction) => status(withPercent(S.progress.generating, fraction, message)),
|
||||||
onWarning: (w) => notify(ctx, w, "warning"),
|
onWarning: (w) => notify(ctx, w, "warning"),
|
||||||
});
|
});
|
||||||
repainted = true;
|
repainted = true;
|
||||||
@@ -1524,7 +1578,7 @@ async function posterCommand(
|
|||||||
artPath = await paintArt(deps, job, spec, "final", {
|
artPath = await paintArt(deps, job, spec, "final", {
|
||||||
signal: ctx.signal,
|
signal: ctx.signal,
|
||||||
from: draftArt,
|
from: draftArt,
|
||||||
onProgress: (_m, fraction) => status(withPercent(S.progress.finalArt, fraction)),
|
onProgress: (message, fraction) => status(withPercent(S.progress.finalArt, fraction, message)),
|
||||||
onWarning: (w) => warnings.push(w),
|
onWarning: (w) => warnings.push(w),
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1606,8 +1660,17 @@ async function posterCommand(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** "Genero l'immagine… 40%" — the label stays Italian, the number is just a number. */
|
/**
|
||||||
function withPercent(label: string, fraction?: number): string {
|
* "Genero l'immagine… 40%" — the label stays Italian, the number is just a number.
|
||||||
|
*
|
||||||
|
* Takes an optional Italian message from the backend's progress parser — "Decodifica
|
||||||
|
* dell'immagine…", "Salvataggio…", "Caricamento del modello…" — and prefers it to the
|
||||||
|
* generic label when present. The progress parser's words are what the user actually
|
||||||
|
* wants to see during a 90-second diffusion run: a percentage that never moves past 80%
|
||||||
|
* for a minute, with no other context, looks like a hang.
|
||||||
|
*/
|
||||||
|
function withPercent(label: string, fraction: number | undefined, hint?: string): string {
|
||||||
|
if (hint && hint.trim()) return hint;
|
||||||
if (typeof fraction !== "number" || !Number.isFinite(fraction)) return label;
|
if (typeof fraction !== "number" || !Number.isFinite(fraction)) return label;
|
||||||
const pct = Math.max(0, Math.min(100, Math.round(fraction * 100)));
|
const pct = Math.max(0, Math.min(100, Math.round(fraction * 100)));
|
||||||
return `${label} ${pct}%`;
|
return `${label} ${pct}%`;
|
||||||
|
|||||||
@@ -548,6 +548,15 @@ async function socialCommand(
|
|||||||
} finally {
|
} finally {
|
||||||
// Never leave a status line behind, on any path.
|
// Never leave a status line behind, on any path.
|
||||||
ctx.ui.setStatus(STATUS_KEY, undefined);
|
ctx.ui.setStatus(STATUS_KEY, undefined);
|
||||||
|
// And kill the working spinner regardless of which branch returned.
|
||||||
|
const ui = ctx.ui as unknown as {
|
||||||
|
setWorkingVisible?: (b: boolean) => void;
|
||||||
|
setWorkingIndicator?: (kind: string | undefined) => void;
|
||||||
|
setWorkingMessage?: (t: string | undefined) => void;
|
||||||
|
};
|
||||||
|
ui.setWorkingVisible?.(false);
|
||||||
|
ui.setWorkingIndicator?.(undefined);
|
||||||
|
ui.setWorkingMessage?.(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+3872
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
Reference in New Issue
Block a user