From 1204a13e2042e45e5f8c637ade4032f612dbf1b0 Mon Sep 17 00:00:00 2001 From: Alex Severin Date: Sat, 19 Oct 2024 21:46:20 +0300 Subject: [PATCH] restore old impl --- src/drawing/text.rs | 37 ++++++++++++++++++++++++------------- tests/data/truth/text.png | Bin 2955 -> 2978 bytes 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/drawing/text.rs b/src/drawing/text.rs index 89b1f586..a5c036c6 100644 --- a/src/drawing/text.rs +++ b/src/drawing/text.rs @@ -5,22 +5,20 @@ use crate::definitions::{Clamp, Image}; use crate::drawing::Canvas; use crate::pixelops::weighted_sum; -use ab_glyph::{point, Font, GlyphId, OutlinedGlyph, PxScale, ScaleFont}; +use ab_glyph::{point, Font, GlyphId, OutlinedGlyph, PxScale, Rect, ScaleFont}; fn layout_glyphs( scale: impl Into + Copy, font: &impl Font, text: &str, - mut f: impl FnMut(OutlinedGlyph, (i32, i32)), + mut f: impl FnMut(OutlinedGlyph, Rect), ) -> (u32, u32) { if text.is_empty() { return (0, 0); } let font = font.as_scaled(scale); - let first_char = text.chars().next().unwrap(); - let first_glyph = font.glyph_id(first_char); - let mut w = font.h_side_bearing(first_glyph).abs(); + let mut w = 0.0; let mut prev: Option = None; for c in text.chars() { @@ -33,9 +31,7 @@ fn layout_glyphs( } prev = Some(glyph_id); let bb = g.px_bounds(); - let bbx = bb.min.x as i32; - let bby = bb.min.y as i32; - f(g, (bbx, bby)); + f(g, bb); } } @@ -92,9 +88,9 @@ pub fn draw_text_mut( let image_width = canvas.width() as i32; let image_height = canvas.height() as i32; - layout_glyphs(scale, font, text, |g, (bbx, bby)| { - let x_shift = x + bbx; - let y_shift = y + bby; + layout_glyphs(scale, font, text, |g, bb| { + let x_shift = x + bb.min.x.round() as i32; + let y_shift = y + bb.min.y.round() as i32; g.draw(|gx, gy, gv| { let image_x = gx as i32 + x_shift; let image_y = gy as i32 + y_shift; @@ -128,11 +124,11 @@ mod proptests { proptest! { #[test] fn proptest_text_size( + img in arbitrary_image_with::>(Just(0), 0..=100, 0..=100), x in 0..100, y in 0..100, scale in 0.0..100f32, ref text in "[0-9a-zA-Z]*", - img in arbitrary_image_with::>(Just(0), 0..=100, 0..=100), ) { let font = FontRef::try_from_slice(FONT_BYTES).unwrap(); let background = Luma([0]); @@ -141,7 +137,22 @@ mod proptests { let img = draw_text(&img, text_color, x, y, scale, &font, text); let (text_w, text_h) = text_size(scale, &font, text); - let rect = Rect::at(x, y).of_size(1 + text_w, 1 + text_h); // TODO: fix Rect::contains + // TODO: fix Rect::contains by making Rect a "closed set" + let (text_w, text_h) = (text_w + 1, text_h + 1); + + let rect = if text.is_empty() { + Rect::at(x, y).of_size(text_w, text_h) + } else { + let first_char = text.chars().next().unwrap(); + let first_x_bearing = + font.as_scaled(scale).h_side_bearing(font.glyph_id(first_char)); + if first_x_bearing < 0.0 { + let x_shift = first_x_bearing.abs().ceil() as i32; + Rect::at(x - x_shift, y).of_size(text_w, text_h) + } else { + Rect::at(x, y).of_size(text_w, text_h) + } + }; for (px, py, &p) in img.enumerate_pixels() { if !rect.contains(px as i32, py as i32) { assert_eq!(p, background, "pixel_position: {:?}, rect: {:?}", (px, py), rect); diff --git a/tests/data/truth/text.png b/tests/data/truth/text.png index dfeb60b53fa701085fe6f9b5bd7b056b7bc07c84..372749f1cb4d443ef3c36a4145920507029fbf0b 100644 GIT binary patch delta 1452 zcmW-geQXnT7{`CzaD~Bg5R{^0E6TfLbV%la^@Rwih&qxg71??qAp}s$EU8F_vz>S%HxGOxpsKtiV0T<>X~}o{oohOYsxzd*D4L>s?`O>zcC2jnCO*4b?Y0 z(3io>vgYOBr_#_>aAlHDE|G^%6|-Uf>vaOO`SG3-BH=_^(sQuYeCUR9P2>_+6&<%V z0Bd&*tn?Gi3d1Kvt5@5Wjo*lbggu@ScsE@yDPZ@4pXfK#7ZjD7b<1oCn9^DwS%jHx z0UlAPZ{MT8H)FhLm&3bLJb#Qm;LAa0slHWcR_ib|h5^+z;~p|7wxTIZm;Wd-{wziM zKZ^;{HjGHRvXkwj9k6!tmSSp5qP++|QCshqM0n`P7D3>YAd)Z#dBPs!)2G%6h-2oO zxzt-bV>|6Wrj>qZ77lmd)DH-m#m)w{$)qv7uSw9C#2Ic=F%k$H&<6N1kKLR~J}5k3 z$h(c+8UM~dM2|%7La*9)Y*-%ouisYuGO496?UiHjHmwRqk?HB>Dc zd!DMKpRQXD7o-1N6wQ%Ok_zUrtN{2U&lvwwog0uHL!;-&;dhWD{WOoWFlvdl-4jie z>oqQKZluvU@~hr9dcC3vS{t`(_$Y%5El_16LGHK1+LdNzyKqoJRod$v%oACt((Vgn z+cnMe`P3%2LUO{O*$1M%B?{pn*Yzjv6H;5@wl#%sGE&ZLdT^F6RM{*yJMZuHcj@K8 z{m@MPDzrFBJu_d&Z@OIM9zf1=MGNG5BKnRTx-I{T0CFRW#q$9YzHb!+Z9X*BNqeLq zx?b6lJ037*>bkMs5UdFtEta7RTZ$yL`w~rw>*{7xs*w0o zq)gR|L`Cjly3i0a^8<&0>LqAu8*`>-qS^l;Xq={@O=&6oJe5HX-@az3U8z~_K;5SY zRr4LAgqCzB&dn7xuqLlGH{e0pyY$~2YTF_2e|z9+NgsRB)%TnQo(T-Uh*Ae{i$S}i zKQ5!*HmDA@b=KxpJ`&m$)}U|fR*(M--ML8a_rrPue9*7l?8pR5bM0+b^0XWjh!EuX z|6j7vHKQcH9+h7)S?T=Jz{0xLbb6@?j)$UI(JvsRnXlS{q`OxX2|vrrZI`OWb>WAW z!yWm;{+fVsmd-6{|APqLweBhzDNNH{GX$k7ok?`rsSzRRNFMCV@=_(BuDgCa7&W&` zRpOK^AE?P8u}si{*7}F@@$Dy*Z2`5zUx=1>EJ8vuxH{FzG0hw!tHi~Cf${7=cSz!k5rKsAwQiDw8Rbwt&+xkC}ty{5HI9-uAg5HCr~nyXpFCyH5NIo_{t4 delta 1429 zcmW-gjZYJI7=W*QDk{|>>kQJW%*@C#oXX0^(IaE(l#jX*g9(h{NJf?b1q-$mPfalHoKT_m zrhVVF`-cF)MGqls;Sh^VVU2-iDRxsjQ_Cb%kg{ef01BeM0M4sg%XOyfYR5pdRuiQ} z>jMWIiK@L+X|B12*AV)Z^Tp}_WL%Ov`iV~hS{;1!a(;oRojg^D8mw<5C&&oe@xH}F zv}E%ij9{pN`nFzQX(Lvt`C^$WQy~PY)2^j{_+^ZzQcHsitr}XPVF-arW}M97B2_63 zVm>G(Wukiwgxmn0cf)TRSYk_Di&?eK&q}awW0eOyQ+WQ0*WRTZ^lO0IvBAq<$@^RAlj4#L7OZR%rHLF{sida;&A&%E?)#`=Q3Sy|JjONokWnq*1W; z<)C0eS!2KpcOV`<20pNV3V@VH7bO81FUxl92AO^#Zk~%gH*(1cgR zVu4)c{1cNC>+dc>WAI}T7RK}(he(sYqUHz!t|@}^sD4p;o{id^1MmHmR=o0uy#K+JHk2?D`%uwQ*e z)GC=#%|1|>uYcC10lT2R)OYvY_SN}nwmpaWRK#eU3ZZ+W{hS2+KY#-<5u&mWD%`po zieY{Ly>5bLJhOBPnj8#Fx|-_EIg_X@yO{JYVqE&8729uhYv9KC+Xo@>Nwlz+vvO16 zZd8o&ZP|E}Gyc(nur{(R6%uy^Xbp z#KQ)Xx##sW5A;J^6Ro-~3$$U6w^Y~ZE0d}tjGeY7$o9szRi@80=^ifY3dvY#GjRlO zsKg%)ZE&n1bF&-NL_VfNVKrYo3o`L?BU_|toMA&&UpnW0;9Jh`hW-|da}IH70!z?D zds>_`L^0?$d5+pME^(YzIrh|yv)l(@Dc6=?{ZmwiZ{*TSL`7>i(5Bj=)T{Kk_BJHI z7(p0$aJUB8calLexpqdUY#XWryG89>O1C=ut|4$u?g7|>lQjLTa#Z#jyk_Zq1z}=% z$E@CekiMmO-!?ERz&0g#h3Z$V!Bsj$=n7D=o3OK{P;u3u+(8hFdON28IJL61XIj(y z^v7^PD4dxnEZ(HfQqFVJ>3&1~_8E88LAA9nrlwBdg{l_&$uZ(YZWq;E(2MVqjVojb zB?!Tupcb$m!UlS&Q8JR(Ni7LIY0w#M^yw#L-&u&Wm}2F)JaO(hHgOxZMAY~M44fNO zgVB4+M|&Er16mlcllI6<8F9Cw_^*nDwy!50m-}V^f=Fn%o3^e#@XB#o7{kb-vCBG- Uj)(9MK>j&;DC3*^U+10s9}|Zoc>n+a