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