Browse Source

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

Co-authored-by: dwelle <luzar.david@gmail.com>
zsviczian 3 years ago
parent
commit
b6ef953dc9
3 changed files with 18 additions and 5 deletions
  1. 14 5
      src/renderer/renderElement.ts
  2. 3 0
      src/renderer/renderScene.ts
  3. 1 0
      src/scene/export.ts

+ 14 - 5
src/renderer/renderElement.ts

@@ -31,6 +31,12 @@ import { getDefaultAppState } from "../appState";
 import { MAX_DECIMALS_FOR_SVG_EXPORT, MIME_TYPES, SVG_NS } from "../constants";
 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 isPendingImageElement = (
@@ -116,17 +122,14 @@ const generateElementCanvas = (
 
   const rc = rough.canvas(canvas);
 
+  // in dark theme, revert the image color filter
   if (
     sceneState.theme === "dark" &&
     isInitializedImageElement(element) &&
     !isPendingImageElement(element, sceneState) &&
     sceneState.imageCache.get(element.fileId)?.mimeType !== MIME_TYPES.svg
   ) {
-    // 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 clors look slightly
-    // desaturing/black is not as black, but...)
-    context.filter = "invert(100%) hue-rotate(180deg) saturate(1.25)";
+    context.filter = IMAGE_INVERT_FILTER;
   }
 
   drawElementOnCanvas(element, rc, context, sceneState);
@@ -744,6 +747,7 @@ export const renderElementToSvg = (
   files: BinaryFiles,
   offsetX?: number,
   offsetY?: number,
+  exportWithDarkMode?: boolean,
 ) => {
   const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
   const cx = (x2 - x1) / 2 - (element.x - x1);
@@ -861,6 +865,11 @@ export const renderElementToSvg = (
         const use = svgRoot.ownerDocument!.createElementNS(SVG_NS, "use");
         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("height", `${Math.round(element.height)}`);
 

+ 3 - 0
src/renderer/renderScene.ts

@@ -802,9 +802,11 @@ export const renderSceneToSvg = (
   {
     offsetX = 0,
     offsetY = 0,
+    exportWithDarkMode = false,
   }: {
     offsetX?: number;
     offsetY?: number;
+    exportWithDarkMode?: boolean;
   } = {},
 ) => {
   if (!svgRoot) {
@@ -821,6 +823,7 @@ export const renderSceneToSvg = (
           files,
           element.x + offsetX,
           element.y + offsetY,
+          exportWithDarkMode,
         );
       } catch (error: any) {
         console.error(error);

+ 1 - 0
src/scene/export.ts

@@ -158,6 +158,7 @@ export const exportToSvg = async (
   renderSceneToSvg(elements, rsvg, svgRoot, files || {}, {
     offsetX: -minX + exportPadding,
     offsetY: -minY + exportPadding,
+    exportWithDarkMode: appState.exportWithDarkMode,
   });
 
   return svgRoot;