initial import
This commit is contained in:
		
						commit
						3dce91450e
					
				
					 24 changed files with 3012 additions and 0 deletions
				
			
		
							
								
								
									
										24
									
								
								.eslintrc.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.eslintrc.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| import globals from "globals"; | ||||
| import tseslint from "typescript-eslint"; | ||||
| 
 | ||||
| 
 | ||||
| export default [ | ||||
|   { | ||||
|     files: ["**/*.{ts}"], | ||||
|     plugins: ['@typescript-eslint/eslint-plugin', 'eslint-plugin-tsdoc'], | ||||
|     parser: '@typescript-eslint/parser', | ||||
|     parserOptions: { | ||||
|       project: './tsconfig.json', | ||||
|       tsconfigRootDir: __dirname, | ||||
|       ecmaVersion: 'ES6', | ||||
|       sourceType: 'module' | ||||
|     }, | ||||
|     rules: { | ||||
|       'tsdoc/syntax': 'warn' | ||||
|     }, | ||||
|     languageOptions: { | ||||
|       globals: globals.browser | ||||
|     } | ||||
|   }, | ||||
|   ...tseslint.configs.recommended, | ||||
| ]; | ||||
							
								
								
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| node_modules | ||||
| dist | ||||
| docs | ||||
| package-lock.json | ||||
							
								
								
									
										100
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | |||
| # Presentationmaker.js | ||||
|  | ||||
| 
 | ||||
| ## What is | ||||
| A simple(ish) tool to create presentation from XML source. | ||||
| For those who fight against typical presentation tools. | ||||
| 
 | ||||
| ## Features | ||||
| * HTML output for use in browser | ||||
| * input from XML file (either single file or embedded into HTML) | ||||
| * transition between pages | ||||
| * HTML in elements supported | ||||
| * Custom templates, you define them, combine them and use it | ||||
| * powerful calculation inside description and templates thanks to [fparser](https://fparser.alexi.ch/) | ||||
| * presentation can be formatted via normal CSS | ||||
| 
 | ||||
| ## Installation | ||||
| If you just want to use it, take a look at the [public/index.html](public/index.html) file. It is a good start to use it. Additionally, you need the [public/presentationmaker.js](public/presentationmaker.js) script. | ||||
| The CSS is optional, but encouraged. | ||||
| It provides all the needed boilerplate to get you running. | ||||
| ### Development | ||||
| If you want to help with development or want to see live updates if you change your xml, check out the project and use | ||||
| ``` | ||||
| npm install | ||||
| npx webpack serve | ||||
| ``` | ||||
| and a browser pointing to localhost:8080 | ||||
| 
 | ||||
| ## Usage | ||||
| The main presentation file is pure XML with a <presentation> root node. | ||||
| Below this there are | ||||
| ### <defintions> | ||||
| These are in the form of | ||||
| ```<name>value<name>``` | ||||
| Later "name" can be used via ```${name}``` in the templates/pages | ||||
| ### <modules> | ||||
| Similar to the definitions, a <module_name>...</module_name> | ||||
| Creates a module that can be used later. | ||||
| The module itself can use other previously defined modules as | ||||
| ```<module_name optional="value">optional inner content</module_name>``` | ||||
| The parameter you add during use will be available to the module as ```${optional}``` | ||||
| Existing internal modules are | ||||
| #### calc | ||||
| Calculates a formula and stores the result in a variable for later use. | ||||
| Parameters: | ||||
| * ```name``` the name of the variable | ||||
| inner text is the formular to be used to calculate the value | ||||
| #### img | ||||
| Shows an image. | ||||
| Parameters: | ||||
| * ```src``` file name of the image | ||||
| * ```x``` Left position of the image (relative to the page) | ||||
| * ```y``` Top position of the image (relative to the page) | ||||
| * ```width``` Image width | ||||
| * ```height``` Image height | ||||
| ### options | ||||
| Creates an effect or transformation layer to affect content that is rendered inside. | ||||
| Parameters: | ||||
| * ```opacity``` optional opacity value 0: fully transparent, 1: fully visible | ||||
| * ```blendmode``` optional one the https://developer.mozilla.org/docs/Web/CSS/mix-blend-mode values | ||||
| * ```flip``` optional flipping of the image (currently only y supported) | ||||
| * ```rotate``` rotation values in X,Y,Z form | ||||
| * ```y``` optional y axis to flip at | ||||
| Inner XML is the content to display | ||||
| #### text | ||||
| Show a text in an invisible bounding box. | ||||
| Parameters: | ||||
| * ```x0``` left side of the bounding box. | ||||
| * ```y0``` top side of the bounding box. | ||||
| * ```x1``` right side of the bounding box (mutally exclusive to width) | ||||
| * ```y1``` bottom side of the bounding box (mutally exclisve to height) | ||||
| * ```pos``` shortcut to x0,y0,x1,y1 (mutually exclusive to above values) | ||||
| * ```halign``` horizontal alignment in the bounding box, possible values: ```left```, ```center```, ```right```, defaults to ```center``` | ||||
| * ```valign``` vertical alignment in the bounding box, possible value: ```top```, ```center```, ```bottom```, default to ```top``` | ||||
| * ```fontsize``` optional font size in pixel | ||||
| * ```color``` optional color | ||||
| Inside the XML is the text to display | ||||
| ### page | ||||
| This is the section for the actual pages to show. | ||||
| In the pages, modules, variables as well as calulation can be used. | ||||
| Parameters: | ||||
| * ```id``` optional id of the page (useful for CSS styling) | ||||
| * ```width``` page width, default to the ```width``` variable in the definitions section | ||||
| * ```height``` page height, default to the ```height``` variable in the definitions section | ||||
| * ```x``` X position of the page in the canvas, defaults to 0 | ||||
| * ```y``` Y position of the page in the canvas, defaults to 0 | ||||
| * ```z``` Z position of the page in the canvas, defaults to 0 | ||||
| * ```rx``` rotation of the page on the X-Axis in °, defaults to 0 | ||||
| * ```ry``` rotation of the page on the Y-Axis in °, defaults to 0 | ||||
| * ```rz``` rotation of the page on the Z-Axis in °, defaults to 0 | ||||
| * ```vx``` viewport position in X, defaults to ```x``` | ||||
| * ```vy``` viewport position in Y, defaults to ```y``` | ||||
| * ```vz``` viewport position in Z, defaults to ```z``` | ||||
| * ```vwidth``` viewport width, defaults to ```width``` | ||||
| * ```vheight``` viewport width, defaults to ```height``` | ||||
| * ```vrx``` rotation of the vieport on the X-Axis in °, defaults to 0 | ||||
| * ```vry``` rotation of the vieport on the Y-Axis in °, defaults to 0 | ||||
| * ```vrz``` rotation of the vieport on the Z-Axis in °, defaults to 0 | ||||
| * ```name``` name of the page (shown in drop down), defaults to page number | ||||
| 
 | ||||
							
								
								
									
										23
									
								
								package.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								package.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| { | ||||
|   "name": "presentationmake.js", | ||||
|   "version": "0.0.1", | ||||
|   "description": "A tool to create browser based presentations", | ||||
|   "author": "Sascha Nitsch (grumpydeveloper https://contentnation.net/@grumpydevelop)", | ||||
|   "license": "GPL-3.0-or-later", | ||||
|   "devDependencies": { | ||||
|     "@typescript-eslint/eslint-plugin": "^7.15.0", | ||||
|     "@typescript-eslint/parser": "^7.15.0", | ||||
|     "eslint": "^8.56.0", | ||||
|     "eslint-plugin-tsdoc": "^0.3.0", | ||||
|     "globals": "^15.6.0", | ||||
|     "ts-loader": "^9.5.1", | ||||
|     "typedoc": "^0.26.3", | ||||
|     "typescript": "^5.5.2", | ||||
|     "typescript-eslint": "^7.14.1", | ||||
|     "webpack-cli": "^5.1.4", | ||||
|     "webpack-dev-server": "^5.0.4" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "fparser": "^3.0.1" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										143
									
								
								public/example.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								public/example.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | |||
| <presentation> | ||||
|   <definitions> | ||||
|     <width>1920</width> | ||||
|     <height>1080</height> | ||||
|     <defaultfontcolor>#ffffff</defaultfontcolor> | ||||
|     <path>img/</path> | ||||
|     <boxwidth>1720</boxwidth> | ||||
|     <boxinnerx>165</boxinnerx> | ||||
|     <boxinnerwidth>1590</boxinnerwidth> | ||||
|     <boxheight>175</boxheight> | ||||
|     <mirrorline>880</mirrorline> | ||||
|     <headerpos>0,35*${scale},1920*${scale},270*${scale}</headerpos> | ||||
|     <headersize>90</headersize> | ||||
|     <boxx>105</boxx> | ||||
|     <box3_1>235</box3_1> | ||||
|     <box3_2>445</box3_2> | ||||
|     <box3_3>655</box3_3> | ||||
|     <listsize>72</listsize> | ||||
|     <transition>transform</transition> | ||||
|     <scale>1</scale> | ||||
|   </definitions> | ||||
|   <modules> | ||||
|     <defaultbg> | ||||
|       <img src="${path}bg.jpg" x="0" y="0" width="${width}" height="${height}"></img> | ||||
|       <img src="${path}logo.svg" x="40*${scale}" y="970*${scale}" width="82*${scale}" height="83*${scale}"></img> | ||||
|       <text x0="0" y0="1000*${scale}" x1="1920*${scale}" y1="1060*${scale}" size="40*${scale}">Introduction to presentationmaker.js</text> | ||||
|       <text x0="1700*${scale}" y0="20*${scale}" x1="1900*${scale}" y1="60*${scale}" size="20*${scale}" halign="right">${page}/${numpages}</text> | ||||
|     </defaultbg> | ||||
|     <boxx3> | ||||
|       <defaultbg /> | ||||
|       <img src="${path}box.png" x="${boxx}*${scale}" y="${box3_1}*${scale}" width="${boxwidth}*${scale}" height="${boxheight}*${scale}"></img> | ||||
|       <img src="${path}box.png" x="${boxx}*${scale}" y="${box3_2}*${scale}" width="${boxwidth}*${scale}" height="${boxheight}*${scale}"></img> | ||||
|       <img src="${path}box.png" x="${boxx}*${scale}" y="${box3_3}*${scale}" width="${boxwidth}*${scale}" height="${boxheight}*${scale}"></img> | ||||
|     </boxx3> | ||||
|     <box3> | ||||
|       <boxx3></boxx3> | ||||
|       <text pos="${headerpos}" size="${headersize}" halign="center" valign="center">${headertext}</text> | ||||
|       <text x0="${boxinnerx}*${scale}" y0="${box3_1}*${scale}" w="${boxinnerwidth}*${scale}" h="${boxheight}*${scale}" size="${listsize}*${scale}" halign="left" valign="center">${text1}</text> | ||||
|       <text x0="${boxinnerx}*${scale}" y0="${box3_2}*${scale}" w="${boxinnerwidth}*${scale}" h="${boxheight}*${scale}" size="${listsize}*${scale}" halign="left" valign="center">${text2}</text> | ||||
|       <text x0="${boxinnerx}*${scale}" y0="${box3_3}*${scale}" w="${boxinnerwidth}*${scale}" h="${boxheight}*${scale}" size="${listsize}*${scale}" halign="left" valign="center">${text3}</text> | ||||
|     </box3> | ||||
|     <box3r> | ||||
|       <options rotate="0,0,90"> | ||||
|         <boxx3 width="${height}" heigh="${width}"></boxx3> | ||||
|         <text pos="200,35,1080,220" size="${headersize}" halign="center" valign="center">${headertext}</text> | ||||
|         <text x0="${boxinnerx}" y0="${box3_1}" w="${boxinnerwidth}" h="${boxheight}" size="${listsize}" halign="left" valign="center">${text1}</text> | ||||
|         <text x0="${boxinnerx}" y0="${box3_2}" w="${boxinnerwidth}" h="${boxheight}" size="${listsize}" halign="left" valign="center">${text2}</text> | ||||
|         <text x0="${boxinnerx}" y0="${box3_3}" w="${boxinnerwidth}" h="${boxheight}" size="${listsize}" halign="left" valign="center">${text3}</text> | ||||
|       </options> | ||||
|     </box3r> | ||||
|     <mirrorimage> | ||||
|       <calc name="y2">((${mirrorline} - ${y}) +${mirrorline} - ${h})</calc> | ||||
|       <img src="${path}${img}" x="${x}*${scale}" y="${y}*${scale}" width="${w}*${scale}" height="${h}*${scale}"></img> | ||||
|       <options opacity=".44" flip="v" y="${height}"> | ||||
|         <img src="${path}${img}" x="${x}*${scale}" y="(${height} - ${mirrorline}*${scale}) - ${scale} * (${mirrorline} - ${y})" width="${w}*${scale}" height="${h}*${scale}" mask-image="linear-gradient(0deg, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.1) 40%)"></img> | ||||
|       </options> | ||||
|     </mirrorimage> | ||||
|   </modules> | ||||
|   <pages> | ||||
|     <page name="Welcome"> | ||||
|       <defaultbg /> | ||||
|       <mirrorimage img="presentationmaker.svg" x="642" y="600" w="634" h="374"></mirrorimage> | ||||
|       <text pos="${headerpos}" size="${headersize}" halign="center" valign="center">Welcome to the presentationmaker.js example</text> | ||||
|       <text x0="100" y0="450" x1="1820" y1="550" size="80" halign="center" valign="top">A quick presentation of the why and how.</text> | ||||
|     </page> | ||||
|     <page x="1920" name="Why"> | ||||
|       <box3> | ||||
|         <headertext>Why using presentationmaker.js</headertext> | ||||
|         <text1>Powerpoint / Impress are hard to use.</text1> | ||||
|         <text2>I wanted to concentrate on the content, not the quirks of the tools.</text2> | ||||
|         <text3>I want to make use of modern browser features.</text3> | ||||
|       </box3> | ||||
|     </page> | ||||
|     <page y="1180" vx="-100" vy="980" vwidth="1920*2+200" vheight="2460" width="1920*2" height="2160" name="Features"> | ||||
|       <calc name="scale">2</calc> | ||||
|       <box3 headertext="Features" text1="Template based slides/pages." text2="you can create new templates than can even calulate positions or things, this is scaled by 2X." text3="Using those templates is easy."></box3>  | ||||
|     </page> | ||||
|     <page x="2020*2" name="Navigation (I)"> | ||||
|       <box3 headertext="Navigation (I)" text1="A click/tap shows next page." text2="Swiping left/right works too." text3="Arrow on keyboard of course as well."></box3> | ||||
|     </page> | ||||
|     <page x="2020*2.5" y="1180" rz="-90" vx="2020*2.5" vy="1180" vrz="90" name="Navigation (II)"> | ||||
|       <box3 headertext="Navigation (II)" text1="On the top left is a fullscreen icon." text2="Forwards and backwards button and a quick jump." text3="This works in every rotation :)"></box3> | ||||
|     </page> | ||||
|     <page x="2020*3" y="0" name="Creating slides"> | ||||
|       <box3 headertext="Creating slides" text1="Presentations are based on easy to understand XML." text2="Basic elements can be combined to templates." text3="Templates can then form pages."></box3> | ||||
|     </page> | ||||
|     <page x="2020*3" y="1180" name="Example"> | ||||
|       <defaultbg /> | ||||
|       <text pos="${headerpos}" size="${headersize}" halign="center" valign="center">Example</text> | ||||
|       <text pos="100,270,1820,860" size="40" halign="left" valign="top"> | ||||
| This page is made by<br /> | ||||
| <pre><code> | ||||
| <page x="2020*3" y="1180" name="Example"> | ||||
|   <defaultbg /> | ||||
|   <text pos="\${headerpos}" size="\${headersize}" halign="center" | ||||
|     valign="center">Example</text> | ||||
|   <text pos="100,270,1820,860" size="40" halign="left" | ||||
|     valign="top"> | ||||
|     This page is made by<br /> | ||||
|     <pre><code>Recursion is nice</code>/</pre> | ||||
|   </text> | ||||
| </page> | ||||
| </code></pre> | ||||
|       </text> | ||||
|     </page> | ||||
|     <page x="2020*3" y="1180*2" name="Modules / Templates"> | ||||
|       <box3 headertext="Used Modules" text1="<strong>page</strong>: A page defintion." text2="<strong>defaultbg:</strong> a custom element that show the green background image" text3="<strong>text:</strong> A text box with given size and text"></box3> | ||||
|     </page> | ||||
|     <page x="2020*4" name="box3"> | ||||
|       <box3 headertext="Module box3" text1="This is rendered by using the box3 custom module." text2="It is based on the boxx3 module (background + background images for text)." text3="Plus text areas for the text."></box3> | ||||
|     </page> | ||||
|     <page x="2020*4" y="1180" name="Modules within modules"> | ||||
|       <calc name="math">sin(30*PI/180) + sqrt(9)</calc> | ||||
|       <box3 headertext="Modules can include other modules" text1="As seen on last slide." text2="In modules you can calculate things that can be used later." text3="This was calulated by "sin(30*PI/180) + sqrt(9)" = ${math}"></box3> | ||||
|     </page> | ||||
|     <page x="2020*4" y="1180*2" name="Practical use for calc"> | ||||
|       <defaultbg /> | ||||
|       <mirrorimage img="presentationmaker.svg" x="642" y="600" w="634" h="374"></mirrorimage> | ||||
|       <text pos="${headerpos}" size="${headersize}" halign="center" valign="center">The mirrored image is an example where calc helps.</text> | ||||
|       <text x0="100" y0="450" x1="1820" y1="550" size="80" halign="center" valign="top">Also it uses some image effects.</text> | ||||
|     </page> | ||||
|     <page x="2020*4" y="1180*3" vx="2020*4-100" vy="1180*3-100" vwidth="2120" vheight="1280" name="Page position" rz="3"> | ||||
|       <box3 headertext="Page positions" text1="Pages can be positioned anywhere on the canvas." text2="Rotation of the page and the view can be different." text3="This can create nice effects, just don't over do it."></box3> | ||||
|     </page> | ||||
|     <page x="5320" y="1180*3" z="0" rx="55" ry="20" width="1920" height="1080" vx="5320-150" vy="4400" vz="450" vwidth="2120" vheight="1280" vrx="-50" name="3D"> | ||||
|         <box3 headertext="Rotation can also be in 3D" text1="Again, use just for rare effects." text2="Don't over do it." text3="Yes, we really mean that."></box3> | ||||
|     </page> | ||||
|     <page x="2020" y="1180*3" name="Get it"> | ||||
|       <box3 headertext="Get it an use it." text1="Licensed under GPL-3." text3="We love to get a shout-out if you use it."> | ||||
|       <text2><a href="https://git.contentnation.net/presentationmaker" target="_blank">git.contentnation.net/presentationmaker</a></text2> | ||||
|       </box3> | ||||
|     </page> | ||||
|     <page x="0" y="1180*3" name="Credits"> | ||||
|       <box3 headertext="Credits" text1="My own render engine I made for an old project."> | ||||
|       <text2><a href="https://impress.js.org/" target="_blank">impress.js.org</a><br />(inspired, no code was used from the project.)</text2> | ||||
|       <text3>Built by <a href="https://contentnatin.net/@grumpydevelop">GrumpyDeveloper</a></text3> | ||||
|       </box3> | ||||
|     </page> | ||||
|     <page x="3500" y="1000" z="2000" vx="4000" vy="1800" vz="4000" width="3840" height="2160" vwidth="1920" vheight="1080" name="The end"> | ||||
|       <text x0="0" y0="0" w="${width}" h="${height}" size="1000" halign="center" valign="center">The end</text> | ||||
|     </page> | ||||
|   </pages> | ||||
| </presentation> | ||||
							
								
								
									
										
											BIN
										
									
								
								public/img/bg.jpg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/img/bg.jpg
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 112 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/img/box.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/img/box.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 781 KiB | 
							
								
								
									
										584
									
								
								public/img/contentnation.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										584
									
								
								public/img/contentnation.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,584 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    sodipodi:docname="contentnation-trans-black.svg" | ||||
|    inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" | ||||
|    id="svg10485" | ||||
|    version="1.1" | ||||
|    viewBox="0 0 116.87181 29.368581" | ||||
|    height="29.368582mm" | ||||
|    width="116.87183mm" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/"> | ||||
|   <defs | ||||
|      id="defs10479"> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8566"> | ||||
|       <path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8564" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8584"> | ||||
|       <path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8582" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8612"> | ||||
|       <path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8610" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8624"> | ||||
|       <path | ||||
|          d="m 271.674,749.573 v -64.657 l 18.3,-18.426 v 44.013 z" | ||||
|          id="path8622" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(0,-29.309916,29.309916,0,107.56319,51.61644)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8640"> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8630" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.215824" | ||||
|          id="stop8632" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.75" | ||||
|          id="stop8634" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.76850016" | ||||
|          id="stop8636" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8638" /> | ||||
|     </linearGradient> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8650"> | ||||
|       <path | ||||
|          d="M 312.701,749.505 V 705.43 l 18.301,-38.937 v 64.659 z" | ||||
|          id="path8648" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(0,-29.284783,29.284783,0,122.03666,51.615502)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8666"> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8656" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.422802" | ||||
|          id="stop8658" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.972582" | ||||
|          id="stop8660" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.97461095" | ||||
|          id="stop8662" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8664" /> | ||||
|     </linearGradient> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8676"> | ||||
|       <path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8674" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8684"> | ||||
|       <path | ||||
|          d="m 270.701,750.4 h 20.3 v -45.214 h -20.3 z" | ||||
|          id="path8682" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8700"> | ||||
|       <path | ||||
|          d="m 311.582,706.377 h 20.301 V 665.35 h -20.301 z" | ||||
|          id="path8698" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8716"> | ||||
|       <path | ||||
|          d="m 289.974,666.49 h -59.353 l -18.425,18.425 59.481,0.001 z" | ||||
|          id="path8714" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(19.297539,-16.192559,-16.192559,-19.297539,84.195184,56.472015)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8732"> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8722" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.29489" | ||||
|          id="stop8724" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.662088" | ||||
|          id="stop8726" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.6870937" | ||||
|          id="stop8728" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8730" /> | ||||
|     </linearGradient> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8742"> | ||||
|       <path | ||||
|          d="m 212.196,731.148 v -46.226 l 18.301,0.002 v 46.224 z" | ||||
|          id="path8740" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(0,-16.307204,16.307204,0,86.58079,45.113934)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8766"> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0" | ||||
|          id="stop8748" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.25" | ||||
|          id="stop8750" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0.44050522" | ||||
|          id="stop8752" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0.5" | ||||
|          id="stop8754" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0.52936829" | ||||
|          id="stop8756" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.75" | ||||
|          id="stop8758" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.996319" | ||||
|          id="stop8760" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.9965914" | ||||
|          id="stop8762" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8764" /> | ||||
|     </linearGradient> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8776"> | ||||
|       <path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8774" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8784"> | ||||
|       <path | ||||
|          d="m 211.196,687.809 h 20.301 v -3.887 h -20.301 z" | ||||
|          id="path8782" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8800"> | ||||
|       <path | ||||
|          d="m 211.196,732.223 h 20.301 v -3.887 h -20.301 z" | ||||
|          id="path8798" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8816"> | ||||
|       <path | ||||
|          d="m 267.565,749.573 h -36.944 l -18.425,-18.425 h 37.755 z" | ||||
|          id="path8814" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(13.689206,12.765392,-12.765392,13.689206,83.04661,19.183338)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8832"> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8822" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.29489" | ||||
|          id="stop8824" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.662088" | ||||
|          id="stop8826" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.6870937" | ||||
|          id="stop8828" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8830" /> | ||||
|     </linearGradient> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8862"> | ||||
|       <path | ||||
|          d="m 331.011,666.473 -39.042,83.1 h -20.312 l 38.993,-83.1 z" | ||||
|          id="path8860" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(-16.76835,31.536681,-31.536681,-16.76835,119.95484,21.196219)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8878"> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8868" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.29489" | ||||
|          id="stop8870" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.662088" | ||||
|          id="stop8872" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.6870937" | ||||
|          id="stop8874" /> | ||||
|       <stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8876" /> | ||||
|     </linearGradient> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath2069"> | ||||
|       <path | ||||
|          d="M 0,0 H 23.3971 V -14.91 H 0 Z" | ||||
|          clip-rule="evenodd" | ||||
|          id="path2067" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath2073"> | ||||
|       <path | ||||
|          d="M 0,-14.91 H 209.76378 V 14.91 H 0 Z" | ||||
|          id="path2071" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        id="i" | ||||
|        spreadMethod="pad" | ||||
|        gradientTransform="matrix(19.29766,-16.19266,-16.19266,-19.29766,29.9802,59.309292)" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        y2="0" | ||||
|        x2="1" | ||||
|        y1="0" | ||||
|        x1="0"> | ||||
|       <stop | ||||
|          offset="0" | ||||
|          stop-color="#dfbd6a" | ||||
|          id="stop2648" /> | ||||
|       <stop | ||||
|          offset=".295" | ||||
|          stop-color="#c78300" | ||||
|          id="stop2650" /> | ||||
|       <stop | ||||
|          offset=".662" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2652" /> | ||||
|       <stop | ||||
|          offset=".687" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2654" /> | ||||
|       <stop | ||||
|          offset="1" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2656" /> | ||||
|     </linearGradient> | ||||
|     <clipPath | ||||
|        id="o" | ||||
|        clipPathUnits="userSpaceOnUse"> | ||||
|       <path | ||||
|          d="m 267.565,749.573 h -36.944 l -18.425,-18.425 h 37.755 z" | ||||
|          id="path2620" /> | ||||
|     </clipPath> | ||||
|     <linearGradient | ||||
|        id="p" | ||||
|        spreadMethod="pad" | ||||
|        gradientTransform="matrix(38.804048,-36.18536,-36.18536,-38.804048,228.9593,749.93786)" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        y2="0" | ||||
|        x2="1" | ||||
|        y1="0" | ||||
|        x1="0"> | ||||
|       <stop | ||||
|          offset="0" | ||||
|          stop-color="#dfbd6a" | ||||
|          id="stop2678" /> | ||||
|       <stop | ||||
|          offset=".295" | ||||
|          stop-color="#c78300" | ||||
|          id="stop2680" /> | ||||
|       <stop | ||||
|          offset=".662" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2682" /> | ||||
|       <stop | ||||
|          offset=".687" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2684" /> | ||||
|       <stop | ||||
|          offset="1" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2686" /> | ||||
|     </linearGradient> | ||||
|   </defs> | ||||
|   <sodipodi:namedview | ||||
|      inkscape:guide-bbox="true" | ||||
|      showguides="true" | ||||
|      inkscape:window-maximized="0" | ||||
|      inkscape:window-y="254" | ||||
|      inkscape:window-x="193" | ||||
|      inkscape:window-height="1761" | ||||
|      inkscape:window-width="3631" | ||||
|      fit-margin-bottom="0" | ||||
|      fit-margin-right="0" | ||||
|      fit-margin-left="0" | ||||
|      fit-margin-top="0" | ||||
|      showgrid="false" | ||||
|      inkscape:document-rotation="0" | ||||
|      inkscape:current-layer="layer1" | ||||
|      inkscape:document-units="mm" | ||||
|      inkscape:cy="80.714286" | ||||
|      inkscape:cx="215.35714" | ||||
|      inkscape:zoom="5.6" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      borderopacity="1.0" | ||||
|      bordercolor="#666666" | ||||
|      pagecolor="#ffffff" | ||||
|      id="base" | ||||
|      inkscape:showpageshadow="2" | ||||
|      inkscape:pagecheckerboard="0" | ||||
|      inkscape:deskcolor="#d1d1d1"> | ||||
|     <sodipodi:guide | ||||
|        id="guide3015" | ||||
|        orientation="0,-1" | ||||
|        position="36.967617,0.063223318" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata10482"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title /> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      transform="translate(-22.905362,-22.155916)" | ||||
|      id="layer1" | ||||
|      inkscape:groupmode="layer" | ||||
|      inkscape:label="Layer 1"> | ||||
|     <g | ||||
|        id="g2277" | ||||
|        transform="matrix(0.35277777,0,0,-0.35277777,65.410913,51.461274)" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 79.101677,34.586067 a 4.0437834,4.0437834 0 0 1 -1.608264,-1.610121 4.9524783,4.9524783 0 0 1 -0.586668,-2.454035 4.9506282,4.9506282 0 0 1 0.582968,-2.450319 4.0437834,4.0437834 0 0 1 1.608262,-1.610118 4.7396478,4.7396478 0 0 1 2.313385,-0.555199 5.4059005,5.4059005 0 0 1 1.56384,0.207263 6.6625271,6.6625271 0 0 1 1.371365,0.592228 0.51634587,0.51634587 0 0 1 0.286856,0.477479 0.48118251,0.48118251 0 0 1 -0.140652,0.342378 0.49783881,0.49783881 0 0 1 -0.370137,0.148065 0.5237487,0.5237487 0 0 1 -0.231337,-0.05156 5.8963364,5.8963364 0 0 0 -1.110426,-0.451571 4.5416229,4.5416229 0 0 0 -1.249219,-0.153609 3.6551366,3.6551366 0 0 0 -1.885864,0.457127 2.9111545,2.9111545 0 0 0 -1.171493,1.249221 3.9753083,3.9753083 0 0 0 -0.394201,1.795181 3.9771578,3.9771578 0 0 0 0.394201,1.797039 2.9111545,2.9111545 0 0 0 1.171493,1.249221 3.6551366,3.6551366 0 0 0 1.884013,0.46637 4.6138002,4.6138002 0 0 0 1.24923,-0.153604 5.8963364,5.8963364 0 0 0 1.110415,-0.451572 0.5237487,0.5237487 0 0 1 0.231337,-0.05155 0.50709238,0.50709238 0 0 1 0.370145,0.142505 0.47377973,0.47377973 0 0 1 0.14065,0.347936 0.51634587,0.51634587 0 0 1 -0.283153,0.48858 6.6625271,6.6625271 0 0 1 -1.371372,0.59223 5.4059005,5.4059005 0 0 1 -1.561994,0.19617 4.7396478,4.7396478 0 0 1 -2.31338,-0.555205 z" | ||||
|        id="path13" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 87.750008,34.556434 a 4.0585894,4.0585894 0 0 1 -1.561992,-1.635997 5.2282335,5.2282335 0 0 1 0,-4.791473 4.0585894,4.0585894 0 0 1 1.569393,-1.636031 5.0265069,5.0265069 0 0 1 4.734096,0 4.1215132,4.1215132 0 0 1 1.571248,1.643433 5.1690107,5.1690107 0 0 1 0,4.776663 4.1215132,4.1215132 0 0 1 -1.582351,1.643405 5.0265069,5.0265069 0 0 1 -4.734097,0 z m 4.160378,-0.966042 a 3.037002,3.037002 0 0 0 1.158545,-1.262184 3.9790099,3.9790099 0 0 0 0.399749,-1.804439 3.9771578,3.9771578 0 0 0 -0.399749,-1.802581 3.037002,3.037002 0 0 0 -1.158545,-1.262173 3.7014043,3.7014043 0 0 0 -3.586661,0 3.0740155,3.0740155 0 0 0 -1.152989,1.262173 3.9771578,3.9771578 0 0 0 -0.397896,1.802581 3.9790099,3.9790099 0 0 0 0.397896,1.804439 3.0740155,3.0740155 0 0 0 1.152989,1.262184 3.7014043,3.7014043 0 0 0 3.586661,0 z" | ||||
|        id="path15" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 96.766628,34.91547 a 0.55521063,0.55521063 0 0 1 -0.168409,-0.410848 v -7.69151 a 0.82541414,0.82541414 0 0 1 0.244291,-0.597784 0.79395199,0.79395199 0 0 1 0.59222,-0.251694 h 0.168416 a 0.87538284,0.87538284 0 0 1 0.708818,0.386804 l 4.958136,7.162215 v -6.954945 a 0.58482187,0.58482187 0 0 1 0.16663,-0.418252 0.55521063,0.55521063 0 0 1 0.41254,-0.173969 0.59407531,0.59407531 0 0 1 0.59207,0.592221 v 7.689681 a 0.79395199,0.79395199 0 0 1 -0.25167,0.592215 0.82541414,0.82541414 0 0 1 -0.60503,0.244291 h -0.15549 a 0.82541414,0.82541414 0 0 1 -0.38671,-0.09625 0.88463599,0.88463599 0 0 1 -0.29446,-0.251668 L 97.76231,27.53673 v 6.96789 a 0.54410636,0.54410636 0 0 1 -0.17397,0.410848 0.57556829,0.57556829 0 0 1 -0.41826,0.168425 0.55521063,0.55521063 0 0 1 -0.403452,-0.168425 z" | ||||
|        id="path17" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 109.19402,34.91547 a 0.55521063,0.55521063 0 0 1 -0.16839,-0.410848 v -7.380587 h -2.6262 a 0.52930072,0.52930072 0 0 1 -0.38681,-0.153613 0.5237487,0.5237487 0 0 1 -0.1555,-0.386789 0.54410636,0.54410636 0 0 1 0.1555,-0.392363 0.51449509,0.51449509 0 0 1 0.38681,-0.161007 h 6.41271 a 0.55521063,0.55521063 0 0 1 0.55561,0.555203 0.51449509,0.51449509 0 0 1 -0.16152,0.386798 0.55521063,0.55521063 0 0 1 -0.39409,0.153608 h -2.61291 v 7.37875 a 0.55521063,0.55521063 0 0 1 -0.17439,0.410848 0.57926969,0.57926969 0 0 1 -0.4201,0.168425 0.55521063,0.55521063 0 0 1 -0.41072,-0.168425 z" | ||||
|        id="path19" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 114.94971,34.852571 a 0.56631481,0.56631481 0 0 1 -0.16631,-0.412727 v -7.811793 a 0.58112041,0.58112041 0 0 1 0.16631,-0.418275 0.55521063,0.55521063 0 0 1 0.41299,-0.173957 h 5.16517 a 0.55521063,0.55521063 0 0 1 0.555,0.555208 0.51449509,0.51449509 0 0 1 -0.16064,0.386792 0.55521063,0.55521063 0 0 1 -0.39265,0.153613 h -4.57495 v 2.838969 h 4.10156 a 0.55521063,0.55521063 0 0 1 0.55502,0.555218 0.51079377,0.51079377 0 0 1 -0.16112,0.386802 0.54225573,0.54225573 0 0 1 -0.3939,0.15731 h -4.10882 v 2.855632 h 4.57285 a 0.55521063,0.55521063 0 0 1 0.55557,0.555204 0.51634587,0.51634587 0 0 1 -0.16131,0.386787 0.55521063,0.55521063 0 0 1 -0.3922,0.153615 h -5.15958 a 0.56631481,0.56631481 0 0 1 -0.41299,-0.168398 z" | ||||
|        id="path21" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 123.16718,34.91547 a 0.55521063,0.55521063 0 0 1 -0.16668,-0.410848 v -7.69151 a 0.82541414,0.82541414 0 0 1 0.24399,-0.597784 0.79395199,0.79395199 0 0 1 0.59244,-0.251694 h 0.16635 a 0.87353062,0.87353062 0 0 1 0.70886,0.386804 l 4.96735,7.162215 v -6.954945 a 0.57741901,0.57741901 0 0 1 0.16839,-0.418252 0.54410636,0.54410636 0 0 1 0.41075,-0.173969 0.59037391,0.59037391 0 0 1 0.59266,0.592221 v 7.689681 a 0.79765285,0.79765285 0 0 1 -0.24992,0.592215 0.83281503,0.83281503 0 0 1 -0.59969,0.244291 h -0.1538 a 0.81986106,0.81986106 0 0 1 -0.3866,-0.09625 0.89018674,0.89018674 0 0 1 -0.29641,-0.251668 l -4.98391,-7.199246 v 6.96789 a 0.54410636,0.54410636 0 0 1 -0.17353,0.410847 0.57741901,0.57741901 0 0 1 -0.41842,0.168425 0.55521063,0.55521063 0 0 1 -0.42183,-0.168425 z" | ||||
|        id="path23" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 135.60159,34.91547 a 0.55521063,0.55521063 0 0 1 -0.16652,-0.410848 v -7.380587 h -2.62775 a 0.5255994,0.5255994 0 0 1 -0.54041,-0.540402 0.55521063,0.55521063 0 0 1 0.15334,-0.392363 0.51634587,0.51634587 0 0 1 0.38707,-0.161007 h 6.41472 a 0.55521063,0.55521063 0 0 1 0.55499,0.555203 0.51449509,0.51449509 0 0 1 -0.16096,0.386798 0.55521063,0.55521063 0 0 1 -0.39232,0.153608 h -2.62461 v 7.37875 a 0.54410636,0.54410636 0 0 1 -0.17362,0.410848 0.57556829,0.57556829 0 0 1 -0.41842,0.168425 0.55521063,0.55521063 0 0 1 -0.40551,-0.168425 z" | ||||
|        id="path25" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 77.615566,47.54096 a 0.55521063,0.55521063 0 0 1 -0.168411,-0.410853 v -7.684111 a 0.81986106,0.81986106 0 0 1 0.246139,-0.603313 0.79025002,0.79025002 0 0 1 0.592227,-0.251708 h 0.166563 a 0.87353062,0.87353062 0 0 1 0.70326,0.392365 l 4.958035,7.160362 v -6.954935 a 0.57741901,0.57741901 0 0 1 0.168413,-0.418268 0.54410636,0.54410636 0 0 1 0.410857,-0.173957 0.59407531,0.59407531 0 0 1 0.592225,0.592225 v 7.689656 a 0.79765285,0.79765285 0 0 1 -0.249847,0.592235 0.83281503,0.83281503 0 0 1 -0.599628,0.244268 h -0.153607 a 0.81986106,0.81986106 0 0 1 -0.386794,-0.09622 0.87353062,0.87353062 0 0 1 -0.296115,-0.251703 l -4.983939,-7.199235 v 6.967918 a 0.55521063,0.55521063 0 0 1 -0.17397,0.410852 0.57926969,0.57926969 0 0 1 -0.420105,0.168392 0.55521063,0.55521063 0 0 1 -0.405303,-0.173966 z" | ||||
|        id="path27" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 87.344703,47.54096 a 0.56816551,0.56816551 0 0 1 -0.16101,-0.410853 0.7032668,0.7032668 0 0 1 0.06459,-0.257229 l 3.28317,-7.754468 a 1.0104838,1.0104838 0 0 1 0.290568,-0.370125 0.71622143,0.71622143 0 0 1 0.457128,-0.14804 h 0.129547 a 0.71992298,0.71992298 0 0 1 0.457124,0.14804 0.9882749,0.9882749 0 0 1 0.288711,0.370125 l 3.286854,7.760013 a 0.7032668,0.7032668 0 0 1 0.06457,0.257259 0.57556829,0.57556829 0 0 1 -0.161013,0.410852 0.55521063,0.55521063 0 0 1 -0.42011,0.168392 0.59592602,0.59592602 0 0 1 -0.327558,-0.09622 0.63108943,0.63108943 0 0 1 -0.225783,-0.264643 l -0.836409,-2.009858 h -4.386163 l -0.830966,2.01169 a 0.63108943,0.63108943 0 0 1 -0.225784,0.264663 0.60703023,0.60703023 0 0 1 -0.329424,0.09624 0.55521063,0.55521063 0 0 1 -0.418261,-0.17584 z m 2.259713,-3.270175 h 3.477465 L 91.34407,40.084508 Z" | ||||
|        id="path29" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="M 98.852371,47.54096 A 0.55521063,0.55521063 0 0 1 98.683954,47.130107 V 39.755064 H 96.05781 a 0.52745008,0.52745008 0 0 1 -0.542258,-0.542239 0.54410636,0.54410636 0 0 1 0.155463,-0.392372 0.51449509,0.51449509 0 0 1 0.386795,-0.161004 h 6.41642 a 0.55521063,0.55521063 0 0 1 0.55528,0.555206 0.51449509,0.51449509 0 0 1 -0.16124,0.38681 0.540405,0.540405 0 0 1 -0.39209,0.153599 h -2.618835 v 7.380618 a 0.55521063,0.55521063 0 0 1 -0.174027,0.410852 0.57926969,0.57926969 0 0 1 -0.4201,0.168392 0.55521063,0.55521063 0 0 1 -0.410847,-0.173966 z" | ||||
|        id="path31" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 104.60795,47.54096 a 0.55521063,0.55521063 0 0 1 -0.16661,-0.410853 v -7.94134 a 0.58482187,0.58482187 0 0 1 0.16661,-0.418268 0.55521063,0.55521063 0 0 1 0.41299,-0.173957 0.59407531,0.59407531 0 0 1 0.59214,0.592225 v 7.946915 a 0.54410636,0.54410636 0 0 1 -0.17782,0.405278 0.57556829,0.57556829 0 0 1 -0.41836,0.168426 0.55521063,0.55521063 0 0 1 -0.40895,-0.168426 z" | ||||
|        id="path33" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 109.72153,47.187498 a 4.0511871,4.0511871 0 0 1 -1.57138,-1.636031 5.2430389,5.2430389 0 0 1 0,-4.791483 4.0511871,4.0511871 0 0 1 1.57138,-1.635995 5.0228053,5.0228053 0 0 1 4.73218,0 4.1085585,4.1085585 0 0 1 1.57138,1.643414 5.1542044,5.1542044 0 0 1 0,4.776648 4.1085585,4.1085585 0 0 1 -1.57138,1.643447 5.0228053,5.0228053 0 0 1 -4.73218,0 z m 4.16046,-0.966083 a 3.0610601,3.0610601 0 0 0 1.15852,-1.262188 4.267719,4.267719 0 0 0 0,-3.607002 3.0610601,3.0610601 0 0 0 -1.15852,-1.262188 3.7014043,3.7014043 0 0 0 -3.58654,0 3.0610601,3.0610601 0 0 0 -1.15298,1.262188 4.267719,4.267719 0 0 0 0,3.607002 3.0610601,3.0610601 0 0 0 1.15298,1.262188 3.7014043,3.7014043 0 0 0 3.58654,0 z" | ||||
|        id="path35" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 118.73656,47.54096 a 0.55521063,0.55521063 0 0 1 -0.16668,-0.410853 v -7.684111 a 0.82541414,0.82541414 0 0 1 0.244,-0.603313 0.79395199,0.79395199 0 0 1 0.59255,-0.251708 h 0.16632 a 0.87353062,0.87353062 0 0 1 0.70887,0.386788 l 4.95608,7.165939 v -6.954935 a 0.57741901,0.57741901 0 0 1 0.16839,-0.418268 0.55521063,0.55521063 0 0 1 0.41306,-0.173957 0.56816551,0.56816551 0 0 1 0.41796,0.173957 0.57556829,0.57556829 0 0 1 0.1742,0.418268 v 7.689656 a 0.79950344,0.79950344 0 0 1 -0.25173,0.592235 0.83096538,0.83096538 0 0 1 -0.59969,0.244268 h -0.1538 a 0.81986106,0.81986106 0 0 1 -0.38661,-0.09622 0.89018674,0.89018674 0 0 1 -0.29631,-0.251703 l -4.98398,-7.199235 v 6.967918 a 0.54410636,0.54410636 0 0 1 -0.17355,0.410852 0.57741901,0.57741901 0 0 1 -0.41841,0.168392 0.55521063,0.55521063 0 0 1 -0.41067,-0.173966 z" | ||||
|        id="path37" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 132.36619,47.662806 a 0.16656329,0.16656329 0 0 1 -0.0526,-0.123236 v -2.305248 a 0.2476239,0.2476239 0 0 1 0.0757,-0.181014 0.23818531,0.23818531 0 0 1 0.17736,-0.0755 h 0.0526 a 0.26205927,0.26205927 0 0 1 0.21265,0.11605 l 1.48691,2.149758 v -2.086452 a 0.17322576,0.17322576 0 0 1 0.053,-0.125508 0.16656329,0.16656329 0 0 1 0.1239,-0.05205 0.17044952,0.17044952 0 0 1 0.12542,0.05205 0.17267036,0.17267036 0 0 1 0.0537,0.125508 v 2.306901 a 0.23985104,0.23985104 0 0 1 -0.0756,0.177669 0.24928962,0.24928962 0 0 1 -0.17993,0.07328 h -0.0471 a 0.24595828,0.24595828 0 0 1 -0.11605,-0.02905 0.26705624,0.26705624 0 0 1 -0.089,-0.0755 l -1.49522,-2.15977 v 2.090368 a 0.16323178,0.16323178 0 0 1 -0.0542,0.123258 0.17322576,0.17322576 0 0 1 -0.12533,0.05061 0.16656329,0.16656329 0 0 1 -0.12329,-0.05205 z" | ||||
|        id="path37-3" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 135.07399,47.664497 a 0.16989438,0.16989438 0 0 1 -0.0525,-0.123816 v -2.343552 a 0.17433613,0.17433613 0 0 1 0.0526,-0.125475 0.16656329,0.16656329 0 0 1 0.12399,-0.05205 h 1.54965 a 0.16656329,0.16656329 0 0 1 0.16636,0.166551 0.15434859,0.15434859 0 0 1 -0.0503,0.116035 0.16656329,0.16656329 0 0 1 -0.11765,0.04614 h -1.37251 v 0.851696 h 1.23043 a 0.16656329,0.16656329 0 0 1 0.16655,0.166554 0.15323809,0.15323809 0 0 1 -0.0503,0.116038 0.16267667,0.16267667 0 0 1 -0.11828,0.04711 h -1.23257 v 0.856687 h 1.37196 a 0.16656329,0.16656329 0 0 1 0.16661,0.166572 0.15490387,0.15490387 0 0 1 -0.0503,0.116017 0.16656329,0.16656329 0 0 1 -0.11768,0.04614 h -1.54784 a 0.16989438,0.16989438 0 0 1 -0.12371,-0.05061 z" | ||||
|        id="path21-6" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <path | ||||
|        class="cls-2" | ||||
|        d="m 138.31938,47.664494 a 0.16656329,0.16656329 0 0 1 -0.0526,-0.12328 V 45.32703 h -0.78834 a 0.15767982,0.15767982 0 0 1 -0.16207,-0.162122 0.16656329,0.16656329 0 0 1 0.0471,-0.117704 0.15490387,0.15490387 0 0 1 0.11604,-0.04838 h 1.92434 a 0.16656329,0.16656329 0 0 1 0.16665,0.166585 0.15434859,0.15434859 0 0 1 -0.0503,0.116026 0.16656329,0.16656329 0 0 1 -0.11765,0.04614 h -0.78728 v 2.213598 a 0.16323178,0.16323178 0 0 1 -0.054,0.12328 0.17267036,0.17267036 0 0 1 -0.12548,0.05061 0.16656329,0.16656329 0 0 1 -0.12163,-0.05061 z" | ||||
|        id="path25-7" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583" /> | ||||
|     <circle | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round" | ||||
|        id="path2370" | ||||
|        cx="131.01605" | ||||
|        cy="47.365242" | ||||
|        r="0.34973946" /> | ||||
|     <g | ||||
|        fill="#ffffff" | ||||
|        id="g5" | ||||
|        transform="matrix(0.99999435,0,0,0.99999435,22.886461,22.155914)"> | ||||
|       <path | ||||
|          d="m 20.983,0 v 22.81 l 6.455,6.5 V 13.783 Z m 14.473,0.024 v 15.549 l 6.456,13.736 V 6.499 Z" | ||||
|          fill-opacity="0.5" | ||||
|          id="path1" /> | ||||
|       <path | ||||
|          d="M 27.438,29.31 H 6.5 L 0,22.81 h 20.984 z" | ||||
|          id="path2" /> | ||||
|       <path | ||||
|          d="M 0,6.5 V 22.807 H 6.456 V 6.5 Z" | ||||
|          fill-opacity="0.5" | ||||
|          id="path3" /> | ||||
|       <path | ||||
|          d="M 19.533,0 H 6.5 L 0,6.5 H 13.32 Z M 41.915,29.316 28.142,0 h -7.165 l 13.755,29.316 z" | ||||
|          id="path4" /> | ||||
|       <path | ||||
|          d="m 47.39,2.545 a 2.545,2.545 0 1 0 -5.09,0 2.545,2.545 0 1 0 5.09,0 m -0.33,0 c 0,1.216 -0.999,2.243 -2.215,2.243 -1.216,0 -2.214,-1.027 -2.214,-2.243 0,-1.216 0.998,-2.243 2.214,-2.243 1.216,0 2.214,1.027 2.214,2.243 m -1.173,1.406 -0.71,-1.202 c 0.372,-0.106 0.64,-0.372 0.64,-0.787 0,-0.478 -0.409,-0.83 -0.872,-0.83 h -0.9 v 2.82 H 44.36 V 2.776 h 0.464 L 45.52,3.95 Z m -0.387,-1.99 c 0,0.31 -0.253,0.535 -0.59,0.535 h -0.55 V 1.42 h 0.55 c 0.337,0 0.59,0.232 0.59,0.542" | ||||
|          fill-opacity="0.51" | ||||
|          id="path5" /> | ||||
|     </g> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 28 KiB | 
							
								
								
									
										42
									
								
								public/img/logo.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								public/img/logo.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| 
 | ||||
| <svg | ||||
|    width="8.2602539mm" | ||||
|    height="8.3228693mm" | ||||
|    viewBox="0 0 8.2602539 8.3228693" | ||||
|    version="1.1" | ||||
|    id="svg1" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg"> | ||||
|   <defs | ||||
|      id="defs1" /> | ||||
|   <g | ||||
|      id="layer1" | ||||
|      transform="translate(-100.80624,-144.46251)"> | ||||
|     <rect | ||||
|        style="fill:none;fill-opacity:1;stroke:#fffdfd;stroke-width:0.396875;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||
|        id="rect3" | ||||
|        width="7.8633785" | ||||
|        height="4.0744472" | ||||
|        x="101.00468" | ||||
|        y="145.71317" /> | ||||
|     <g | ||||
|        id="g6" | ||||
|        transform="matrix(0.44901262,0,0,0.30313405,81.948876,138.55801)" | ||||
|        style="stroke:#ffffff;stroke-width:1.07574;stroke-dasharray:none;stroke-opacity:1"> | ||||
|       <path | ||||
|          style="fill:none;stroke:#ffffff;stroke-width:1.07574;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" | ||||
|          d="m 49.030808,37.632967 -2.348149,8.763414 m 6.348149,-8.763414 2.677863,8.763414" | ||||
|          id="path6" /> | ||||
|     </g> | ||||
|     <path | ||||
|        style="fill:none;fill-opacity:1;stroke:none;stroke-width:0.661458;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||
|        id="path7" | ||||
|        d="m 105.61076,145.15149 a 0.42403585,0.34019229 0 0 1 -0.21202,0.29461 0.42403585,0.34019229 0 0 1 -0.42404,0 0.42403585,0.34019229 0 0 1 -0.21201,-0.29461 h 0.42403 z" /> | ||||
|     <path | ||||
|        style="fill:#fbfbfb;fill-opacity:1;stroke:none;stroke-width:0.661458;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||
|        id="path8" | ||||
|        d="m 103.81304,145.58186 a 1.1233398,1.1193535 0 0 1 1.12334,-1.11935 1.1233398,1.1193535 0 0 1 1.12334,1.11935 h -1.12334 z" /> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										423
									
								
								public/img/presentationmaker.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								public/img/presentationmaker.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,423 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    viewBox="0 0 176 48" | ||||
|    version="1.1" | ||||
|    id="svg1" | ||||
|    width="176" | ||||
|    height="48" | ||||
|    xml:space="preserve" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg"><defs | ||||
|      id="defs1"><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8566"><path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8564" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8584"><path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8582" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8612"><path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8610" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8624"><path | ||||
|          d="m 271.674,749.573 v -64.657 l 18.3,-18.426 v 44.013 z" | ||||
|          id="path8622" /></clipPath><linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(0,-29.309916,29.309916,0,107.56319,51.61644)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8640"><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8630" /><stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.215824" | ||||
|          id="stop8632" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.75" | ||||
|          id="stop8634" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.76850016" | ||||
|          id="stop8636" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8638" /></linearGradient><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8650"><path | ||||
|          d="M 312.701,749.505 V 705.43 l 18.301,-38.937 v 64.659 z" | ||||
|          id="path8648" /></clipPath><linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(0,-29.284783,29.284783,0,122.03666,51.615502)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8666"><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8656" /><stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.422802" | ||||
|          id="stop8658" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.972582" | ||||
|          id="stop8660" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.97461095" | ||||
|          id="stop8662" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8664" /></linearGradient><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8676"><path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8674" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8684"><path | ||||
|          d="m 270.701,750.4 h 20.3 v -45.214 h -20.3 z" | ||||
|          id="path8682" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8700"><path | ||||
|          d="m 311.582,706.377 h 20.301 V 665.35 h -20.301 z" | ||||
|          id="path8698" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8716"><path | ||||
|          d="m 289.974,666.49 h -59.353 l -18.425,18.425 59.481,0.001 z" | ||||
|          id="path8714" /></clipPath><linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(19.297539,-16.192559,-16.192559,-19.297539,84.195184,56.472015)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8732"><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8722" /><stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.29489" | ||||
|          id="stop8724" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.662088" | ||||
|          id="stop8726" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.6870937" | ||||
|          id="stop8728" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8730" /></linearGradient><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8742"><path | ||||
|          d="m 212.196,731.148 v -46.226 l 18.301,0.002 v 46.224 z" | ||||
|          id="path8740" /></clipPath><linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(0,-16.307204,16.307204,0,86.58079,45.113934)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8766"><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0" | ||||
|          id="stop8748" /><stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.25" | ||||
|          id="stop8750" /><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0.44050522" | ||||
|          id="stop8752" /><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0.5" | ||||
|          id="stop8754" /><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0.52936829" | ||||
|          id="stop8756" /><stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.75" | ||||
|          id="stop8758" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.996319" | ||||
|          id="stop8760" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.9965914" | ||||
|          id="stop8762" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8764" /></linearGradient><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8776"><path | ||||
|          d="M 0,0 H 1280 V 800 H 0 Z" | ||||
|          id="path8774" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8784"><path | ||||
|          d="m 211.196,687.809 h 20.301 v -3.887 h -20.301 z" | ||||
|          id="path8782" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8800"><path | ||||
|          d="m 211.196,732.223 h 20.301 v -3.887 h -20.301 z" | ||||
|          id="path8798" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8816"><path | ||||
|          d="m 267.565,749.573 h -36.944 l -18.425,-18.425 h 37.755 z" | ||||
|          id="path8814" /></clipPath><linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(13.689206,12.765392,-12.765392,13.689206,83.04661,19.183338)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8832"><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8822" /><stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.29489" | ||||
|          id="stop8824" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.662088" | ||||
|          id="stop8826" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.6870937" | ||||
|          id="stop8828" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8830" /></linearGradient><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath8862"><path | ||||
|          d="m 331.011,666.473 -39.042,83.1 h -20.312 l 38.993,-83.1 z" | ||||
|          id="path8860" /></clipPath><linearGradient | ||||
|        x1="0" | ||||
|        y1="0" | ||||
|        x2="1" | ||||
|        y2="0" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(-16.76835,31.536681,-31.536681,-16.76835,119.95484,21.196219)" | ||||
|        spreadMethod="pad" | ||||
|        id="linearGradient8878"><stop | ||||
|          style="stop-opacity:1;stop-color:#dfbd6a" | ||||
|          offset="0" | ||||
|          id="stop8868" /><stop | ||||
|          style="stop-opacity:1;stop-color:#c78300" | ||||
|          offset="0.29489" | ||||
|          id="stop8870" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.662088" | ||||
|          id="stop8872" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="0.6870937" | ||||
|          id="stop8874" /><stop | ||||
|          style="stop-opacity:1;stop-color:#6f3200" | ||||
|          offset="1" | ||||
|          id="stop8876" /></linearGradient><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath2069"><path | ||||
|          d="M 0,0 H 23.3971 V -14.91 H 0 Z" | ||||
|          clip-rule="evenodd" | ||||
|          id="path2067" /></clipPath><clipPath | ||||
|        clipPathUnits="userSpaceOnUse" | ||||
|        id="clipPath2073"><path | ||||
|          d="M 0,-14.91 H 209.76378 V 14.91 H 0 Z" | ||||
|          id="path2071" /></clipPath><linearGradient | ||||
|        id="i" | ||||
|        spreadMethod="pad" | ||||
|        gradientTransform="matrix(19.29766,-16.19266,-16.19266,-19.29766,29.9802,59.309292)" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        y2="0" | ||||
|        x2="1" | ||||
|        y1="0" | ||||
|        x1="0"><stop | ||||
|          offset="0" | ||||
|          stop-color="#dfbd6a" | ||||
|          id="stop2648" /><stop | ||||
|          offset=".295" | ||||
|          stop-color="#c78300" | ||||
|          id="stop2650" /><stop | ||||
|          offset=".662" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2652" /><stop | ||||
|          offset=".687" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2654" /><stop | ||||
|          offset="1" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2656" /></linearGradient><clipPath | ||||
|        id="o" | ||||
|        clipPathUnits="userSpaceOnUse"><path | ||||
|          d="m 267.565,749.573 h -36.944 l -18.425,-18.425 h 37.755 z" | ||||
|          id="path2620" /></clipPath><linearGradient | ||||
|        id="p" | ||||
|        spreadMethod="pad" | ||||
|        gradientTransform="matrix(38.804048,-36.18536,-36.18536,-38.804048,228.9593,749.93786)" | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        y2="0" | ||||
|        x2="1" | ||||
|        y1="0" | ||||
|        x1="0"><stop | ||||
|          offset="0" | ||||
|          stop-color="#dfbd6a" | ||||
|          id="stop2678" /><stop | ||||
|          offset=".295" | ||||
|          stop-color="#c78300" | ||||
|          id="stop2680" /><stop | ||||
|          offset=".662" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2682" /><stop | ||||
|          offset=".687" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2684" /><stop | ||||
|          offset="1" | ||||
|          stop-color="#6f3200" | ||||
|          id="stop2686" /></linearGradient></defs><text | ||||
|      xml:space="preserve" | ||||
|      style="font-weight:bold;font-size:13.3333px;line-height:1.25;font-family:'DejaVu Serif';-inkscape-font-specification:'DejaVu Serif Bold';fill:#ffffff;fill-opacity:1" | ||||
|      x="42.828514" | ||||
|      y="15.528239" | ||||
|      id="text1"><tspan | ||||
|        id="tspan1" | ||||
|        x="42.828514" | ||||
|        y="15.528239" | ||||
|        style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;font-family:Roboto;-inkscape-font-specification:Roboto;fill:#ffffff;fill-opacity:1">PresentationMaker.js</tspan></text><text | ||||
|      xml:space="preserve" | ||||
|      style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:Roboto;fill:#ffffff;fill-opacity:1" | ||||
|      x="53.405025" | ||||
|      y="39.509506" | ||||
|      id="text2"><tspan | ||||
|        id="tspan2" | ||||
|        x="53.405025" | ||||
|        y="39.509506" | ||||
|        style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;font-family:Roboto;-inkscape-font-specification:Roboto;fill:#ffffff;fill-opacity:1">by</tspan></text><g | ||||
|      id="g2277" | ||||
|      transform="matrix(1.3333333,0,0,-1.3333333,17.273461,90.445105)" /><path | ||||
|      class="cls-2" | ||||
|      d="m 116.17083,31.093495 a 2.7248604,2.7248604 0 0 1 -1.08371,-1.084962 3.3371748,3.3371748 0 0 1 -0.39532,-1.653626 3.3359281,3.3359281 0 0 1 0.39282,-1.651121 2.7248604,2.7248604 0 0 1 1.08371,-1.084961 3.1937612,3.1937612 0 0 1 1.55885,-0.374115 3.6427085,3.6427085 0 0 1 1.05378,0.139662 4.4894729,4.4894729 0 0 1 0.92408,0.399067 0.34793417,0.34793417 0 0 1 0.19329,0.321744 0.32423971,0.32423971 0 0 1 -0.0948,0.230707 0.33546338,0.33546338 0 0 1 -0.24942,0.09977 0.35292248,0.35292248 0 0 1 -0.15588,-0.03474 3.9731835,3.9731835 0 0 0 -0.74825,-0.304286 3.0603242,3.0603242 0 0 0 -0.84177,-0.103508 2.4629749,2.4629749 0 0 0 -1.27077,0.30803 1.9616505,1.9616505 0 0 0 -0.7894,0.841775 2.6787192,2.6787192 0 0 0 -0.26563,1.209663 2.6799654,2.6799654 0 0 0 0.26563,1.210916 1.9616505,1.9616505 0 0 0 0.7894,0.841774 2.4629749,2.4629749 0 0 0 1.26952,0.314259 3.1089601,3.1089601 0 0 0 0.84178,-0.103505 3.9731835,3.9731835 0 0 0 0.74824,-0.304287 0.35292248,0.35292248 0 0 1 0.15589,-0.03474 0.3416988,0.3416988 0 0 1 0.24942,0.09602 0.31925143,0.31925143 0 0 1 0.0948,0.234453 0.34793417,0.34793417 0 0 1 -0.1908,0.329225 4.4894729,4.4894729 0 0 1 -0.92408,0.399067 3.6427085,3.6427085 0 0 1 -1.05254,0.132188 3.1937612,3.1937612 0 0 1 -1.55884,-0.374119 z" | ||||
|      id="path13" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 121.99841,31.073528 a 2.7348372,2.7348372 0 0 1 -1.05253,-1.1024 3.5229895,3.5229895 0 0 1 0,-3.228683 2.7348372,2.7348372 0 0 1 1.05752,-1.102422 3.3870581,3.3870581 0 0 1 3.19002,0 2.7772378,2.7772378 0 0 1 1.05877,1.10741 3.4830828,3.4830828 0 0 1 0,3.218704 2.7772378,2.7772378 0 0 1 -1.06625,1.107391 3.3870581,3.3870581 0 0 1 -3.19002,0 z m 2.80343,-0.650958 a 2.0464515,2.0464515 0 0 0 0.78067,-0.850509 2.6812134,2.6812134 0 0 0 0.26937,-1.215902 2.6799654,2.6799654 0 0 0 -0.26937,-1.21465 2.0464515,2.0464515 0 0 0 -0.78067,-0.850502 2.4941519,2.4941519 0 0 0 -2.41683,0 2.0713926,2.0713926 0 0 0 -0.77693,0.850502 2.6799654,2.6799654 0 0 0 -0.26812,1.21465 2.6812134,2.6812134 0 0 0 0.26812,1.215902 2.0713926,2.0713926 0 0 0 0.77693,0.850509 2.4941519,2.4941519 0 0 0 2.41683,0 z" | ||||
|      id="path15" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 128.07417,31.31546 a 0.37412277,0.37412277 0 0 1 -0.11348,-0.276845 v -5.182843 a 0.55619653,0.55619653 0 0 1 0.16461,-0.40281 0.53499609,0.53499609 0 0 1 0.39906,-0.169601 h 0.11349 a 0.5898674,0.5898674 0 0 1 0.47762,0.260644 l 3.34099,4.826182 v -4.686516 a 0.39407599,0.39407599 0 0 1 0.11228,-0.281834 0.37412277,0.37412277 0 0 1 0.27799,-0.117228 0.40031132,0.40031132 0 0 1 0.39896,0.399062 v 5.18161 a 0.53499609,0.53499609 0 0 1 -0.16959,0.399058 0.55619653,0.55619653 0 0 1 -0.40769,0.164613 h -0.10477 a 0.55619653,0.55619653 0 0 1 -0.26058,-0.06486 0.59610254,0.59610254 0 0 1 -0.19842,-0.169583 l -3.35954,-4.851136 v 4.695238 a 0.36664028,0.36664028 0 0 1 -0.11723,0.276846 0.38784056,0.38784056 0 0 1 -0.28184,0.113491 0.37412277,0.37412277 0 0 1 -0.27186,-0.113491 z" | ||||
|      id="path17" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 136.44823,31.31546 a 0.37412277,0.37412277 0 0 1 -0.11347,-0.276845 v -4.97333 h -1.76963 a 0.35666365,0.35666365 0 0 1 -0.26065,-0.103511 0.35292248,0.35292248 0 0 1 -0.10478,-0.260634 0.36664028,0.36664028 0 0 1 0.10478,-0.264389 0.34668704,0.34668704 0 0 1 0.26065,-0.108493 h 4.32113 a 0.37412277,0.37412277 0 0 1 0.3744,0.374118 0.34668704,0.34668704 0 0 1 -0.10884,0.260639 0.37412277,0.37412277 0 0 1 -0.26556,0.103507 h -1.76068 v 4.972093 a 0.37412277,0.37412277 0 0 1 -0.11751,0.276845 0.39033471,0.39033471 0 0 1 -0.28308,0.113492 0.37412277,0.37412277 0 0 1 -0.27676,-0.113492 z" | ||||
|      id="path19" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 140.32664,31.273076 a 0.3816052,0.3816052 0 0 1 -0.11206,-0.278111 v -5.263894 a 0.3915818,0.3915818 0 0 1 0.11206,-0.28185 0.37412277,0.37412277 0 0 1 0.27829,-0.117219 h 3.4805 a 0.37412277,0.37412277 0 0 1 0.37398,0.374121 0.34668704,0.34668704 0 0 1 -0.10825,0.260636 0.37412277,0.37412277 0 0 1 -0.26458,0.10351 h -3.08278 v 1.913009 h 2.76379 a 0.37412277,0.37412277 0 0 1 0.37399,0.374128 0.34419294,0.34419294 0 0 1 -0.10856,0.260642 0.36539325,0.36539325 0 0 1 -0.26543,0.106002 h -2.76868 v 1.924237 h 3.08136 a 0.37412277,0.37412277 0 0 1 0.37437,0.374118 0.34793417,0.34793417 0 0 1 -0.1087,0.260633 0.37412277,0.37412277 0 0 1 -0.26428,0.103511 h -3.47673 a 0.3816052,0.3816052 0 0 1 -0.27829,-0.113473 z" | ||||
|      id="path21" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 145.8639,31.31546 a 0.37412277,0.37412277 0 0 1 -0.11232,-0.276845 v -5.182843 a 0.55619653,0.55619653 0 0 1 0.16441,-0.40281 0.53499609,0.53499609 0 0 1 0.39921,-0.169601 h 0.11209 a 0.58861931,0.58861931 0 0 1 0.47766,0.260644 l 3.3472,4.826182 v -4.686516 a 0.38908765,0.38908765 0 0 1 0.11347,-0.281834 0.36664028,0.36664028 0 0 1 0.27678,-0.117228 0.39781717,0.39781717 0 0 1 0.39935,0.399062 v 5.18161 a 0.53748988,0.53748988 0 0 1 -0.1684,0.399058 0.56118354,0.56118354 0 0 1 -0.4041,0.164613 h -0.10363 a 0.55245464,0.55245464 0 0 1 -0.26051,-0.06486 0.59984285,0.59984285 0 0 1 -0.19973,-0.169583 l -3.35836,-4.851136 v 4.695239 a 0.36664028,0.36664028 0 0 1 -0.11693,0.276845 0.38908765,0.38908765 0 0 1 -0.28195,0.113491 0.37412277,0.37412277 0 0 1 -0.28424,-0.113491 z" | ||||
|      id="path23" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 154.24269,31.31546 a 0.37412277,0.37412277 0 0 1 -0.11221,-0.276845 v -4.97333 h -1.77068 a 0.35416956,0.35416956 0 0 1 -0.36415,-0.364145 0.37412277,0.37412277 0 0 1 0.10333,-0.264389 0.34793417,0.34793417 0 0 1 0.26082,-0.108493 h 4.32249 a 0.37412277,0.37412277 0 0 1 0.37398,0.374118 0.34668704,0.34668704 0 0 1 -0.10846,0.260639 0.37412277,0.37412277 0 0 1 -0.26436,0.103507 h -1.76857 v 4.972093 a 0.36664028,0.36664028 0 0 1 -0.11699,0.276845 0.38784056,0.38784056 0 0 1 -0.28195,0.113492 0.37412277,0.37412277 0 0 1 -0.27325,-0.113492 z" | ||||
|      id="path25" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 115.16943,39.823012 a 0.37412277,0.37412277 0 0 1 -0.11348,-0.276849 v -5.177856 a 0.55245464,0.55245464 0 0 1 0.16585,-0.406536 0.53250156,0.53250156 0 0 1 0.39907,-0.169611 h 0.11224 a 0.58861931,0.58861931 0 0 1 0.47388,0.264391 l 3.34092,4.824934 v -4.686509 a 0.38908765,0.38908765 0 0 1 0.11348,-0.281846 0.36664028,0.36664028 0 0 1 0.27685,-0.117219 0.40031132,0.40031132 0 0 1 0.39907,0.399065 v 5.181593 a 0.53748988,0.53748988 0 0 1 -0.16836,0.399071 0.56118354,0.56118354 0 0 1 -0.40405,0.164597 h -0.10351 a 0.55245464,0.55245464 0 0 1 -0.26063,-0.06484 0.58861931,0.58861931 0 0 1 -0.19954,-0.169607 l -3.35837,-4.851128 v 4.695258 a 0.37412277,0.37412277 0 0 1 -0.11723,0.276848 0.39033471,0.39033471 0 0 1 -0.28308,0.113469 0.37412277,0.37412277 0 0 1 -0.27311,-0.117225 z" | ||||
|      id="path27" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 121.7253,39.823012 a 0.38285228,0.38285228 0 0 1 -0.10849,-0.276849 0.47388884,0.47388884 0 0 1 0.0435,-0.173331 l 2.21233,-5.225266 a 0.68090375,0.68090375 0 0 1 0.1958,-0.249404 0.48261818,0.48261818 0 0 1 0.30803,-0.09976 h 0.0873 a 0.48511243,0.48511243 0 0 1 0.30803,0.09976 0.66593852,0.66593852 0 0 1 0.19454,0.249404 l 2.21482,5.229003 a 0.47388884,0.47388884 0 0 1 0.0435,0.173351 0.38784056,0.38784056 0 0 1 -0.1085,0.276848 0.37412277,0.37412277 0 0 1 -0.28309,0.113469 0.4015584,0.4015584 0 0 1 -0.22072,-0.06484 0.42525289,0.42525289 0 0 1 -0.15214,-0.178326 l -0.56361,-1.354322 h -2.95557 l -0.55993,1.355556 a 0.42525289,0.42525289 0 0 1 -0.15215,0.17834 0.40904086,0.40904086 0 0 1 -0.22197,0.06485 0.37412277,0.37412277 0 0 1 -0.28184,-0.118488 z m 1.52269,-2.203573 h 2.34325 l -1.17101,-2.820878 z" | ||||
|      id="path29" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 129.47962,39.823012 a 0.37412277,0.37412277 0 0 1 -0.11348,-0.276849 v -4.969594 h -1.7696 a 0.35541662,0.35541662 0 0 1 -0.3654,-0.365382 0.36664028,0.36664028 0 0 1 0.10476,-0.264396 0.34668704,0.34668704 0 0 1 0.26064,-0.108491 h 4.32363 a 0.37412277,0.37412277 0 0 1 0.37417,0.37412 0.34668704,0.34668704 0 0 1 -0.10865,0.260648 0.36414615,0.36414615 0 0 1 -0.2642,0.103501 h -1.76468 v 4.973351 a 0.37412277,0.37412277 0 0 1 -0.11726,0.276848 0.39033471,0.39033471 0 0 1 -0.28308,0.113469 0.37412277,0.37412277 0 0 1 -0.27685,-0.117225 z" | ||||
|      id="path31" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 133.35796,39.823012 a 0.37412277,0.37412277 0 0 1 -0.11227,-0.276849 v -5.351187 a 0.39407599,0.39407599 0 0 1 0.11227,-0.281846 0.37412277,0.37412277 0 0 1 0.27829,-0.117219 0.40031132,0.40031132 0 0 1 0.399,0.399065 v 5.354944 a 0.36664028,0.36664028 0 0 1 -0.11982,0.273092 0.38784056,0.38784056 0 0 1 -0.28191,0.113492 0.37412277,0.37412277 0 0 1 -0.27556,-0.113492 z" | ||||
|      id="path33" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 136.80369,39.584835 a 2.7298493,2.7298493 0 0 1 -1.05886,-1.102422 3.5329659,3.5329659 0 0 1 0,-3.228689 2.7298493,2.7298493 0 0 1 1.05886,-1.102398 3.3845639,3.3845639 0 0 1 3.18873,0 2.7685084,2.7685084 0 0 1 1.05886,1.107397 3.4731057,3.4731057 0 0 1 0,3.218693 2.7685084,2.7685084 0 0 1 -1.05886,1.107419 3.3845639,3.3845639 0 0 1 -3.18873,0 z m 2.80348,-0.650984 a 2.0626627,2.0626627 0 0 0 0.78066,-0.850512 2.875757,2.875757 0 0 0 0,-2.43054 2.0626627,2.0626627 0 0 0 -0.78066,-0.850512 2.4941519,2.4941519 0 0 0 -2.41675,0 2.0626627,2.0626627 0 0 0 -0.77692,0.850512 2.875757,2.875757 0 0 0 0,2.43054 2.0626627,2.0626627 0 0 0 0.77692,0.850512 2.4941519,2.4941519 0 0 0 2.41675,0 z" | ||||
|      id="path35" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 142.87837,39.823012 a 0.37412277,0.37412277 0 0 1 -0.11231,-0.276849 v -5.177856 a 0.55619653,0.55619653 0 0 1 0.16441,-0.406536 0.53499609,0.53499609 0 0 1 0.39929,-0.169611 h 0.11207 a 0.58861931,0.58861931 0 0 1 0.47766,0.260633 l 3.33961,4.828692 v -4.686509 a 0.38908765,0.38908765 0 0 1 0.11346,-0.281846 0.37412277,0.37412277 0 0 1 0.27834,-0.117219 0.38285228,0.38285228 0 0 1 0.28164,0.117219 0.38784056,0.38784056 0 0 1 0.11738,0.281846 v 5.181593 a 0.53873688,0.53873688 0 0 1 -0.16963,0.399071 0.55993717,0.55993717 0 0 1 -0.40409,0.164597 h -0.10364 a 0.55245464,0.55245464 0 0 1 -0.26051,-0.06484 0.59984285,0.59984285 0 0 1 -0.19967,-0.169607 l -3.3584,-4.851128 v 4.695258 a 0.36664028,0.36664028 0 0 1 -0.11694,0.276848 0.38908765,0.38908765 0 0 1 -0.28194,0.113469 0.37412277,0.37412277 0 0 1 -0.27673,-0.117225 z" | ||||
|      id="path37" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 152.06255,39.905117 a 0.1122369,0.1122369 0 0 1 -0.0354,-0.08304 v -1.553366 a 0.16685873,0.16685873 0 0 1 0.051,-0.121975 0.16049863,0.16049863 0 0 1 0.11951,-0.05088 h 0.0354 a 0.17658585,0.17658585 0 0 1 0.1433,0.0782 l 1.00193,1.448592 v -1.405933 a 0.11672633,0.11672633 0 0 1 0.0357,-0.08457 0.1122369,0.1122369 0 0 1 0.0835,-0.03507 0.11485559,0.11485559 0 0 1 0.0845,0.03507 0.11635208,0.11635208 0 0 1 0.0362,0.08457 v 1.55448 a 0.16162107,0.16162107 0 0 1 -0.0509,0.119721 0.16798116,0.16798116 0 0 1 -0.12124,0.04938 h -0.0317 a 0.16573637,0.16573637 0 0 1 -0.0782,-0.01958 0.179953,0.179953 0 0 1 -0.06,-0.05087 l -1.00754,-1.455338 v 1.408572 a 0.109992,0.109992 0 0 1 -0.0365,0.08306 0.11672633,0.11672633 0 0 1 -0.0844,0.0341 0.1122369,0.1122369 0 0 1 -0.0831,-0.03507 z" | ||||
|      id="path37-3" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 153.88717,39.906256 a 0.11448152,0.11448152 0 0 1 -0.0354,-0.08343 v -1.579177 a 0.11747454,0.11747454 0 0 1 0.0354,-0.08455 0.1122369,0.1122369 0 0 1 0.0836,-0.03507 h 1.04422 a 0.1122369,0.1122369 0 0 1 0.1121,0.112229 0.10400615,0.10400615 0 0 1 -0.0339,0.07819 0.1122369,0.1122369 0 0 1 -0.0793,0.03109 h -0.92486 v 0.573906 h 0.82912 a 0.1122369,0.1122369 0 0 1 0.11222,0.112231 0.10325785,0.10325785 0 0 1 -0.0339,0.07819 0.10961794,0.10961794 0 0 1 -0.0797,0.03174 h -0.83056 v 0.57727 h 0.92448 a 0.1122369,0.1122369 0 0 1 0.11227,0.112242 0.10438032,0.10438032 0 0 1 -0.0339,0.07818 0.1122369,0.1122369 0 0 1 -0.0793,0.03109 h -1.04299 a 0.11448152,0.11448152 0 0 1 -0.0834,-0.0341 z" | ||||
|      id="path21-6" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><path | ||||
|      class="cls-2" | ||||
|      d="m 156.07405,39.906254 a 0.1122369,0.1122369 0 0 1 -0.0354,-0.08307 V 38.33118 h -0.53121 a 0.10625087,0.10625087 0 0 1 -0.10921,-0.109244 0.1122369,0.1122369 0 0 1 0.0317,-0.07931 0.10438032,0.10438032 0 0 1 0.0782,-0.0326 h 1.29669 a 0.1122369,0.1122369 0 0 1 0.1123,0.112251 0.10400615,0.10400615 0 0 1 -0.0339,0.07818 0.1122369,0.1122369 0 0 1 -0.0793,0.03109 h -0.5305 v 1.49161 a 0.109992,0.109992 0 0 1 -0.0364,0.08307 0.11635208,0.11635208 0 0 1 -0.0846,0.0341 0.1122369,0.1122369 0 0 1 -0.082,-0.0341 z" | ||||
|      id="path25-7" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke-width:0.999998" /><circle | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:6.80315;stroke-linecap:round;stroke-linejoin:round" | ||||
|      id="path2370" | ||||
|      cx="151.15277" | ||||
|      cy="39.704605" | ||||
|      r="0.23566821" /><rect | ||||
|      style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||
|      id="rect3" | ||||
|      width="29.719856" | ||||
|      height="15.399486" | ||||
|      x="9.3059111" | ||||
|      y="12.942889" /><g | ||||
|      id="g6" | ||||
|      transform="matrix(1.6970556,0,0,1.1457035,-62.716054,-14.100197)" | ||||
|      style="stroke-width:1.07574;stroke-dasharray:none;stroke:#ffffff;stroke-opacity:1"><path | ||||
|        style="fill:none;stroke:#ffffff;stroke-width:1.07574;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" | ||||
|        d="m 49.030808,37.632967 -2.348149,8.763414 m 6.348149,-8.763414 2.677863,8.763414" | ||||
|        id="path6" /></g><path | ||||
|      style="fill:none;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||
|      id="path7" | ||||
|      d="m 26.714672,10.820005 a 1.6026552,1.2857661 0 0 1 -0.801328,1.113507 1.6026552,1.2857661 0 0 1 -1.602655,0 1.6026552,1.2857661 0 0 1 -0.801327,-1.113507 h 1.602655 z" /><path | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||
|      id="path8" | ||||
|      d="m 19.920145,12.446616 a 4.2456937,4.2306275 0 0 1 4.245693,-4.2306274 4.2456937,4.2306275 0 0 1 4.245694,4.2306274 h -4.245694 z" /><g | ||||
|      id="g1" | ||||
|      transform="matrix(0,0.13298493,-0.12521031,0,101.95019,26.354144)" | ||||
|      style="stroke-width:7.74957"><path | ||||
|        id="path8642" | ||||
|        class="cls-1" | ||||
|        d="M -30,76.61 H 92.8 l 35,-34.76 H 44.2 Z" | ||||
|        style="fill:#d9e663;stroke-width:7.74957" /><path | ||||
|        id="path8668" | ||||
|        class="cls-1" | ||||
|        d="M -29.87,-1.31 H 53.8 l 74,-34.75 H 4.99 Z" | ||||
|        style="fill:#d9e663;stroke-width:7.74957" /><path | ||||
|        id="path8734" | ||||
|        class="cls-2" | ||||
|        d="m 127.8,41.85 v 112.72 l -35,35 v -113 z" | ||||
|        style="fill:#edfe60;stroke-width:7.74957" /><path | ||||
|        id="path8702" | ||||
|        class="cls-3" | ||||
|        d="m 53.94,-1.08 73.94,-34.76 h 0.17" | ||||
|        style="fill:#371900;stroke-width:7.74957" /><path | ||||
|        id="path8768" | ||||
|        class="cls-1" | ||||
|        d="M 5,189.56 H 92.8 V 154.81 H 5 Z" | ||||
|        style="fill:#d9e663;stroke-width:7.74957" /><path | ||||
|        id="path8834" | ||||
|        class="cls-2" | ||||
|        d="m -30,84.38 v 70.19 l 35,35 v -71.7 z" | ||||
|        style="fill:#edfe60;stroke-width:7.74957" /><path | ||||
|        id="path8880" | ||||
|        class="cls-2" | ||||
|        d="M 127.8,-36.08 -30,38.06 v 38.58 l 157.82,-74 z" | ||||
|        style="fill:#edfe60;stroke-width:7.74957" /><path | ||||
|        id="Pfad_210" | ||||
|        data-name="Pfad 210" | ||||
|        class="cls-1" | ||||
|        d="m -16.55,-66 a 13.07,13.07 0 0 0 -13.07,13.06 v 0 a 13.08,13.08 0 0 0 13.06,13.07 v 0 a 13.06,13.06 0 0 0 13.07,-13.05 v 0 a 13.06,13.06 0 0 0 -13.05,-13.07 v 0 m 0,1.7 a 11.37,11.37 0 1 1 -11.52,11.37 11.54,11.54 0 0 1 11.52,-11.37 m 7.22,6 -6.18,3.67 a 4.11,4.11 0 0 0 -4.05,-3.29 4.37,4.37 0 0 0 -4.26,4.45 v 4.66 h 14.48 v -1.62 h -6 v -2.39 l 6,-3.57 z m -10.21,2 a 2.83,2.83 0 0 1 2.75,2.88 v 3 h -5.54 v -2.82 a 2.84,2.84 0 0 1 2.65,-3 h 0.13" | ||||
|        style="fill:#d9e663;stroke-width:7.74957" /></g></svg> | ||||
| After Width: | Height: | Size: 27 KiB | 
							
								
								
									
										34
									
								
								public/index.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								public/index.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| <!DOCTYPE html> | ||||
| <html> | ||||
|   <head> | ||||
|     <title>Example</title> | ||||
|     <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1,maximum-scale=1, user-scalable=no"> | ||||
|     <link rel="stylesheet" href="style.css" /> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div id="ar"> | ||||
|       <div id="render"> | ||||
|         <div class="ui"> | ||||
|           <a href="#" data-action="fullscreen">⛶</a> | ||||
|           <a href="#" data-action="prev">🠈</a> | ||||
|           <select data-id="pages"></select> | ||||
|           <a href="#" data-action="next">🠊</a> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <script src="presentationmaker.js" type="text/javascript"></script> | ||||
|     <script type="text/javascript"> | ||||
|       document.addEventListener("DOMContentLoaded", async () => { | ||||
|         const config = { | ||||
|           targetSelector: '#render', | ||||
|           sourceURI: 'example.xml', | ||||
|           transitionType: 'transform', | ||||
|         }; | ||||
|         const pm = new PresentationMaker(config); | ||||
|         await pm.generate(); | ||||
|         pm.present(); | ||||
|         // custom script logic | ||||
|       }); | ||||
|     </script> | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										
											BIN
										
									
								
								public/roboto.woff2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/roboto.woff2
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										106
									
								
								public/style.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								public/style.css
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | |||
| @font-face { | ||||
|   font-family:'Roboto'; | ||||
|   font-style:bold; | ||||
|   font-weight:600; | ||||
|   src:url(roboto.woff2) format('woff2'); | ||||
|   font-display:swap | ||||
| } | ||||
| 
 | ||||
| html, | ||||
| body { | ||||
|   margin: 0; | ||||
|   padding: 0; | ||||
| } | ||||
| 
 | ||||
| body { | ||||
|   width: 100vw; | ||||
|   height: 100vh; | ||||
|   display: flex; | ||||
|   justify-content: center; | ||||
|   align-items: center; | ||||
|   background-color: #000000; | ||||
|   font-size: min(1vw, 1.778vh); | ||||
|   overflow:clip; | ||||
|   font-family: Roboto, sans-serif; | ||||
| } | ||||
| 
 | ||||
| #ar { | ||||
|   width: 100em; | ||||
|   height: 56.25em; | ||||
| } | ||||
| 
 | ||||
| #render { | ||||
|   font-size: 1em; | ||||
|   a { | ||||
|     color: #BBBBff; | ||||
|     img { | ||||
|       vertical-align: bottom; | ||||
|     } | ||||
|   } | ||||
|   .ui { | ||||
|     position: fixed; | ||||
|     z-index: 999999; | ||||
|     color: #ffffff; | ||||
|     top: 20px; | ||||
|     left: 20px; | ||||
|     text-shadow: #000000 2px 0 0; | ||||
|     opacity: 0; | ||||
|     transition: opacity 1s ease-in-out; | ||||
|     font-size:2em; | ||||
|     &.visible { | ||||
|       opacity: 0.75; | ||||
|     } | ||||
|     a { | ||||
|       color: inherit; | ||||
|       text-decoration: none; | ||||
|       font-size: 1.0em; | ||||
|     } | ||||
|     a.disabled { | ||||
|       color: transparent; | ||||
|       cursor: default; | ||||
|     } | ||||
|     select { | ||||
|       margin: 0 5px; | ||||
|       outline: none; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #fullscreen { | ||||
|   font-weight: bold; | ||||
| } | ||||
| #fs { | ||||
|   margin-left:10px; | ||||
| } | ||||
| 
 | ||||
| .page { | ||||
|   position: absolute; | ||||
|   transform-origin: top left 0px; | ||||
|   transition: opacity .5s ease-in-out; | ||||
| } | ||||
| .page.inactive { | ||||
|   opacity: 0.5; | ||||
|   transition: opacity .5s ease-in-out; | ||||
| } | ||||
| 
 | ||||
| [data-action] { | ||||
|   height: 2em; | ||||
|   vertical-align: middle; | ||||
|   cursor: pointer; | ||||
| } | ||||
| 
 | ||||
| #viewport { | ||||
|   transition: all 1s ease-in-out; | ||||
|   transform-style: preserve-3d; | ||||
|   transform-origin: top left 0px; | ||||
| } | ||||
| #render { | ||||
|   overflow: clip; | ||||
|   height:100vh; | ||||
|   perspective: 1000px; | ||||
| } | ||||
| 
 | ||||
| .option { | ||||
|   width:100%; | ||||
|   height:100%; | ||||
| } | ||||
							
								
								
									
										432
									
								
								src/presentationmaker.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										432
									
								
								src/presentationmaker.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,432 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  **/ | ||||
| 
 | ||||
| import { RenderTree } from './rendertree/rendertree'; | ||||
| import { RTPage, RTTransformation } from './rendertree/rtpage'; | ||||
| 
 | ||||
| /** | ||||
|  * configuration options for PresentationMaker | ||||
|  */ | ||||
| export interface initialConfig { | ||||
|   /** selector for source tree inside a <script type="presentationmaker">...</script> */ | ||||
|   sourceSelector?: string, | ||||
|   /** alternative URL instead of script tag */ | ||||
|   sourceURI?: string, | ||||
|   /** position to attach generated tree to */ | ||||
|   targetSelector: string, | ||||
|   /** optional transition type, defaults to flip */ | ||||
|   transitionType?: string | ||||
|   /** option ui selector string */ | ||||
|   uiSelector?: string; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * main class | ||||
|  */ | ||||
| export class PresentationMaker { | ||||
|   /** generated render tree */ | ||||
|   private tree: RenderTree; | ||||
|   /** definitions for variable replacements */ | ||||
|   private definitions: Array<Map<string, string>>; | ||||
|   /** custom modules defined by the import document */ | ||||
|   private modules: Map<string, RenderTree>; | ||||
|   /** current page index */ | ||||
|   private currentPage: number; | ||||
|   /** number of slide */ | ||||
|   private numPages: number; | ||||
|   /** our viewport (window to the presentation) */ | ||||
|   private viewportElement: HTMLDivElement; | ||||
|   /** transition type [flip / transition] */ | ||||
|   private transition: string; | ||||
|   /** time for autohiding of UI */ | ||||
|   private timer: number; | ||||
|   /** ui root node */ | ||||
|   private ui: HTMLDivElement; | ||||
|   /** page selector */ | ||||
|   private select: HTMLSelectElement; | ||||
|   /** X start position to detect slide left/right */ | ||||
|   private touchStartX: number; | ||||
|   /** initial config from caller */ | ||||
|   private config: initialConfig; | ||||
| 
 | ||||
|   /** | ||||
|    * change slide to given number | ||||
|    * @param slideNum slide number 0-based | ||||
|    */ | ||||
|   private changeSlide(slideNum: number) { | ||||
|     if (slideNum < 0 && slideNum >= this.numPages) { | ||||
|       return; | ||||
|     } | ||||
|     const newPage = this.tree.getElement(slideNum); | ||||
|     const page = <RTPage>newPage; | ||||
|     const pages = this.viewportElement.querySelectorAll('.page'); | ||||
|     if (this.currentPage >= 0 && this.currentPage < this.numPages) { | ||||
|       (<HTMLElement>pages[this.currentPage]).classList.add('inactive'); | ||||
|     } | ||||
|     switch (this.transition) { | ||||
|       case 'transform': | ||||
|         // this.transform = page.getView();
 | ||||
|         this.currentPage = slideNum; | ||||
|         this.moveViewpoint(); | ||||
|         break; | ||||
|       default: | ||||
|         if (this.currentPage >= 0 && this.currentPage < this.numPages) { | ||||
|           (<HTMLElement>pages[this.currentPage]).style.display = 'none'; | ||||
|         } | ||||
|         this.currentPage = slideNum; | ||||
|         const newPage = <HTMLElement>pages[this.currentPage]; | ||||
|         newPage.style.display = 'block' | ||||
|         break; | ||||
|     } | ||||
|     if (this.currentPage >= 0 && this.currentPage < this.numPages) { | ||||
|       (<HTMLElement>pages[this.currentPage]).classList.remove('inactive'); | ||||
|     } | ||||
|     document.location.hash = (this.currentPage + 1).toString(); | ||||
|     this.select.value = this.currentPage.toString(); | ||||
|     const prev = document.querySelector('[data-action="prev"]'); | ||||
|     if (this.currentPage == 0) { | ||||
|       prev.classList.add('disabled'); | ||||
|     } else { | ||||
|       prev.classList.remove('disabled'); | ||||
|     } | ||||
|     const next = document.querySelector('[data-action="next"]'); | ||||
|     if (this.currentPage + 1 >= this.numPages) { | ||||
|       next.classList.add('disabled'); | ||||
|     } else { | ||||
|       next.classList.remove('disabled'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    */ | ||||
|   constructor(config: initialConfig) { | ||||
|     if (config === undefined) { | ||||
|       throw('please supply a configuration'); | ||||
|     } | ||||
|     this.definitions = []; | ||||
|     this.modules = new Map<string, RenderTree>(); | ||||
|     this.currentPage = 0; | ||||
|     this.numPages = 0; | ||||
|     this.transition = config.transitionType || 'flip'; | ||||
|     this.tree = new RenderTree(this, null); | ||||
|     this.ui = document.querySelector(config.uiSelector || '.ui'); | ||||
|     this.select = this.ui.querySelector('select[data-id=pages]'); | ||||
|     if (document.location.hash) { | ||||
|       this.currentPage = parseInt(document.location.hash.substring(1)) - 1; | ||||
|     } | ||||
|     this.config = config; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create definitions from element tree | ||||
|    * @param elem <definition>...</definition> node tree | ||||
|    */ | ||||
|   private createDefinitions(elem: HTMLElement): void { | ||||
|     const definitions: Map<string, string> = new Map<string, string>(); | ||||
|     elem.childNodes.forEach((def) => { | ||||
|       if (def.nodeType == 1) { | ||||
|         const definitionElement = <HTMLElement>def; | ||||
|         definitions.set(definitionElement.localName, definitionElement.innerHTML); | ||||
|       } | ||||
|     }); | ||||
|     this.definitions.push(definitions); | ||||
|      | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create a custom module from input | ||||
|    * @param elem <module>...</module> node tree | ||||
|    */ | ||||
|   private createModules(elem: HTMLElement): void { | ||||
|     elem.childNodes.forEach((module) => { | ||||
|       if (module.nodeType == 1) { | ||||
|         const moduleElement = <HTMLElement>module; | ||||
|         const tree = new RenderTree(this); | ||||
|         tree.createFromElem(moduleElement); | ||||
|         this.modules.set(moduleElement.localName, tree); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create pages from input | ||||
|    * @param elem <slides>...</slides> node tree | ||||
|    */ | ||||
|   private createPages(elem: HTMLElement): void { | ||||
|     const pageElement = <HTMLElement>elem; | ||||
|     this.tree.createFromElem(pageElement); | ||||
|     this.numPages = this.tree.getElementCount(); | ||||
|     this.definitions[0].set('numpages', this.numPages.toString()); | ||||
|     this.definitions[0].set('page', '0'); | ||||
|     for (let i = 0; i < this.numPages; ++i) { | ||||
|       const newPage = this.tree.getElement(i); | ||||
|       const page = <RTPage>newPage; | ||||
|       const option = document.createElement('option'); | ||||
|       option.value = i.toString(); | ||||
|       option.innerText = page.getName(); | ||||
|       this.select.append(option); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * generate HTML tree from input XML | ||||
|    */ | ||||
|   async generate(): Promise<void> { | ||||
|     let root; | ||||
|     const parser = new DOMParser(); | ||||
|     if (this.config.sourceSelector !== undefined) { | ||||
|       const source = document.querySelector(this.config.sourceSelector); | ||||
|       root = <HTMLElement>parser.parseFromString(source.outerHTML, 'application/xml').querySelector('script'); | ||||
|     } else { | ||||
|       const response = await fetch(this.config.sourceURI); | ||||
|       const data = await response.blob(); | ||||
|       root = <HTMLElement>parser.parseFromString(await data.text(), 'application/xml').querySelector('presentation'); | ||||
|     } | ||||
| 
 | ||||
|     // iterate over the elements
 | ||||
|     root.childNodes.forEach((node) => { | ||||
|       const elem = <HTMLElement>node; | ||||
|       switch (elem.localName) { | ||||
|         case 'definitions': | ||||
|           this.createDefinitions(elem); | ||||
|           break; | ||||
|         case 'modules': | ||||
|           this.createModules(elem); | ||||
|           break; | ||||
|         case 'pages': | ||||
|           this.createPages(elem); | ||||
|           break; | ||||
|       } | ||||
|       node = node.nextSibling; | ||||
|     }); | ||||
|     // render pages
 | ||||
|     this.viewportElement = <HTMLDivElement>document.createElement('div'); | ||||
|     this.viewportElement.id = 'viewport'; | ||||
|     this.tree.render(this.viewportElement); | ||||
|     const renderTarget = <HTMLDivElement>document.querySelector(this.config.targetSelector); | ||||
|     renderTarget.append(this.viewportElement); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * get a definition (value) for given name | ||||
|    * @param name name to look up | ||||
|    * @returns value or '' if not found | ||||
|    * @internal | ||||
|    */ | ||||
|   getDefinition(name: string): string { | ||||
|     let ret = ''; | ||||
|     this.definitions.forEach((definitions) => { | ||||
|       const i = definitions.get(name); | ||||
|       if (i !== undefined) { | ||||
|         ret = i; | ||||
|       } | ||||
|     }); | ||||
|     if (ret === '') { | ||||
|       console.log('failed to get definition for', name); | ||||
|     } | ||||
|     return ret; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create a new module (copy) with given name | ||||
|    * @param name name of module | ||||
|    * @return copy of module or null if not found | ||||
|    * @internal | ||||
|    */ | ||||
|   getNewModule(name: string): RenderTree { | ||||
|     const i = this.modules.get(name); | ||||
|     if (i !== undefined) { | ||||
|       return (new RenderTree(this, i)); | ||||
|     } | ||||
|     console.log('unknown render element', name); | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * handle mouse click or tap events | ||||
|    * @param ev brower event | ||||
|    */ | ||||
|   private handleClick = (ev?: MouseEvent) => { | ||||
|     const target = <HTMLElement>ev.target; | ||||
|     let action = target.getAttribute('data-action'); | ||||
|     if (action === null) { | ||||
|       action = target.getAttribute("data-id"); | ||||
|     } | ||||
|     let slideNum; | ||||
|     switch (action) { | ||||
|       case 'fullscreen': | ||||
|         if (!document.fullscreenElement) { | ||||
|           document.documentElement.requestFullscreen(); | ||||
|         } else { | ||||
|           document.exitFullscreen(); | ||||
|         } | ||||
|         ev.stopPropagation(); | ||||
|         ev.preventDefault(); | ||||
|         break; | ||||
|       case 'prev': | ||||
|         slideNum = Math.max(this.currentPage - 1, 0); | ||||
|         break; | ||||
|       case 'next': | ||||
|       case null: | ||||
|         slideNum = Math.min(this.currentPage + 1, this.numPages - 1); | ||||
|         break; | ||||
|     } | ||||
|     if (slideNum !== undefined) { | ||||
|       this.changeSlide(slideNum); | ||||
|     } | ||||
|     if (target.closest('.ui')) { | ||||
|       ev.stopPropagation(); | ||||
|       ev.preventDefault(); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * handle a change of the page dropdown | ||||
|    */ | ||||
|   private handleDropdown = (ev?: Event) => { | ||||
|     ev.stopPropagation(); | ||||
|     ev.preventDefault(); | ||||
|     this.changeSlide(parseInt(this.select.value)); | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * handle key presses | ||||
|    * @param ev pressed key | ||||
|    */ | ||||
|   private handleKey = (ev?: KeyboardEvent) => { | ||||
|     switch (ev.key) { | ||||
|       case 'ArrowLeft': | ||||
|         this.changeSlide(Math.max(this.currentPage - 1, 0)); | ||||
|         break; | ||||
|       case 'ArrowRight': | ||||
|         this.changeSlide(Math.min(this.currentPage + 1, this.numPages - 1)); | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * handle mouse move and show ui | ||||
|    */ | ||||
|   private handleMouseMove = () => { | ||||
|     if (this.timer) { | ||||
|       window.clearTimeout(this.timer); | ||||
|     } | ||||
|     this.ui.classList.add('visible'); | ||||
|     document.body.style.cursor = 'auto'; | ||||
|     this.timer = window.setTimeout(this.hideUI, 2000); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * handle end of touch event | ||||
|    * creates slide left or right if swipe was long enough | ||||
|    * @param ev browser touch event | ||||
|    */ | ||||
|   private handleTouchEnd = (ev: TouchEvent) => { | ||||
|     const touchEndX = ev.changedTouches[0].screenX; | ||||
|     if (Math.abs(this.touchStartX - touchEndX) > 100) { | ||||
|       let slideNum; | ||||
|       if (this.touchStartX < touchEndX) { | ||||
|         slideNum = Math.max(this.currentPage - 1, 0); | ||||
|       } else { | ||||
|         slideNum = Math.min(this.currentPage + 1, this.numPages - 1); | ||||
|       } | ||||
|       this.changeSlide(slideNum); | ||||
|     } else { | ||||
|       this.handleMouseMove(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * handle start of touch | ||||
|    * saves position to detect swipes | ||||
|    */ | ||||
|   private handleTouchStart = (ev: TouchEvent) => { | ||||
|     this.touchStartX = ev.changedTouches[0].screenX; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * hide ui | ||||
|    * called by timer function | ||||
|    */ | ||||
|   private hideUI = () => { | ||||
|     this.ui.classList.remove('visible'); | ||||
|     document.body.style.cursor = 'none'; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * move viewpoint to area defined by current page | ||||
|    */ | ||||
|   private moveViewpoint = () => { | ||||
|     const view = (<RTPage>this.tree.getElement(this.currentPage)).getView(); | ||||
|     let transform = ''; | ||||
|     if (view.viewRotation.x) { | ||||
|       transform += ' rotateX(' + (-view.viewRotation.x) + 'deg) ' + transform; | ||||
|     } | ||||
|     if (view.viewRotation.y) { | ||||
|       transform += ' rotateY(' + (-view.viewRotation.y) + 'deg) ' + transform; | ||||
|     } | ||||
|     if (view.viewRotation.z) { | ||||
|       transform += ' rotateZ(' + (-view.viewRotation.z) + 'deg) ' + transform; | ||||
|     } | ||||
|     transform += ' translate3d(' + (-view.position.x) + 'px,' + (-view.position.y) + 'px, ' + (-view.position.z) + 'px)'; | ||||
| 
 | ||||
|     // calculate zoom
 | ||||
|     const wc = parseInt(this.getDefinition('width')) / view.size.w; | ||||
|     const hc = parseInt(this.getDefinition('height')) / view.size.h; | ||||
|     const scale = Math.min(wc, hc); | ||||
|     const zoom = this.viewportElement.parentElement.clientHeight / parseFloat(this.getDefinition('height')) * scale; | ||||
|     if (zoom != 1) { | ||||
|       transform = 'scale(' + zoom + ')' + transform; | ||||
|     } | ||||
|     this.viewportElement.style.transform = transform; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * pop defintion list to remove last definition from stack | ||||
|    * @internal | ||||
|    */ | ||||
|   pop() { | ||||
|     this.definitions.pop(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * add handles for presentation and start it | ||||
|    */ | ||||
|   present() { | ||||
|     window.addEventListener('resize', this.moveViewpoint); | ||||
|     const list = document.querySelectorAll('body, [data-action]'); | ||||
|     list.forEach((e) => { | ||||
|       e.addEventListener('click', this.handleClick); | ||||
|     }); | ||||
|     window.addEventListener('keydown', this.handleKey); | ||||
|     this.select.addEventListener('change', this.handleDropdown); | ||||
|     window.addEventListener('mousemove', this.handleMouseMove); | ||||
|     document.body.addEventListener('touchstart', this.handleTouchStart); | ||||
|     document.body.addEventListener('touchend', this.handleTouchEnd); | ||||
|     this.moveViewpoint(); | ||||
|     this.changeSlide(this.currentPage); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * push a new empty definition list to stack | ||||
|    * @internal | ||||
|    */ | ||||
|   push(): void { | ||||
|     this.definitions.push(new Map()); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * set a value to current definition list on stack | ||||
|    * @internal | ||||
|    */ | ||||
|   set(key: string, value: string): void { | ||||
|     const definition = this.definitions.at(-1); | ||||
|     definition.set(key, value); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										178
									
								
								src/rendertree/rendertree.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/rendertree/rendertree.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,178 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  **/ | ||||
| 
 | ||||
| import { PresentationMaker } from '../presentationmaker'; | ||||
| import { RTModule } from './rtmodule'; | ||||
| import { RTNode } from './rtnode'; | ||||
| import { RTImg } from './rtimg'; | ||||
| import { RTCalc } from './rtcalc'; | ||||
| import { RTText } from './rttext'; | ||||
| import { RTOptions } from './rtoptions'; | ||||
| import { RTPage } from './rtpage'; | ||||
| 
 | ||||
| /** | ||||
|  * the root of render tree | ||||
|  * @internal | ||||
|  */ | ||||
| export class RenderTree { | ||||
|   /** handle to main instance */ | ||||
|   private main: PresentationMaker; | ||||
|   /** our child elements */ | ||||
|   private elements: RTNode[]; | ||||
|   /** definitions from input */ | ||||
|   private definitions: Map<string, string>; | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param pm handle to main instance | ||||
|    * @param other optional other tree to copy data from | ||||
|    */ | ||||
|   constructor(pm: PresentationMaker, other: RenderTree = null) { | ||||
|     this.main = pm; | ||||
|     this.elements = []; | ||||
|     this.definitions = new Map<string, string>(); | ||||
|     if (other !== null) { | ||||
|       other.elements.forEach((e) => { | ||||
|         this.elements.push(e.clone()); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create elements from given parent | ||||
|    * @param baseElem root element to create new render tree nodes | ||||
|    */ | ||||
|   createFromElem(baseElem: HTMLElement) { | ||||
|     const nodes = baseElem.childNodes; | ||||
|     nodes.forEach((node) => { | ||||
|       if (node.nodeType === 1) { | ||||
|         const newNode = this.createNodeFromElem(<HTMLElement>node); | ||||
|         if (newNode !== null) { | ||||
|           this.elements.push(newNode); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * create a new node from given element | ||||
|    *  | ||||
|    * currently supports 'calc', 'img', 'options', 'page', 'text' | ||||
|    * @param elem to create from | ||||
|    */ | ||||
|   createNodeFromElem(elem: HTMLElement): RTNode { | ||||
|     const name = elem.localName; | ||||
|     // final types
 | ||||
|     switch (name) { | ||||
|       case 'calc': | ||||
|         return RTCalc.fromElem(this, elem); | ||||
|       case 'img': | ||||
|         return RTImg.fromElem(this, elem); | ||||
|       case 'options': | ||||
|         return RTOptions.fromElem(this.main, this, elem); | ||||
|       case 'page': | ||||
|         return RTPage.fromElem(this.main, this, elem); | ||||
|       case 'text': | ||||
|         return RTText.fromElem(this, elem); | ||||
|     } | ||||
|     // still here, probably a module
 | ||||
|     const tree = this.main.getNewModule(name); | ||||
|     if (tree === null) { | ||||
|       console.log('unknown module', name); | ||||
|       return null; | ||||
|     } | ||||
|     tree.definitions.clear(); | ||||
|     // add attributes to node
 | ||||
|     for (let i = 0; i < elem.attributes.length; ++i) { | ||||
|       const attr = elem.attributes[i]; | ||||
|       tree.definitions.set(attr.localName, attr.textContent); | ||||
|     } | ||||
|     elem.childNodes.forEach((child) => { | ||||
|       if (child.nodeType === 1) { | ||||
|         const childElem = <HTMLElement>child; | ||||
|         tree.definitions.set(childElem.localName, childElem.innerHTML); | ||||
|       } | ||||
|     }); | ||||
|     return new RTModule(this, tree); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * get current definition for given name | ||||
|    * @param name name to look up | ||||
|    * @returns value or '' | ||||
|    */ | ||||
|   getDefinition(name: string): string { | ||||
|     return this.main.getDefinition(name); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * get node with given index | ||||
|    * @param num index | ||||
|    * @return node or null if invalid index | ||||
|    */ | ||||
|   getElement(num: number): RTNode { | ||||
|     if (num >= 0 && num <= this.elements.length) { | ||||
|       return this.elements[num]; | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * return the number of elements in the root tree | ||||
|    */ | ||||
|   getElementCount(): number { | ||||
|     return this.elements.length; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * get main instance | ||||
|    * @returns main instance | ||||
|    */ | ||||
|   getMain(): PresentationMaker { | ||||
|     return this.main; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * pop defintion list to remove last definition from stack | ||||
|    */ | ||||
|   pop() { | ||||
|     this.main.pop(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * push a new empty definition list to stack | ||||
|    */ | ||||
|   push(): void { | ||||
|     this.main.push(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * render tree to given target | ||||
|    * @param target target to render into | ||||
|    */ | ||||
|   render(target: HTMLElement) { | ||||
|     this.main.push(); | ||||
|     // save current definitions on the stack
 | ||||
|     this.definitions.forEach((v, k) => { | ||||
|       this.main.set(k, v); | ||||
|     }); | ||||
|     this.elements.forEach((element) => { | ||||
|       element.render(target); | ||||
|     }); | ||||
|     this.main.pop(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * set definition | ||||
|    * @param key key name | ||||
|    * @param value value data | ||||
|    */ | ||||
|   set(key: string, value: string) { | ||||
|     this.main.set(key, value); | ||||
|   } | ||||
| 
 | ||||
| }; | ||||
							
								
								
									
										67
									
								
								src/rendertree/rtcalc.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/rendertree/rtcalc.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  * @internal | ||||
|  **/ | ||||
| 
 | ||||
| import { RTNode } from './rtnode'; | ||||
| import { RenderTree } from './rendertree'; | ||||
| import Formula from 'fparser'; | ||||
| 
 | ||||
| /** | ||||
|  * calculate new defintions based on formula | ||||
|  */ | ||||
| export class RTCalc extends RTNode { | ||||
|   /** name of the definition */ | ||||
|   private target: string; | ||||
|   /** expression to calculate */ | ||||
|   private expression: string; | ||||
| 
 | ||||
|   /** | ||||
|    * clone function | ||||
|    * @return a copy of us | ||||
|    */ | ||||
|   clone(): RTCalc { | ||||
|     return new RTCalc(this.root, this.target, this.expression); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param root our parent RenderTree | ||||
|    * @param target name of the new definition | ||||
|    * @param expression expression to calculate | ||||
|    */ | ||||
|   constructor(root: RenderTree, target: string, expression: string) { | ||||
|     super(root); | ||||
|     this.target = target; | ||||
|     this.expression = expression; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create RTCalc from given node into given RenderTree | ||||
|    * @param root render tree to insert to | ||||
|    * @param node input node | ||||
|    * @returns new RTCalc node | ||||
|    */ | ||||
|   static fromElem(root: RenderTree, node: HTMLElement): RTCalc { | ||||
|     return new RTCalc( | ||||
|       root, | ||||
|       node.getAttribute('name') || '', | ||||
|       node.innerHTML | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * render our element into target | ||||
|    * @param target target to render into | ||||
|    */ | ||||
|   // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||
|   render(target: HTMLElement): void { | ||||
|     const exp = this.resolveString(this.expression); | ||||
|     const fObj = new Formula(exp); | ||||
|     const result = fObj.evaluate({}); | ||||
|     this.root.set(this.target, result.toString()); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										99
									
								
								src/rendertree/rtimg.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/rendertree/rtimg.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,99 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  * @internal | ||||
|  **/ | ||||
| 
 | ||||
| import { RTNode } from './rtnode'; | ||||
| import { RenderTree } from './rendertree'; | ||||
| 
 | ||||
| /** | ||||
|  * renders an image from <img> tag | ||||
|  */ | ||||
| export class RTImg extends RTNode { | ||||
|   /** src URI */ | ||||
|   private src: string; | ||||
|   /** x position */ | ||||
|   private x: string; | ||||
|   /** y position */ | ||||
|   private y: string; | ||||
|   /** width */ | ||||
|   private width: string; | ||||
|   /** height */ | ||||
|   private height: string; | ||||
|   /** mask-image css string */ | ||||
|   private maskImage: string; | ||||
| 
 | ||||
|   /** | ||||
|    * clone function | ||||
|    * @return a copy of us | ||||
|    */ | ||||
|   clone(): RTImg { | ||||
|     return new RTImg( | ||||
|       this.root, | ||||
|       this.src, | ||||
|       this.x, | ||||
|       this.y, | ||||
|       this.width, | ||||
|       this.height, | ||||
|       this.maskImage | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param root our parent RenderTree | ||||
|    * @param src source URI | ||||
|    * @param x x position | ||||
|    * @param y y position | ||||
|    * @param width image width | ||||
|    * @param height image height | ||||
|    * @param maskImage optional css for mask-image | ||||
|    */ | ||||
|   constructor(root: RenderTree, src: string, x: string, y: string, width: string, height: string, maskImage: string) { | ||||
|     super(root); | ||||
|     this.src = src; | ||||
|     this.x = x; | ||||
|     this.y = y; | ||||
|     this.width = width; | ||||
|     this.height = height; | ||||
|     this.maskImage = maskImage; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create RTImg from given node into given RenderTree | ||||
|    * @param root render tree to insert to | ||||
|    * @param node input node | ||||
|    * @returns new RTImg node | ||||
|    */ | ||||
|   static fromElem(root: RenderTree, node: HTMLElement): RTImg { | ||||
|     return new RTImg( | ||||
|       root, | ||||
|       this.getField(node, 'src'), | ||||
|       this.getField(node, 'x'), | ||||
|       this.getField(node, 'y'), | ||||
|       this.getField(node, 'width'), | ||||
|       this.getField(node, 'height'), | ||||
|       this.getField(node, 'mask-image') | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * render image to HTML target | ||||
|    * @param target target to render to | ||||
|    */ | ||||
|   render(target: HTMLElement): void { | ||||
|     const img = document.createElement('img'); | ||||
|     img.style.position = 'absolute'; | ||||
|     img.style.top = this.calc(this.resolveString(this.y)) + 'px'; | ||||
|     img.style.left = this.calc(this.resolveString(this.x)) + 'px'; | ||||
|     img.setAttribute('width', this.calc(this.resolveString(this.width)).toString()); | ||||
|     img.setAttribute('height', this.calc(this.resolveString(this.height)).toString()); | ||||
|     img.setAttribute('src', this.resolveString(this.src)); | ||||
|     if (this.maskImage) { | ||||
|       img.style.maskImage = this.maskImage; | ||||
|     } | ||||
|     target.append(img); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/rendertree/rtmodule.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/rendertree/rtmodule.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  **/ | ||||
| 
 | ||||
| import { RTNode } from './rtnode'; | ||||
| import { RenderTree } from './rendertree'; | ||||
| 
 | ||||
| /** | ||||
|  * custom user declared module | ||||
|  */ | ||||
| export class RTModule extends RTNode { | ||||
|   /** render tree for our children */ | ||||
|   private tree: RenderTree; | ||||
| 
 | ||||
|   /** | ||||
|    * clone function | ||||
|    * @return a copy of us | ||||
|    */ | ||||
|   clone(): RTModule { | ||||
|     const tree = new RenderTree(this.root.getMain(), this.tree); | ||||
|     return new RTModule(this.root, tree); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param root parent RenderTree | ||||
|    * @param tree child renderTree | ||||
|    */ | ||||
|   constructor(root: RenderTree, tree: RenderTree) { | ||||
|     super(root); | ||||
|     this.tree = tree; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * render module content to given target | ||||
|    * @param target target to render to | ||||
|    */ | ||||
|   render(target: HTMLElement): void { | ||||
|     this.tree.render(target); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										105
									
								
								src/rendertree/rtnode.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/rendertree/rtnode.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,105 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  * @internal | ||||
|  **/ | ||||
| 
 | ||||
| import { RenderTree } from './rendertree'; | ||||
| import Formula from 'fparser'; | ||||
| 
 | ||||
| /** | ||||
|  * base class for all RenderTree nodes | ||||
|  */ | ||||
| export abstract class RTNode { | ||||
|   /** root render tree */ | ||||
|   protected root: RenderTree; | ||||
| 
 | ||||
|   /** | ||||
|    * calculate given expression | ||||
|    * @param exp expression string | ||||
|    * @returns result as number or 0 in case of error | ||||
|    */ | ||||
|   calc(exp: string): number { | ||||
|     if (exp === '') { | ||||
|       return 0; | ||||
|     } | ||||
|     try { | ||||
|       const fObj = new Formula(exp); | ||||
|       return <number>fObj.evaluate({}); | ||||
|     } catch(e) { | ||||
|     } | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * abstract function to clone the node | ||||
|    * must be implemented by every sub class | ||||
|    */ | ||||
|   abstract clone(): RTNode; | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param root parent RenderTree | ||||
|    */ | ||||
|   constructor(root: RenderTree) { | ||||
|     this.root = root; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * helper function to get value from attribute or from named child node | ||||
|    * @param node current HTML element | ||||
|    * @param name name of element to fetch | ||||
|    * @return value or '' in case of error | ||||
|    */ | ||||
|   static getField(node: HTMLElement, name: string): string { | ||||
|     // try attribute
 | ||||
|     let field = node.getAttribute(name); | ||||
|     // try child nodes
 | ||||
|     node.childNodes.forEach((child) => { | ||||
|       if (child.nodeType === 1) { | ||||
|         const childElem = <HTMLElement>child; | ||||
|         if (childElem.localName === name) { | ||||
|           field = childElem.innerHTML; | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|     return field; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * abstract function to render the node | ||||
|    * must be implemented by every sub class | ||||
|    * @param target target to render into | ||||
|    */ | ||||
|   abstract render(target: HTMLElement): void; | ||||
| 
 | ||||
|   /** | ||||
|    * resolve a string using variable replacements | ||||
|    * @param input input string | ||||
|    * @returns input strings with replaced variables | ||||
|    */ | ||||
|   resolveString(input: string): string { | ||||
|     if (!input || input.indexOf('$') < 0) { | ||||
|       return input; | ||||
|     } | ||||
|     let str = input; | ||||
|     let dollar; | ||||
|     let lastDollar = 0; | ||||
|     while ((dollar = str.indexOf('${', lastDollar)) >= 0) { | ||||
|       if (str.at(dollar - 1) == '\\') { | ||||
|         str = str.substring(0, dollar - 1) + str.substring(dollar); | ||||
|         lastDollar = dollar + 1; | ||||
|         continue; | ||||
|       } | ||||
|       const end = str.indexOf('}', dollar); | ||||
|       if (end < 0) break; | ||||
|       const search = str.substring(dollar + 2, end); | ||||
|       const replace = this.root.getDefinition(search); | ||||
|       str = str.replace(str.substring(dollar, end + 1), replace); | ||||
|     } | ||||
|     return (str); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										125
									
								
								src/rendertree/rtoptions.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/rendertree/rtoptions.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,125 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  * @internal | ||||
|  **/ | ||||
| 
 | ||||
| import { PresentationMaker } from '../presentationmaker'; | ||||
| import { RTNode } from './rtnode'; | ||||
| import { RenderTree } from './rendertree'; | ||||
| 
 | ||||
| /** | ||||
|  * transform subtree by given options | ||||
|  */ | ||||
| export class RTOptions extends RTNode { | ||||
|   /** blend mode */ | ||||
|   private blendmode: string; | ||||
|   /** flip axis */ | ||||
|   private flip: string; | ||||
|   /** opactity */ | ||||
|   private opacity: string; | ||||
|   /** rotate */ | ||||
|   private rotate: string; | ||||
|   /** subtee to transform */ | ||||
|   private subtree: RenderTree; | ||||
|   /** y position when flipping */ | ||||
|   private y: string; | ||||
| 
 | ||||
|   /** | ||||
|    * clone function | ||||
|    * @return a copy of us | ||||
|    */ | ||||
|   clone(): RTOptions { | ||||
|     return new RTOptions( | ||||
|       this.root, | ||||
|       this.subtree, | ||||
|       this.opacity, | ||||
|       this.blendmode, | ||||
|       this.flip, | ||||
|       this.rotate, | ||||
|       this.y | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param root parent RenderTree | ||||
|    * @param subtree child sub tree | ||||
|    * @param opacity opacity value | ||||
|    * @param blendmode blend mode | ||||
|    * @param flip flip axis | ||||
|    * @param rotate rotation in degree X, Y, Z | ||||
|    * @param y y position when flipping | ||||
|    */ | ||||
|   constructor(root: RenderTree, subtree: RenderTree, opacity: string, blendmode: string, flip: string, rotate: string, y: string) { | ||||
|     super(root); | ||||
|     this.subtree = subtree; | ||||
|     this.opacity = opacity; | ||||
|     this.blendmode = blendmode; | ||||
|     this.flip = flip; | ||||
|     this.rotate = rotate; | ||||
|     this.y = y; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create RTOptions from given node into given RenderTree | ||||
|    * @param root render tree to insert to | ||||
|    * @param node input node | ||||
|    * @returns new RTOptions node | ||||
|    */ | ||||
|   static fromElem(main: PresentationMaker, root: RenderTree, node: HTMLElement): RTOptions { | ||||
|     const subtree = new RenderTree(main); | ||||
|     subtree.createFromElem(node); | ||||
|     return new RTOptions( | ||||
|       root, | ||||
|       subtree, | ||||
|       this.getField(node, 'opacity') || '', | ||||
|       this.getField(node, 'blend') || '', | ||||
|       this.getField(node, 'flip') || '', | ||||
|       this.getField(node, 'rotate') || '', | ||||
|       this.getField(node, 'y') || '' | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * render our element into target | ||||
|    * @param target target to render into | ||||
|    */ | ||||
|   render(target: HTMLElement): void { | ||||
|     const div = document.createElement('div'); | ||||
|     div.classList.add('option'); | ||||
|     if (this.opacity !== '') { | ||||
|       div.style.opacity = this.opacity; | ||||
|     } | ||||
|     if (this.blendmode !== '') { | ||||
|       div.style.mixBlendMode = this.blendmode; | ||||
|     } | ||||
|     if (this.flip !== '') { | ||||
|       if (this.flip == 'v') { | ||||
|         div.style.transform = 'scaleY(-1)'; | ||||
|       } | ||||
|     } | ||||
|     if (this.y) { | ||||
|       div.style.position = 'absolute'; | ||||
|       div.style.bottom = '0px'; | ||||
|     } | ||||
|     if (this.rotate !== '') { | ||||
|       const r = this.rotate.split(','); | ||||
|       let transform = ''; | ||||
|       if (r[0]) { | ||||
|         transform += 'rotateX(' + (this.calc(this.resolveString(r[0]))) + 'deg)'; | ||||
|       } | ||||
|       if (r[1]) { | ||||
|         transform += 'rotateY(' + (this.calc(this.resolveString(r[1]))) + 'deg)'; | ||||
|       } | ||||
|       if (r[2]) { | ||||
|         transform += 'rotateZ(' + (this.calc(this.resolveString(r[2]))) + 'deg)'; | ||||
|       } | ||||
|       div.style.transform = transform; | ||||
|       div.style.transformOrigin = 'top left'; | ||||
|     } | ||||
|     this.subtree.render(div); | ||||
|     target.append(div); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										257
									
								
								src/rendertree/rtpage.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								src/rendertree/rtpage.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,257 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  * @internal | ||||
|  **/ | ||||
| 
 | ||||
| import { RTNode } from './rtnode'; | ||||
| import { RenderTree } from './rendertree'; | ||||
| import { PresentationMaker } from '../presentationmaker'; | ||||
| 
 | ||||
| /** | ||||
|  * view transformations as strings | ||||
|  */ | ||||
| export interface TransformationS { | ||||
|   /** position on HTML space */ | ||||
|   position: {x: string, y: string, z: string}; | ||||
|   /** rotation in HTML space */ | ||||
|   rotation: {x: string, y: string, z: string}; | ||||
|   /** page size in pixels */ | ||||
|   size: {w: string, h: string}; | ||||
|   /** view position in HTML space */ | ||||
|   viewpos: {x: string, y: string, z: string}; | ||||
|   /** view size in pixels */ | ||||
|   viewSize: {w: string, h: string}; | ||||
|   /** view rotation in degree */ | ||||
|   viewRotation: {x: string, y: string, z: string}; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * view transformation as numbers | ||||
|  */ | ||||
| export interface RTTransformation { | ||||
|   /** view position */ | ||||
|   position: {x: number, y: number, z: number}; | ||||
|   /** view size */ | ||||
|   size: {w: number, h: number}; | ||||
|   /** view rotation in degrees */ | ||||
|   viewRotation: {x: number, y: number, z: number}; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * page node | ||||
|  */ | ||||
| export class RTPage extends RTNode { | ||||
|   /** page id */ | ||||
|   private id: string; | ||||
|   /** page name */ | ||||
|   private name: string; | ||||
|   /** tree to render on page */ | ||||
|   private subtree: RenderTree; | ||||
|   /** tranform informations */ | ||||
|   private transformation: TransformationS; | ||||
| 
 | ||||
|   /** | ||||
|    * clone function | ||||
|    * @return a copy of us | ||||
|    */ | ||||
|   clone(): RTPage { | ||||
|     return new RTPage( | ||||
|       this.root, | ||||
|       this.subtree, | ||||
|       this.id, | ||||
|       this.transformation.size.w, | ||||
|       this.transformation.size.h, | ||||
|       this.transformation.position.x, | ||||
|       this.transformation.position.y, | ||||
|       this.transformation.position.z, | ||||
|       this.transformation.rotation.y, | ||||
|       this.transformation.rotation.y, | ||||
|       this.transformation.rotation.z, | ||||
|       this.transformation.viewpos.x, | ||||
|       this.transformation.viewpos.y, | ||||
|       this.transformation.viewpos.z, | ||||
|       this.transformation.viewSize.w, | ||||
|       this.transformation.viewSize.h, | ||||
|       this.transformation.viewRotation.x, | ||||
|       this.transformation.viewRotation.y, | ||||
|       this.transformation.viewRotation.z, | ||||
|       this.name | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param root parent RenderTree | ||||
|    * @param subtree RenderTree for page content | ||||
|    * @param id page id | ||||
|    * @param width page width | ||||
|    * @param height page height | ||||
|    * @param x x position | ||||
|    * @param y y position | ||||
|    * @param z z position | ||||
|    * @param rx rotation on X-axis | ||||
|    * @param ry rotation on Y-axis | ||||
|    * @param rz rotation on Z-axis | ||||
|    * @param vx view position on X-axis | ||||
|    * @param vy view position on Y-axis | ||||
|    * @param vz view position on Z-axis | ||||
|    * @param vrx view rotation on X-axis | ||||
|    * @param vry view rotation on Y-axis | ||||
|    * @param vrz view rotation on Z-axis | ||||
|    */ | ||||
|   constructor(root: RenderTree, subtree: RenderTree, id: string, width: string, height: string, x: string, y: string, z: string, rx: string, ry: string, rz:string, vx: string, vy: string, vz: string, vw: string, vh: string, vrx: string, vry: string, vrz: string, name: string) { | ||||
|     super(root); | ||||
|     this.subtree = subtree; | ||||
|     this.id = id; | ||||
|     this.transformation = { | ||||
|       size: { w: width, h: height}, | ||||
|       position: {x: x, y: y, z: z}, | ||||
|       rotation: {x: rx, y: ry, z: rz}, | ||||
|       viewpos: {x: vx, y: vy, z: vz}, | ||||
|       viewSize: {w: vw, h: vh}, | ||||
|       viewRotation: {x: vrx, y: vry, z: vrz} | ||||
|     }; | ||||
|     this.name = name; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create RTPage from given node into given RenderTree | ||||
|    * @param root render tree to insert to | ||||
|    * @param node input node | ||||
|    * @returns new RTOptions node | ||||
|    */ | ||||
|   static fromElem(main:PresentationMaker, root: RenderTree, node: HTMLElement): RTPage { | ||||
|     const subtree = new RenderTree(main); | ||||
|     subtree.createFromElem(node); | ||||
|     return new RTPage( | ||||
|       root, | ||||
|       subtree, | ||||
|       node.getAttribute('id') || '', | ||||
|       node.getAttribute('width') || '${width}', | ||||
|       node.getAttribute('height') || '${height}', | ||||
|       node.getAttribute('x') || '0', | ||||
|       node.getAttribute('y') || '0', | ||||
|       node.getAttribute('z') || '0', | ||||
|       node.getAttribute('rx') || '0', | ||||
|       node.getAttribute('ry') || '0', | ||||
|       node.getAttribute('rz') || '0', | ||||
|       node.getAttribute('vx') || '', | ||||
|       node.getAttribute('vy') || '', | ||||
|       node.getAttribute('vz') || '', | ||||
|       node.getAttribute('vwidth') || '', | ||||
|       node.getAttribute('vheight') || '', | ||||
|       node.getAttribute('vrx') || '', | ||||
|       node.getAttribute('vry') || '', | ||||
|       node.getAttribute('vrz') || '', | ||||
|       node.getAttribute('name') || '${page}', | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * get page name | ||||
|    * @returns page name | ||||
|    */ | ||||
|   getName(): string { | ||||
|     return this.name; | ||||
|   } | ||||
|    | ||||
|   /** | ||||
|    * get view transformation | ||||
|    * @return RTTransformation | ||||
|    */ | ||||
|   getView(): RTTransformation { | ||||
|     let position; | ||||
|     if (this.transformation.viewpos.x !== '' || this.transformation.viewpos.y !== '' || this.transformation.viewpos.z !=='') { | ||||
|       position = { | ||||
|         x: this.calc(this.resolveString(this.transformation.viewpos.x)), | ||||
|         y: this.calc(this.resolveString(this.transformation.viewpos.y)), | ||||
|         z: this.calc(this.resolveString(this.transformation.viewpos.z)) | ||||
|       }; | ||||
|     } else { | ||||
|       position = { | ||||
|         x: this.calc(this.resolveString(this.transformation.position.x)), | ||||
|         y: this.calc(this.resolveString(this.transformation.position.y)), | ||||
|         z: this.calc(this.resolveString(this.transformation.position.z)) | ||||
|       } | ||||
|     } | ||||
|     let size; | ||||
|     if (this.transformation.viewSize.w !== '' || this.transformation.viewSize.h !== '') { | ||||
|       size = { | ||||
|         w: this.calc(this.resolveString(this.transformation.viewSize.w)), | ||||
|         h: this.calc(this.resolveString(this.transformation.viewSize.h)) | ||||
|       }; | ||||
|     } else { | ||||
|       size = { | ||||
|         w: this.calc(this.resolveString(this.transformation.size.w)), | ||||
|         h: this.calc(this.resolveString(this.transformation.size.h)) | ||||
|       } | ||||
|     } | ||||
|     let viewRotation; | ||||
|     if (this.transformation.viewRotation.x !== '' || this.transformation.viewRotation.y !== '' || this.transformation.viewRotation.z !== '') { | ||||
|       viewRotation = { | ||||
|         x: this.calc(this.resolveString(this.transformation.viewRotation.x)), | ||||
|         y: this.calc(this.resolveString(this.transformation.viewRotation.y)), | ||||
|         z: this.calc(this.resolveString(this.transformation.viewRotation.z)) | ||||
|       } | ||||
|     } else { | ||||
|       viewRotation = { | ||||
|         x: 0, | ||||
|         y: 0, | ||||
|         z: 0 | ||||
|       } | ||||
|     } | ||||
|     return { | ||||
|       position: position, | ||||
|       size: size, | ||||
|       viewRotation: viewRotation | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * render our element into target | ||||
|    * @param target target to render into | ||||
|    */ | ||||
|   render(target: HTMLElement): void { | ||||
|     this.root.set('page', (parseInt(this.root.getDefinition('page')) + 1).toString()); | ||||
|     const pageDiv = document.createElement('article'); | ||||
|     pageDiv.classList.add('page'); | ||||
|     pageDiv.classList.add('inactive'); | ||||
|     let transform = ''; | ||||
|     const x = this.calc(this.resolveString(this.transformation.position.x)); | ||||
|     const y = this.calc(this.resolveString(this.transformation.position.y)); | ||||
|     const z = this.calc(this.resolveString(this.transformation.position.z)); | ||||
|     if (x || y || z) { | ||||
|       transform += 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)'; | ||||
|     } | ||||
|     const rx = -this.calc(this.resolveString(this.transformation.rotation.x)); | ||||
|     const ry = -this.calc(this.resolveString(this.transformation.rotation.y)); | ||||
|     const rz = -this.calc(this.resolveString(this.transformation.rotation.z)); | ||||
|     if (rx) { | ||||
|       transform += 'rotateX(' + rx + 'deg)'; | ||||
|     } | ||||
|     if (ry) { | ||||
|       transform += 'rotateY(' + ry + 'deg)'; | ||||
|     } | ||||
|     if (rz) { | ||||
|       transform += 'rotateZ(' + rz + 'deg)'; | ||||
|     } | ||||
|     if (transform !== '') { | ||||
|       pageDiv.style.transform = transform; | ||||
|     } | ||||
|     const width = this.calc(this.resolveString(this.transformation.size.w)).toString(); | ||||
|     const height = this.calc(this.resolveString(this.transformation.size.h)).toString(); | ||||
|     pageDiv.style.width = width + 'px'; | ||||
|     pageDiv.style.height = height + 'px'; | ||||
|     if (this.id) { | ||||
|       pageDiv.id = this.id; | ||||
|     } | ||||
|     target.append(pageDiv); | ||||
|     this.root.push() | ||||
|     this.subtree.set('width', width); | ||||
|     this.subtree.set('height', height); | ||||
|     this.subtree.render(pageDiv); | ||||
|     this.root.pop() | ||||
|   } | ||||
| } | ||||
							
								
								
									
										179
									
								
								src/rendertree/rttext.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								src/rendertree/rttext.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,179 @@ | |||
| /** | ||||
|  * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  * @author Author: Sascha Nitsch (grumpydeveloper) | ||||
|  * @internal | ||||
|  **/ | ||||
| 
 | ||||
| import { RTNode } from './rtnode'; | ||||
| import { RenderTree } from './rendertree'; | ||||
| 
 | ||||
| /** | ||||
|  * Text node | ||||
|  */ | ||||
| export class RTText extends RTNode { | ||||
|   /** left position of text box */ | ||||
|   private x0: string; | ||||
|   /** top position of text box */ | ||||
|   private y0: string; | ||||
|   /** rigth position of text box */ | ||||
|   private x1: string; | ||||
|   /** left bottom of text box */ | ||||
|   private y1: string; | ||||
|   /** width of text box */ | ||||
|   private width: string; | ||||
|   /** height of text box */ | ||||
|   private height: string; | ||||
|   /** compact list of [left, top, right, bottom] */ | ||||
|   private pos: string; | ||||
|   /** horizontal alignment of text in box */ | ||||
|   private halign: string; | ||||
|   /** vertical alignment of text in box */ | ||||
|   private valign: string; | ||||
|   /** font size */ | ||||
|   private fontSize: string; | ||||
|   /** actual text */ | ||||
|   private text: string; | ||||
|   /** text color */ | ||||
|   private color: string; | ||||
| 
 | ||||
|   /** | ||||
|    * clone function | ||||
|    * @return a copy of us | ||||
|    */ | ||||
|   clone(): RTText { | ||||
|     return new RTText( | ||||
|       this.root, | ||||
|       this.x0, | ||||
|       this.y0, | ||||
|       this.x1, | ||||
|       this.y1, | ||||
|       this.width, | ||||
|       this.height, | ||||
|       this.pos, | ||||
|       this.halign, | ||||
|       this.valign, | ||||
|       this.fontSize, | ||||
|       this.text, | ||||
|       this.color | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * create Node from HTMLElement | ||||
|    * @internal | ||||
|    * */ | ||||
|   static fromElem(root: RenderTree, node: HTMLElement): RTText { | ||||
|     return new RTText( | ||||
|       root, | ||||
|       node.getAttribute('x0'), | ||||
|       node.getAttribute('y0'), | ||||
|       node.getAttribute('x1'), | ||||
|       node.getAttribute('y1'), | ||||
|       node.getAttribute('w'), | ||||
|       node.getAttribute('h'), | ||||
|       node.getAttribute('pos'), | ||||
|       node.getAttribute('halign') || 'center', | ||||
|       node.getAttribute('valign'), | ||||
|       node.getAttribute('size'), | ||||
|       node.innerHTML, | ||||
|       node.getAttribute('color') || root.getDefinition('defaultfontcolor') | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * constructor | ||||
|    * @param root parent RenderTree | ||||
|    * @param x0 left position of text box | ||||
|    * @param y0 top position of text box | ||||
|    * @param width width of text box | ||||
|    * @param height heightof text box | ||||
|    * @param pos short version of [left, top, right, bottom] | ||||
|    * @param halign horizontal alignment in text box | ||||
|    * @param valign vertical alignment in text box | ||||
|    * @param fontSize font size | ||||
|    * @param text actural text | ||||
|    * @param color text color | ||||
|    */ | ||||
|   constructor(root: RenderTree, x0: string, y0: string, x1: string, y1: string, width: string, height: string, pos: string, halign: string, valign: string, fontSize: string, text: string, color: string) { | ||||
|     super(root); | ||||
|     this.x0 = x0; | ||||
|     this.y0 = y0; | ||||
|     this.x1 = x1; | ||||
|     this.y1 = y1; | ||||
|     this.width = width; | ||||
|     this.height = height; | ||||
|     this.pos = pos; | ||||
|     this.halign = halign; | ||||
|     this.valign = valign; | ||||
|     this.fontSize = fontSize; | ||||
|     this.text = text; | ||||
|     this.color = color; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * render image to HTML target | ||||
|    * @param target target to render to | ||||
|    */ | ||||
|   render(target: HTMLElement): void { | ||||
|     let x0: number; | ||||
|     let y0: number; | ||||
|     let x1: number; | ||||
|     let y1: number; | ||||
|     if (this.pos) { | ||||
|       const posLookup = this.resolveString(this.pos); | ||||
|       const tokens = posLookup.split(','); | ||||
|       if (tokens.length != 4) { | ||||
|         return; | ||||
|       } | ||||
|       x0 = this.calc(this.resolveString(tokens[0])); | ||||
|       y0 = this.calc(this.resolveString(tokens[1])); | ||||
|       x1 = this.calc(this.resolveString(tokens[2])); | ||||
|       y1 = this.calc(this.resolveString(tokens[3])); | ||||
|     } else { | ||||
|       x0 = this.calc(this.resolveString(this.x0)); | ||||
|       y0 = this.calc(this.resolveString(this.y0)); | ||||
|       if (this.x1) { | ||||
|         x1 = this.calc(this.resolveString(this.x1)); | ||||
|         y1 = this.calc(this.resolveString(this.y1)); | ||||
|       } else { | ||||
|         x1 = x0 + this.calc(this.resolveString(this.width)); | ||||
|         y1 = y0 + this.calc(this.resolveString(this.height)); | ||||
|       } | ||||
|     } | ||||
|     const halign = this.resolveString(this.halign); | ||||
|     const valign = this.resolveString(this.valign); | ||||
|     const text = this.resolveString(this.text); | ||||
|     const div = document.createElement('div'); | ||||
|     if (this.color) { | ||||
|       div.style.color = this.resolveString(this.color); | ||||
|     } | ||||
|     div.style.position = 'absolute'; | ||||
|     if (this.fontSize) { | ||||
|       div.style.fontSize = this.calc(this.resolveString(this.fontSize)) + 'px'; | ||||
|     } | ||||
|     div.style.left = x0 + 'px'; | ||||
|     div.style.top = y0 + 'px'; | ||||
|     div.style.width = (x1 - x0) + 'px'; | ||||
|     div.style.height = (y1 - y0) + 'px'; | ||||
|     div.style.overflow = 'clip'; | ||||
|     switch (halign) { | ||||
|       case 'center': | ||||
|         div.style.textAlign = 'center'; | ||||
|         break; | ||||
|       case 'right': | ||||
|         div.style.textAlign = 'right'; | ||||
|         break; | ||||
|     } | ||||
|     switch (valign) { | ||||
|       case 'center': | ||||
|         div.style.alignContent = 'center'; | ||||
|         break; | ||||
|       case 'bottom': | ||||
|         div.style.alignContent = 'end'; | ||||
|         break; | ||||
|     } | ||||
|     div.insertAdjacentHTML('afterbegin', text); | ||||
|     target.append(div); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										21
									
								
								tsconfig.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tsconfig.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| { | ||||
|   "compilerOptions": { | ||||
|     "outDir": "./dist/", | ||||
|     "noImplicitAny": true, | ||||
|     "module": "ES6", | ||||
|     "target": "ES6", | ||||
|     "allowJs": true, | ||||
|     "moduleResolution": "Bundler", | ||||
|   }, | ||||
|   "typedocOptions": { | ||||
|     "entryPoints": ["./src", "./src/rendertree"], | ||||
|     "entryPointStrategy": "expand", | ||||
|     "out": "docs", | ||||
|     "excludePrivate": false, | ||||
|   }, | ||||
|   "visibilityFilters": { | ||||
|         "protected": true, | ||||
|         "private": true, | ||||
|         "inherited": true, | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								webpack.config.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								webpack.config.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| const path = require('path'); | ||||
| 
 | ||||
| module.exports = { | ||||
|   entry: './src/presentationmaker.ts', | ||||
|   mode: 'production', | ||||
|   module: { | ||||
|     rules: [ | ||||
|       { | ||||
|         test: /\.tsx?$/, | ||||
|         use: 'ts-loader', | ||||
|         exclude: /node_modules/, | ||||
|       }, | ||||
|     ], | ||||
|   }, | ||||
|   resolve: { | ||||
|     extensions: ['.tsx', '.ts', '.js'], | ||||
|   }, | ||||
|   output: { | ||||
|     path: path.resolve(__dirname, 'dist'), | ||||
|     filename: 'presentationmaker.js', | ||||
|     libraryTarget: 'global', | ||||
|   }, | ||||
| }; | ||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Sascha Nitsch
						Sascha Nitsch