diff options
Diffstat (limited to 'lib/percept/src/egd_font.erl')
-rw-r--r-- | lib/percept/src/egd_font.erl | 176 |
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. + |