├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── doc ├── Makefile ├── colony.css ├── enums.adoc ├── index.adoc ├── index.html ├── load.adoc ├── perlin.adoc ├── powered-by-lua.gif ├── preface.adoc └── write.adoc ├── examples ├── hello.lua ├── sunflowers.jpg └── version.lua ├── moonimage └── README ├── src ├── Makefile ├── _make ├── compat-5.3.c ├── compat-5.3.h ├── include │ ├── stb_image.h │ ├── stb_image_write.h │ └── stb_perlin.h ├── internal.h ├── load.c ├── main.c ├── moonimage.h ├── perlin.c ├── utils.c └── write.c └── thirdparty ├── asciidoctor-styles-license ├── lua-compat-5.3-license ├── powered-by-lua-license └── stb-license /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.so 3 | *.dll 4 | *.o 5 | *.swp 6 | *.symbols 7 | core.* 8 | examples/output*.* 9 | local/ 10 | src/DIFF 11 | src/TODO 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Stefano Trettel 4 | 5 | Software repository: MoonImage, https://github.com/stetre/moonimage 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | 26 | (See also the THIRD-PARTY LICENSES contained in the thirdparty/ directory 27 | of the Software repository.) 28 | 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | default: build 3 | 4 | build install uninstall where: 5 | @cd src; $(MAKE) $@ 6 | 7 | clean : 8 | @cd src; $(MAKE) $@ 9 | @cd doc; $(MAKE) $@ 10 | 11 | docs: 12 | @cd doc; $(MAKE) 13 | 14 | cleanall: clean 15 | 16 | backup: clean 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## MoonImage: Image Loading for Lua 2 | 3 | MoonImage is a Lua image loading library based on Sean Barrett's 4 | [STB libraries](https://github.com/nothings/stb). 5 | 6 | It runs on GNU/Linux and on Windows (MSYS2/MinGW) and requires 7 | [Lua](http://www.lua.org/) (>=5.3). 8 | 9 | _Author:_ _[Stefano Trettel](https://www.linkedin.com/in/stetre)_ 10 | 11 | [![Lua logo](./doc/powered-by-lua.gif)](http://www.lua.org/) 12 | 13 | #### License 14 | 15 | MIT/X11 license (same as Lua). See [LICENSE](./LICENSE). 16 | 17 | #### Documentation 18 | 19 | See the [Reference Manual](https://stetre.github.io/moonimage/doc/index.html). 20 | 21 | #### Getting and installing 22 | 23 | Setup the build environment as described [here](https://github.com/stetre/moonlibs), then: 24 | 25 | ```sh 26 | $ git clone https://github.com/stetre/moonimage 27 | $ cd moonimage 28 | moonimage$ make 29 | moonimage$ sudo make install 30 | ``` 31 | 32 | #### Example 33 | 34 | The example below loads an image from a JPG file and writes it to a BMP file. 35 | 36 | Other examples can be found in the **examples/** directory contained in the release package. 37 | 38 | ```lua 39 | -- MoonImage example: hello.lua 40 | mi = require('moonimage') 41 | 42 | -- Load an image from a jpg file: 43 | data, w, h, channels = mi.load("sunflowers.jpg", 'rgba') 44 | 45 | -- Write it to a bmp file: 46 | mi.write_bmp("output.bmp", w, h, channels, data) 47 | ``` 48 | 49 | The script can be executed at the shell prompt with the standard Lua interpreter: 50 | 51 | ```shell 52 | $ lua hello.lua 53 | ``` 54 | 55 | #### See also 56 | 57 | * [MoonLibs - Graphics and Audio Lua Libraries](https://github.com/stetre/moonlibs). 58 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | TgtAdoc := index 2 | TgtPdf := MoonImage-RefMan 3 | 4 | Stylesdir = ./ 5 | Stylesheet = colony.css 6 | Style = -a stylesheet=$(Stylesheet) -a stylesdir=$(Stylesdir) 7 | Style = 8 | 9 | ifdef TgtAdoc 10 | # one file only 11 | Src = $(TgtAdoc).adoc 12 | else 13 | # all .adoc files 14 | Src := $(wildcard *.adoc) 15 | endif 16 | 17 | Xml := $(Src:.adoc=.xml) 18 | Html := $(Src:.adoc=.html) 19 | Pdf := $(Src:.adoc=.pdf) 20 | 21 | default: html 22 | 23 | check: 24 | 25 | clean: 26 | @-rm -f *~ 27 | @-rm -f *.pdf 28 | @-rm -f *.pdfmarks 29 | @-rm -f *.xml 30 | @-rm -f *.html 31 | @-rm -f *.epub 32 | @-rm -f *.fo 33 | @-rm -f *.log 34 | 35 | install: 36 | 37 | html: clean 38 | @asciidoctor $(Style) $(Src) 39 | 40 | preview: html 41 | @google-chrome $(Html) 42 | 43 | ifdef TgtAdoc 44 | # one file only 45 | pdf: clean 46 | @asciidoctor-pdf $(TgtAdoc).adoc -o $(TgtPdf).pdf 47 | else 48 | # all .adoc files 49 | pdf: clean 50 | @asciidoctor-pdf -a pdf-style=asciidoctor $(TgtAdoc).adoc 51 | endif 52 | 53 | docs: html pdf 54 | -------------------------------------------------------------------------------- /doc/colony.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.1.2 | MIT License | git.io/normalize */ 2 | /* ========================================================================== HTML5 display definitions ========================================================================== */ 3 | /** Correct `block` display not defined in IE 8/9. */ 4 | article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; } 5 | 6 | /** Correct `inline-block` display not defined in IE 8/9. */ 7 | audio, canvas, video { display: inline-block; } 8 | 9 | /** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */ 10 | audio:not([controls]) { display: none; height: 0; } 11 | 12 | /** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */ 13 | [hidden], template { display: none; } 14 | 15 | script { display: none !important; } 16 | 17 | /* ========================================================================== Base ========================================================================== */ 18 | /** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */ 19 | html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ } 20 | 21 | /** Remove default margin. */ 22 | body { margin: 0; } 23 | 24 | /* ========================================================================== Links ========================================================================== */ 25 | /** Remove the gray background color from active links in IE 10. */ 26 | a { background: transparent; } 27 | 28 | /** Address `outline` inconsistency between Chrome and other browsers. */ 29 | a:focus { outline: thin dotted; } 30 | 31 | /** Improve readability when focused and also mouse hovered in all browsers. */ 32 | a:active, a:hover { outline: 0; } 33 | 34 | /* ========================================================================== Typography ========================================================================== */ 35 | /** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */ 36 | h1 { font-size: 2em; margin: 0.67em 0; } 37 | 38 | /** Address styling not present in IE 8/9, Safari 5, and Chrome. */ 39 | abbr[title] { border-bottom: 1px dotted; } 40 | 41 | /** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ 42 | b, strong { font-weight: bold; } 43 | 44 | /** Address styling not present in Safari 5 and Chrome. */ 45 | dfn { font-style: italic; } 46 | 47 | /** Address differences between Firefox and other browsers. */ 48 | hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } 49 | 50 | /** Address styling not present in IE 8/9. */ 51 | mark { background: #ff0; color: #000; } 52 | 53 | /** Correct font family set oddly in Safari 5 and Chrome. */ 54 | code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; } 55 | 56 | /** Improve readability of pre-formatted text in all browsers. */ 57 | pre { white-space: pre-wrap; } 58 | 59 | /** Set consistent quote types. */ 60 | q { quotes: "\201C" "\201D" "\2018" "\2019"; } 61 | 62 | /** Address inconsistent and variable font size in all browsers. */ 63 | small { font-size: 80%; } 64 | 65 | /** Prevent `sub` and `sup` affecting `line-height` in all browsers. */ 66 | sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } 67 | 68 | sup { top: -0.5em; } 69 | 70 | sub { bottom: -0.25em; } 71 | 72 | /* ========================================================================== Embedded content ========================================================================== */ 73 | /** Remove border when inside `a` element in IE 8/9. */ 74 | img { border: 0; } 75 | 76 | /** Correct overflow displayed oddly in IE 9. */ 77 | svg:not(:root) { overflow: hidden; } 78 | 79 | /* ========================================================================== Figures ========================================================================== */ 80 | /** Address margin not present in IE 8/9 and Safari 5. */ 81 | figure { margin: 0; } 82 | 83 | /* ========================================================================== Forms ========================================================================== */ 84 | /** Define consistent border, margin, and padding. */ 85 | fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } 86 | 87 | /** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */ 88 | legend { border: 0; /* 1 */ padding: 0; /* 2 */ } 89 | 90 | /** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */ 91 | button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ } 92 | 93 | /** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */ 94 | button, input { line-height: normal; } 95 | 96 | /** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */ 97 | button, select { text-transform: none; } 98 | 99 | /** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */ 100 | button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } 101 | 102 | /** Re-set default cursor for disabled elements. */ 103 | button[disabled], html input[disabled] { cursor: default; } 104 | 105 | /** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */ 106 | input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } 107 | 108 | /** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */ 109 | input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } 110 | 111 | /** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */ 112 | input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } 113 | 114 | /** Remove inner padding and border in Firefox 4+. */ 115 | button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } 116 | 117 | /** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */ 118 | textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ } 119 | 120 | /* ========================================================================== Tables ========================================================================== */ 121 | /** Remove most spacing between table cells. */ 122 | table { border-collapse: collapse; border-spacing: 0; } 123 | 124 | meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; } 125 | 126 | meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; } 127 | 128 | meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; } 129 | 130 | *, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } 131 | 132 | html, body { font-size: 100%; } 133 | 134 | body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; } 135 | 136 | a:hover { cursor: pointer; } 137 | 138 | img, object, embed { max-width: 100%; height: auto; } 139 | 140 | object, embed { height: 100%; } 141 | 142 | img { -ms-interpolation-mode: bicubic; } 143 | 144 | #map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; } 145 | 146 | .left { float: left !important; } 147 | 148 | .right { float: right !important; } 149 | 150 | .text-left { text-align: left !important; } 151 | 152 | .text-right { text-align: right !important; } 153 | 154 | .text-center { text-align: center !important; } 155 | 156 | .text-justify { text-align: justify !important; } 157 | 158 | .hide { display: none; } 159 | 160 | .antialiased, body { -webkit-font-smoothing: antialiased; } 161 | 162 | img { display: inline-block; vertical-align: middle; } 163 | 164 | textarea { height: auto; min-height: 50px; } 165 | 166 | select { width: 100%; } 167 | 168 | p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; } 169 | 170 | .subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: #003b6b; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; } 171 | 172 | /* Typography resets */ 173 | div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; } 174 | 175 | /* Default Link Styles */ 176 | a { color: #00579e; text-decoration: none; line-height: inherit; } 177 | a:hover, a:focus { color: #333333; } 178 | a img { border: none; } 179 | 180 | /* Default paragraph styles */ 181 | p { font-family: Arial, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; } 182 | p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; } 183 | 184 | /* Default header styles */ 185 | h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Arial, sans-serif; font-weight: normal; font-style: normal; color: #7b2d00; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; } 186 | h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #ff6b15; line-height: 0; } 187 | 188 | h1 { font-size: 2.125em; } 189 | 190 | h2 { font-size: 1.6875em; } 191 | 192 | h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; } 193 | 194 | h4 { font-size: 1.125em; } 195 | 196 | h5 { font-size: 1.125em; } 197 | 198 | h6 { font-size: 1em; } 199 | 200 | hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; } 201 | 202 | /* Helpful Typography Defaults */ 203 | em, i { font-style: italic; line-height: inherit; } 204 | 205 | strong, b { font-weight: bold; line-height: inherit; } 206 | 207 | small { font-size: 60%; line-height: inherit; } 208 | 209 | code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: bold; color: #003426; } 210 | 211 | /* Lists */ 212 | ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Arial, sans-serif; } 213 | 214 | ul, ol { margin-left: 1.5em; } 215 | ul.no-bullet, ol.no-bullet { margin-left: 1.5em; } 216 | 217 | /* Unordered Lists */ 218 | ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ } 219 | ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; } 220 | ul.square { list-style-type: square; } 221 | ul.circle { list-style-type: circle; } 222 | ul.disc { list-style-type: disc; } 223 | ul.no-bullet { list-style: none; } 224 | 225 | /* Ordered Lists */ 226 | ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; } 227 | 228 | /* Definition Lists */ 229 | dl dt { margin-bottom: 0.3em; font-weight: bold; } 230 | dl dd { margin-bottom: 0.75em; } 231 | 232 | /* Abbreviations */ 233 | abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; } 234 | 235 | abbr { text-transform: none; } 236 | 237 | /* Blockquotes */ 238 | blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; } 239 | blockquote cite { display: block; font-size: 0.8125em; color: #e15200; } 240 | blockquote cite:before { content: "\2014 \0020"; } 241 | blockquote cite a, blockquote cite a:visited { color: #e15200; } 242 | 243 | blockquote, blockquote p { line-height: 1.6; color: #333333; } 244 | 245 | /* Microformats */ 246 | .vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; } 247 | .vcard li { margin: 0; display: block; } 248 | .vcard .fn { font-weight: bold; font-size: 0.9375em; } 249 | 250 | .vevent .summary { font-weight: bold; } 251 | .vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; } 252 | 253 | @media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; } 254 | h1 { font-size: 2.75em; } 255 | h2 { font-size: 2.3125em; } 256 | h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; } 257 | h4 { font-size: 1.4375em; } } 258 | /* Tables */ 259 | table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; } 260 | table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; } 261 | table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; } 262 | table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; } 263 | table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; } 264 | table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; } 265 | 266 | h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; } 267 | 268 | a:hover, a:focus { text-decoration: underline; } 269 | 270 | .clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; } 271 | .clearfix:after, .float-group:after { clear: both; } 272 | 273 | *:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 3px 2px 1px 2px; background-color: #eeeeee; border: 1px solid #dddddd; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; } 274 | 275 | pre, pre > code { line-height: 1.6; color: black; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; } 276 | 277 | .keyseq { color: #333333; } 278 | 279 | kbd { display: inline-block; color: black; font-size: 0.75em; line-height: 1.4; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; } 280 | 281 | .keyseq kbd:first-child { margin-left: 0; } 282 | 283 | .keyseq kbd:last-child { margin-right: 0; } 284 | 285 | .menuseq, .menu { color: black; } 286 | 287 | b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; } 288 | 289 | b.button:before { content: "["; padding: 0 3px 0 2px; } 290 | 291 | b.button:after { content: "]"; padding: 0 2px 0 3px; } 292 | 293 | #header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; } 294 | #header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; } 295 | #header:after, #content:after, #footnotes:after, #footer:after { clear: both; } 296 | 297 | #content { margin-top: 1.25em; } 298 | 299 | #content:before { content: none; } 300 | 301 | #header > h1:first-child { color: #7b2d00; margin-top: 2.25rem; margin-bottom: 0; } 302 | #header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; } 303 | #header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; } 304 | #header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #e15200; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; } 305 | #header .details span:first-child { margin-left: -0.125em; } 306 | #header .details span.email a { color: #333333; } 307 | #header .details br { display: none; } 308 | #header .details br + span:before { content: "\00a0\2013\00a0"; } 309 | #header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; } 310 | #header .details br + span#revremark:before { content: "\00a0|\00a0"; } 311 | #header #revnumber { text-transform: capitalize; } 312 | #header #revnumber:after { content: "\00a0"; } 313 | 314 | #content > h1:first-child:not([class]) { color: #7b2d00; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; } 315 | 316 | #toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; } 317 | #toc > ul { margin-left: 0.125em; } 318 | #toc ul.sectlevel0 > li > a { font-style: italic; } 319 | #toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; } 320 | #toc ul { font-family: Arial, sans-serif; list-style-type: none; } 321 | #toc a { text-decoration: none; } 322 | #toc a:active { text-decoration: underline; } 323 | 324 | #toctitle { color: #003b6b; font-size: 1.2em; } 325 | 326 | @media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; } 327 | body.toc2 { padding-left: 15em; padding-right: 0; } 328 | #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; } 329 | #toc.toc2 #toctitle { margin-top: 0; font-size: 1.2em; } 330 | #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; } 331 | #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; } 332 | #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; } 333 | body.toc2.toc-right { padding-left: 0; padding-right: 15em; } 334 | body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } } 335 | @media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; } 336 | #toc.toc2 { width: 20em; } 337 | #toc.toc2 #toctitle { font-size: 1.375em; } 338 | #toc.toc2 > ul { font-size: 0.95em; } 339 | #toc.toc2 ul ul { padding-left: 1.25em; } 340 | body.toc2.toc-right { padding-left: 0; padding-right: 20em; } } 341 | #content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } 342 | #content #toc > :first-child { margin-top: 0; } 343 | #content #toc > :last-child { margin-bottom: 0; } 344 | 345 | #footer { max-width: 100%; background-color: none; padding: 1.25em; } 346 | 347 | #footer-text { color: black; line-height: 1.44; } 348 | 349 | .sect1 { padding-bottom: 0.625em; } 350 | 351 | @media only screen and (min-width: 768px) { .sect1 { padding-bottom: 1.25em; } } 352 | .sect1 + .sect1 { border-top: 0 solid #dddddd; } 353 | 354 | #content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; } 355 | #content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; } 356 | #content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; } 357 | #content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: #7b2d00; text-decoration: none; } 358 | #content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: #622400; } 359 | 360 | .audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; } 361 | 362 | .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; } 363 | 364 | table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; } 365 | 366 | .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: #7b2d00; } 367 | 368 | table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; } 369 | 370 | .admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; } 371 | .admonitionblock > table td.icon { text-align: center; width: 80px; } 372 | .admonitionblock > table td.icon img { max-width: none; } 373 | .admonitionblock > table td.icon .title { font-weight: bold; font-family: Arial, sans-serif; text-transform: uppercase; } 374 | .admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #e15200; } 375 | .admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; } 376 | 377 | .exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } 378 | .exampleblock > .content > :first-child { margin-top: 0; } 379 | .exampleblock > .content > :last-child { margin-bottom: 0; } 380 | 381 | .sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } 382 | .sidebarblock > :first-child { margin-top: 0; } 383 | .sidebarblock > :last-child { margin-bottom: 0; } 384 | .sidebarblock > .content > .title { color: #003b6b; margin-top: 0; } 385 | 386 | .exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; } 387 | 388 | .literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; } 389 | .sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; } 390 | 391 | .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px dashed #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; } 392 | .literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; } 393 | @media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } } 394 | @media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } } 395 | 396 | .literalblock.output pre { color: #eeeeee; background-color: black; } 397 | 398 | .listingblock pre.highlightjs { padding: 0; } 399 | .listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; } 400 | 401 | .listingblock > .content { position: relative; } 402 | 403 | .listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; } 404 | 405 | .listingblock:hover code[data-lang]:before { display: block; } 406 | 407 | .listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; } 408 | 409 | .listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; } 410 | 411 | table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; } 412 | 413 | table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; } 414 | 415 | table.pyhltable td.code { padding-left: .75em; padding-right: 0; } 416 | 417 | pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; } 418 | 419 | pre.pygments .lineno { display: inline-block; margin-right: .25em; } 420 | 421 | table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; } 422 | 423 | .quoteblock { margin: 0 1em 0.75em 1.5em; display: table; } 424 | .quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; } 425 | .quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; } 426 | .quoteblock blockquote { margin: 0; padding: 0; border: 0; } 427 | .quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: #003b6b; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } 428 | .quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; } 429 | .quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; } 430 | .quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #e15200; } 431 | .quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; } 432 | .quoteblock .quoteblock blockquote:before { display: none; } 433 | 434 | .verseblock { margin: 0 1em 0.75em 1em; } 435 | .verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; } 436 | .verseblock pre strong { font-weight: 400; } 437 | .verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; } 438 | 439 | .quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; } 440 | .quoteblock .attribution br, .verseblock .attribution br { display: none; } 441 | .quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.05em; color: #e15200; } 442 | 443 | .quoteblock.abstract { margin: 0 0 0.75em 0; display: block; } 444 | .quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; } 445 | .quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; } 446 | 447 | table.tableblock { max-width: 100%; border-collapse: separate; } 448 | table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; } 449 | 450 | table.spread { width: 100%; } 451 | 452 | table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; } 453 | 454 | table.grid-all th.tableblock, table.grid-all td.tableblock { border-width: 0 1px 1px 0; } 455 | 456 | table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { border-width: 1px 1px 0 0; } 457 | 458 | table.grid-cols th.tableblock, table.grid-cols td.tableblock { border-width: 0 1px 0 0; } 459 | 460 | table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { border-right-width: 0; } 461 | 462 | table.grid-rows th.tableblock, table.grid-rows td.tableblock { border-width: 0 0 1px 0; } 463 | 464 | table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { border-bottom-width: 0; } 465 | 466 | table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { border-width: 1px 0 0 0; } 467 | 468 | table.frame-all { border-width: 1px; } 469 | 470 | table.frame-sides { border-width: 0 1px; } 471 | 472 | table.frame-topbot { border-width: 1px 0; } 473 | 474 | th.halign-left, td.halign-left { text-align: left; } 475 | 476 | th.halign-right, td.halign-right { text-align: right; } 477 | 478 | th.halign-center, td.halign-center { text-align: center; } 479 | 480 | th.valign-top, td.valign-top { vertical-align: top; } 481 | 482 | th.valign-bottom, td.valign-bottom { vertical-align: bottom; } 483 | 484 | th.valign-middle, td.valign-middle { vertical-align: middle; } 485 | 486 | table thead th, table tfoot th { font-weight: bold; } 487 | 488 | tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); } 489 | 490 | tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; } 491 | 492 | p.tableblock > code:only-child { background: none; padding: 0; } 493 | 494 | p.tableblock { font-size: 1em; } 495 | 496 | td > div.verse { white-space: pre; } 497 | 498 | ol { margin-left: 1.75em; } 499 | 500 | ul li ol { margin-left: 1.5em; } 501 | 502 | dl dd { margin-left: 1.125em; } 503 | 504 | dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; } 505 | 506 | ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; } 507 | 508 | ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; } 509 | 510 | ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; } 511 | 512 | ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1em; font-size: 0.85em; } 513 | 514 | ul.checklist li > p:first-child > input[type="checkbox"]:first-child { width: 1em; position: relative; top: 1px; } 515 | 516 | ul.inline { margin: 0 auto 0.375em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; } 517 | ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; } 518 | ul.inline > li > * { display: block; } 519 | 520 | .unstyled dl dt { font-weight: normal; font-style: normal; } 521 | 522 | ol.arabic { list-style-type: decimal; } 523 | 524 | ol.decimal { list-style-type: decimal-leading-zero; } 525 | 526 | ol.loweralpha { list-style-type: lower-alpha; } 527 | 528 | ol.upperalpha { list-style-type: upper-alpha; } 529 | 530 | ol.lowerroman { list-style-type: lower-roman; } 531 | 532 | ol.upperroman { list-style-type: upper-roman; } 533 | 534 | ol.lowergreek { list-style-type: lower-greek; } 535 | 536 | .hdlist > table, .colist > table { border: 0; background: none; } 537 | .hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; } 538 | 539 | td.hdlist1 { padding-right: .75em; font-weight: bold; } 540 | 541 | td.hdlist1, td.hdlist2 { vertical-align: top; } 542 | 543 | .literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; } 544 | 545 | .colist > table tr > td:first-of-type { padding: 0 0.75em; line-height: 1; } 546 | .colist > table tr > td:last-of-type { padding: 0.25em 0; } 547 | 548 | .thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; } 549 | 550 | .imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; } 551 | .imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; } 552 | .imageblock > .title { margin-bottom: 0; } 553 | .imageblock.thumb, .imageblock.th { border-width: 6px; } 554 | .imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; } 555 | 556 | .image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; } 557 | .image.left { margin-right: 0.625em; } 558 | .image.right { margin-left: 0.625em; } 559 | 560 | a.image { text-decoration: none; } 561 | 562 | span.footnote, span.footnoteref { vertical-align: super; font-size: 0.875em; } 563 | span.footnote a, span.footnoteref a { text-decoration: none; } 564 | span.footnote a:active, span.footnoteref a:active { text-decoration: underline; } 565 | 566 | #footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; } 567 | #footnotes hr { width: 20%; min-width: 6.25em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; } 568 | #footnotes .footnote { padding: 0 0.375em; line-height: 1.3; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; } 569 | #footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; } 570 | #footnotes .footnote:last-of-type { margin-bottom: 0; } 571 | 572 | #content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; } 573 | 574 | .gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; } 575 | .gist .file-data > table td.line-data { width: 99%; } 576 | 577 | div.unbreakable { page-break-inside: avoid; } 578 | 579 | .big { font-size: larger; } 580 | 581 | .small { font-size: smaller; } 582 | 583 | .underline { text-decoration: underline; } 584 | 585 | .overline { text-decoration: overline; } 586 | 587 | .line-through { text-decoration: line-through; } 588 | 589 | .aqua { color: #00bfbf; } 590 | 591 | .aqua-background { background-color: #00fafa; } 592 | 593 | .black { color: black; } 594 | 595 | .black-background { background-color: black; } 596 | 597 | .blue { color: #0000bf; } 598 | 599 | .blue-background { background-color: #0000fa; } 600 | 601 | .fuchsia { color: #bf00bf; } 602 | 603 | .fuchsia-background { background-color: #fa00fa; } 604 | 605 | .gray { color: #606060; } 606 | 607 | .gray-background { background-color: #7d7d7d; } 608 | 609 | .green { color: #006000; } 610 | 611 | .green-background { background-color: #007d00; } 612 | 613 | .lime { color: #00bf00; } 614 | 615 | .lime-background { background-color: #00fa00; } 616 | 617 | .maroon { color: #600000; } 618 | 619 | .maroon-background { background-color: #7d0000; } 620 | 621 | .navy { color: #000060; } 622 | 623 | .navy-background { background-color: #00007d; } 624 | 625 | .olive { color: #606000; } 626 | 627 | .olive-background { background-color: #7d7d00; } 628 | 629 | .purple { color: #600060; } 630 | 631 | .purple-background { background-color: #7d007d; } 632 | 633 | .red { color: #bf0000; } 634 | 635 | .red-background { background-color: #fa0000; } 636 | 637 | .silver { color: #909090; } 638 | 639 | .silver-background { background-color: #bcbcbc; } 640 | 641 | .teal { color: #006060; } 642 | 643 | .teal-background { background-color: #007d7d; } 644 | 645 | .white { color: #bfbfbf; } 646 | 647 | .white-background { background-color: #fafafa; } 648 | 649 | .yellow { color: #bfbf00; } 650 | 651 | .yellow-background { background-color: #fafa00; } 652 | 653 | span.icon > .fa { cursor: default; } 654 | 655 | .admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; } 656 | .admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #004176; } 657 | .admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; } 658 | .admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; } 659 | .admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; } 660 | .admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; } 661 | 662 | .conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; } 663 | .conum[data-value] * { color: #fff !important; } 664 | .conum[data-value] + b { display: none; } 665 | .conum[data-value]:after { content: attr(data-value); } 666 | pre .conum[data-value] { position: relative; top: -0.125em; } 667 | 668 | b.conum * { color: inherit !important; } 669 | 670 | .conum:not([data-value]):empty { display: none; } 671 | 672 | h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; } 673 | 674 | .sect1 { padding-bottom: 0; } 675 | 676 | #toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; } 677 | 678 | .sidebarblock { border-color: #aaa; } 679 | 680 | code { -webkit-border-radius: 4px; border-radius: 4px; } 681 | 682 | p.tableblock.header { color: #6d6e71; } 683 | 684 | .literalblock pre, .listingblock pre { background: #eeeeee; } 685 | -------------------------------------------------------------------------------- /doc/enums.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[enums]] 3 | == Enums 4 | 5 | [[channels]] 6 | [small]#*channels*: '_y_' (grey), '_ya_' (grey alpha), '_rgb_', '_rgba_'. + 7 | Notice that _#channels_ gives the number of channels (e.g. #_'rgb'_ = 3 channels).# 8 | 9 | [[chantype]] 10 | [small]#*chantype*: '_u8_', '_u16_', '_f_'.# 11 | 12 | -------------------------------------------------------------------------------- /doc/index.adoc: -------------------------------------------------------------------------------- 1 | = MoonImage Reference Manual 2 | Stefano Trettel 3 | v0.3, 2020-04-21 4 | :toc: left 5 | :toclevels: 2 6 | :stylesdir: ./ 7 | :stylesheet: colony.css 8 | :source-highlighter: pygments 9 | :pygments-style: autumn 10 | :source-language: lua 11 | :exampledir: ../examples 12 | 13 | image::powered-by-lua.gif[Lua logo, link=http://www.lua.org] 14 | 15 | // Macros for trees: {tS} = " ", {tI} = "│  ", {tH} = "├─ ", {tL} = "└─ " 16 | :tS:      17 | :tI: │    18 | :tH: ├─  19 | :tL: └─  20 | 21 | include::preface.adoc[] 22 | 23 | include::load.adoc[] 24 | include::write.adoc[] 25 | include::perlin.adoc[] 26 | include::enums.adoc[] 27 | 28 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | MoonImage Reference Manual 10 | 697 | 765 | 766 | 767 | 793 |
794 |
795 |
796 |
797 |
798 | Lua logo 799 |
800 |
801 |
802 |
803 |
804 |

Preface

805 |
806 |
807 |

This is the reference manual of MoonImage, which is a 808 | Lua image loading library based on Sean Barrett’s 809 | STB libraries. 810 | [1]

811 |
812 |
813 |

It is assumed that the reader is familiar with the Lua programming language.

814 |
815 |
816 |

For convenience of reference, this document contains external (deep) links to the 817 | Lua Reference Manual.

818 |
819 |
820 |

Getting and installing

821 |
822 |

For installation intructions, refer to the README file in the 823 | MoonImage official repository 824 | on GitHub.

825 |
826 |
827 |
828 |

Module organization

829 |
830 |

The MoonImage module is loaded using Lua’s 831 | require() and 832 | returns a table containing the functions it provides 833 | (as usual with Lua modules). This manual assumes that such 834 | table is named mi, i.e. that it is loaded with:

835 |
836 |
837 |
838 |
 mi = require("image")
839 |
840 |
841 |
842 |

but nothing forbids the use of a different name.

843 |
844 |
845 |
846 |

Examples

847 |
848 |

Complete examples can be found in the examples/ directory of the release package.

849 |
850 |
851 |
852 |

License

853 |
854 |

MoonImage is released under the MIT/X11 license (same as 855 | Lua, and with the same only requirement to give proper 856 | credits to the original author). 857 | The copyright notice is in the LICENSE file in the base directory 858 | of the official repository on GitHub.

859 |
860 |
861 |
862 |

See also

863 |
864 |

MoonImage is part of MoonLibs, a collection of 865 | Lua libraries for graphics and audio programming.

866 |
867 |
868 |
869 |
870 |
871 |

Load images

872 |
873 |
874 |

Rfr: stb_image.h

875 |
876 |
877 |
    878 |
  • 879 |

    data, w, h, channels = load(filename, [desiredchannels], [chantype])
    880 | Loads an image from a file, and returns the image data, its width w and height h, and the color channels contained in data (which is the same as desiredchannels unless this is nil, in which case channels is the same as in the image file).
    881 | The returned data is a binary string containing w*h pixels, each pixel consisting of up to 4 interleaved components (one per channel).
    882 | The type of the components is determined by the chantype parameter:
    883 | -if chantype is 'u8' or nil, then each component is an unsigned 8 bit integer;
    884 | -if chantype is 'u16', then each component is an unsigned 16 bit integer;
    885 | -if chantype is 'f', then each component is a single precision float value.
    886 | Note that this may involve lossy data conversion if chantype does not match how data is stored 887 | in the image file.
    888 | (u16 values are converted to u8 by just keeping the MSB, u8 values 889 | are converted to u16 by mapping x to x*28+x, while conversion to or from floats is done 890 | using gamma correction with the current gamma and scale values.)

    891 |
  • 892 |
893 |
894 |
895 |
    896 |
  • 897 |

    w, h, channels = info(filename)
    898 | Retrieves information for an image without loading it.

    899 |
  • 900 |
901 |
902 |
903 |
    904 |
  • 905 |

    boolean = is_hdr(filename)
    906 | Returns true the image contained in filename is HDR (High Dynamic Range).

    907 |
  • 908 |
909 |
910 |
911 |
    912 |
  • 913 |

    set_gamma_and_scale(gamma, scale)
    914 | gamma, scale = gamma_and_scale( )
    915 | Set/get the gamma and scale values used in gamma correction (by default, gamma = 2.2 and scale = 1.0).

    916 |
  • 917 |
918 |
919 |
920 |
    921 |
  • 922 |

    flip_vertically_on_load(boolean)
    923 | unpremultiply_on_load(boolean)
    924 | convert_iphone_png_to_rgb(boolean)
    925 | Load flags that control a few aspects of how an image is loaded (see stb_image.h for more details).

    926 |
  • 927 |
928 |
929 |
930 |
    931 |
  • 932 |

    reset_load_flags( )
    933 | Resets all the load flags to false (which is also their initial value).

    934 |
  • 935 |
936 |
937 |
938 |
    939 |
  • 940 |

    data = reduce_to_u8(data, w, h, channels, chantype)
    941 | Downgrades 'u16' or 'f' image data to 'u8' (see load( )).

    942 |
  • 943 |
944 |
945 |
946 |
947 |
948 |

Write images

949 |
950 |
951 |

Rfr: stb_image_write.h

952 |
953 |
954 |
    955 |
  • 956 |

    write_png(filename, w, h, channels, data, [stride])
    957 | Write data to a PNG file. 958 | Expects w*h*#channels bytes of data.

    959 |
  • 960 |
961 |
962 |
963 |
    964 |
  • 965 |

    write_bmp(filename, w, h, channels, data)
    966 | Write data to a BMP file. 967 | Expects w*h*#channels bytes of data.

    968 |
  • 969 |
970 |
971 |
972 |
    973 |
  • 974 |

    write_tga(filename, w, h, channels, data, [rle])
    975 | Write data to a TGA file. 976 | Expects w*h*#channels bytes of data.
    977 | Pass rle = true to use RLE compression.

    978 |
  • 979 |
980 |
981 |
982 |
    983 |
  • 984 |

    write_jpg(filename, w, h, channels, data, quality)
    985 | Write data to a JPG file. 986 | Expects w*h*#channels bytes of data.
    987 | quality = 1 (min) .. 100 (max).

    988 |
  • 989 |
990 |
991 |
992 |
    993 |
  • 994 |

    write_hdr(filename, w, h, channels, data)
    995 | Write data to a HDR file. 996 | Expects w*h*#channels*sizeof(float) bytes of data.

    997 |
  • 998 |
999 |
1000 |
1001 |
1002 |
1003 |

Perlin noise

1004 |
1005 |
1006 |

Rfr: stb_perlin.h

1007 |
1008 |
1009 |
    1010 |
  • 1011 |

    value = perlin(x, [y, z, xwrap, ywrap, zwrap, seed])
    1012 | Computes a random value at coordinates (x, y, z).
    1013 | Binding to stb_perlin_noise3_seed( ). See stb_perlin.h for details.

    1014 |
  • 1015 |
1016 |
1017 |
1018 |
1019 |
1020 |

Enums

1021 |
1022 |
1023 |

channels: 'y' (grey), 'ya' (grey alpha), 'rgb', 'rgba'.
1024 | Notice that #channels gives the number of channels (e.g. #'rgb' = 3 channels).

1025 |
1026 |
1027 |

chantype: 'u8', 'u16', 'f'.

1028 |
1029 |
1030 |
1031 |
1032 |
1033 |
1034 |
1035 | 1. This manual is written in AsciiDoc, rendered with AsciiDoctor and a CSS from the AsciiDoctor Stylesheet Factory. 1036 |
1037 |
1038 | 1044 | 1045 | -------------------------------------------------------------------------------- /doc/load.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Load images 3 | 4 | [small]#Rfr: https://github.com/nothings/stb[stb_image.h]# 5 | 6 | [[load]] 7 | * _data_, _w_, _h_, <> = *load*(_filename_, [<>], [<>]) + 8 | [small]#Loads an image from a file, and returns the image _data_, its width _w_ and height _h_, and the color _channels_ contained in _data_ (which is the same as _desiredchannels_ unless this is _nil_, in which case _channels_ is the same as in the image file). + 9 | The returned _data_ is a binary string containing _w*h_ pixels, each pixel consisting of up to 4 interleaved components (one per channel). + 10 | The type of the components is determined by the _chantype_ parameter: + 11 | pass:[-]if _chantype_ is '_u8_' or _nil_, then each component is an unsigned 8 bit integer; + 12 | pass:[-]if _chantype_ is '_u16_', then each component is an unsigned 16 bit integer; + 13 | pass:[-]if _chantype_ is '_f_', then each component is a single precision float value. + 14 | Note that this may involve lossy data conversion if _chantype_ does not match how data is stored 15 | in the image file. + 16 | (_u16_ values are converted to _u8_ by just keeping the MSB, _u8_ values 17 | are converted to _u16_ by mapping _x_ to _x*2^8^+x_, while conversion to or from floats is done 18 | using gamma correction with the current <> values.)# 19 | 20 | //// 21 | u8 <-> u18 conversions: 22 | u8->u16 x -> (x>>8) & 0xff (MSB as 8bit approximation of a 16 bit value) 23 | u16->u8 x -> (x<<8) + x (map 0->0 and 255->0xffff) 24 | //// 25 | 26 | [[info]] 27 | * _w_, _h_, <> = *info*(_filename_) + 28 | [small]#Retrieves information for an image without loading it.# 29 | 30 | [[is_hdr]] 31 | * _boolean_ = *is_hdr*(_filename_) + 32 | [small]#Returns _true_ the image contained in _filename_ is HDR (High Dynamic Range).# 33 | 34 | [[gamma_and_scale]] 35 | * *set_gamma_and_scale*(_gamma_, _scale_) + 36 | _gamma_, _scale_ = *gamma_and_scale*( ) + 37 | [small]#Set/get the _gamma_ and _scale_ values used in https://en.wikipedia.org/wiki/Gamma_correction[gamma correction] (by default, _gamma = 2.2_ and _scale = 1.0_).# 38 | 39 | [[load_flags]] 40 | * *flip_vertically_on_load*(_boolean_) + 41 | *unpremultiply_on_load*(_boolean_) + 42 | *convert_iphone_png_to_rgb*(_boolean_) + 43 | [small]#Load flags that control a few aspects of how an image is loaded (see https://github.com/nothings/stb[stb_image.h] for more details).# 44 | 45 | 46 | [[reset_load_flags]] 47 | * *reset_load_flags*( ) + 48 | [small]#Resets all the <> to _false_ (which is also their initial value).# 49 | 50 | [[reduce_to_u8]] 51 | * _data_ = *reduce_to_u8*(_data_, _w_, _h_, <>, <>) + 52 | [small]#Downgrades '_u16_' or '_f_' image data to '_u8_' (see <>( )).# 53 | 54 | //// 55 | [[]] 56 | * **( ) + 57 | [small]#@@TODO.# 58 | //// 59 | 60 | -------------------------------------------------------------------------------- /doc/perlin.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[Write]] 3 | == Perlin noise 4 | 5 | [small]#Rfr: https://github.com/nothings/stb[stb_perlin.h]# 6 | 7 | [[perlin]] 8 | * _value_ = *perlin*(_x_, [_y_, _z_, _xwrap_, _ywrap_, _zwrap_, _seed_]) + 9 | [small]#Computes a random value at coordinates _(x, y, z)_. + 10 | Binding to _stb_perlin_noise3_seed( )_. See stb_perlin.h for details.# 11 | 12 | -------------------------------------------------------------------------------- /doc/powered-by-lua.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonimage/6d8bbb75ff47429c426e61e59aada3950e2b2217/doc/powered-by-lua.gif -------------------------------------------------------------------------------- /doc/preface.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Preface 3 | 4 | This is the reference manual of *MoonImage*, which is a 5 | http://www.lua.org[*Lua*] image loading library based on Sean Barrett's 6 | https://github.com/nothings/stb[*STB libraries*]. 7 | footnote:[ 8 | This manual is written in 9 | http://www.methods.co.nz/asciidoc/[AsciiDoc], rendered with 10 | http://asciidoctor.org/[AsciiDoctor] and a CSS from the 11 | https://github.com/asciidoctor/asciidoctor-stylesheet-factory[AsciiDoctor Stylesheet Factory].] 12 | 13 | It is assumed that the reader is familiar with the Lua programming language. 14 | 15 | For convenience of reference, this document contains external (deep) links to the 16 | http://www.lua.org/manual/5.3/manual.html[Lua Reference Manual]. 17 | 18 | === Getting and installing 19 | 20 | For installation intructions, refer to the README file in the 21 | https://github.com/stetre/image[*MoonImage official repository*] 22 | on GitHub. 23 | 24 | === Module organization 25 | 26 | The MoonImage module is loaded using Lua's 27 | http://www.lua.org/manual/5.3/manual.html#pdf-require[require]() and 28 | returns a table containing the functions it provides 29 | (as usual with Lua modules). This manual assumes that such 30 | table is named *mi*, i.e. that it is loaded with: 31 | 32 | [source,lua,indent=1] 33 | ---- 34 | mi = require("image") 35 | ---- 36 | 37 | but nothing forbids the use of a different name. 38 | 39 | === Examples 40 | 41 | Complete examples can be found in the *examples/* directory of the release package. 42 | 43 | === License 44 | 45 | MoonImage is released under the *MIT/X11 license* (same as 46 | http://www.lua.org/license.html[Lua], and with the same only requirement to give proper 47 | credits to the original author). 48 | The copyright notice is in the LICENSE file in the base directory 49 | of the https://github.com/stetre/moonimage[official repository] on GitHub. 50 | 51 | [[see-also]] 52 | === See also 53 | 54 | MoonImage is part of https://github.com/stetre/moonlibs[MoonLibs], a collection of 55 | Lua libraries for graphics and audio programming. 56 | 57 | -------------------------------------------------------------------------------- /doc/write.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[Write]] 3 | == Write images 4 | 5 | [small]#Rfr: https://github.com/nothings/stb[stb_image_write.h]# 6 | 7 | [[write_png]] 8 | * *write_png*(_filename_, _w_, _h_, <>, _data_, [_stride_]) + 9 | [small]#Write data to a https://en.wikipedia.org/wiki/Portable_Network_Graphics[PNG] file. 10 | Expects _w*h*#channels_ bytes of _data_.# 11 | 12 | [[write_bmp]] 13 | * *write_bmp*(_filename_, _w_, _h_, <>, _data_) + 14 | [small]#Write data to a https://en.wikipedia.org/wiki/BMP_file_format[BMP] file. 15 | Expects _w*h*#channels_ bytes of _data_.# 16 | 17 | [[write_tga]] 18 | * *write_tga*(_filename_, _w_, _h_, <>, _data_, [_rle_]) + 19 | [small]#Write data to a https://en.wikipedia.org/wiki/Truevision_TGA[TGA] file. 20 | Expects _w*h*#channels_ bytes of _data_. + 21 | Pass _rle_ = _true_ to use RLE compression.# 22 | 23 | [[write_jpg]] 24 | * *write_jpg*(_filename_, _w_, _h_, <>, _data_, _quality_) + 25 | [small]#Write data to a https://en.wikipedia.org/wiki/JPEG[JPG] file. 26 | Expects _w*h*#channels_ bytes of _data_. + 27 | _quality = 1 (min) .. 100 (max)_.# 28 | 29 | [[write_hdr]] 30 | * *write_hdr*(_filename_, _w_, _h_, <>, _data_) + 31 | [small]#Write data to a https://en.wikipedia.org/wiki/Radiance_(software)#HDR_image_format[HDR] file. 32 | Expects _w*h*#channels*sizeof(float)_ bytes of _data_.# 33 | -------------------------------------------------------------------------------- /examples/hello.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonImage example: hello.lua 3 | 4 | mi = require("moonimage") 5 | 6 | -- Load an image from a jpg file: 7 | data, w, h, channels = mi.load("sunflowers.jpg", 'rgba') 8 | 9 | -- Write it to a bmp file: 10 | mi.write_bmp("output.bmp", w, h, channels, data) 11 | 12 | -------------------------------------------------------------------------------- /examples/sunflowers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonimage/6d8bbb75ff47429c426e61e59aada3950e2b2217/examples/sunflowers.jpg -------------------------------------------------------------------------------- /examples/version.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | mi = require("moonimage") 4 | 5 | print(mi._VERSION) 6 | 7 | 8 | -------------------------------------------------------------------------------- /moonimage/README: -------------------------------------------------------------------------------- 1 | 2 | This directory should contain any additional utility implemented in pure Lua. 3 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ifdef MINGW_PREFIX 3 | MINGW=1 4 | else 5 | LINUX=1 6 | endif 7 | 8 | # Lua version 9 | LUAVER?=$(shell lua -e 'print(string.match(_VERSION, "%d+%.%d+") or "5.3")') 10 | ifeq ($(LUAVER),) 11 | # lua-interpreter not found 12 | LUAVER=5.3 13 | endif 14 | 15 | # Base install directory 16 | ifdef LINUX 17 | PREFIX?=/usr/local 18 | endif 19 | ifdef MINGW 20 | PREFIX?=$(MINGW_PREFIX) 21 | endif 22 | 23 | # Directory where to install Lua modules 24 | L_DIR=$(PREFIX)/share/lua/$(LUAVER) 25 | # Directory where to install Lua C modules 26 | C_DIR=$(PREFIX)/lib/lua/$(LUAVER) 27 | # Directory where to install C headers 28 | H_DIR=$(PREFIX)/include 29 | # Directory where to install C libraries 30 | S_DIR=$(PREFIX)/lib 31 | 32 | ifeq ($(D),1) 33 | DEBUG=1 34 | endif 35 | 36 | Tgt := moonimage 37 | Src := $(wildcard *.c) 38 | Objs := $(Src:.c=.o) 39 | 40 | COPT += -O2 41 | #COPT += -O0 -g 42 | #COPT += -m32 43 | COPT += -Wall -Wextra -Wpedantic 44 | COPT += -DCOMPAT53_PREFIX=moonimage_compat_ 45 | COPT += -Wno-unused-function -Wno-implicit-fallthrough #@@ 46 | COPT += -std=gnu99 47 | COPT += -DLUAVER=$(LUAVER) 48 | ifdef LINUX 49 | COPT += -fpic 50 | COPT += -DLINUX 51 | INCDIR = -I./include -I/usr/include/lua$(LUAVER) 52 | endif 53 | ifdef MINGW 54 | COPT += -DMINGW 55 | INCDIR = -I./include 56 | LIBS = -llua 57 | endif 58 | ifdef DEBUG 59 | COPT += -DDEBUG 60 | COPT += -Wshadow -Wsign-compare -Wundef -Wwrite-strings 61 | COPT += -Wdisabled-optimization -Wdeclaration-after-statement 62 | COPT += -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs 63 | COPT += -Wc++-compat -Wold-style-definition 64 | endif 65 | 66 | override CFLAGS = $(COPT) $(INCDIR) 67 | 68 | default: build 69 | 70 | where: 71 | @echo "PREFIX="$(PREFIX) 72 | @echo "LUAVER="$(LUAVER) 73 | @echo $(L_DIR) 74 | @echo $(C_DIR) 75 | @echo $(H_DIR) 76 | @echo $(S_DIR) 77 | 78 | clean: 79 | @-rm -f *.so *.dll *.o *.err *.map *.S *~ *.log 80 | @-rm -f $(Tgt).symbols 81 | 82 | install: 83 | @-mkdir -pv $(H_DIR) 84 | @-mkdir -pv $(C_DIR) 85 | @-mkdir -pv $(S_DIR) 86 | @-mkdir -pv $(L_DIR) 87 | @-cp -fpv $(Tgt).h $(H_DIR) 88 | @-cp -fpvr ../$(Tgt) $(L_DIR) 89 | ifdef LINUX 90 | @-cp -fpv $(Tgt).so $(C_DIR) 91 | @-ln -fsv $(C_DIR)/$(Tgt).so $(S_DIR)/lib$(Tgt).so 92 | endif 93 | ifdef MINGW 94 | @-cp -fpv $(Tgt).dll $(C_DIR) 95 | endif 96 | 97 | uninstall: 98 | @-rm -f $(H_DIR)/$(Tgt).h 99 | @-rm -f $(C_DIR)/$(Tgt).so 100 | @-rm -f $(S_DIR)/lib$(Tgt).so 101 | @-rm -fr $(L_DIR)/$(Tgt) 102 | @-rm -f $(C_DIR)/$(Tgt).dll 103 | 104 | build: clean $(Tgt) 105 | 106 | symbols: build 107 | @objdump -T $(Tgt).so > $(Tgt).symbols 108 | 109 | $(Tgt): $(Objs) 110 | ifdef LINUX 111 | @-$(CC) -shared -o $(Tgt).so $(Objs) $(LIBDIR) $(LIBS) 112 | endif 113 | ifdef MINGW 114 | @-$(CC) -shared -o $(Tgt).dll $(Objs) $(LIBDIR) $(LIBS) 115 | endif 116 | @-rm -f $(Objs) 117 | @echo 118 | 119 | -------------------------------------------------------------------------------- /src/_make: -------------------------------------------------------------------------------- 1 | make D=$1 LUAVER=5.4 && sudo make LUAVER=5.4 install 2 | -------------------------------------------------------------------------------- /src/compat-5.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "compat-5.3.h" 8 | 9 | /* don't compile it again if it already is included via compat53.h */ 10 | #ifndef COMPAT53_C_ 11 | #define COMPAT53_C_ 12 | 13 | 14 | 15 | /* definitions for Lua 5.1 only */ 16 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 17 | 18 | #ifndef COMPAT53_FOPEN_NO_LOCK 19 | # if defined(_MSC_VER) 20 | # define COMPAT53_FOPEN_NO_LOCK 1 21 | # else /* otherwise */ 22 | # define COMPAT53_FOPEN_NO_LOCK 0 23 | # endif /* VC++ only so far */ 24 | #endif /* No-lock fopen_s usage if possible */ 25 | 26 | #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK 27 | # include 28 | #endif /* VC++ _fsopen for share-allowed file read */ 29 | 30 | #ifndef COMPAT53_HAVE_STRERROR_R 31 | # if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ 32 | (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) || \ 33 | defined(__APPLE__) 34 | # define COMPAT53_HAVE_STRERROR_R 1 35 | # else /* none of the defines matched: define to 0 */ 36 | # define COMPAT53_HAVE_STRERROR_R 0 37 | # endif /* have strerror_r of some form */ 38 | #endif /* strerror_r */ 39 | 40 | #ifndef COMPAT53_HAVE_STRERROR_S 41 | # if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \ 42 | defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) 43 | # define COMPAT53_HAVE_STRERROR_S 1 44 | # else /* not VC++ or C11 */ 45 | # define COMPAT53_HAVE_STRERROR_S 0 46 | # endif /* strerror_s from VC++ or C11 */ 47 | #endif /* strerror_s */ 48 | 49 | #ifndef COMPAT53_LUA_FILE_BUFFER_SIZE 50 | # define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 51 | #endif /* Lua File Buffer Size */ 52 | 53 | 54 | static char* compat53_strerror (int en, char* buff, size_t sz) { 55 | #if COMPAT53_HAVE_STRERROR_R 56 | /* use strerror_r here, because it's available on these specific platforms */ 57 | if (sz > 0) { 58 | buff[0] = '\0'; 59 | /* we don't care whether the GNU version or the XSI version is used: */ 60 | if (strerror_r(en, buff, sz)) { 61 | /* Yes, we really DO want to ignore the return value! 62 | * GCC makes that extra hard, not even a (void) cast will do. */ 63 | } 64 | if (buff[0] == '\0') { 65 | /* Buffer is unchanged, so we probably have called GNU strerror_r which 66 | * returned a static constant string. Chances are that strerror will 67 | * return the same static constant string and therefore be thread-safe. */ 68 | return strerror(en); 69 | } 70 | } 71 | return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ 72 | #elif COMPAT53_HAVE_STRERROR_S 73 | /* for MSVC and other C11 implementations, use strerror_s since it's 74 | * provided by default by the libraries */ 75 | strerror_s(buff, sz, en); 76 | return buff; 77 | #else 78 | /* fallback, but strerror is not guaranteed to be threadsafe due to modifying 79 | * errno itself and some impls not locking a static buffer for it ... but most 80 | * known systems have threadsafe errno: this might only change if the locale 81 | * is changed out from under someone while this function is being called */ 82 | (void)buff; 83 | (void)sz; 84 | return strerror(en); 85 | #endif 86 | } 87 | 88 | 89 | COMPAT53_API int lua_absindex (lua_State *L, int i) { 90 | if (i < 0 && i > LUA_REGISTRYINDEX) 91 | i += lua_gettop(L) + 1; 92 | return i; 93 | } 94 | 95 | 96 | static void compat53_call_lua (lua_State *L, char const code[], size_t len, 97 | int nargs, int nret) { 98 | lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); 99 | if (lua_type(L, -1) != LUA_TFUNCTION) { 100 | lua_pop(L, 1); 101 | if (luaL_loadbuffer(L, code, len, "=none")) 102 | lua_error(L); 103 | lua_pushvalue(L, -1); 104 | lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); 105 | } 106 | lua_insert(L, -nargs-1); 107 | lua_call(L, nargs, nret); 108 | } 109 | 110 | 111 | static const char compat53_arith_code[] = 112 | "local op,a,b=...\n" 113 | "if op==0 then return a+b\n" 114 | "elseif op==1 then return a-b\n" 115 | "elseif op==2 then return a*b\n" 116 | "elseif op==3 then return a/b\n" 117 | "elseif op==4 then return a%b\n" 118 | "elseif op==5 then return a^b\n" 119 | "elseif op==6 then return -a\n" 120 | "end\n"; 121 | 122 | COMPAT53_API void lua_arith (lua_State *L, int op) { 123 | if (op < LUA_OPADD || op > LUA_OPUNM) 124 | luaL_error(L, "invalid 'op' argument for lua_arith"); 125 | luaL_checkstack(L, 5, "not enough stack slots"); 126 | if (op == LUA_OPUNM) 127 | lua_pushvalue(L, -1); 128 | lua_pushnumber(L, op); 129 | lua_insert(L, -3); 130 | compat53_call_lua(L, compat53_arith_code, 131 | sizeof(compat53_arith_code)-1, 3, 1); 132 | } 133 | 134 | 135 | static const char compat53_compare_code[] = 136 | "local a,b=...\n" 137 | "return a<=b\n"; 138 | 139 | COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) { 140 | int result = 0; 141 | switch (op) { 142 | case LUA_OPEQ: 143 | return lua_equal(L, idx1, idx2); 144 | case LUA_OPLT: 145 | return lua_lessthan(L, idx1, idx2); 146 | case LUA_OPLE: 147 | luaL_checkstack(L, 5, "not enough stack slots"); 148 | idx1 = lua_absindex(L, idx1); 149 | idx2 = lua_absindex(L, idx2); 150 | lua_pushvalue(L, idx1); 151 | lua_pushvalue(L, idx2); 152 | compat53_call_lua(L, compat53_compare_code, 153 | sizeof(compat53_compare_code)-1, 2, 1); 154 | result = lua_toboolean(L, -1); 155 | lua_pop(L, 1); 156 | return result; 157 | default: 158 | luaL_error(L, "invalid 'op' argument for lua_compare"); 159 | } 160 | return 0; 161 | } 162 | 163 | 164 | COMPAT53_API void lua_copy (lua_State *L, int from, int to) { 165 | int abs_to = lua_absindex(L, to); 166 | luaL_checkstack(L, 1, "not enough stack slots"); 167 | lua_pushvalue(L, from); 168 | lua_replace(L, abs_to); 169 | } 170 | 171 | 172 | COMPAT53_API void lua_len (lua_State *L, int i) { 173 | switch (lua_type(L, i)) { 174 | case LUA_TSTRING: 175 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); 176 | break; 177 | case LUA_TTABLE: 178 | if (!luaL_callmeta(L, i, "__len")) 179 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); 180 | break; 181 | case LUA_TUSERDATA: 182 | if (luaL_callmeta(L, i, "__len")) 183 | break; 184 | /* FALLTHROUGH */ 185 | default: 186 | luaL_error(L, "attempt to get length of a %s value", 187 | lua_typename(L, lua_type(L, i))); 188 | } 189 | } 190 | 191 | 192 | COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) { 193 | int abs_i = lua_absindex(L, i); 194 | lua_pushlightuserdata(L, (void*)p); 195 | lua_rawget(L, abs_i); 196 | return lua_type(L, -1); 197 | } 198 | 199 | COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) { 200 | int abs_i = lua_absindex(L, i); 201 | luaL_checkstack(L, 1, "not enough stack slots"); 202 | lua_pushlightuserdata(L, (void*)p); 203 | lua_insert(L, -2); 204 | lua_rawset(L, abs_i); 205 | } 206 | 207 | 208 | COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) { 209 | lua_Number n = lua_tonumber(L, i); 210 | if (isnum != NULL) { 211 | *isnum = (n != 0 || lua_isnumber(L, i)); 212 | } 213 | return n; 214 | } 215 | 216 | 217 | COMPAT53_API void luaL_checkversion (lua_State *L) { 218 | (void)L; 219 | } 220 | 221 | 222 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg) { 223 | if (!lua_checkstack(L, sp+LUA_MINSTACK)) { 224 | if (msg != NULL) 225 | luaL_error(L, "stack overflow (%s)", msg); 226 | else { 227 | lua_pushliteral(L, "stack overflow"); 228 | lua_error(L); 229 | } 230 | } 231 | } 232 | 233 | 234 | COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) { 235 | int abs_i = lua_absindex(L, i); 236 | luaL_checkstack(L, 3, "not enough stack slots"); 237 | lua_pushstring(L, name); 238 | lua_gettable(L, abs_i); 239 | if (lua_istable(L, -1)) 240 | return 1; 241 | lua_pop(L, 1); 242 | lua_newtable(L); 243 | lua_pushstring(L, name); 244 | lua_pushvalue(L, -2); 245 | lua_settable(L, abs_i); 246 | return 0; 247 | } 248 | 249 | 250 | COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) { 251 | lua_Integer res = 0; 252 | int isnum = 0; 253 | luaL_checkstack(L, 1, "not enough stack slots"); 254 | lua_len(L, i); 255 | res = lua_tointegerx(L, -1, &isnum); 256 | lua_pop(L, 1); 257 | if (!isnum) 258 | luaL_error(L, "object length is not an integer"); 259 | return res; 260 | } 261 | 262 | 263 | COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { 264 | luaL_checkstack(L, nup+1, "too many upvalues"); 265 | for (; l->name != NULL; l++) { /* fill the table with given functions */ 266 | int i; 267 | lua_pushstring(L, l->name); 268 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ 269 | lua_pushvalue(L, -(nup + 1)); 270 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ 271 | lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ 272 | } 273 | lua_pop(L, nup); /* remove upvalues */ 274 | } 275 | 276 | 277 | COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) { 278 | luaL_checkstack(L, 1, "not enough stack slots"); 279 | luaL_getmetatable(L, tname); 280 | lua_setmetatable(L, -2); 281 | } 282 | 283 | 284 | COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) { 285 | void *p = lua_touserdata(L, i); 286 | luaL_checkstack(L, 2, "not enough stack slots"); 287 | if (p == NULL || !lua_getmetatable(L, i)) 288 | return NULL; 289 | else { 290 | int res = 0; 291 | luaL_getmetatable(L, tname); 292 | res = lua_rawequal(L, -1, -2); 293 | lua_pop(L, 2); 294 | if (!res) 295 | p = NULL; 296 | } 297 | return p; 298 | } 299 | 300 | 301 | static int compat53_countlevels (lua_State *L) { 302 | lua_Debug ar; 303 | int li = 1, le = 1; 304 | /* find an upper bound */ 305 | while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } 306 | /* do a binary search */ 307 | while (li < le) { 308 | int m = (li + le)/2; 309 | if (lua_getstack(L, m, &ar)) li = m + 1; 310 | else le = m; 311 | } 312 | return le - 1; 313 | } 314 | 315 | static int compat53_findfield (lua_State *L, int objidx, int level) { 316 | if (level == 0 || !lua_istable(L, -1)) 317 | return 0; /* not found */ 318 | lua_pushnil(L); /* start 'next' loop */ 319 | while (lua_next(L, -2)) { /* for each pair in table */ 320 | if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ 321 | if (lua_rawequal(L, objidx, -1)) { /* found object? */ 322 | lua_pop(L, 1); /* remove value (but keep name) */ 323 | return 1; 324 | } 325 | else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */ 326 | lua_remove(L, -2); /* remove table (but keep name) */ 327 | lua_pushliteral(L, "."); 328 | lua_insert(L, -2); /* place '.' between the two names */ 329 | lua_concat(L, 3); 330 | return 1; 331 | } 332 | } 333 | lua_pop(L, 1); /* remove value */ 334 | } 335 | return 0; /* not found */ 336 | } 337 | 338 | static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) { 339 | int top = lua_gettop(L); 340 | lua_getinfo(L, "f", ar); /* push function */ 341 | lua_pushvalue(L, LUA_GLOBALSINDEX); 342 | if (compat53_findfield(L, top + 1, 2)) { 343 | lua_copy(L, -1, top + 1); /* move name to proper place */ 344 | lua_pop(L, 2); /* remove pushed values */ 345 | return 1; 346 | } 347 | else { 348 | lua_settop(L, top); /* remove function and global table */ 349 | return 0; 350 | } 351 | } 352 | 353 | static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) { 354 | if (*ar->namewhat != '\0') /* is there a name? */ 355 | lua_pushfstring(L, "function " LUA_QS, ar->name); 356 | else if (*ar->what == 'm') /* main? */ 357 | lua_pushliteral(L, "main chunk"); 358 | else if (*ar->what == 'C') { 359 | if (compat53_pushglobalfuncname(L, ar)) { 360 | lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); 361 | lua_remove(L, -2); /* remove name */ 362 | } 363 | else 364 | lua_pushliteral(L, "?"); 365 | } 366 | else 367 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); 368 | } 369 | 370 | #define COMPAT53_LEVELS1 12 /* size of the first part of the stack */ 371 | #define COMPAT53_LEVELS2 10 /* size of the second part of the stack */ 372 | 373 | COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, 374 | const char *msg, int level) { 375 | lua_Debug ar; 376 | int top = lua_gettop(L); 377 | int numlevels = compat53_countlevels(L1); 378 | int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0; 379 | if (msg) lua_pushfstring(L, "%s\n", msg); 380 | lua_pushliteral(L, "stack traceback:"); 381 | while (lua_getstack(L1, level++, &ar)) { 382 | if (level == mark) { /* too many levels? */ 383 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ 384 | level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */ 385 | } 386 | else { 387 | lua_getinfo(L1, "Slnt", &ar); 388 | lua_pushfstring(L, "\n\t%s:", ar.short_src); 389 | if (ar.currentline > 0) 390 | lua_pushfstring(L, "%d:", ar.currentline); 391 | lua_pushliteral(L, " in "); 392 | compat53_pushfuncname(L, &ar); 393 | lua_concat(L, lua_gettop(L) - top); 394 | } 395 | } 396 | lua_concat(L, lua_gettop(L) - top); 397 | } 398 | 399 | 400 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { 401 | const char *serr = NULL; 402 | int en = errno; /* calls to Lua API may change this value */ 403 | char buf[512] = { 0 }; 404 | if (stat) { 405 | lua_pushboolean(L, 1); 406 | return 1; 407 | } 408 | else { 409 | lua_pushnil(L); 410 | serr = compat53_strerror(en, buf, sizeof(buf)); 411 | if (fname) 412 | lua_pushfstring(L, "%s: %s", fname, serr); 413 | else 414 | lua_pushstring(L, serr); 415 | lua_pushnumber(L, (lua_Number)en); 416 | return 3; 417 | } 418 | } 419 | 420 | 421 | static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) { 422 | if (mode && strchr(mode, modename[0]) == NULL) { 423 | lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode); 424 | return err; 425 | } 426 | return LUA_OK; 427 | } 428 | 429 | 430 | typedef struct { 431 | lua_Reader reader; 432 | void *ud; 433 | int has_peeked_data; 434 | const char *peeked_data; 435 | size_t peeked_data_size; 436 | } compat53_reader_data; 437 | 438 | 439 | static const char *compat53_reader (lua_State *L, void *ud, size_t *size) { 440 | compat53_reader_data *data = (compat53_reader_data *)ud; 441 | if (data->has_peeked_data) { 442 | data->has_peeked_data = 0; 443 | *size = data->peeked_data_size; 444 | return data->peeked_data; 445 | } else 446 | return data->reader(L, data->ud, size); 447 | } 448 | 449 | 450 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) { 451 | int status = LUA_OK; 452 | compat53_reader_data compat53_data = { 0, NULL, 1, 0, 0 }; 453 | compat53_data.reader = reader; 454 | compat53_data.ud = data; 455 | compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); 456 | if (compat53_data.peeked_data && compat53_data.peeked_data_size && 457 | compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ 458 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); 459 | else 460 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); 461 | if (status != LUA_OK) 462 | return status; 463 | /* we need to call the original 5.1 version of lua_load! */ 464 | #undef lua_load 465 | return lua_load(L, compat53_reader, &compat53_data, source); 466 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) 467 | } 468 | 469 | 470 | typedef struct { 471 | int n; /* number of pre-read characters */ 472 | FILE *f; /* file being read */ 473 | char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ 474 | } compat53_LoadF; 475 | 476 | 477 | static const char *compat53_getF (lua_State *L, void *ud, size_t *size) { 478 | compat53_LoadF *lf = (compat53_LoadF *)ud; 479 | (void)L; /* not used */ 480 | if (lf->n > 0) { /* are there pre-read characters to be read? */ 481 | *size = lf->n; /* return them (chars already in buffer) */ 482 | lf->n = 0; /* no more pre-read characters */ 483 | } 484 | else { /* read a block from file */ 485 | /* 'fread' can return > 0 *and* set the EOF flag. If next call to 486 | 'compat53_getF' called 'fread', it might still wait for user input. 487 | The next check avoids this problem. */ 488 | if (feof(lf->f)) return NULL; 489 | *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ 490 | } 491 | return lf->buff; 492 | } 493 | 494 | 495 | static int compat53_errfile (lua_State *L, const char *what, int fnameindex) { 496 | char buf[512] = {0}; 497 | const char *serr = compat53_strerror(errno, buf, sizeof(buf)); 498 | const char *filename = lua_tostring(L, fnameindex) + 1; 499 | lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); 500 | lua_remove(L, fnameindex); 501 | return LUA_ERRFILE; 502 | } 503 | 504 | 505 | static int compat53_skipBOM (compat53_LoadF *lf) { 506 | const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ 507 | int c; 508 | lf->n = 0; 509 | do { 510 | c = getc(lf->f); 511 | if (c == EOF || c != *(const unsigned char *)p++) return c; 512 | lf->buff[lf->n++] = (char)c; /* to be read by the parser */ 513 | } while (*p != '\0'); 514 | lf->n = 0; /* prefix matched; discard it */ 515 | return getc(lf->f); /* return next character */ 516 | } 517 | 518 | 519 | /* 520 | ** reads the first character of file 'f' and skips an optional BOM mark 521 | ** in its beginning plus its first line if it starts with '#'. Returns 522 | ** true if it skipped the first line. In any case, '*cp' has the 523 | ** first "valid" character of the file (after the optional BOM and 524 | ** a first-line comment). 525 | */ 526 | static int compat53_skipcomment (compat53_LoadF *lf, int *cp) { 527 | int c = *cp = compat53_skipBOM(lf); 528 | if (c == '#') { /* first line is a comment (Unix exec. file)? */ 529 | do { /* skip first line */ 530 | c = getc(lf->f); 531 | } while (c != EOF && c != '\n'); 532 | *cp = getc(lf->f); /* skip end-of-line, if present */ 533 | return 1; /* there was a comment */ 534 | } 535 | else return 0; /* no comment */ 536 | } 537 | 538 | 539 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { 540 | compat53_LoadF lf; 541 | int status, readstatus; 542 | int c; 543 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ 544 | if (filename == NULL) { 545 | lua_pushliteral(L, "=stdin"); 546 | lf.f = stdin; 547 | } 548 | else { 549 | lua_pushfstring(L, "@%s", filename); 550 | #if defined(_MSC_VER) 551 | /* This code is here to stop a deprecation error that stops builds 552 | * if a certain macro is defined. While normally not caring would 553 | * be best, some header-only libraries and builds can't afford to 554 | * dictate this to the user. A quick check shows that fopen_s this 555 | * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, 556 | * possibly even before that so we don't need to do any version 557 | * number checks, since this has been there since forever. */ 558 | 559 | /* TO USER: if you want the behavior of typical fopen_s/fopen, 560 | * which does lock the file on VC++, define the macro used below to 0 */ 561 | #if COMPAT53_FOPEN_NO_LOCK 562 | lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ 563 | if (lf.f == NULL) 564 | return compat53_errfile(L, "open", fnameindex); 565 | #else /* use default locking version */ 566 | if (fopen_s(&lf.f, filename, "r") != 0) 567 | return compat53_errfile(L, "open", fnameindex); 568 | #endif /* Locking vs. No-locking fopen variants */ 569 | #else 570 | lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ 571 | if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex); 572 | #endif 573 | } 574 | if (compat53_skipcomment(&lf, &c)) /* read initial portion */ 575 | lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ 576 | if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ 577 | #if defined(_MSC_VER) 578 | if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) 579 | return compat53_errfile(L, "reopen", fnameindex); 580 | #else 581 | lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ 582 | if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); 583 | #endif 584 | compat53_skipcomment(&lf, &c); /* re-read initial portion */ 585 | } 586 | if (c != EOF) 587 | lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */ 588 | status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); 589 | readstatus = ferror(lf.f); 590 | if (filename) fclose(lf.f); /* close file (even in case of errors) */ 591 | if (readstatus) { 592 | lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ 593 | return compat53_errfile(L, "read", fnameindex); 594 | } 595 | lua_remove(L, fnameindex); 596 | return status; 597 | } 598 | 599 | 600 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { 601 | int status = LUA_OK; 602 | if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { 603 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); 604 | } 605 | else { 606 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); 607 | } 608 | if (status != LUA_OK) 609 | return status; 610 | return luaL_loadbuffer(L, buff, sz, name); 611 | } 612 | 613 | 614 | #if !defined(l_inspectstat) && \ 615 | (defined(unix) || defined(__unix) || defined(__unix__) || \ 616 | defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ 617 | (defined(__APPLE__) && defined(__MACH__))) 618 | /* some form of unix; check feature macros in unistd.h for details */ 619 | # include 620 | /* check posix version; the relevant include files and macros probably 621 | * were available before 2001, but I'm not sure */ 622 | # if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L 623 | # include 624 | # define l_inspectstat(stat,what) \ 625 | if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ 626 | else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } 627 | # endif 628 | #endif 629 | 630 | /* provide default (no-op) version */ 631 | #if !defined(l_inspectstat) 632 | # define l_inspectstat(stat,what) ((void)0) 633 | #endif 634 | 635 | 636 | COMPAT53_API int luaL_execresult (lua_State *L, int stat) { 637 | const char *what = "exit"; 638 | if (stat == -1) 639 | return luaL_fileresult(L, 0, NULL); 640 | else { 641 | l_inspectstat(stat, what); 642 | if (*what == 'e' && stat == 0) 643 | lua_pushboolean(L, 1); 644 | else 645 | lua_pushnil(L); 646 | lua_pushstring(L, what); 647 | lua_pushinteger(L, stat); 648 | return 3; 649 | } 650 | } 651 | 652 | 653 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) { 654 | /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ 655 | B->b.p = NULL; 656 | B->b.L = NULL; 657 | B->b.lvl = 0; 658 | /* reuse the buffer from the 5.1-style luaL_Buffer though! */ 659 | B->ptr = B->b.buffer; 660 | B->capacity = LUAL_BUFFERSIZE; 661 | B->nelems = 0; 662 | B->L2 = L; 663 | } 664 | 665 | 666 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) { 667 | if (B->capacity - B->nelems < s) { /* needs to grow */ 668 | char* newptr = NULL; 669 | size_t newcap = B->capacity * 2; 670 | if (newcap - B->nelems < s) 671 | newcap = B->nelems + s; 672 | if (newcap < B->capacity) /* overflow */ 673 | luaL_error(B->L2, "buffer too large"); 674 | newptr = (char*)lua_newuserdata(B->L2, newcap); 675 | memcpy(newptr, B->ptr, B->nelems); 676 | if (B->ptr != B->b.buffer) 677 | lua_replace(B->L2, -2); /* remove old buffer */ 678 | B->ptr = newptr; 679 | B->capacity = newcap; 680 | } 681 | return B->ptr+B->nelems; 682 | } 683 | 684 | 685 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) { 686 | memcpy(luaL_prepbuffsize(B, l), s, l); 687 | luaL_addsize(B, l); 688 | } 689 | 690 | 691 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) { 692 | size_t len = 0; 693 | const char *s = lua_tolstring(B->L2, -1, &len); 694 | if (!s) 695 | luaL_error(B->L2, "cannot convert value to string"); 696 | if (B->ptr != B->b.buffer) 697 | lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ 698 | luaL_addlstring(B, s, len); 699 | lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); 700 | } 701 | 702 | 703 | void luaL_pushresult (luaL_Buffer_53 *B) { 704 | lua_pushlstring(B->L2, B->ptr, B->nelems); 705 | if (B->ptr != B->b.buffer) 706 | lua_replace(B->L2, -2); /* remove userdata buffer */ 707 | } 708 | 709 | 710 | #endif /* Lua 5.1 */ 711 | 712 | 713 | 714 | /* definitions for Lua 5.1 and Lua 5.2 */ 715 | #if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502 716 | 717 | 718 | COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) { 719 | index = lua_absindex(L, index); 720 | lua_pushinteger(L, i); 721 | lua_gettable(L, index); 722 | return lua_type(L, -1); 723 | } 724 | 725 | 726 | #ifndef LUA_EXTRASPACE 727 | #define LUA_EXTRASPACE (sizeof(void*)) 728 | #endif 729 | 730 | COMPAT53_API void *lua_getextraspace (lua_State *L) { 731 | int is_main = 0; 732 | void *ptr = NULL; 733 | luaL_checkstack(L, 4, "not enough stack slots available"); 734 | lua_pushliteral(L, "__compat53_extraspace"); 735 | lua_pushvalue(L, -1); 736 | lua_rawget(L, LUA_REGISTRYINDEX); 737 | if (!lua_istable(L, -1)) { 738 | lua_pop(L, 1); 739 | lua_createtable(L, 0, 2); 740 | lua_createtable(L, 0, 1); 741 | lua_pushliteral(L, "k"); 742 | lua_setfield(L, -2, "__mode"); 743 | lua_setmetatable(L, -2); 744 | lua_pushvalue(L, -2); 745 | lua_pushvalue(L, -2); 746 | lua_rawset(L, LUA_REGISTRYINDEX); 747 | } 748 | lua_replace(L, -2); 749 | is_main = lua_pushthread(L); 750 | lua_rawget(L, -2); 751 | ptr = lua_touserdata(L, -1); 752 | if (!ptr) { 753 | lua_pop(L, 1); 754 | ptr = lua_newuserdata(L, LUA_EXTRASPACE); 755 | if (is_main) { 756 | memset(ptr, '\0', LUA_EXTRASPACE); 757 | lua_pushthread(L); 758 | lua_pushvalue(L, -2); 759 | lua_rawset(L, -4); 760 | lua_pushboolean(L, 1); 761 | lua_pushvalue(L, -2); 762 | lua_rawset(L, -4); 763 | } else { 764 | void* mptr = NULL; 765 | lua_pushboolean(L, 1); 766 | lua_rawget(L, -3); 767 | mptr = lua_touserdata(L, -1); 768 | if (mptr) 769 | memcpy(ptr, mptr, LUA_EXTRASPACE); 770 | else 771 | memset(ptr, '\0', LUA_EXTRASPACE); 772 | lua_pop(L, 1); 773 | lua_pushthread(L); 774 | lua_pushvalue(L, -2); 775 | lua_rawset(L, -4); 776 | } 777 | } 778 | lua_pop(L, 2); 779 | return ptr; 780 | } 781 | 782 | 783 | COMPAT53_API int lua_isinteger (lua_State *L, int index) { 784 | if (lua_type(L, index) == LUA_TNUMBER) { 785 | lua_Number n = lua_tonumber(L, index); 786 | lua_Integer i = lua_tointeger(L, index); 787 | if (i == n) 788 | return 1; 789 | } 790 | return 0; 791 | } 792 | 793 | 794 | COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) { 795 | int ok = 0; 796 | lua_Number n = lua_tonumberx(L, i, &ok); 797 | if (ok) { 798 | if (n == (lua_Integer)n) { 799 | if (isnum) 800 | *isnum = 1; 801 | return (lua_Integer)n; 802 | } 803 | } 804 | if (isnum) 805 | *isnum = 0; 806 | return 0; 807 | } 808 | 809 | 810 | static void compat53_reverse (lua_State *L, int a, int b) { 811 | for (; a < b; ++a, --b) { 812 | lua_pushvalue(L, a); 813 | lua_pushvalue(L, b); 814 | lua_replace(L, a); 815 | lua_replace(L, b); 816 | } 817 | } 818 | 819 | 820 | COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) { 821 | int n_elems = 0; 822 | idx = lua_absindex(L, idx); 823 | n_elems = lua_gettop(L)-idx+1; 824 | if (n < 0) 825 | n += n_elems; 826 | if ( n > 0 && n < n_elems) { 827 | luaL_checkstack(L, 2, "not enough stack slots available"); 828 | n = n_elems - n; 829 | compat53_reverse(L, idx, idx+n-1); 830 | compat53_reverse(L, idx+n, idx+n_elems-1); 831 | compat53_reverse(L, idx, idx+n_elems-1); 832 | } 833 | } 834 | 835 | 836 | COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) { 837 | luaL_checkstack(L, 1, "not enough stack slots available"); 838 | index = lua_absindex(L, index); 839 | lua_pushinteger(L, i); 840 | lua_insert(L, -2); 841 | lua_settable(L, index); 842 | } 843 | 844 | 845 | #if !defined(lua_str2number) 846 | # define lua_str2number(s, p) strtod((s), (p)) 847 | #endif 848 | 849 | COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) { 850 | char* endptr; 851 | lua_Number n = lua_str2number(s, &endptr); 852 | if (endptr != s) { 853 | while (*endptr != '\0' && isspace((unsigned char)*endptr)) 854 | ++endptr; 855 | if (*endptr == '\0') { 856 | lua_pushnumber(L, n); 857 | return endptr - s + 1; 858 | } 859 | } 860 | return 0; 861 | } 862 | 863 | 864 | COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { 865 | if (!luaL_callmeta(L, idx, "__tostring")) { 866 | int t = lua_type(L, idx), tt = 0; 867 | char const* name = NULL; 868 | switch (t) { 869 | case LUA_TNIL: 870 | lua_pushliteral(L, "nil"); 871 | break; 872 | case LUA_TSTRING: 873 | case LUA_TNUMBER: 874 | lua_pushvalue(L, idx); 875 | break; 876 | case LUA_TBOOLEAN: 877 | if (lua_toboolean(L, idx)) 878 | lua_pushliteral(L, "true"); 879 | else 880 | lua_pushliteral(L, "false"); 881 | break; 882 | default: 883 | tt = luaL_getmetafield(L, idx, "__name"); 884 | name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t); 885 | lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx)); 886 | if (tt != LUA_TNIL) 887 | lua_replace(L, -2); 888 | break; 889 | } 890 | } else { 891 | if (!lua_isstring(L, -1)) 892 | luaL_error(L, "'__tostring' must return a string"); 893 | } 894 | return lua_tolstring(L, -1, len); 895 | } 896 | 897 | 898 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, 899 | lua_CFunction openf, int glb) { 900 | luaL_checkstack(L, 3, "not enough stack slots available"); 901 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); 902 | if (lua_getfield(L, -1, modname) == LUA_TNIL) { 903 | lua_pop(L, 1); 904 | lua_pushcfunction(L, openf); 905 | lua_pushstring(L, modname); 906 | lua_call(L, 1, 1); 907 | lua_pushvalue(L, -1); 908 | lua_setfield(L, -3, modname); 909 | } 910 | if (glb) { 911 | lua_pushvalue(L, -1); 912 | lua_setglobal(L, modname); 913 | } 914 | lua_replace(L, -2); 915 | } 916 | 917 | 918 | #endif /* Lua 5.1 and 5.2 */ 919 | 920 | 921 | #endif /* COMPAT53_C_ */ 922 | 923 | 924 | /********************************************************************* 925 | * This file contains parts of Lua 5.2's and Lua 5.3's source code: 926 | * 927 | * Copyright (C) 1994-2014 Lua.org, PUC-Rio. 928 | * 929 | * Permission is hereby granted, free of charge, to any person obtaining 930 | * a copy of this software and associated documentation files (the 931 | * "Software"), to deal in the Software without restriction, including 932 | * without limitation the rights to use, copy, modify, merge, publish, 933 | * distribute, sublicense, and/or sell copies of the Software, and to 934 | * permit persons to whom the Software is furnished to do so, subject to 935 | * the following conditions: 936 | * 937 | * The above copyright notice and this permission notice shall be 938 | * included in all copies or substantial portions of the Software. 939 | * 940 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 941 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 942 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 943 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 944 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 945 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 946 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 947 | *********************************************************************/ 948 | 949 | -------------------------------------------------------------------------------- /src/compat-5.3.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPAT53_H_ 2 | #define COMPAT53_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) 8 | extern "C" { 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) 14 | } 15 | #endif 16 | 17 | 18 | #undef COMPAT53_INCLUDE_SOURCE 19 | #if defined(COMPAT53_PREFIX) 20 | /* - change the symbol names of functions to avoid linker conflicts 21 | * - compat-5.3.c needs to be compiled (and linked) separately 22 | */ 23 | # if !defined(COMPAT53_API) 24 | # define COMPAT53_API extern 25 | # endif 26 | #else /* COMPAT53_PREFIX */ 27 | /* - make all functions static and include the source. 28 | * - compat-5.3.c doesn't need to be compiled (and linked) separately 29 | */ 30 | # define COMPAT53_PREFIX compat53 31 | # undef COMPAT53_API 32 | # if defined(__GNUC__) || defined(__clang__) 33 | # define COMPAT53_API __attribute__((__unused__)) static 34 | # else 35 | # define COMPAT53_API static 36 | # endif 37 | # define COMPAT53_INCLUDE_SOURCE 38 | #endif /* COMPAT53_PREFIX */ 39 | 40 | #define COMPAT53_CONCAT_HELPER(a, b) a##b 41 | #define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b) 42 | 43 | 44 | 45 | /* declarations for Lua 5.1 */ 46 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 47 | 48 | /* XXX not implemented: 49 | * lua_arith (new operators) 50 | * lua_upvalueid 51 | * lua_upvaluejoin 52 | * lua_version 53 | * lua_yieldk 54 | */ 55 | 56 | #ifndef LUA_OK 57 | # define LUA_OK 0 58 | #endif 59 | #ifndef LUA_OPADD 60 | # define LUA_OPADD 0 61 | #endif 62 | #ifndef LUA_OPSUB 63 | # define LUA_OPSUB 1 64 | #endif 65 | #ifndef LUA_OPMUL 66 | # define LUA_OPMUL 2 67 | #endif 68 | #ifndef LUA_OPDIV 69 | # define LUA_OPDIV 3 70 | #endif 71 | #ifndef LUA_OPMOD 72 | # define LUA_OPMOD 4 73 | #endif 74 | #ifndef LUA_OPPOW 75 | # define LUA_OPPOW 5 76 | #endif 77 | #ifndef LUA_OPUNM 78 | # define LUA_OPUNM 6 79 | #endif 80 | #ifndef LUA_OPEQ 81 | # define LUA_OPEQ 0 82 | #endif 83 | #ifndef LUA_OPLT 84 | # define LUA_OPLT 1 85 | #endif 86 | #ifndef LUA_OPLE 87 | # define LUA_OPLE 2 88 | #endif 89 | 90 | /* LuaJIT/Lua 5.1 does not have the updated 91 | * error codes for thread status/function returns (but some patched versions do) 92 | * define it only if it's not found 93 | */ 94 | #if !defined(LUA_ERRGCMM) 95 | /* Use + 2 because in some versions of Lua (Lua 5.1) 96 | * LUA_ERRFILE is defined as (LUA_ERRERR+1) 97 | * so we need to avoid it (LuaJIT might have something at this 98 | * integer value too) 99 | */ 100 | # define LUA_ERRGCMM (LUA_ERRERR + 2) 101 | #endif /* LUA_ERRGCMM define */ 102 | 103 | typedef size_t lua_Unsigned; 104 | 105 | typedef struct luaL_Buffer_53 { 106 | luaL_Buffer b; /* make incorrect code crash! */ 107 | char *ptr; 108 | size_t nelems; 109 | size_t capacity; 110 | lua_State *L2; 111 | } luaL_Buffer_53; 112 | #define luaL_Buffer luaL_Buffer_53 113 | 114 | /* In PUC-Rio 5.1, userdata is a simple FILE* 115 | * In LuaJIT, it's a struct where the first member is a FILE* 116 | * We can't support the `closef` member 117 | */ 118 | typedef struct luaL_Stream { 119 | FILE *f; 120 | } luaL_Stream; 121 | 122 | #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) 123 | COMPAT53_API int lua_absindex (lua_State *L, int i); 124 | 125 | #define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) 126 | COMPAT53_API void lua_arith (lua_State *L, int op); 127 | 128 | #define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) 129 | COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op); 130 | 131 | #define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) 132 | COMPAT53_API void lua_copy (lua_State *L, int from, int to); 133 | 134 | #define lua_getuservalue(L, i) \ 135 | (lua_getfenv((L), (i)), lua_type((L), -1)) 136 | #define lua_setuservalue(L, i) \ 137 | (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i))) 138 | 139 | #define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len) 140 | COMPAT53_API void lua_len (lua_State *L, int i); 141 | 142 | #define lua_pushstring(L, s) \ 143 | (lua_pushstring((L), (s)), lua_tostring((L), -1)) 144 | 145 | #define lua_pushlstring(L, s, len) \ 146 | ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1)) 147 | 148 | #ifndef luaL_newlibtable 149 | # define luaL_newlibtable(L, l) \ 150 | (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1)) 151 | #endif 152 | #ifndef luaL_newlib 153 | # define luaL_newlib(L, l) \ 154 | (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l))) 155 | #endif 156 | 157 | #define lua_pushglobaltable(L) \ 158 | lua_pushvalue((L), LUA_GLOBALSINDEX) 159 | 160 | #define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp) 161 | COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p); 162 | 163 | #define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp) 164 | COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p); 165 | 166 | #define lua_rawlen(L, i) lua_objlen((L), (i)) 167 | 168 | #define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL) 169 | 170 | #define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx) 171 | COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); 172 | 173 | #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) 174 | COMPAT53_API void luaL_checkversion (lua_State *L); 175 | 176 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) 177 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); 178 | 179 | #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) 180 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); 181 | 182 | #define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx) 183 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); 184 | 185 | #define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) 186 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg); 187 | 188 | #define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable) 189 | COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name); 190 | 191 | #define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len) 192 | COMPAT53_API lua_Integer luaL_len (lua_State *L, int i); 193 | 194 | #define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs) 195 | COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); 196 | 197 | #define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable) 198 | COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname); 199 | 200 | #define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata) 201 | COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname); 202 | 203 | #define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback) 204 | COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level); 205 | 206 | #define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult) 207 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname); 208 | 209 | #define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult) 210 | COMPAT53_API int luaL_execresult (lua_State *L, int stat); 211 | 212 | #define lua_callk(L, na, nr, ctx, cont) \ 213 | ((void)(ctx), (void)(cont), lua_call((L), (na), (nr))) 214 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ 215 | ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err))) 216 | 217 | #define lua_resume(L, from, nargs) \ 218 | ((void)(from), lua_resume((L), (nargs))) 219 | 220 | #define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) 221 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B); 222 | 223 | #define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) 224 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s); 225 | 226 | #define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) 227 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l); 228 | 229 | #define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) 230 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B); 231 | 232 | #define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) 233 | COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B); 234 | 235 | #undef luaL_buffinitsize 236 | #define luaL_buffinitsize(L, B, s) \ 237 | (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s))) 238 | 239 | #undef luaL_prepbuffer 240 | #define luaL_prepbuffer(B) \ 241 | luaL_prepbuffsize((B), LUAL_BUFFERSIZE) 242 | 243 | #undef luaL_addchar 244 | #define luaL_addchar(B, c) \ 245 | ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \ 246 | ((B)->ptr[(B)->nelems++] = (c))) 247 | 248 | #undef luaL_addsize 249 | #define luaL_addsize(B, s) \ 250 | ((B)->nelems += (s)) 251 | 252 | #undef luaL_addstring 253 | #define luaL_addstring(B, s) \ 254 | luaL_addlstring((B), (s), strlen((s))) 255 | 256 | #undef luaL_pushresultsize 257 | #define luaL_pushresultsize(B, s) \ 258 | (luaL_addsize((B), (s)), luaL_pushresult((B))) 259 | 260 | #if defined(LUA_COMPAT_APIINTCASTS) 261 | #define lua_pushunsigned(L, n) \ 262 | lua_pushinteger((L), (lua_Integer)(n)) 263 | #define lua_tounsignedx(L, i, is) \ 264 | ((lua_Unsigned)lua_tointegerx((L), (i), (is))) 265 | #define lua_tounsigned(L, i) \ 266 | lua_tounsignedx((L), (i), NULL) 267 | #define luaL_checkunsigned(L, a) \ 268 | ((lua_Unsigned)luaL_checkinteger((L), (a))) 269 | #define luaL_optunsigned(L, a, d) \ 270 | ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d))) 271 | #endif 272 | 273 | #endif /* Lua 5.1 only */ 274 | 275 | 276 | 277 | /* declarations for Lua 5.1 and 5.2 */ 278 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 279 | 280 | typedef int lua_KContext; 281 | 282 | typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); 283 | 284 | #define lua_dump(L, w, d, s) \ 285 | ((void)(s), lua_dump((L), (w), (d))) 286 | 287 | #define lua_getfield(L, i, k) \ 288 | (lua_getfield((L), (i), (k)), lua_type((L), -1)) 289 | 290 | #define lua_gettable(L, i) \ 291 | (lua_gettable((L), (i)), lua_type((L), -1)) 292 | 293 | #define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) 294 | COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i); 295 | 296 | #define lua_getextraspace COMPAT53_CONCAT(COMPAT53_PREFIX, _getextraspace) 297 | COMPAT53_API void *lua_getextraspace (lua_State *L); 298 | 299 | #define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) 300 | COMPAT53_API int lua_isinteger (lua_State *L, int index); 301 | 302 | #define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53) 303 | COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum); 304 | 305 | #define lua_numbertointeger(n, p) \ 306 | ((*(p) = (lua_Integer)(n)), 1) 307 | 308 | #define lua_rawget(L, i) \ 309 | (lua_rawget((L), (i)), lua_type((L), -1)) 310 | 311 | #define lua_rawgeti(L, i, n) \ 312 | (lua_rawgeti((L), (i), (n)), lua_type((L), -1)) 313 | 314 | #define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate) 315 | COMPAT53_API void lua_rotate (lua_State *L, int idx, int n); 316 | 317 | #define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti) 318 | COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i); 319 | 320 | #define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber) 321 | COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s); 322 | 323 | #define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring) 324 | COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len); 325 | 326 | #define luaL_getmetafield(L, o, e) \ 327 | (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL) 328 | 329 | #define luaL_newmetatable(L, tn) \ 330 | (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0) 331 | 332 | #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) 333 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, 334 | lua_CFunction openf, int glb ); 335 | 336 | #endif /* Lua 5.1 and Lua 5.2 */ 337 | 338 | 339 | 340 | /* declarations for Lua 5.2 */ 341 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502 342 | 343 | /* XXX not implemented: 344 | * lua_isyieldable 345 | * lua_arith (new operators) 346 | * lua_pushfstring (new formats) 347 | */ 348 | 349 | #define lua_getglobal(L, n) \ 350 | (lua_getglobal((L), (n)), lua_type((L), -1)) 351 | 352 | #define lua_getuservalue(L, i) \ 353 | (lua_getuservalue((L), (i)), lua_type((L), -1)) 354 | 355 | #define lua_pushlstring(L, s, len) \ 356 | (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))) 357 | 358 | #define lua_rawgetp(L, i, p) \ 359 | (lua_rawgetp((L), (i), (p)), lua_type((L), -1)) 360 | 361 | #define LUA_KFUNCTION(_name) \ 362 | static int (_name)(lua_State *L, int status, lua_KContext ctx); \ 363 | static int (_name ## _52)(lua_State *L) { \ 364 | lua_KContext ctx; \ 365 | int status = lua_getctx(L, &ctx); \ 366 | return (_name)(L, status, ctx); \ 367 | } \ 368 | static int (_name)(lua_State *L, int status, lua_KContext ctx) 369 | 370 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ 371 | lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52) 372 | 373 | #define lua_callk(L, na, nr, ctx, cont) \ 374 | lua_callk((L), (na), (nr), (ctx), cont ## _52) 375 | 376 | #define lua_yieldk(L, nr, ctx, cont) \ 377 | lua_yieldk((L), (nr), (ctx), cont ## _52) 378 | 379 | #ifdef lua_call 380 | # undef lua_call 381 | # define lua_call(L, na, nr) \ 382 | (lua_callk)((L), (na), (nr), 0, NULL) 383 | #endif 384 | 385 | #ifdef lua_pcall 386 | # undef lua_pcall 387 | # define lua_pcall(L, na, nr, err) \ 388 | (lua_pcallk)((L), (na), (nr), (err), 0, NULL) 389 | #endif 390 | 391 | #ifdef lua_yield 392 | # undef lua_yield 393 | # define lua_yield(L, nr) \ 394 | (lua_yieldk)((L), (nr), 0, NULL) 395 | #endif 396 | 397 | #endif /* Lua 5.2 only */ 398 | 399 | 400 | 401 | /* other Lua versions */ 402 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504 403 | //@@ #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 503 404 | 405 | # error "unsupported Lua version (i.e. not Lua 5.1, 5.2, or 5.3)" 406 | 407 | #endif /* other Lua versions except 5.1, 5.2, and 5.3 */ 408 | 409 | 410 | 411 | /* helper macro for defining continuation functions (for every version 412 | * *except* Lua 5.2) */ 413 | #ifndef LUA_KFUNCTION 414 | #define LUA_KFUNCTION(_name) \ 415 | static int (_name)(lua_State *L, int status, lua_KContext ctx) 416 | #endif 417 | 418 | 419 | #if defined(COMPAT53_INCLUDE_SOURCE) 420 | # include "compat-5.3.c" 421 | #endif 422 | 423 | 424 | #endif /* COMPAT53_H_ */ 425 | 426 | -------------------------------------------------------------------------------- /src/include/stb_perlin.h: -------------------------------------------------------------------------------- 1 | // stb_perlin.h - v0.5 - perlin noise 2 | // public domain single-file C implementation by Sean Barrett 3 | // 4 | // LICENSE 5 | // 6 | // See end of file. 7 | // 8 | // 9 | // to create the implementation, 10 | // #define STB_PERLIN_IMPLEMENTATION 11 | // in *one* C/CPP file that includes this file. 12 | // 13 | // 14 | // Documentation: 15 | // 16 | // float stb_perlin_noise3( float x, 17 | // float y, 18 | // float z, 19 | // int x_wrap=0, 20 | // int y_wrap=0, 21 | // int z_wrap=0) 22 | // 23 | // This function computes a random value at the coordinate (x,y,z). 24 | // Adjacent random values are continuous but the noise fluctuates 25 | // its randomness with period 1, i.e. takes on wholly unrelated values 26 | // at integer points. Specifically, this implements Ken Perlin's 27 | // revised noise function from 2002. 28 | // 29 | // The "wrap" parameters can be used to create wraparound noise that 30 | // wraps at powers of two. The numbers MUST be powers of two. Specify 31 | // 0 to mean "don't care". (The noise always wraps every 256 due 32 | // details of the implementation, even if you ask for larger or no 33 | // wrapping.) 34 | // 35 | // float stb_perlin_noise3_seed( float x, 36 | // float y, 37 | // float z, 38 | // int x_wrap=0, 39 | // int y_wrap=0, 40 | // int z_wrap=0, 41 | // int seed) 42 | // 43 | // As above, but 'seed' selects from multiple different variations of the 44 | // noise function. The current implementation only uses the bottom 8 bits 45 | // of 'seed', but possibly in the future more bits will be used. 46 | // 47 | // 48 | // Fractal Noise: 49 | // 50 | // Three common fractal noise functions are included, which produce 51 | // a wide variety of nice effects depending on the parameters 52 | // provided. Note that each function will call stb_perlin_noise3 53 | // 'octaves' times, so this parameter will affect runtime. 54 | // 55 | // float stb_perlin_ridge_noise3(float x, float y, float z, 56 | // float lacunarity, float gain, float offset, int octaves) 57 | // 58 | // float stb_perlin_fbm_noise3(float x, float y, float z, 59 | // float lacunarity, float gain, int octaves) 60 | // 61 | // float stb_perlin_turbulence_noise3(float x, float y, float z, 62 | // float lacunarity, float gain, int octaves) 63 | // 64 | // Typical values to start playing with: 65 | // octaves = 6 -- number of "octaves" of noise3() to sum 66 | // lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) 67 | // gain = 0.5 -- relative weighting applied to each successive octave 68 | // offset = 1.0? -- used to invert the ridges, may need to be larger, not sure 69 | // 70 | // 71 | // Contributors: 72 | // Jack Mott - additional noise functions 73 | // Jordan Peck - seeded noise 74 | // 75 | 76 | 77 | #ifdef __cplusplus 78 | extern "C" { 79 | #endif 80 | extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); 81 | extern float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed); 82 | extern float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves); 83 | extern float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); 84 | extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); 85 | extern float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed); 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | #ifdef STB_PERLIN_IMPLEMENTATION 91 | 92 | #include // fabs() 93 | 94 | // not same permutation table as Perlin's reference to avoid copyright issues; 95 | // Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ 96 | static unsigned char stb__perlin_randtab[512] = 97 | { 98 | 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, 99 | 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, 100 | 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, 101 | 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, 102 | 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, 103 | 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, 104 | 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, 105 | 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, 106 | 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, 107 | 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, 108 | 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, 109 | 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, 110 | 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, 111 | 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, 112 | 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, 113 | 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, 114 | 115 | // and a second copy so we don't need an extra mask or static initializer 116 | 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, 117 | 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, 118 | 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, 119 | 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, 120 | 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, 121 | 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, 122 | 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, 123 | 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, 124 | 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, 125 | 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, 126 | 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, 127 | 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, 128 | 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, 129 | 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, 130 | 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, 131 | 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, 132 | }; 133 | 134 | 135 | // perlin's gradient has 12 cases so some get used 1/16th of the time 136 | // and some 2/16ths. We reduce bias by changing those fractions 137 | // to 5/64ths and 6/64ths 138 | 139 | // this array is designed to match the previous implementation 140 | // of gradient hash: indices[stb__perlin_randtab[i]&63] 141 | static unsigned char stb__perlin_randtab_grad_idx[512] = 142 | { 143 | 7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7, 144 | 8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8, 145 | 7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8, 146 | 8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5, 147 | 5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1, 148 | 2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4, 149 | 9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11, 150 | 1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6, 151 | 10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0, 152 | 6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2, 153 | 4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3, 154 | 11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11, 155 | 10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1, 156 | 3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10, 157 | 11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7, 158 | 9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5, 159 | 160 | // and a second copy so we don't need an extra mask or static initializer 161 | 7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7, 162 | 8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8, 163 | 7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8, 164 | 8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5, 165 | 5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1, 166 | 2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4, 167 | 9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11, 168 | 1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6, 169 | 10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0, 170 | 6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2, 171 | 4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3, 172 | 11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11, 173 | 10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1, 174 | 3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10, 175 | 11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7, 176 | 9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5, 177 | }; 178 | 179 | static float stb__perlin_lerp(float a, float b, float t) 180 | { 181 | return a + (b-a) * t; 182 | } 183 | 184 | static int stb__perlin_fastfloor(float a) 185 | { 186 | int ai = (int) a; 187 | return (a < ai) ? ai-1 : ai; 188 | } 189 | 190 | // different grad function from Perlin's, but easy to modify to match reference 191 | static float stb__perlin_grad(int grad_idx, float x, float y, float z) 192 | { 193 | static float basis[12][4] = 194 | { 195 | { 1, 1, 0 }, 196 | { -1, 1, 0 }, 197 | { 1,-1, 0 }, 198 | { -1,-1, 0 }, 199 | { 1, 0, 1 }, 200 | { -1, 0, 1 }, 201 | { 1, 0,-1 }, 202 | { -1, 0,-1 }, 203 | { 0, 1, 1 }, 204 | { 0,-1, 1 }, 205 | { 0, 1,-1 }, 206 | { 0,-1,-1 }, 207 | }; 208 | 209 | float *grad = basis[grad_idx]; 210 | return grad[0]*x + grad[1]*y + grad[2]*z; 211 | } 212 | 213 | float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed) 214 | { 215 | float u,v,w; 216 | float n000,n001,n010,n011,n100,n101,n110,n111; 217 | float n00,n01,n10,n11; 218 | float n0,n1; 219 | 220 | unsigned int x_mask = (x_wrap-1) & 255; 221 | unsigned int y_mask = (y_wrap-1) & 255; 222 | unsigned int z_mask = (z_wrap-1) & 255; 223 | int px = stb__perlin_fastfloor(x); 224 | int py = stb__perlin_fastfloor(y); 225 | int pz = stb__perlin_fastfloor(z); 226 | int x0 = px & x_mask, x1 = (px+1) & x_mask; 227 | int y0 = py & y_mask, y1 = (py+1) & y_mask; 228 | int z0 = pz & z_mask, z1 = (pz+1) & z_mask; 229 | int r0,r1, r00,r01,r10,r11; 230 | 231 | #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) 232 | 233 | x -= px; u = stb__perlin_ease(x); 234 | y -= py; v = stb__perlin_ease(y); 235 | z -= pz; w = stb__perlin_ease(z); 236 | 237 | r0 = stb__perlin_randtab[x0+seed]; 238 | r1 = stb__perlin_randtab[x1+seed]; 239 | 240 | r00 = stb__perlin_randtab[r0+y0]; 241 | r01 = stb__perlin_randtab[r0+y1]; 242 | r10 = stb__perlin_randtab[r1+y0]; 243 | r11 = stb__perlin_randtab[r1+y1]; 244 | 245 | n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z ); 246 | n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 ); 247 | n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z ); 248 | n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 ); 249 | n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z ); 250 | n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 ); 251 | n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z ); 252 | n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 ); 253 | 254 | n00 = stb__perlin_lerp(n000,n001,w); 255 | n01 = stb__perlin_lerp(n010,n011,w); 256 | n10 = stb__perlin_lerp(n100,n101,w); 257 | n11 = stb__perlin_lerp(n110,n111,w); 258 | 259 | n0 = stb__perlin_lerp(n00,n01,v); 260 | n1 = stb__perlin_lerp(n10,n11,v); 261 | 262 | return stb__perlin_lerp(n0,n1,u); 263 | } 264 | 265 | float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) 266 | { 267 | return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap,0); 268 | } 269 | 270 | float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed) 271 | { 272 | return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap, (unsigned char) seed); 273 | } 274 | 275 | float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves) 276 | { 277 | int i; 278 | float frequency = 1.0f; 279 | float prev = 1.0f; 280 | float amplitude = 0.5f; 281 | float sum = 0.0f; 282 | 283 | for (i = 0; i < octaves; i++) { 284 | float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i); 285 | r = offset - (float) fabs(r); 286 | r = r*r; 287 | sum += r*amplitude*prev; 288 | prev = r; 289 | frequency *= lacunarity; 290 | amplitude *= gain; 291 | } 292 | return sum; 293 | } 294 | 295 | float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves) 296 | { 297 | int i; 298 | float frequency = 1.0f; 299 | float amplitude = 1.0f; 300 | float sum = 0.0f; 301 | 302 | for (i = 0; i < octaves; i++) { 303 | sum += stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude; 304 | frequency *= lacunarity; 305 | amplitude *= gain; 306 | } 307 | return sum; 308 | } 309 | 310 | float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves) 311 | { 312 | int i; 313 | float frequency = 1.0f; 314 | float amplitude = 1.0f; 315 | float sum = 0.0f; 316 | 317 | for (i = 0; i < octaves; i++) { 318 | float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude; 319 | sum += (float) fabs(r); 320 | frequency *= lacunarity; 321 | amplitude *= gain; 322 | } 323 | return sum; 324 | } 325 | 326 | float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed) 327 | { 328 | float u,v,w; 329 | float n000,n001,n010,n011,n100,n101,n110,n111; 330 | float n00,n01,n10,n11; 331 | float n0,n1; 332 | 333 | int px = stb__perlin_fastfloor(x); 334 | int py = stb__perlin_fastfloor(y); 335 | int pz = stb__perlin_fastfloor(z); 336 | int x_wrap2 = (x_wrap ? x_wrap : 256); 337 | int y_wrap2 = (y_wrap ? y_wrap : 256); 338 | int z_wrap2 = (z_wrap ? z_wrap : 256); 339 | int x0 = px % x_wrap2, x1; 340 | int y0 = py % y_wrap2, y1; 341 | int z0 = pz % z_wrap2, z1; 342 | int r0,r1, r00,r01,r10,r11; 343 | 344 | if (x0 < 0) x0 += x_wrap2; 345 | if (y0 < 0) y0 += y_wrap2; 346 | if (z0 < 0) z0 += z_wrap2; 347 | x1 = (x0+1) % x_wrap2; 348 | y1 = (y0+1) % y_wrap2; 349 | z1 = (z0+1) % z_wrap2; 350 | 351 | #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) 352 | 353 | x -= px; u = stb__perlin_ease(x); 354 | y -= py; v = stb__perlin_ease(y); 355 | z -= pz; w = stb__perlin_ease(z); 356 | 357 | r0 = stb__perlin_randtab[x0]; 358 | r0 = stb__perlin_randtab[r0+seed]; 359 | r1 = stb__perlin_randtab[x1]; 360 | r1 = stb__perlin_randtab[r1+seed]; 361 | 362 | r00 = stb__perlin_randtab[r0+y0]; 363 | r01 = stb__perlin_randtab[r0+y1]; 364 | r10 = stb__perlin_randtab[r1+y0]; 365 | r11 = stb__perlin_randtab[r1+y1]; 366 | 367 | n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z ); 368 | n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 ); 369 | n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z ); 370 | n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 ); 371 | n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z ); 372 | n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 ); 373 | n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z ); 374 | n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 ); 375 | 376 | n00 = stb__perlin_lerp(n000,n001,w); 377 | n01 = stb__perlin_lerp(n010,n011,w); 378 | n10 = stb__perlin_lerp(n100,n101,w); 379 | n11 = stb__perlin_lerp(n110,n111,w); 380 | 381 | n0 = stb__perlin_lerp(n00,n01,v); 382 | n1 = stb__perlin_lerp(n10,n11,v); 383 | 384 | return stb__perlin_lerp(n0,n1,u); 385 | } 386 | #endif // STB_PERLIN_IMPLEMENTATION 387 | 388 | /* 389 | ------------------------------------------------------------------------------ 390 | This software is available under 2 licenses -- choose whichever you prefer. 391 | ------------------------------------------------------------------------------ 392 | ALTERNATIVE A - MIT License 393 | Copyright (c) 2017 Sean Barrett 394 | Permission is hereby granted, free of charge, to any person obtaining a copy of 395 | this software and associated documentation files (the "Software"), to deal in 396 | the Software without restriction, including without limitation the rights to 397 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 398 | of the Software, and to permit persons to whom the Software is furnished to do 399 | so, subject to the following conditions: 400 | The above copyright notice and this permission notice shall be included in all 401 | copies or substantial portions of the Software. 402 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 403 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 404 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 405 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 406 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 407 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 408 | SOFTWARE. 409 | ------------------------------------------------------------------------------ 410 | ALTERNATIVE B - Public Domain (www.unlicense.org) 411 | This is free and unencumbered software released into the public domain. 412 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 413 | software, either in source code form or as a compiled binary, for any purpose, 414 | commercial or non-commercial, and by any means. 415 | In jurisdictions that recognize copyright laws, the author or authors of this 416 | software dedicate any and all copyright interest in the software to the public 417 | domain. We make this dedication for the benefit of the public at large and to 418 | the detriment of our heirs and successors. We intend this dedication to be an 419 | overt act of relinquishment in perpetuity of all present and future rights to 420 | this software under copyright law. 421 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 422 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 423 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 424 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 425 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 426 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 427 | ------------------------------------------------------------------------------ 428 | */ 429 | -------------------------------------------------------------------------------- /src/internal.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2017 Stefano Trettel 4 | * 5 | * Software repository: MoonImage, https://github.com/stetre/moonimage 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | /******************************************************************************** 27 | * Internal common header * 28 | ********************************************************************************/ 29 | 30 | #ifndef internalDEFINED 31 | #define internalDEFINED 32 | 33 | #include 34 | #include 35 | #include 36 | #include "moonimage.h" 37 | 38 | #define TOSTR_(x) #x 39 | #define TOSTR(x) TOSTR_(x) 40 | 41 | /* Note: all the dynamic symbols of this library (should) start with 'moonimage_' . 42 | * The only exception is the luaopen_moonimage() function, which is searched for 43 | * with that name by Lua. 44 | * MoonImage's string references on the Lua registry also start with 'moonimage_'. 45 | */ 46 | 47 | #if 0 48 | /* .c */ 49 | #define moonimage_ 50 | #endif 51 | 52 | /* utils.c */ 53 | #define noprintf moonimage_noprintf 54 | int noprintf(const char *fmt, ...); 55 | #define notavailable moonimage_notavailable 56 | int notavailable(lua_State *L, ...); 57 | #define malloc_init moonimage_malloc_init 58 | void malloc_init(lua_State *L); 59 | #define Malloc moonimage_Malloc 60 | void *Malloc(lua_State *L, size_t size); 61 | #define MallocNoErr moonimage_MallocNoErr 62 | void *MallocNoErr(lua_State *L, size_t size); 63 | #define Strdup moonimage_Strdup 64 | char *Strdup(lua_State *L, const char *s); 65 | #define Free moonimage_Free 66 | void Free(lua_State *L, void *ptr); 67 | #define checkboolean moonimage_checkboolean 68 | int checkboolean(lua_State *L, int arg); 69 | #define testboolean moonimage_testboolean 70 | int testboolean(lua_State *L, int arg, int *err); 71 | #define optboolean moonimage_optboolean 72 | int optboolean(lua_State *L, int arg, int d); 73 | 74 | #define checkchannels moonimage_checkchannels 75 | int checkchannels(lua_State *L, int arg); 76 | #define optchannels moonimage_optchannels 77 | int optchannels(lua_State *L, int arg); 78 | #define pushchannels moonimage_pushchannels 79 | int pushchannels(lua_State *L, int val); 80 | #define checkchantype moonimage_checkchantype 81 | int checkchantype(lua_State *L, int arg); 82 | #define optchantype moonimage_optchantype 83 | int optchantype(lua_State *L, int arg, int defval); 84 | #define pushchantype moonimage_pushchantype 85 | int pushchantype(lua_State *L, int val); 86 | 87 | #define checkflags(L, arg) (uint32_t)luaL_checkinteger((L), (arg)) 88 | #define optflags(L, arg, defval) (uint32_t)luaL_optinteger((L), (arg), (defval)) 89 | 90 | 91 | /* Color channels. 92 | * Note that the length of the corresponding Lua literal gives the number of channels 93 | * (y = 1, ya = 2, rgb = 3, rgba = 4). 94 | */ 95 | #define CHAN_default 0 /* STBI_default */ 96 | #define CHAN_y 1 /* STBI_grey */ 97 | #define CHAN_ya 2 /* STBI_grey_alpha */ 98 | #define CHAN_rgb 3 /* STBI_rgb */ 99 | #define CHAN_rgba 4 /* STBI_rgb_alpha */ 100 | 101 | /* Color channel type. */ 102 | #define CHANTYPE_u8 0 103 | #define CHANTYPE_u16 1 104 | #define CHANTYPE_f 2 105 | /* Internal error codes */ 106 | #define ERR_NOTPRESENT 1 107 | #define ERR_SUCCESS 0 108 | #define ERR_GENERIC -1 109 | #define ERR_TYPE -2 110 | #define ERR_VALUE -3 111 | #define ERR_TABLE -4 112 | #define ERR_EMPTY -5 113 | #define ERR_MEMORY -6 114 | #define ERR_LENGTH -7 115 | #define ERR_POOL -8 116 | #define ERR_BOUNDARIES -9 117 | #define ERR_UNKNOWN -10 118 | #define errstring moonimage_errstring 119 | const char* errstring(int err); 120 | 121 | /* main.c */ 122 | int luaopen_moonimage(lua_State *L); 123 | void moonimage_open_load(lua_State *L); 124 | void moonimage_open_write(lua_State *L); 125 | void moonimage_open_perlin(lua_State *L); 126 | 127 | /*------------------------------------------------------------------------------* 128 | | Debug and other utilities | 129 | *------------------------------------------------------------------------------*/ 130 | 131 | /* If this is printed, it denotes a suspect bug: */ 132 | #define UNEXPECTED_ERROR "unexpected error (%s, %d)", __FILE__, __LINE__ 133 | 134 | #define unexpected(L) luaL_error((L), UNEXPECTED_ERROR) 135 | #define notsupported(L) luaL_error((L), "operation not supported") 136 | 137 | #define badvalue(L,s) lua_pushfstring((L), "invalid value '%s'", (s)) 138 | 139 | /* DEBUG -------------------------------------------------------- */ 140 | #if defined(DEBUG) 141 | 142 | #define DBG printf 143 | #define TR() do { printf("trace %s %d\n",__FILE__,__LINE__); } while(0) 144 | #define BK() do { printf("break %s %d\n",__FILE__,__LINE__); getchar(); } while(0) 145 | 146 | #else 147 | 148 | #define DBG noprintf 149 | #define TR() 150 | #define BK() 151 | 152 | #endif /* DEBUG ------------------------------------------------- */ 153 | 154 | 155 | #endif /* internalDEFINED */ 156 | -------------------------------------------------------------------------------- /src/load.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2017 Stefano Trettel 4 | * 5 | * Software repository: MoonImage, https://github.com/stetre/moonimage 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #define STB_IMAGE_IMPLEMENTATION 28 | #define STBI_FAILURE_USERMSG 29 | #define STB_IMAGE_STATIC 30 | #include "stb_image.h" 31 | 32 | static int Error(lua_State *L) 33 | { 34 | const char * reason = stbi_failure_reason(); /* a VERY brief reason for failure */ 35 | return luaL_error(L, (reason!=NULL) ? reason : "unknown reason"); 36 | } 37 | 38 | /* FLAGS --------------------------------------------------------------------*/ 39 | 40 | static int Reset_load_flags(lua_State *L) 41 | { 42 | (void)L; 43 | stbi_set_unpremultiply_on_load(0); 44 | stbi_convert_iphone_png_to_rgb(0); 45 | stbi_set_flip_vertically_on_load(0); 46 | return 0; 47 | } 48 | 49 | #define SET_FLAG_FUNC(Func, func) \ 50 | static int Func(lua_State *L) \ 51 | { \ 52 | stbi_##func(checkboolean(L, 1)); \ 53 | return 0; \ 54 | } 55 | 56 | SET_FLAG_FUNC(Set_unpremultiply_on_load, set_unpremultiply_on_load) 57 | SET_FLAG_FUNC(Convert_iphone_png_to_rgb, convert_iphone_png_to_rgb) 58 | SET_FLAG_FUNC(Set_flip_vertically_on_load, set_flip_vertically_on_load) 59 | 60 | #undef SET_FLAG_FUNC 61 | 62 | /*@@TODO: Image object 63 | * image = load_image(...) 64 | * Instead of passing the image data as a binary string, returns an image object 65 | * that holds the pointer to the data returned by stbi_load(). 66 | * The data is retained until the object is destroyed. 67 | * 68 | * Methods: 69 | * image:data() -> returns the data as a binary string 70 | * image:ptr() 71 | * image:size() 72 | * image:width() 73 | * image:height() 74 | * image:channels() 75 | * image:free() 76 | * 77 | * Also, make write_xxx() functions accept a image object in lieu of data,w,h. 78 | * 79 | * Advantages: when the loaded image is to be passed to a C library that accepts 80 | * (ptr, size), with this interface we can just pass the pointer from C to Lua and 81 | * from Lua to C (zero-copy). 82 | */ 83 | 84 | static int Load(lua_State *L) 85 | { 86 | int x, y, len, chansz; 87 | int channels; 88 | void *data; 89 | const char *filename = luaL_checkstring(L, 1); 90 | int desired_channels = optchannels(L, 2); 91 | int chantype = optchantype(L, 3, CHANTYPE_u8); 92 | 93 | switch(chantype) 94 | { 95 | case CHANTYPE_u8: 96 | chansz = sizeof(stbi_uc); 97 | data = stbi_load(filename, &x, &y, &channels, desired_channels); 98 | break; 99 | case CHANTYPE_u16: 100 | chansz = sizeof(stbi_us); 101 | data = stbi_load_16(filename, &x, &y, &channels, desired_channels); 102 | break; 103 | case CHANTYPE_f: 104 | chansz = sizeof(float); 105 | data = stbi_loadf(filename, &x, &y, &channels, desired_channels); 106 | break; 107 | default: 108 | return unexpected(L); 109 | } 110 | 111 | if(!data) return Error(L); 112 | channels = (desired_channels > 0) ? desired_channels : channels; 113 | len = x * y * channels * chansz; 114 | lua_pushlstring(L, (const char*)data, len); 115 | stbi_image_free((void*)data); 116 | lua_pushinteger(L, x); 117 | lua_pushinteger(L, y); 118 | pushchannels(L, channels); 119 | /* note that this function returns the used no. of channels, while stbi_load() 120 | * returns the channels in file even if it is not the used number */ 121 | return 4; 122 | } 123 | 124 | 125 | static int Set_gamma_and_scale(lua_State *L) 126 | { 127 | float gamma = luaL_checknumber(L, 1); 128 | float scale = luaL_checknumber(L, 2); 129 | stbi_hdr_to_ldr_gamma(gamma); 130 | stbi_hdr_to_ldr_scale(scale); 131 | stbi_ldr_to_hdr_gamma(gamma); 132 | stbi_ldr_to_hdr_scale(scale); 133 | return 0; 134 | } 135 | 136 | static int Gamma_and_scale(lua_State *L) 137 | { 138 | lua_pushnumber(L, stbi__l2h_gamma); 139 | lua_pushnumber(L, stbi__l2h_scale); 140 | // lua_pushnumber(L, stbi__h2l_gamma_i); 141 | // lua_pushnumber(L, stbi__h2l_scale_i); 142 | return 2; 143 | } 144 | 145 | static int Is_hdr(lua_State *L) 146 | { 147 | const char *filename = luaL_checkstring(L, 1); 148 | lua_pushboolean(L, stbi_is_hdr(filename)); 149 | return 1; 150 | } 151 | 152 | static int Info(lua_State *L) 153 | { 154 | int x, y, channels; 155 | const char *filename = luaL_checkstring(L, 1); 156 | 157 | if(!stbi_info(filename, &x, &y, &channels)) 158 | return Error(L); 159 | 160 | lua_pushinteger(L, x); 161 | lua_pushinteger(L, y); 162 | pushchannels(L, channels); 163 | return 3; 164 | } 165 | 166 | static int Reduce_to_u8(lua_State *L) 167 | { 168 | size_t len; 169 | void *inout; 170 | const char *data = luaL_checklstring(L, 1, &len); 171 | int w = luaL_checkinteger(L, 2); 172 | int h = luaL_checkinteger(L, 3); 173 | int channels = checkchannels(L, 4); 174 | int chantype = checkchantype(L, 5); 175 | 176 | switch(chantype) 177 | { 178 | case CHANTYPE_u8: 179 | lua_pushlstring(L, data, len); 180 | return 1; 181 | case CHANTYPE_u16: 182 | if(len != (size_t)(w*h*channels*sizeof(stbi_us))) 183 | return luaL_error(L, "invalid data length"); 184 | inout = STBI_MALLOC(len); 185 | memcpy(inout, data, len); 186 | inout = stbi__convert_16_to_8((stbi_us*)inout, w, h, channels); 187 | break; 188 | case CHANTYPE_f: 189 | if(len != (size_t)(w*h*channels*sizeof(float))) 190 | return luaL_error(L, "invalid data length"); 191 | inout = STBI_MALLOC(len); 192 | memcpy(inout, data, len); 193 | inout = stbi__hdr_to_ldr((float*)inout, w, h, channels); 194 | break; 195 | default: 196 | return unexpected(L); 197 | } 198 | 199 | if(!inout) return Error(L); 200 | len = (size_t)(w*h*channels); 201 | lua_pushlstring(L, (const char*)inout, len); 202 | STBI_FREE(inout); 203 | return 1; 204 | 205 | } 206 | 207 | 208 | static const struct luaL_Reg Functions[] = 209 | { 210 | { "info", Info }, 211 | { "reset_load_flags", Reset_load_flags }, 212 | { "unpremultiply_on_load", Set_unpremultiply_on_load }, 213 | { "convert_iphone_png_to_rgb", Convert_iphone_png_to_rgb }, 214 | { "flip_vertically_on_load", Set_flip_vertically_on_load }, 215 | { "load", Load }, 216 | { "set_gamma_and_scale", Set_gamma_and_scale }, 217 | { "gamma_and_scale", Gamma_and_scale }, 218 | { "is_hdr", Is_hdr }, 219 | { "reduce_to_u8", Reduce_to_u8 }, 220 | { NULL, NULL } /* sentinel */ 221 | }; 222 | 223 | 224 | void moonimage_open_load(lua_State *L) 225 | { 226 | luaL_setfuncs(L, Functions, 0); 227 | } 228 | 229 | 230 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2017 Stefano Trettel 4 | * 5 | * Software repository: MoonImage, https://github.com/stetre/moonimage 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | static lua_State *moonimage_L = NULL; 29 | 30 | static void AtExit(void) 31 | { 32 | if(moonimage_L) 33 | { 34 | moonimage_L = NULL; 35 | } 36 | } 37 | 38 | static int AddVersions(lua_State *L) 39 | /* Add version strings to the gl table */ 40 | { 41 | lua_pushstring(L, "_VERSION"); 42 | lua_pushstring(L, "MoonImage "MOONIMAGE_VERSION); 43 | lua_settable(L, -3); 44 | return 0; 45 | } 46 | 47 | 48 | int luaopen_moonimage(lua_State *L) 49 | /* Lua calls this function to load the module */ 50 | { 51 | moonimage_L = L; 52 | 53 | malloc_init(L); 54 | atexit(AtExit); 55 | 56 | lua_newtable(L); /* the module table */ 57 | AddVersions(L); 58 | 59 | /* add functions: */ 60 | moonimage_open_load(L); 61 | moonimage_open_write(L); 62 | moonimage_open_perlin(L); 63 | 64 | #if 0 //@@ 65 | /* Add functions implemented in Lua */ 66 | lua_pushvalue(L, -1); lua_setglobal(L, "moonimage"); 67 | if(luaL_dostring(L, "require('moonimage.utils')") != 0) lua_error(L); 68 | lua_pushnil(L); lua_setglobal(L, "moonimage"); 69 | #endif 70 | 71 | return 1; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/moonimage.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2017 Stefano Trettel 4 | * 5 | * Software repository: MoonImage, https://github.com/stetre/moonimage 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | /**************************************************************************** 27 | * MoonImage library - C API * 28 | ****************************************************************************/ 29 | 30 | #ifndef moonimageDEFINED 31 | #define moonimageDEFINED 32 | 33 | #include 34 | #include "lualib.h" 35 | #include "lauxlib.h" 36 | #include "compat-5.3.h" 37 | 38 | #define MOONIMAGE_VERSION "0.3" 39 | 40 | #endif /* moonimageDEFINED */ 41 | 42 | -------------------------------------------------------------------------------- /src/perlin.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2019 Stefano Trettel 4 | * 5 | * Software repository: MoonImage, https://github.com/stetre/moonimage 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /* Currently stb_perlin.h lacks a mechanism to make its functions static, such as 29 | * STB_IMAGE_STATIC in stb_image.h, so we prepend our moonimage_ prefix. 30 | */ 31 | #define stb_perlin_noise3_internal moonimage_stb_perlin_noise3_internal 32 | float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed); 33 | #define stb_perlin_noise3 moonimage_stb_perlin_noise3 34 | float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); 35 | #define stb_perlin_noise3_seed moonimage_stb_perlin_noise3_seed 36 | float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed); 37 | #define stb_perlin_ridge_noise3 moonimage_stb_perlin_ridge_noise3 38 | float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves); 39 | #define stb_perlin_fbm_noise3 moonimage_stb_perlin_fbm_noise3 40 | float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); 41 | #define stb_perlin_turbulence_noise3 moonimage_stb_perlin_turbulence_noise3 42 | float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); 43 | #define stb_perlin_noise3_wrap_nonpow2 moonimage_stb_perlin_noise3_wrap_nonpow2 44 | float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed); 45 | 46 | #define STB_PERLIN_IMPLEMENTATION 47 | #include "stb_perlin.h" 48 | 49 | /*------------------------------------------------------------------------------* 50 | | Perlin noise | 51 | *------------------------------------------------------------------------------*/ 52 | 53 | static int Perlin(lua_State *L) 54 | { 55 | float value; 56 | float x = luaL_checknumber(L, 1); 57 | float y = luaL_optnumber(L, 2, 0); 58 | float z = luaL_optnumber(L, 3, 0); 59 | int x_wrap = luaL_optinteger(L, 4, 0); 60 | int y_wrap = luaL_optinteger(L, 5, 0); 61 | int z_wrap = luaL_optinteger(L, 6, 0); 62 | int seed = luaL_optinteger(L, 7, 0); /* 0-256 */ 63 | value = stb_perlin_noise3_seed(x, y, z, x_wrap, y_wrap, z_wrap, seed); 64 | //@@value = stb_perlin_noise3_wrap_nonpow2(x, y, z, x_wrap, y_wrap, z_wrap, seed); 65 | /* Clamp between -1 and 1, just to be sure */ 66 | if(value < -1.0f) value=-1.0f; else if(value > 1.0f) value=1.0f; 67 | lua_pushnumber(L, value); 68 | return 1; 69 | } 70 | 71 | static const struct luaL_Reg Functions[] = 72 | { 73 | { "perlin", Perlin}, 74 | { NULL, NULL } /* sentinel */ 75 | }; 76 | 77 | void moonimage_open_perlin(lua_State *L) 78 | { 79 | luaL_setfuncs(L, Functions, 0); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2017 Stefano Trettel 4 | * 5 | * Software repository: MoonImage, https://github.com/stetre/moonimage 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Misc utilities | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | int noprintf(const char *fmt, ...) 33 | { (void)fmt; return 0; } 34 | 35 | int notavailable(lua_State *L, ...) 36 | { 37 | return luaL_error(L, "function not available in this version"); 38 | } 39 | 40 | /*------------------------------------------------------------------------------* 41 | | Malloc | 42 | *------------------------------------------------------------------------------*/ 43 | 44 | /* We do not use malloc(), free() etc directly. Instead, we inherit the memory 45 | * allocator from the main Lua state instead (see lua_getallocf in the Lua manual) 46 | * and use that. 47 | * 48 | * By doing so, we can use an alternative malloc() implementation without recompiling 49 | * this library (we have needs to recompile lua only, or execute it with LD_PRELOAD 50 | * set to the path to the malloc library we want to use). 51 | */ 52 | static lua_Alloc Alloc = NULL; 53 | static void* AllocUd = NULL; 54 | 55 | void malloc_init(lua_State *L) 56 | { 57 | if(Alloc) unexpected(L); 58 | Alloc = lua_getallocf(L, &AllocUd); 59 | } 60 | 61 | static void* Malloc_(size_t size) 62 | { return Alloc ? Alloc(AllocUd, NULL, 0, size) : NULL; } 63 | 64 | static void Free_(void *ptr) 65 | { if(Alloc) Alloc(AllocUd, ptr, 0, 0); } 66 | 67 | void *Malloc(lua_State *L, size_t size) 68 | { 69 | void *ptr = Malloc_(size); 70 | if(ptr==NULL) 71 | { luaL_error(L, errstring(ERR_MEMORY)); return NULL; } 72 | memset(ptr, 0, size); 73 | //DBG("Malloc %p\n", ptr); 74 | return ptr; 75 | } 76 | 77 | void *MallocNoErr(lua_State *L, size_t size) /* do not raise errors (check the retval) */ 78 | { 79 | void *ptr = Malloc_(size); 80 | (void)L; 81 | if(ptr==NULL) 82 | return NULL; 83 | memset(ptr, 0, size); 84 | //DBG("MallocNoErr %p\n", ptr); 85 | return ptr; 86 | } 87 | 88 | char *Strdup(lua_State *L, const char *s) 89 | { 90 | size_t len = strnlen(s, 256); 91 | char *ptr = (char*)Malloc(L, len + 1); 92 | if(len>0) 93 | memcpy(ptr, s, len); 94 | ptr[len]='\0'; 95 | return ptr; 96 | } 97 | 98 | 99 | void Free(lua_State *L, void *ptr) 100 | { 101 | (void)L; 102 | //DBG("Free %p\n", ptr); 103 | if(ptr) Free_(ptr); 104 | } 105 | 106 | /*------------------------------------------------------------------------------* 107 | | Custom luaL_checkxxx() style functions | 108 | *------------------------------------------------------------------------------*/ 109 | 110 | int checkboolean(lua_State *L, int arg) 111 | { 112 | if(!lua_isboolean(L, arg)) 113 | return (int)luaL_argerror(L, arg, "boolean expected"); 114 | return lua_toboolean(L, arg); 115 | } 116 | 117 | 118 | int testboolean(lua_State *L, int arg, int *err) 119 | { 120 | if(!lua_isboolean(L, arg)) 121 | { *err = ERR_TYPE; return 0; } 122 | *err = 0; 123 | return lua_toboolean(L, arg); 124 | } 125 | 126 | 127 | int optboolean(lua_State *L, int arg, int d) 128 | { 129 | if(!lua_isboolean(L, arg)) 130 | return d; 131 | return lua_toboolean(L, arg); 132 | } 133 | 134 | /* Color channels (enum) ----------------------------------------------------*/ 135 | 136 | int checkchannels(lua_State *L, int arg) 137 | { 138 | const char *s = luaL_checkstring(L, arg); 139 | #define CASE(CODE,str) if((strcmp(s, str)==0)) return CODE 140 | // CASE(CHAN_default, "default"); 141 | CASE(CHAN_y, "y"); 142 | CASE(CHAN_ya, "ya"); 143 | CASE(CHAN_rgb, "rgb"); 144 | CASE(CHAN_rgba, "rgba"); 145 | #undef CASE 146 | return luaL_argerror(L, arg, badvalue(L,s)); 147 | } 148 | 149 | int optchannels(lua_State *L, int arg) 150 | { 151 | if(lua_isnoneornil(L, arg)) 152 | return CHAN_default; 153 | return checkchannels(L, arg); 154 | } 155 | 156 | int pushchannels(lua_State *L, int val) 157 | { 158 | switch(val) 159 | { 160 | #define CASE(CODE,str) case CODE: lua_pushstring(L, str); break 161 | // CASE(CHAN_default, "default"); 162 | CASE(CHAN_y, "y"); 163 | CASE(CHAN_ya, "ya"); 164 | CASE(CHAN_rgb, "rgb"); 165 | CASE(CHAN_rgba, "rgba"); 166 | #undef CASE 167 | default: 168 | return unexpected(L); 169 | } 170 | return 1; 171 | } 172 | 173 | /* Color channel type (enum) ------------------------------------------------*/ 174 | 175 | int checkchantype(lua_State *L, int arg) 176 | { 177 | const char *s = luaL_checkstring(L, arg); 178 | #define CASE(CODE,str) if((strcmp(s, str)==0)) return CODE 179 | CASE(CHANTYPE_u8, "u8"); 180 | CASE(CHANTYPE_u16, "u16"); 181 | CASE(CHANTYPE_f, "f"); 182 | #undef CASE 183 | return luaL_argerror(L, arg, badvalue(L,s)); 184 | } 185 | 186 | int optchantype(lua_State *L, int arg, int defval) 187 | { 188 | if(lua_isnoneornil(L, arg)) 189 | return defval; 190 | return checkchantype(L, arg); 191 | } 192 | 193 | int pushchantype(lua_State *L, int val) 194 | { 195 | switch(val) 196 | { 197 | #define CASE(CODE,str) case CODE: lua_pushstring(L, str); break 198 | CASE(CHANTYPE_u8, "u8"); 199 | CASE(CHANTYPE_u16, "u16"); 200 | CASE(CHANTYPE_f, "f"); 201 | #undef CASE 202 | default: 203 | return unexpected(L); 204 | } 205 | return 1; 206 | } 207 | 208 | /*------------------------------------------------------------------------------* 209 | | Internal error codes | 210 | *------------------------------------------------------------------------------*/ 211 | 212 | const char* errstring(int err) 213 | { 214 | switch(err) 215 | { 216 | case 0: return "success"; 217 | case ERR_GENERIC: return "generic error"; 218 | case ERR_TABLE: return "not a table"; 219 | case ERR_EMPTY: return "empty list"; 220 | case ERR_TYPE: return "invalid type"; 221 | case ERR_VALUE: return "invalid value"; 222 | case ERR_NOTPRESENT: return "missing"; 223 | case ERR_MEMORY: return "out of memory"; 224 | case ERR_LENGTH: return "invalid length"; 225 | case ERR_POOL: return "elements are not from the same pool"; 226 | case ERR_BOUNDARIES: return "invalid boundaries"; 227 | case ERR_UNKNOWN: return "unknown field name"; 228 | default: 229 | return "???"; 230 | } 231 | return NULL; /* unreachable */ 232 | } 233 | 234 | -------------------------------------------------------------------------------- /src/write.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2017 Stefano Trettel 4 | * 5 | * Software repository: MoonImage, https://github.com/stetre/moonimage 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | #define STB_IMAGE_WRITE_IMPLEMENTATION 29 | #define STB_IMAGE_WRITE_STATIC 30 | #include "stb_image_write.h" 31 | 32 | static int Error(lua_State *L) 33 | { 34 | return luaL_error(L, "operation failed"); 35 | } 36 | 37 | static int Write_png(lua_State *L) 38 | { 39 | size_t len; 40 | const char *filename = luaL_checkstring(L, 1); 41 | int w = luaL_checkinteger(L, 2); 42 | int h = luaL_checkinteger(L, 3); 43 | int channels = checkchannels(L, 4); 44 | const void *data = luaL_checklstring(L, 5, &len); 45 | int stride = luaL_optinteger(L, 6, 0); 46 | if(stride < 0) 47 | return luaL_argerror(L, 6, "stride must be non negative"); 48 | if(len != (size_t)(w*h*channels)) 49 | return luaL_error(L, "invalid data length"); 50 | if(!stbi_write_png(filename, w, h, channels, data, stride)) return Error(L); 51 | return 0; 52 | } 53 | 54 | static int Write_bmp(lua_State *L) 55 | { 56 | size_t len; 57 | const char *filename = luaL_checkstring(L, 1); 58 | int w = luaL_checkinteger(L, 2); 59 | int h = luaL_checkinteger(L, 3); 60 | int channels = checkchannels(L, 4); 61 | const void *data = luaL_checklstring(L, 5, &len); 62 | if(len != (size_t)(w*h*channels)) 63 | return luaL_error(L, "invalid data length"); 64 | if(!stbi_write_bmp(filename, w, h, channels, data)) return Error(L); 65 | return 0; 66 | } 67 | 68 | static int Write_tga(lua_State *L) 69 | { 70 | int rc; 71 | size_t len; 72 | const char *filename = luaL_checkstring(L, 1); 73 | int w = luaL_checkinteger(L, 2); 74 | int h = luaL_checkinteger(L, 3); 75 | int channels = checkchannels(L, 4); 76 | const void *data = luaL_checklstring(L, 5, &len); 77 | int rle = optboolean(L, 6, 0); 78 | if(len != (size_t)(w*h*channels)) 79 | return luaL_error(L, "invalid data length"); 80 | if(!rle) stbi_write_tga_with_rle = 0; 81 | rc = stbi_write_tga(filename, w, h, channels, data); 82 | stbi_write_tga_with_rle = 1; 83 | if(!rc) return Error(L); 84 | return 0; 85 | } 86 | 87 | 88 | static int Write_hdr(lua_State *L) 89 | { 90 | size_t len; 91 | const char *filename = luaL_checkstring(L, 1); 92 | int w = luaL_checkinteger(L, 2); 93 | int h = luaL_checkinteger(L, 3); 94 | int channels = checkchannels(L, 4); 95 | const void *data = luaL_checklstring(L, 5, &len); 96 | if(len != (size_t)(w*h*channels*sizeof(float))) 97 | return luaL_error(L, "invalid data length"); 98 | if(!stbi_write_hdr(filename, w, h, channels, (const float*)data)) return Error(L); 99 | return 0; 100 | } 101 | 102 | 103 | static int Write_jpg(lua_State *L) 104 | { 105 | int rc; 106 | size_t len; 107 | const char *filename = luaL_checkstring(L, 1); 108 | int w = luaL_checkinteger(L, 2); 109 | int h = luaL_checkinteger(L, 3); 110 | int channels = checkchannels(L, 4); 111 | const void *data = luaL_checklstring(L, 5, &len); 112 | int quality = luaL_checkinteger(L, 6); 113 | if((quality < 1) || (quality > 100)) 114 | return luaL_argerror(L, 6, "quality must be between 1 (min) and 100 (max)"); 115 | if(len != (size_t)(w*h*channels)) 116 | return luaL_error(L, "invalid data length"); 117 | rc = stbi_write_jpg(filename, w, h, channels, data, quality); 118 | if(!rc) return Error(L); 119 | return 0; 120 | } 121 | 122 | static const struct luaL_Reg Functions[] = 123 | { 124 | { "write_png", Write_png }, 125 | { "write_bmp", Write_bmp }, 126 | { "write_tga", Write_tga }, 127 | { "write_hdr", Write_hdr }, 128 | { "write_jpg", Write_jpg }, 129 | { NULL, NULL } /* sentinel */ 130 | }; 131 | 132 | 133 | void moonimage_open_write(lua_State *L) 134 | { 135 | luaL_setfuncs(L, Functions, 0); 136 | } 137 | 138 | 139 | -------------------------------------------------------------------------------- /thirdparty/asciidoctor-styles-license: -------------------------------------------------------------------------------- 1 | The CSS used for the Reference Manual is taken from the 2 | Asciidoctor styles project 3 | (https://github.com/asciidoctor/asciidoctor-stylesheet-factory ). 4 | 5 | Below is a copy of the Asciidoctor styles copyright notice. 6 | 7 | Stefano Trettel 8 | 9 | ======================================================================== 10 | 11 | Asciidoctor styles 12 | ------------------ 13 | 14 | Copyright (c) 2013 Dan Allen 15 | 16 | MIT License 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining 19 | a copy of this software and associated documentation files (the 20 | "Software"), to deal in the Software without restriction, including 21 | without limitation the rights to use, copy, modify, merge, publish, 22 | distribute, sublicense, and/or sell copies of the Software, and to 23 | permit persons to whom the Software is furnished to do so, subject to 24 | the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be 27 | included in all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 33 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 34 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 35 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | 38 | Other licensed work 39 | ------------------- 40 | 41 | - Foundation 4 by Zurb, on which the themes are built, is licensed under the 42 | Apache License, v2.0: 43 | 44 | http://apache.org/licenses/LICENSE-2.0 45 | http://foundation.zurb.com 46 | 47 | - The riak theme is derived from the Riak documentation theme by Basho, 48 | licensed under the Creative Commons Attribution 3.0 Unported License: 49 | 50 | http://creativecommons.org/licenses/by/3.0/us 51 | http://docs.basho.org 52 | 53 | - The iconic theme is inspired by O'Reilly typography and Atlas manual. 54 | 55 | http://oreilly.com 56 | -------------------------------------------------------------------------------- /thirdparty/lua-compat-5.3-license: -------------------------------------------------------------------------------- 1 | The src/compat-5.3.h and src/compat-5.3.c files are taken from: 2 | https://github.com/keplerproject/lua-compat-5.3 3 | 4 | Below is a copy of the original copyright notice, from the same source. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | 10 | The MIT License (MIT) 11 | 12 | Copyright (c) 2015 Kepler Project. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy of 15 | this software and associated documentation files (the "Software"), to deal in 16 | the Software without restriction, including without limitation the rights to 17 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 18 | the Software, and to permit persons to whom the Software is furnished to do so, 19 | subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | -------------------------------------------------------------------------------- /thirdparty/powered-by-lua-license: -------------------------------------------------------------------------------- 1 | The 'powered by Lua' logo (doc/powered-by-lua.gif ) is taken from: 2 | http://www.lua.org/images . 3 | 4 | Below is a copy of the copyright notice from the same web-page. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | Copyright © 1998 Lua.org. Graphic design by Alexandre Nakonechnyj. 10 | 11 | Permission is hereby granted, without written agreement and without license 12 | or royalty fees, to use, copy, and distribute this logo for any purpose, 13 | including commercial applications, subject to the following conditions: 14 | 15 | - The origin of this logo must not be misrepresented; you must not claim that 16 | you drew the original logo. 17 | - The only modification you can make is to adapt the orbiting text to your 18 | product name. 19 | - The logo can be used in any scale as long as the relative proportions of its 20 | elements are maintained. 21 | -------------------------------------------------------------------------------- /thirdparty/stb-license: -------------------------------------------------------------------------------- 1 | The following files are taken from the STB libraries: 2 | - src/include/stb_image.h 3 | - src/include/stb_image_write.h 4 | (Taken from https://github.com/nothings/stb) 5 | 6 | Below is a copy of their copyright statement. 7 | 8 | Stefano Trettel 9 | 10 | =========================================================================== 11 | 12 | /* 13 | ------------------------------------------------------------------------------ 14 | This software is available under 2 licenses -- choose whichever you prefer. 15 | ------------------------------------------------------------------------------ 16 | ALTERNATIVE A - MIT License 17 | Copyright (c) 2017 Sean Barrett 18 | Permission is hereby granted, free of charge, to any person obtaining a copy of 19 | this software and associated documentation files (the "Software"), to deal in 20 | the Software without restriction, including without limitation the rights to 21 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 22 | of the Software, and to permit persons to whom the Software is furnished to do 23 | so, subject to the following conditions: 24 | The above copyright notice and this permission notice shall be included in all 25 | copies or substantial portions of the Software. 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | ------------------------------------------------------------------------------ 34 | ALTERNATIVE B - Public Domain (www.unlicense.org) 35 | This is free and unencumbered software released into the public domain. 36 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 37 | software, either in source code form or as a compiled binary, for any purpose, 38 | commercial or non-commercial, and by any means. 39 | In jurisdictions that recognize copyright laws, the author or authors of this 40 | software dedicate any and all copyright interest in the software to the public 41 | domain. We make this dedication for the benefit of the public at large and to 42 | the detriment of our heirs and successors. We intend this dedication to be an 43 | overt act of relinquishment in perpetuity of all present and future rights to 44 | this software under copyright law. 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 49 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 50 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 51 | ------------------------------------------------------------------------------ 52 | */ 53 | --------------------------------------------------------------------------------