diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/App.java b/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
index 5b0e1c36bded3b87ca70493b051e8a3c03d49a65..0b9a0ebbe0e4f3ee865fb5a7488d60230ba6d5b9 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
@@ -1,21 +1,23 @@
 package de.tudresden.inf.mci.brailleplot;
 
+import ch.qos.logback.classic.Level;
 import de.tudresden.inf.mci.brailleplot.configparser.Format;
 import de.tudresden.inf.mci.brailleplot.configparser.JavaPropertiesConfigurationParser;
 import de.tudresden.inf.mci.brailleplot.configparser.Printer;
 
 import de.tudresden.inf.mci.brailleplot.configparser.Representation;
-import de.tudresden.inf.mci.brailleplot.layout.PlotCanvas;
+import de.tudresden.inf.mci.brailleplot.csvparser.MalformedCsvException;
 import de.tudresden.inf.mci.brailleplot.datacontainers.PointListContainer;
-import de.tudresden.inf.mci.brailleplot.diagrams.ScatterPlot;
+import de.tudresden.inf.mci.brailleplot.datacontainers.SimpleCategoricalPointListContainerImpl;
+import de.tudresden.inf.mci.brailleplot.diagrams.CategoricalBarChart;
+import de.tudresden.inf.mci.brailleplot.diagrams.Diagram;
+import de.tudresden.inf.mci.brailleplot.layout.AbstractCanvas;
+import de.tudresden.inf.mci.brailleplot.layout.PlotCanvas;
 import de.tudresden.inf.mci.brailleplot.layout.RasterCanvas;
-import de.tudresden.inf.mci.brailleplot.layout.Rectangle;
-import de.tudresden.inf.mci.brailleplot.point.Point2DValued;
-import de.tudresden.inf.mci.brailleplot.printabledata.FloatingPointData;
+import de.tudresden.inf.mci.brailleplot.printabledata.PrintableData;
 import de.tudresden.inf.mci.brailleplot.printerbackend.PrintDirector;
 import de.tudresden.inf.mci.brailleplot.printerbackend.PrinterCapability;
 
-import de.tudresden.inf.mci.brailleplot.printabledata.SimpleMatrixDataImpl;
 
 import de.tudresden.inf.mci.brailleplot.commandline.CommandLineParser;
 import de.tudresden.inf.mci.brailleplot.commandline.SettingType;
@@ -25,39 +27,36 @@ import de.tudresden.inf.mci.brailleplot.commandline.SettingsWriter;
 import de.tudresden.inf.mci.brailleplot.csvparser.CsvOrientation;
 import de.tudresden.inf.mci.brailleplot.csvparser.CsvParser;
 import de.tudresden.inf.mci.brailleplot.csvparser.CsvType;
+import de.tudresden.inf.mci.brailleplot.datacontainers.CategoricalPointListContainer;
 import de.tudresden.inf.mci.brailleplot.datacontainers.PointList;
 
-import de.tudresden.inf.mci.brailleplot.rendering.BrailleText;
-import de.tudresden.inf.mci.brailleplot.rendering.FunctionalRasterizer;
 import de.tudresden.inf.mci.brailleplot.rendering.LiblouisBrailleTextRasterizer;
-
 import de.tudresden.inf.mci.brailleplot.rendering.MasterRenderer;
 import de.tudresden.inf.mci.brailleplot.svgexporter.BoolFloatingPointDataSvgExporter;
 import de.tudresden.inf.mci.brailleplot.svgexporter.BoolMatrixDataSvgExporter;
 import de.tudresden.inf.mci.brailleplot.svgexporter.SvgExporter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import tec.units.ri.quantity.Quantities;
-import tec.units.ri.unit.MetricPrefix;
 
-import javax.measure.Quantity;
-import javax.measure.quantity.Length;
 import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.net.URL;
 import java.nio.file.Path;
-import java.util.Optional;
+import java.util.Iterator;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentLinkedDeque;
 
-import static tec.units.ri.unit.Units.METRE;
-
 /**
  * Main class.
  * Set up the application and run it.
- * @author Georg Graßnick, Andrey Ruzhanskiy
- * @version 2019.08.26
+ * @author Georg Graßnick, Andrey Ruzhanskiy, Leonard Kupper
+ * @version 2019.10.03
  */
 
 public final class App {
@@ -155,16 +154,14 @@ public final class App {
             mLogger.info("Application started");
             // Parse command line parameters
             CommandLineParser cliParser = new CommandLineParser();
+            if (CommandLineParser.checkForHelp(args)) {
+                cliParser.printHelp(); // If requested, print help and exit
+                return EXIT_SUCCESS;
+            }
             SettingsWriter settings = cliParser.parse(args);
             SettingsReader settingsReader = settings;
 
-
-            // If requested, print help and exit
-            Optional<Boolean> printHelp = settingsReader.isTrue(SettingType.DISPLAY_HELP);
-            if (printHelp.isPresent() && printHelp.get()) {
-                cliParser.printHelp();
-                return EXIT_SUCCESS;
-            }
+            setLoggingLevel(Level.valueOf(settingsReader.getSetting(SettingType.LOG_LEVEL).orElse("Info")));
 
             // Config Parsing
             JavaPropertiesConfigurationParser configParser;
@@ -178,81 +175,114 @@ public final class App {
                 configParser = new JavaPropertiesConfigurationParser(configPath, defaultConfig);
             }
 
-            Printer indexV4Printer = configParser.getPrinter();
-            Format a4Format = configParser.getFormat("A4");
+            // Set up Printer, Representation & Format Configurables
+            Printer printer = configParser.getPrinter();
             Representation representationParameters = configParser.getRepresentation();
+            Format format;
+            if (!settingsReader.isPresent(SettingType.FORMAT)) {
+                format = configParser.getFormat("default"); // Default behaviour from default config (A4 portrait)
+            } else {
+                format = configParser.getFormat(settingsReader.getSetting(SettingType.FORMAT).get());
+            }
 
-            // Parse csv data
-            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
-            InputStream csvStream = classloader.getResourceAsStream("examples/csv/2_line_plot.csv");
-            Reader csvReader = new BufferedReader(new InputStreamReader(csvStream));
-
+            // Parse csv data and create diagram
+            InputStream csvStream;
+            if (!settingsReader.isPresent(SettingType.CSV_LOCATION)) {
+                ClassLoader classloader = Thread.currentThread().getContextClassLoader();
+                csvStream = classloader.getResourceAsStream("examples/csv/0_bar_chart_categorical.csv");
+                mLogger.warn("ATTENTION! Using example csv. Please remove this behavior before packaging the jar.");
+            } else {
+                csvStream = new FileInputStream(settingsReader.getSetting(SettingType.CSV_LOCATION).get());
+            }
+            Reader csvReader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(csvStream)));
             CsvParser csvParser = new CsvParser(csvReader, ',', '\"');
-            PointListContainer<PointList> container = csvParser.parse(CsvType.DOTS, CsvOrientation.HORIZONTAL);
-            mLogger.debug("Internal data representation:\n {}", container.toString());
-
-            ScatterPlot scatterPlot = new ScatterPlot(container);
-            scatterPlot.setTitle("Scatter Plot");
-            scatterPlot.setXAxisName("X-Achse foo");
-            scatterPlot.setYAxisName("Y-Achse bar");
+            Diagram diagram;
+            CsvOrientation csvOrientation;
+            if (settingsReader.isTrue(SettingType.VERTICAL_CSV).orElse(false)) {
+                csvOrientation = CsvOrientation.VERTICAL;
+            } else {
+                csvOrientation = CsvOrientation.HORIZONTAL;
+            }
+            switch (settingsReader.getSetting(SettingType.DIAGRAM_TYPE).orElse("")) {
+                case "ScatterPlot":
+                    PointListContainer<PointList> scatterPlotContainer = csvParser.parse(CsvType.DOTS, csvOrientation);
+                    throw new UnsupportedOperationException("Scatter Plots coming soon."); // TODO: integrate scatter plots
+                case "LineChart":
+                    PointListContainer<PointList> lineChartContainer = csvParser.parse(CsvType.DOTS, csvOrientation);
+                    throw new UnsupportedOperationException("Line Charts coming soon."); // TODO: integrate line charts
+                case "BarChart":
+                    CategoricalPointListContainer<PointList> barChartContainer;
+                    try { // first try to parse as regular bar chart and convert to single category bar cart.
+                        barChartContainer = new SimpleCategoricalPointListContainerImpl(csvParser.parse(CsvType.X_ALIGNED, csvOrientation));
+                    } catch (MalformedCsvException e) { // else parse as categorical bar chart
+                        barChartContainer = csvParser.parse(CsvType.X_ALIGNED_CATEGORIES, csvOrientation);
+                    }
+                    diagram = new CategoricalBarChart(barChartContainer);
+                    break;
+                default: throw new IllegalStateException("Unknown diagram type: " + settingsReader.getSetting(SettingType.DIAGRAM_TYPE).orElse("<none>"));
+            }
+            diagram.setTitle(settingsReader.getSetting(SettingType.DIAGRAM_TITLE).orElse(""));
+            diagram.setXAxisName(settingsReader.getSetting(SettingType.X_AXIS_LABEL).orElse(""));
+            diagram.setYAxisName(settingsReader.getSetting(SettingType.Y_AXIS_LABEL).orElse(""));
 
             // Render diagram
             LiblouisBrailleTextRasterizer.initModule();
-            MasterRenderer renderer = new MasterRenderer(indexV4Printer, representationParameters, a4Format);
-            RasterCanvas canvas = renderer.rasterize(scatterPlot);
-            SimpleMatrixDataImpl<Boolean> mat = (SimpleMatrixDataImpl<Boolean>) canvas.getCurrentPage();
-            mLogger.debug("Render preview:\n" + mat.toBoolString());
-
-            // SVG exporting
-            SvgExporter<RasterCanvas> svgExporter = new BoolMatrixDataSvgExporter(canvas);
-            svgExporter.render();
-            svgExporter.dump("boolMat");
-
-            // FloatingPointData SVG exporting example
-            PlotCanvas floatCanvas = new PlotCanvas(indexV4Printer, representationParameters, a4Format);
-            FloatingPointData<Boolean> points = floatCanvas.getNewPage();
-
-            final int blockX = 230;
-            final int blockY = 400;
-            for (int y = 0; y < blockY; y += 2) {
-                for (int x = 0; x < blockX; x += 2) {
-                    Point2DValued<Quantity<Length>, Boolean> point = new Point2DValued<>(Quantities.getQuantity(x, MetricPrefix.MILLI(METRE)), Quantities.getQuantity(y, MetricPrefix.MILLI(METRE)), true);
-                    points.addPoint(point);
-                }
+            MasterRenderer renderer = new MasterRenderer(printer, representationParameters, format);
+            PrinterCapability mode = PrinterCapability.valueOf(printer.getProperty("mode").toString().toUpperCase());
+            Iterator<? extends PrintableData> outputPages;
+            SvgExporter<? extends AbstractCanvas> svgExporter;
+            switch (mode) { // Decide on correct rendering mode to apply
+                case NORMALPRINTER:
+                    RasterCanvas rasterCanvas = renderer.rasterize(diagram);
+                    svgExporter = new BoolMatrixDataSvgExporter(rasterCanvas);
+                    outputPages = rasterCanvas.getPageIterator();
+                    break;
+                case INDEX_EVEREST_D_V4_FLOATINGDOT_PRINTER:
+                    PlotCanvas plotCanvas = new PlotCanvas(printer, representationParameters, format); // TODO: call renderer.plot()
+                    svgExporter = new BoolFloatingPointDataSvgExporter(plotCanvas);
+                    outputPages = plotCanvas.getPageIterator();
+                    break;
+                default: throw new UnsupportedOperationException("Mode not supported: " + mode);
             }
 
-            SvgExporter<PlotCanvas> floatSvgExporter = new BoolFloatingPointDataSvgExporter(floatCanvas);
-            floatSvgExporter.render();
-            floatSvgExporter.dump("floatingPointData");
-            LiblouisBrailleTextRasterizer textRasterizer = new LiblouisBrailleTextRasterizer(indexV4Printer);
-            renderer.getRenderingBase().registerRasterizer(new FunctionalRasterizer<BrailleText>(BrailleText.class, textRasterizer));
-            RasterCanvas refCanvas = renderer.rasterize(new BrailleText(" ", new Rectangle(0, 0, 0, 0)));
-            mat = (SimpleMatrixDataImpl<Boolean>) canvas.getCurrentPage();
-            mLogger.debug("Render preview:\n" + mat.toBoolString());
+            // Action switches
+            boolean doPrint = !settingsReader.isTrue(SettingType.INHIBIT_PRINT).orElse(false);
+            boolean doSvgExport = settingsReader.isPresent(SettingType.SVG_EXPORT);
+            boolean doByteDump = settingsReader.isPresent(SettingType.BYTE_DUMP);
 
-
-
-            // Check if some SpoolerService/Printservice exists
-            if (!PrintDirector.isPrintServiceOn()) {
-                throw new Exception("Can't find any Printservices on this System.");
+            // SVG exporting
+            if (doSvgExport) {
+                File svgBaseFile = new File(settingsReader.getSetting(SettingType.SVG_EXPORT).get());
+                svgExporter.render();
+                svgExporter.dump(svgBaseFile.getAbsolutePath());
             }
 
-            /*
-             We do not want to actually print on each run.
-            Until CLI parsing is fully integrated, you will have to disable this check by hand if you actually do
-            want to print.
-            Please do not commit changes to this.
-            */
-            if (true) {
-                return EXIT_SUCCESS;
+            // Printing and Byte Dumping
+            PrintDirector printD = new PrintDirector(mode, printer);
+            if (doPrint && !PrintDirector.isPrintServiceOn()) { // Check for running spooler or print service
+                throw new Exception("Can't find any running print services on this system.");
+            }
+            File dumpBaseFile = null; // Setup dump base file if required
+            if (doByteDump) {
+                dumpBaseFile = new File(settingsReader.getSetting(SettingType.BYTE_DUMP).get());
+            }
+            int pageNumber = 0;
+            while (outputPages.hasNext()) { // Iterate pages
+                PrintableData page = outputPages.next();
+                if (doByteDump) { // Byte dump
+                    try (FileOutputStream outputStream = new FileOutputStream(dumpBaseFile.getAbsolutePath() + String.format("_%03d.bin", pageNumber))) {
+                        outputStream.write(printD.byteDump(page));
+                    } catch (IOException ex) {
+                        // Inform user, but do not stop execution
+                        mLogger.error("An error occured while creating byte dump", ex);
+                        throw new RuntimeException();
+                    }
+                }
+                if (doPrint) { // Print page
+                    printD.print(page);
+                }
+                pageNumber++;
             }
-
-            // Last Step: Printing
-            @SuppressWarnings("checkstyle:MagicNumber")
-            String printerConfigUpperCase = indexV4Printer.getProperty("mode").toString().toUpperCase();
-            PrintDirector printD = new PrintDirector(PrinterCapability.valueOf(printerConfigUpperCase), indexV4Printer);
-            printD.print(mat);
-
         } catch (final Exception e) {
             terminateWithException(e);
         }
@@ -261,4 +291,9 @@ public final class App {
 
         return EXIT_SUCCESS;
     }
+
+    public static void setLoggingLevel(final Level level) {
+        ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
+        root.setLevel(level);
+    }
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParser.java b/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParser.java
index 81e77493f2815a72fe27a5da3ea8de51adb7a686..2ad445dea44aca67cafed64cecb46eb065d20e68 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParser.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParser.java
@@ -3,28 +3,49 @@ package de.tudresden.inf.mci.brailleplot.commandline;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.DefaultParser;
 import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 
+import java.util.Arrays;
+import java.util.Objects;
+
+
 /**
  * Performs command line parsing and creates a {@link Settings} object.
- * @author Georg Graßnick
- * @version 2019.05.31
+ * @author Georg Graßnick, Andrey Ruzhanskiy, Leonard Kupper
+ * @version 2019.10.03
  */
 public class CommandLineParser {
 
     private Options mOptions;
 
+    public static Option helpOption = Option.builder("h")
+            .longOpt("help")
+            .required(false)
+            .hasArg(false)
+            .desc("Print help and exit")
+            .build();
+
     public CommandLineParser() {
         setupOptions();
     }
 
     private void setupOptions() {
         mOptions = new Options();
-        mOptions.addOption("h", SettingType.DISPLAY_HELP.toString(), false, "Print help and exit")
-                .addOption("c", SettingType.CSV_LOCATION.toString(), true, "Path to CSV")
-                .addOption("s", SettingType.SEMANTIC_MAPPING.toString(), true, "Literal for semantic mapping")
-                .addOption("p", SettingType.PRINTER_CONFIG_PATH.toString(), true, "Path to printer configuration file");
+        mOptions.addOption(helpOption)
+                .addRequiredOption("c", SettingType.CSV_LOCATION.toString(), true, "Path to CSV")
+                .addRequiredOption("p", SettingType.PRINTER_CONFIG_PATH.toString(), true, "Path to printer configuration file")
+                .addRequiredOption("t", SettingType.DIAGRAM_TITLE.toString(), true, "Title of the diagram")
+                .addRequiredOption("d", SettingType.DIAGRAM_TYPE.toString(), true, "Type of the diagram. Possible Values: [ScatterPlot, LineChart, BarChart]")
+                .addOption("x", SettingType.X_AXIS_LABEL.toString(), true, "Label of X-axis including unit")
+                .addOption("y", SettingType.Y_AXIS_LABEL.toString(), true, "Label of Y-axis including unit")
+                .addOption("f", SettingType.FORMAT.toString(), true, "Name of predefined format from configuration (A4 portrait if not specified)")
+                .addOption("v", SettingType.VERTICAL_CSV.toString(), false, "Parse CSV in vertical instead of horizontal orientation (Only applicable for BarChart)")
+                .addOption("i", SettingType.INHIBIT_PRINT.toString(), false, "Inhibit the printing process")
+                .addOption("s", SettingType.SVG_EXPORT.toString(), true, "Base file path for export of svg file(s) (Omit '.svg' suffix)")
+                .addOption("b", SettingType.BYTE_DUMP.toString(), true, "Base file path for print data byte dump file(s) (Omit '.bin' suffix)")
+                .addOption("l", SettingType.LOG_LEVEL.toString(), true, "Logging output level. Possible Values: [All, Trace, Debug, Info, Warn, Error, Off] Defaults to 'Info'");
     }
 
     /**
@@ -45,13 +66,35 @@ public class CommandLineParser {
         return new Settings(cmdLine);
     }
 
+    public static boolean checkForHelp(final String[] args)  {
+
+        boolean hasHelp = false;
+        Options options = new Options();
+        options.addOption(helpOption);
+        org.apache.commons.cli.CommandLineParser parser = new DefaultParser();
+        CommandLine cmd = null;
+        try {
+            cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            // Will occur if any other option than "help" is encountered
+            // For this case we can safely ignore it.
+        }
+        if ((Objects.nonNull(cmd) && cmd.hasOption(helpOption.getOpt()))
+                || (args.length == 0)
+                || (Arrays.asList(args).contains("-" + helpOption.getOpt())
+                || (Arrays.asList(args).contains("--" + helpOption.getLongOpt())))) {
+            hasHelp = true;
+        }
+        return hasHelp;
+    }
+
     /**
      * Print usage information to the command line.
      */
     public final void printHelp() {
         HelpFormatter formatter = new HelpFormatter();
         String headerForOptions = "Convert csv into braille";
-        String footerForOptions = "Report Issues to Leonard Kupper";
+        String footerForOptions = ""; // TODO: Add footer with version and official contact.
 
         formatter.printHelp("braillegraphics", headerForOptions, mOptions, footerForOptions, true);
     }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/SettingType.java b/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/SettingType.java
index 010c9c528891ffdb81549f715eac363625469e76..c8154bc15e62744a5db2a6e715e760565682e844 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/SettingType.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/commandline/SettingType.java
@@ -2,15 +2,25 @@ package de.tudresden.inf.mci.brailleplot.commandline;
 
 /**
  * Represents all possible parsed options parsed from the command line.
- * @author Georg Graßnick
- * @version 2019.05.31
+ * @author Georg Graßnick, Andrey Ruzhanskiy, Leonard Kupper
+ * @version 2019.10.03
  */
 public enum SettingType {
 
     DISPLAY_HELP("help"),
     CSV_LOCATION("csv-path"),
     PRINTER_CONFIG_PATH("printer-config-path"),
-    SEMANTIC_MAPPING("semantic-mapping");
+    DIAGRAM_TITLE("title"),
+    X_AXIS_LABEL("xLabel"),
+    Y_AXIS_LABEL("yLabel"),
+    DIAGRAM_TYPE("diagram-type"),
+    FORMAT("format"),
+    VERTICAL_CSV("vertical-csv"),
+    INHIBIT_PRINT("inhibit-print"),
+    SVG_EXPORT("svg-export"),
+    BYTE_DUMP("byte-dump"),
+    LOG_LEVEL("log-level");
+
 
     private final String mName;
 
@@ -26,8 +36,26 @@ public enum SettingType {
                 return  CSV_LOCATION;
             case "printer-config-path":
                 return PRINTER_CONFIG_PATH;
-            case "semantic-mapping":
-                return SEMANTIC_MAPPING;
+            case "title":
+                return DIAGRAM_TITLE;
+            case "xLabel":
+                return X_AXIS_LABEL;
+            case "yLabel":
+                return Y_AXIS_LABEL;
+            case "diagram-type":
+                return DIAGRAM_TYPE;
+            case "format":
+                return FORMAT;
+            case "vertical-csv":
+                return VERTICAL_CSV;
+            case "inhibit-print":
+                return INHIBIT_PRINT;
+            case "svg-export":
+                return SVG_EXPORT;
+            case "byte-dump":
+                return BYTE_DUMP;
+            case "log-level":
+                return LOG_LEVEL;
             default:
                 throw new IllegalArgumentException("Setting not available");
         }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java
index ccfcf8f8bccdbf26f84730890e4ef2855a2e3d45..5f4f4dc62d17d6c2cf3b366a7d5f880726365915 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java
@@ -1,6 +1,7 @@
 package de.tudresden.inf.mci.brailleplot.configparser;
 
 
+import de.tudresden.inf.mci.brailleplot.rendering.language.BrailleLanguage;
 import de.tudresden.inf.mci.brailleplot.util.GeneralResource;
 import de.tudresden.inf.mci.brailleplot.printerbackend.PrinterCapability;
 import org.slf4j.Logger;
@@ -76,6 +77,8 @@ public final class JavaPropertiesConfigurationValidator implements Configuration
 
         // Definition of valid representation properties
         defineRepresentationProperty("general.nonexistentDataText", requireNotEmpty);
+        defineRepresentationProperty("general.brailleLanguage", requireNotEmpty);
+        defineRepresentationProperty("general.legendKeyword", requireNotEmpty);
         defineRepresentationProperty("general.maxTitleHeight", requireInteger.and(requirePositive).and(requireNonZero));
         defineRepresentationProperty("rasterize.barChart.maxBarThickness", requireInteger.and(requirePositive));
         defineRepresentationProperty("rasterize.barChart.minBarThickness", requireInteger.and(requirePositive));
@@ -98,6 +101,9 @@ public final class JavaPropertiesConfigurationValidator implements Configuration
                 case "brailletable":
                 case "semantictable":
                     return new GeneralResource(value, mSearchPath).getResourcePath();
+                case "general.brailleLanguage":
+                    BrailleLanguage.Language language = BrailleLanguage.Language.valueOf(value.toUpperCase());
+                    return language.toString();
                 default: return value;
             }
         } catch (Exception e) {
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/PointList.java b/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/PointList.java
index 9d41811040a8de1dde43be7ac983d8af6517ab18..668c5698fc8186bc2b0e20e1c738952016d15e0b 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/PointList.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/PointList.java
@@ -4,12 +4,13 @@ import de.tudresden.inf.mci.brailleplot.point.Point2DDouble;
 
 import java.util.ListIterator;
 
+
 /**
  * Interface for a list-like data structure that holds a set of {@link Point2DDouble}.
  * Implementing classes can be instantiated by data parser classes and are used as a data representation
  * for use of the rasterizer.
- * @author Georg Graßnick
- * @version 2019.07.29
+ * @author Georg Graßnick, Andrey Ruzhanskiy
+ * @version 2019.09.24
  */
 public interface PointList extends PointContainer<Point2DDouble>, Named {
 
@@ -19,4 +20,10 @@ public interface PointList extends PointContainer<Point2DDouble>, Named {
      */
     ListIterator<Point2DDouble> getListIterator();
 
+    /**
+     * Returns a sorted list copy in ascending fashion for the x-values.
+     * @return An {@link PointList} which is sorted by the x-values in ascending fashion.
+     */
+
+    PointList sortXAscend();
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java b/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java
index 278faef9e14388a1f41c95da276661c321ced7a9..5b6dd2faab37bd00c31098a3a7793efbfcd92459 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java
@@ -6,11 +6,12 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * A low effort implementation of {@link PointList}.
- * @author Georg Graßnick
- * @version 2019.07.29
+ * @author Georg Graßnick, Andrey Ruzhanskiy
+ * @version 2019.09.24
  */
 public class SimplePointListImpl extends AbstractPointContainer<Point2DDouble> implements PointList {
 
@@ -36,6 +37,21 @@ public class SimplePointListImpl extends AbstractPointContainer<Point2DDouble> i
         return mElements.listIterator();
     }
 
+    @Override
+    public PointList sortXAscend() {
+        PointList list = this;
+        List<Point2DDouble> temp = list.stream().sorted((o1, o2) -> {
+            if (o1.getX() < o2.getX()) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }).collect(Collectors.toList());
+        SimplePointListImpl result = new SimplePointListImpl(list.getName(), temp);
+        result.calculateExtrema();
+        return result;
+    }
+
     @Override
     public String getName() {
         return mName;
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/diagrams/LineChart.java b/src/main/java/de/tudresden/inf/mci/brailleplot/diagrams/LineChart.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5fcf6c24d1d3376bc584c2cdff2268682dfea46
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/diagrams/LineChart.java
@@ -0,0 +1,66 @@
+package de.tudresden.inf.mci.brailleplot.diagrams;
+
+import de.tudresden.inf.mci.brailleplot.datacontainers.PointList;
+import de.tudresden.inf.mci.brailleplot.datacontainers.PointListContainer;
+
+import java.util.Objects;
+
+/**
+ * Representation of a line chart with basic data functions. Implements Renderable.
+ * @author Andrey Ruzhanskiy
+ * @version 2019.08.17
+ */
+public class LineChart extends Diagram {
+
+    private PointListContainer<PointList> mData;
+
+    /**
+     * Constructor for a line chart.
+     * @param data The container, which holds the information about the datapoints.
+     */
+    public LineChart(final PointListContainer<PointList> data) {
+        Objects.requireNonNull(data);
+        mData = data;
+    }
+
+    /**
+     * Getter for the underlying Pointlistcontainer.
+     * @return Pointlistcontainer.
+     */
+    public PointListContainer<PointList> getData() {
+        return mData;
+    }
+
+    /**
+     * Getter for the minimum y-value.
+     * @return minimum y-value.
+     */
+    public double getMinY() {
+        return mData.getMinY();
+    }
+
+    /**
+     * Getter for the maximum y-value.
+     * @return maximum y-value.
+     */
+    public double getMaxY() {
+        return mData.getMaxY();
+    }
+
+    /**
+     * Getter for the minimum x-value.
+     * @return minimum x-value.
+     */
+    public double getMinX() {
+        return mData.getMinX();
+    }
+
+    /**
+     * Getter for the maximum x-value.
+     * @return maximum x-value.
+     */
+    public double getMaxX() {
+        return mData.getMaxX();
+    }
+
+}
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractDocumentBuilder.java b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractDocumentBuilder.java
index 690f112e977b7c7af386e3d0d9dfbd6ae4257cc3..8aff7615c903f5422b2963b34abf9ef074366e79 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractDocumentBuilder.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractDocumentBuilder.java
@@ -1,20 +1,21 @@
 package de.tudresden.inf.mci.brailleplot.printerbackend;
+
 import de.tudresden.inf.mci.brailleplot.brailleparser.AbstractBrailleTableParser;
-import de.tudresden.inf.mci.brailleplot.printabledata.MatrixData;
+import de.tudresden.inf.mci.brailleplot.printabledata.PrintableData;
 
 /**
  * This class provides an extension point for further implementation
  * and protocol building for documents that need to be send to the printer.
  * The common Interface is the getDocument() and assemble() method.
  * Its usable for all braille printers.
- * @param <T> Type of MatrixData.
+ * @param <T> Type of Data.
  * @author Andrey Ruzhanskiy
  * @version 28.05.2019
  */
 
-abstract class AbstractDocumentBuilder<T> {
+abstract class AbstractDocumentBuilder<T extends PrintableData> {
 
-    MatrixData<T> mData;
+    T mData;
 
 
     AbstractBrailleTableParser mParser;
@@ -24,6 +25,6 @@ abstract class AbstractDocumentBuilder<T> {
      * @param data Raw data to be printed without any escapes equences
      * @return Fully build document as byte[]
      */
-    abstract byte[] assemble(MatrixData<T> data);
+    abstract byte[] assemble(T data);
 
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractIndexV4Builder.java b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractIndexV4Builder.java
index b79ba6a7bd627ac0db6f1adb17ecf564ad7b1c7b..dd89611885c8b025529cfa9c8a31e0bd47b2319a 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractIndexV4Builder.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/AbstractIndexV4Builder.java
@@ -1,17 +1,20 @@
 package de.tudresden.inf.mci.brailleplot.printerbackend;
 
+import de.tudresden.inf.mci.brailleplot.printabledata.PrintableData;
+
 /**
  * Abstract class for Documents, that need special escape sequences for the Index Everest-V4.
  * All special documents (i.e. Floating Dot Area) should implement this class. All information taken
  * from the Index PrinterCapability Interface Protocol V5_V4 2ß16-05-13. All the variables with the respective values have no
  * particular order (except mStartTemporaryDoc, which must be at the beginning). All the variable names are set to
  * final, these are PrinterCapability specific values that should not be changed.
+ * @param <T>  Type of Data, must extend PrintableData.
  * @author Andrey Ruzhanskiy
  * @version 31.05.2019
  */
 
 @SuppressWarnings("checkstyle:MagicNumber")
-abstract class AbstractIndexV4Builder extends AbstractDocumentBuilder {
+abstract class AbstractIndexV4Builder<T extends PrintableData> extends AbstractDocumentBuilder<T> {
 
 
 
@@ -22,6 +25,10 @@ abstract class AbstractIndexV4Builder extends AbstractDocumentBuilder {
 
     final byte[] mStartTemporaryDoc = new byte[] {0x1B, 0x44};
 
+    final byte[] mStartFloatingMode = new byte[] {0x1B, 0x46};
+
+    final byte[] mNewLine = new byte[] {0x0A};
+
     /**
      * Standard variable name for binding margin (BI).
      */
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/FloatingDotAreaBuilder.java b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/FloatingDotAreaBuilder.java
index b16826be2e92e2ace441eafc47927548f932a5f1..032d0c750a7227187f03f748948cbef11ad732be 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/FloatingDotAreaBuilder.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/FloatingDotAreaBuilder.java
@@ -1,16 +1,28 @@
 package de.tudresden.inf.mci.brailleplot.printerbackend;
 
 
-import de.tudresden.inf.mci.brailleplot.printabledata.MatrixData;
+import de.tudresden.inf.mci.brailleplot.point.Point2DValued;
+import de.tudresden.inf.mci.brailleplot.printabledata.SimpleFloatingPointDataImpl;
+import tec.units.ri.unit.MetricPrefix;
+
+import javax.measure.Quantity;
+import javax.measure.quantity.Length;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Objects;
+
+import static tec.units.ri.unit.Units.METRE;
 
 /**
- * Class representing the FloatingDotAre protocol for the braille Index Everest V4 for printing
+ * Class representing the FloatingDotArea protocol for the braille Index Everest V4 for printing
  * variable areas on paper via coordinates.
  * @author Andrey Ruzhanskiy, Leonard Kupper
  * @version 29.05.2019
  */
 
-class FloatingDotAreaBuilder extends AbstractIndexV4Builder {
+class FloatingDotAreaBuilder extends AbstractIndexV4Builder<SimpleFloatingPointDataImpl<Boolean>> {
 
     /**
      * Constructor. Does not have any functionality. Should only be used in  {@link PrintDirector}
@@ -19,10 +31,38 @@ class FloatingDotAreaBuilder extends AbstractIndexV4Builder {
 
     /**
      * Currently not implemented.
-     * @param data Raw data to be printed without any escape sequences
+     * @param data Raw data to be printed via the FloatingDotArea
      * @return Exception.
      */
-    byte[] assemble(final MatrixData data) {
-        throw new UnsupportedOperationException();
+    @Override
+    byte[] assemble(final SimpleFloatingPointDataImpl<Boolean> data) {
+        mData = Objects.requireNonNull(data);
+        Iterator<Point2DValued<Quantity<Length>, Boolean>> iter = mData.getIterator();
+        ByteArrayOutputStream stream = new ByteArrayOutputStream();
+        try {
+            stream.write(mStartFloatingMode);
+            stream.write(mSemicolon);
+            stream.write(mNewLine);
+            // Start iteration over values
+            while (iter.hasNext()) {
+                Point2DValued<Quantity<Length>, Boolean> current = iter.next();
+                Quantity<Length> x = current.getX().to(MetricPrefix.MILLI(METRE));
+                Quantity<Length> y = current.getY().to(MetricPrefix.MILLI(METRE));
+                String xFormated = String.format(Locale.ENGLISH, "%.2f", x.getValue().doubleValue());
+                String yFormated = String.format(Locale.ENGLISH, "%.2f", x.getValue().doubleValue());
+                stream.write(xFormated.getBytes());
+                stream.write(mColon);
+                stream.write(yFormated.getBytes());
+                if (iter.hasNext()) {
+                    stream.write(mNewLine);
+                }
+            }
+            // End with ;
+            stream.write(mSemicolon);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return stream.toByteArray();
+        //return null;
     }
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/GraphicPrintBuilder.java b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/GraphicPrintBuilder.java
index a51107b5ca0fa00cee02ff52dc7ef6038d187afd..ad72df45ec0a0d0c249308aa4f315f49aee95b9e 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/GraphicPrintBuilder.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/GraphicPrintBuilder.java
@@ -7,7 +7,7 @@ import de.tudresden.inf.mci.brailleplot.printabledata.MatrixData;
  * Class representing the graphic mode protocol from braille Index Everest D4.
  * @author Andrey Ruzhanskiy
  */
-class GraphicPrintBuilder extends AbstractIndexV4Builder {
+class GraphicPrintBuilder extends AbstractIndexV4Builder<MatrixData> {
 
     /**
      * Constructor. Does not have any functionality. Should only be used in  {@link PrintDirector}
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/NormalBuilder.java b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/NormalBuilder.java
index 39cee042a55d6c3fec38ea239205db5265fec999..27919f292b0f18a563170d459265a0f3c93fa3a4 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/NormalBuilder.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/NormalBuilder.java
@@ -16,7 +16,7 @@ import java.util.Objects;
  * @version 12.07.2019
  */
 @SuppressWarnings("checkstyle:MagicNumber")
-class NormalBuilder extends AbstractDocumentBuilder<Boolean> {
+class NormalBuilder extends AbstractDocumentBuilder<MatrixData<Boolean>> {
 
 
     /**
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/PrintDirector.java b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/PrintDirector.java
index 1ac2ba4a64afa11f20d56f63b2f90ec277c5fa7d..0868ad0387fdd4d8b0092af226f160636cd30ed2 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/PrintDirector.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/printerbackend/PrintDirector.java
@@ -2,19 +2,23 @@ package de.tudresden.inf.mci.brailleplot.printerbackend;
 
 
 import de.tudresden.inf.mci.brailleplot.configparser.Printer;
-import de.tudresden.inf.mci.brailleplot.printabledata.MatrixData;
+import de.tudresden.inf.mci.brailleplot.printabledata.PrintableData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+
+import javax.print.Doc;
 import javax.print.DocFlavor;
 import javax.print.DocPrintJob;
 import javax.print.PrintException;
 import javax.print.PrintService;
 import javax.print.PrintServiceLookup;
-import javax.print.Doc;
-
 import javax.print.SimpleDoc;
 import javax.print.attribute.HashPrintRequestAttributeSet;
 import javax.print.attribute.PrintRequestAttributeSet;
 import javax.print.attribute.standard.JobName;
+import javax.print.attribute.standard.PrinterState;
+import javax.print.event.PrintJobEvent;
 import java.util.Objects;
 /**
  * Implements a variation of the GoF design pattern Builder. This class is used for setting the printer configuration and
@@ -29,6 +33,7 @@ public class PrintDirector {
     private PrintService mService;
     private String mPrinterName;
     private DocFlavor mDocflavor;
+    private final Logger mLogger = LoggerFactory.getLogger(PrintDirector.class);
     private DocPrintJob mPrintJob;
 
 
@@ -44,14 +49,20 @@ public class PrintDirector {
         Objects.requireNonNull(printerConfig);
         this.mPrinter = printerCap;
         mPrinterName = printerConfig.getProperty("name").toString();
+        mLogger.trace("Using following printercapability {}", printerCap.toString(), " loaded");
+        mLogger.info("Using the following printer: {}", mPrinterName);
         switch (mPrinter) {
             case NORMALPRINTER:
-                mBuilder = new NormalBuilder(); break;
+                mBuilder = new NormalBuilder();
+                mLogger.trace("Using NormalBuilder as protocol");
+                break;
             case INDEX_EVEREST_D_V4_GRAPHIC_PRINTER:
                 mBuilder = new GraphicPrintBuilder();
+                mLogger.trace("Using Index Everest-D V4 graphic print as protocol");
                 break;
             case INDEX_EVEREST_D_V4_FLOATINGDOT_PRINTER:
                 mBuilder = new FloatingDotAreaBuilder();
+                mLogger.trace("Using Index Everest-D V4 floatingdot as protocol");
                 break;
             default: throw new IllegalArgumentException();
         }
@@ -61,26 +72,48 @@ public class PrintDirector {
     /**
      * Public method for printing the given document with the given data.
      * @param data {@link de.tudresden.inf.mci.brailleplot.printabledata.MatrixData} to be printed.
-     * @param <T> The type of {@link MatrixData}.
      */
 
 
     // Needed if someone tries to use a normal builder with something that is not a boolean.
 
     @SuppressWarnings("unchecked")
-    public <T> void print(final MatrixData<T> data)  {
+    public void print(final PrintableData data)  {
+        mLogger.info("Starting with print process");
         Objects.requireNonNull(data);
+        mLogger.info("Setting up docflavour and service");
         setUpDoc();
         setUpService();
         byte[] result;
+        mLogger.info("Finished setting up doc and service");
         try {
+            mLogger.trace("Assembling the data according to protocol: {}", mBuilder.getClass().getCanonicalName());
             result = mBuilder.assemble(data);
         } catch (ClassCastException e) {
             throw new IllegalArgumentException(e.getMessage(), e);
         }
+        mLogger.info("Finished assembling data");
         print(result);
     }
 
+    /**
+     * Method for creating the byte array form the printing process.
+     * @param data Data to be later dumped.
+     * @return Byte array containing the sequence for the printer.
+     */
+    @SuppressWarnings("unchecked")
+    public byte[] byteDump(final PrintableData data) {
+        mLogger.info("Starting with textdump process");
+        byte[] result;
+        try {
+            mLogger.trace("Assembling the data according to protocol: {}", mBuilder.getClass().getCanonicalName());
+            result = mBuilder.assemble(data);
+        } catch (ClassCastException e) {
+            throw new IllegalArgumentException(e.getMessage(), e);
+        }
+        mLogger.info("Finished with creating textdump");
+        return result;
+    }
     /**
      * Method for setting up the DocFlavor for printing. Currently, not parameterised because the printer can
      * (hopefully) understand raw bytes with an octet stream.
@@ -117,12 +150,24 @@ public class PrintDirector {
         Objects.requireNonNull(data);
         Objects.requireNonNull(mService);
         Objects.requireNonNull(mDocflavor);
+        mLogger.info("Setting up doc, asset and job");
         Doc doc = new SimpleDoc(data, mDocflavor, null);
         PrintRequestAttributeSet asset = new HashPrintRequestAttributeSet();
         DocPrintJob job = mService.createPrintJob();
+        mLogger.trace("Finished setting up doc, asset and job");
+        PrinterState state;
         asset.add(new JobName("Braille Printing", null));
         try {
+            mLogger.trace("Adding job to the PrintJobListener");
+            PrintJobListener listener = new PrintJobListener();
+            job.addPrintJobListener(listener);
+            mLogger.trace("Starting printing");
+            //PrinterIsAcceptingJobs set = mService.getAttribute(PrinterIsAcceptingJobs.class);
+            //PrinterStateReasons reasons = mService.getAttribute(PrinterStateReasons.class);
             job.print(doc, asset);
+            //set = mService.getAttribute(PrinterIsAcceptingJobs.class);
+            //reasons = mService.getAttribute(PrinterStateReasons.class);
+            listener.waitForDone();
             mPrintJob = job;
         } catch (PrintException pe) {
             throw new RuntimeException(pe);
@@ -141,4 +186,69 @@ public class PrintDirector {
         }
         return true;
     }
+
+    /**
+     * Eventlistener which receives updates regarding printing.
+     * Because of enormous shortcoming in the implementation of printing in java, some events are never received.
+     */
+    private class PrintJobListener implements javax.print.event.PrintJobListener {
+        boolean done = false;
+
+        @Override
+        public void printDataTransferCompleted(final PrintJobEvent pje) {
+            mLogger.info("Data transfer to printer complete");
+        }
+
+        @Override
+        public void printJobCompleted(final PrintJobEvent pje) {
+            mLogger.info("Printjob completed");
+            synchronized (PrintJobListener.this) {
+                done = true;
+                PrintJobListener.this.notify();
+            }
+        }
+
+        @Override
+        public void printJobFailed(final PrintJobEvent pje) {
+            mLogger.info("Printjob failed");
+            synchronized (PrintJobListener.this) {
+                done = true;
+                PrintJobListener.this.notify();
+            }
+        }
+
+        @Override
+        public void printJobCanceled(final PrintJobEvent pje) {
+            mLogger.info("Printjob was canceled");
+            synchronized (PrintJobListener.this) {
+                done = true;
+                PrintJobListener.this.notify();
+            }
+        }
+
+        @Override
+        public void printJobNoMoreEvents(final PrintJobEvent pje) {
+            mLogger.info("Printjob has no more events");
+            synchronized (PrintJobListener.this) {
+                done = true;
+            }
+        }
+
+        @Override
+        public void printJobRequiresAttention(final PrintJobEvent pje) {
+            mLogger.info("Printjob requires attention");
+            PrintJobListener.this.notify();
+        }
+        public synchronized void waitForDone() {
+            try {
+                // Not busy waiting, sleeping as long as not notified.
+                while (!done) {
+                    wait();
+                }
+            } catch (InterruptedException e) {
+                return;
+            }
+        }
+    }
+
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Axis.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Axis.java
index 2406f03bfd54140e03172cf95387152317f4a03f..0f282f0bbcb4cd472ba5bf6ee1c5dcbf437a60f9 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Axis.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Axis.java
@@ -26,7 +26,7 @@ public class Axis implements Renderable {
      * @param type Just changes the orientation of the axis. Can be either {@link Axis.Type#X_AXIS} or {@link Axis.Type#Y_AXIS}.
      * @param originX The x coordinate of the position where the axis line and the tickmark and label corresponding to the value '0' is placed.
      * @param originY The y coordinate of the position where the axis line and the tickmark and label corresponding to the value '0' is placed.
-     * @param stepWidth The distance between two tickmarks on the axis.
+     * @param stepWidth The distance between two tickmarks on the axis in dots.
      * @param tickSize The size and orientation of the tickmarks. The absolute value controls the length, the sign controls on which side they are displayed.
      */
     public Axis(final Type type, final double originX, final double originY, final double stepWidth,
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BarChartRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BarChartRasterizer.java
index e9a1c3eaaeddcd943793bccce0570c9dbef7431b..5aab47f95fd240c13888b42d04498df8aae895f6 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BarChartRasterizer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BarChartRasterizer.java
@@ -54,6 +54,7 @@ public class BarChartRasterizer implements Rasterizer<CategoricalBarChart> {
     private int mGroupPaddingCells; // the padding size between two neighbouring bar groups in cells
     private int mBarPaddingCells; // the padding size between two bars inside the same group in cells
     private String nonexistentDataText; // the text which is displayed for a missing datapoint
+    private BrailleLanguage.Language mBrailleLanguage; // the preferred language & level for titles, captions, ...
 
     // Texture Management
     private List<Texture<Boolean>> mTextures = new ArrayList<>(); // A list of textures to differentiate bars inside a group
@@ -98,6 +99,8 @@ public class BarChartRasterizer implements Rasterizer<CategoricalBarChart> {
 
         nonexistentDataText = canvas.getRepresentation().getProperty("general.nonexistentDataText").toString();
 
+        mBrailleLanguage = BrailleLanguage.Language.valueOf(canvas.getRepresentation().getProperty("general.brailleLanguage").toString());
+
         // Load textures
         double[] rotate90 = {0, 0, 0, 1, 1, 0};
         registerTexture(new Texture<>(TexturedArea.BOTTOM_T_PATTERN).applyAffineTransformation(rotate90), 0, 0);
@@ -139,7 +142,7 @@ public class BarChartRasterizer implements Rasterizer<CategoricalBarChart> {
             // PHASE 1 - LAYOUT: The following calculations will divide the canvas area to create the basic chart layout.
             // Diagram Title
             String title = diagram.getTitle();
-            int titleLength = mTextRasterizer.getBrailleStringLength(title);
+            int titleLength = mTextRasterizer.getBrailleStringLength(title, mBrailleLanguage);
             int titleHeight = (int) Math.ceil(titleLength / referenceCellArea.getWidth());
             if (titleHeight > mMaximumTitleHeightCells) {
                 throw new InsufficientRenderingAreaException("Title is too long. (Exceeds maximum height)");
@@ -198,20 +201,20 @@ public class BarChartRasterizer implements Rasterizer<CategoricalBarChart> {
 
             // PHASE 2 - RASTERIZING: Now, every element of the chart will be drawn onto the according area.
             // Diagram Title
-            mTextRasterizer.rasterize(new BrailleText(title, titleDotArea), canvas);
+            mTextRasterizer.rasterize(new BrailleText(title, titleDotArea, mBrailleLanguage), canvas);
             // Y-Axis: no units, no tickmarks
             Axis yAxis = new Axis(Axis.Type.Y_AXIS, originXDotCoordinate, originYDotCoordinate, 1, 0);
             yAxis.setBoundary(yAxisDotArea);
             mAxisRasterizer.rasterize(yAxis, canvas);
             // Y-Axis name
-            mTextRasterizer.rasterize(new BrailleText(diagram.getYAxisName(), yAxisNameDotArea), canvas);
+            mTextRasterizer.rasterize(new BrailleText(diagram.getYAxisName(), yAxisNameDotArea, mBrailleLanguage), canvas);
             // X-Axis: units and labels
             Axis xAxis = new Axis(Axis.Type.X_AXIS, originXDotCoordinate, originYDotCoordinate, X_AXIS_UNIT_SIZE_DOTS, X_AXIS_TICK_SIZE_DOTS);
             xAxis.setBoundary(xAxisDotArea);
             xAxis.setLabels(generateNumericAxisLabels(xAxisScaling, xAxisScalingMagnitude, negativeAvailableUnits, positiveAvailableUnits));
             mAxisRasterizer.rasterize(xAxis, canvas);
             // X-Axis name
-            mTextRasterizer.rasterize(new BrailleText(diagram.getXAxisName(), xAxisNameDotArea), canvas);
+            mTextRasterizer.rasterize(new BrailleText(diagram.getXAxisName(), xAxisNameDotArea, mBrailleLanguage), canvas);
             // The actual groups and bars:
             // This is done by iterating through the diagram data set and drawing borders with the respective padding based on whether switched
             // from one bar to another or a group to another. In between, the bars are rasterized as textured areas, with a line on the bars top.
@@ -270,7 +273,7 @@ public class BarChartRasterizer implements Rasterizer<CategoricalBarChart> {
             }
 
             // PHASE 3 - DIAGRAM LEGEND: Symbols and textures are explained in the legend which will be created by the LegendRasterizer
-            Legend diagramLegend = new Legend(title); // Create a legend container
+            Legend diagramLegend = new Legend(title, mBrailleLanguage); // Create a legend container
             diagramLegend.addSymbolExplanation("Achsenskalierung:", "X-Achse", "Faktor " + xAxisScalingMagnitude); // Explain axis scaling
             diagramLegend.addSymbolExplanationGroup("Kategorien:", groupNameExplanations); // Explain bar group single character captions
             if (textureExplanations.size() > 1) { // Explain textures (if multiple of them were used)
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleText.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleText.java
index 786a34ff1bbd019f63bbc3f01bb0e7ad2a023295..12be5aa30abae24fc2e7b747744e6baa57e88173 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleText.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleText.java
@@ -15,6 +15,10 @@ public class BrailleText implements Renderable {
     private String mContent;
     private Rectangle mArea;
 
+    /**
+     * Getter for the associated language used in this braille text.
+     * @return String containing the language
+     */
     public String getLanguage() {
         return mLanguage;
     }
@@ -32,7 +36,7 @@ public class BrailleText implements Renderable {
         mLanguage = "de-g0.utb";
     }
 
-    public BrailleText(final String content, final Rectangle area, BrailleLanguage.Language language) {
+    public BrailleText(final String content, final Rectangle area, final BrailleLanguage.Language language) {
         setText(content);
         setArea(area);
         mLanguage = BrailleLanguage.getCorrectLanguage(language);
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleTextRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleTextRasterizer.java
index c0e89d1131bfe096a1e63fab871f3637c4f527e1..2cb6cf2b4db756b8d06ea6fe56f8cc9f752a0a3f 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleTextRasterizer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/BrailleTextRasterizer.java
@@ -11,7 +11,6 @@ import de.tudresden.inf.mci.brailleplot.printerbackend.NotSupportedFileExtension
 
 /**
  * A rasterizer for text on braille grids. This class is still a stub and must be implemented!
-<<<<<<< HEAD
  * @version 2019.08.17
  * @author Leonard Kupper, Andrey Ruzhanskiy
  */
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Legend.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Legend.java
index 1f4b13c4d97c55a9971da6323b5e6b23c3f4f762..feb7567a30891b594a71ebcfa90739af0ed532fe 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Legend.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Legend.java
@@ -1,29 +1,45 @@
 package de.tudresden.inf.mci.brailleplot.rendering;
 
+import de.tudresden.inf.mci.brailleplot.rendering.language.BrailleLanguage;
+
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Objects;
 
 /**
  * Simple representation of a legend.
- * @author Leonard Kupper
- * @version 2019.08.29
+ * @author Leonard Kupper, Andrey Ruzhanskiy
+ * @version 2019.09.25
  */
 public class Legend implements Renderable {
 
     private String mTitle;
+    private BrailleLanguage.Language mLanguage;
     private Map<String, Map<String, String>> mStringExplanationLists = new LinkedHashMap<>();
     private Map<String, Map<Texture<Boolean>, String>> mTextureExplanationLists = new LinkedHashMap<>();
+    private String mColumnViewTitle;
 
+    private Map<String, Map<String, String>> mColumnView = new LinkedHashMap<>();
     private int mTextureExampleWidthCells = 1;
     private int mTextureExampleHeightCells = 1;
 
     /**
-     * Constructor. Creates a legend.
+     * Constructor. Creates a legend with default language (DE_BASISSCHRIFT).
      * @param title The title of the legend.
      */
     public Legend(final String title) {
         setTitle(title);
+        setLanguage(BrailleLanguage.Language.DE_BASISSCHRIFT);
+    }
+
+    /**
+     * Constructor. Creates a legend with a defined language.
+     * @param title The title of the legend.
+     * @param language A {@link BrailleLanguage.Language}.
+     */
+    public Legend(final String title, final BrailleLanguage.Language language) {
+        setTitle(title);
+        setLanguage(language);
     }
 
     /**
@@ -34,6 +50,14 @@ public class Legend implements Renderable {
         mTitle = Objects.requireNonNull(title);
     }
 
+    /**
+     * Sets the braille language and level.
+     * @param language The new language.
+     */
+    public void setLanguage(final BrailleLanguage.Language language) {
+        mLanguage = Objects.requireNonNull(language);
+    }
+
     /**
      * Gets the current title of the legend.
      * @return A {@link String} containing the title.
@@ -42,6 +66,14 @@ public class Legend implements Renderable {
         return mTitle;
     }
 
+    /**
+     * Gets the current braille language and level.
+     * @return A {@link BrailleLanguage.Language} determining the language and braille level.
+     */
+    public BrailleLanguage.Language getLanguage() {
+        return mLanguage;
+    }
+
     /**
      * Add a text symbol and the associated description text to the legend.
      * @param groupName The name of the header under which explanations of this group will be placed. (e.g. "Categories")
@@ -55,6 +87,40 @@ public class Legend implements Renderable {
         mStringExplanationLists.get(groupName).put(symbol, descriptionText);
     }
 
+    /**
+     * Add a column to the columnview.
+     * @param columnName Name of column.
+     * @param explanations {@link Map} of symbols and descriptions inside the column.
+     */
+    public void addColumn(final String columnName, final Map<String, String> explanations) {
+            mColumnView.put(columnName, explanations);
+    }
+
+    /**
+     * Set the columnview title.
+     * @param columnViewTitle The title for the columnview.
+     */
+    public void setColumnViewTitle(final String columnViewTitle) {
+        this.mColumnViewTitle = columnViewTitle;
+    }
+
+    /**
+     * Getter for the column-view.
+     * @return {@link Map} representing the columnview.
+     */
+    public Map<String, Map<String, String>> getColumnView() {
+        return mColumnView;
+    }
+
+    /**
+     * Getter for the columnview-title.
+     * @return {@link String} representing the columnview-title.
+     */
+    public String getColumnViewTitle() {
+        return mColumnViewTitle;
+    }
+
+
     /**
      * Add a texture and the associated description text to the legend.
      * @param groupName The name of the header under which explanations of this group will be placed. (e.g. "Series")
@@ -119,4 +185,5 @@ public class Legend implements Renderable {
     final int getTextureExampleHeightCells() {
         return mTextureExampleHeightCells;
     }
+
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LegendRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LegendRasterizer.java
index 76509b4e26c9e24254127709d508b82387810283..68d31c85f541132713dad209f1c7526d00086481 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LegendRasterizer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LegendRasterizer.java
@@ -4,13 +4,15 @@ import de.tudresden.inf.mci.brailleplot.layout.InsufficientRenderingAreaExceptio
 import de.tudresden.inf.mci.brailleplot.layout.RasterCanvas;
 import de.tudresden.inf.mci.brailleplot.layout.Rectangle;
 import de.tudresden.inf.mci.brailleplot.printabledata.MatrixData;
+import de.tudresden.inf.mci.brailleplot.rendering.language.BrailleLanguage;
 import java.util.Map;
 import static java.lang.Integer.max;
+import static java.lang.StrictMath.min;
 
 /**
  * A rasterizer that is able to draw a legend on a new page.
- * @author Leonard Kupper
- * @version 2019.08.28
+ * @author Leonard Kupper, Andrey Ruzhanskiy
+ * @version 2019.09.25
  */
 public class LegendRasterizer implements Rasterizer<Legend> {
 
@@ -19,7 +21,9 @@ public class LegendRasterizer implements Rasterizer<Legend> {
 
     private static final int MIN_TEXT_WIDTH_CELLS = 10; // how much space should be available for an explanation text at least. (To avoid excessive line breaking)
     private static final int EXPLANATION_TEXT_INDENTATION_CELLS = 1; // indentation for explanation texts.
-    private static final String LEGEND_KEYWORD = "Legende:"; // title for the legend
+    private BrailleLanguage.Language mLanguage;
+    private String mLegendKeyword; // title for the legend
+    private static final BrailleLanguage.Language EXPLANATION_LIST_LANGUAGE = BrailleLanguage.Language.DE_BASISSCHRIFT;
 
     // Sub rasterizers
     private LiblouisBrailleTextRasterizer mTextRasterizer;
@@ -36,44 +40,86 @@ public class LegendRasterizer implements Rasterizer<Legend> {
         mTextRasterizer = new LiblouisBrailleTextRasterizer(canvas.getPrinter());
         mCanvas = canvas;
         mLegend = legend;
+        mLegendKeyword = mCanvas.getRepresentation().getProperty("general.legendKeyword").toString();
 
         // Create a fresh page on the canvas.
-        MatrixData<Boolean> page = canvas.getNewPage();
+        canvas.getNewPage();
         Rectangle referenceCellArea = canvas.getCellRectangle();
 
         try {
 
             // Write "Legend" keyword + title
-            writeLine(LEGEND_KEYWORD + " " + legend.getTitle(), referenceCellArea);
+            setLanguage(legend.getLanguage());
+            writeLine(mLegendKeyword + " " + legend.getTitle(), referenceCellArea);
 
-            // String explanation lists
-            for (Map.Entry<String, Map<String, String>> list : legend.getSymbolExplanationGroups().entrySet()) {
+            // Texture explanation lists
+            for (Map.Entry<String, Map<Texture<Boolean>, String>> list : legend.getTextureExplanationGroups().entrySet()) {
                 String groupName = list.getKey();
+                setLanguage(legend.getLanguage());
                 writeLine("", referenceCellArea); // Leave space of one empty line
-                writeLine(groupName + ":", referenceCellArea);
+                writeLine(groupName, referenceCellArea);
                 moveIndentation(referenceCellArea, EXPLANATION_TEXT_INDENTATION_CELLS); // set indentation
-                for (Map.Entry<String, String> explanation : list.getValue().entrySet()) {
-                    String symbol = explanation.getKey();
+                setLanguage(EXPLANATION_LIST_LANGUAGE);
+                for (Map.Entry<Texture<Boolean>, String> explanation : list.getValue().entrySet()) {
+                    Texture<Boolean> texture = explanation.getKey();
                     String description = explanation.getValue();
-                    writeLine(symbol + " - " + description, referenceCellArea);
+                    drawTextureExample(referenceCellArea, texture, description);
                 }
                 moveIndentation(referenceCellArea, -1 * EXPLANATION_TEXT_INDENTATION_CELLS); // reset indentation
             }
 
-            // Texture explanation lists
-            for (Map.Entry<String, Map<Texture<Boolean>, String>> list : legend.getTextureExplanationGroups().entrySet()) {
+            // String explanation lists
+            for (Map.Entry<String, Map<String, String>> list : legend.getSymbolExplanationGroups().entrySet()) {
                 String groupName = list.getKey();
+                setLanguage(legend.getLanguage());
                 writeLine("", referenceCellArea); // Leave space of one empty line
-                writeLine(groupName + ":", referenceCellArea);
+                writeLine(groupName, referenceCellArea);
                 moveIndentation(referenceCellArea, EXPLANATION_TEXT_INDENTATION_CELLS); // set indentation
-                for (Map.Entry<Texture<Boolean>, String> explanation : list.getValue().entrySet()) {
-                    Texture<Boolean> texture = explanation.getKey();
+                setLanguage(EXPLANATION_LIST_LANGUAGE);
+                for (Map.Entry<String, String> explanation : list.getValue().entrySet()) {
+                    String symbol = explanation.getKey();
                     String description = explanation.getValue();
-                    drawTextureExample(referenceCellArea, texture, description);
+                    writeLine(symbol + "  " + description, referenceCellArea);
                 }
                 moveIndentation(referenceCellArea, -1 * EXPLANATION_TEXT_INDENTATION_CELLS); // reset indentation
             }
 
+            // Columnview
+            if (legend.getColumnView().size() > 0) {
+                setLanguage(legend.getLanguage());
+                writeLine(legend.getColumnViewTitle(), referenceCellArea);
+                for (Map.Entry<String, Map<String, String>> list : legend.getColumnView().entrySet()) {
+                    Rectangle columnCellArea = new Rectangle(referenceCellArea);
+                    setLanguage(legend.getLanguage());
+                    writeLine(list.getKey(), columnCellArea);
+                    int maxWidth = 0;
+                    for (Map.Entry<String, String> explanation : list.getValue().entrySet()) {
+                        String symbol = explanation.getKey();
+                        String description = explanation.getValue();
+                        String textToWrite = symbol + "  " + description;
+
+                        setLanguage(EXPLANATION_LIST_LANGUAGE);
+                        try {
+                            int usedWidth = writeLine(textToWrite, columnCellArea);
+                            if (usedWidth > maxWidth) {
+                                maxWidth = usedWidth;
+                            }
+                        } catch (Rectangle.OutOfSpaceException e) {
+                            referenceCellArea.removeFromLeft(maxWidth + 1);
+                            maxWidth = 0;
+                            columnCellArea = new Rectangle(referenceCellArea);
+                            columnCellArea.removeFromTop(1);
+                            int usedWidth = writeLine(textToWrite, columnCellArea);
+                            if (usedWidth > maxWidth) {
+                                maxWidth = usedWidth;
+                            }
+                        }
+
+                    }
+                    referenceCellArea.removeFromLeft(maxWidth + 1 + EXPLANATION_TEXT_INDENTATION_CELLS);
+                }
+            }
+
         } catch (Rectangle.OutOfSpaceException e) {
             throw new InsufficientRenderingAreaException("The amount of data in the legend does not fit on the format.", e);
         }
@@ -131,15 +177,23 @@ public class LegendRasterizer implements Rasterizer<Legend> {
         cellArea.setWidth(cellArea.getWidth() - indent);
     }
 
-    private void writeLine(final String text, final Rectangle cellArea) throws InsufficientRenderingAreaException, Rectangle.OutOfSpaceException {
+    private int writeLine(final String text, final Rectangle cellArea) throws InsufficientRenderingAreaException, Rectangle.OutOfSpaceException {
         if (cellArea.getWidth() < MIN_TEXT_WIDTH_CELLS) {
             throw new InsufficientRenderingAreaException("Not enough space for legend text.");
         }
         // write text lines
-        int textLength = mTextRasterizer.getBrailleStringLength(text);
+        int textLength = mTextRasterizer.getBrailleStringLength(text, getLanguage());
         int textHeight = max(1, (int) Math.ceil(textLength / cellArea.getWidth()));
         Rectangle textLineDotArea = mCanvas.toDotRectangle(cellArea.removeFromTop(textHeight));
-        mTextRasterizer.rasterize(new BrailleText(text, textLineDotArea), mCanvas);
+        mTextRasterizer.rasterize(new BrailleText(text, textLineDotArea, getLanguage()), mCanvas);
+        return min(textLength, cellArea.intWrapper().getWidth());
     }
 
+    private void setLanguage(final BrailleLanguage.Language language) {
+        mLanguage = language;
+    }
+
+    private BrailleLanguage.Language getLanguage() {
+        return mLanguage;
+    }
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
index e214755c5ff66fbe0a4b534b26d63eb1aa081b3b..08201f0a21e60d78e40478073803bdbb92582d7d 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
@@ -85,9 +85,7 @@ public class LiblouisBrailleTextRasterizer implements Rasterizer<BrailleText> {
         TranslationResult result = null;
         try {
             result = mTranslator.translate(data.getText(), null, null, null, DisplayTable.StandardDisplayTables.DEFAULT);
-        } catch (TranslationException e) {
-            e.printStackTrace();
-        } catch (DisplayException e) {
+        } catch (TranslationException | DisplayException e) {
             e.printStackTrace();
         }
         String[] resultAsArray = result.getBraille().split("");
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LineChartRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LineChartRasterizer.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7c44f2d795f4b0db3ede022a72bada6c1f96967
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LineChartRasterizer.java
@@ -0,0 +1,565 @@
+package de.tudresden.inf.mci.brailleplot.rendering;
+
+import de.tudresden.inf.mci.brailleplot.datacontainers.PointList;
+import de.tudresden.inf.mci.brailleplot.datacontainers.SimplePointListImpl;
+import de.tudresden.inf.mci.brailleplot.diagrams.LineChart;
+import de.tudresden.inf.mci.brailleplot.layout.InsufficientRenderingAreaException;
+import de.tudresden.inf.mci.brailleplot.layout.RasterCanvas;
+import de.tudresden.inf.mci.brailleplot.layout.Rectangle;
+import de.tudresden.inf.mci.brailleplot.point.Point2DDouble;
+import de.tudresden.inf.mci.brailleplot.rendering.language.BrailleLanguage;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+import java.util.TreeMap;
+
+import static java.lang.Math.abs;
+import static java.lang.Math.ceil;
+import static java.lang.Math.log10;
+import static java.lang.Math.pow;
+import static java.lang.StrictMath.floor;
+import static java.lang.StrictMath.round;
+
+/**
+ * Class representing a line chart rasterizer.
+ * @author Andrey Ruzhanskiy
+ * @version 2019.09.24
+ */
+public class LineChartRasterizer implements Rasterizer<LineChart> {
+    private LineChart mDiagram;
+    private RasterCanvas mCanvas;
+
+    private LiblouisBrailleTextRasterizer mTextRasterizer;
+    private LinearMappingAxisRasterizer mAxisRasterizer;
+    private Legend mLegend;
+    private final double tenth = 0.1, fifth = 0.2, quarter = 0.25, half = 0.5;
+    private final double[] mUnitScalings = new double[]{tenth, fifth, quarter, half, 1.0};
+
+    private int mXStepWidth;
+    private int mYStepWidth;
+    private double mDpiX;
+    private double mDpiY;
+    private final int  mPaddingBetweenAxisTextAndDiagram = 3;
+    private final int mPaddingXandYText = 1;
+    private Rectangle mCellLineArea;
+    private boolean mPrintOnSamePaper = false; // If you want to print on the same paper, change this variable to true.
+    private BrailleLanguage.Language mLanguage;
+    private int mTitleHeight;
+    private int mPaddingToTitle = 1;
+
+
+    LineChartRasterizer() {
+        mAxisRasterizer = new LinearMappingAxisRasterizer();
+    }
+
+    /**
+     * Method for rasterizing a {@link LineChart}-diagram.
+     * This approach of an algorithm is minimaly adjustable by design, the algorithm for itself tries to find the best fitting
+     * for the given dataset.
+     * @param data The renderable representation.
+     * @param canvas An instance of {@link RasterCanvas} representing the target for the rasterizer output.
+     * @throws InsufficientRenderingAreaException If the data can not be rasterized due to shortcomings of the algorithm
+     *                                              or because the data was too big.
+     */
+    @Override
+    public void rasterize(final LineChart data, final RasterCanvas canvas) throws InsufficientRenderingAreaException {
+        if (data.equals(null)) {
+            throw new NullPointerException("The given data for the LineChartRasterizer was null!");
+        }
+        if (canvas.equals(null)) {
+            throw new NullPointerException("The given canvas for the LineChartRasterizer was null!");
+        }
+        mLanguage = BrailleLanguage.Language.valueOf(canvas.getRepresentation().getProperty("general.brailleLanguage").toString());
+        mTitleHeight = canvas.getRepresentation().getProperty("general.maxTitleHeight").toInt();
+        mTextRasterizer = new LiblouisBrailleTextRasterizer(canvas.getPrinter());
+        mLegend = new Legend(data.getTitle(), mLanguage); //
+
+        mCanvas = canvas;
+        mDiagram = data;
+        // Important: Its a cell rectangle, not a dot rectangle.
+        mCellLineArea = mCanvas.getCellRectangle();
+
+        // ITS CALCULATION TIME //
+
+        // Step one: Calculate area needed for the title.
+        Rectangle titleArea = calculateTitle();
+        Rectangle yAxisText;
+        Rectangle xAxisText;
+        try {
+            yAxisText = canvas.toDotRectangle(mCellLineArea.removeFromTop(mPaddingXandYText));
+            xAxisText = canvas.toDotRectangle(mCellLineArea.removeFromBottom(mPaddingXandYText));
+        } catch (Rectangle.OutOfSpaceException e) {
+            throw new InsufficientRenderingAreaException("The axis text cant fit to the layout.", e);
+        }
+
+        // Step two: Calculate area needed for the x/y axis.
+        Rectangle xAxisArea = calculateXAxis();
+        Rectangle yAxisArea = calculateYAxis();
+
+        // Step three: Calculate various things needed for computing the most simple approach for the x axis.
+        double rangeOfXValues = valueRangeOfXAxis();
+        int xUnitsAvailable = calculateUnitsWidthInCells(xAxisArea);
+        mDpiX = calculateDPI(rangeOfXValues, xUnitsAvailable);
+        mXStepWidth = (int) findXAxisStepWidth(rangeOfXValues, xUnitsAvailable);
+        int xNumberOfTicks = (int) getNumberOfTicks(xUnitsAvailable);
+        Rectangle xAxisBound = xAxisArea.scaledBy(mCanvas.getCellWidth(), mCanvas.getCellHeight());  // Change to canvas convert toDotRectangle
+        int originY = xAxisBound.intWrapper().getY();
+        int originX = xAxisBound.intWrapper().getX();
+
+        // Step four: Same thing for the y axis.
+        Rectangle yAxisBound = yAxisArea.scaledBy(mCanvas.getCellWidth(), mCanvas.getCellHeight());
+        int yOriginY = originY - 1; // Drawing the diagram so that the y = 0 lies not on the x axis
+        int yOriginX = yAxisBound.intWrapper().getRight();
+        double rangeOfYValues = valueRangeOfYAxis();
+        int yUnitsAvailable = calculateUnitsHeightInCells(yAxisArea);
+        mYStepWidth =  findYAxisStepWidth(rangeOfYValues, yUnitsAvailable);
+        mDpiY = calculateDPI(rangeOfYValues, yUnitsAvailable);
+        int yNumberOfTicks = (int) getNumberOfTicks(yUnitsAvailable);
+
+        // Step five: Setting correct labels for x and y axis.
+        Map<String, String> xLabelsForLegend = new TreeMap<>();
+        Map<String, String> yLabelsForLegend = new TreeMap<>();
+        Map<Integer, String> xLabels = setCorrectLabelsforX(rangeOfXValues, xNumberOfTicks, mDpiX, xLabelsForLegend);
+        Map<Integer, String> yLabels = setCorrectLabelsforY(rangeOfYValues, yNumberOfTicks, mDpiY, yLabelsForLegend);
+
+        // Step six: Filling the legend.
+        mLegend.addSymbolExplanation("Achsenskalierung:", "X-Achse", "Faktor " + mDpiX);
+        mLegend.addSymbolExplanation("Achsenskalierung:", "Y-Achse", "Faktor " + mDpiY);
+        mLegend.setColumnViewTitle("Werte der Tickmarks");
+        setLabelsXForLegend(xLabelsForLegend);
+        setLabelsYForLegend(yLabelsForLegend);
+
+        // Step seven: Iterate through the lines, rasterize the axis for each paper.
+        LegendRasterizer mLegendRasterizer = new LegendRasterizer();
+        Iterator<PointList> iter  = mDiagram.getData().iterator();
+        while (iter.hasNext()) {
+            rasterizeTitle(data.getTitle(), titleArea);
+            rasterizeXAxis(originY, originX, mXStepWidth, xAxisBound, xLabels);
+            rasterizeYAxis(yOriginY, yOriginX, mYStepWidth, yAxisBound, yLabels);
+            mTextRasterizer.rasterize(new BrailleText(data.getYAxisName(), yAxisText, BrailleLanguage.Language.GERMAN_BASISSCHRIFT), mCanvas);
+            mTextRasterizer.rasterize(new BrailleText(data.getXAxisName(), xAxisText, BrailleLanguage.Language.GERMAN_BASISSCHRIFT), mCanvas);
+            rasterizeData(mDiagram.getMinX(), mDiagram.getMinY(), iter.next());
+            if (iter.hasNext() && !mPrintOnSamePaper) {
+                mCanvas.getNewPage();
+            }
+        }
+        // Last Step eight: Rasterize the legend (only needed one time).
+        mLegendRasterizer.rasterize(mLegend, mCanvas);
+    }
+
+    // Various helper methods //
+
+    /**
+     * Method for setting the correct x-labels to the {@link Legend}.
+     * Places first the value of the map and then the corresponding key.
+     * @param labelsForLegend A map containing the values and the letters which will be put on the legend.
+     */
+    private void setLabelsXForLegend(final Map<String, String> labelsForLegend) {
+        mLegend.addColumn("X-Achse", labelsForLegend);
+    }
+
+    /**
+     * Method for setting the correct y-labels to the {@link Legend}.
+     * Places first the value of the map and then the corresponding key.
+     * @param labelsForLegend A map containing the values and the letters which will be put on the legend.
+     */
+    private void setLabelsYForLegend(final Map<String, String> labelsForLegend) {
+        mLegend.addColumn("Y-Achse", labelsForLegend);
+    }
+
+    /**
+     * Method for rasterizing the data inside a {@link LineChart}.
+     * @param globalMinX The global minimum of the x values in the {@link LineChart}.
+     * @param globalMinY The global minimum of the y values in the {@link LineChart}.
+     * @param next The {@link PointList} containing the data for rasterization.
+     */
+    private void rasterizeData(final double globalMinX, final double globalMinY, final PointList next) {
+        PointList sorted = next.sortXAscend();
+        SimplePointListImpl points = rasterizePoints(sorted, globalMinX, globalMinY);
+        Iterator<Point2DDouble> iter = points.getListIterator();
+        Point2DDouble previous = null;
+        while (iter.hasNext()) {
+            Point2DDouble current = iter.next();
+            if (previous == null) {
+                previous = current;
+                continue;
+            }
+            // Here you can swap bresenham to a new linerasterizing algorithm
+            bresenham(previous.getX(), previous.getY(), current.getX(), current.getY());
+            previous = current;
+        }
+    }
+
+    /**
+     * Bresenham algorithm for rasterizing lines.
+     * Important: It translates the y coordinates to a normal coordinate-system. Currently, the Y-coordinate of the
+     * {@link RasterCanvas} lies on the left upper corner, representing 0. But Bresenham assumes the Y-coordinate lies
+     * in the left buttom corner. The difference is that the Y-Coordinate grows in a normal coordinate system as it lies
+     * further and further above, but in a {@link RasterCanvas} it actually decreases as it goes further up.
+     * Before setting the point on to the {@link RasterCanvas} it translates it back to the {@link RasterCanvas}-coordinate
+     * system.
+     * @param xStart X-coordinate of the startpoint.
+     * @param yStart Y-coordinate of the startpoint.
+     * @param xEnd X-coordinate of the endpoint.
+     * @param yEnd Y-coordinate of the endpoint.
+     */
+    @SuppressWarnings("avoidinlineconditionals")
+    private void bresenham(final Double xStart, final Double yStart, final Double xEnd, final Double yEnd) {
+        int y0 = (int) (mCanvas.toDotRectangle(mCellLineArea).intWrapper().getHeight() - yStart);
+        int y1 = (int) (mCanvas.toDotRectangle(mCellLineArea).intWrapper().getHeight() - yEnd);
+        int x0 = (int) (xStart.doubleValue());
+        int x1 = (int) (xEnd.doubleValue());
+        int dx =  abs(x1 - x0);
+        int dy = -abs(y1 - y0);
+        int sx = x0 < x1 ? 1 : -1;
+        int sy = y0 < y1 ? 1 : -1;
+        int err = dx + dy;
+        int e2;
+        while (true) {
+            mCanvas.getCurrentPage().setValue((int) (mCanvas.toDotRectangle(mCellLineArea).getHeight() - y0), (int) x0, true);
+            if (x0 == x1 && y0 == y1) {
+                break;
+            }
+            e2 = 2 * err;
+            if (e2 > dy) {
+                err += dy;
+                x0 += sx;
+            }
+            if (e2 < dx) {
+                err += dx;
+                y0 += sy;
+            }
+        }
+    }
+
+    /**
+     * Method for rasterizing the points.
+     * @param list A {@link PointList} containing points which will be rasterized.
+     * @param globalMinX The global minimum of the x values in the {@link LineChart}.
+     * @param globalMinY The global minimum of the y values in the {@link LineChart}.
+     * @return The {@link SimplePointListImpl} containing the converted coordinates of the points.
+     */
+    private SimplePointListImpl rasterizePoints(final PointList list, final double globalMinX, final double globalMinY) {
+        Objects.requireNonNull(list, "The given PointList for the rasterization of points was null!");
+        double xMin = globalMinX;
+        double yMin = globalMinY;
+        Iterator<Point2DDouble> iter = list.getListIterator();
+        Rectangle canvas = mCanvas.toDotRectangle(mCellLineArea);
+        double canvasStartX = canvas.intWrapper().getX();
+        double canvasStartY = canvas.intWrapper().getBottom();
+        SimplePointListImpl result = new SimplePointListImpl();
+        while (iter.hasNext()) {
+            Point2DDouble current = iter.next();
+            double currentValueX = current.getX() - xMin;
+            double currentValueY = current.getY() - yMin;
+            double stepX = currentValueX / mDpiX;
+            double stepY = currentValueY / mDpiY;
+            result.pushBack(new Point2DDouble(round(canvasStartX + mXStepWidth * mCanvas.getCellWidth() * stepX), round(canvasStartY - mYStepWidth * mCanvas.getCellHeight() * stepY)));
+            mCanvas.getCurrentPage().setValue((int) round(canvasStartY - mYStepWidth * mCanvas.getCellHeight() * stepY), (int) round(canvasStartX + mXStepWidth * mCanvas.getCellWidth() * stepX), true);
+        }
+        result.calculateExtrema();
+        return result;
+    }
+
+
+    /**
+     * Method for creating a map containing the key-value pair for the datapoints for the y-axis. The key represents an integer, which has
+     * no special meaning (but is needed for the {@link LinearMappingAxisRasterizer}, the value is a letter which will be
+     * drawn on to the diagram. This same letter will appear on the legend with its representational value
+     * (for example: 'a' -> 0.5 ).
+     * @param rangeOfYValues The value range for the y datapoints.
+     * @param numberOfTicks The number of ticks wich will be drawn on to the diagram.
+     * @param dpi The resolution, or in other words, what one step for the tickmark along the axis means for the datapoints (for example 0.5 means
+     *            for each tickmark the coordinatesystem where the datapoints lies is increased by 0.5)
+     * @param yLabelsForLegend The map (can be empty, but must be initialized) in which the representation of the letters will be stored.
+     *                         For example: 2.5 -> a, 3.0 -> b and so on.
+     * @return A map containing the correct number of labels which will be needed to address all datapoints in {@link LineChart}.
+     */
+    @SuppressWarnings({"finalparameters", "magicnumber"})
+    private Map<Integer, String> setCorrectLabelsforY(final double rangeOfYValues, final int numberOfTicks, double dpi, Map<String, String> yLabelsForLegend) {
+        Objects.requireNonNull(yLabelsForLegend, "The given map for setting the correct labels for the y-axis was null!");
+        double min = mDiagram.getData().getMinY();
+        Map<Integer, String> result = new HashMap<>();
+        double tmpDpi = dpi;
+
+        // According to a not representative study the y axis should start with 'a' on the highest value, not the lowest.
+        // So we need to calculate an offset and decrement the letter
+        // Works currently only with letters represented in ASCII
+        int datapoints = (int) ceil(rangeOfYValues / dpi);
+        int range = 25; // Number of letters in the ASCII alphabet
+        int offset = range - datapoints;
+        byte z = 0x7A;
+        byte letterAsByte = (byte) (z - offset);
+        char letter = (char) letterAsByte;
+
+
+        for (int i = 0; i < numberOfTicks; i++) {
+            result.put(i, String.valueOf(letter));
+            if (i == 0) {
+                yLabelsForLegend.put(String.valueOf(letter), String.valueOf(min));
+            } else {
+                yLabelsForLegend.put(String.valueOf(letter), String.valueOf((dpi + min)));
+                dpi = dpi + tmpDpi;
+            }
+            letter--;
+            if (i >= datapoints) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Calculates the resolution (meaning how much in the datapoint we go if we do one tickmark-step).
+     * @param rangeOfValues The range of values in the {@link LineChart}.
+     * @param unitsAvailable How many units (Braillecells) are available on the axis.
+     * @return Double representing the resolution.
+     */
+    @SuppressWarnings("magicnumber")
+    private double calculateDPI(final double rangeOfValues, final int unitsAvailable) {
+        if (unitsAvailable < 0) {
+            throw new RuntimeException("The units available were less then zero!");
+        }
+        double minRangePerUnit = rangeOfValues / unitsAvailable; // this range must fit into one 'axis step'
+        double orderOfMagnitude = pow(10, ceil(log10(minRangePerUnit)));
+        double scaledRangePerUnit = 0;
+        for (double scaling : mUnitScalings) {
+            scaledRangePerUnit = (scaling * orderOfMagnitude);
+            if (scaledRangePerUnit >= minRangePerUnit) {
+                break;
+            }
+        }
+        return scaledRangePerUnit;
+    }
+
+    /**
+     * Method for creating a map containing the key-value pair for the datapoints for the x-axis. The key represents an integer, which has
+     * no special meaning (but is needed for the {@link LinearMappingAxisRasterizer}, the value is a letter which will be
+     * drawn on to the diagram. This same letter will appear on the legend with its representational value
+     * (for example: 'a' -> 0.5 ).
+     * @param rangeOfXValues The value range for the y datapoints.
+     * @param numberOfTicks The number of ticks wich will be drawn on to the diagram.
+     * @param dpi The resolution, or in other words, what one step for the tickmark along the axis means for the datapoints (for example 0.5 means
+     *            for each tickmark the coordinatesystem where the datapoints lies is increased by 0.5)
+     * @param xLabelsForLegend The map (can be empty, but must be initialized) in which the representation of the letters will be stored.
+     *                         For example: 2.5 -> a, 3.0 -> b and so on.
+     * @return A map containing the correct number of labels which will be needed to address all datapoints in {@link LineChart}.
+     */
+    @SuppressWarnings("finalparameters")
+    private Map<Integer, String> setCorrectLabelsforX(final double rangeOfXValues, final int numberOfTicks, double dpi, Map<String, String> xLabelsForLegend) {
+        Objects.requireNonNull(xLabelsForLegend, "The given map to set the correct labels for the x-axis was null!");
+        double min = mDiagram.getMinX();
+        Map<Integer, String> result = new HashMap<>();
+        double tmpDpi = dpi;
+        char letter = 'a';
+        double datapoints = rangeOfXValues / dpi;
+        for (int i = 0; i < numberOfTicks; i++) {
+            result.put(i, String.valueOf(letter));
+            if (i == 0) {
+                xLabelsForLegend.put(String.valueOf(letter), String.valueOf(min));
+            } else {
+                xLabelsForLegend.put(String.valueOf(letter), String.valueOf((dpi + min)));
+                dpi = dpi + tmpDpi;
+            }
+            letter++;
+            if (i >= datapoints) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Method for the calculation of the stepwidth for the y-axis on the canvas.
+     * Important: Not meant in the datapoints, but on the canvas. Currently returning 1.
+     * @param rangeOfYValues The range of values along the y-axis.
+     * @param yUnitsAvailable The number of available units along the y-axis, measured in braillecells.
+     * @return Integer representing the number of braillecells between two tickmarks.
+     */
+    private int findYAxisStepWidth(final double rangeOfYValues, final int yUnitsAvailable) {
+        // You can change the following step width to cater your needs.
+        // The minimum int taken by the y-axis rasterizer is 1
+        return 1;
+    }
+
+    /**
+     * Method for calculating the height for a given {@link Rectangle} in braillecells.
+     * @param rectangle The rectangle for which the height is computed.
+     * @return Integer, representing the height in braillecells.
+     */
+    private int calculateUnitsHeightInCells(final Rectangle rectangle) {
+        // Needed because one can get a height that encapsulates a fraction of a braillecell, so we need to ensure that
+        // we work on whole cells.
+        return (int) floor((rectangle.getHeight() * mCanvas.getCellHeight()) / mCanvas.getCellHeight());
+    }
+
+    /**
+     * Method for rasterizing the title of the diagram.
+     * @param title String which contains the title of the diagram.
+     * @param titleArea The {@link Rectangle} on which the the text will be rasterized.
+     */
+    private void rasterizeTitle(final String title, final Rectangle titleArea) {
+        BrailleText diagramTitle = new BrailleText(title, titleArea);
+        try {
+            mTextRasterizer.rasterize(diagramTitle, mCanvas);
+        } catch (InsufficientRenderingAreaException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Wrapper method for creating an X-{@link Axis} and rasterize it. Delegates to the {@link LinearMappingAxisRasterizer} for rasterizing.
+     * @param originY The y coordinate of the position where the axis line and the tickmark and label corresponding to the value '0' is placed.
+     * @param originX The x coordinate of the position where the axis line and the tickmark and label corresponding to the value '0' is placed.
+     * @param stepWidthX The distance between two tickmarks on the axis in cells. This will be automatically converted in dots for the {@link Axis}.
+     * @param xAxisBound The x-axis bound so that the borders are considered.
+     * @param labels Map containing the labels (letters).
+     */
+    private void rasterizeXAxis(final int originY, final int originX, final int stepWidthX, final Rectangle xAxisBound, final Map<Integer, String> labels) {
+        Axis xAxis = new Axis(Axis.Type.X_AXIS, originX, originY, stepWidthX * mCanvas.getCellWidth(), 2);
+        xAxis.setBoundary(xAxisBound);
+        xAxis.setLabels(labels);
+        Rectangle test = xAxis.getBoundary();
+        try {
+            mAxisRasterizer.rasterize(xAxis, mCanvas);
+        } catch (InsufficientRenderingAreaException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Wrapper method for creating an Y-{@link Axis} and rasterize it. Delegates to the {@link LinearMappingAxisRasterizer} for rasterizing.
+     * @param originY The y coordinate of the position where the axis line and the tickmark and label corresponding to the value '0' is placed.
+     * @param originX The x coordinate of the position where the axis line and the tickmark and label corresponding to the value '0' is placed.
+     * @param stepWidthY The distance between two tickmarks on the axis in cells. This will be automatically converted in dots for the {@link Axis}.
+     * @param yAxisBound The x-axis bound so that the borders are considered.
+     * @param labels {@link Map} containing the labels (letters).
+     */
+    @SuppressWarnings("magicnumber")
+    private void rasterizeYAxis(final int originY, final int originX, final int stepWidthY, final Rectangle yAxisBound, final Map<Integer, String> labels) {
+        Axis yAxis = new Axis(Axis.Type.Y_AXIS, originX, originY, stepWidthY * mCanvas.getCellHeight(), -2);
+        yAxis.setBoundary(yAxisBound);
+        yAxis.setLabels(labels);
+        try {
+            mAxisRasterizer.rasterize(yAxis, mCanvas);
+        } catch (InsufficientRenderingAreaException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Method for cutting off the right {@link Rectangle} from the whole {@link RasterCanvas}.
+     * Internally it uses the mDiagram variable.
+     * @return {@link Rectangle} with the correct length and width so that the diagramtitle can be rasterized on it.
+     * @throws InsufficientRenderingAreaException If the text is too big to fit on the {@link RasterCanvas}.
+     */
+    private Rectangle calculateTitle() throws InsufficientRenderingAreaException {
+        if (mDiagram.getTitle().isEmpty()) {
+            throw new IllegalArgumentException("The title in LineChartRasterizer was empty!");
+        }
+        int widthOfCompleteArea = mCellLineArea.intWrapper().getWidth();
+        int titleBarHeight = mTextRasterizer.calculateRequiredHeight(mDiagram.getTitle(), widthOfCompleteArea, mCanvas, BrailleLanguage.Language.GERMAN_BASISSCHRIFT);
+        try {
+            return  mCellLineArea.removeFromTop(mCanvas.getCellYFromDotY(mTitleHeight) + mPaddingToTitle);
+        } catch (Rectangle.OutOfSpaceException e) {
+            throw new InsufficientRenderingAreaException("Not enough space to build the title area for the line chart!");
+        }
+    }
+
+    /**
+     * Method for cutting off the right {@link Rectangle} from the whole {@link RasterCanvas}.
+     * Currently it cuts of from the bottom and left by the amount of the offset variable
+     * @return {@link Rectangle} for the x-axis.
+     * @throws InsufficientRenderingAreaException If the offset amount cant be cut off the mCellLineArea.
+     */
+    private Rectangle calculateXAxis() throws InsufficientRenderingAreaException {
+        Objects.requireNonNull(mCellLineArea, "The given Rectangle for the x axis to be removed from was null!");
+        try {
+            Rectangle result = mCellLineArea.removeFromBottom(mPaddingBetweenAxisTextAndDiagram);
+            result.removeFromLeft(mPaddingBetweenAxisTextAndDiagram);
+            return result;
+        } catch (Rectangle.OutOfSpaceException e) {
+            throw new InsufficientRenderingAreaException("Not enough space to build the X-Axis for the line chart!");
+        }
+    }
+
+    /**
+     * Method for cutting off the right {@link Rectangle} from the whole {@link RasterCanvas}.
+     * Currently it cuts of from the left by the amount of the offset variable
+     * @return {@link Rectangle} for the y-axis.
+     * @throws InsufficientRenderingAreaException If the offset amount cant be cut off the mCellLineArea.
+     */
+    private Rectangle calculateYAxis() throws InsufficientRenderingAreaException {
+        Objects.requireNonNull(mCellLineArea, "The given Rectangle for the y axis to be removed from was null!");
+        try {
+            return mCellLineArea.removeFromLeft(mPaddingBetweenAxisTextAndDiagram);
+        } catch (Rectangle.OutOfSpaceException e) {
+            throw new InsufficientRenderingAreaException("Not enough space to build the Y-Axis for the line chart!");
+        }
+    }
+
+    /**
+     * Method for calculating the valuerange of the x-axis.
+     * @return {@link Double} representing the value range of the x-axis.
+     */
+    private double valueRangeOfYAxis() {
+        Objects.requireNonNull(mDiagram, "The given linechart for the calculation of the value range of the y-axis was null!");
+        double minY = mDiagram.getMinY();
+        double maxY = mDiagram.getMaxY();
+        double valueRangeOfYAxis;
+        if (minY >= 0) {
+            valueRangeOfYAxis = maxY - minY;
+        } else {
+            valueRangeOfYAxis = abs(maxY) + abs(minY);
+        }
+        return valueRangeOfYAxis;
+    }
+
+    /**
+     * Calculate width, measured in cells. Important: it divides by two and floors the result. The current axis rasterizer
+     * does not support a width of 1.
+     * @param rectangle The cell rectangle which you want to know the width.
+     * @return Width in cells divided by two and floored.
+     */
+    private int calculateUnitsWidthInCells(final Rectangle rectangle) {
+        Objects.requireNonNull(rectangle, "The given rectangle for the calculation of its width was null!");
+        return (int) floor((rectangle.getWidth() - 1) / 2);
+    }
+
+    /**
+     * Method for calculating the value range of the x axis.
+     * @return {@link Double} representing the value range.
+     */
+    private double valueRangeOfXAxis() {
+        Objects.requireNonNull(mDiagram, "The given linechart for the calculation of the value range of the x-axis was null!");
+        double minX = mDiagram.getMinX();
+        double maxX = mDiagram.getMaxX();
+        return maxX - minX;
+    }
+
+    /**
+     * Returns the number of ticks. Currently, it adds one to the given parameter.
+     * @param unitsAvailable How many units are available on the x axis.
+     * @return {@link Double} representing ticks available.
+     */
+    private double getNumberOfTicks(final int unitsAvailable) {
+        if (unitsAvailable < 0) {
+            throw new RuntimeException("The units available was less then zero!");
+        }
+        return unitsAvailable + 1;
+    }
+
+    /**
+     * Method for finding the x axis step width.
+     * @param rangeOfXValues Representing the range of values.
+     * @param xUnitsAvailable Representing the availabe units on the xAxis.
+     * @return Currently always 2;
+     */
+    private double findXAxisStepWidth(final double rangeOfXValues, final int xUnitsAvailable) {
+        // Most simple approach: always take the minimum stepwidth, which the x-axis rasterizer can handle
+        // The signature is not adjusted so that someone can change the calculation if he needs it
+        return 2;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LinearMappingAxisRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LinearMappingAxisRasterizer.java
index f20e2e41121d5339009e78f45d9248f02e7f54b6..5fc0baaed683beeb392fb3675a140e294bc2ae2b 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LinearMappingAxisRasterizer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LinearMappingAxisRasterizer.java
@@ -127,7 +127,8 @@ public class LinearMappingAxisRasterizer implements Rasterizer<Axis> {
                 labelCellX = mCanvas.getCellXFromDotX(dotX + (mTickSize + labelOffset)) + labelOffset;
                 labelCellY = mCanvas.getCellYFromDotY(dotY);
                 if (mTickSize < 0) {
-                    labelCellArea = new Rectangle(labelCellX - (stringLength), labelCellY, stringLength, 1);
+                    // Calculate x position of first character in right aligned text
+                    labelCellArea = new Rectangle(labelCellX - (stringLength - 1), labelCellY, stringLength, 1);
                 } else {
                     labelCellArea = new Rectangle(labelCellX, labelCellY, stringLength, 1);
                 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/MasterRenderer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/MasterRenderer.java
index 7f41d757c56680a42633f8ca3397fdd9e8e53752..78b721d7175247763a63f116805f16239538ac5b 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/MasterRenderer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/MasterRenderer.java
@@ -6,6 +6,9 @@ import de.tudresden.inf.mci.brailleplot.diagrams.CategoricalBarChart;
 import de.tudresden.inf.mci.brailleplot.layout.InsufficientRenderingAreaException;
 import de.tudresden.inf.mci.brailleplot.layout.RasterCanvas;
 import de.tudresden.inf.mci.brailleplot.layout.SixDotBrailleRasterCanvas;
+
+import de.tudresden.inf.mci.brailleplot.diagrams.LineChart;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,11 +47,14 @@ public final class MasterRenderer {
         Rasterizer<CategoricalBarChart> barChartRasterizer = new BarChartRasterizer();
         Rasterizer<Image> linearImageMapping = new ImageRasterizer();
         Rasterizer<ScatterPlot> scatter = new ScatterPlotRasterizer();
+        Rasterizer<LineChart> lineChart = new LineChartRasterizer();
 
         mLogger.trace("Registering default rasterizers");
         renderingBase.registerRasterizer(new FunctionalRasterizer<CategoricalBarChart>(CategoricalBarChart.class, barChartRasterizer));
         renderingBase.registerRasterizer(new FunctionalRasterizer<Image>(Image.class, linearImageMapping));
         renderingBase.registerRasterizer(new FunctionalRasterizer<ScatterPlot>(ScatterPlot.class, scatter));
+        renderingBase.registerRasterizer(new FunctionalRasterizer<LineChart>(LineChart.class, lineChart));
+        //renderingBase.registerRasterizer(new FunctionalRasterizer<ScatterPlot>(ScatterPlot.class, ScatterPlotRasterizing::fooRasterizing));
         //...
 
         setRenderingContext(printer, representation, format, renderingBase);
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Texture.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Texture.java
index f4f85f46ad028d3f1fc6d91c38f98ebf375e4742..8fdacb2273ac662d488e49ded640224d3724c63b 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Texture.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/Texture.java
@@ -43,6 +43,7 @@ public class Texture<T> {
      *                       (x, y) is a vector describing the translation.
      *                       | a b |
      *                       | c d | is a linear transformation matrix.
+     * @return Returns a reference to this {@link Texture}.
      */
     public Texture<T> setAffineTransformation(final double[] transformation) {
         if ((transformation.length != TRANSLATION_SIZE) && (transformation.length != TRANSFORMATION_SIZE)) {
@@ -61,6 +62,7 @@ public class Texture<T> {
      *                       (x, y) is a vector describing the translation.
      *                       | a b |
      *                       | c d | is a linear transformation matrix.
+     * @return Returns a reference to this {@link Texture}.
      */
     @SuppressWarnings("checkstyle:MagicNumber")
     public Texture<T> applyAffineTransformation(final double[] transformation) {
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/language/BrailleLanguage.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/language/BrailleLanguage.java
index 724691c67c43636a23ce9fffa01e873ad1aa53f2..fd633ab8787bb48a2382c753c5f9b8980701e9f3 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/language/BrailleLanguage.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/language/BrailleLanguage.java
@@ -1,13 +1,20 @@
 package de.tudresden.inf.mci.brailleplot.rendering.language;
 
 /**
- * Helper class for braillelanguage
+ * Helper class for braillelanguage.
  * @author Andrey Ruzhanskiy
  * @version 27.09.2019
  */
+
+@SuppressWarnings("HideUtilityClassConstructor")
 public class BrailleLanguage {
 
-    public static String getCorrectLanguage(Language language){
+    /**
+     * Method to get the correct name of the table for the given enum.
+     * @param language Enum, for which the table is to be known.
+     * @return String containing the name of the table.
+     */
+    public static String getCorrectLanguage(final Language language) {
         switch (language) {
             case GERMAN_VOLLSCHRIFT:
             case DE_VOLLSCHRIFT:
@@ -18,11 +25,14 @@ public class BrailleLanguage {
             case GERMAN_KURZSCHRIFT:
             case DE_KURZSCHRIFT:
                 return "de-g2.ctb";
+            default:
+                throw new RuntimeException("Unsupported language given as braillelanguage!  \"" + language.toString() + "\"");
         }
-        throw new RuntimeException("Unsupported language given as braillelanguage!  \"" + language.toString() + "\"");
     }
 
-
+    /**
+     * Enum describing the current supported braille languages and grammars.
+     */
     public enum Language {
         DE_KURZSCHRIFT,
         DE_BASISSCHRIFT,
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/language/package-info.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/language/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..61d15ce437090456f96c52d9827fac4e2be7c3fd
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/language/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * This package contains the language helper class and the braille language declaration.
+ */
+package de.tudresden.inf.mci.brailleplot.rendering.language;
\ No newline at end of file
diff --git a/src/main/resources/config/default.properties b/src/main/resources/config/default.properties
index 90039e37e7cf88ab4cc97bc4c9cc44245a26bdc7..74da5a7ca6688fbec357278ba89697217519bfbd 100644
--- a/src/main/resources/config/default.properties
+++ b/src/main/resources/config/default.properties
@@ -50,14 +50,16 @@ printer.raster.dotDiameter=1.5
 format.default.page.width=210
 format.default.page.height=297
 format.default.margin.top=0
-format.default.margin.left=0
+format.default.margin.left=5
 format.default.margin.bottom=0
 format.default.margin.right=0
 
 ### Diagram Formatting
 ### ==================
 
+representation.general.brailleLanguage=DE_BASISSCHRIFT
 representation.general.nonexistentDataText=n/a
+representation.general.legendKeyword=Legende:
 representation.general.maxTitleHeight=2
 representation.rasterize.barChart.maxBarThickness=3
 representation.rasterize.barChart.minBarThickness=1
diff --git a/src/main/resources/config/index_basic_d.properties b/src/main/resources/config/index_basic_d.properties
index 0d83722d223c7941fa8953e7ca3a0164e17dee49..a403fe0b95f708fa625bfd40829235555bee2d74 100644
--- a/src/main/resources/config/index_basic_d.properties
+++ b/src/main/resources/config/index_basic_d.properties
@@ -1,7 +1,7 @@
 # JProperties Printer & Format Configuration
 #
 # Embosser: Index Basic-D
-# Version 1 Rev. 4 (19-08-21)
+# Version 1 Rev. 5 (19-10-01)
 #
 # Description:
 # This is the main configuration file for use with the braille plot application
@@ -17,7 +17,6 @@
 
 printer.name=Index Basic-D V3
 printer.mode=normalprinter
-printer.brailletable=src/main/resources/mapping/eurobraille.properties
 printer.floatingDot.support=false
 
 # The following values represent the fixed indentation and maximum technical printing area of the embosser.
diff --git a/src/main/resources/config/standard_formats.properties b/src/main/resources/config/standard_formats.properties
index c3aee460f7adb21daafa6f86885548069edbd01f..502ca9e5465090f2e850f98e4e411a256e00cdb0 100644
--- a/src/main/resources/config/standard_formats.properties
+++ b/src/main/resources/config/standard_formats.properties
@@ -17,6 +17,16 @@ format.A4.margin.left=10
 format.A4.margin.bottom=0
 format.A4.margin.right=0
 
+
+### A4 Landscape Format No Margin
+### ===================
+format.A4L.page.width=297
+format.A4L.page.height=210
+format.A4L.margin.top=0
+format.A4L.margin.left=5
+format.A4L.margin.bottom=0
+format.A4L.margin.right=0
+
 ### A5 Format Standard
 ### ===================
 format.A5.page.width=148
diff --git a/src/main/resources/examples/csv/1_scatter_plot.csv b/src/main/resources/examples/csv/1_scatter_plot.csv
index 904d14586cc75f52b04e835a7a1802ba6894570c..c90c77fe69fa65fe7f492f6859dea5a2614b8031 100644
--- a/src/main/resources/examples/csv/1_scatter_plot.csv
+++ b/src/main/resources/examples/csv/1_scatter_plot.csv
@@ -1,5 +1,6 @@
-Linie1, ,1,7,9,2,10
-        ,1,2,5,4,10
-Linie2, ,0,2,7,9,1,4
-        ,3,9,4,2,5,7
-
+Erste Gruppe,"2,14577671155962","3,83957088149638","2,74381418592686","4,44040259535766","3,05835335915677","3,51347910532925","4,50752129340682","3,10684847076423"
+,"1,86189289220467","0,845650622246947","1,62491581811196","0,716873892169058","1,07960644510134","1,25420442725184","0,868213570630901","0,3131242131342"
+Zweite Gruppe,"2,13687514878477","1,0900468273911","0,202664216808808","-0,117994978447507","1,91197730783847","0,472235461102831","1,01858439429409","1,54912208686837"
+,"0,983807817453276","2,34845526278731","0,785524371519466","0,220854402806683","1,77117365732932","3,01226487117459","-0,327141232914824","-0,210388758733043"
+Dritte Gruppe,"4,11271848986168","4,99244908180646","5,98316851481515","4,95765061866595","4,00636404848764","5,49799175180235","4,34309770180236","5,36675690932105"
+,"5,09261289722065","4,92838187744164","4,47540951345638","3,45104975190378","5,64998407245105","4,88914941630864","5,92876353824873","6,67452703834106"
diff --git a/src/main/resources/examples/csv/2_1_line_plot_equal_distance.csv b/src/main/resources/examples/csv/2_1_line_plot_equal_distance.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f7982779a1fd188735db9af69f5a7eeb7ff494d4
--- /dev/null
+++ b/src/main/resources/examples/csv/2_1_line_plot_equal_distance.csv
@@ -0,0 +1,5 @@
+Linie1, ,1,5,7,3,9
+        ,1,2,5,4,10
+Linie2, ,0,2,4,6,8,10
+        ,3,9,4,2,5,7
+
diff --git a/src/main/resources/examples/csv/2_line_plot - small.csv b/src/main/resources/examples/csv/2_line_plot - small.csv
new file mode 100644
index 0000000000000000000000000000000000000000..c715ad8052b2455f8f1971bbf70fc89cdf82f249
--- /dev/null
+++ b/src/main/resources/examples/csv/2_line_plot - small.csv	
@@ -0,0 +1,4 @@
+Linie1, ,"0,1","0,7","0,9","0,2",1
+        ,"0,1","0,2","0,5","0,4",1
+
+
diff --git a/src/main/resources/examples/csv/2_line_plot.csv b/src/main/resources/examples/csv/2_line_plot.csv
index c90c77fe69fa65fe7f492f6859dea5a2614b8031..904d14586cc75f52b04e835a7a1802ba6894570c 100644
--- a/src/main/resources/examples/csv/2_line_plot.csv
+++ b/src/main/resources/examples/csv/2_line_plot.csv
@@ -1,6 +1,5 @@
-Erste Gruppe,"2,14577671155962","3,83957088149638","2,74381418592686","4,44040259535766","3,05835335915677","3,51347910532925","4,50752129340682","3,10684847076423"
-,"1,86189289220467","0,845650622246947","1,62491581811196","0,716873892169058","1,07960644510134","1,25420442725184","0,868213570630901","0,3131242131342"
-Zweite Gruppe,"2,13687514878477","1,0900468273911","0,202664216808808","-0,117994978447507","1,91197730783847","0,472235461102831","1,01858439429409","1,54912208686837"
-,"0,983807817453276","2,34845526278731","0,785524371519466","0,220854402806683","1,77117365732932","3,01226487117459","-0,327141232914824","-0,210388758733043"
-Dritte Gruppe,"4,11271848986168","4,99244908180646","5,98316851481515","4,95765061866595","4,00636404848764","5,49799175180235","4,34309770180236","5,36675690932105"
-,"5,09261289722065","4,92838187744164","4,47540951345638","3,45104975190378","5,64998407245105","4,88914941630864","5,92876353824873","6,67452703834106"
+Linie1, ,1,7,9,2,10
+        ,1,2,5,4,10
+Linie2, ,0,2,7,9,1,4
+        ,3,9,4,2,5,7
+
diff --git a/src/test/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParserTest.java b/src/test/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParserTest.java
index 436ef4d2be887c6df4d423c42497c91b68df58df..1749fa2d8e003b32f5f8e5fbfa30dd4a00e00e35 100644
--- a/src/test/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParserTest.java
+++ b/src/test/java/de/tudresden/inf/mci/brailleplot/commandline/CommandLineParserTest.java
@@ -1,5 +1,7 @@
 package de.tudresden.inf.mci.brailleplot.commandline;
 
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.commons.cli.ParseException;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -16,7 +18,7 @@ class CommandLineParserTest {
 
     @Test
     void testParseLegalArgs() {
-        String[] args = {"-h", "--csv-path", "foobar"};
+        String[] args = {"-h", "--csv-path", "foobar", "-p", "test", "-t", "title", "-x", "x-axis", "-y", "y-axis", "-d", "BarChart"};
         Assertions.assertDoesNotThrow(() -> {commandLineParser.parse(args);});
     }
 
@@ -29,12 +31,13 @@ class CommandLineParserTest {
     @Test
     void testEmptyArgs() {
         String[] args = {""};
-        Assertions.assertDoesNotThrow(() -> {commandLineParser.parse(args);});
+        Assertions.assertThrows(ParsingException.class, () -> {commandLineParser.parse(args);});
     }
 
     @Test
     void testBoolFlagRecognized() {
-        String[] args = {"-h"};
+        final String param = "xyz";
+        String[] args = {"--csv-path", param, "-p", param, "-t", param, "-x", param, "-y", param, "-d", param, "-i"};
         SettingsReader settings;
         try {
             settings = commandLineParser.parse(args);
@@ -42,14 +45,15 @@ class CommandLineParserTest {
             fail();
             return; // Never executed, satisfy compiler
         }
-        Optional<Boolean> flag = settings.isTrue(SettingType.DISPLAY_HELP);
+        Optional<Boolean> flag = settings.isTrue(SettingType.INHIBIT_PRINT);
         Assertions.assertTrue(flag.isPresent());
         Assertions.assertTrue(flag.get());
     }
 
     @Test
     void testBoolFlagCorrectlyNotRecognized() {
-        String[] args = {""};
+        final String param = "xyz";
+        String[] args = {"--csv-path", param, "-p", param, "-t", param, "-x", param, "-y", param, "-d", param};
         SettingsReader settings;
         try {
             settings = commandLineParser.parse(args);
@@ -57,14 +61,14 @@ class CommandLineParserTest {
             fail();
             return; // Never executed, satisfy compiler
         }
-        Optional<Boolean> flag = settings.isTrue(SettingType.DISPLAY_HELP);
+        Optional<Boolean> flag = settings.isTrue(SettingType.INHIBIT_PRINT);
         Assertions.assertFalse(flag.isPresent());
     }
 
     @Test
     void testParameterRecognized() {
         final String param = "xyz";
-        String[] args = {"--csv-path", param};
+        String[] args = {"--csv-path", param, "-p", param, "-t", param, "-x", param, "-y", param, "-d", param};
         SettingsReader settings;
         try {
             settings = commandLineParser.parse(args);
@@ -72,14 +76,21 @@ class CommandLineParserTest {
             fail();
             return; // Never executed, satisfy compiler
         }
-        Optional<String> flag = settings.getSetting(SettingType.CSV_LOCATION);
-        Assertions.assertTrue(flag.isPresent());
-        Assertions.assertTrue(flag.get().equals(param));
+        Optional<String> flag;
+        for (SettingType setting : new SettingType[]{
+                SettingType.CSV_LOCATION, SettingType.PRINTER_CONFIG_PATH, SettingType.DIAGRAM_TITLE,
+                SettingType.X_AXIS_LABEL, SettingType.X_AXIS_LABEL, SettingType.DIAGRAM_TYPE}
+                ) {
+            flag = settings.getSetting(setting);
+            Assertions.assertTrue(flag.isPresent());
+            Assertions.assertTrue(flag.get().equals(param));
+        }
     }
 
     @Test
     void testParameterCorrectlyNotRecognized() {
-        String[] args = {""};
+        final String param = "xyz";
+        String[] args = {"--csv-path", param, "-p", param, "-t", param, "-x", param, "-y", param, "-d", param};
         SettingsReader settings;
         try {
             settings = commandLineParser.parse(args);
@@ -87,7 +98,7 @@ class CommandLineParserTest {
             fail();
             return; // Never executed, satisfy compiler
         }
-        Optional<String> flag = settings.getSetting(SettingType.CSV_LOCATION);
+        Optional<String> flag = settings.getSetting(SettingType.SVG_EXPORT);
         Assertions.assertFalse(flag.isPresent());
     }
 }
diff --git a/src/test/resources/config/default.properties b/src/test/resources/config/default.properties
index 3ca645921f4865c0ec0c504fac4afa47330978fc..fdc3d1a1a49da21cf66dc7944493ede218aeb594 100644
--- a/src/test/resources/config/default.properties
+++ b/src/test/resources/config/default.properties
@@ -56,7 +56,9 @@ format.default.margin.right=10
 ### Diagram Formatting
 ### ==================
 
+representation.general.brailleLanguage=DE_KURZSCHRIFT
 representation.general.nonexistentDataText=n/a
+representation.general.legendKeyword=Legende:
 representation.general.maxTitleHeight=2
 representation.rasterize.barChart.maxBarThickness=3
 representation.rasterize.barChart.minBarThickness=1
diff --git a/src/test/resources/config/rasterizer_test_default.properties b/src/test/resources/config/rasterizer_test_default.properties
index 0a78cfee948ef6ede757dedc4e102b1a4676a3ea..033ae6d9479c71427f0ad9c8a33ab815ce60ff48 100644
--- a/src/test/resources/config/rasterizer_test_default.properties
+++ b/src/test/resources/config/rasterizer_test_default.properties
@@ -45,7 +45,9 @@ format.default.margin.right=0
 ### Diagram Formatting
 ### ==================
 
+representation.general.brailleLanguage=DE_KURZSCHRIFT
 representation.general.nonexistentDataText=n/a
+representation.general.legendKeyword=Legende:
 representation.general.maxTitleHeight=2
 representation.rasterize.barChart.maxBarThickness=3
 representation.rasterize.barChart.minBarThickness=1
diff --git a/third_party/liblouis b/third_party/liblouis
index 67ab8e96cc2f4db70f220f71cbdee0903e8abac6..364cab426fd86f417a675073914a2f3f0d233194 160000
--- a/third_party/liblouis
+++ b/third_party/liblouis
@@ -1 +1 @@
-Subproject commit 67ab8e96cc2f4db70f220f71cbdee0903e8abac6
+Subproject commit 364cab426fd86f417a675073914a2f3f0d233194
diff --git a/third_party/liblouis.dll b/third_party/liblouis.dll
deleted file mode 100644
index 452b2f1747e1d6c26355a9972265f0514b46233b..0000000000000000000000000000000000000000
Binary files a/third_party/liblouis.dll and /dev/null differ