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