From f2ee95d8e7e2a0aebb417016a6193b36e0ebfb4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Sun, 15 May 2016 00:00:31 +0200 Subject: egd: Use anti-aliasing for lines * Also remove old line algorithm --- lib/percept/src/egd_render.erl | 113 ++++++++++------------------------------- 1 file changed, 27 insertions(+), 86 deletions(-) diff --git a/lib/percept/src/egd_render.erl b/lib/percept/src/egd_render.erl index a97bb05cac..c0075b8c42 100644 --- a/lib/percept/src/egd_render.erl +++ b/lib/percept/src/egd_render.erl @@ -28,7 +28,6 @@ -compile(inline). -export([line_to_linespans/3]). --export([line_ls/2]). -include("egd.hrl"). -define('DummyC',0). @@ -287,9 +286,9 @@ object_line_data(#image_object{type=filled_triangle, end; object_line_data(#image_object{type=line, - intervals=M, color=C}, Y, Z) -> + intervals=M, color={R,G,B,_}}, Y, Z) -> case M of - #{Y := Ls} -> [{Z, Xl, Xr, C}||{Xl,Xr} <- Ls]; + #{Y := Ls} -> [{Z, Xl, Xr, {R,G,B,1.0-C/255}}||{Xl,Xr,C} <- Ls]; _ -> [] end; @@ -331,8 +330,8 @@ precompile_objects([#image_object{type=filled_ellipse, span={X0,Y0,X1,Y1}}=O|Os] [O#image_object{internals={Xr,Yr,Yr2}}|precompile_objects(Os)]; precompile_objects([#image_object{type=arc, points=[P0,P1], internals=D}=O|Os]) -> Es = egd_primitives:arc_to_edges(P0, P1, D), - Ls = lists:foldl(fun ({Ep0, Ep1}, D0) -> - linespans_to_map(line_ls(Ep0, Ep1), D0) + Ls = lists:foldl(fun ({Ep0,Ep1},M) -> + linespans_to_map(line_to_linespans(Ep0,Ep1,1),M) end, #{}, Es), [O#image_object{type=line, intervals=Ls}|precompile_objects(Os)]; precompile_objects([#image_object{type=text_horizontal, @@ -353,7 +352,8 @@ triangle_ls(P1,P2,P3) -> % At an end point, a new line to the point already being drawn % repeat same procedure as above [Sp1, Sp2, Sp3] = tri_pt_ysort([P1,P2,P3]), - triangle_ls_lp(tri_ls_ysort(line_ls(Sp1,Sp2)), Sp2, tri_ls_ysort(line_ls(Sp1,Sp3)), Sp3, []). + triangle_ls_lp(tri_ls_ysort(line_to_linespans(Sp1,Sp2,1)), Sp2, + tri_ls_ysort(line_to_linespans(Sp1,Sp3,1)), Sp3, []). % There will be Y mismatches between the two lists since bresenham is not perfect. % I can be remedied with checking intervals this could however be costly and @@ -362,7 +362,7 @@ triangle_ls(P1,P2,P3) -> triangle_ls_lp([],_,[],_,Out) -> Out; triangle_ls_lp(LSs1, P1, [], P2, Out) -> - SLSs = tri_ls_ysort(line_ls(P2,P1)), + SLSs = tri_ls_ysort(line_to_linespans(P2,P1,1)), N2 = length(SLSs), N1 = length(LSs1), if @@ -376,7 +376,7 @@ triangle_ls_lp(LSs1, P1, [], P2, Out) -> triangle_ls_lp(LSs1, SLSs, Out) end; triangle_ls_lp([], P1, LSs2, P2, Out) -> - SLSs = tri_ls_ysort(line_ls(P1,P2)), + SLSs = tri_ls_ysort(line_to_linespans(P1,P2,1)), N1 = length(SLSs), N2 = length(LSs2), if @@ -390,21 +390,21 @@ triangle_ls_lp([], P1, LSs2, P2, Out) -> triangle_ls_lp(SLSs, LSs2, Out) end; triangle_ls_lp([LS1|LSs1],P1,[LS2|LSs2],P2, Out) -> - {Y, Xl1, Xr1} = LS1, - {_, Xl2, Xr2} = LS2, + {Y, Xl1, Xr1,_Ca1} = LS1, + {_, Xl2, Xr2,_Ca2} = LS2, Xr = lists:max([Xl1,Xr1,Xl2,Xr2]), Xl = lists:min([Xl1,Xr1,Xl2,Xr2]), - triangle_ls_lp(LSs1,P1, LSs2, P2, [{Y,Xl,Xr}|Out]). + triangle_ls_lp(LSs1,P1,LSs2,P2,[{Y,Xl,Xr}|Out]). triangle_ls_lp([],[],Out) -> Out; triangle_ls_lp([],_,Out) -> Out; triangle_ls_lp(_,[],Out) -> Out; triangle_ls_lp([LS1|LSs1], [LS2|LSs2], Out) -> - {Y, Xl1, Xr1} = LS1, - {_, Xl2, Xr2} = LS2, + {Y, Xl1, Xr1, _Ca1} = LS1, + {_, Xl2, Xr2, _Ca2} = LS2, Xr = lists:max([Xl1,Xr1,Xl2,Xr2]), Xl = lists:min([Xl1,Xr1,Xl2,Xr2]), - triangle_ls_lp(LSs1, LSs2, [{Y,Xl,Xr}|Out]). + triangle_ls_lp(LSs1,LSs2,[{Y,Xl,Xr}|Out]). tri_pt_ysort(Pts) -> % {X,Y} @@ -414,9 +414,9 @@ tri_pt_ysort(Pts) -> end, Pts). tri_ls_ysort(LSs) -> - % {Y, Xl, Xr} + % {Y, Xl, Xr, Ca} lists:sort( - fun ({Y1,_,_},{Y2,_,_}) -> + fun ({Y1,_,_,_},{Y2,_,_,_}) -> if Y1 > Y2 -> false; true -> true end end, LSs). @@ -508,70 +508,14 @@ point_inside_triangle(P, P1, P2, P3) -> linespans_to_map(Ls) -> linespans_to_map(Ls,#{}). -linespans_to_map([{Y,Xl,Xr}|Ls], M) -> +linespans_to_map([{Y,Xl,Xr,C}|Ls], M) -> case M of - #{Y := Spans} -> linespans_to_map(Ls, M#{Y := [{Xl,Xr}|Spans]}); - _ -> linespans_to_map(Ls, M#{Y => [{Xl,Xr}]}) + #{Y := Spans} -> linespans_to_map(Ls, M#{Y := [{Xl,Xr,C}|Spans]}); + _ -> linespans_to_map(Ls, M#{Y => [{Xl,Xr,C}]}) end; linespans_to_map([], M) -> M. -%% line_ls -%% In: -%% P1 :: point() -%% P2 :: point() -%% Out: -%% {{Ymin,Ymax}, LSD :: line_step_data()} -%% Purpose: -%% Instead of points -> intervals - - -line_ls({Xi0, Yi0},{Xi1,Yi1}) -> - % swap X with Y if line is steep - Steep = abs(Yi1 - Yi0) > abs(Xi1 - Xi0), - - {Xs0, Ys0, Xs1, Ys1} = case Steep of - true -> {Yi0,Xi0,Yi1,Xi1}; - false -> {Xi0,Yi0,Xi1,Yi1} - end, - - {X0,Y0,X1,Y1} = case Xs0 > Xs1 of - true -> {Xs1,Ys1,Xs0,Ys0}; - false -> {Xs0,Ys0,Xs1,Ys1} - end, - - DX = X1 - X0, - DY = abs(Y1 - Y0), - - Error = -DX/2, - - Ystep = case Y0 < Y1 of - true -> 1; - false -> -1 - end, - line_ls_step(X0, X1,Y0, DX, DY, Ystep, Error, X0, Steep, []). - -%% line_ls_step_(not)_steep -%% In: -%% Out: -%% [{Yi, Xl,Xr}] -%% Purpose: -%% Produce an line_interval for each Yi (Y index) - -line_ls_step(X, X1, Y, Dx, Dy, Ys, E, X0, false = Steep, LSs) when X < X1, E >= 0 -> - line_ls_step(X+1,X1,Y+Ys,Dx,Dy,Ys, E - Dx + Dy, X+1, Steep, [{Y,X0,X}|LSs]); -line_ls_step(X, X1, Y, Dx, Dy, Ys, E, X0, false = Steep, LSs) when X < X1 -> - line_ls_step(X+1,X1,Y,Dx,Dy,Ys, E + Dy, X0, Steep, LSs); -line_ls_step(X, _X1, Y, _Dx, _Dy, _Ys, _E, X0, false, LSs) -> - [{Y,X0,X}|LSs]; -line_ls_step(X, X1, Y, Dx, Dy, Ys, E, _X0, true = Steep, LSs) when X =< X1, E >= 0 -> - line_ls_step(X+1,X1,Y+Ys,Dx,Dy,Ys, E - Dx + Dy, X, Steep, [{X,Y,Y}|LSs]); -line_ls_step(X, X1, Y, Dx, Dy, Ys, E, X0, true = Steep, LSs) when X =< X1 -> - line_ls_step(X+1,X1,Y,Dx,Dy,Ys,E + Dy, X0, Steep, [{X,Y,Y}|LSs]); -line_ls_step(_X,_,_Y,_Dx,_Dy,_Ys,_E,_X0,_,LSs) -> - LSs. - - %% line_to_linespans %% Anti-aliased thick line @@ -592,9 +536,8 @@ line_to_linespans({X0,Y0},{X1,Y1},Wd) -> line_to_ls(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E0,Ed,(Wd+1)/2,[]). line_to_ls(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0) -> - %C = max(0, 255*(abs(E - Dx+Dy)/Ed - Wd + 1)), - %Ls1 = [{ls,Y0,X0,C}|Ls0], - Ls1 = [{Y0,X0,X0}|Ls0], + C = max(0, 255*(abs(E - Dx+Dy)/Ed - Wd + 1)), + Ls1 = [{Y0,X0,X0,C}|Ls0], line_to_ls_sx(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls1,E). line_to_ls_sx(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2) when 2*E2 > -Dx -> @@ -605,9 +548,8 @@ line_to_ls_sx(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2) -> line_to_ls_sx_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,E2,Y) when E2 < Ed*Wd andalso (Y1 =/= Y orelse Dx > Dy) -> Y2 = Y + Sy, - %C = max(0,255*(abs(E2)/Ed-Wd+1)), - %Ls = [{sx,Y2,X0,C}|Ls0], - Ls = [{Y2,X0,X0}|Ls0], + C = max(0,255*(abs(E2)/Ed-Wd+1)), + Ls = [{Y2,X0,X0,C}|Ls0], line_to_ls_sx_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2+Dx,Y2); line_to_ls_sx_do(X0,_Y0,X1,_Y1,_Dx,_Dy,_Sx,_Sy,_E,_Ed,_Wd,Ls,_E2,_Y) when X0 =:= X1 -> Ls; @@ -622,14 +564,13 @@ line_to_ls_sy(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,_E2,_X) -> line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,E2,X) when E2 < Ed*Wd andalso (X1 =/= X orelse Dx < Dy) -> X2 = X + Sx, - %C = max(0,255*(abs(E2)/Ed-Wd+1)), - %Ls = [{sy,Y0,X2,C}|Ls0], - Ls = [{Y0,X2,X2}|Ls0], + C = max(0,255*(abs(E2)/Ed-Wd+1)), + Ls = [{Y0,X2,X2,C}|Ls0], line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,E2+Dy,X2); line_to_ls_sy_do(_X0,Y0,_X1,Y1,_Dx,_Dy,_Sx,_Sy,_E,_Ed,_Wd,Ls,_E2,_X) when Y0 =:= Y1 -> Ls; -line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls,_E2,_X) -> - line_to_ls(X0,Y0+Sy,X1,Y1,Dx,Dy,Sx,Sy,E+Dx,Ed,Wd,Ls). +line_to_ls_sy_do(X0,Y0,X1,Y1,Dx,Dy,Sx,Sy,E,Ed,Wd,Ls0,_E2,_X) -> + line_to_ls(X0,Y0+Sy,X1,Y1,Dx,Dy,Sx,Sy,E+Dx,Ed,Wd,Ls0). % Text -- cgit v1.2.3