1. Philipp Gesang
  2. context-stellen

Commits

Philipp Gesang  committed 3568dc7

[fitbox] adaptational font size

  • Participants
  • Parent commits 8c3cb5b
  • Branches default

Comments (0)

Files changed (3)

File testfile.tex

View file
 \showframe
 \setuplayout[page]
 
-\setupwhitespace[none]
-
 \setupbodyfont[10pt]
 
 \setupwhitespace[none]
 
 \usemodule[bibelstellen]
 
+%······································································%
 %% English
+%······································································%
 % columns, rows -> Number of columns (x -- horizontal) and rows (y -- vertical).
 % headstyle     -> Font for passage heading.
 % head          -> Which field to use as passage heading.
 % frame         -> Show separating rules (may be useful for cutting).
 % inbetween     -> Whitespace between heading and text, default:
 %                  “\blank[small]”.
-
+%······································································%
+%                      font size adaptation mode
+%                             EXPERIMENTAL
+%······································································%
+% adapt         -> [yes|no] enables adaptation
+% minfontsize   -> lower font size limit for adaptation
+% fontsize      -> start adaptation at this font size
+% fontstep      -> decrement by this measure
+%······································································%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%······································································%
 %% German
+%······································································%
 % columns, rows -> Anzahl von Spalten (x) und Zeilen (y)
 % headstyle     -> Font switch für die Stellenangabe
 % head          -> Werte: "sigle" oder "stelle": Feld für die
 % frame         -> "on" oder "off", Anzeigen der Hilfslinien
 % inbetween     -> Befehl für den vertikalen Abstand zwischen
 %                  Sigle und Text, default: "\blank[small]"
+%······································································%
+%                 automatische Schriftgradanpassung
+%                             KEINE GEWÄHR
+%······································································%
+% adapt         -> [yes|no] schaltet Anpassung an bzw. aus
+% minfontsize   -> untere Grenze für Anpassung
+% fontsize      -> obere Grenze für Anpassung
+% fontstep      -> Differenz zwischen Anpassungsversuchen
+%······································································%
 
 %% Example 1
 %\setupstellen[columns=2,rows=6,headstyle=\sc,bodystyle=\tf,head=stelle] % default
 %]
 
 %% Example 4
-\setupstellen[
-  columns=3,
-  rows=4,
-  head=sigle,
-  longheadstyle={\setupbodyfont[9pt]\sc},
-  longbodystyle={\setupbodyfont[7pt]},
-  headstyle={\setupbodyfont[12pt]\sc},
-  bodystyle={\setupbodyfont[10pt]\tf},
-  frameoffset=1em,
-  frameoffset=8mm,
-  frame=on,
-]
+% \setupstellen[
+%   columns=3,
+%   rows=4,
+%   head=sigle,
+%   longheadstyle={\setupbodyfont[9pt]\sc},
+%   longbodystyle={\setupbodyfont[7pt]},
+%   headstyle={\setupbodyfont[12pt]\sc},
+%   bodystyle={\setupbodyfont[10pt]\tf},
+%   frameoffset=1em,
+%   frameoffset=8mm,
+%   frame=on,
+% ]
 
 %% Example 5
 %\setupstellen[%
   %inbetween=,
 %]
 
+%% Example 6
+\setupstellen[
+  columns=3,
+  rows=4,
+  head=sigle,
+  headstyle=\sc,
+  bodystyle=\italic,
+  % headstyle=,
+  % bodystyle=,
+  frameoffset=1em,
+  frameoffset=8mm,
+  frame=on,
+  adapt=yes,
+  minfontsize=6pt,
+  fontsize=24pt,
+  fontstep=1pt,
+  % adapt=no,
+  verbose=yes,
+]
+
 %% Some reasonable setup, add as many as you like.
 \definefontfeature [oldstyle][default][mode=node,script=latn,onum=yes]
 \unexpanded\def\os{\setfontfeature{oldstyle}}
 % Das erste Argument ist der Dateiname der Stellen-Datenbank.
 
 %\typesetstellen[beispiel.txt,beispiel2.txt]{dummy1,dummy3}
-\typesetstellen[dummyfile.txt]{dummy2,dummy4}
+% \typesetstellen[dummyfile.txt]{dummy2,dummy4}
+\typesetstellen[dummyfile.txt]{}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \stoptext

File tex/context/third/bstellen/bibelstellen.lua

View file
 --  DESCRIPTION:  typeset bible quotations automagically
 -- REQUIREMENTS:  context mkiv
 --       AUTHOR:  Philipp Gesang (Phg), <megas.kapaneus@gmail.com>
---      VERSION:  hg tip, rev21+
+--      VERSION:  hg tip, rev23+
 --     MODIFIED:  2012-06-02 15:04:40+0200
 ------------------------------------------------------------------------
 --
   = lpeg.C, lpeg.Cf, lpeg.Cg, lpeg.Cs, lpeg.Ct
 local lpegmatch         = lpeg.match
 
-local contextframed       = context.framed
+local contextstellenframe = context.stellenframe
+local contextfitbox       = context.fitbox
 local contextpage         = context.page
 local contextpar          = context.par
 local contextbgroup       = context.bgroup
 local iowrite       = io.write
 local stringexplode = string.explode
 local stringfind    = string.find
+local stringformat  = string.format
 local stringmatch   = string.match
 local stringsub     = string.sub
 local utflower      = unicode.utf8.lower
 
-local warn = function (...)
-    if verbose then
-        local args = { ... }
-        iowrite("*t-bs*>")
-        for i=1, #args do
-            iowrite(" " .. args[i])
-        end
-        iowrite"\n"
-    end
-    return 0
-end
-
 local td
 if context then
     thirddata = thirddata or { }
     td = { }
 end
 
+
 --td.stellen.escape = function (str)
 --    return str:gsub("\\","\\\\")
 --end
 td.stellen.parameters   = { }
 td.stellen.warn         = warn
 
+td.stellen.parameters.verbose = verbose
+local warn = function (...)
+    if td.stellen.parameters.verbose then
+        local args = { ... }
+        iowrite("*t-bs*>")
+        for i=1, #args do
+            iowrite(" " .. args[i])
+        end
+        iowrite"\n"
+    end
+    return 0
+end
+
 ------------------------------------------------------------------------
 -- aux functions
 ------------------------------------------------------------------------
     return nil
 end
 
+td.stellen.truth = { -- boolean switches are translated for convenience
+    yes =  true, good =  true, ok   =  true, asyouwish =  true,  ["true"] =  true,
+    no  = false, nope = false, njet = false, dont      = false, ["false"] = false,
+}
+
 ------------------------------------------------------------------------
 -- directives, for postprocessing
 ------------------------------------------------------------------------
 -- typesetting routines
 ------------------------------------------------------------------------
 
+local f_adapted = [[{%s %s}\endgraf%s{%s %s}]]
+local do_do_adapt = function (parms, entry)
+    local thishead = entry[parms.head].value
+    local thisbody = entry.text.value
+    local thisheadstyle = parms.headstyle
+    local thisbodystyle = parms.bodystyle
+    return stringformat(f_adapted,
+                        thisheadstyle,
+                        thishead,
+                        parms.inbetween,
+                        thisbodystyle,
+                        thisbody)
+end
+
+local do_adapt = function (entry)
+    local tdsp = td.stellen.parameters
+    contextfitbox(
+        --{ height = tdsp.boxheight .. "sp", }, 
+        do_do_adapt(tdsp, entry)
+    )
+    return 0
+end
+
 local do_do_one = function (parms, entry)
     local thishead = entry[parms.head].value
     local thisheadstyle = entry[parms.head].long and parms.longheadstyle or parms.headstyle
 
 local do_one = function (entry)
     local tdsp = td.stellen.parameters
-    contextframed( {
-            frame        = "off",
-            topframe     = "off",
-            bottomframe  = tdsp.frame,
-            leftframe    = tdsp.frame,
-            rightframe   = tdsp.frame,
-            width        = "\\hsize",
-            height       = td.stellen.parameters.boxheight .. "sp",
-            align        = "lohi", --"right",
-            loffset      = tdsp.foffset,
-            roffset      = tdsp.foffset,
-        }, 
+    contextstellenframe(
+        { height = tdsp.boxheight .. "sp", }, 
         function ()
                 do_do_one(tdsp, entry)
             return ""
     return 0
 end
 
-local by_category = function (cat)
-    local cats   = { }
-    local result = { }
-    local data   = td.stellen.data
-    for _, cat in next,stringexplode(cat, ",") do
-        cats[#cats+1] = stringstrip(cat)
+local by_category = function (raw)
+    local cats    = { }
+    local result  = { }
+    local data    = td.stellen.data
+    local rawcats = stringexplode(raw, ",")
+    local any     = false
+    if #rawcats == 1 and rawcats[1] == "" then
+        any = true
+    else
+        for _, cat in next,rawcats do
+            cats[#cats+1] = stringstrip(cat)
+        end
     end
     local ncats = #cats
     for i=1, #data do
         local entry = data[i]
         local keys  = entry["schlüssel"]
-        for i=1, ncats do
-            if keys[cats[i]] == true then
-                --table.print(entry)
-                result[#result+1] = entry
-                break
+        if any then
+            result[#result+1] = entry
+        else
+            for i=1, ncats do
+                if keys[cats[i]] == true then
+                    --table.print(entry)
+                    result[#result+1] = entry
+                    break
+                end
             end
         end
     end
     --table.print(tdsk)
     --table.print(tdsp)
     --table.print(job)
-    warn("processing categories:", categories)
+    warn("processing categories:", categories ~= "" and categories or " all")
     warn("total entries selected:", #job)
     contextstartcolumns({
         n        = tdsp.columns,
         elseif cnt > 1 and cnt % 6 == tdsp.rows then
             contextpar()
         end
-        do_one(entry)
+        if tdsp.adapt == true then
+            do_adapt(entry)
+        else
+            do_one(entry)
+        end
         cnt       = cnt + 1
     end
     contextstopcolumns()

File tex/context/third/bstellen/t-bibelstellen.mkiv

View file
 %D \module [
 %D         file=t-bibelstellen,
-%D      version=hg-r20+ 2012-04-30 18:19:04+0200,
+%D      version=hg-r23+ 2012-06-02 20:29:30+0200,
 %D        title=\CONTEXT\ User Module,
 %D       author=Philipp Gesang,
 %D         date=\currentdate,
 
 \unprotect
 
-\definenamespace [BS] [
+\definenamespace [bstellen] [
   command=no,
   comment=typeset snippets from reference works using KISS markup,
   name=\v!bstellen,
 
 \ctxlua{if not thirddata.stellen then os.exit() end}
 
+\newconditional\fitbox_verbose
+
+%······································································%
+%                         setups macros
+%······································································%
 \def\setupstellen[#1]{%
-  \setupbstellen[#1]%
+  \setupbstellen[#1]% hackish but works
   \setuppapersize[\bstellenparameter{paper},landscape][\bstellenparameter{paper},landscape]%
   \startluacode
     local td = thirddata or {}
     local tdsp = td.stellen.parameters
-    tdsp.columns   = tonumber("\bstellenparameter{columns}")
-    tdsp.rows      = tonumber("\bstellenparameter{rows}")
-    tdsp.headstyle = "\luaescapestring{\bstellenparameter{headstyle}}"
-    tdsp.bodystyle = "\luaescapestring{\bstellenparameter{bodystyle}}"
-    tdsp.head      = "\bstellenparameter{head}"
-    tdsp.frame     = "\bstellenparameter{frame}"
-    tdsp.foffset   = "\bstellenparameter{frameoffset}"
-    tdsp.inbetween = "\luaescapestring{\bstellenparameter{inbetween}}"
-    tdsp.boxheight = tex.vsize / td.stellen.parameters.rows
+    tdsp.columns   = tonumber(\!!bs\number\bstellenparameter{columns}\!!es)
+    tdsp.rows      = tonumber(\!!bs\number\bstellenparameter{rows}\!!es)
+    tdsp.headstyle = \!!bs\bstellenparameter{headstyle}\!!es
+    tdsp.bodystyle = \!!bs\bstellenparameter{bodystyle}\!!es
+    tdsp.head      = \!!bs\bstellenparameter{head}\!!es
+    tdsp.frame     = \!!bs\bstellenparameter{frame}\!!es
+    tdsp.foffset   = \!!bs\bstellenparameter{frameoffset}\!!es
+    tdsp.inbetween = \!!bs\bstellenparameter{inbetween}\!!es
+    tdsp.adapt     = td.stellen.truth[ \!!bs\bstellenparameter{adapt}\!!es ]
+    tdsp.verbose   = td.stellen.truth[ \!!bs\bstellenparameter{verbose}\!!es ]
+    tdsp.boxheight = tex.vsize / tdsp.rows
   \stopluacode
-%
   \doifsomethingelse{\bstellenparameter{longheadstyle}}
-    {\ctxlua{thirddata.stellen.parameters.longheadstyle = "\luaescapestring{\bstellenparameter{longheadstyle}}"}}
-    {\ctxlua{thirddata.stellen.parameters.longheadstyle = "\luaescapestring{\bstellenparameter{headstyle}}"}}
+    {\ctxlua{thirddata.stellen.parameters.longheadstyle = \!!bs\bstellenparameter{longheadstyle}\!!es}}
+    {\ctxlua{thirddata.stellen.parameters.longheadstyle = \!!bs\bstellenparameter{headstyle}\!!es}}
   \doifsomethingelse{\bstellenparameter{longbodystyle}}
-    {\ctxlua{thirddata.stellen.parameters.longbodystyle = "\luaescapestring{\bstellenparameter{longbodystyle}}"}}
-    {\ctxlua{thirddata.stellen.parameters.longbodystyle = "\luaescapestring{\bstellenparameter{bodystyle}}"}}
+    {\ctxlua{thirddata.stellen.parameters.longbodystyle = \!!bs\bstellenparameter{longbodystyle}\!!es}}
+    {\ctxlua{thirddata.stellen.parameters.longbodystyle = \!!bs\bstellenparameter{bodystyle}\!!es}}
 }
 
 %\def\dosetupstellen{\dosingleargument\getparameters[BS]}
 
+%······································································%
+%                     fitbox (experimental)
+%······································································%
+\def\fit_dbg#1{%
+  \ifconditional\fitbox_verbose
+    \writestatus{fitbox}{#1}%
+  \fi%
+}
+
+\newdimen\normal_fontsize
+\newdimen\min_fontsize
+\newdimen\decrease_step
+\newdimen\fitbox_targetht
+
+\def\do_prepare_bodyfont_definitions{%
+  \fit_dbg{defining bodyfont size \the\current_fontsize}%
+  \definebodyfont[\the\current_fontsize][rm][default]%
+  \advance\current_fontsize by-\decrease_step
+  \ifdim\current_fontsize>\min_fontsize
+    \do_prepare_bodyfont_definitions
+  \fi%
+}
+
+\def\prepare_bodyfont_definitions{%
+  \fit_dbg{defining font sizes from \the\normal_fontsize\space to \the\min_fontsize}%
+    \newdimen\current_fontsize
+    \current_fontsize\dimexpr(\normal_fontsize)%
+    \do_prepare_bodyfont_definitions
+  \let\current_fontsize      \relax
+}
+
+\appendtoks
+  \doifelse{\bstellenparameter{verbose}}\v!yes
+    {\settrue\fitbox_verbose}
+    {\setfalse\fitbox_verbose}
+  \decrease_step  =\bstellenparameter{fontstep}
+  \normal_fontsize=\bstellenparameter{fontsize}
+  \min_fontsize   =\bstellenparameter{minfontsize}
+  \prepare_bodyfont_definitions
+  \fitbox_targetht=\dimexpr(\vsize / \bstellenparameter{rows})\relax
+\to \everysetupbstellen
+
+\def\set_fit_box_interline_space{%
+  \newdimen\scratchdimen \scratchdimen\dimexpr(\current_fontsize*6/5)\relax
+  \setuplocalinterlinespace[\the\scratchdimen]%
+}
+
+\def\do_do_do_fit_box{%
+  \stellenframe[height=\fitbox_targetht]{%
+    \switchtobodyfont[\the\current_fontsize]%
+    \set_fit_box_interline_space
+    \current_content
+    \par%
+  }%
+}
+
+\def\do_do_fit_box{%
+  \setbox\scratchbox\vbox{%
+    \stellenframe{%
+      \set_fit_box_interline_space
+      \switchtobodyfont[\the\current_fontsize]%
+      \current_content
+      \par%
+    }%
+  }%
+  \fit_dbg{box height = \the\ht\scratchbox;    goal      = \the\fitbox_targetht}%
+  \fit_dbg{font size  = \the\current_fontsize; threshold = \the\min_fontsize}%
+  \ifdim\ht\scratchbox>\fitbox_targetht
+    \advance\current_fontsize by-\decrease_step
+    \fit_dbg{font size reduced to \the\current_fontsize}%
+    \ifdim\current_fontsize>\min_fontsize
+      \advance\recurse_level by 1\relax
+      \fit_dbg{result too high; recursing (\the\recurse_level)}%
+      \do_do_fit_box
+    \else
+      \fit_dbg{content too big, can’t fit it to \the\fitbox_targetht}%
+      %% flush anyways
+      \do_do_do_fit_box
+    \fi
+  \else
+    \fit_dbg{final font size: \the\current_fontsize}%
+    %% optimal size reached
+    \do_do_do_fit_box
+  \fi%
+}
+
+\def\do_fitbox[#1]#2{%
+  \setupframed[stellenframe][#1]%
+  \newdimen\current_fontsize
+  \current_fontsize\dimexpr(\normal_fontsize)%
+  \def\current_content{#2}%
+  \do_do_fit_box%
+  \let\current_fontsize\relax
+  \let\recurse_level\relax
+}
+
+\def\fitbox{%
+  \fit_dbg{===== new fitbox =====================================}%
+  \newcount \recurse_level \recurse_level=0
+  \dontcomplain
+  \dosingleempty\do_fitbox%
+}
+
+%······································································%
+%                       auxiliary macros
+%······································································%
+
+\defineframed[stellenframe][
+        frame=off,
+     topframe=off,
+  bottomframe=off,
+    leftframe=off,
+   rightframe=off,
+        width=\hsize,
+        align=lohi,
+]
+
+% \def\calc_stellenframe_ht{%
+%   \dimexpr(\vsize/\bstellenparameter{rows})\relax%
+% }
+
+\appendtoks
+  % \calc_stellenframe_ht
+  \setupframed[stellenframe][
+    bottomframe=\bstellenparameter{frame},
+     rightframe=\bstellenparameter{frame},
+        loffset=\bstellenparameter{frameoffset},
+        roffset=\bstellenparameter{frameoffset},
+        toffset=\bstellenparameter{frameoffset},
+        boffset=\bstellenparameter{frameoffset},
+        % height=\dimexpr(\vsize/\bstellenparameter{rows})\relax,
+        % height=\calc_stellenframe_ht,
+  ]
+\to \everysetupbstellen
+
+%······································································%
+%                            defaults
+%······································································%
+
 \setupbstellen[
-      bodystyle=\tf,              % any style switch
+      bodystyle=,                 % any style switch
         columns=2,
            file=\jobname.txt,
           frame=off,
            head=stelle,           % sigle|stelle
       headstyle=\sc,              % any style switch
       inbetween={\blank[small]},
-% longbodystyle={\tfx},
-% longheadstyle={\tfx\sc},
+  longbodystyle=\bstellenparameter{bodystyle},
+  longheadstyle=\bstellenparameter{headstyle},
           paper=A4,
            rows=6,
+          adapt=no,
+    minfontsize=6pt,
+       fontsize=16pt,
+       fontstep=1pt,
 ]
 
 \def\typesetstellen[#1]#2{%
   \iffirstargument
-    \edef\BSfile{#1}
+    \edef\stellen_file{#1}
   \else
-    \edef\BSfile{\bstellenparameter{file}}
+    \edef\stellen_file{\bstellenparameter{file}}
   \fi
-  \ctxlua{thirddata.stellen.typeset("\BSfile", "#2")}%
+  \ctxlua{thirddata.stellen.typeset("\stellen_file", "#2")}%
 }
 
 \protect \stopmodule \endinput