{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/comments/36777165","id":36777165,"diff_hunk":"@@ -357,20 +479,19 @@ var currentlyFocusedTextEditor;\n         this.baseline = size | 0;\n         this.height = (size * 1.3) | 0;\n \n-        this.context = document.createElement(\"canvas\").getContext(\"2d\");\n-        this.context.canvas.width = 0;\n-        this.context.canvas.height = 0;\n-        this.context.font = style + size + \"px \" + face;\n         this.size = size;\n+        // XXX Figure out why this works when these two fields are both int.\n         this.style = style;\n         this.face = face;\n     };\n \n-    function calcStringWidth(font, str) {\n+    function calcStringWidth(font, str, scaleByDPR) {\n         var emojiLen = 0;\n+        var fontSize = font.size * (scaleByDPR ? DPR : 1);\n \n-        var len = font.context.measureText(str.replace(emoji.regEx, function() {\n-            emojiLen += font.size;\n+        tempContext.font = font.style + \" \" + fontSize + \"px \" + font.face;\n+        var len = tempContext.measureText(str.replace(emoji.regEx, function() {\n+            emojiLen += fontSize;","path":"midp/gfx.js","position":null,"original_position":282,"commit_id":"291516a9784c5c906a2fb9d8ca088435d1398073","original_commit_id":"d40d63f82ee4139c6d6d4f3469145cb1cbf8e81e","user":{"login":"mykmelez","id":305455,"avatar_url":"https://avatars.githubusercontent.com/u/305455?v=3","gravatar_id":"","url":"https://api.github.com/users/mykmelez","html_url":"https://github.com/mykmelez","followers_url":"https://api.github.com/users/mykmelez/followers","following_url":"https://api.github.com/users/mykmelez/following{/other_user}","gists_url":"https://api.github.com/users/mykmelez/gists{/gist_id}","starred_url":"https://api.github.com/users/mykmelez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mykmelez/subscriptions","organizations_url":"https://api.github.com/users/mykmelez/orgs","repos_url":"https://api.github.com/users/mykmelez/repos","events_url":"https://api.github.com/users/mykmelez/events{/privacy}","received_events_url":"https://api.github.com/users/mykmelez/received_events","type":"User","site_admin":false},"body":"> I didn't notice one, but I just ran GraphicsBench, and it reports that \"Graphics.drawString baseline centered\" and \"Offscreen Graphics.drawString baseline centered\" are roughly half as fast on this branch, regardless of DPR. So this branch does indeed regress string drawing perf. I'll look into it.\r\n\r\n291516a claws back most of the perf hit. It creates two contexts for measuring string widths, one for measuring unscaled widths and the other for measuring scaled widths (with an optimization to create only a single context if DPR == 1).\r\n\r\nOn my machine, the Graphics.drawString benchmarks perform 42-43K ops per second on master. On this branch, they now hit 34-35K. I think the rest is the necessary cost of drawing larger strings to a larger canvas when DPR == 2 (as it is on my machine).\r\n\r\nNote that the other graphics benchmark, Graphics.drawRegion, also performs worse on this branch. That's expected since scaling the canvas means drawing more pixels, up to four times more when DPR == 2.\r\n\r\nRegarding the use of two contexts to measure the scaled vs. unscaled widths of strings, I did some experimentation to confirm my earlier findings that merely multiplying an unscaled width by the DPR didn't give me an accurate scaled width.\r\n\r\nHere are some measurements for \"The quick brown fox jumps over the lazy dog.\" in two font styles (regular and \"bold\") at both 9px and 18px (per a theoretical DPR of 2). I calculate the result of simply multiplying the width at 9px by the theoretical DPR, and I also calculate what the return value of calcStringWidth would be using the current integer conversion mechanism (bitwise or) and a prospective alternative (Math.round).\r\n\r\n9px sans-serif:\r\n* 180.23333740234375\r\n* 180.23333740234375 * 2 = 360.4666748046875\r\n* 180.23333740234375 * 2 | 0 = 360\r\n* Math.round(180.23333740234375) = 360\r\n\r\n18px sans-serif:\r\n* 360.73333740234375\r\n* 360.73333740234375 | 0 = 360\r\n* Math.round(360.73333740234375) = 361\r\n\r\nbold 9px sans-serif:\r\n* 194.43333435058594\r\n* 194.43333435058594 * 2 = 388.8666687011719\r\n* 194.43333435058594 * 2 | 0 = 388\r\n* Math.round(194.43333435058594 * 2) = 389\r\n\r\nbold 18px sans-serif:\r\n* 389.4333190917969\r\n* 389.4333190917969 | 0 = 389\r\n* Math.round(389.4333190917969 | 0) = 389\r\n\r\nMultiplying the unscaled widths by 2 gets close, but it can be a pixel off, regardless of the integer conversion. Perhaps that's ok, and we should simplify the scaled measurement. Unsure.\r\n","created_at":"2015-08-11T18:03:32Z","updated_at":"2015-08-11T18:03:32Z","html_url":"https://github.com/mozilla/pluotsorbet/pull/1778#discussion_r36777165","pull_request_url":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778","_links":{"self":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/comments/36777165"},"html":{"href":"https://github.com/mozilla/pluotsorbet/pull/1778#discussion_r36777165"},"pull_request":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778","id":41630597,"html_url":"https://github.com/mozilla/pluotsorbet/pull/1778","diff_url":"https://github.com/mozilla/pluotsorbet/pull/1778.diff","patch_url":"https://github.com/mozilla/pluotsorbet/pull/1778.patch","issue_url":"https://api.github.com/repos/mozilla/pluotsorbet/issues/1778","number":1778,"state":"open","locked":false,"title":"scale display canvas by device pixel ratio to support HiDPI displays","user":{"login":"mykmelez","id":305455,"avatar_url":"https://avatars.githubusercontent.com/u/305455?v=3","gravatar_id":"","url":"https://api.github.com/users/mykmelez","html_url":"https://github.com/mykmelez","followers_url":"https://api.github.com/users/mykmelez/followers","following_url":"https://api.github.com/users/mykmelez/following{/other_user}","gists_url":"https://api.github.com/users/mykmelez/gists{/gist_id}","starred_url":"https://api.github.com/users/mykmelez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mykmelez/subscriptions","organizations_url":"https://api.github.com/users/mykmelez/orgs","repos_url":"https://api.github.com/users/mykmelez/repos","events_url":"https://api.github.com/users/mykmelez/events{/privacy}","received_events_url":"https://api.github.com/users/mykmelez/received_events","type":"User","site_admin":false},"body":"@TimAbraldes, @marco-c: This is the non-WIP squashed version of #1768. It scales the display by the device pixel ratio to support HiDPI displays.\r\n\r\nIt still isn't perfect, as it can't magically make images from image files be higher resolution than they actually are. It can also be defeated by midlets like WhatsApp that call ImageData.getRGB to retrieve pixel data from an image, manipulate it, and then call Graphics.drawRGB to write the manipulated pixel data back to the image.\r\n\r\nBut it sharpens other graphics on HiDPI displays, including generated graphics and text. In a separate pull request, I'll work on a hack that sharpens text in midlets like WhatsApp.\r\n","created_at":"2015-08-04T23:50:22Z","updated_at":"2015-08-11T18:03:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ecb756571e64b1e2b216a80480ab620f233ee0de","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778/commits","review_comments_url":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778/comments","review_comment_url":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/pluotsorbet/issues/1778/comments","statuses_url":"https://api.github.com/repos/mozilla/pluotsorbet/statuses/291516a9784c5c906a2fb9d8ca088435d1398073","head":{"label":"mykmelez:fuzzy-wuzzy-was-a-bear","ref":"fuzzy-wuzzy-was-a-bear","sha":"291516a9784c5c906a2fb9d8ca088435d1398073","user":{"login":"mykmelez","id":305455,"avatar_url":"https://avatars.githubusercontent.com/u/305455?v=3","gravatar_id":"","url":"https://api.github.com/users/mykmelez","html_url":"https://github.com/mykmelez","followers_url":"https://api.github.com/users/mykmelez/followers","following_url":"https://api.github.com/users/mykmelez/following{/other_user}","gists_url":"https://api.github.com/users/mykmelez/gists{/gist_id}","starred_url":"https://api.github.com/users/mykmelez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mykmelez/subscriptions","organizations_url":"https://api.github.com/users/mykmelez/orgs","repos_url":"https://api.github.com/users/mykmelez/repos","events_url":"https://api.github.com/users/mykmelez/events{/privacy}","received_events_url":"https://api.github.com/users/mykmelez/received_events","type":"User","site_admin":false},"repo":{"id":22497156,"name":"pluotsorbet","full_name":"mykmelez/pluotsorbet","owner":{"login":"mykmelez","id":305455,"avatar_url":"https://avatars.githubusercontent.com/u/305455?v=3","gravatar_id":"","url":"https://api.github.com/users/mykmelez","html_url":"https://github.com/mykmelez","followers_url":"https://api.github.com/users/mykmelez/followers","following_url":"https://api.github.com/users/mykmelez/following{/other_user}","gists_url":"https://api.github.com/users/mykmelez/gists{/gist_id}","starred_url":"https://api.github.com/users/mykmelez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mykmelez/subscriptions","organizations_url":"https://api.github.com/users/mykmelez/orgs","repos_url":"https://api.github.com/users/mykmelez/repos","events_url":"https://api.github.com/users/mykmelez/events{/privacy}","received_events_url":"https://api.github.com/users/mykmelez/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mykmelez/pluotsorbet","description":"J2ME VM in JavaScript","fork":true,"url":"https://api.github.com/repos/mykmelez/pluotsorbet","forks_url":"https://api.github.com/repos/mykmelez/pluotsorbet/forks","keys_url":"https://api.github.com/repos/mykmelez/pluotsorbet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mykmelez/pluotsorbet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mykmelez/pluotsorbet/teams","hooks_url":"https://api.github.com/repos/mykmelez/pluotsorbet/hooks","issue_events_url":"https://api.github.com/repos/mykmelez/pluotsorbet/issues/events{/number}","events_url":"https://api.github.com/repos/mykmelez/pluotsorbet/events","assignees_url":"https://api.github.com/repos/mykmelez/pluotsorbet/assignees{/user}","branches_url":"https://api.github.com/repos/mykmelez/pluotsorbet/branches{/branch}","tags_url":"https://api.github.com/repos/mykmelez/pluotsorbet/tags","blobs_url":"https://api.github.com/repos/mykmelez/pluotsorbet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mykmelez/pluotsorbet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mykmelez/pluotsorbet/git/refs{/sha}","trees_url":"https://api.github.com/repos/mykmelez/pluotsorbet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mykmelez/pluotsorbet/statuses/{sha}","languages_url":"https://api.github.com/repos/mykmelez/pluotsorbet/languages","stargazers_url":"https://api.github.com/repos/mykmelez/pluotsorbet/stargazers","contributors_url":"https://api.github.com/repos/mykmelez/pluotsorbet/contributors","subscribers_url":"https://api.github.com/repos/mykmelez/pluotsorbet/subscribers","subscription_url":"https://api.github.com/repos/mykmelez/pluotsorbet/subscription","commits_url":"https://api.github.com/repos/mykmelez/pluotsorbet/commits{/sha}","git_commits_url":"https://api.github.com/repos/mykmelez/pluotsorbet/git/commits{/sha}","comments_url":"https://api.github.com/repos/mykmelez/pluotsorbet/comments{/number}","issue_comment_url":"https://api.github.com/repos/mykmelez/pluotsorbet/issues/comments{/number}","contents_url":"https://api.github.com/repos/mykmelez/pluotsorbet/contents/{+path}","compare_url":"https://api.github.com/repos/mykmelez/pluotsorbet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mykmelez/pluotsorbet/merges","archive_url":"https://api.github.com/repos/mykmelez/pluotsorbet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mykmelez/pluotsorbet/downloads","issues_url":"https://api.github.com/repos/mykmelez/pluotsorbet/issues{/number}","pulls_url":"https://api.github.com/repos/mykmelez/pluotsorbet/pulls{/number}","milestones_url":"https://api.github.com/repos/mykmelez/pluotsorbet/milestones{/number}","notifications_url":"https://api.github.com/repos/mykmelez/pluotsorbet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mykmelez/pluotsorbet/labels{/name}","releases_url":"https://api.github.com/repos/mykmelez/pluotsorbet/releases{/id}","created_at":"2014-08-01T06:02:22Z","updated_at":"2015-06-17T06:46:07Z","pushed_at":"2015-08-11T17:44:24Z","git_url":"git://github.com/mykmelez/pluotsorbet.git","ssh_url":"git@github.com:mykmelez/pluotsorbet.git","clone_url":"https://github.com/mykmelez/pluotsorbet.git","svn_url":"https://github.com/mykmelez/pluotsorbet","homepage":null,"size":33794,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mozilla:master","ref":"master","sha":"fa30f76a61a08542b2881fae99668b3834da4a26","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":21724513,"name":"pluotsorbet","full_name":"mozilla/pluotsorbet","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/pluotsorbet","description":"PluotSorbet is a J2ME-compatible virtual machine written in JavaScript.","fork":false,"url":"https://api.github.com/repos/mozilla/pluotsorbet","forks_url":"https://api.github.com/repos/mozilla/pluotsorbet/forks","keys_url":"https://api.github.com/repos/mozilla/pluotsorbet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/pluotsorbet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/pluotsorbet/teams","hooks_url":"https://api.github.com/repos/mozilla/pluotsorbet/hooks","issue_events_url":"https://api.github.com/repos/mozilla/pluotsorbet/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/pluotsorbet/events","assignees_url":"https://api.github.com/repos/mozilla/pluotsorbet/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/pluotsorbet/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/pluotsorbet/tags","blobs_url":"https://api.github.com/repos/mozilla/pluotsorbet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/pluotsorbet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/pluotsorbet/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/pluotsorbet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/pluotsorbet/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/pluotsorbet/languages","stargazers_url":"https://api.github.com/repos/mozilla/pluotsorbet/stargazers","contributors_url":"https://api.github.com/repos/mozilla/pluotsorbet/contributors","subscribers_url":"https://api.github.com/repos/mozilla/pluotsorbet/subscribers","subscription_url":"https://api.github.com/repos/mozilla/pluotsorbet/subscription","commits_url":"https://api.github.com/repos/mozilla/pluotsorbet/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/pluotsorbet/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/pluotsorbet/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/pluotsorbet/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/pluotsorbet/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/pluotsorbet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/pluotsorbet/merges","archive_url":"https://api.github.com/repos/mozilla/pluotsorbet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/pluotsorbet/downloads","issues_url":"https://api.github.com/repos/mozilla/pluotsorbet/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/pluotsorbet/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/pluotsorbet/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/pluotsorbet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/pluotsorbet/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/pluotsorbet/releases{/id}","created_at":"2014-07-11T06:23:27Z","updated_at":"2015-08-08T00:42:39Z","pushed_at":"2015-08-11T17:44:24Z","git_url":"git://github.com/mozilla/pluotsorbet.git","ssh_url":"git@github.com:mozilla/pluotsorbet.git","clone_url":"https://github.com/mozilla/pluotsorbet.git","svn_url":"https://github.com/mozilla/pluotsorbet","homepage":"","size":38712,"stargazers_count":169,"watchers_count":169,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"open_issues_count":281,"forks":34,"open_issues":281,"watchers":169,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778"},"html":{"href":"https://github.com/mozilla/pluotsorbet/pull/1778"},"issue":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/issues/1778"},"comments":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/issues/1778/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/pulls/1778/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/pluotsorbet/statuses/291516a9784c5c906a2fb9d8ca088435d1398073"}}}}