fix: SVG export in dark mode with embedded bitmap image (#4285)

Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
zsviczian 2021-11-20 15:31:51 +01:00 committed by GitHub
parent 620b662085
commit b6ef953dc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 18 additions and 5 deletions

View File

@ -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)}`);

View File

@ -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);

View File

@ -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;