Blob Blame History Raw
From b6d26111ee16d57559c5ea33b0815a02c371ec0c Mon Sep 17 00:00:00 2001
From: Bjorn Gustavsson <bjorng@users.sourceforge.net>
Date: Mon, 7 Jan 2013 20:22:34 +0100
Subject: [PATCH 4/6] Simplify font handling and stop using parameterized
 modules

The wings__font.erl module uses the experimental feature
"parameterized modules", which is scheduled to be removed in
Erlang/OTP R16.

It turns out that wings__font for historical reasons is more
flexible than it needs to be and that it is almost unused. Most
of its functionality has been taken over by wings_font_table.
By slightly tweaking wings_text and wings_font_table we can easily
eliminate the need for wing__font.

By going a step further, we can see that there is no need to keep
the code in wings_font_table in a separate module. There is not
a large amount of code, and having code split into two modules
does not make it easier to understand since there is
wings_font_table does not hide any information from wings_text.

Therefore, move all font handling code into wings_text and remove
both wings__font and wings_font_table.

Conflicts:
	plugins_src/accel/Makefile
---
 src/Makefile             |   2 -
 src/wings__font.erl      |  75 -------------------
 src/wings_console.erl    |  10 +--
 src/wings_font_table.erl |  73 -------------------
 src/wings_io.erl         |  20 +-----
 src/wings_pref_dlg.erl   |   2 -
 src/wings_text.erl       | 184 ++++++++++++++++++++++++-----------------------
 src/wings_wm.erl         |   2 +-
 8 files changed, 101 insertions(+), 267 deletions(-)
 delete mode 100644 src/wings__font.erl
 delete mode 100644 src/wings_font_table.erl

diff --git a/src/Makefile b/src/Makefile
index 1f7380c..e1b06cc 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -70,8 +70,6 @@ MODULES= \
 	wings_file \
 	wings_ff_ndo \
 	wings_ff_wings \
-	wings_font_table \
-	wings__font \
 	wings_gl \
 	wings_help \
 	wings_hotkey \
diff --git a/src/wings__font.erl b/src/wings__font.erl
deleted file mode 100644
index bb969df..0000000
--- a/src/wings__font.erl
+++ /dev/null
@@ -1,75 +0,0 @@
-%%
-%%  wings__font.erl --
-%%
-%%     Generic font operations.
-%%
-%%  Copyright (c) 2005-2011 Bjorn Gustavsson.
-%%
-%%  See the file "license.terms" for information on usage and redistribution
-%%  of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-%%
-%%     $Id$
-%%
-
--module(wings__font, [Key,Desc,Width,Height,GlyphTab,Bitmaps]).
--export([key/0,desc/0,width/0,height/0,draw/1,char/1,char_width/1,
-	bold_char/1,bold_char_width/1]).
-
-draw([C|T]) ->
-    char(C),
-    draw(T);
-draw([]) -> ok.
-
-key() -> Key.
-desc() -> Desc.
-
-char_width(C) ->
-    element(1, glyph_info(C)).
-width() ->
-    insert_glyph(char_width, Width),
-    Width.
-height() ->
-    insert_glyph(char_height, Height),
-    Height.
-
-bold_char(C) ->
-    Glyph = glyph_info(C),
-    draw_glyph(Glyph),
-    Cw = glyph_width(Glyph),
-    gl:bitmap(1, 1, 0, 0, -Cw+1, 0, <<0>>),
-    draw_glyph(Glyph).
-
-bold_char_width(C) ->
-    Glyph = glyph_info(C),
-    glyph_width(Glyph)+1.
-
-char(C) ->
-    draw_glyph(glyph_info(C)).
-
-draw_glyph({W,H,Xorig,Yorig,Xmove,B}) ->
-    gl:bitmap(W, H, Xorig, Yorig, Xmove, 0, B).
-
-glyph_info(C) ->
-    BitMap = case ets:lookup(GlyphTab, C) of
-	[] when is_integer(C), C > 0 ->
-	    %% Undefined character. Return a filled box.
-	    NumBytes = ((Width+7) div 8) * Height,
-	    B = <<(-1):NumBytes/unit:8>>,
-	    {Width,Height,0,0,Width+1,B};
-	[{_,W,H,Xorig,Yorig,Xmove,Offset}] ->
-	    %% Valid character.
-	    NumBytes = ((W+7) div 8)*H,
-	    <<_:Offset/binary,B:NumBytes/binary,_/binary>> = Bitmaps,
-	    {W,H,Xorig,Yorig,Xmove,B}
-    end,
-    insert_glyph(C, BitMap),
-    BitMap.
-
-glyph_width({_,_,_,_,Xmove,_}) -> Xmove.
-
-insert_glyph(C, BitMap) ->
-    Font = case wings_wm:this() of
-        console -> console_font;
-        _ -> system_font
-    end,
-    ets:insert(Font, {C,BitMap}).
diff --git a/src/wings_console.erl b/src/wings_console.erl
index bc75ce4..2d79876 100644
--- a/src/wings_console.erl
+++ b/src/wings_console.erl
@@ -171,9 +171,9 @@ do_window(Name) ->
     Height0 = wings_pref:get_value(console_height),
     wings_wm:delete(Name),
     {X1,_,W1,H1} = wings_wm:viewport(desktop),
-    Font = wings_pref:get_value(new_console_font),
-    CwLh = wings_io:use_font(Font, fun() -> {?CHAR_WIDTH,?LINE_HEIGHT} end),
-    {Cw,Lh} = CwLh,
+    Font = console_font,
+    {Cw,Lh} = CwLh = wings_text:font_cw_lh(Font),
+    io:format("w h: ~p ~p\n", [Cw,Lh]),
     Sw = wings_wm:vscroller_width(),
     Th = wings_wm:title_height(),
     %%
@@ -184,8 +184,8 @@ do_window(Name) ->
     do_window(Name, Font, CwLh, PosUR, Size, []).
 
 do_window(Name, Pos, Size, Ps) ->
-    Font = wings_pref:get_value(new_console_font),
-    CwLh = wings_io:use_font(Font, fun() -> {?CHAR_WIDTH,?LINE_HEIGHT} end),
+    Font = console_font,
+    CwLh = wings_text:font_cw_lh(Font),
     do_window(Name, Font, CwLh, Pos, Size, Ps).
 
 do_window(Name, Font, {Cw,Lh}, {X,Y}, {W,H}=Size, Ps) -> % {X,Y} is upper right
diff --git a/src/wings_font_table.erl b/src/wings_font_table.erl
deleted file mode 100644
index 99732a4..0000000
--- a/src/wings_font_table.erl
+++ /dev/null
@@ -1,73 +0,0 @@
-%%
-%%  wings_font_table.erl --
-%%
-%%     Functions to access the accumulated font table in ets comprised of seen
-%%     glyphs. Seen returns the glyph, unseen returns 'undefined' and then
-%%     proceeds to look up the glyph in the full font table.
-%%
-%%  Copyright (c) 2010-2011 Richard Jones.
-%%
-%%  See the file "license.terms" for information on usage and redistribution
-%%  of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-%%
-%%
-
--module(wings_font_table).
--export([draw/1,char/1,bold_char/1,bold_char_width/1,char_width/1]).
-
-draw([C|T]) ->
-    char(C),
-    draw(T);
-draw([]) -> ok.
-
-bold_char_width(C) ->
-    case glyph_info(C) of
-        undefined -> undefined;
-    Glyph ->
-        glyph_width(Glyph)+1
-    end.
-
-char_width(C) ->
-    case glyph_info(C) of
-        undefined -> undefined;
-    Glyph ->
-        glyph_width(Glyph)
-    end.
-
-bold_char(C) ->
-    case glyph_info(C) of
-        undefined -> undefined;
-    Glyph ->
-        draw_glyph(Glyph),
-        Cw = glyph_width(Glyph),
-        gl:bitmap(1, 1, 0, 0, -Cw+1, 0, <<0>>),
-        draw_glyph(Glyph)
-    end.
-
-char(C) when C=:=char_width; C=:=char_height ->
-    case glyph_info(C) of
-        undefined -> undefined;
-        Glyph -> Glyph
-    end;
-char(C) ->
-    case glyph_info(C) of
-        undefined -> undefined;
-        Glyph -> draw_glyph(Glyph)
-    end.
-
-draw_glyph({W,H,Xorig,Yorig,Xmove,B}) -> 
-    gl:bitmap(W, H, Xorig, Yorig, Xmove, 0, B).
-
-glyph_info(C) ->
-    Font = case wings_wm:this() of
-        console -> console_font;
-        _ -> system_font
-    end,
-    case ets:lookup(Font, C) of
-        [] ->
-            undefined;
-        [{C,BitMap}] ->
-            BitMap
-    end.
-
-glyph_width({_,_,_,_,Xmove,_}) -> Xmove.
diff --git a/src/wings_io.erl b/src/wings_io.erl
index 1da919c..143bdfe 100644
--- a/src/wings_io.erl
+++ b/src/wings_io.erl
@@ -3,7 +3,7 @@
 %%
 %%     This module is a wrapper for the different backends
 %%
-%%  Copyright (c) 2001-2011 Bjorn Gustavsson
+%%  Copyright (c) 2001-2013 Bjorn Gustavsson
 %%
 %%  See the file "license.terms" for information on usage and redistribution
 %%  of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -36,7 +36,7 @@
 	 sunken_gradient/7,
 	 raised_rect/4,raised_rect/5,raised_rect/6,
 	 gradient_rect/5,gradient_rect_burst/5,
-	 use_font/2,text_at/2,text_at/3,unclipped_text/3,
+	 text_at/2,text_at/3,unclipped_text/3,
 	 draw_icons/1,draw_icon/3,draw_char/1,
 	 set_color/1]).
 -export([putback_event/1,putback_event_once/1,get_event/0,get_matching_events/1,
@@ -440,22 +440,6 @@ gradient_rect(X, Y, W, H, Color) ->
     gl:'end'(),
     gl:shadeModel(?GL_FLAT).
 
-use_font(Font, Fun) ->
-    case wings_wm:this() of
-	none ->
-	    OldFont = wings_pref:get_value(new_system_font),
-	    wings_pref:set_value(new_system_font, Font),
-	    Res = Fun(),
-	    wings_pref:set_value(new_system_font, OldFont),
-	    Res;
-	This ->
-	    OldFont = wings_wm:get_prop(This, font),
-	    wings_wm:set_prop(This, font, Font),
-	    Res = Fun(),
-	    wings_wm:set_prop(This, font, OldFont),
-	    Res
-    end.
-
 text_at(X, S) ->
     text_at(X, 0, S).
 
diff --git a/src/wings_pref_dlg.erl b/src/wings_pref_dlg.erl
index 2d458d7..e560430 100644
--- a/src/wings_pref_dlg.erl
+++ b/src/wings_pref_dlg.erl
@@ -666,8 +666,6 @@ smart_set_value_1(Key, Val, St) ->
 		          delayed_set_value(Key, OldVal, Val),
 		          wings_u:message(?__(5,"The language change will take effect\nthe next time Wings 3D is started."));
 		      _ ->
-		          ets:delete_all_objects(system_font),
-		          ets:delete_all_objects(console_font),
 		          wings_lang:load_language(Val)
 		    end;
 		polygon_offset_f ->
diff --git a/src/wings_text.erl b/src/wings_text.erl
index e1be5ba..645fa24 100644
--- a/src/wings_text.erl
+++ b/src/wings_text.erl
@@ -3,7 +3,7 @@
 %%
 %%     Text and font support.
 %%
-%%  Copyright (c) 2001-2011 Bjorn Gustavsson
+%%  Copyright (c) 2001-2013 Bjorn Gustavsson
 %%
 %%  See the file "license.terms" for information on usage and redistribution
 %%  of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -13,9 +13,9 @@
 
 -module(wings_text).
 -export([init/0,resize/0,width/0,width/1,height/0,draw/1,char/1,bold/1]).
+-export([font_cw_lh/1]).
 -export([break_lines/2]).
 -export([fonts/0]).
--export([current_font/0]).
 
 -define(NEED_ESDL, 1).
 -define(NEED_OPENGL, 1).
@@ -25,13 +25,16 @@
 -import(lists, [reverse/1,foreach/2]).
 
 init() ->
-    wings_pref:set_default(new_system_font, '7x14'),
-    wings_pref:set_default(new_console_font, 'fixed7x14'),
+    set_font_default(new_system_font),
+    set_font_default(new_console_font),
     ets:new(system_font, [named_table,ordered_set,public]),
     ets:new(console_font, [named_table,ordered_set,public]),
     ets:new(wings_fonts, [named_table,ordered_set,public]),
     load_fonts().
 
+set_font_default(PrefKey) ->
+    wings_pref:set_default(PrefKey, get_font_default(PrefKey)).
+
 resize() ->
     %% Force rebuild of display lists next time each font
     %% is needed.
@@ -64,31 +67,23 @@ width_1([C|Cs], W) ->
 width_1([], W) -> W.
 
 bold_string_width([C|S], W) ->
-    BCW = case wings_font_table:bold_char_width(C) of
-        undefined -> (current_font()):bold_char_width(C);
-        Other -> Other
-    end,
+    BCW = glyph_width(glyph_info(C)) + 1,
     bold_string_width(S, BCW+W);
 bold_string_width([], W) ->
     W.
 
 char_width(C) ->
-    case wings_font_table:char_width(C) of
-        undefined -> (current_font()):char_width(C);
-        Other -> Other
-    end.
+    glyph_width(glyph_info(C)).
 
 width() ->
-    case wings_font_table:char(char_width) of
-        undefined -> (current_font()):width();
-        Other -> Other
-    end.
+    glyph_info(char_width).
 
 height() ->
-    case wings_font_table:char(char_height) of
-        undefined -> (current_font()):height();
-        Other -> Other
-    end.
+    glyph_info(char_height).
+
+font_cw_lh(Font) ->
+    {glyph_info(Font, char_width),
+     glyph_info(Font, char_height)}.
 
 draw([{bold,S}|Cs]) ->
     bold(S),
@@ -109,41 +104,27 @@ draw([C|Cs]) ->
 draw([]) -> ok.
 
 char(C) when is_atom(C) -> special(C);
-char(C) ->
-    case wings_font_table:char(C) of
-        undefined -> (current_font()):char(C);
-        Other -> Other
-    end.
+char(C) -> draw_glyph(glyph_info(C)).
 
 bold([C|S]) ->
-    case wings_font_table:bold_char(C) of
-        undefined -> (current_font()):bold_char(C);
-        Other -> Other
-    end,
+    Glyph = glyph_info(C),
+    draw_glyph(Glyph),
+    Cw = glyph_width(Glyph),
+    gl:bitmap(1, 1, 0, 0, -Cw+1, 0, <<0>>),
+    draw_glyph(Glyph),
     bold(S);
 bold([]) -> ok.
 
-%% Table of characters already seen.
-%% Because the CJK fonts are HUGE (+30000 glyphs), I wrote a character
-%% accumulator. The reason for this is due to the nature of the ets, which when
-%% accessed, copies the requested data to the memory of the local process. With
-%% the smaller font libraries, this wasn't a problem, but with the CJK font for
-%% supporting Chinese, Japanese, and Korean - this became an issue.
-
 current_font() ->
     case wings_wm:this() of
 	none ->
-	    FontKey = wings_pref:get_value(new_system_font),
-	    ets:lookup_element(wings_fonts, FontKey, 2);
+	    system_font;
 	This ->
-	    FontKey = wings_wm:get_prop(This, font),
-	    ets:lookup_element(wings_fonts, FontKey, 2)
+	    wings_wm:get_prop(This, font)
     end.
-
+	    
 fonts() ->
-    MatchSpec = ets:fun2ms(fun({Key,_Font,Desc}) -> {Desc,Key} end),
-    ets:select(wings_fonts, MatchSpec).
-
+    [{Desc,Key} || {Key,Desc} <- ets:tab2list(wings_fonts)].
 
 %% Formats strings to fit the width of a line length given in PIXELS
 
@@ -227,6 +208,39 @@ string_to_text_box(#tb{text=[],line=Line,res=Res0}=Tb) ->
 reverse_list(A) when length(A) < 2 -> A;
 reverse_list(A) -> reverse(A).
 
+draw_glyph({W,H,Xorig,Yorig,Xmove,B}) -> 
+    gl:bitmap(W, H, Xorig, Yorig, Xmove, 0, B).
+
+glyph_width({_,_,_,_,Xmove,_}) -> Xmove.
+
+glyph_info(C) ->
+    glyph_info(current_font(), C).
+
+glyph_info(Font, C) ->
+    case ets:lookup(Font, C) of
+	[] when is_integer(C), C > 0 ->
+	    %% Undefined character. Return a filled box.
+	    [{char_width,Width}] = ets:lookup(Font, char_width),
+	    [{char_height,Height}] = ets:lookup(Font, char_height),
+	    NumBytes = ((Width+7) div 8) * Height,
+	    B = <<(-1):NumBytes/unit:8>>,
+	    {Width,Height,0,0,Width+1,B};
+	[{C,Bitmap}] ->
+	    %% Bitmap ready for display.
+	    Bitmap;
+	[{C,W,H,Xorig,Yorig,Xmove,Offset}] ->
+	    %% Raw valid character. We will need to extract a sub-binary
+	    %% from the binary of all fonts, and write back the result
+	    %% to the ets table to speed up the next access to this
+	    %% character.
+	    [{bitmap,Bitmaps}] = ets:lookup(Font, bitmap),
+	    NumBytes = ((W+7) div 8)*H,
+	    <<_:Offset/binary,B:NumBytes/binary,_/binary>> = Bitmaps,
+	    Bitmap = {W,H,Xorig,Yorig,Xmove,B},
+	    ets:insert(Font, {C,Bitmap}),
+	    Bitmap
+    end.
+
 %%%
 %%% Special characters.
 %%%
@@ -466,52 +480,40 @@ caret() ->
 %%%
 
 load_fonts() ->
-    SystemFont = wings_pref:get_value(new_system_font),
-    ConsoleFont = wings_pref:get_value(new_console_font),
+    Wc = font_file("*"),
+    Fonts = [begin
+		 FontNameStr = filename:basename(F, ".wingsfont"),
+		 FontNameAtom = list_to_atom(FontNameStr),
+		 {FontNameAtom,FontNameStr}
+	     end || F <- filelib:wildcard(Wc)],
+    ets:insert(wings_fonts, Fonts),
+    load_font(system_font),
+    load_font(console_font).
+
+load_font(FontTab) ->
+    PrefKey = list_to_atom(lists:concat(["new_",FontTab])),
+    FontName = wings_pref:get_value(PrefKey),
+    FontFile0 = font_file(FontName),
+    FontFile = case filelib:is_file(FontFile0) of
+		   true ->
+		       FontFile0;
+		   false ->
+		       DefFont = get_font_default(PrefKey),
+		       wings_pref:set_value(PrefKey, DefFont),
+		       font_file(DefFont)
+	       end,
+    {ok,Bin} = file:read_file(FontFile),
+    {wings_font,?wings_version,Font} = binary_to_term(Bin),
+    {_Key,_Desc,Width,Height,GlyphInfo,Bitmaps} = Font,
+    ets:insert(FontTab, GlyphInfo),
+    ets:insert(FontTab, [{char_width,Width},
+			 {char_height,Height},
+			 {bitmap,Bitmaps}|GlyphInfo]).
+
+font_file(FontName) ->
     WingsDir = wings_util:lib_dir(wings),
-    WF = ".wingsfont",
-    SFont = filename:join([WingsDir,"fonts",atom_to_list(SystemFont)++WF]),
-    CFont = filename:join([WingsDir,"fonts",atom_to_list(ConsoleFont)++WF]),
-    %% Make sure font is available, otherwise load default font
-    System = case filelib:is_file(SFont) of
-        true -> SystemFont;
-        false ->
-            wings_pref:set_value(new_system_font, '7x14'),
-            '7x14'
-    end,
-    Console = case filelib:is_file(CFont) of
-        true -> ConsoleFont;
-        false ->
-            wings_pref:set_value(new_console_font, 'fixed7x14'),
-            'fixed7x14'
-    end,
-    Wc = filename:join([WingsDir,"fonts","*.wingsfont"]),
-    Fonts = filelib:wildcard(Wc),
-    foreach(fun(F) ->
-        load_font(System, Console, F)
-    end, Fonts).
-
-load_font(SystemFont, ConsoleFont, FontDir) ->
-    FontNameStr = filename:basename(FontDir, ".wingsfont"),
-    FontNameAtom = list_to_atom(FontNameStr),
-    case FontNameAtom of
-        SystemFont -> load_font_0(FontDir);
-        ConsoleFont -> load_font_0(FontDir);
-        _other -> ets:insert(wings_fonts, {FontNameAtom,ok,FontNameStr})
-    end.
+    FontFileBase = lists:concat([FontName,".wingsfont"]),
+    filename:join([WingsDir,"fonts",FontFileBase]).
 
-load_font_0(FontDir) ->
-    {ok,Bin} = file:read_file(FontDir),
-    Font = binary_to_term(Bin),
-    Mod = load_font_1(Font),
-    Key = Mod:key(),
-    Desc = Mod:desc(),
-    ets:insert(wings_fonts, {Key,Mod,Desc}).
-
-load_font_1({wings_font,?wings_version,Font}) ->
-    load_font_2(Font).
-
-load_font_2({Key,Desc,Width,Height,GlyphInfo,Bitmaps}) ->
-    T = ets:new(font, [set,public]),
-    ets:insert(T, GlyphInfo),
-    wings__font:new(Key, Desc, Width, Height, T, Bitmaps).
+get_font_default(new_system_font) -> '7x14';
+get_font_default(new_console_font) -> 'fixed7x14'.
diff --git a/src/wings_wm.erl b/src/wings_wm.erl
index 6becc49..503a035 100644
--- a/src/wings_wm.erl
+++ b/src/wings_wm.erl
@@ -211,7 +211,7 @@ new(Name, {X,Y,Z0}, {W,H}, Op) when is_integer(X), is_integer(Y),
 				    is_integer(W), is_integer(H) ->
     Z = new_resolve_z(Z0),
     Stk = handle_response(Op, dummy_event, default_stack(Name)),
-    Props = gb_trees:from_orddict([{font,wings_pref:get_value(new_system_font)}]),
+    Props = gb_trees:from_orddict([{font,system_font}]),
     Win = #win{x=X,y=Y,z=Z,w=W,h=H,name=Name,stk=Stk,props=Props},
     put(wm_windows, gb_trees:insert(Name, Win, get(wm_windows))),
     dirty().
-- 
1.8.1.4