aboutsummaryrefslogtreecommitdiffstats
path: root/lib/percept/src/egd_font.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/percept/src/egd_font.erl')
-rw-r--r--lib/percept/src/egd_font.erl176
1 files changed, 176 insertions, 0 deletions
diff --git a/lib/percept/src/egd_font.erl b/lib/percept/src/egd_font.erl
new file mode 100644
index 0000000000..2b2a89a0a9
--- /dev/null
+++ b/lib/percept/src/egd_font.erl
@@ -0,0 +1,176 @@
+%%
+%% %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_font
+%%
+
+-module(egd_font).
+
+-export([load/1, size/1, glyph/2]).
+-include("egd.hrl").
+
+%% Font represenatation in ets table
+%% egd_font_table
+%%
+%% Information:
+%% {Key, Description, Size}
+%% Key :: {Font :: atom(), information}
+%% Description :: any(), Description header from font file
+%% Size :: {W :: integer(), H :: integer()}
+%%
+%% Glyphs:
+%% {Key, Translation LSs} where
+%% Key :: {Font :: atom(), Code :: integer()}, Code = glyph char code
+%% Translation :: {
+%% W :: integer(), % BBx width
+%% H :: integer(), % BBx height
+%% X0 :: integer(), % X start
+%% Y0 :: integer(), % Y start
+%% Xm :: integer(), % Glyph X move when drawing
+%% }
+%% LSs :: [[{Xl :: integer(), Xr :: integer()}]]
+%% The first list is height (top to bottom), the inner list is the list
+%% of line spans for the glyphs horizontal pixels.
+%%
+
+%%==========================================================================
+%%
+%% Interface functions
+%%
+%%==========================================================================
+
+size(Font) ->
+ [{_Key, _Description, Size}] = ets:lookup(egd_font_table,{Font,information}),
+ Size.
+
+glyph(Font, Code) ->
+ [{_Key, Translation, LSs}] = ets:lookup(egd_font_table,{Font,Code}),
+ {Translation, LSs}.
+
+load(Filename) ->
+ {ok, Bin} = file:read_file(Filename),
+ Font = erlang:binary_to_term(Bin),
+ load_font_header(Font).
+
+%%==========================================================================
+%%
+%% Internal functions
+%%
+%%==========================================================================
+
+%% ETS handler functions
+
+initialize_table() ->
+ ets:new(egd_font_table, [named_table, ordered_set, public]).
+
+glyph_insert(Font, Code, Translation, LSs) ->
+ Element = {{Font, Code}, Translation, LSs},
+ ets:insert(egd_font_table, Element).
+
+font_insert(Font, Description, Dimensions) ->
+ Element = {{Font, information}, Description, Dimensions},
+ ets:insert(egd_font_table, Element).
+
+%% Font loader functions
+
+is_font_loaded(Font) ->
+ try
+ case ets:lookup(egd_font_table, {Font, information}) of
+ [] -> false;
+ _ -> true
+ end
+ catch
+ error:_ ->
+ initialize_table(),
+ false
+ end.
+
+
+load_font_header({_Type, _Version, Font}) ->
+ load_font_body(Font).
+
+load_font_body({Key,Desc,W,H,Glyphs,Bitmaps}) ->
+ case is_font_loaded(Key) of
+ true -> Key;
+ false ->
+ % insert dimensions
+ font_insert(Key, Desc, {W,H}),
+ parse_glyphs(Glyphs, Bitmaps, Key),
+ Key
+ end.
+
+parse_glyphs([], _ , _Key) -> ok;
+parse_glyphs([Glyph|Glyphs], Bs, Key) ->
+ {Code, Translation, LSs} = parse_glyph(Glyph, Bs),
+ glyph_insert(Key, Code, Translation, LSs),
+ parse_glyphs(Glyphs, Bs, Key).
+
+parse_glyph({Code,W,H,X0,Y0,Xm,Offset}, Bitmasks) ->
+ BytesPerLine = ((W+7) div 8),
+ NumBytes = BytesPerLine*H,
+ <<_:Offset/binary,Bitmask:NumBytes/binary,_/binary>> = Bitmasks,
+ LSs = render_glyph(W,H,X0,Y0,Xm,Bitmask),
+ {Code, {W,H,X0,Y0,Xm}, LSs}.
+
+render_glyph(W, H, X0, Y0, Xm, Bitmask) ->
+ render_glyph(W,{0,H},X0,Y0,Xm,Bitmask, []).
+render_glyph(_W, {H,H}, _X0, _Y0, _Xm, _Bitmask, Out) -> Out;
+render_glyph(W, {Hi,H}, X0, Y0,Xm, Bitmask, LSs) ->
+ N = ((W+7) div 8),
+ O = N*Hi,
+ <<_:O/binary, Submask/binary>> = Bitmask,
+ LS = render_glyph_horizontal(
+ Submask, % line glyph bitmask
+ {down, W - 1}, % loop state
+ W - 1, % Width
+ []), % Linespans
+ render_glyph(W,{Hi+1,H},X0,Y0,Xm, Bitmask, [LS|LSs]).
+
+render_glyph_horizontal(Value, {Pr, Px}, 0, Spans) ->
+ Cr = bit_spin(Value, 0),
+ case {Pr,Cr} of
+ {up , up } -> % closure of interval since its last
+ [{0, Px}|Spans];
+ {up , down} -> % closure of interval
+ [{1, Px}|Spans];
+ {down, up } -> % beginning of interval
+ [{0, 0}|Spans];
+ {down, down} -> % no change in interval
+ Spans
+ end;
+render_glyph_horizontal(Value, {Pr, Px}, Cx, Spans) ->
+ Cr = bit_spin(Value, Cx),
+ case {Pr,Cr} of
+ {up , up } -> % no change in interval
+ render_glyph_horizontal(Value, {Cr, Px}, Cx - 1, Spans);
+ {up , down} -> % closure of interval
+ render_glyph_horizontal(Value, {Cr, Cx}, Cx - 1, [{Cx+1,Px}|Spans]);
+ {down, up } -> % beginning of interval
+ render_glyph_horizontal(Value, {Cr, Cx}, Cx - 1, Spans);
+ {down, down} -> % no change in interval
+ render_glyph_horizontal(Value, {Cr, Px}, Cx - 1, Spans)
+ end.
+
+bit_spin(Value, Cx) ->
+ <<_:Cx, Bit:1, _/bits>> = Value,
+ case Bit of
+ 1 -> up;
+ 0 -> down
+ end.
+