Skip to content

Commit

Permalink
Snap editor line-height to the nearest device pixel…
Browse files Browse the repository at this point in the history
…in order to avoid small gaps or overlaps between lines.

Fixes #1181.
  • Loading branch information
savetheclocktower committed Jan 7, 2025
1 parent 613feb7 commit 3d3c6bc
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
13 changes: 4 additions & 9 deletions src/text-editor-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -2465,17 +2465,12 @@ module.exports = class TextEditorComponent {
}

measureCharacterDimensions() {
let lines = [
'normalWidthCharacterSpan',
'doubleWidthCharacterSpan',
'halfWidthCharacterSpan',
'koreanCharacterSpan'
];
this.measurements.lineHeight = Math.max(
1,
// Each of these characters exists in its own block-level element. Set
// the line height to the tallest of these four characters.
...lines.map(l => this.refs[l].parentNode.getBoundingClientRect().height)
// Each of the four characters below exists inside its own block-level
// element, but each of those containers should have the same height. We
// don't need to check more than one.
this.refs.normalWidthCharacterSpan.parentNode.getBoundingClientRect().height
);
this.measurements.baseCharacterWidth = this.refs.normalWidthCharacterSpan.getBoundingClientRect().width;
this.measurements.doubleWidthCharacterWidth = this.refs.doubleWidthCharacterSpan.getBoundingClientRect().width;
Expand Down
28 changes: 25 additions & 3 deletions src/workspace-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,32 @@ class WorkspaceElement extends HTMLElement {
}

updateGlobalTextEditorStyleSheet() {
// We multiply `editor.fontSize` by `editor.lineHeight` to determine how
// tall our lines will be. We could just pass `editor.lineHeight` into the
// CSS as a factor and let CSS do the math, but Chromium tends to make a
// mess of it, with the result being occasional tiny gaps between lines.
// (See https://github.com/pulsar-edit/pulsar/issues/1181.)
//
// The best way around this seems to be to compute the line height
// ourselves while rounding to the nearest device pixel, then specifying
// the editor `line-height` in CSS pixels instead of a bare number.
let fontSize = this.config.get('editor.fontSize');
let fontFamily = this.config.get('editor.fontFamily');
let lineHeight = this.config.get('editor.lineHeight');
let pixelRatio = window.devicePixelRatio;

// Most screens out there these days have a `devicePixelRatio` of `2`,
// meaning that `1px` in CSS will use two screen pixels. So this would have
// the effect of snapping the line height to the nearest half-CSS-pixel.
//
// On older displays with lower DPI, this will theoretically do the right
// thing and snap to the nearest whole pixel.
let computedLineHeight = Math.round(fontSize * lineHeight * pixelRatio) / pixelRatio;

const styleSheetSource = `atom-workspace {
--editor-font-size: ${this.config.get('editor.fontSize')}px;
--editor-font-family: ${this.config.get('editor.fontFamily')};
--editor-line-height: ${this.config.get('editor.lineHeight')};
--editor-font-size: ${fontSize}px;
--editor-font-family: ${fontFamily};
--editor-line-height: ${computedLineHeight.toFixed(6)}px;
}`;
this.styleManager.addStyleSheet(styleSheetSource, {
sourcePath: 'global-text-editor-styles',
Expand Down

0 comments on commit 3d3c6bc

Please sign in to comment.