aboutsummaryrefslogtreecommitdiffstats
path: root/lib/percept/src/egd.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/percept/src/egd.erl')
-rw-r--r--lib/percept/src/egd.erl287
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.