commit 28fff1f37b4eb8ab8833bda83f64581216c13ba1 Author: baldeau Date: Tue Feb 13 15:22:59 2024 +0100 initial diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5cbca32 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0881880 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +out/ +mermaid-filter.err +_minted-input/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..301d8ad --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "folder-path-color.folders": [ + { "path": "chapters/01", "symbol": "SR", "tooltip": "Source files" }, + { "path": "chapters/02", "symbol": "T", "tooltip": "Common" }, + { "path": "chapters/03", "symbol": "T", "tooltip": "Common" }, + { "path": "chapters/04", "symbol": "T", "tooltip": "Common" }, + { "path": "chapters/05", "symbol": "T", "tooltip": "Common" }, + { "path": "chapters/06", "symbol": "T", "tooltip": "Common" }, + { "path": "chapters/07", "symbol": "T", "tooltip": "Common" }, + ] +} \ No newline at end of file diff --git a/Bachelor.bib b/Bachelor.bib new file mode 100644 index 0000000..e382bdc --- /dev/null +++ b/Bachelor.bib @@ -0,0 +1,37 @@ +@online{bizzottoComparisonPopularFlutter2023, + title = {A {{Comparison}} of {{Popular Flutter App Architectures}}}, + author = {Bizzotto, Andrea}, + date = {2023-09-01}, + url = {https://codewithandrea.com/articles/comparison-flutter-app-architectures/}, + urldate = {2023-11-19}, + abstract = {Comparing my Riverpod App Architecture with other popular ones such as MVC, MVVM, Bloc, Stacked, Clean Architecture, and Android App Architecture.}, + langid = {english}, + organization = {{Code With Andrea}}, + file = {/Users/fabian/Zotero/storage/DUDXBAGD/comparison-flutter-app-architectures.html} +} + +@online{FlutterArchitecturalOverviewb, + title = {Flutter Architectural Overview}, + url = {https://docs.flutter.dev/resources/architectural-overview}, + urldate = {2024-02-12}, + abstract = {A high-level overview of the architecture of Flutter, including the core principles and concepts that form its design.}, + langid = {english}, + file = {/Users/fabian/Zotero/storage/W67CJYBZ/architectural-overview.html} +} + +@article{weiserComputer21stCentury1999, + title = {The Computer for the 21st Century}, + author = {Weiser, Mark}, + date = {1999-07-01}, + journaltitle = {ACM SIGMOBILE Mobile Computing and Communications Review}, + shortjournal = {SIGMOBILE Mob. Comput. Commun. Rev.}, + volume = {3}, + number = {3}, + pages = {3--11}, + issn = {1559-1662}, + doi = {10.1145/329124.329126}, + url = {https://dl.acm.org/doi/10.1145/329124.329126}, + urldate = {2023-11-14}, + abstract = {Specialized elements of hardware and software, connected by wires, radio waves and infrared, will be so ubiquitous that no one will notice their presence.}, + file = {/Users/fabian/Zotero/storage/8CCSE83J/Weiser - 1999 - The computer for the 21st century.pdf} +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4fd4e95 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +SHELL:=/bin/bash +MARKDOWN_FILES := $(shell find chapters -type f -name "*.md" | sort | tr '\n' ' ') +BACHELOR_TEXT := @cat $(MARKDOWN_FILES) + +all: local + +help: + @echo "Please choose an option!" + @echo "- Create pdf: make pdf" + +dir: + mkdir -p out + +bachelor: @cat $(MARKDOWN_FILES) + +local: dir + @echo "Building paper" + MERMAID_FILTER_FORMAT=pdf pandoc -V colorlinks=true -V linkcolor=black -V urlcolor=black -f 'markdown+autolink_bare_uris' --pdf-engine=lualatex --pdf-engine-opt=-shell-escape --filter mermaid-filter --lua-filter columns.lua --citeproc -s $(MARKDOWN_FILES) -o ./out/bachelor.pdf -V lang=de-DE -V fontsize=11pt --highlight-style tango --reference-links --bibliography Bachelor.bib --csl=harvard-right.csl -M lang:de --number-sections + +clean: + rm -rf out diff --git a/assets/.DS_Store b/assets/.DS_Store new file mode 100644 index 0000000..ea09623 Binary files /dev/null and b/assets/.DS_Store differ diff --git a/assets/skizzen/dashgame.png b/assets/skizzen/dashgame.png new file mode 100644 index 0000000..36b5701 Binary files /dev/null and b/assets/skizzen/dashgame.png differ diff --git a/assets/skizzen/einstellungen.png b/assets/skizzen/einstellungen.png new file mode 100644 index 0000000..3eabb76 Binary files /dev/null and b/assets/skizzen/einstellungen.png differ diff --git a/assets/skizzen/home.png b/assets/skizzen/home.png new file mode 100644 index 0000000..673de63 Binary files /dev/null and b/assets/skizzen/home.png differ diff --git a/assets/skizzen/led.png b/assets/skizzen/led.png new file mode 100644 index 0000000..f0a6333 Binary files /dev/null and b/assets/skizzen/led.png differ diff --git a/assets/skizzen/materialWidgets.png b/assets/skizzen/materialWidgets.png new file mode 100644 index 0000000..eaf354f Binary files /dev/null and b/assets/skizzen/materialWidgets.png differ diff --git a/assets/skizzen/matrix.png b/assets/skizzen/matrix.png new file mode 100644 index 0000000..95b255f Binary files /dev/null and b/assets/skizzen/matrix.png differ diff --git a/assets/skizzen/openapi.png b/assets/skizzen/openapi.png new file mode 100644 index 0000000..e6f335d Binary files /dev/null and b/assets/skizzen/openapi.png differ diff --git a/assets/skizzen/openstreetmap.png b/assets/skizzen/openstreetmap.png new file mode 100644 index 0000000..4a51e4a Binary files /dev/null and b/assets/skizzen/openstreetmap.png differ diff --git a/assets/skizzen/redled.jpg b/assets/skizzen/redled.jpg new file mode 100644 index 0000000..df7a0d1 Binary files /dev/null and b/assets/skizzen/redled.jpg differ diff --git a/assets/skizzen/sparkfun.jpg b/assets/skizzen/sparkfun.jpg new file mode 100644 index 0000000..38d1ab7 Binary files /dev/null and b/assets/skizzen/sparkfun.jpg differ diff --git a/assets/skizzen/systeminfo.png b/assets/skizzen/systeminfo.png new file mode 100644 index 0000000..272f0ca Binary files /dev/null and b/assets/skizzen/systeminfo.png differ diff --git a/assets/skizzen/video.png b/assets/skizzen/video.png new file mode 100644 index 0000000..e6b7c18 Binary files /dev/null and b/assets/skizzen/video.png differ diff --git a/chapters/.DS_Store b/chapters/.DS_Store new file mode 100644 index 0000000..8c655af Binary files /dev/null and b/chapters/.DS_Store differ diff --git a/chapters/00_pandoc/00_pandoc.md b/chapters/00_pandoc/00_pandoc.md new file mode 100644 index 0000000..2bf7b0c --- /dev/null +++ b/chapters/00_pandoc/00_pandoc.md @@ -0,0 +1,79 @@ +--- +header-includes: | + \usepackage[T1]{fontenc} + \usepackage[usefilenames,RMstyle={Text,Semibold},SSstyle={Text,Semibold},TTstyle={Text,Semibold},DefaultFeatures={Ligatures=Common}]{plex-otf} + \usepackage[a4paper,bindingoffset=0.2in,% + left=4cm,right=2cm,top=2cm,bottom=2cm,% + footskip=.25in]{geometry} + \usepackage{fancyhdr} + \usepackage[utf8]{inputenc} + \usepackage{tikz} + \usetikzlibrary{snakes,arrows,shapes} + \usepackage{amsmath} + \usepackage{pgfplots} + \usepackage{pgfplotstable} + \pgfplotsset{compat=1.8} + \usepackage{multicol,lipsum} + \usepackage{listings} + \usepackage{wrapfig} + \usepackage[font=small,labelfont=bf]{caption} + \usepackage{graphicx} + \usepackage{xcolor,stackengine} + \usepackage{colortbl} + \usepackage{tcolorbox} + \usepackage{lastpage} + \usepackage{subcaption} + \usepackage{tabularx} + \usepackage{biblatex} + \usepackage{float} + \usepackage{refract} + \usepackage{svg} + \usepackage{setspace} + \usepackage{titling} + \usepackage{fvextra} + \usepackage{emoji} + \DefineVerbatimEnvironment{Highlighting}{Verbatim}{breaklines,commandchars=\\\{\}} + \newcommand{\hideFromPandoc}[1]{#1} + \hideFromPandoc{ + \let\Begin\begin + \let\End\end + } + \makeatletter + \def\fps@figure{h} + \makeatother +nocite: | + @* +--- + +\setstretch{1.5} + +\setemojifont{Twemoji Mozilla} + +\renewcommand{\familydefault}{\sfdefault} + +\graphicspath{ {./img/} } + +\overfullrule=0pt + +\newcolumntype{C}{>{\centering\arraybackslash}X} + +\renewcommand{\comment}[1]{\hspace{2em}{\small\textit{#1}}\bigskip\par} + +\newcommand\palbox[1]{{\sffamily\fboxsep=5pt\relax\fboxrule=1pt\relax\footnotesize% + \fcolorbox{gray!50}{gray!10}{% + \stackengine{4pt}{% + \colorbox[HTML]{#1}{\rule{30pt}{0pt}\rule{0pt}{30pt}}% +}{% +\color{black!60}\stackengine{6pt}{\##1}{\saycolors{#1}}{U}{l}{F}{F}{S}% +}{U}{l}{F}{F}{S}% +}% +}} +\newcommand\saycolors[1]{\relax} + +\lstset{ +basicstyle=\ttfamily, +columns=fullflexible, +frame=single, +breaklines=true, +postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space}, +} diff --git a/chapters/01_titel/00_titlepage.md b/chapters/01_titel/00_titlepage.md new file mode 100644 index 0000000..feacd26 --- /dev/null +++ b/chapters/01_titel/00_titlepage.md @@ -0,0 +1,32 @@ +\thispagestyle{empty} + +\begin{titlepage} +\begin{center} +\Large Hochschule Rhein-Waal \\ +\vspace{2.5cm} +\Large Proposal für die Bachelorarbeit \\ +\vspace{2.5cm} +\huge \textbf{\textsc{Flutter als Entwicklungsplattform für eingebettete Linux Systeme: eine Fallstudie}} \\ +\vspace{1.0cm} +\Large Fabian Baldeau \\ +\vspace{2.5cm} +\vspace{0.25cm} +\textsc{Studiengang}\\ +\vspace{0.25cm} +\textsc{Medieninformatik}\\ +\vspace{2.5cm} +\textsc{Gutachter}\\ +\vspace{0.25cm} +\textsc{Prof. Dr.-Ing. Ido Iurgel}\\ +\vspace{0.25cm} +\textsc{Prof. Dr. Kai Essig}\\ +\vspace{2cm} +\end{center} + +\end{titlepage} + +\pagenumbering{Roman} +\fancyhf{} +\fancyhead[C]{\thepage} +\renewcommand{\headrulewidth}{0pt} +\pagestyle{fancy} diff --git a/chapters/01_titel/01_abstract.md b/chapters/01_titel/01_abstract.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/01_titel/02_toc.md b/chapters/01_titel/02_toc.md new file mode 100644 index 0000000..b4245c6 --- /dev/null +++ b/chapters/01_titel/02_toc.md @@ -0,0 +1,23 @@ +\tableofcontents +\pagebreak + + + +\renewcommand{\headrulewidth}{0pt} + +\pagenumbering{arabic} + + + +\fancyhead[C]{} +\fancyfoot[R]{\thepage} diff --git a/chapters/02_einleitung/00_motivation_relevanz.md b/chapters/02_einleitung/00_motivation_relevanz.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/chapters/02_einleitung/00_motivation_relevanz.md @@ -0,0 +1 @@ + diff --git a/chapters/02_einleitung/01_zielsetzung.md b/chapters/02_einleitung/01_zielsetzung.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/02_einleitung/02_methodik.md b/chapters/02_einleitung/02_methodik.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/03_grundlagen/01_eLinux.md b/chapters/03_grundlagen/01_eLinux.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/03_grundlagen/02_raspberryPi.md b/chapters/03_grundlagen/02_raspberryPi.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/03_grundlagen/03_i2c_bus.md b/chapters/03_grundlagen/03_i2c_bus.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/03_grundlagen/04_spi_bus.md b/chapters/03_grundlagen/04_spi_bus.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/03_grundlagen/05_yocto_linux.md b/chapters/03_grundlagen/05_yocto_linux.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/03_grundlagen/06_flutter.md b/chapters/03_grundlagen/06_flutter.md new file mode 100644 index 0000000..ed97d61 --- /dev/null +++ b/chapters/03_grundlagen/06_flutter.md @@ -0,0 +1,25 @@ + + +# Flutter + +Was ist Flutter [@FlutterArchitecturalOverviewb] + +test [@weiserComputer21stCentury1999] + +```{#test .dart .number-lines caption="Example Dart test"} +import 'package:retry/retry.dart'; + +final response = await retry( + // Make a GET request + () => http.get('https://google.com').timeout(Duration(seconds: 5)), + // Retry on SocketException or TimeoutException + retryIf: (e) => e is SocketException || e is TimeoutException, +); +print(response.body); +``` + +Nice Dart highlighting! + +![](./assets/skizzen/led.png) + +WORKING :) diff --git a/chapters/04_stand_der_technik/04_01_stand_technik.md b/chapters/04_stand_der_technik/04_01_stand_technik.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/04_stand_der_technik/04_02_entwicklung_umsetzung.md b/chapters/04_stand_der_technik/04_02_entwicklung_umsetzung.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/05_yocto/.DS_Store b/chapters/05_yocto/.DS_Store new file mode 100644 index 0000000..8fd7d5d Binary files /dev/null and b/chapters/05_yocto/.DS_Store differ diff --git a/chapters/05_yocto/01_pi_image.md b/chapters/05_yocto/01_pi_image.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/05_yocto/02_meta_flutter.md b/chapters/05_yocto/02_meta_flutter.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/05_yocto/03_network_manager.md b/chapters/05_yocto/03_network_manager.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/05_yocto/04_hot_reload_embedder.md b/chapters/05_yocto/04_hot_reload_embedder.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/05_yocto/05_qemu_linux.md b/chapters/05_yocto/05_qemu_linux.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/.DS_Store b/chapters/06_flutter/.DS_Store new file mode 100644 index 0000000..dd57921 Binary files /dev/null and b/chapters/06_flutter/.DS_Store differ diff --git a/chapters/06_flutter/01_architecture.md b/chapters/06_flutter/01_architecture.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/02_home.md b/chapters/06_flutter/02_home.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/03_material_demo.md b/chapters/06_flutter/03_material_demo.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/04_liste.md b/chapters/06_flutter/04_liste.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/05_kartenansicht.md b/chapters/06_flutter/05_kartenansicht.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/06_einstellungen.md b/chapters/06_flutter/06_einstellungen.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/08_matrix.md b/chapters/06_flutter/08_matrix.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/09_video.md b/chapters/06_flutter/09_video.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/10_flame.md b/chapters/06_flutter/10_flame.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/06_flutter/led.md b/chapters/06_flutter/led.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/07_fazit/.DS_Store b/chapters/07_fazit/.DS_Store new file mode 100644 index 0000000..4f437d4 Binary files /dev/null and b/chapters/07_fazit/.DS_Store differ diff --git a/chapters/07_fazit/01_vergleich.md b/chapters/07_fazit/01_vergleich.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/07_fazit/02_bewertung.md b/chapters/07_fazit/02_bewertung.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/07_fazit/03_zusammenfassung_ausblick.md b/chapters/07_fazit/03_zusammenfassung_ausblick.md new file mode 100644 index 0000000..e69de29 diff --git a/chapters/08_literatur/00_literature.md b/chapters/08_literatur/00_literature.md new file mode 100644 index 0000000..8e4b4b1 --- /dev/null +++ b/chapters/08_literatur/00_literature.md @@ -0,0 +1,3 @@ +\pagebreak + +# Literaturverzeichnis diff --git a/columns.lua b/columns.lua new file mode 100644 index 0000000..d519ed9 --- /dev/null +++ b/columns.lua @@ -0,0 +1,941 @@ +--[[-- # Columns - multiple column support in Pandoc's markdown. + +This Lua filter provides support for multiple columns in +latex and html outputs. For details, see README.md. + +@author Julien Dutant +@copyright 2021 Julien Dutant +@license MIT - see LICENSE file for details. +@release 1.1.2 +]] + +-- # Version control +local required_version = '2.9.0' +local version_err_msg = "ERROR: pandoc >= " .. required_version + .. " required for columns filter" +-- pandoc 2.9 required for pandoc.List insert method +-- if PANDOC_VERSION == nil then -- if pandoc_version < 2.1 +-- error(version_err_msg) +-- elseif PANDOC_VERSION[2] < 9 then +-- error(version_err_msg) +-- else +-- PANDOC_VERSION:must_be_at_least(required_version, version_err_msg) +-- end +local utils = require('pandoc.utils') -- this is superfluous in Pandoc >= 2.7 I think + +-- # Internal settings + +-- target_formats filter is triggered when those formats are targeted +local target_formats = { + "html.*", + "latex", +} +local options = { + raggedcolumns = false, -- global ragged columns option +} + +-- # Helper functions + +--- type: pandoc-friendly type function +-- panbdoc.utils.type is only defined in Pandoc >= 2.17 +-- if it isn't, we extend Lua's type function to give the same values +-- as pandoc.utils.type on Meta objects: Inlines, Inline, Blocks, Block, +-- string and booleans +-- Caution: not to be used on non-Meta Pandoc elements, the +-- results will differ (only 'Block', 'Blocks', 'Inline', 'Inlines' in +-- >=2.17, the .t string in <2.17). +local type = utils.type or function(obj) + local tag = type(obj) == 'table' and obj.t and obj.t:gsub('^Meta', '') + return tag and tag ~= 'Map' and tag or type(obj) +end + +--- Test whether the target format is in a given list. +-- @param formats list of formats to be matched +-- @return true if match, false otherwise +local function format_matches(formats) + for _, format in pairs(formats) do + if FORMAT:match(format) then + return true + end + end + return false +end + + +--- Add a block to the document's header-includes meta-data field. +-- @param meta the document's metadata block +-- @param block Pandoc block element (e.g. RawBlock or Para) to be added to header-includes +-- @return meta the modified metadata block +local function add_header_includes(meta, block) + local header_includes = pandoc.List:new() + + -- use meta['header-includes'] + + if meta['header-includes'] then + if type(meta['header-includes']) == 'List' then + header_includes:extend(meta['header-includes']) + else + header_includes:insert(meta['header-includes']) + end + end + + -- insert `block` in header-includes + + header_includes:insert(pandoc.MetaBlocks({ block })) + + -- save header-includes in the document's meta + + meta['header-includes'] = header_includes + + return meta +end + +--- Add a class to an element. +-- @param element Pandoc AST element +-- @param class name of the class to be added (string) +-- @return the modified element, or the unmodified element if the element has no classes +local function add_class(element, class) + -- act only if the element has classes + if element.attr and element.attr.classes then + -- if the class is absent, add it + if not element.attr.classes:includes(class) then + element.attr.classes:insert(class) + end + end + + return element +end + +--- Removes a class from an element. +-- @param element Pandoc AST element +-- @param class name of the class to be removed (string) +-- @return the modified element, or the unmodified element if the element has no classes +local function remove_class(element, class) + -- act only if the element has classes + if element.attr and element.attr.classes then + -- if the class is present, remove it + if element.attr.classes:includes(class) then + element.attr.classes = element.attr.classes:filter( + function(x) + return not (x == class) + end + ) + end + end + + return element +end + +--- Set the value of an element's attribute. +-- @param element Pandoc AST element to be modified +-- @param key name of the attribute to be set (string) +-- @param value value to be set. If nil, the attribute is removed. +-- @return the modified element, or the element if it's not an element with attributes. +local function set_attribute(element, key, value) + -- act only if the element has attributes + if element.attr and element.attr.attributes then + -- if `value` is `nil`, remove the attribute + if value == nil then + if element.attr.attributes[key] then + element.attr.attributes[key] = nil + end + + -- otherwise set its value + else + element.attr.attributes[key] = value + end + end + + return element +end + +--- Add html style markup to an element's attributes. +-- @param element the Pandoc AST element to be modified +-- @param style the style markup to add (string in CSS) +-- @return the modified element, or the unmodified element if it's an element without attributes +local function add_to_html_style(element, style) + -- act only if the element has attributes + if element.attr and element.attr.attributes then + -- if the element has style markup, append + if element.attr.attributes['style'] then + element.attr.attributes['style'] = + element.attr.attributes['style'] .. '; ' .. style .. ' ;' + + -- otherwise create + else + element.attr.attributes['style'] = style .. ' ;' + end + end + + return element +end + +--- Translate an English number name into a number. +-- Converts cardinals ("one") and numerals ("first"). +-- Returns nil if the name isn't understood. +-- @param name an English number name (string) +-- @return number or nil +local function number_by_name(name) + local names = { + one = 1, + two = 2, + three = 3, + four = 4, + five = 5, + six = 6, + seven = 7, + eight = 8, + nine = 9, + ten = 10, + first = 1, + second = 2, + third = 3, + fourth = 4, + fifth = 5, + sixth = 6, + seventh = 7, + eighth = 8, + ninth = 9, + tenth = 10, + } + + result = nil + + if name and names[name] then + return names[name] + end +end + +--- Convert some CSS values (lengths, colous) to LaTeX equivalents. +-- Example usage: `css_values_to_latex("1px solid black")` returns +-- `{ length = "1pt", color = "black", colour = "black"}`. +-- @param css_str a CSS string specifying a value +-- @return table with keys `length`, `color` (alias `colour`) if found +local function css_values_to_latex(css_str) + -- color conversion table + -- keys are CSS values, values are LaTeX equivalents + + latex_colors = { + -- xcolor always available + black = 'black', + blue = 'blue', + brown = 'brown', + cyan = 'cyan', + darkgray = 'darkgray', + gray = 'gray', + green = 'green', + lightgray = 'lightgray', + lime = 'lime', + magenta = 'magenta', + olive = 'olive', + orange = 'orange', + pink = 'pink', + purple = 'purple', + red = 'red', + teal = 'teal', + violet = 'violet', + white = 'white', + yellow = 'yellow', + -- css1 colors + silver = 'lightgray', + fuschia = 'magenta', + aqua = 'cyan', + } + + local result = {} + + -- look for color values + -- by color name + -- rgb, etc.: to be added + + local color = '' + + -- space in front simplifies pattern matching + css_str = ' ' .. css_str + + -- look for colour names + for text in string.gmatch(css_str, '[%s](%a+)') do + -- if we have LaTeX equivalent of `text`, store it + if latex_colors[text] then + result['color'] = latex_colors[text] + end + end + + -- provide British spelling + + if result['color'] then + result['colour'] = result['color'] + end + + -- look for lengths + + -- 0 : converted to 0em + if string.find(css_str, '%s0%s') then + result['length'] = '0em' + end + + -- px : converted to pt + for text in string.gmatch(css_str, '(%s%d+)px') do + result['length'] = text .. 'pt' + end + + -- lengths units to be kept as is + -- nb, % must be escaped + -- nb, if several found, the latest type is preserved + keep_units = { '%%', 'pt', 'mm', 'cm', 'in', 'ex', 'em' } + + for _, unit in pairs(keep_units) do + -- .11em format + for text in string.gmatch(css_str, '%s%.%d+' .. unit) do + result['length'] = text + end + + -- 2em and 1.2em format + for text in string.gmatch(css_str, '%s%d+%.?%d*' .. unit) do + result['length'] = text + end + end + + return result +end + +--- Ensures that a string specifies a LaTeX length +-- @param text text to be checked +-- @return text if it is a LaTeX length, `nil` otherwise +local function ensures_latex_length(text) + -- LaTeX lengths units + -- nb, % must be escaped in lua patterns + units = { '%%', 'pt', 'mm', 'cm', 'in', 'ex', 'em' } + + local result = nil + + -- ignore spaces, controls and punctuation other than + -- dot, plus, minus + text = string.gsub(text, "[%s%c,;%(%)%[%]%*%?%%%^%$]+", "") + + for _, unit in pairs(units) do + -- match .11em format and 1.2em format + if string.match(text, '^%.%d+' .. unit .. '$') or + string.match(text, '^%d+%.?%d*' .. unit .. '$') then + result = text + end + end + + return result +end + + +-- # Filter-specific functions + +--- Process the metadata block. +-- Adds any needed material to the document's metadata block. +-- @param meta the document's metadata element +local function process_meta(meta) + -- in LaTeX, require the `multicols` package + if FORMAT:match('latex') then + return add_header_includes(meta, + pandoc.RawBlock('latex', '\\usepackage{multicol}\n')) + end + + -- in html, ensure that the first element of `columns` div + -- has a top margin of zero (otherwise we get white space + -- on the top of the first column) + -- idem for the first element after a `column-span` element + if FORMAT:match('html.*') then + html_header = [[ + +]] + + return add_header_includes(meta, pandoc.RawBlock('html', html_header)) + end + + return meta +end + +--- Convert explicit columnbreaks. +-- This function converts any explict columnbreak markup in an element +-- into a single syntax: a Div with class `columnbreak`. +-- Note: if there are `column` Divs in the element we keep them +-- in case they harbour further formatting (e.g. html classes). However +-- we remove their `column` class to avoid double-processing when +-- column fields are nested. +-- @param elem Pandoc native Div element +-- @return elem modified as needed +local function convert_explicit_columbreaks(elem) + -- if `elem` ends with a `column` Div, this last Div should + -- not generate a columnbreak. We tag it to make sure we don't convert it. + + if elem.content[#elem.content] and elem.content[#elem.content].classes + and elem.content[#elem.content].classes:includes('column') then + elem.content[#elem.content] = + add_class(elem.content[#elem.content], 'column-div-in-last-position') + end + + -- processes `column` Divs and `\columnbreak` LaTeX RawBlocks + filter = { + + Div = function(el) + -- syntactic sugar: `column-break` converted to `columnbreak` + if el.classes:includes("column-break") then + el = add_class(el, "columnbreak") + el = remove_class(el, "column-break") + end + + if el.classes:includes("column") then + -- with `column` Div, add a break if it's not in last position + if not el.classes:includes('column-div-in-last-position') then + local breaking_div = pandoc.Div({}) + breaking_div = add_class(breaking_div, "columnbreak") + + el.content:insert(breaking_div) + + -- if it's in the last position, remove the custom tag + else + el = remove_class(el, 'column-div-in-last-position') + end + + -- remove `column` classes, but leave the div and other + -- attributes the user might have added + el = remove_class(el, 'column') + end + + return el + end, + + RawBlock = function(el) + if el.format == "tex" and el.text == '\\columnbreak' then + local breaking_div = pandoc.Div({}) + breaking_div = add_class(breaking_div, "columnbreak") + + return breaking_div + else + return el + end + end + + } + + return pandoc.walk_block(elem, filter) +end + +--- Tag an element with the number of explicit columnbreaks it contains. +-- Counts the number of epxlicit columnbreaks contained in an element and +-- tags the element with a `number_explicit_columnbreaks` attribute. +-- In the process columnbreaks are tagged with the class `columnbreak_already_counted` +-- in order to avoid double-counting when multi-columns are nested. +-- @param elem Pandoc element (native Div element of class `columns`) +-- @return elem with the attribute `number_explicit_columnbreaks` set. +local function tag_with_number_of_explicit_columnbreaks(elem) + local number_columnbreaks = 0 + + local filter = { + + Div = function(el) + if el.classes:includes('columnbreak') and + not el.classes:includes('columnbreak_already_counted') then + number_columnbreaks = number_columnbreaks + 1 + el = add_class(el, 'columnbreak_already_counted') + end + + return el + end + } + + elem = pandoc.walk_block(elem, filter) + + elem = set_attribute(elem, 'number_explicit_columnbreaks', + number_columnbreaks) + + return elem +end + +--- Consolidate aliases for column attributes. +-- Provides syntacic sugar: unifies various ways of +-- specifying attributes of a multi-column environment. +-- When several specifications conflit, favours `column-gap` and +-- `column-rule` specifications. +-- @param elem Pandoc element (Div of class `columns`) with column attributes. +-- @return elem modified as needed. +local function consolidate_colattrib_aliases(elem) + if elem.attr and elem.attr.attributes then + -- `column-gap` if the preferred syntax is set, erase others + if elem.attr.attributes["column-gap"] then + elem = set_attribute(elem, "columngap", nil) + elem = set_attribute(elem, "column-sep", nil) + elem = set_attribute(elem, "columnsep", nil) + + -- otherwise fetch and unset any alias + else + if elem.attr.attributes["columnsep"] then + elem = set_attribute(elem, "column-gap", + elem.attr.attributes["columnsep"]) + elem = set_attribute(elem, "columnsep", nil) + end + + if elem.attr.attributes["column-sep"] then + elem = set_attribute(elem, "column-gap", + elem.attr.attributes["column-sep"]) + elem = set_attribute(elem, "column-sep", nil) + end + + if elem.attr.attributes["columngap"] then + elem = set_attribute(elem, "column-gap", + elem.attr.attributes["columngap"]) + elem = set_attribute(elem, "columngap", nil) + end + end + + -- `column-rule` if the preferred syntax is set, erase others + if elem.attr.attributes["column-rule"] then + elem = set_attribute(elem, "columnrule", nil) + + -- otherwise fetch and unset any alias + else + if elem.attr.attributes["columnrule"] then + elem = set_attribute(elem, "column-rule", + elem.attr.attributes["columnrule"]) + elem = set_attribute(elem, "columnrule", nil) + end + end + end + + return elem +end + +--- Pre-process a Div of class `columns`. +-- Converts explicit column breaks into a unified syntax +-- and count the Div's number of columns. +-- When several columns are nested Pandoc will apply +-- this filter to the innermost `columns` Div first; +-- we use that feature to prevent double-counting. +-- @param elem Pandoc element to be processes (Div of class `columns`) +-- @return elem modified as needed +local function preprocess_columns(elem) + -- convert any explicit column syntax in a single format: + -- native Divs with class `columnbreak` + + elem = convert_explicit_columbreaks(elem) + + -- count explicit columnbreaks + + elem = tag_with_number_of_explicit_columnbreaks(elem) + + return elem +end + +--- Determine the number of column in a `columns` Div. +-- Looks up two attributes in the Div: the user-specified +-- `columns-count` and the filter-generated `number_explicit_columnbreaks` +-- which is based on the number of explicit breaks specified. +-- The final number of columns will be 2 or whichever of `column-count` and +-- `number_explicit_columnbreaks` is the highest. This ensures there are +-- enough columns for all explicit columnbreaks. +-- This provides a single-column when the user specifies `column-count = 1` and +-- there are no explicit columnbreaks. +-- @param elem Pandoc element (Div of class `columns`) whose number of columns is to be determined. +-- @return number of columns (number, default 2). +local function determine_column_count(elem) + -- is there a specified column count? + local specified_column_count = 0 + if elem.attr.attributes and elem.attr.attributes['column-count'] then + specified_column_count = tonumber( + elem.attr.attributes["column-count"]) + end + + -- is there an count of explicit columnbreaks? + local number_explicit_columnbreaks = 0 + if elem.attr.attributes and elem.attr.attributes['number_explicit_columnbreaks'] then + number_explicit_columnbreaks = tonumber( + elem.attr.attributes['number_explicit_columnbreaks'] + ) + + set_attribute(elem, 'number_explicit_columnbreaks', nil) + end + + -- determines the number of columns + -- default 2 + -- recall that number of columns = nb columnbreaks + 1 + + local number_columns = 2 + + if specified_column_count > 0 or number_explicit_columnbreaks > 0 then + if (number_explicit_columnbreaks + 1) > specified_column_count then + number_columns = number_explicit_columnbreaks + 1 + else + number_columns = specified_column_count + end + end + + return number_columns +end + +--- Convert a pandoc Header to a list of inlines for latex output. +-- @param header Pandoc Header element +-- @return list of Inline elements +local function header_to_latex_and_inlines(header) + -- @todo check if level interpretation has been shifted, e.g. section is level 2 + -- @todo we could check the Pandoc state to check whether hypertargets are required? + + local latex_header = { + 'section', + 'subsection', + 'subsubsection', + 'paragraph', + 'subparagraph', + } + + -- create a list if the header's inlines + local inlines = pandoc.List:new(header.content) + + -- wrap in a latex_header if available + + if header.level and latex_header[header.level] then + inlines:insert(1, pandoc.RawInline('latex', + '\\' .. latex_header[header.level] .. '{')) + inlines:insert(pandoc.RawInline('latex', '}')) + end + + -- wrap in a link if available + if header.identifier then + inlines:insert(1, pandoc.RawInline('latex', + '\\hypertarget{' .. header.identifier .. '}{%\n')) + inlines:insert(pandoc.RawInline('latex', + '\\label{' .. header.identifier .. '}}')) + end + + return inlines +end + +--- Format column span in LaTeX. +-- Formats a bit of text spanning across all columns for LaTeX output. +-- If the colspan is only one block, it is turned into an option +-- of a new `multicol` environment. Otherwise insert it is +-- inserted between the two `multicol` environments. +-- @param elem Pandoc element that is supposed to span across all +-- columns. +-- @param number_columns number of columns in the present environment. +-- @return a pandoc RawBlock element in LaTeX format +local function format_colspan_latex(elem, number_columns) + local result = pandoc.List:new() + + -- does the content consists of a single header? + + if #elem.content == 1 and elem.content[1].t == 'Header' then + -- create a list of inlines + inlines = pandoc.List:new() + inlines:insert(pandoc.RawInline('latex', + "\\end{multicols}\n")) + inlines:insert(pandoc.RawInline('latex', + "\\begin{multicols}{" .. number_columns .. "}[")) + inlines:extend(header_to_latex_and_inlines(elem.content[1])) + inlines:insert(pandoc.RawInline('latex', "]\n")) + + -- insert as a Plain block + result:insert(pandoc.Plain(inlines)) + + return result + else + result:insert(pandoc.RawBlock('latex', + "\\end{multicols}\n")) + result:extend(elem.content) + result:insert(pandoc.RawBlock('latex', + "\\begin{multicols}{" .. number_columns .. "}")) + return result + end +end + +--- Format columns for LaTeX output +-- @param elem Pandoc element (Div of "columns" class) containing the +-- columns to be formatted. +-- @return elem with suitable RawBlocks in LaTeX added +local function format_columns_latex(elem) + -- make content into a List object + pandoc.List:new(elem.content) + + -- how many columns? + number_columns = determine_column_count(elem) + + -- set properties and insert LaTeX environment + -- we wrap the entire environment in `{...}` to + -- ensure properties (gap, rule) don't carry + -- over to following columns + + local latex_begin = '{' + local latex_end = '}' + local ragged = options.raggedcolumns + + -- override global ragged setting? + if elem.classes:includes('ragged') + or elem.classes:includes('raggedcolumns') + or elem.classes:includes('ragged-columns') then + ragged = true + elseif elem.classes:includes('justified') + or elem.classes:includes('justifiedcolumns') + or elem.classes:includes('justified-columns') then + ragged = false + end + if ragged then + latex_begin = latex_begin .. '\\raggedcolumns' + end + + if elem.attr.attributes then + if elem.attr.attributes["column-gap"] then + local latex_value = ensures_latex_length( + elem.attr.attributes["column-gap"]) + + if latex_value then + latex_begin = latex_begin .. + "\\setlength{\\columnsep}{" .. latex_value .. "}\n" + end + + -- remove the `column-gap` attribute + elem = set_attribute(elem, "column-gap", nil) + end + + if elem.attr.attributes["column-rule"] then + -- converts CSS value string to LaTeX values + local latex_values = css_values_to_latex( + elem.attr.attributes["column-rule"]) + + if latex_values["length"] then + latex_begin = latex_begin .. + "\\setlength{\\columnseprule}{" .. + latex_values["length"] .. "}\n" + end + + if latex_values["color"] then + latex_begin = latex_begin .. + "\\renewcommand{\\columnseprulecolor}{\\color{" .. + latex_values["color"] .. "}}\n" + end + + + -- remove the `column-rule` attribute + elem = set_attribute(elem, "column-rule", nil) + end + end + + latex_begin = latex_begin .. + "\\begin{multicols}{" .. number_columns .. "}\n" + latex_end = "\\end{multicols}\n" .. latex_end + + elem.content:insert(1, pandoc.RawBlock('latex', latex_begin)) + elem.content:insert(pandoc.RawBlock('latex', latex_end)) + + -- process blocks contained in `elem` + -- turn any explicit columnbreaks into LaTeX markup + -- turn `column-span` Divs into LaTeX markup + + filter = { + + Div = function(el) + if el.classes:includes("columnbreak") then + return pandoc.RawBlock('latex', "\\columnbreak\n") + end + + if el.classes:includes("column-span-to-be-processed") then + return format_colspan_latex(el, number_columns) + end + end + + } + + elem = pandoc.walk_block(elem, filter) + + return elem +end + + +--- Formats columns for html output. +-- Uses CSS3 style added to the elements themselves. +-- @param elem Pandoc element (Div of `columns` style) +-- @return elem with suitable html attributes +local function format_columns_html(elem) + -- how many columns? + number_columns = determine_column_count(elem) + + -- add properties to the `columns` Div + + elem = add_to_html_style(elem, 'column-count: ' .. number_columns) + elem = set_attribute(elem, 'column-count', nil) + + if elem.attr.attributes then + if elem.attr.attributes["column-gap"] then + elem = add_to_html_style(elem, 'column-gap: ' .. + elem.attr.attributes["column-gap"]) + + -- remove the `column-gap` attribute + elem = set_attribute(elem, "column-gap") + end + + if elem.attr.attributes["column-rule"] then + elem = add_to_html_style(elem, 'column-rule: ' .. + elem.attr.attributes["column-rule"]) + + -- remove the `column-rule` attribute + elem = set_attribute(elem, "column-rule", nil) + end + end + + -- convert any explicit columnbreaks in CSS markup + + filter = { + + Div = function(el) + -- format column-breaks + if el.classes:includes("columnbreak") then + el = add_to_html_style(el, 'break-after: column') + + -- remove columbreaks class to avoid double processing + -- when nested + -- clean up already-counted tag + el = remove_class(el, "columnbreak") + el = remove_class(el, "columnbreak_already_counted") + + -- format column-spans + elseif el.classes:includes("column-span-to-be-processed") then + el = add_to_html_style(el, 'column-span: all') + + -- remove column-span-to-be-processed class to avoid double processing + -- add column-span class to allow for styling + el = add_class(el, "column-span") + el = remove_class(el, "column-span-to-be-processed") + end + + return el + end + + } + + elem = pandoc.walk_block(elem, filter) + + return elem +end + + +-- # Main filters + +--- Formating filter. +-- Applied last, converts prepared columns in target output formats +-- @field Div looks for `columns` class +format_filter = { + + Div = function(element) + -- pick up `columns` Divs for formatting + if element.classes:includes("columns") then + if FORMAT:match('latex') then + element = format_columns_latex(element) + elseif FORMAT:match('html.*') then + element = format_columns_html(element) + end + + return element + end + end +} + +--- Preprocessing filter. +-- Processes meta-data fields and walks the document to pre-process +-- columns blocks. Determine how many columns they contain, tags the +-- last column Div, etc. Avoids double-counting when columns environments +-- are nested. +-- @field Div looks for `columns` class +-- @field Meta processes the metadata block +preprocess_filter = { + + Div = function(element) + -- send `columns` Divs to pre-processing + if element.classes:includes("columns") then + return preprocess_columns(element) + end + end, + + Meta = function(meta) + return process_meta(meta) + end +} + +--- Syntactic sugar filter. +-- Provides alternative ways of specifying columns properties. +-- Kept separate from the pre-processing filter for clarity. +-- @field Div looks for Div of classes `columns` (and related) and `column-span` +syntactic_sugar_filter = { + + Div = function(element) + -- convert "two-columns" into `columns` Divs + for _, class in pairs(element.classes) do + -- match xxxcolumns, xxx_columns, xxx-columns + -- if xxx is the name of a number, make + -- a `columns` div and set its `column-count` attribute + local number = number_by_name( + string.match(class, '(%a+)[_%-]?columns$') + ) + + if number then + element = set_attribute(element, + "column-count", tostring(number)) + element = remove_class(element, class) + element = add_class(element, "columns") + end + end + + -- allows different ways of specifying `columns` attributes + if element.classes:includes('columns') then + element = consolidate_colattrib_aliases(element) + end + + -- `column-span` syntax + -- mark up as "to-be-processed" to avoid + -- double processing when nested + if element.classes:includes('column-span') or + element.classes:includes('columnspan') then + element = add_class(element, 'column-span-to-be-processed') + element = remove_class(element, 'column-span') + element = remove_class(element, 'columnspan') + end + + return element + end + +} + +--- Read options filter +read_options_filter = { + Meta = function(meta) + if not meta then return end + + -- global vertical ragged / justified settings + if meta.raggedcolumns or meta['ragged-columns'] then + options.raggedcolumns = true + elseif meta.justifiedcolumns or meta['justified-columns'] then + options.raggedcolumns = false + end + end +} + +-- Main statement returns filters only if the +-- target format matches our list. The filters +-- returned are applied in the following order: +-- 1. `syntatic_sugar_filter` deals with multiple syntax +-- 2. `preprocessing_filter` converts all explicit +-- columnbreaks into a common syntax and tags +-- those that are already counted. We must do +-- that for all `columns` environments before +-- turning any break back into LaTeX `\columnbreak` blocks +-- otherwise we mess up the count in nested `columns` Divs. +-- 3. `format_filter` formats the columns after the counting +-- has been done +if format_matches(target_formats) then + return { + read_options_filter, + syntactic_sugar_filter, + preprocess_filter, + format_filter + } +else + return +end diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1923b8a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: "2.4" +services: + void: + # if you want to build your own container locally: + # container_name: paper-builder + # build: . + image: baldeau/paper-builder + platform: linux/amd64 + volumes: + - ".:/paper" + environment: + - PATH=$PATH:~/.local/bin + - PATH=$PATH:~/.cabal/bin + - TERM=xterm-256color + command: bash -c "cd paper && ./docker_build.sh" diff --git a/docker_build.sh b/docker_build.sh new file mode 100755 index 0000000..f437d75 --- /dev/null +++ b/docker_build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +shopt -s globstar # Enable recursive globbing + +markdown_files=(chapters/**/*.md) + +IFS=$'\n' +sorted_files=($(sort <<<"${markdown_files[*]}")); +unset IFS + +echo "${sorted_files[@]}" +MERMAID_FILTER_FORMAT=pdf pandoc -V colorlinks=true -V linkcolor=black -V urlcolor=black -f 'markdown+autolink_bare_uris' --pdf-engine=lualatex --pdf-engine-opt=-shell-escape --filter mermaid-filter --lua-filter columns.lua --citeproc -s "${sorted_files[@]}" -o ./out/bachelor.pdf -V lang=de-DE -V fontsize=11pt --highlight-style tango --reference-links --bibliography Bachelor.bib --csl=harvard-right.csl -M lang:de --number-sections \ No newline at end of file diff --git a/harvard-right.csl b/harvard-right.csl new file mode 100644 index 0000000..2800678 --- /dev/null +++ b/harvard-right.csl @@ -0,0 +1,318 @@ + + diff --git a/refract.sty b/refract.sty new file mode 100644 index 0000000..f810944 --- /dev/null +++ b/refract.sty @@ -0,0 +1,361 @@ +%% +%% This is the file fzframes.sty +%% Author: Kathryn Andersen +%% +%% This provides a collection of nice frames based on the niceframes +%% package +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{refract}[2001/06/22 +fancy frames for fanzine package +: Kathryn Andersen] +\RequirePackage{niceframe} +\RequirePackage{graphics} + +%% Frame with scrolly things +\newcommand{\fzframescroll}[1]{% +\font\border=umranda +\generalframe{\border\char'136}{\border\char'137}{\border\char'140} + {\border\char'145} {\border\char'141} + {\border\char'144}{\border\char'143}{\border\char'142} +{#1}} +%% Frame with flowers +\newcommand{\fzframeflower}[1]{% +\font\border=umranda +\generalframe{\border\char78}{\border\char79}{\border\char84} + {\border\char81} {\border\char85} + {\border\char80}{\border\char83}{\border\char82} +{#1}} + +%% Frame with snakes +\newcommand{\fzframesnake}[1]{% +\font\border=umranda +\generalframe{\border\char87}{\border\char87}{\border\char87} + {\border\char89} {\border\char93} + {\border\char91}{\border\char91}{\border\char91} +{#1}} + +%% Frame with triangles +\newcommand{\fzframetri}[1]{% +\font\border=umranda +\generalframe{\border\char7}{\border\char6}{\border\char5} + {\reflectbox{\border\char4}} {\border\char4} + {\border\char1}{\border\char2}{\border\char3} +{#1}} +%% Frame with triangles pointing out +\newcommand{\fzframetriout}[1]{% +\font\border=umranda +\generalframe{\border\char3}{\border\char2}{\border\char1} + {\border\char4} {\reflectbox{\border\char4}} + {\border\char5}{\border\char6}{\border\char7} +{#1}} + +%% Here follows a collection of frames made of decorative boxes +%% so they are called fzframebx with a letter to differentiate +%% them, A-Z +\newcommand{\fzframebxA}[1]{% +\font\border=umranda +\generalframe{\border\char39}{\border\char37}{\border\char37} + {\border\char39} {\border\char43} + {\border\char41}{\border\char41}{\border\char43} +{#1}} +% +\newcommand{\fzframebxB}[1]{% +\font\border=umranda +\generalframe{\border\char41}{\border\char41}{\border\char39} + {\border\char43} {\border\char39} + {\border\char43}{\border\char37}{\border\char37} +{#1}} + +\newcommand{\fzframebxC}[1]{% +\font\border=umranda +\generalframe{\border\char38}{\border\char38}{\border\char36} + {\border\char38} {\border\char36} + {\border\char40}{\border\char40}{\border\char42} +{#1} +} + +\newcommand{\fzframebxD}[1]{% +\font\border=umranda +\generalframe{\border\char42}{\border\char40}{\border\char40} + {\border\char36} {\border\char38} + {\border\char36}{\border\char38}{\border\char38} +{#1} +} + +\newcommand{\fzframebxE}[1]{% +\font\border=umranda +\generalframe{\border\char44}{\border\char44}{\border\char50} + {\border\char46} {\border\char50} + {\border\char46}{\border\char48}{\border\char48} +{#1}} + +\newcommand{\fzframebxF}[1]{% +\font\border=umranda +\generalframe{\border\char51}{\border\char51}{\border\char49} + {\border\char45} {\border\char49} + {\border\char45}{\border\char47}{\border\char47} +{#1}} + +%% Here follows a collection of frames made of circles +%% so they are called fzframecir with a letter to differentiate +%% them, A-Z +\newcommand{\fzframecirA}[1]{% +\font\border=umranda +\generalframe{\border\char34}{\border\char34}{\border\char34} + {\border\char34} {\border\char34} + {\border\char34}{\border\char34}{\border\char34} +{#1}} +\newcommand{\fzframecirB}[1]{% +\font\border=umranda +\generalframe{\border\char35}{\border\char35}{\border\char35} + {\border\char35} {\border\char35} + {\border\char35}{\border\char35}{\border\char35} +{#1}} + +\newcommand{\fzframecirC}[1]{% +\font\border=umranda +\generalframe{\border\char20}{\border\char25}{\border\char24} + {\border\char22} {\border\char22} + {\border\char24}{\border\char25}{\border\char20} +{#1}} +\newcommand{\fzframecirD}[1]{% +\font\border=umranda +\generalframe{\border\char26}{\border\char30}{\border\char29} + {\border\char27} {\border\char27} + {\border\char29}{\border\char30}{\border\char26} +{#1}} + +%% Here follows a collection of frames with lots of lines +%% so they are called fzframelin with a letter to differentiate +%% them, A-Z + +%% This bunch, the border has 6 lines, same thickness +\newcommand{\fzframelinA}[1]{% +\font\border=umrandb +\generalframe{\border\char5}{\border\char1}{\border\char4} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char6}{\border\char3}{\border\char7} +{#1}} + +\newcommand{\fzframelinB}[1]{% +\font\border=umrandb +\generalframe{\border\char9}{\border\char1}{\border\char8} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char10}{\border\char3}{\border\char11} +{#1}} + +\newcommand{\fzframelinC}[1]{% +\font\border=umrandb +\generalframe{\border\char13}{\border\char1}{\border\char12} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char14}{\border\char3}{\border\char15} +{#1}} + +\newcommand{\fzframelinD}[1]{% +\font\border=umrandb +\generalframe{\border\char17}{\border\char1}{\border\char16} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char18}{\border\char3}{\border\char19} +{#1}} + +\newcommand{\fzframelinE}[1]{% +\font\border=umrandb +\generalframe{\border\char21}{\border\char1}{\border\char20} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char22}{\border\char3}{\border\char23} +{#1}} + +\newcommand{\fzframelinF}[1]{% +\font\border=umrandb +\generalframe{\border\char25}{\border\char1}{\border\char24} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char26}{\border\char3}{\border\char27} +{#1}} + +\newcommand{\fzframelinG}[1]{% +\font\border=umrandb +\generalframe{\border\char29}{\border\char1}{\border\char28} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char30}{\border\char3}{\border\char31} +{#1}} + +\newcommand{\fzframelinH}[1]{% +\font\border=umrandb +\generalframe{\border\char33}{\border\char1}{\border\char32} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char34}{\border\char3}{\border\char35} +{#1}} + +\newcommand{\fzframelinI}[1]{% +\font\border=umrandb +\generalframe{\border\char37}{\border\char1}{\border\char36} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char38}{\border\char3}{\border\char39} +{#1}} + +\newcommand{\fzframelinJ}[1]{% +\font\border=umrandb +\generalframe{\border\char41}{\border\char1}{\border\char40} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char42}{\border\char3}{\border\char43} +{#1}} + +\newcommand{\fzframelinK}[1]{% +\font\border=umrandb +\generalframe{\border\char45}{\border\char1}{\border\char44} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char46}{\border\char3}{\border\char47} +{#1}} + +\newcommand{\fzframelinL}[1]{% +\font\border=umrandb +\generalframe{\border\char49}{\border\char1}{\border\char48} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char50}{\border\char3}{\border\char51} +{#1}} + +\newcommand{\fzframelinM}[1]{% +\font\border=umrandb +\generalframe{\border\char53}{\border\char1}{\border\char52} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char54}{\border\char3}{\border\char55} +{#1}} + +\newcommand{\fzframelinN}[1]{% +\font\border=umrandb +\generalframe{\border\char57}{\border\char1}{\border\char56} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char58}{\border\char3}{\border\char59} +{#1}} + +\newcommand{\fzframelinO}[1]{% +\font\border=umrandb +\generalframe{\border\char61}{\border\char1}{\border\char60} + {\border\char2} {\reflectbox{\border\char2}} + {\border\char62}{\border\char3}{\border\char63} +{#1}} + +%% Border has 4 lines, same thickness +\newcommand{\fzframelinP}[1]{% +\font\border=umrandb +\generalframe{\border\char69}{\border\char65}{\border\char68} + {\border\char64} {\border\char66} + {\border\char70}{\border\char67}{\border\char71} +{#1}} + +\newcommand{\fzframelinQ}[1]{% +\font\border=umrandb +\generalframe{\border\char73}{\border\char65}{\border\char72} + {\border\char64} {\border\char66} + {\border\char74}{\border\char67}{\border\char75} +{#1}} + +\newcommand{\fzframelinR}[1]{% +\font\border=umrandb +\generalframe{\border\char77}{\border\char65}{\border\char76} + {\border\char64} {\border\char66} + {\border\char78}{\border\char67}{\border\char79} +{#1}} + +\newcommand{\fzframelinS}[1]{% +\font\border=umrandb +\generalframe{\border\char81}{\border\char65}{\border\char80} + {\border\char64} {\border\char66} + {\border\char82}{\border\char67}{\border\char83} +{#1}} + +\newcommand{\fzframelinT}[1]{% +\font\border=umrandb +\generalframe{\border\char85}{\border\char65}{\border\char84} + {\border\char64} {\border\char66} + {\border\char86}{\border\char67}{\border\char87} +{#1}} + +\newcommand{\fzframelinU}[1]{% +\font\border=umrandb +\generalframe{\border\char89}{\border\char65}{\border\char88} + {\border\char64} {\border\char66} + {\border\char90}{\border\char67}{\border\char91} +{#1}} + +\newcommand{\fzframelinV}[1]{% +\font\border=umrandb +\generalframe{\border\char93}{\border\char65}{\border\char92} + {\border\char64} {\border\char66} + {\border\char94}{\border\char67}{\border\char95} +{#1}} + +\newcommand{\fzframelinW}[1]{% +\font\border=umrandb +\generalframe{\border\char97}{\border\char65}{\border\char96} + {\border\char64} {\border\char66} + {\border\char98}{\border\char67}{\border\char99} +{#1}} + +\newcommand{\fzframelinX}[1]{% +\font\border=umrandb +\generalframe{\border\char101}{\border\char65}{\border\char100} + {\border\char64} {\border\char66} + {\border\char102}{\border\char67}{\border\char103} +{#1}} + +%% Border has 5 lines, the middle one thicker +\newcommand{\fzframelinY}[1]{% +\font\border=umrandb +\generalframe{\border\char113}{\border\char105}{\border\char112} + {\border\char106} {\border\char104} + {\border\char114}{\border\char107}{\border\char115} +{#1}} + +\newcommand{\fzframelinZ}[1]{% +\font\border=umrandb +\generalframe{\border\char113}{\border\char109}{\border\char112} + {\border\char110} {\border\char108} + {\border\char114}{\border\char111}{\border\char115} +{#1}} + +\newcommand{\fzframelinAA}[1]{% +\font\border=umrandb +\generalframe{\border\char117}{\border\char105}{\border\char116} + {\border\char106} {\border\char104} + {\border\char118}{\border\char107}{\border\char119} +{#1}} + +\newcommand{\fzframelinAB}[1]{% +\font\border=umrandb +\generalframe{\border\char117}{\border\char109}{\border\char116} + {\border\char110} {\border\char108} + {\border\char118}{\border\char111}{\border\char119} +{#1}} + +\newcommand{\fzframelinAC}[1]{% +\font\border=umrandb +\generalframe{\border\char121}{\border\char105}{\border\char120} + {\border\char106} {\border\char104} + {\border\char122}{\border\char107}{\border\char123} +{#1}} + +\newcommand{\fzframelinAD}[1]{% +\font\border=umrandb +\generalframe{\border\char121}{\border\char109}{\border\char120} + {\border\char110} {\border\char108} + {\border\char122}{\border\char111}{\border\char123} +{#1}} + +%% +%% Sample of dingbats in a font +\RequirePackage{ifthen} +\newcounter{clet} +\newcounter{numchars} +\newcommand{\dingsample}{% +\setcounter{clet}{1} +\setcounter{numchars}{256} +\whiledo{\value{clet}<256}{% +\mbox{ +\texttt{ \theclet\ = }\char\value{clet} +} +\addtocounter{clet}{1} +} +} +\endinput