Make the ends of vline/hline sharper (#5676)

TL;DR: line caps are annoying in two ways:

A) we only add them for lines wider than a pixel
B) they always make the line longer (if added)
This commit is contained in:
Emil Ernerfeldt 2025-02-04 15:31:51 +01:00 committed by GitHub
parent c90b97f4ef
commit c6bda9a38c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 135 additions and 97 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4aeab31841dd95b5e0f4bd0af0c0ba49a862d50836dbafdf2172fbbab950c105
size 327741
oid sha256:2c15a74a1b1ed3b52a53966a3df2901ca520b92fbfbd10503e32ddb8431e1467
size 335399

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7bcf6e2977bed682d7bdaa0b6a6786e528662dd0791d2e6f83cf1b4852035838
size 182833
oid sha256:d8f1046ee5d50d73a17009fd1f11f056b5828fedc62908d00730a6aa77125473
size 182900

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:23f19871720b67659a7b56cee8a78edc941c4bac86f55efc6fa549f10c4712fb
size 31754
oid sha256:73b24bec3383450b627683370467b68f0195bd43ce205a44dd49b60cca187b1b
size 31773

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e4d8fee9fd8e69ecd60ebd0dd41c29b61cc13e7013b1d20ad93d40fc4ed1cc03
size 27091
oid sha256:062b6e6b6bd7167df24545308afbc3e38ce328fff0b76ca9921180010766f827
size 27153

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b291e7efd895ab095590285b841903f05dc7d4dadbab7d9001b04a92953c1694
size 81677
oid sha256:d6287aa1fd30baee49bd5fdf3fb307f49c2ecdcb5e6a83c309ec4c051d7506a4
size 81718

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5d75230689807ae7fb692bac5c9b33ee04c02b9e54963e2d6ada05860157daf6
size 11705
oid sha256:5dfdfe8ed7edf0074b9a4f4dd0f9c27f4c9d7411398c6dba590f032a342ad0e4
size 11716

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f512159108c7681834ae2a52c5e1d4eb4dbe678a509f3dab3384e35d6c8dbee2
size 25865
oid sha256:16fdf761b370962678b938735d41221b70658d5b003794c71f73327bfd7d2017
size 25907

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f2a4f5e67ff6615877794304e8be5a5db647d48e20e4248259179cddefbf4088
size 20806
oid sha256:f789cc43f83f01b014b07e93e33ed85ecc0ef323fec404f602ca44ba6fc0ce9e
size 20819

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0bc474a37d6d3a7a08dd41963bf9009c05315de91bb515cc2b19443b79480bff
size 10723
oid sha256:baca02791fa90a063dff7f365ce7a0a748f7b892a920cddebd9d2593a8231786
size 10769

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0bff769b3f9e46c5e38170885b2c8301294cbcc1c8ee22c17672205edd509924
size 133170
oid sha256:23ddfd103996b7a6d71ada175b714a3d1813ef6f521fea307b5d9cb2908cb638
size 133212

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:244d539111e994a4ed2aa95a2b4d0ff12b948e21843c8a1dddcf54cbb388f1aa
size 24280
oid sha256:0be2bf06ea69579fe72d03abd0c5cc17fefcac4f403f5e6c6343b8b275080f29
size 24324

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fdbdf1159f0ab4579bf9ceefbd8e40ac7af468368ab11ffec8578214b57d867c
size 17758
oid sha256:094db03eeea90a1e901c581b19c6ab733f50a396eb9927d82dd558c719404524
size 17805

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ce647fd9626f126e7f19b4494bb98a2086071f9c45f7dd6ba4708632e7433a7b
size 22418
oid sha256:234ae929c7f8b3f623b7e09690f8069d98ba72052c08fc58c85fd9a3dfee04a1
size 22430

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a843e6772809a1c904968fac19b49973675e726a3b7727ca1b898ad3b9072b0c
size 64257
oid sha256:e8251378ba4c74fd29a6aff82517ec6b4c322c5589f85398c6d5e757986a3d83
size 64300

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b437f27c46ddf82e4268d9bb86d33f43c382d1ab3ed45297bc136600cdc9960c
size 32493
oid sha256:8679ac7ec6e90cfe9164b66a02ce3c9db403df0f20f45211c73b1d9a950d2718
size 32522

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2cd0bda8b4d3d7f833273097c8bb52cfd8ea63a405d6798b9aeb7002b143ac74
size 36459
oid sha256:05987e9dfd291b0db57d7611c1feb6742198c14546b779975366643d64ef9ea5
size 36539

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a57c3bf373a283b79188080e2ddf7407c2974655fc5ad59222442e14faae055c
size 17508
oid sha256:1107f4ab1411e054ecefe19e0de6a7276ec2ab81c2c9221056860a3d62263ebf
size 17596

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:161b5853f528206f2531587753369f2f6f3c52203af668eba0d81a41c2a915e0
size 264432
oid sha256:8ca983bab555739e9a2eefb518a8009e1de9638c70efb50edb407cc26973d1eb
size 264478

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:118413a5ec56c6589914c5cb59bda2884a4d6acec3b34bbc367bc893c3de8127
size 35409
oid sha256:0728689de055812e85ccb15e5f4175dd7f9096e610d4ac04256367afa4e036a5
size 35477

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:361791f30739f841c46433f5d16d281ba9d0c52027b4cf156c3ac293aa795f46
size 23592
oid sha256:ffc6e6011ab774613f1a937dace27129bf9c5e5ee10a3a3cfa4973d82b8e5429
size 23604

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:81338d7b0412989590bc0808419d93788e972e7ab6f70f481f86bd23263a5395
size 183821
oid sha256:d84c161d7fd0b1d5670b79e360d6737a3c004998c94835592180a12c055959de
size 183870

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:41c51350c09360738ca284b05c944a11164e4a614beb95ce4cc962222af33d87
size 117764
oid sha256:32a9eba39d88023484abf29ab0bd7a29bfc2ba6b1f7ca42496f87a854616f424
size 117783

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:794475478cfe2fc954731742165b1f0419a0e64616e72b3766c1e031dbba7ca1
size 26092
oid sha256:e91609711f26a067de0e9bfd5f6f1680339e8137ab1a8325290ce399857d2797
size 26135

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7073aa30f3e7dfd116d9a4f02f6c5a075ce068d2e6f43eaede3c4dd6c56f925e
size 70439
oid sha256:b5171572d2bfee9f44cb8fc6aeba2ff3035823035d27ec42480e4bd49e6f5e63
size 70524

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4bb3cd05f253c0e109b83a0556b975af7a96d57678e57de3b9fa130cc8a8de1c
size 66318
oid sha256:f7b21826be83c1a16b9fa7b19130f40261a9735c3eb450eaf9f8d5a3bbfccb7a
size 66365

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5b550769d5ec5d834f89fba56375d10e5f9b3ba703599d90a5b6607aff1c2b06
size 21194
oid sha256:7f7986da3f4a3b94e701bf94066896aedb41458f12f6cdaf93a4fd371b1705da
size 21206

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:45f343b55be98976de32bd3c5438212a46b787123ea3096cf8fc6bec99493184
size 59699
oid sha256:8fb28c16dc2e4359ada002a5fb98e955db606f44db4bdd1a400ab2e4c43c850e
size 59701

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8d25f774320ca844fa4dfba5215ed66f067d0f30c6d7c8ad7ec29d97ee7732e0
size 13073
oid sha256:2a8a3e5953a5ee41d95f2a23b580bb9c82e869b7bad0f2611ed866c55bc12b07
size 13102

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:540a05c5b1de7e362bcb48a04611323fbc65c8787b8ae852ada8aa145803753d
size 34968
oid sha256:12fdbe6805dbce0d993236f30ac14d9c03411b6918399ec5bfa7aa39104d0640
size 35182

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2276b8221389da4f644cad43ce446cd7d28f41820cea36fa3ea860808710053d
size 47878
oid sha256:3d270118b982413bd0c05e9f20a3ee53b88a1681e273f73a81d1733b05c7a006
size 47889

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:054d606681e08bf61762e5c7d7596c4f483e66ac889795e4be4956103328e0bb
size 47862
oid sha256:9f4ad4ac06f2113533943fc00ed9747c237c9b7b6f0890ccf9857e606290c7ec
size 47871

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f7fb29285e53b619f333757052d05f86d973680ac1ce6d1b25d28b7824bbce51
size 43725
oid sha256:5fee7a7f4ebcda3fd55d1d31e21b46246c4d5f166fb1f0de04265e7db424d9c8
size 43733

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:be50a396838d4fe29bcfd0807377ad0cda538fea8569acf709da0b13505bf09b
size 43871
oid sha256:510a3b5d8b10013eed234977bf46575a39cc951611a073154652ce6bf2bc3ecc
size 43880

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c03f90098fb2b2ff846586cc608126580050303b48e7c918b135efcdc6d52686
size 554947
oid sha256:03ee62427611101758958adf2650a4a0eea4e023f07c9ec4ebc63425233e8a04
size 554949

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6ee96b64140d91e1b98cbf5dfef9ac5654050c48b3f9d36889f83a62c9ec985a
size 788322
oid sha256:82ef265f0e22649c7fcdb9556879c1a30df582bd4e97c647258b3e5acc03d112
size 771298

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c82611e7b3ec5c7b82e552421aeef6ad5562d649339708ab6283e0c5af3589c6
size 939339
oid sha256:cad71b486a479eb9c5339a93f4acc3df2d0b6b188ad023b9b044be7311b0ab72
size 918775

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3b315e64464b060c4ef2b508bcb223663e0560871b82c9513fe232f92bd33609
size 1041890
oid sha256:dc9ed4d29f4227b9d38b477ee8f546ea8597acda56a6909ba4826891ebdbea01
size 1039263

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1dc4d7c51eb301ab3e0679b0247c96997ffa30b763c7b203a91fff706264d929
size 1134943
oid sha256:e9bf826bee811d8af345ec1281266fc9bef6d7c3782279516984a6c75130a929
size 1130895

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:92c0615b09916c9a70fc898fbbde2921363044a3bcfcf82410e1d3f6e466bb8a
size 1311678
oid sha256:9345de28f09e2891fd01db20bb0b94176ec3c89d8c2f344a6640d33e97ab5400
size 1311417

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:70fd682bf6ba07b235cf2db643e9d050522aeb3e6ef28426c2b3d23c09920d22
size 46196
oid sha256:5524138c3cb98aa71ef67083ad2d01813ab2394f93f9a7897f2e465ef5a1d0bc
size 46270

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:daa5ec4ddd2f983c4b9f2b0a73c973f58abcb186fbd0d68a9fd0ce7173e5d4e7
size 88031
oid sha256:bdf06c41b69eef1eadc8b46020e6e2a7b985a54e1cf75646ca47caaaea525b95
size 88092

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c09af9c7f4297e2d5b2305366ed57b3203807ca2426314acdf836e25f154d8eb
size 120244
oid sha256:c5ca9c97cef8242ee6ff73d571479be12a8d4e9b3508b3eb6cdf93abda62f4e6
size 120314

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f621bcf7c8fd18156bef2428ab3b9994e6a4d475ae589eb734d50f9a4f3383bd
size 52101
oid sha256:f0481c97c34693b32575d96b1d4bc1238cbb0eb75a934661072f1b52ffee71cf
size 52171

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f1476e105a3e9c1ff7b2f4a82481462795e4708e3fcf6d495a042faae537184e
size 55298
oid sha256:883fdf81e51bfe6333ddcad7998458db251f9cf513c9433179061d7d086eebe0
size 55367

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:695a731d9e302db2c5b7f4a0ef44794cf55eb0be093c070b8ffaeb28121569bc
size 55888
oid sha256:4294949669042e009ac6825ea599dc96e33cdde25e21174b01e3ef108ad478d5
size 55944

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:854c12c69b31c0c82a9596d167772e00d7a051600e4151535e2cec04491e57a6
size 37139
oid sha256:39e5d196ddcaa213b30b0655fe29881a1551c3036c2262f84af8960f66365300
size 37207

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1aacb27847c2e942d56d60e4b72797d93f7265a6effe4e47437e1314e6477e6f
size 37184
oid sha256:f9cf9d7f1921bfc0d61a2ae31e69a98d28280e4699823de5e732cdb102aee5ac
size 37253

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7008bdb595a19782c4f724bed363e51bd93121f5211186aa0e8014c8ba1007c2
size 3005
oid sha256:b5aa7db1bb52481607069ee4a81209ece81b0c70801969b33bc2d1b2f7087de7
size 2911

View File

@ -1002,7 +1002,11 @@ fn stroke_and_fill_path(
let color_outer = Color32::TRANSPARENT;
let color_middle = &stroke.color;
let thin_line = stroke.width <= feathering;
// We add a bit of an epsilon here, because when we round to pixels,
// we can get rounding errors (unless pixels_per_point is an integer).
// And it's better to err on the side of the nicer rendering with line caps
// (the thin-line optimization has no line caps).
let thin_line = stroke.width <= 0.9 * feathering;
if thin_line {
// If the stroke is painted smaller than the pixel width (=feathering width),
// then we risk severe aliasing.
@ -1017,6 +1021,8 @@ fn stroke_and_fill_path(
}
}
// TODO(emilk): add line caps (if this is an open line).
let opacity = stroke.width / feathering;
/*
@ -1129,6 +1135,10 @@ fn stroke_and_fill_path(
// (in the future it would be great with an option to add a circular end instead)
// TODO(emilk): we should probably shrink before adding the line caps,
// so that we don't add to the area of the line.
// TODO(emilk): make line caps optional.
out.reserve_triangles(6 * n as usize + 4);
out.reserve_vertices(4 * n as usize);
@ -1637,6 +1647,11 @@ impl Tessellator {
}
if self.options.round_line_segments_to_pixels {
let feathering = self.feathering;
let pixels_per_point = self.pixels_per_point;
let quarter_pixel = 0.25 * feathering; // Used to avoid fence post problem.
let [a, b] = &mut points;
if a.x == b.x {
// Vertical line
@ -1644,6 +1659,20 @@ impl Tessellator {
round_line_segment(&mut x, &stroke, self.pixels_per_point);
a.x = x;
b.x = x;
// Often the ends of the line are exactly on a pixel boundary,
// but we extend line segments with a cap that is a pixel wide…
// Solution: first shrink the line segment (on each end),
// then round to pixel center!
// We shrink by half-a-pixel n total (a quarter on each end),
// so that on average we avoid the fence-post-problem after rounding.
if a.y < b.y {
a.y = (a.y + quarter_pixel).round_to_pixel_center(pixels_per_point);
b.y = (b.y - quarter_pixel).round_to_pixel_center(pixels_per_point);
} else {
a.y = (a.y - quarter_pixel).round_to_pixel_center(pixels_per_point);
b.y = (b.y + quarter_pixel).round_to_pixel_center(pixels_per_point);
}
}
if a.y == b.y {
// Horizontal line
@ -1651,6 +1680,15 @@ impl Tessellator {
round_line_segment(&mut y, &stroke, self.pixels_per_point);
a.y = y;
b.y = y;
// See earlier comment for vertical lines
if a.x < b.x {
a.x = (a.x + quarter_pixel).round_to_pixel_center(pixels_per_point);
b.x = (b.x - quarter_pixel).round_to_pixel_center(pixels_per_point);
} else {
a.x = (a.x - quarter_pixel).round_to_pixel_center(pixels_per_point);
b.x = (b.x + quarter_pixel).round_to_pixel_center(pixels_per_point);
}
}
}