浏览代码

feat: disable canvas smoothing (antialiasing) for right-angled elements (#6186)Co-authored-by: Ignacio Cuadra <67276174+ignacio-cuadra@users.noreply.github.com>

* feat: disable canvas smoothing for text and other types

* disable smoothing for all right-angled elements

* Update src/renderer/renderElement.ts

Co-authored-by: Ignacio Cuadra <67276174+ignacio-cuadra@users.noreply.github.com>

* Update src/renderer/renderElement.ts

Co-authored-by: Ignacio Cuadra <67276174+ignacio-cuadra@users.noreply.github.com>

* fix lint

* always enable smoothing while zooming

---------

Co-authored-by: Ignacio Cuadra <67276174+ignacio-cuadra@users.noreply.github.com>
David Luzar 2 年之前
父节点
当前提交
4414069617
共有 2 个文件被更改,包括 39 次插入1 次删除
  1. 12 0
      src/math.ts
  2. 27 1
      src/renderer/renderElement.ts

+ 12 - 0
src/math.ts

@@ -459,3 +459,15 @@ export const mapIntervalToBezierT = (
 export const arePointsEqual = (p1: Point, p2: Point) => {
   return p1[0] === p2[0] && p1[1] === p2[1];
 };
+
+export const isRightAngle = (angle: number) => {
+  // if our angles were mathematically accurate, we could just check
+  //
+  //    angle % (Math.PI / 2) === 0
+  //
+  // but since we're in floating point land, we need to round.
+  //
+  // Below, after dividing by Math.PI, a multiple of 0.5 indicates a right
+  // angle, which we can check with modulo after rounding.
+  return Math.round((angle / Math.PI) * 10000) % 5000 === 0;
+};

+ 27 - 1
src/renderer/renderElement.ts

@@ -27,7 +27,7 @@ import { RoughGenerator } from "roughjs/bin/generator";
 
 import { RenderConfig } from "../scene/types";
 import { distance, getFontString, getFontFamilyString, isRTL } from "../utils";
-import { getCornerRadius, isPathALoop } from "../math";
+import { getCornerRadius, isPathALoop, isRightAngle } from "../math";
 import rough from "roughjs/bin/rough";
 import { AppState, BinaryFiles, Zoom } from "../types";
 import { getDefaultAppState } from "../appState";
@@ -989,7 +989,33 @@ export const renderElement = (
           element,
           renderConfig,
         );
+
+        const currentImageSmoothingStatus = context.imageSmoothingEnabled;
+
+        if (
+          // do not disable smoothing during zoom as blurry shapes look better
+          // on low resolution (while still zooming in) than sharp ones
+          !renderConfig?.shouldCacheIgnoreZoom &&
+          // angle is 0 -> always disable smoothing
+          (!element.angle ||
+            // or check if angle is a right angle in which case we can still
+            // disable smoothing without adversely affecting the result
+            isRightAngle(element.angle))
+        ) {
+          // Disabling smoothing makes output much sharper, especially for
+          // text. Unless for non-right angles, where the aliasing is really
+          // terrible on Chromium.
+          //
+          // Note that `context.imageSmoothingQuality="high"` has almost
+          // zero effect.
+          //
+          context.imageSmoothingEnabled = false;
+        }
+
         drawElementFromCanvas(elementWithCanvas, rc, context, renderConfig);
+
+        // reset
+        context.imageSmoothingEnabled = currentImageSmoothingStatus;
       }
       break;
     }