{"action":"created","issue":{"url":"https://api.github.com/repos/atom/atom/issues/8811","labels_url":"https://api.github.com/repos/atom/atom/issues/8811/labels{/name}","comments_url":"https://api.github.com/repos/atom/atom/issues/8811/comments","events_url":"https://api.github.com/repos/atom/atom/issues/8811/events","html_url":"https://github.com/atom/atom/pull/8811","id":106771471,"number":8811,"title":"DOM-based measurements","user":{"login":"as-cii","id":482957,"avatar_url":"https://avatars.githubusercontent.com/u/482957?v=3","gravatar_id":"","url":"https://api.github.com/users/as-cii","html_url":"https://github.com/as-cii","followers_url":"https://api.github.com/users/as-cii/followers","following_url":"https://api.github.com/users/as-cii/following{/other_user}","gists_url":"https://api.github.com/users/as-cii/gists{/gist_id}","starred_url":"https://api.github.com/users/as-cii/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/as-cii/subscriptions","organizations_url":"https://api.github.com/users/as-cii/orgs","repos_url":"https://api.github.com/users/as-cii/repos","events_url":"https://api.github.com/users/as-cii/events{/privacy}","received_events_url":"https://api.github.com/users/as-cii/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/atom/atom/labels/needs-review","name":"needs-review","color":"bfe5bf"},{"url":"https://api.github.com/repos/atom/atom/labels/needs-testing","name":"needs-testing","color":"bfe5bf"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":12,"created_at":"2015-09-16T13:15:20Z","updated_at":"2015-10-01T20:11:31Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/atom/atom/pulls/8811","html_url":"https://github.com/atom/atom/pull/8811","diff_url":"https://github.com/atom/atom/pull/8811.diff","patch_url":"https://github.com/atom/atom/pull/8811.patch"},"body":"Supersedes and closes #6083.\r\nSupersedes and closes #7945.\r\n\r\n## A Brief Flashback\r\n\r\nOver the past month we have evaluated several strategies to attack the problem, among which:\r\n\r\n#### iframe\r\n\r\nBuild the lines inside an `<iframe>` element and measure from them.\r\n\r\n**Pros**: measurements happen in a separate context, completely decoupled from the current DOM. Some optimization can, therefore, be applied: skinnier DOM, less stylesheet, and so on.\r\n**Cons**: building the lines twice has a cost which is higher than the optimizations we tried out. Moreover, we cannot alter the original DOM structure as, otherwise, measurements could be wrong. \r\n\r\n#### Canvas\r\n\r\nHave a canvas element and use the `measureText` function to provide all the metrics we need to position visual elements.\r\n\r\n**Pros**: measurements happen in a separate context and the overhead is minimal.\r\n**Cons**: CSS typography is not fully supported (e.g. ligatures/contextual alternates get screwed up) and the risk of reporting corrupted measurements is very high.\r\n\r\n#### No Measurements\r\n\r\nInstead of positioning decorations, cursors, etc. with absolute coordinates, embed them inside each line and let the browser figure out all the metrics.\r\n\r\n**Pros**: no need for measurements and more semantical HTML. In addition, this enriches the power of styling customizations (e.g. the user has the possibility to style a piece of text surrounded by a decoration).\r\n**Cons**: worse performance, because the DOM gets more complicated and nesting increases. Overlays need to be displayed on top of lines node, which forces us to employ tricks to let them appear in front of everything. \r\n\r\n## The Present\r\n\r\nIn this PR we have implemented DOM-based measurements. The idea here is to append the real lines to the DOM, measure from them, and render everything else that needs measurements. \r\n\r\nEvery time `TextEditorElement::pixelPositionForScreenPosition` or `TextEditorElement::screenPositionForPixelPosition` is called, we trigger a reflow (a bit like the DOM does when you try to read from it when its information is stale).\r\n\r\nIn `TextEditorPresenter` we update the DOM with all lines we'll need to measure before computing any state, in order to avoid multiple reflows caused by reading from line nodes more than once.\r\n\r\nWhat's missing:\r\n\r\n- [x] Autoscroll when reaching the right end of the editor.\r\n- [x] Implement `screenPositionForPixelPosition` in `LinesYardstick`.\r\n- [x] Fix remaining specs.\r\n- [x] Avoid using `NodeIterator` as it is slow. Cache text nodes and measure those instead.\r\n- [x] Evaluate if caching already computed positions yields some improvements.\r\n- [x] Remove measurement in `TextEditorComponent::readAfterUpdateSync`.\r\n- [ ] Ensure we have no significant regression performance-wise.\r\n- [ ] Investigate why Hasklig behaves oddly.\r\n- [ ] Fix bug where the cursor disappears when moving it left/right.\r\n\r\nFeedback is super welcome and appreciated! Thanks! :bow: \r\n\r\n/cc: @nathansobo @atom/feedback for :eyes: "},"comment":{"url":"https://api.github.com/repos/atom/atom/issues/comments/144834293","html_url":"https://github.com/atom/atom/pull/8811#issuecomment-144834293","issue_url":"https://api.github.com/repos/atom/atom/issues/8811","id":144834293,"user":{"login":"izuzak","id":38924,"avatar_url":"https://avatars.githubusercontent.com/u/38924?v=3","gravatar_id":"","url":"https://api.github.com/users/izuzak","html_url":"https://github.com/izuzak","followers_url":"https://api.github.com/users/izuzak/followers","following_url":"https://api.github.com/users/izuzak/following{/other_user}","gists_url":"https://api.github.com/users/izuzak/gists{/gist_id}","starred_url":"https://api.github.com/users/izuzak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/izuzak/subscriptions","organizations_url":"https://api.github.com/users/izuzak/orgs","repos_url":"https://api.github.com/users/izuzak/repos","events_url":"https://api.github.com/users/izuzak/events{/privacy}","received_events_url":"https://api.github.com/users/izuzak/received_events","type":"User","site_admin":true},"created_at":"2015-10-01T20:11:31Z","updated_at":"2015-10-01T20:11:31Z","body":"> in the meantime you can already try this out as every other issue should be fixed and your super helpful feedback would be truly appreciated, @izuzak.\r\n\r\n:cool: sounds good. Here's one I found on this branch (latest commit) but couldn't reproduce on master:\r\n\r\n![lorem](https://cloud.githubusercontent.com/assets/38924/10232443/198316c4-6889-11e5-8b7c-2f8672c28510.gif)\r\n\r\nNotice how when I trigger soft-wrap -- the width of the window isn't updated and I can still scroll.\r\n"}}