fix: SVG export in dark mode with embedded bitmap image (#4285)
Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
620b662085
commit
b6ef953dc9
@ -31,6 +31,12 @@ import { getDefaultAppState } from "../appState";
|
|||||||
import { MAX_DECIMALS_FOR_SVG_EXPORT, MIME_TYPES, SVG_NS } from "../constants";
|
import { MAX_DECIMALS_FOR_SVG_EXPORT, MIME_TYPES, SVG_NS } from "../constants";
|
||||||
import { getStroke, StrokeOptions } from "perfect-freehand";
|
import { getStroke, StrokeOptions } from "perfect-freehand";
|
||||||
|
|
||||||
|
// using a stronger invert (100% vs our regular 93%) and saturate
|
||||||
|
// as a temp hack to make images in dark theme look closer to original
|
||||||
|
// color scheme (it's still not quite there and the colors look slightly
|
||||||
|
// desatured, alas...)
|
||||||
|
const IMAGE_INVERT_FILTER = "invert(100%) hue-rotate(180deg) saturate(1.25)";
|
||||||
|
|
||||||
const defaultAppState = getDefaultAppState();
|
const defaultAppState = getDefaultAppState();
|
||||||
|
|
||||||
const isPendingImageElement = (
|
const isPendingImageElement = (
|
||||||
@ -116,17 +122,14 @@ const generateElementCanvas = (
|
|||||||
|
|
||||||
const rc = rough.canvas(canvas);
|
const rc = rough.canvas(canvas);
|
||||||
|
|
||||||
|
// in dark theme, revert the image color filter
|
||||||
if (
|
if (
|
||||||
sceneState.theme === "dark" &&
|
sceneState.theme === "dark" &&
|
||||||
isInitializedImageElement(element) &&
|
isInitializedImageElement(element) &&
|
||||||
!isPendingImageElement(element, sceneState) &&
|
!isPendingImageElement(element, sceneState) &&
|
||||||
sceneState.imageCache.get(element.fileId)?.mimeType !== MIME_TYPES.svg
|
sceneState.imageCache.get(element.fileId)?.mimeType !== MIME_TYPES.svg
|
||||||
) {
|
) {
|
||||||
// using a stronger invert (100% vs our regular 93%) and saturate
|
context.filter = IMAGE_INVERT_FILTER;
|
||||||
// as a temp hack to make images in dark theme look closer to original
|
|
||||||
// color scheme (it's still not quite there and the clors look slightly
|
|
||||||
// desaturing/black is not as black, but...)
|
|
||||||
context.filter = "invert(100%) hue-rotate(180deg) saturate(1.25)";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawElementOnCanvas(element, rc, context, sceneState);
|
drawElementOnCanvas(element, rc, context, sceneState);
|
||||||
@ -744,6 +747,7 @@ export const renderElementToSvg = (
|
|||||||
files: BinaryFiles,
|
files: BinaryFiles,
|
||||||
offsetX?: number,
|
offsetX?: number,
|
||||||
offsetY?: number,
|
offsetY?: number,
|
||||||
|
exportWithDarkMode?: boolean,
|
||||||
) => {
|
) => {
|
||||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||||
const cx = (x2 - x1) / 2 - (element.x - x1);
|
const cx = (x2 - x1) / 2 - (element.x - x1);
|
||||||
@ -861,6 +865,11 @@ export const renderElementToSvg = (
|
|||||||
const use = svgRoot.ownerDocument!.createElementNS(SVG_NS, "use");
|
const use = svgRoot.ownerDocument!.createElementNS(SVG_NS, "use");
|
||||||
use.setAttribute("href", `#${symbolId}`);
|
use.setAttribute("href", `#${symbolId}`);
|
||||||
|
|
||||||
|
// in dark theme, revert the image color filter
|
||||||
|
if (exportWithDarkMode && fileData.mimeType !== MIME_TYPES.svg) {
|
||||||
|
use.setAttribute("filter", IMAGE_INVERT_FILTER);
|
||||||
|
}
|
||||||
|
|
||||||
use.setAttribute("width", `${Math.round(element.width)}`);
|
use.setAttribute("width", `${Math.round(element.width)}`);
|
||||||
use.setAttribute("height", `${Math.round(element.height)}`);
|
use.setAttribute("height", `${Math.round(element.height)}`);
|
||||||
|
|
||||||
|
@ -802,9 +802,11 @@ export const renderSceneToSvg = (
|
|||||||
{
|
{
|
||||||
offsetX = 0,
|
offsetX = 0,
|
||||||
offsetY = 0,
|
offsetY = 0,
|
||||||
|
exportWithDarkMode = false,
|
||||||
}: {
|
}: {
|
||||||
offsetX?: number;
|
offsetX?: number;
|
||||||
offsetY?: number;
|
offsetY?: number;
|
||||||
|
exportWithDarkMode?: boolean;
|
||||||
} = {},
|
} = {},
|
||||||
) => {
|
) => {
|
||||||
if (!svgRoot) {
|
if (!svgRoot) {
|
||||||
@ -821,6 +823,7 @@ export const renderSceneToSvg = (
|
|||||||
files,
|
files,
|
||||||
element.x + offsetX,
|
element.x + offsetX,
|
||||||
element.y + offsetY,
|
element.y + offsetY,
|
||||||
|
exportWithDarkMode,
|
||||||
);
|
);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
@ -158,6 +158,7 @@ export const exportToSvg = async (
|
|||||||
renderSceneToSvg(elements, rsvg, svgRoot, files || {}, {
|
renderSceneToSvg(elements, rsvg, svgRoot, files || {}, {
|
||||||
offsetX: -minX + exportPadding,
|
offsetX: -minX + exportPadding,
|
||||||
offsetY: -minY + exportPadding,
|
offsetY: -minY + exportPadding,
|
||||||
|
exportWithDarkMode: appState.exportWithDarkMode,
|
||||||
});
|
});
|
||||||
|
|
||||||
return svgRoot;
|
return svgRoot;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user