diff options
Diffstat (limited to 'lib/percept/src/egd.erl')
-rw-r--r-- | lib/percept/src/egd.erl | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/lib/percept/src/egd.erl b/lib/percept/src/egd.erl new file mode 100644 index 0000000000..4becfef19b --- /dev/null +++ b/lib/percept/src/egd.erl @@ -0,0 +1,287 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +%% +%% @doc egd - erlang graphical drawer +%% +%% + +-module(egd). + +-export([create/2, destroy/1, information/1]). +-export([text/5, line/4, color/1, color/2]). +-export([rectangle/4, filledRectangle/4, filledEllipse/4]). +-export([arc/4, arc/5]). +-export([render/1, render/2, render/3]). + +-export([filledTriangle/5, polygon/3]). + +-export([save/2]). + +-include("egd.hrl"). + +%%========================================================================== +%% +%% Type definitions +%% +%%========================================================================== + +%% @type egd_image() +%% @type point() = {integer(), integer()} +%% @type color() +%% @type render_option() = {render_engine, opaque} | {render_engine, alpha} + +-type(egd_image() :: pid()). +-type(point() :: {non_neg_integer(), non_neg_integer()}). +-type(render_option() :: {'render_engine', 'opaque'} | {'render_engine', 'alpha'}). +-type(color() :: {float(), float(), float(), float()}). + +%%========================================================================== +%% +%% Interface functions +%% +%%========================================================================== + +%% @spec create(integer(), integer()) -> egd_image() +%% @doc Creates an image area and returns its reference. + +-spec(create/2 :: (Width :: integer(), Height :: integer()) -> egd_image()). + +create(Width,Height) -> + spawn_link(fun() -> init(trunc(Width),trunc(Height)) end). + + +%% @spec destroy(egd_image()) -> ok +%% @doc Destroys the image. + +-spec(destroy/1 :: (Image :: egd_image()) -> ok). + +destroy(Image) -> + cast(Image, destroy), + ok. + + +%% @spec render(egd_image()) -> binary() +%% @equiv render(Image, png, [{render_engine, opaque}]) + + +render(Image) -> + render(Image, png, [{render_engine, opaque}]). + +%% @spec render(egd_image(), png | raw_bitmap) -> binary() +%% @equiv render(Image, Type, [{render_engine, opaque}]) + +render(Image, Type) -> + render(Image, Type, [{render_engine, opaque}]). + +%% @spec render(egd_image(), png | raw_bitmap, [render_option()]) -> binary() +%% @doc Renders a binary from the primitives specified by egd_image(). The +%% binary can either be a raw bitmap with rgb tripplets or a binary in png +%% format. + +-spec(render/3 :: ( + Image :: egd_image(), + Type :: 'png' | 'raw_bitmap' | 'eps', + Options :: [render_option()]) -> binary()). + +render(Image, Type, Options) -> + {render_engine, RenderType} = proplists:lookup(render_engine, Options), + call(Image, {render, Type, RenderType}). + + +%% @spec information(egd_image()) -> ok +%% @hidden +%% @doc Writes out information about the image. This is a debug feature +%% mainly. + +information(Pid) -> + cast(Pid, information), + ok. + +%% @spec line(egd_image(), point(), point(), color()) -> ok +%% @doc Creates a line object from P1 to P2 in the image. + +-spec(line/4 :: ( + Image :: egd_image(), + P1 :: point(), + P2 :: point(), + Color :: color()) -> 'ok'). + +line(Image, P1, P2, Color) -> + cast(Image, {line, P1, P2, Color}), + ok. + +%% @spec color( Value | Name ) -> color() +%% where +%% Value = {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} +%% Name = black | silver | gray | white | maroon | red | purple | fuchia | green | lime | olive | yellow | navy | blue | teal | aqua +%% @doc Creates a color reference. + +-spec(color/1 :: ( + Value :: {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} | atom()) -> + color()). + +color(Color) -> + egd_primitives:color(Color). + +%% @spec color(egd_image(), {byte(), byte(), byte()}) -> color() +%% @doc Creates a color reference. +%% @hidden + +color(_Image, Color) -> + egd_primitives:color(Color). + +%% @spec text(egd_image(), point(), font(), string(), color()) -> ok +%% @doc Creates a text object. + +text(Image, P, Font, Text, Color) -> + cast(Image, {text, P, Font, Text, Color}), + ok. + +%% @spec rectangle(egd_image(), point(), point(), color()) -> ok +%% @doc Creates a rectangle object. + +rectangle(Image, P1, P2, Color) -> + cast(Image, {rectangle, P1, P2, Color}), + ok. + +%% @spec filledRectangle(egd_image(), point(), point(), color()) -> ok +%% @doc Creates a filled rectangle object. + +filledRectangle(Image, P1, P2, Color) -> + cast(Image, {filled_rectangle, P1, P2, Color}), + ok. + +%% @spec filledEllipse(egd_image(), point(), point(), color()) -> ok +%% @doc Creates a filled ellipse object. + +filledEllipse(Image, P1, P2, Color) -> + cast(Image, {filled_ellipse, P1, P2, Color}), + ok. + +%% @spec filledTriangle(egd_image(), point(), point(), point(), color()) -> ok +%% @hidden +%% @doc Creates a filled triangle object. + +filledTriangle(Image, P1, P2, P3, Color) -> + cast(Image, {filled_triangle, P1, P2, P3, Color}), + ok. + +%% @spec polygon(egd_image(), [point()], color()) -> ok +%% @hidden +%% @doc Creates a filled filled polygon object. + +polygon(Image, Pts, Color) -> + cast(Image, {polygon, Pts, Color}), + ok. + +%% @spec arc(egd_image(), point(), point(), color()) -> ok +%% @hidden +%% @doc Creates an arc with radius of bbx corner. + +arc(Image, P1, P2, Color) -> + cast(Image, {arc, P1, P2, Color}), + ok. + +%% @spec arc(egd_image(), point(), point(), integer(), color()) -> ok +%% @hidden +%% @doc Creates an arc. + +arc(Image, P1, P2, D, Color) -> + cast(Image, {arc, P1, P2, D, Color}), + ok. + +%% @spec save(binary(), string()) -> ok +%% @doc Saves the binary to file. + +save(Binary, Filename) when is_binary(Binary) -> + file:write_file(Filename, Binary), + ok. +% --------------------------------- +% Aux functions +% --------------------------------- + +cast(Pid, Command) -> + Pid ! {egd, self(), Command}. + +call(Pid, Command) -> + Pid ! {egd, self(), Command}, + receive {egd, Pid, Result} -> Result end. + +% --------------------------------- +% Server loop +% --------------------------------- + +init(W,H) -> + Image = egd_primitives:create(W,H), + loop(Image). + +loop(Image) -> + receive + % Quitting + {egd, _Pid, destroy} -> ok; + + % Rendering + {egd, Pid, {render, BinaryType, RenderType}} -> + case BinaryType of + raw_bitmap -> + Bitmap = egd_render:binary(Image, RenderType), + Pid ! {egd, self(), Bitmap}, + loop(Image); + eps -> + Eps = egd_render:eps(Image), + Pid ! {egd, self(), Eps}, + loop(Image); + png -> + Bitmap = egd_render:binary(Image, RenderType), + Png = egd_png:binary( + Image#image.width, + Image#image.height, + Bitmap), + Pid ! {egd, self(), Png}, + loop(Image); + Unhandled -> + Pid ! {egd, self(), {error, {format, Unhandled}}}, + loop(Image) + end; + + % Drawing primitives + {egd, _Pid, {line, P1, P2, C}} -> + loop(egd_primitives:line(Image, P1, P2, C)); + {egd, _Pid, {text, P, Font, Text, C}} -> + loop(egd_primitives:text(Image, P, Font, Text, C)); + {egd, _Pid, {filled_ellipse, P1, P2, C}} -> + loop(egd_primitives:filledEllipse(Image, P1, P2, C)); + {egd, _Pid, {filled_rectangle, P1, P2, C}} -> + loop(egd_primitives:filledRectangle(Image, P1, P2, C)); + {egd, _Pid, {filled_triangle, P1, P2, P3, C}} -> + loop(egd_primitives:filledTriangle(Image, P1, P2, P3, C)); + {egd, _Pid, {polygon, Pts, C}} -> + loop(egd_primitives:polygon(Image, Pts, C)); + {egd, _Pid, {arc, P1, P2, C}} -> + loop(egd_primitives:arc(Image, P1, P2, C)); + {egd, _Pid, {arc, P1, P2, D, C}} -> + loop(egd_primitives:arc(Image, P1, P2, D, C)); + {egd, _Pid, {rectangle, P1, P2, C}} -> + loop(egd_primitives:rectangle(Image, P1, P2, C)); + {egd, _Pid, information} -> + egd_primitives:info(Image), + loop(Image); + _ -> + loop(Image) + end. |