/source/otp_src_R14B02/lib/percept/src/egd_font.erl

https://github.com/cparedes/omnibus · Erlang · 175 lines · 96 code · 23 blank · 56 comment · 0 complexity · 726de96a9368a8fd9b7758d252f75d98 MD5 · raw file

  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 2008-2009. All Rights Reserved.
  5. %%
  6. %% The contents of this file are subject to the Erlang Public License,
  7. %% Version 1.1, (the "License"); you may not use this file except in
  8. %% compliance with the License. You should have received a copy of the
  9. %% Erlang Public License along with this software. If not, it can be
  10. %% retrieved online at http://www.erlang.org/.
  11. %%
  12. %% Software distributed under the License is distributed on an "AS IS"
  13. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14. %% the License for the specific language governing rights and limitations
  15. %% under the License.
  16. %%
  17. %% %CopyrightEnd%
  18. %%
  19. %% @doc egd_font
  20. %%
  21. -module(egd_font).
  22. -export([load/1, size/1, glyph/2]).
  23. -include("egd.hrl").
  24. %% Font represenatation in ets table
  25. %% egd_font_table
  26. %%
  27. %% Information:
  28. %% {Key, Description, Size}
  29. %% Key :: {Font :: atom(), information}
  30. %% Description :: any(), Description header from font file
  31. %% Size :: {W :: integer(), H :: integer()}
  32. %%
  33. %% Glyphs:
  34. %% {Key, Translation LSs} where
  35. %% Key :: {Font :: atom(), Code :: integer()}, Code = glyph char code
  36. %% Translation :: {
  37. %% W :: integer(), % BBx width
  38. %% H :: integer(), % BBx height
  39. %% X0 :: integer(), % X start
  40. %% Y0 :: integer(), % Y start
  41. %% Xm :: integer(), % Glyph X move when drawing
  42. %% }
  43. %% LSs :: [[{Xl :: integer(), Xr :: integer()}]]
  44. %% The first list is height (top to bottom), the inner list is the list
  45. %% of line spans for the glyphs horizontal pixels.
  46. %%
  47. %%==========================================================================
  48. %%
  49. %% Interface functions
  50. %%
  51. %%==========================================================================
  52. size(Font) ->
  53. [{_Key, _Description, Size}] = ets:lookup(egd_font_table,{Font,information}),
  54. Size.
  55. glyph(Font, Code) ->
  56. [{_Key, Translation, LSs}] = ets:lookup(egd_font_table,{Font,Code}),
  57. {Translation, LSs}.
  58. load(Filename) ->
  59. {ok, Bin} = file:read_file(Filename),
  60. Font = erlang:binary_to_term(Bin),
  61. load_font_header(Font).
  62. %%==========================================================================
  63. %%
  64. %% Internal functions
  65. %%
  66. %%==========================================================================
  67. %% ETS handler functions
  68. initialize_table() ->
  69. ets:new(egd_font_table, [named_table, ordered_set, public]).
  70. glyph_insert(Font, Code, Translation, LSs) ->
  71. Element = {{Font, Code}, Translation, LSs},
  72. ets:insert(egd_font_table, Element).
  73. font_insert(Font, Description, Dimensions) ->
  74. Element = {{Font, information}, Description, Dimensions},
  75. ets:insert(egd_font_table, Element).
  76. %% Font loader functions
  77. is_font_loaded(Font) ->
  78. try
  79. case ets:lookup(egd_font_table, {Font, information}) of
  80. [] -> false;
  81. _ -> true
  82. end
  83. catch
  84. error:_ ->
  85. initialize_table(),
  86. false
  87. end.
  88. load_font_header({_Type, _Version, Font}) ->
  89. load_font_body(Font).
  90. load_font_body({Key,Desc,W,H,Glyphs,Bitmaps}) ->
  91. case is_font_loaded(Key) of
  92. true -> Key;
  93. false ->
  94. % insert dimensions
  95. font_insert(Key, Desc, {W,H}),
  96. parse_glyphs(Glyphs, Bitmaps, Key),
  97. Key
  98. end.
  99. parse_glyphs([], _ , _Key) -> ok;
  100. parse_glyphs([Glyph|Glyphs], Bs, Key) ->
  101. {Code, Translation, LSs} = parse_glyph(Glyph, Bs),
  102. glyph_insert(Key, Code, Translation, LSs),
  103. parse_glyphs(Glyphs, Bs, Key).
  104. parse_glyph({Code,W,H,X0,Y0,Xm,Offset}, Bitmasks) ->
  105. BytesPerLine = ((W+7) div 8),
  106. NumBytes = BytesPerLine*H,
  107. <<_:Offset/binary,Bitmask:NumBytes/binary,_/binary>> = Bitmasks,
  108. LSs = render_glyph(W,H,X0,Y0,Xm,Bitmask),
  109. {Code, {W,H,X0,Y0,Xm}, LSs}.
  110. render_glyph(W, H, X0, Y0, Xm, Bitmask) ->
  111. render_glyph(W,{0,H},X0,Y0,Xm,Bitmask, []).
  112. render_glyph(_W, {H,H}, _X0, _Y0, _Xm, _Bitmask, Out) -> Out;
  113. render_glyph(W, {Hi,H}, X0, Y0,Xm, Bitmask , LSs) ->
  114. N = ((W+7) div 8),
  115. O = N*Hi,
  116. <<_:O/binary, Submask/binary>> = Bitmask,
  117. LS = render_glyph_horizontal(
  118. Submask, % line glyph bitmask
  119. {down, W - 1}, % loop state
  120. W - 1, % Width
  121. []), % Linespans
  122. render_glyph(W,{Hi+1,H},X0,Y0,Xm, Bitmask, [LS|LSs]).
  123. render_glyph_horizontal(Value, {Pr, Px}, 0, Spans) ->
  124. Cr = bit_spin(Value, 0),
  125. case {Pr,Cr} of
  126. {up , up } -> % closure of interval since its last
  127. [{0, Px}|Spans];
  128. {up , down} -> % closure of interval
  129. [{1, Px}|Spans];
  130. {down, up } -> % beginning of interval
  131. [{0, 0}|Spans];
  132. {down, down} -> % no change in interval
  133. Spans
  134. end;
  135. render_glyph_horizontal(Value, {Pr, Px}, Cx, Spans) ->
  136. Cr = bit_spin(Value, Cx),
  137. case {Pr,Cr} of
  138. {up , up } -> % no change in interval
  139. render_glyph_horizontal(Value, {Cr, Px}, Cx - 1, Spans);
  140. {up , down} -> % closure of interval
  141. render_glyph_horizontal(Value, {Cr, Cx}, Cx - 1, [{Cx+1,Px}|Spans]);
  142. {down, up } -> % beginning of interval
  143. render_glyph_horizontal(Value, {Cr, Cx}, Cx - 1, Spans);
  144. {down, down} -> % no change in interval
  145. render_glyph_horizontal(Value, {Cr, Px}, Cx - 1, Spans)
  146. end.
  147. bit_spin(Value, Cx) ->
  148. <<_:Cx, Bit:1, _/bits>> = Value,
  149. case Bit of
  150. 1 -> up;
  151. 0 -> down
  152. end.