├── .gitignore ├── English.lproj └── InfoPlist.strings ├── LICENSE ├── Plask.icns ├── README ├── docs ├── footer.html ├── header.html ├── markdown.js ├── parse_docs_to_html.js ├── prism.js ├── webgl.idl └── webgl2.idl ├── examples ├── 001_hello_circle.js ├── 002_hello_circle_pulse.js ├── 003_hello_circle_click.js ├── 004_hello_circle_drag.js ├── 005_hello_circle_drag_spring.js ├── 006_hello_circle_follow.js ├── 007_hello_circle_keyboard.js ├── 008_hello_circle_keyboard_arrows.js ├── 010_image_drop.js ├── 030_midi_send.js ├── 031_midi_receive.js ├── 040_applescript.js ├── 100_ryan_particles.js ├── 101_thatcher_drops.js ├── 104_chainreaction.js ├── 105_fontMetrics.js ├── 500_triangle │ ├── app.fshader │ ├── app.js │ └── app.vshader └── 505_perlin │ ├── app.fshader │ ├── app.js │ └── app.vshader ├── fetch_deps.sh ├── libev.patch ├── main.mm ├── node-libuv.diff ├── node-load.diff ├── plask-Info.plist ├── plask.js ├── plask.xcodeproj └── project.pbxproj ├── plaskAppDelegate.h ├── plaskAppDelegate.mm ├── plask_Prefix.pch ├── plask_bindings.h ├── plask_bindings.mm ├── tests ├── gradient_alpha.js └── tests.js ├── v8_utils.cc ├── v8_utils.h └── webgl_constants.h /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | deps/ 4 | project.xcworkspace/ 5 | xcuserdata/ 6 | *.pbxuser 7 | *.perspective 8 | *.perspectivev3 9 | *.mode1v3 10 | *.mode2v3 11 | -------------------------------------------------------------------------------- /English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Plask, (c) Dean McNamee , 2011. BSD license: 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to 5 | deal in the Software without restriction, including without limitation the 6 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 | sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 | IN THE SOFTWARE. 20 | 21 | 22 | 23 | Syphon is licensed under a Simplified BSD license. 24 | 25 | Copyright 2010 bangnoise (Tom Butterworth) & vade (Anton Marini). 26 | All rights reserved. 27 | 28 | Redistribution and use in source and binary forms, with or without 29 | modification, are permitted provided that the following conditions are met: 30 | 31 | * Redistributions of source code must retain the above copyright 32 | notice, this list of conditions and the following disclaimer. 33 | 34 | * Redistributions in binary form must reproduce the above copyright 35 | notice, this list of conditions and the following disclaimer in the 36 | documentation and/or other materials provided with the distribution. 37 | 38 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 39 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 40 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 42 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 43 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 44 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 46 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 47 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 | 49 | 50 | 51 | Skia license: 52 | 53 | Copyright 2006, The Android Open Source Project 54 | 55 | Licensed under the Apache License, Version 2.0 (the "License"); 56 | you may not use this file except in compliance with the License. 57 | You may obtain a copy of the License at 58 | 59 | http://www.apache.org/licenses/LICENSE-2.0 60 | 61 | Unless required by applicable law or agreed to in writing, software 62 | distributed under the License is distributed on an "AS IS" BASIS, 63 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 64 | See the License for the specific language governing permissions and 65 | limitations under the License. 66 | 67 | 68 | 69 | FreeImage Public License - Version 1.0 70 | --------------------------------------------- 71 | 72 | 1. Definitions. 73 | 74 | 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 75 | 76 | 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 77 | 78 | 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 79 | 80 | 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 81 | 82 | 1.5. "Executable" means Covered Code in any form other than Source Code. 83 | 84 | 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 85 | 86 | 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 87 | 88 | 1.8. "License" means this document. 89 | 90 | 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a 91 | Modification is: 92 | 93 | A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. 94 | 95 | B. Any new file that contains any part of the Original Code or previous Modifications. 96 | 97 | 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 98 | 99 | 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control 100 | compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 101 | 102 | 1.12. "You" means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the 103 | direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. 104 | 105 | 2. Source Code License. 106 | 107 | 2.1. The Initial Developer Grant. 108 | The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: 109 | 110 | (a) to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and 111 | 112 | (b) under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell ("Utilize") the Original Code (or portions thereof), but solely to the extent that 113 | any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or 114 | combinations. 115 | 116 | 2.2. Contributor Grant. 117 | Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: 118 | 119 | (a) to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and 120 | 121 | (b) under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that 122 | may be necessary to Utilize further Modifications or combinations. 123 | 124 | 3. Distribution Obligations. 125 | 126 | 3.1. Application of License. 127 | The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or 128 | restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 129 | 130 | 3.2. Availability of Source Code. 131 | Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 132 | 133 | 3.3. Description of Modifications. 134 | You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 135 | 136 | 3.4. Intellectual Property Matters 137 | 138 | (a) Third Party Claims. 139 | If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make 140 | available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. 141 | 142 | (b) Contributor APIs. 143 | If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. 144 | 145 | 3.5. Required Notices. 146 | You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its 147 | structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or 148 | liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of 149 | warranty, support, indemnity or liability terms You offer. 150 | 151 | 3.6. Distribution of Executable Versions. 152 | You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You 153 | describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, 154 | provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 155 | 156 | 3.7. Larger Works. 157 | You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 158 | 159 | 4. Inability to Comply Due to Statute or Regulation. 160 | 161 | If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 162 | 163 | 5. Application of this License. 164 | 165 | This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. 166 | 167 | 6. Versions of the License. 168 | 169 | 6.1. New Versions. 170 | Floris van den Berg may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 171 | 172 | 6.2. Effect of New Versions. 173 | Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Floris van den Berg 174 | No one other than Floris van den Berg has the right to modify the terms applicable to Covered Code created under this License. 175 | 176 | 6.3. Derivative Works. 177 | If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases "FreeImage", `FreeImage Public License", "FIPL", or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the FreeImage Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 178 | 179 | 7. DISCLAIMER OF WARRANTY. 180 | 181 | COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 182 | 183 | 8. TERMINATION. 184 | 185 | This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 186 | 187 | 9. LIMITATION OF LIABILITY. 188 | 189 | UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE 190 | EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 191 | 192 | 10. U.S. GOVERNMENT END USERS. 193 | 194 | The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 195 | 196 | 11. MISCELLANEOUS. 197 | 198 | This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by Dutch law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the The Netherlands: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Almelo, The Netherlands; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the court of Almelo, The Netherlands with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 199 | 200 | 12. RESPONSIBILITY FOR CLAIMS. 201 | 202 | Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based 203 | on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute 204 | responsibility on an equitable basis. 205 | 206 | EXHIBIT A. 207 | 208 | "The contents of this file are subject to the FreeImage Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://home.wxs.nl/~flvdberg/freeimage-license.txt 209 | 210 | Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. 211 | 212 | 213 | 214 | Node's license follows: 215 | 216 | ==== 217 | 218 | Copyright Joyent, Inc. and other Node contributors. All rights reserved. 219 | Permission is hereby granted, free of charge, to any person obtaining a copy 220 | of this software and associated documentation files (the "Software"), to 221 | deal in the Software without restriction, including without limitation the 222 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 223 | sell copies of the Software, and to permit persons to whom the Software is 224 | furnished to do so, subject to the following conditions: 225 | 226 | The above copyright notice and this permission notice shall be included in 227 | all copies or substantial portions of the Software. 228 | 229 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 230 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 231 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 232 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 233 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 234 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 235 | IN THE SOFTWARE. 236 | 237 | ==== 238 | 239 | This license applies to all parts of Node that are not externally 240 | maintained libraries. 241 | 242 | The externally maintained libraries used by Node are: 243 | 244 | - v8, located at deps/v8. v8 is copyright Google, Inc, and released 245 | under a BSD license. 246 | 247 | - libev, located at deps/libev, and libeio, located at deps/libeio. libev 248 | and libeio are copyright Marc Alexander Lehmann, and dual-licensed 249 | under the MIT license and GPL2. 250 | 251 | - WAF build system, located at tools/waf. WAF is copyright Thomas Nagy, 252 | and released under the MIT license. 253 | 254 | - The SCONS build system, located at tools/scons. SCONS is copyright 255 | the SCONS Foundation and released under the MIT license. 256 | 257 | - C-Ares, an asynchronous DNS client, located at deps/c-ares. C-Ares is 258 | copyright the Massachusetts Institute of Technology, authored by 259 | Greg Hudson, Daniel Stenberg and others, and released under the MIT 260 | license. 261 | 262 | - Node, optionally, dynamically links to OpenSSL, cryptographic software 263 | written by Eric Young (eay@cryptsoft.com) to provide SSL/TLS encryption. 264 | OpenSSL is copyright The OpenSSL Project and released under the OpenSSL 265 | license. OpenSSL is not included in the Node distribution. 266 | See http://openssl.org/ for more information. 267 | 268 | - tools/doctool/markdown.js is copyright 2009-2010 Dominic Baggott and Ash 269 | Berli and released under the MIT license. 270 | 271 | - HTTP Parser, located at deps/http_parser, is a small C library 272 | copyright Ryan Lienhart Dahl and released under the MIT license. 273 | 274 | - src/platform_darwin_proctitle.cc, has code taken from the Chromium 275 | project copyright Google Inc. and released under a BSD license. 276 | 277 | - tools/closure_linter is copyright The Closure Linter Authors and 278 | Google Inc. and released under the Apache License, version 2.0. 279 | 280 | - tools/cpplint.py is copyright Google Inc. and released under a 281 | BSD license. 282 | -------------------------------------------------------------------------------- /Plask.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deanm/plask/8add16d88270c28a61efa99950dfc3707086d7f1/Plask.icns -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Plask is a programming environment for multimedia and computational design. 2 | 3 | www.plask.org 4 | 5 | 6 | - Getting Plask 7 | 8 | For the common user, it is best to use the binary distribution provided at 9 | www.plask.org. If you're interested in building and running from source, the 10 | following section should help you get started. 11 | 12 | 13 | - Building and running from source 14 | 15 | Plask integrates together quite a few pieces of technology, which unfortunately 16 | makes the build process more complicated. It is possible to do a boostrapped 17 | build, where you only build the Plask source file, but use prebuilt object 18 | files for Plask's dependencies. Run the fetch_deps.sh script to download and 19 | extract a copy of these prebuilt dependencies. When fetching new source 20 | changes to Plask, you will have to be aware if there have been any changes to 21 | the prebuilt dependencies, and if so, to run fetch_deps.sh again. 22 | 23 | For example, to build from a completely new checkout would look something like: 24 | 25 | $ sh fetch_deps.sh 26 | $ xcodebuild -project plask.xcodeproj -configuration Release -target Plask 27 | 28 | This should produce Plask.app. For some technical and design reasons, Plask.app 29 | is effectively a commandline application inside a bundle. For example, running 30 | Plask.app/Contents/MacOS/Plask on the command line will start a Node-style REPL 31 | loop, an interactive JavaScript shell of sorts. 32 | 33 | Pass a filename on the command line to run that JavaScript file. 34 | 35 | NOTE: To ease development, the Plask.app built has a symlink to plask.js in 36 | the source. This allows you to edit plask.js in the source repository without 37 | having to rebuild the project. 38 | 39 | A separate project, PlaskLauncher, creates the UI application for launching 40 | Plask by dragging/dropping or File->Open. 41 | 42 | 43 | - Creating standalone applications 44 | 45 | When Plask.app is launched, it will look for a file named main.js inside of 46 | the bundle (in Contents/Resources). This allows you to easily create 47 | standalone applications by copying Plask.app and putting your JavaScript source 48 | inside of the bundle. 49 | 50 | NOTE: When running "bundled", the current working directory will likely be 51 | different from running Plask on the command line. Generally this means if you 52 | open files you should open a path relative to __dirname, which is Node's global 53 | variable for the directory that your JavaScript file is in. 54 | 55 | 56 | - Credits 57 | 58 | Released under the BSD license. Full details in the included LICENSE file. 59 | 60 | (c) 2010, Dean McNamee 61 | 62 | This software contains code and ideas from the fantastic: 63 | 64 | Nicolas Garcia Belmonte 65 | Thatcher Ulrich 66 | Ryan Alexander 67 | Marcin Ignac 68 | 69 | Built with the fantastic: 70 | 71 | V8 JavaScript Engine 72 | Skia rasterization library 73 | NodeJS 74 | Cocoa and OpenGL 75 | FreeImage 76 | Syphon 77 | -------------------------------------------------------------------------------- /docs/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /docs/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Plask v3 Documentation 6 | 7 | 195 | 196 | 197 |
198 |
199 |

Plask v3 Reference Documentation

200 |
201 |
202 | -------------------------------------------------------------------------------- /docs/parse_docs_to_html.js: -------------------------------------------------------------------------------- 1 | // parses the bindings code and plask.js and produces and html file with 2 | // reference documentation from markdown in the code comments. 3 | var fs = require('fs'); 4 | var markdown = require('./markdown.js'); 5 | var prism = require('./prism.js'); 6 | 7 | var header = fs.readFileSync(__dirname + '/header.html', 'utf8'); 8 | var footer = fs.readFileSync(__dirname + '/footer.html', 'utf8'); 9 | 10 | var webgl1_idl = fs.readFileSync(__dirname + '/webgl.idl', 'utf8'); 11 | var webgl2_idl = fs.readFileSync(__dirname + '/webgl2.idl', 'utf8'); 12 | 13 | function htmlescape(str) { 14 | return str.replace(/&/g, '&').replace(//g, '>'); 15 | } 16 | 17 | function parse_source_cpp(lines, cb_continue, cb_start, cb_end) { 18 | var cur_class = null; 19 | var cur_indent = null; 20 | var cur_method = null; 21 | var cur_arity = undefined; 22 | var cur_cmt = ''; 23 | 24 | for (var i = 0, il = lines.length; i < il; ++i) { 25 | var line = lines[i]; 26 | 27 | var match; 28 | 29 | var prev_cmt = cur_cmt; 30 | 31 | match = line.match(/^\s*\/\/ ?(.*)$/); 32 | if (match) { 33 | cur_cmt += match[1] + '\n'; 34 | } else { 35 | cur_cmt = ''; 36 | } 37 | 38 | match = line.match(/^class ([A-Za-z_0-9]+)/); 39 | if (match) { 40 | cur_class = match[1]; 41 | cb_continue(line); 42 | continue; 43 | } 44 | 45 | if (cur_class === null) { 46 | cb_continue(line); 47 | continue; 48 | } 49 | 50 | match = line.match(/^(\s*)(static void ([A-Za-z_0-9]+)\(const v8::FunctionCallbackInfo& args\)|DEFINE_METHOD\(([A-Za-z_0-9]+), (\d+))/); 51 | if (match) { 52 | cur_indent = match[1]; 53 | cur_method = match[3] || match[4]; 54 | cur_arity = match[5]; 55 | cb_start(line, cur_indent, cur_class, cur_method, cur_arity, prev_cmt); 56 | continue; 57 | } 58 | 59 | if (cur_indent === null) { 60 | cb_continue(line); 61 | continue; 62 | } 63 | 64 | match = line.match(/args\[(\d+)\]/); 65 | if (match) { 66 | var arity = parseInt(match[1]) + 1; 67 | if (cur_arity === undefined || arity > cur_arity) 68 | cur_arity = arity; 69 | cb_continue(line); 70 | continue; 71 | } 72 | 73 | match = line.match(/^(\s*)}/); 74 | if (match && match[1] === cur_indent) { 75 | cur_indent = null; 76 | cb_end(line, cur_class, cur_method, arity); 77 | continue; 78 | } 79 | 80 | cb_continue(line); 81 | } 82 | } 83 | 84 | function parse_source_js(lines, cb_continue, cb_start, cb_end, cb_export) { 85 | var cur_class = null; 86 | var cur_indent = null; 87 | var cur_method = null; 88 | var cur_arity = undefined; 89 | var cur_cmt = ''; 90 | 91 | for (var i = 0, il = lines.length; i < il; ++i) { 92 | var line = lines[i]; 93 | 94 | var match; 95 | 96 | var prev_cmt = cur_cmt; 97 | 98 | match = line.match(/^\s*\/\/ ?(.*)$/); 99 | if (match) { 100 | cur_cmt += match[1] + '\n'; 101 | } else { 102 | cur_cmt = ''; 103 | } 104 | 105 | match = line.match(/^(\s*)exports.([A-Za-z_0-9]+) = ([A-Za-z_0-9]+);/); 106 | if (match) { 107 | cur_indent = match[1]; 108 | cur_lhs = match[2]; 109 | cur_rhs = match[2]; 110 | cb_export(line, cur_indent, cur_lhs, cur_rhs); 111 | continue; 112 | } 113 | 114 | match = line.match(/^(\s*)function ([A-Za-z_0-9]+)\(/); 115 | if (match) { 116 | cur_indent = match[1]; 117 | cur_class = match[2]; 118 | cur_method = match[2]; 119 | cb_start(line, cur_indent, cur_class, cur_method, cur_arity, prev_cmt); 120 | continue; 121 | } 122 | 123 | match = line.match(/^(\s*)([A-Za-z_0-9]+)(?:\.prototype)?\.([A-Za-z_0-9]+) = function/); 124 | if (!match) 125 | match = line.match(/^(\s*)exports\.([A-Za-z_0-9]+)\.([A-Za-z_0-9]+) = function/); 126 | if (match) { 127 | cur_indent = match[1]; 128 | cur_class = match[2]; 129 | cur_method = match[3]; 130 | cb_start(line, cur_indent, cur_class, cur_method, cur_arity, prev_cmt); 131 | continue; 132 | } 133 | 134 | if (cur_indent === null) { 135 | cb_continue(line); 136 | continue; 137 | } 138 | 139 | cb_continue(line); 140 | } 141 | } 142 | 143 | var functions = [ ]; 144 | var jsexports = [ ]; 145 | 146 | function make_md(meth, cmt) { 147 | if (cmt.length === 0) '### ' + meth + "\n"; 148 | 149 | cmt = cmt.replace(/^(TODO|FIXME|NOTE).*$/mg, ''); 150 | 151 | var headi = cmt.indexOf('\n\n'); 152 | if (headi === -1) headi = cmt.length; 153 | var head = cmt.substr(0, headi), tail = cmt.substr(headi); 154 | //console.log([head, tail]); 155 | 156 | // We sort of assume the structure of a first line with a function prototype, 157 | // but that isn't always true (yet). 158 | if (head.indexOf(meth) !== -1) { 159 | head = head.replace(/^/mg, ' '); // Turn into a code block. 160 | } 161 | 162 | cmt = head + "\n\n" + tail; 163 | 164 | return '### ' + meth + "\n" + cmt; 165 | } 166 | 167 | var lines_cpp = fs.readFileSync(__dirname + '/../plask_bindings.mm', 'utf8').split('\n'); 168 | var lines_js = fs.readFileSync(__dirname + '/../plask.js', 'utf8').split('\n'); 169 | 170 | // Our proto declarations are in this sort of C style more or less like WebIDL. 171 | // We have something like "returntype functionname(type argname, ...) 172 | // Additionally you have [ ] for arrays, ? for "nullable types", etc. 173 | function redo_tokens_for_proto(tokens) { 174 | var i = 0, il = tokens.length; 175 | while (i < il) { 176 | // split something like "BLAH " to keyword BLAH and ' ', for the case where 177 | // BLAH didn't match the keyword regex. 178 | if (typeof(tokens[i]) === "string") { 179 | var typename = tokens[i]; 180 | if (typename[typename.length - 1] === " ") { 181 | typename = typename.substr(0, typename.length - 1); 182 | tokens.splice(i+1, 0, ' '); 183 | ++il; 184 | } 185 | tokens[i] = new prism.Token('keyword', typename); 186 | } 187 | 188 | while (i < il) { 189 | while (i < il && tokens[i] !== " ") ++i; 190 | if (i === il) return; 191 | ++i; 192 | if (tokens[i].type === 'function' || tokens[i].type === "class-name") break; 193 | } 194 | 195 | tokens[i].type = 'function'; 196 | ++i; 197 | if (tokens[i].content !== '(') throw JSON.stringify(tokens); 198 | ++i; 199 | break; 200 | } 201 | } 202 | 203 | function gen_highlighted_html(htmltree, par1, sib1, sib2) { 204 | var content = ''; 205 | 206 | var tag = htmltree[0]; 207 | 208 | if (tag === "code" && par1 === "pre") { 209 | var js = htmltree[1]; 210 | var tokens = prism.tokenize(js, prism.languages.javascript); 211 | if (sib2 === "h3") 212 | redo_tokens_for_proto(tokens); 213 | content = prism.Token.stringify(prism.util.encode(tokens)); 214 | } else { 215 | for (var i = 1, il = htmltree.length; i < il; ++i) { 216 | content += Array.isArray(htmltree[i]) ? 217 | gen_highlighted_html(htmltree[i], tag, htmltree[i-1][0], sib1) : 218 | htmltree[i]; 219 | } 220 | } 221 | 222 | return '<' + tag + '>' + content + ''; 223 | } 224 | 225 | function make_md_to_html(meth, cmt) { 226 | var md = markdown.parse(make_md(meth, cmt)); 227 | var htmltree = markdown.toHTMLTree(md); 228 | var html = gen_highlighted_html(htmltree); 229 | return html + "\n"; 230 | } 231 | 232 | parse_source_cpp(lines_cpp, function() { }, 233 | function(line, indent, cls, meth, arity, cmt) { 234 | var html = make_md_to_html(meth.replace('V8New', cls.replace(/Wrapper/g, '')), cmt); 235 | functions.push({cls: cls, meth: meth, html: html}); 236 | }, 237 | function(line, cls, meth, arity) { 238 | }); 239 | 240 | //functions = [ ]; 241 | parse_source_js(lines_js, function() { }, 242 | function(line, indent, cls, meth, arity, cmt) { 243 | var html = make_md_to_html(meth, cmt); 244 | functions.push({cls: cls, meth: meth, html: html}); 245 | }, 246 | function(line, cls, meth, arity) { 247 | }, 248 | function(line, indent, lhs, rhs) { 249 | jsexports.push(lhs); 250 | }); 251 | 252 | function sorter(a, b) { 253 | if (a.cls === b.cls) return a.meth.localeCompare(b.meth); 254 | return a.cls.localeCompare(b.cls); 255 | } 256 | 257 | // Rewrite some of the small "loose" functions to be under 'plask'. 258 | for (var i = 0, il = functions.length; i < il; ++i) { 259 | var f = functions[i]; 260 | if (f.cls[0].toLowerCase() === f.cls[0] && f.meth === f.cls && jsexports.indexOf(f.meth) !== -1) 261 | f.cls = "plask"; 262 | } 263 | 264 | functions.sort(sorter); 265 | 266 | var last_cls = null; 267 | 268 | var kIncludeCls = ['AVPlayer', 'NSOpenGLContext', 'NSWindow', 269 | 'SkCanvas', 'SkPaint', 'SkPath', 270 | 'MagicProgram', 'Mat3', 'Mat4', 'Vec2', 'Vec3', 'Vec4', 'plask']; 271 | 272 | var tochtml = ''; 273 | var bodyhtml = ''; 274 | 275 | for (var i = 0, il = functions.length; i < il; ++i) { 276 | var f = functions[i]; 277 | 278 | var clsdisp = f.cls.replace(/Wrapper/g, ''); 279 | 280 | if (kIncludeCls.indexOf(clsdisp) === -1) { 281 | process.stderr.write("Skipping: " + f.cls + "\n"); 282 | continue; 283 | } 284 | 285 | var methdisp = f.meth.replace('V8New', clsdisp); 286 | if (clsdisp === "MagicProgram") clsdisp = "gl." + clsdisp; 287 | var aname = (clsdisp + ' ' + methdisp).replace(/[^a-zA-Z0-9]/g, '_'); 288 | 289 | if (clsdisp !== last_cls) { 290 | if (tochtml.length) tochtml += '
' 291 | tochtml += '

' + clsdisp + '

'; 292 | bodyhtml += ''; 293 | bodyhtml += '

' + clsdisp + '

'; 294 | last_cls = clsdisp; 295 | } 296 | 297 | tochtml += '
' + methdisp + '
'; 298 | 299 | var html = f.html; 300 | 301 | var link = null; 302 | 303 | if (clsdisp === "NSOpenGLContext") { 304 | var rx = new RegExp('^.*\\b' + f.meth + '\\([^;]+;', 'mg'); 305 | var glver = '1.0'; 306 | var match = webgl1_idl.match(rx); 307 | if (!match) { 308 | var glver = '2.0'; 309 | match = webgl2_idl.match(rx); 310 | } 311 | 312 | if (match) { 313 | var url = 'https://www.khronos.org/registry/webgl/specs/latest/' + glver + '/'; 314 | link = 'WebGL ' + glver + ''; 315 | //console.log('
' + htmlescape(match[0]) + '
'); 316 | } 317 | } 318 | 319 | if (clsdisp === "AVPlayer") { 320 | var m = f.meth; 321 | if (m.substr(0, 3) === "set") m = m.substr(3, 1).toLowerCase() + m.substr(4); 322 | var url = 'https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVPlayer_Class/index.html#//apple_ref/occ/instm/AVPlayer/' + m; 323 | link = 'AVPlayer'; 324 | 325 | } 326 | 327 | if (clsdisp === "NSEvent") { 328 | var m = f.meth; 329 | if (m.substr(0, 3) === "set") m = m.substr(3, 1).toLowerCase() + m.substr(4); 330 | var url = 'https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/#//apple_ref/occ/instm/NSEvent/' + m; 331 | link = 'NSEvent'; 332 | } 333 | 334 | if (m === 'V8New') link = null; 335 | 336 | if (link !== null) { 337 | link = '[' + link + ']'; 338 | html = html.replace('', link + ''); 339 | } 340 | 341 | html = '' + html; 342 | html = html.replace('
', '
');
343 |   html = html.replace('', '\n
') + '
'; 344 | 345 | bodyhtml += html; 346 | } 347 | 348 | console.log(header); 349 | console.log('
' + tochtml + '
'); 350 | console.log('
' + bodyhtml + '
'); 351 | console.log(footer); 352 | -------------------------------------------------------------------------------- /docs/prism.js: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism&languages=clike+javascript */ 2 | self = (typeof window !== 'undefined') 3 | ? window // if in browser 4 | : ( 5 | (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) 6 | ? self // if in worker 7 | : {} // if in node js 8 | ); 9 | 10 | /** 11 | * Prism: Lightweight, robust, elegant syntax highlighting 12 | * MIT license http://www.opensource.org/licenses/mit-license.php/ 13 | * @author Lea Verou http://lea.verou.me 14 | */ 15 | 16 | var Prism = (function(){ 17 | 18 | // Private helper vars 19 | var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i; 20 | 21 | var _ = self.Prism = { 22 | util: { 23 | encode: function (tokens) { 24 | if (tokens instanceof Token) { 25 | return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias); 26 | } else if (_.util.type(tokens) === 'Array') { 27 | return tokens.map(_.util.encode); 28 | } else { 29 | return tokens.replace(/&/g, '&').replace(/ text.length) { 270 | // Something went terribly wrong, ABORT, ABORT! 271 | break tokenloop; 272 | } 273 | 274 | if (str instanceof Token) { 275 | continue; 276 | } 277 | 278 | pattern.lastIndex = 0; 279 | 280 | var match = pattern.exec(str); 281 | 282 | if (match) { 283 | if(lookbehind) { 284 | lookbehindLength = match[1].length; 285 | } 286 | 287 | var from = match.index - 1 + lookbehindLength, 288 | match = match[0].slice(lookbehindLength), 289 | len = match.length, 290 | to = from + len, 291 | before = str.slice(0, from + 1), 292 | after = str.slice(to + 1); 293 | 294 | var args = [i, 1]; 295 | 296 | if (before) { 297 | args.push(before); 298 | } 299 | 300 | var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias); 301 | 302 | args.push(wrapped); 303 | 304 | if (after) { 305 | args.push(after); 306 | } 307 | 308 | Array.prototype.splice.apply(strarr, args); 309 | } 310 | } 311 | } 312 | } 313 | 314 | return strarr; 315 | }, 316 | 317 | hooks: { 318 | all: {}, 319 | 320 | add: function (name, callback) { 321 | var hooks = _.hooks.all; 322 | 323 | hooks[name] = hooks[name] || []; 324 | 325 | hooks[name].push(callback); 326 | }, 327 | 328 | run: function (name, env) { 329 | var callbacks = _.hooks.all[name]; 330 | 331 | if (!callbacks || !callbacks.length) { 332 | return; 333 | } 334 | 335 | for (var i=0, callback; callback = callbacks[i++];) { 336 | callback(env); 337 | } 338 | } 339 | } 340 | }; 341 | 342 | var Token = _.Token = function(type, content, alias) { 343 | this.type = type; 344 | this.content = content; 345 | this.alias = alias; 346 | }; 347 | 348 | Token.stringify = function(o, language, parent) { 349 | if (typeof o == 'string') { 350 | return o; 351 | } 352 | 353 | if (Object.prototype.toString.call(o) == '[object Array]') { 354 | return o.map(function(element) { 355 | return Token.stringify(element, language, o); 356 | }).join(''); 357 | } 358 | 359 | var env = { 360 | type: o.type, 361 | content: Token.stringify(o.content, language, parent), 362 | tag: 'span', 363 | classes: ['token', o.type], 364 | attributes: {}, 365 | language: language, 366 | parent: parent 367 | }; 368 | 369 | if (env.type == 'comment') { 370 | env.attributes['spellcheck'] = 'true'; 371 | } 372 | 373 | if (o.alias) { 374 | var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; 375 | Array.prototype.push.apply(env.classes, aliases); 376 | } 377 | 378 | _.hooks.run('wrap', env); 379 | 380 | var attributes = ''; 381 | 382 | for (var name in env.attributes) { 383 | attributes += name + '="' + (env.attributes[name] || '') + '"'; 384 | } 385 | 386 | return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + ''; 387 | 388 | }; 389 | 390 | if (!self.document) { 391 | if (!self.addEventListener) { 392 | // in Node.js 393 | return self.Prism; 394 | } 395 | // In worker 396 | self.addEventListener('message', function(evt) { 397 | var message = JSON.parse(evt.data), 398 | lang = message.language, 399 | code = message.code; 400 | 401 | self.postMessage(JSON.stringify(_.util.encode(_.tokenize(code, _.languages[lang])))); 402 | self.close(); 403 | }, false); 404 | 405 | return self.Prism; 406 | } 407 | 408 | // Get current script and highlight 409 | var script = document.getElementsByTagName('script'); 410 | 411 | script = script[script.length - 1]; 412 | 413 | if (script) { 414 | _.filename = script.src; 415 | 416 | if (document.addEventListener && !script.hasAttribute('data-manual')) { 417 | document.addEventListener('DOMContentLoaded', _.highlightAll); 418 | } 419 | } 420 | 421 | return self.Prism; 422 | 423 | })(); 424 | 425 | if (typeof module !== 'undefined' && module.exports) { 426 | module.exports = Prism; 427 | } 428 | ; 429 | Prism.languages.clike = { 430 | 'comment': [ 431 | { 432 | pattern: /(^|[^\\])\/\*[\w\W]*?\*\//g, 433 | lookbehind: true 434 | }, 435 | { 436 | pattern: /(^|[^\\:])\/\/.*?(\r?\n|$)/g, 437 | lookbehind: true 438 | } 439 | ], 440 | 'string': /("|')(\\\n|\\?.)*?\1/g, 441 | 'class-name': { 442 | pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig, 443 | lookbehind: true, 444 | inside: { 445 | punctuation: /(\.|\\)/ 446 | } 447 | }, 448 | 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g, 449 | 'boolean': /\b(true|false)\b/g, 450 | 'function': { 451 | pattern: /[a-z0-9_]+\(/ig, 452 | inside: { 453 | punctuation: /\(/ 454 | } 455 | }, 456 | 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g, 457 | 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|~|\^|%/g, 458 | 'ignore': /&(lt|gt|amp);/gi, 459 | 'punctuation': /[{}[\];(),.:]/g 460 | }; 461 | ; 462 | Prism.languages.javascript = Prism.languages.extend('clike', { 463 | 'keyword': /\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/g, 464 | 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|-?Infinity)\b/g, 465 | 'function': /(?!\d)[a-z0-9_$]+(?=\()/ig 466 | }); 467 | 468 | Prism.languages.insertBefore('javascript', 'keyword', { 469 | 'regex': { 470 | pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g, 471 | lookbehind: true 472 | } 473 | }); 474 | 475 | if (Prism.languages.markup) { 476 | Prism.languages.insertBefore('markup', 'tag', { 477 | 'script': { 478 | pattern: /[\w\W]*?<\/script>/ig, 479 | inside: { 480 | 'tag': { 481 | pattern: /|<\/script>/ig, 482 | inside: Prism.languages.markup.tag.inside 483 | }, 484 | rest: Prism.languages.javascript 485 | }, 486 | alias: 'language-javascript' 487 | } 488 | }); 489 | } 490 | ; 491 | -------------------------------------------------------------------------------- /docs/webgl2.idl: -------------------------------------------------------------------------------- 1 | // AUTOGENERATED FILE -- DO NOT EDIT -- SEE Makefile 2 | // 3 | // WebGL IDL definitions scraped from the Khronos specification: 4 | // https://www.khronos.org/registry/webgl/specs/latest/ 5 | // 6 | // This IDL depends on the typed array specification defined at: 7 | // https://www.khronos.org/registry/typedarray/specs/latest/typedarrays.idl 8 | 9 | typedef long long GLint64; 10 | typedef unsigned long long GLuint64; 11 | 12 | 13 | interface WebGLQuery : WebGLObject { 14 | }; 15 | 16 | interface WebGLSampler : WebGLObject { 17 | }; 18 | 19 | interface WebGLSync : WebGLObject { 20 | }; 21 | 22 | interface WebGLTransformFeedback : WebGLObject { 23 | }; 24 | 25 | interface WebGLVertexArrayObject : WebGLObject { 26 | }; 27 | 28 | [NoInterfaceObject] 29 | interface WebGL2RenderingContextBase 30 | { 31 | const GLenum READ_BUFFER = 0x0C02; 32 | const GLenum UNPACK_ROW_LENGTH = 0x0CF2; 33 | const GLenum UNPACK_SKIP_ROWS = 0x0CF3; 34 | const GLenum UNPACK_SKIP_PIXELS = 0x0CF4; 35 | const GLenum PACK_ROW_LENGTH = 0x0D02; 36 | const GLenum PACK_SKIP_ROWS = 0x0D03; 37 | const GLenum PACK_SKIP_PIXELS = 0x0D04; 38 | const GLenum COLOR = 0x1800; 39 | const GLenum DEPTH = 0x1801; 40 | const GLenum STENCIL = 0x1802; 41 | const GLenum RED = 0x1903; 42 | const GLenum RGB8 = 0x8051; 43 | const GLenum RGBA8 = 0x8058; 44 | const GLenum RGB10_A2 = 0x8059; 45 | const GLenum TEXTURE_BINDING_3D = 0x806A; 46 | const GLenum UNPACK_SKIP_IMAGES = 0x806D; 47 | const GLenum UNPACK_IMAGE_HEIGHT = 0x806E; 48 | const GLenum TEXTURE_3D = 0x806F; 49 | const GLenum TEXTURE_WRAP_R = 0x8072; 50 | const GLenum MAX_3D_TEXTURE_SIZE = 0x8073; 51 | const GLenum UNSIGNED_INT_2_10_10_10_REV = 0x8368; 52 | const GLenum MAX_ELEMENTS_VERTICES = 0x80E8; 53 | const GLenum MAX_ELEMENTS_INDICES = 0x80E9; 54 | const GLenum TEXTURE_MIN_LOD = 0x813A; 55 | const GLenum TEXTURE_MAX_LOD = 0x813B; 56 | const GLenum TEXTURE_BASE_LEVEL = 0x813C; 57 | const GLenum TEXTURE_MAX_LEVEL = 0x813D; 58 | const GLenum MIN = 0x8007; 59 | const GLenum MAX = 0x8008; 60 | const GLenum DEPTH_COMPONENT24 = 0x81A6; 61 | const GLenum MAX_TEXTURE_LOD_BIAS = 0x84FD; 62 | const GLenum TEXTURE_COMPARE_MODE = 0x884C; 63 | const GLenum TEXTURE_COMPARE_FUNC = 0x884D; 64 | const GLenum CURRENT_QUERY = 0x8865; 65 | const GLenum QUERY_RESULT = 0x8866; 66 | const GLenum QUERY_RESULT_AVAILABLE = 0x8867; 67 | const GLenum STREAM_READ = 0x88E1; 68 | const GLenum STREAM_COPY = 0x88E2; 69 | const GLenum STATIC_READ = 0x88E5; 70 | const GLenum STATIC_COPY = 0x88E6; 71 | const GLenum DYNAMIC_READ = 0x88E9; 72 | const GLenum DYNAMIC_COPY = 0x88EA; 73 | const GLenum MAX_DRAW_BUFFERS = 0x8824; 74 | const GLenum DRAW_BUFFER0 = 0x8825; 75 | const GLenum DRAW_BUFFER1 = 0x8826; 76 | const GLenum DRAW_BUFFER2 = 0x8827; 77 | const GLenum DRAW_BUFFER3 = 0x8828; 78 | const GLenum DRAW_BUFFER4 = 0x8829; 79 | const GLenum DRAW_BUFFER5 = 0x882A; 80 | const GLenum DRAW_BUFFER6 = 0x882B; 81 | const GLenum DRAW_BUFFER7 = 0x882C; 82 | const GLenum DRAW_BUFFER8 = 0x882D; 83 | const GLenum DRAW_BUFFER9 = 0x882E; 84 | const GLenum DRAW_BUFFER10 = 0x882F; 85 | const GLenum DRAW_BUFFER11 = 0x8830; 86 | const GLenum DRAW_BUFFER12 = 0x8831; 87 | const GLenum DRAW_BUFFER13 = 0x8832; 88 | const GLenum DRAW_BUFFER14 = 0x8833; 89 | const GLenum DRAW_BUFFER15 = 0x8834; 90 | const GLenum MAX_FRAGMENT_UNIFORM_COMPONENTS = 0x8B49; 91 | const GLenum MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A; 92 | const GLenum SAMPLER_3D = 0x8B5F; 93 | const GLenum SAMPLER_2D_SHADOW = 0x8B62; 94 | const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT = 0x8B8B; 95 | const GLenum PIXEL_PACK_BUFFER = 0x88EB; 96 | const GLenum PIXEL_UNPACK_BUFFER = 0x88EC; 97 | const GLenum PIXEL_PACK_BUFFER_BINDING = 0x88ED; 98 | const GLenum PIXEL_UNPACK_BUFFER_BINDING = 0x88EF; 99 | const GLenum FLOAT_MAT2x3 = 0x8B65; 100 | const GLenum FLOAT_MAT2x4 = 0x8B66; 101 | const GLenum FLOAT_MAT3x2 = 0x8B67; 102 | const GLenum FLOAT_MAT3x4 = 0x8B68; 103 | const GLenum FLOAT_MAT4x2 = 0x8B69; 104 | const GLenum FLOAT_MAT4x3 = 0x8B6A; 105 | const GLenum SRGB = 0x8C40; 106 | const GLenum SRGB8 = 0x8C41; 107 | const GLenum SRGB8_ALPHA8 = 0x8C43; 108 | const GLenum COMPARE_REF_TO_TEXTURE = 0x884E; 109 | const GLenum RGBA32F = 0x8814; 110 | const GLenum RGB32F = 0x8815; 111 | const GLenum RGBA16F = 0x881A; 112 | const GLenum RGB16F = 0x881B; 113 | const GLenum VERTEX_ATTRIB_ARRAY_INTEGER = 0x88FD; 114 | const GLenum MAX_ARRAY_TEXTURE_LAYERS = 0x88FF; 115 | const GLenum MIN_PROGRAM_TEXEL_OFFSET = 0x8904; 116 | const GLenum MAX_PROGRAM_TEXEL_OFFSET = 0x8905; 117 | const GLenum MAX_VARYING_COMPONENTS = 0x8B4B; 118 | const GLenum TEXTURE_2D_ARRAY = 0x8C1A; 119 | const GLenum TEXTURE_BINDING_2D_ARRAY = 0x8C1D; 120 | const GLenum R11F_G11F_B10F = 0x8C3A; 121 | const GLenum UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B; 122 | const GLenum RGB9_E5 = 0x8C3D; 123 | const GLenum UNSIGNED_INT_5_9_9_9_REV = 0x8C3E; 124 | const GLenum TRANSFORM_FEEDBACK_BUFFER_MODE = 0x8C7F; 125 | const GLenum MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 0x8C80; 126 | const GLenum TRANSFORM_FEEDBACK_VARYINGS = 0x8C83; 127 | const GLenum TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84; 128 | const GLenum TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85; 129 | const GLenum TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 0x8C88; 130 | const GLenum RASTERIZER_DISCARD = 0x8C89; 131 | const GLenum MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 0x8C8A; 132 | const GLenum MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B; 133 | const GLenum INTERLEAVED_ATTRIBS = 0x8C8C; 134 | const GLenum SEPARATE_ATTRIBS = 0x8C8D; 135 | const GLenum TRANSFORM_FEEDBACK_BUFFER = 0x8C8E; 136 | const GLenum TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F; 137 | const GLenum RGBA32UI = 0x8D70; 138 | const GLenum RGB32UI = 0x8D71; 139 | const GLenum RGBA16UI = 0x8D76; 140 | const GLenum RGB16UI = 0x8D77; 141 | const GLenum RGBA8UI = 0x8D7C; 142 | const GLenum RGB8UI = 0x8D7D; 143 | const GLenum RGBA32I = 0x8D82; 144 | const GLenum RGB32I = 0x8D83; 145 | const GLenum RGBA16I = 0x8D88; 146 | const GLenum RGB16I = 0x8D89; 147 | const GLenum RGBA8I = 0x8D8E; 148 | const GLenum RGB8I = 0x8D8F; 149 | const GLenum RED_INTEGER = 0x8D94; 150 | const GLenum RGB_INTEGER = 0x8D98; 151 | const GLenum RGBA_INTEGER = 0x8D99; 152 | const GLenum SAMPLER_2D_ARRAY = 0x8DC1; 153 | const GLenum SAMPLER_2D_ARRAY_SHADOW = 0x8DC4; 154 | const GLenum SAMPLER_CUBE_SHADOW = 0x8DC5; 155 | const GLenum UNSIGNED_INT_VEC2 = 0x8DC6; 156 | const GLenum UNSIGNED_INT_VEC3 = 0x8DC7; 157 | const GLenum UNSIGNED_INT_VEC4 = 0x8DC8; 158 | const GLenum INT_SAMPLER_2D = 0x8DCA; 159 | const GLenum INT_SAMPLER_3D = 0x8DCB; 160 | const GLenum INT_SAMPLER_CUBE = 0x8DCC; 161 | const GLenum INT_SAMPLER_2D_ARRAY = 0x8DCF; 162 | const GLenum UNSIGNED_INT_SAMPLER_2D = 0x8DD2; 163 | const GLenum UNSIGNED_INT_SAMPLER_3D = 0x8DD3; 164 | const GLenum UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4; 165 | const GLenum UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7; 166 | const GLenum DEPTH_COMPONENT32F = 0x8CAC; 167 | const GLenum DEPTH32F_STENCIL8 = 0x8CAD; 168 | const GLenum FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD; 169 | const GLenum FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210; 170 | const GLenum FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE = 0x8211; 171 | const GLenum FRAMEBUFFER_ATTACHMENT_RED_SIZE = 0x8212; 172 | const GLenum FRAMEBUFFER_ATTACHMENT_GREEN_SIZE = 0x8213; 173 | const GLenum FRAMEBUFFER_ATTACHMENT_BLUE_SIZE = 0x8214; 174 | const GLenum FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE = 0x8215; 175 | const GLenum FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE = 0x8216; 176 | const GLenum FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE = 0x8217; 177 | const GLenum FRAMEBUFFER_DEFAULT = 0x8218; 178 | const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A; 179 | const GLenum DEPTH_STENCIL = 0x84F9; 180 | const GLenum UNSIGNED_INT_24_8 = 0x84FA; 181 | const GLenum DEPTH24_STENCIL8 = 0x88F0; 182 | const GLenum UNSIGNED_NORMALIZED = 0x8C17; 183 | const GLenum DRAW_FRAMEBUFFER_BINDING = 0x8CA6; /* Same as FRAMEBUFFER_BINDING */ 184 | const GLenum READ_FRAMEBUFFER = 0x8CA8; 185 | const GLenum DRAW_FRAMEBUFFER = 0x8CA9; 186 | const GLenum READ_FRAMEBUFFER_BINDING = 0x8CAA; 187 | const GLenum RENDERBUFFER_SAMPLES = 0x8CAB; 188 | const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = 0x8CD4; 189 | const GLenum MAX_COLOR_ATTACHMENTS = 0x8CDF; 190 | const GLenum COLOR_ATTACHMENT1 = 0x8CE1; 191 | const GLenum COLOR_ATTACHMENT2 = 0x8CE2; 192 | const GLenum COLOR_ATTACHMENT3 = 0x8CE3; 193 | const GLenum COLOR_ATTACHMENT4 = 0x8CE4; 194 | const GLenum COLOR_ATTACHMENT5 = 0x8CE5; 195 | const GLenum COLOR_ATTACHMENT6 = 0x8CE6; 196 | const GLenum COLOR_ATTACHMENT7 = 0x8CE7; 197 | const GLenum COLOR_ATTACHMENT8 = 0x8CE8; 198 | const GLenum COLOR_ATTACHMENT9 = 0x8CE9; 199 | const GLenum COLOR_ATTACHMENT10 = 0x8CEA; 200 | const GLenum COLOR_ATTACHMENT11 = 0x8CEB; 201 | const GLenum COLOR_ATTACHMENT12 = 0x8CEC; 202 | const GLenum COLOR_ATTACHMENT13 = 0x8CED; 203 | const GLenum COLOR_ATTACHMENT14 = 0x8CEE; 204 | const GLenum COLOR_ATTACHMENT15 = 0x8CEF; 205 | const GLenum FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8D56; 206 | const GLenum MAX_SAMPLES = 0x8D57; 207 | const GLenum HALF_FLOAT = 0x140B; 208 | const GLenum RG = 0x8227; 209 | const GLenum RG_INTEGER = 0x8228; 210 | const GLenum R8 = 0x8229; 211 | const GLenum RG8 = 0x822B; 212 | const GLenum R16F = 0x822D; 213 | const GLenum R32F = 0x822E; 214 | const GLenum RG16F = 0x822F; 215 | const GLenum RG32F = 0x8230; 216 | const GLenum R8I = 0x8231; 217 | const GLenum R8UI = 0x8232; 218 | const GLenum R16I = 0x8233; 219 | const GLenum R16UI = 0x8234; 220 | const GLenum R32I = 0x8235; 221 | const GLenum R32UI = 0x8236; 222 | const GLenum RG8I = 0x8237; 223 | const GLenum RG8UI = 0x8238; 224 | const GLenum RG16I = 0x8239; 225 | const GLenum RG16UI = 0x823A; 226 | const GLenum RG32I = 0x823B; 227 | const GLenum RG32UI = 0x823C; 228 | const GLenum VERTEX_ARRAY_BINDING = 0x85B5; 229 | const GLenum R8_SNORM = 0x8F94; 230 | const GLenum RG8_SNORM = 0x8F95; 231 | const GLenum RGB8_SNORM = 0x8F96; 232 | const GLenum RGBA8_SNORM = 0x8F97; 233 | const GLenum SIGNED_NORMALIZED = 0x8F9C; 234 | const GLenum PRIMITIVE_RESTART_FIXED_INDEX = 0x8D69; 235 | const GLenum COPY_READ_BUFFER = 0x8F36; 236 | const GLenum COPY_WRITE_BUFFER = 0x8F37; 237 | const GLenum COPY_READ_BUFFER_BINDING = 0x8F36; /* Same as COPY_READ_BUFFER */ 238 | const GLenum COPY_WRITE_BUFFER_BINDING = 0x8F37; /* Same as COPY_WRITE_BUFFER */ 239 | const GLenum UNIFORM_BUFFER = 0x8A11; 240 | const GLenum UNIFORM_BUFFER_BINDING = 0x8A28; 241 | const GLenum UNIFORM_BUFFER_START = 0x8A29; 242 | const GLenum UNIFORM_BUFFER_SIZE = 0x8A2A; 243 | const GLenum MAX_VERTEX_UNIFORM_BLOCKS = 0x8A2B; 244 | const GLenum MAX_FRAGMENT_UNIFORM_BLOCKS = 0x8A2D; 245 | const GLenum MAX_COMBINED_UNIFORM_BLOCKS = 0x8A2E; 246 | const GLenum MAX_UNIFORM_BUFFER_BINDINGS = 0x8A2F; 247 | const GLenum MAX_UNIFORM_BLOCK_SIZE = 0x8A30; 248 | const GLenum MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 0x8A31; 249 | const GLenum MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 0x8A33; 250 | const GLenum UNIFORM_BUFFER_OFFSET_ALIGNMENT = 0x8A34; 251 | const GLenum ACTIVE_UNIFORM_BLOCKS = 0x8A36; 252 | const GLenum UNIFORM_TYPE = 0x8A37; 253 | const GLenum UNIFORM_SIZE = 0x8A38; 254 | const GLenum UNIFORM_BLOCK_INDEX = 0x8A3A; 255 | const GLenum UNIFORM_OFFSET = 0x8A3B; 256 | const GLenum UNIFORM_ARRAY_STRIDE = 0x8A3C; 257 | const GLenum UNIFORM_MATRIX_STRIDE = 0x8A3D; 258 | const GLenum UNIFORM_IS_ROW_MAJOR = 0x8A3E; 259 | const GLenum UNIFORM_BLOCK_BINDING = 0x8A3F; 260 | const GLenum UNIFORM_BLOCK_DATA_SIZE = 0x8A40; 261 | const GLenum UNIFORM_BLOCK_ACTIVE_UNIFORMS = 0x8A42; 262 | const GLenum UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8A43; 263 | const GLenum UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8A44; 264 | const GLenum UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8A46; 265 | const GLenum INVALID_INDEX = 0xFFFFFFFF; 266 | const GLenum MAX_VERTEX_OUTPUT_COMPONENTS = 0x9122; 267 | const GLenum MAX_FRAGMENT_INPUT_COMPONENTS = 0x9125; 268 | const GLenum MAX_SERVER_WAIT_TIMEOUT = 0x9111; 269 | const GLenum OBJECT_TYPE = 0x9112; 270 | const GLenum SYNC_CONDITION = 0x9113; 271 | const GLenum SYNC_STATUS = 0x9114; 272 | const GLenum SYNC_FLAGS = 0x9115; 273 | const GLenum SYNC_FENCE = 0x9116; 274 | const GLenum SYNC_GPU_COMMANDS_COMPLETE = 0x9117; 275 | const GLenum UNSIGNALED = 0x9118; 276 | const GLenum SIGNALED = 0x9119; 277 | const GLenum ALREADY_SIGNALED = 0x911A; 278 | const GLenum TIMEOUT_EXPIRED = 0x911B; 279 | const GLenum CONDITION_SATISFIED = 0x911C; 280 | const GLenum WAIT_FAILED = 0x911D; 281 | const GLenum SYNC_FLUSH_COMMANDS_BIT = 0x00000001; 282 | const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88FE; 283 | const GLenum ANY_SAMPLES_PASSED = 0x8C2F; 284 | const GLenum ANY_SAMPLES_PASSED_CONSERVATIVE = 0x8D6A; 285 | const GLenum SAMPLER_BINDING = 0x8919; 286 | const GLenum RGB10_A2UI = 0x906F; 287 | const GLenum TEXTURE_SWIZZLE_R = 0x8E42; 288 | const GLenum TEXTURE_SWIZZLE_G = 0x8E43; 289 | const GLenum TEXTURE_SWIZZLE_B = 0x8E44; 290 | const GLenum TEXTURE_SWIZZLE_A = 0x8E45; 291 | const GLenum GREEN = 0x1904; 292 | const GLenum BLUE = 0x1905; 293 | const GLenum INT_2_10_10_10_REV = 0x8D9F; 294 | const GLenum TRANSFORM_FEEDBACK = 0x8E22; 295 | const GLenum TRANSFORM_FEEDBACK_PAUSED = 0x8E23; 296 | const GLenum TRANSFORM_FEEDBACK_ACTIVE = 0x8E24; 297 | const GLenum TRANSFORM_FEEDBACK_BINDING = 0x8E25; 298 | const GLenum COMPRESSED_R11_EAC = 0x9270; 299 | const GLenum COMPRESSED_SIGNED_R11_EAC = 0x9271; 300 | const GLenum COMPRESSED_RG11_EAC = 0x9272; 301 | const GLenum COMPRESSED_SIGNED_RG11_EAC = 0x9273; 302 | const GLenum COMPRESSED_RGB8_ETC2 = 0x9274; 303 | const GLenum COMPRESSED_SRGB8_ETC2 = 0x9275; 304 | const GLenum COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276; 305 | const GLenum COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277; 306 | const GLenum COMPRESSED_RGBA8_ETC2_EAC = 0x9278; 307 | const GLenum COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279; 308 | const GLenum TEXTURE_IMMUTABLE_FORMAT = 0x912F; 309 | const GLenum MAX_ELEMENT_INDEX = 0x8D6B; 310 | const GLenum NUM_SAMPLE_COUNTS = 0x9380; 311 | const GLenum TEXTURE_IMMUTABLE_LEVELS = 0x82DF; 312 | 313 | const GLuint64 TIMEOUT_IGNORED = 0xFFFFFFFFFFFFFFFF; 314 | 315 | /* Buffer objects */ 316 | void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, 317 | GLintptr writeOffset, GLsizeiptr size); 318 | // MapBufferRange, in particular its read-only and write-only modes, 319 | // can not be exposed safely to JavaScript. GetBufferSubData 320 | // replaces it for the purpose of fetching data back from the GPU. 321 | void getBufferSubData(GLenum target, GLintptr offset, ArrayBufferData returnedData); 322 | 323 | /* Framebuffer objects */ 324 | void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, 325 | GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); 326 | void framebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, 327 | GLint layer); 328 | any getInternalformatParameter(GLenum target, GLenum internalformat, GLenum pname); 329 | void invalidateFramebuffer(GLenum target, sequence attachments); 330 | void invalidateSubFramebuffer(GLenum target, sequence attachments, 331 | GLint x, GLint y, GLsizei width, GLsizei height); 332 | void readBuffer(GLenum src); 333 | 334 | /* Renderbuffer objects */ 335 | void renderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, 336 | GLsizei width, GLsizei height); 337 | 338 | /* Texture objects */ 339 | void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); 340 | void texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, 341 | GLsizei depth); 342 | void texImage3D(GLenum target, GLint level, GLint internalformat, 343 | GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, 344 | GLenum type, ArrayBufferView? pixels); 345 | void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, 346 | GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, 347 | ArrayBufferView? pixels); 348 | void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, 349 | GLenum format, GLenum type, TexImageSource? source); 350 | void copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, 351 | GLint x, GLint y, GLsizei width, GLsizei height); 352 | void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat, 353 | GLsizei width, GLsizei height, GLsizei depth, 354 | GLint border, GLsizei imageSize, ArrayBufferView data); 355 | void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, 356 | GLsizei width, GLsizei height, GLsizei depth, 357 | GLenum format, GLsizei imageSize, ArrayBufferView data); 358 | 359 | /* Programs and shaders */ 360 | [WebGLHandlesContextLoss] GLint getFragDataLocation(WebGLProgram? program, DOMString name); 361 | 362 | /* Uniforms and attributes */ 363 | void uniform1ui(WebGLUniformLocation? location, GLuint v0); 364 | void uniform2ui(WebGLUniformLocation? location, GLuint v0, GLuint v1); 365 | void uniform3ui(WebGLUniformLocation? location, GLuint v0, GLuint v1, GLuint v2); 366 | void uniform4ui(WebGLUniformLocation? location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); 367 | void uniform1uiv(WebGLUniformLocation? location, sequence value); 368 | void uniform2uiv(WebGLUniformLocation? location, sequence value); 369 | void uniform3uiv(WebGLUniformLocation? location, sequence value); 370 | void uniform4uiv(WebGLUniformLocation? location, sequence value); 371 | typedef (Float32Array or sequence) UniformMatrixFVSource; 372 | void uniformMatrix2x3fv(WebGLUniformLocation? location, GLboolean transpose, UniformMatrixFVSource value); 373 | void uniformMatrix3x2fv(WebGLUniformLocation? location, GLboolean transpose, UniformMatrixFVSource value); 374 | void uniformMatrix2x4fv(WebGLUniformLocation? location, GLboolean transpose, UniformMatrixFVSource value); 375 | void uniformMatrix4x2fv(WebGLUniformLocation? location, GLboolean transpose, UniformMatrixFVSource value); 376 | void uniformMatrix3x4fv(WebGLUniformLocation? location, GLboolean transpose, UniformMatrixFVSource value); 377 | void uniformMatrix4x3fv(WebGLUniformLocation? location, GLboolean transpose, UniformMatrixFVSource value); 378 | void vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w); 379 | void vertexAttribI4iv(GLuint index, sequence v); 380 | void vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); 381 | void vertexAttribI4uiv(GLuint index, sequence v); 382 | void vertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); 383 | 384 | /* Writing to the drawing buffer */ 385 | void vertexAttribDivisor(GLuint index, GLuint divisor); 386 | void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); 387 | void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei instanceCount); 388 | /* TODO(kbr): argue against exposing this because it can't safely 389 | offer better performance than drawElements */ 390 | void drawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLintptr offset); 391 | 392 | /* Multiple Render Targets */ 393 | void drawBuffers(sequence buffers); 394 | typedef (Int32Array or sequence) ClearBufferIVSource; 395 | typedef (Uint32Array or sequence) ClearBufferUIVSource; 396 | typedef (Float32Array or sequence) ClearBufferFVSource; 397 | void clearBufferiv(GLenum buffer, GLint drawbuffer, ClearBufferIVSource value); 398 | void clearBufferuiv(GLenum buffer, GLint drawbuffer, ClearBufferUIVSource value); 399 | void clearBufferfv(GLenum buffer, GLint drawbuffer, ClearBufferFVSource value); 400 | void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); 401 | 402 | /* Query Objects */ 403 | WebGLQuery? createQuery(); 404 | void deleteQuery(WebGLQuery? query); 405 | [WebGLHandlesContextLoss] GLboolean isQuery(WebGLQuery? query); 406 | void beginQuery(GLenum target, WebGLQuery? query); 407 | void endQuery(GLenum target); 408 | WebGLQuery? getQuery(GLenum target, GLenum pname); 409 | any getQueryParameter(WebGLQuery? query, GLenum pname); 410 | 411 | /* Sampler Objects */ 412 | WebGLSampler? createSampler(); 413 | void deleteSampler(WebGLSampler? sampler); 414 | [WebGLHandlesContextLoss] GLboolean isSampler(WebGLSampler? sampler); 415 | void bindSampler(GLuint unit, WebGLSampler? sampler); 416 | void samplerParameteri(WebGLSampler? sampler, GLenum pname, GLint param); 417 | void samplerParameterf(WebGLSampler? sampler, GLenum pname, GLfloat param); 418 | any getSamplerParameter(WebGLSampler? sampler, GLenum pname); 419 | 420 | /* Sync objects */ 421 | WebGLSync? fenceSync(GLenum condition, GLbitfield flags); 422 | [WebGLHandlesContextLoss] GLboolean isSync(WebGLSync? sync); 423 | void deleteSync(WebGLSync? sync); 424 | GLenum clientWaitSync(WebGLSync? sync, GLbitfield flags, GLuint64 timeout); 425 | void waitSync(WebGLSync? sync, GLbitfield flags, GLuint64 timeout); 426 | any getSyncParameter(WebGLSync? sync, GLenum pname); 427 | 428 | /* Transform Feedback */ 429 | WebGLTransformFeedback? createTransformFeedback(); 430 | void deleteTransformFeedback(WebGLTransformFeedback?); 431 | [WebGLHandlesContextLoss] GLboolean isTransformFeedback(WebGLTransformFeedback?); 432 | void bindTransformFeedback (GLenum target, WebGLTransformFeedback? id); 433 | void beginTransformFeedback(GLenum primitiveMode); 434 | void endTransformFeedback(); 435 | void transformFeedbackVaryings(WebGLProgram? program, sequence varyings, GLenum bufferMode); 436 | WebGLActiveInfo? getTransformFeedbackVarying(WebGLProgram? program, GLuint index); 437 | void pauseTransformFeedback(); 438 | void resumeTransformFeedback(); 439 | 440 | /* Uniform Buffer Objects and Transform Feedback Buffers */ 441 | void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer); 442 | void bindBufferRange(GLenum target, GLuint index, WebGLBuffer? buffer, GLintptr offset, GLsizeiptr size); 443 | any getIndexedParameter(GLenum target, GLuint index); 444 | sequence? getUniformIndices(WebGLProgram? program, sequence uniformNames); 445 | sequence? getActiveUniforms(WebGLProgram? program, sequence uniformIndices, GLenum pname); 446 | GLuint getUniformBlockIndex(WebGLProgram? program, DOMString uniformBlockName); 447 | any getActiveUniformBlockParameter(WebGLProgram? program, GLuint uniformBlockIndex, GLenum pname); 448 | /* TODO: if there were a fake enum for GL_UNIFORM_BLOCK_NAME, then this could be folded into getActiveUniformBlockParameter */ 449 | DOMString? getActiveUniformBlockName(WebGLProgram? program, GLuint uniformBlockIndex); 450 | void uniformBlockBinding(WebGLProgram? program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); 451 | 452 | /* Vertex Array Objects */ 453 | WebGLVertexArrayObject? createVertexArray(); 454 | void deleteVertexArray(WebGLVertexArrayObject? vertexArray); 455 | [WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray); 456 | void bindVertexArray(WebGLVertexArrayObject? array); 457 | }; 458 | WebGL2RenderingContextBase implements WebGLRenderingContextBase; 459 | 460 | interface WebGL2RenderingContext 461 | { 462 | }; 463 | WebGL2RenderingContext implements WebGL2RenderingContextBase; 464 | 465 | 466 | -------------------------------------------------------------------------------- /examples/001_hello_circle.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a red circle on a gray background. 3 | // 4 | 5 | // Plask follows the CommonJS specification for module loading. 6 | var plask = require('plask'); 7 | 8 | plask.simpleWindow({ 9 | init: function() { 10 | // The canvas is the drawing object, attached to the screen. 11 | // The paint holds the drawing settings: color, sizes, stoke/fill, etc. 12 | var canvas = this.canvas, paint = this.paint; 13 | 14 | // Set the paint to fill an anti-aliased dark red. 15 | paint.setFill(); // Fill is the default, so this is just for clarity. 16 | paint.setAntiAlias(true); 17 | paint.setColor(80, 0, 0, 255); 18 | }, 19 | 20 | draw: function() { 21 | var canvas = this.canvas, paint = this.paint; 22 | 23 | // Draw the light gray background. 24 | canvas.clear(230, 230, 230, 255); 25 | 26 | // By default our window will be 400x300, so our center is at 200x150. 27 | // Using the settings on our paint set above, draw a circle of radius 100px. 28 | canvas.drawCircle(paint, 200, 150, 100); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /examples/002_hello_circle_pulse.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a pulsing red circle on a gray background. 3 | // 4 | 5 | var plask = require('plask'); 6 | 7 | plask.simpleWindow({ 8 | init: function() { 9 | var canvas = this.canvas, paint = this.paint; 10 | 11 | // The call to framerate() sets up how often the screen should be redrawn. 12 | // By default, the value is 0, and the screen is only drawn once during 13 | // initialization, and then any time when redraw() is called. The value 14 | // is the number of frames that should be drawn every second. 15 | this.framerate(30); 16 | 17 | paint.setFill(); 18 | paint.setAntiAlias(true); 19 | paint.setColor(80, 0, 0, 255); 20 | }, 21 | 22 | draw: function() { 23 | var canvas = this.canvas, paint = this.paint; 24 | 25 | canvas.clear(230, 230, 230, 255); 26 | 27 | // The frametime property is automatically computed by simpleWindow(), and 28 | // contains the number of seconds since the window was created. 29 | var t = Math.sin(this.frametime) * 0.5 + 0.5; 30 | 31 | // The lerp function performs a linear interpolation between two values. 32 | // By cycling the value of the interpolation between 0 and 1, the radius 33 | // will cycle between 50 and 100 pixels. 34 | var radius = plask.lerp(50, 100, t); 35 | 36 | // The canvas object contains its width and height, which can be used to 37 | // compute the x and y coordinates of the center of the canvas. 38 | canvas.drawCircle(paint, canvas.width/2, canvas.height/2, radius); 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /examples/003_hello_circle_click.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a red circle on a gray background centered 3 | // where the mouse was clicked. 4 | // 5 | 6 | var plask = require('plask'); 7 | 8 | plask.simpleWindow({ 9 | init: function() { 10 | var canvas = this.canvas, paint = this.paint; 11 | 12 | // Keep track of where we want to draw the circle. 13 | this.center = {x: canvas.width/2, y: canvas.height/2}; 14 | 15 | // Plask follows the event emitter conventions of Node. The simpleWindow 16 | // object can be listened on for mouse and keyboard events. 17 | this.on('leftMouseDown', function(e) { 18 | this.center.x = e.x; 19 | this.center.y = e.y; 20 | // Since framerate() wasn't called, there is no draw timer set. The 21 | // draw() method call and screen update will only happen when we 22 | // explicitly call redraw(). 23 | this.redraw(); 24 | }); 25 | 26 | paint.setFill(); 27 | paint.setAntiAlias(true); 28 | paint.setColor(80, 0, 0, 255); 29 | }, 30 | 31 | draw: function() { 32 | var canvas = this.canvas, paint = this.paint; 33 | canvas.clear(230, 230, 230, 255); 34 | canvas.drawCircle(paint, this.center.x, this.center.y, 100); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /examples/004_hello_circle_drag.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a red circle on a gray background centered 3 | // where the mouse is dragged. 4 | // 5 | 6 | var plask = require('plask'); 7 | 8 | plask.simpleWindow({ 9 | init: function() { 10 | var canvas = this.canvas, paint = this.paint; 11 | 12 | this.center = {x: canvas.width/2, y: canvas.height/2}; 13 | 14 | function updatePosition(e) { 15 | this.center.x = e.x; 16 | this.center.y = e.y; 17 | this.redraw(); 18 | } 19 | 20 | // leftMouseClicked is only called once on a click, and not again if the 21 | // mouse is moved while clicked. leftMouseDragged is not called for the 22 | // initial click, but is called when the mouse is moved when the button is 23 | // held. Listen on both to get click and drag. Dragging can return 24 | // positions outside the window bounds. 25 | this.on('leftMouseDown', updatePosition); 26 | this.on('leftMouseDragged', updatePosition); 27 | 28 | paint.setFill(); 29 | paint.setAntiAlias(true); 30 | paint.setColor(80, 0, 0, 255); 31 | }, 32 | 33 | draw: function() { 34 | var canvas = this.canvas, paint = this.paint; 35 | canvas.clear(230, 230, 230, 255); 36 | canvas.drawCircle(paint, this.center.x, this.center.y, 100); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /examples/005_hello_circle_drag_spring.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a red circle on a gray background centered 3 | // where the mouse is dragged and springing back to the center when let go. 4 | // 5 | 6 | var plask = require('plask'); 7 | 8 | plask.simpleWindow({ 9 | init: function() { 10 | var canvas = this.canvas, paint = this.paint; 11 | 12 | this.center = {x: canvas.width/2, y: canvas.height/2}; 13 | this.mouse_down = false; 14 | 15 | this.framerate(30); // Run constantly for computing animations. 16 | 17 | function updatePosition(e) { 18 | this.center.x = e.x; 19 | this.center.y = e.y; 20 | this.mouse_down = true; 21 | // Don't redraw since a framerate timer is running. 22 | } 23 | 24 | // leftMouseClicked is only called once on a click, and not again if the 25 | // mouse is moved while clicked. leftMouseDragged is not called for the 26 | // initial click, but is called when the mouse is moved when the button is 27 | // held. Listen on both to get click and drag. Dragging can return 28 | // positions outside the window bounds. 29 | this.on('leftMouseDown', updatePosition); 30 | this.on('leftMouseDragged', updatePosition); 31 | this.on('leftMouseUp', function(e) { 32 | this.mouse_down = false; 33 | }); 34 | 35 | paint.setFill(); 36 | paint.setAntiAlias(true); 37 | paint.setColor(80, 0, 0, 255); 38 | }, 39 | 40 | draw: function() { 41 | var canvas = this.canvas, paint = this.paint; 42 | canvas.clear(230, 230, 230, 255); 43 | canvas.drawCircle(paint, this.center.x, this.center.y, 100); 44 | if (this.mouse_down === false) { 45 | // Not proper physics, but a simple non-linear tween. 46 | this.center.x = plask.lerp(this.center.x, canvas.width/2, 0.3); 47 | this.center.y = plask.lerp(this.center.y, canvas.height/2, 0.3); 48 | } 49 | } 50 | }); 51 | -------------------------------------------------------------------------------- /examples/006_hello_circle_follow.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a red circle on a gray background centered 3 | // where the mouse is moved. 4 | // 5 | 6 | var plask = require('plask'); 7 | 8 | plask.simpleWindow({ 9 | init: function() { 10 | var canvas = this.canvas, paint = this.paint; 11 | 12 | this.center = {x: canvas.width/2, y: canvas.height/2}; 13 | 14 | // It can be a bad idea to draw every time mouse event is received, 15 | // especially for mouse move events which can happen very frequently. 16 | // This example runs a normal framerate timer instead of calling redraw(). 17 | this.framerate(30); 18 | 19 | // Note that it can be troublesome to listen for mouseMoved as it 20 | // potentially generates a large amount of events. 21 | this.on('mouseMoved', function(e) { 22 | // Note that the mouse coordinates can go outside the window bounds. 23 | // Also note that when this example is first launched, the circle will 24 | // be centered even if the mouse is not, because a mouseMoved event will 25 | // not be received until the mouse is moved. 26 | this.center.x = e.x; 27 | this.center.y = e.y; 28 | }); 29 | 30 | paint.setFill(); 31 | paint.setAntiAlias(true); 32 | paint.setColor(80, 0, 0, 255); 33 | }, 34 | 35 | draw: function() { 36 | var canvas = this.canvas, paint = this.paint; 37 | canvas.clear(230, 230, 230, 255); 38 | canvas.drawCircle(paint, this.center.x, this.center.y, 100); 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /examples/007_hello_circle_keyboard.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a red circle on a gray background centered 3 | // where the mouse is moved. 4 | // 5 | 6 | var plask = require('plask'); 7 | 8 | plask.simpleWindow({ 9 | // Introducing the settings object, which allows you to set things like the 10 | // window width and height, title, window type and configuration, etc. 11 | settings: { 12 | width: 400, 13 | height: 300, 14 | title: "Move with the AWSD keys." 15 | }, 16 | 17 | init: function() { 18 | var canvas = this.canvas, paint = this.paint; 19 | 20 | this.center = {x: canvas.width/2, y: canvas.height/2}; 21 | 22 | this.on('keyDown', function(e) { 23 | // The |str| property on the key event is a string of the unicode 24 | // translation of the key. Take bigger steps while holding shift. 25 | switch (e.str) { 26 | case 'w': this.center.y -= 1; break; 27 | case 'W': this.center.y -= 10; break; 28 | case 's': this.center.y += 1; break; 29 | case 'S': this.center.y += 10; break; 30 | case 'a': this.center.x -= 1; break; 31 | case 'A': this.center.x -= 10; break; 32 | case 'd': this.center.x += 1; break; 33 | case 'D': this.center.x += 10; break; 34 | } 35 | this.redraw(); 36 | }); 37 | 38 | paint.setFill(); 39 | paint.setAntiAlias(true); 40 | paint.setColor(80, 0, 0, 255); 41 | }, 42 | 43 | draw: function() { 44 | var canvas = this.canvas, paint = this.paint; 45 | canvas.clear(230, 230, 230, 255); 46 | canvas.drawCircle(paint, this.center.x, this.center.y, 100); 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /examples/008_hello_circle_keyboard_arrows.js: -------------------------------------------------------------------------------- 1 | // 2 | // A simple Plask example, drawing a red circle on a gray background centered 3 | // where the mouse is moved. 4 | // 5 | 6 | var plask = require('plask'); 7 | 8 | plask.simpleWindow({ 9 | // Introducing the settings object, which allows you to set things like the 10 | // window width and height, title, window type and configuration, etc. 11 | settings: { 12 | width: 400, 13 | height: 300, 14 | title: "Move with the AWSD or arrow keys." 15 | }, 16 | 17 | init: function() { 18 | var canvas = this.canvas, paint = this.paint; 19 | 20 | this.center = {x: canvas.width/2, y: canvas.height/2}; 21 | 22 | this.on('keyDown', function(e) { 23 | // NOTE: The function keys are mapped into the private unicode area 24 | // 0xf700 by AppKit, see NSUpArrowFunctionKey and friends. 25 | switch (e.str) { 26 | case '\uf700': case 'w': case 'W': 27 | this.center.y -= e.shift ? 10 : 1; break; 28 | case '\uf701': case 's': case 'S': 29 | this.center.y += e.shift ? 10 : 1; break; 30 | case '\uf702': case 'a': case 'A': 31 | this.center.x -= e.shift ? 10 : 1; break; 32 | case '\uf703': case 'd': case 'D': 33 | this.center.x += e.shift ? 10 : 1; break; 34 | } 35 | 36 | // An alternative to the unicode |str| property is the low-level key 37 | // code. This has different semantics, for example, an 'A' key with 38 | // shift held is the same code as without shift held. Key codes are raw 39 | // identifiers of the keyboard, and generally you should use the |str| 40 | // property instead to account for keyboard layout and language. 41 | // 42 | // The keyCode version looks something like: 43 | // 44 | // switch (e.keyCode) { 45 | // case 126: case 13: this.center.y -= e.shift ? 10 : 1; break; 46 | // case 125: case 1: this.center.y += e.shift ? 10 : 1; break; 47 | // case 123: case 0: this.center.x -= e.shift ? 10 : 1; break; 48 | // case 124: case 2: this.center.x += e.shift ? 10 : 1; break; 49 | // } 50 | 51 | this.redraw(); 52 | }); 53 | 54 | paint.setFill(); 55 | paint.setAntiAlias(true); 56 | paint.setColor(80, 0, 0, 255); 57 | }, 58 | 59 | draw: function() { 60 | var canvas = this.canvas, paint = this.paint; 61 | canvas.clear(230, 230, 230, 255); 62 | canvas.drawCircle(paint, this.center.x, this.center.y, 100); 63 | } 64 | }); 65 | -------------------------------------------------------------------------------- /examples/010_image_drop.js: -------------------------------------------------------------------------------- 1 | // 2 | // A Plask example, painting images where they are dropped onto the window. 3 | // 4 | 5 | var plask = require('plask'); 6 | 7 | plask.simpleWindow({ 8 | settings: { 9 | width: 800, 10 | height: 600 11 | }, 12 | 13 | init: function() { 14 | var canvas = this.canvas, paint = this.paint; 15 | 16 | this.image = null; 17 | this.image_pos = {x: 0, y: 0}; 18 | 19 | this.on('filesDropped', function(e) { 20 | // Multiple files can be dropped at once, but for this example only the 21 | // first file is used. 22 | this.image = plask.SkCanvas.createFromImage(e.paths[0]); 23 | this.image_pos.x = e.x; this.image_pos.y = e.y; 24 | this.redraw(); 25 | }); 26 | 27 | canvas.clear(230, 230, 230, 255); // Draw the background, just once. 28 | }, 29 | 30 | draw: function() { 31 | var canvas = this.canvas, paint = this.paint; 32 | if (this.image !== null) { 33 | var p = this.image_pos; 34 | canvas.drawCanvas(paint, this.image, 35 | p.x, p.y, 36 | p.x + this.image.width, p.y + this.image.height); 37 | } 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /examples/030_midi_send.js: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2011. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | var plask = require('plask'); 23 | 24 | plask.simpleWindow({ 25 | settings: { 26 | width: 400, 27 | height: 300 28 | }, 29 | 30 | init: function() { 31 | this.framerate(30); 32 | var canvas = this.canvas, paint = this.paint; 33 | paint.setAntiAlias(true); 34 | 35 | var midi = new plask.MidiOut(); // Create a midi output. 36 | midi.createVirtual('030_midi_send'); // Make it a virtual output. 37 | 38 | canvas.clear(0, 0, 0, 255); // Draw the background. 39 | paint.setColor(0, 0, 255, 255); 40 | 41 | this.on('leftMouseDown', function(e) { 42 | var note = (e.x / this.width) * 50 + 50; 43 | var vel = (1 - (e.y / this.height)) * 127; 44 | 45 | // Trigger a 300ms long note. 46 | midi.noteOn(1, note, vel); // Send a MIDI note on channel 1. 47 | setTimeout(function() { midi.noteOff(1, note, vel); }, 300); 48 | 49 | canvas.drawCircle(paint, e.x, e.y, 10); 50 | }); 51 | }, 52 | 53 | draw: function() { 54 | var canvas = this.canvas, paint = this.paint; 55 | canvas.drawColor(0, 0, 0, 30); // Fade. 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /examples/031_midi_receive.js: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2011. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | var plask = require('plask'); 23 | 24 | // Given a list of points, fit a cubic bezier path smoothly through them. 25 | function pointsToCatmullPath(points, path) { 26 | for (var i = 3, il = points.length; i < il; ++i) { 27 | var p0 = points[i - 3]; 28 | var p1 = points[i - 2]; 29 | var p2 = points[i - 1]; 30 | var p3 = points[i] 31 | 32 | if (i === 3) path.moveTo(p1.x, p1.y); 33 | 34 | // Change of basis from Catmull-Rom to Bezier. 35 | // See Pyramid Algorithms by Ron Goldman. 36 | var c0x = (p2.x / 6) + p1.x - (p0.x / 6); 37 | var c0y = (p2.y / 6) + p1.y - (p0.y / 6); 38 | var c1x = (p3.x / -6) + p2.x + p1.x / 6; 39 | var c1y = (p3.y / -6) + p2.y + p1.y / 6; 40 | 41 | path.cubicTo(c0x, c0y, c1x, c1y, p2.x, p2.y); 42 | } 43 | return path; 44 | } 45 | 46 | plask.simpleWindow({ 47 | settings: { 48 | width: 400, 49 | height: 300 50 | }, 51 | 52 | init: function() { 53 | this.framerate(30); 54 | var canvas = this.canvas, paint = this.paint; 55 | 56 | paint.setAntiAlias(true); 57 | paint.setStroke(); 58 | paint.setStrokeWidth(2); 59 | paint.setColor(255, 0, 255, 255); 60 | 61 | this.path = new plask.SkPath(); // A path to reuse each draw(). 62 | 63 | var midi = new plask.MidiIn(); // Create a midi output. 64 | var sources = midi.sources(); 65 | if (sources.length === 0) 66 | throw "No available MIDI sources."; 67 | midi.openSource(sources.length - 1); 68 | console.log('Using midi source: ' + sources[sources.length - 1]); 69 | 70 | // In order to animate, keep two sets of states. What the current value is 71 | // and what it should be going towards. 72 | var cur_vel = Array(128); 73 | var dst_vel = Array(128); 74 | for (var i = 0, il = cur_vel.length; i < il; ++i) 75 | cur_vel[i] = dst_vel[i] = 0; 76 | 77 | this.cur_vel = cur_vel; 78 | this.dst_vel = dst_vel; 79 | 80 | midi.on('noteOn', function(e) { 81 | dst_vel[e.note] = e.vel / 127; 82 | }); 83 | 84 | midi.on('noteOff', function(e) { 85 | dst_vel[e.note] = 0; 86 | }); 87 | 88 | canvas.translate(this.width / 2, this.height / 2); // Center at (0, 0). 89 | }, 90 | 91 | draw: function() { 92 | var canvas = this.canvas, paint = this.paint, path = this.path; 93 | var cur_vel = this.cur_vel, dst_vel = this.dst_vel; 94 | 95 | var points = Array(128); 96 | for (var i = 0, il = points.length; i < il; ++i) { 97 | // Calculate the polar point. 98 | var theta = i / il * plask.k2PI; 99 | var r = cur_vel[i] * 100 + 50; 100 | var x = Math.cos(theta) * r, y = Math.sin(theta) * r; 101 | points[i] = {x: x, y: y}; 102 | 103 | // Animate (interpolate) between previous state and where we want to be. 104 | cur_vel[i] = plask.lerp(cur_vel[i], dst_vel[i], 0.1); 105 | } 106 | 107 | // Since Catmull-Rom needs a point of context on each side, the path we 108 | // make wouldn't include the first or last segment. Since we want it to 109 | // close and loop completely, duplicate the first 3 points at the end. 110 | points.push(points[0], points[1], points[2]); 111 | 112 | canvas.clear(0, 0, 0, 255); 113 | 114 | path.rewind(); 115 | pointsToCatmullPath(points, path); 116 | path.close(); // Not really needed, but shouldn't hurt anything either. 117 | canvas.drawPath(paint, path); 118 | } 119 | }); 120 | -------------------------------------------------------------------------------- /examples/040_applescript.js: -------------------------------------------------------------------------------- 1 | var plask = require('plask'); 2 | 3 | var ascript = new plask.AppleScript( 4 | 'tell application "iTunes"\n' + 5 | ' playpause\n' + 6 | 'end tell'); 7 | 8 | ascript.execute(); 9 | 10 | // One day I'll fix the event loop and then programs will end automatically. 11 | process.exit(0); // Exit the program. 12 | -------------------------------------------------------------------------------- /examples/100_ryan_particles.js: -------------------------------------------------------------------------------- 1 | // (c) Ryan Alexander 2 | 3 | var plask = require('plask'); 4 | 5 | function Particle(pos) { 6 | this.pos = pos.dup(); 7 | this.vel = new plask.Vec2(0, 0); 8 | this.bias = Math.sqrt(Math.random()) * (Math.random() < 0.5 ? -1 : 1); 9 | } 10 | 11 | Particle.prototype = { 12 | update: function() { 13 | this.pos.add(this.vel); 14 | }, 15 | damp: function(damping) { 16 | this.vel.scale(damping); 17 | }, 18 | gravity: function(center, pow, mindist) { 19 | var xo = center.x - this.pos.x; 20 | var yo = center.y - this.pos.y; 21 | var dist = Math.sqrt(xo*xo + yo*yo); 22 | var force = pow / Math.max(dist, mindist); 23 | this.vel.add({ 24 | x: force * xo / dist, 25 | y: force * yo / dist 26 | }); 27 | }, 28 | orbit: function(center, pow) { 29 | var xo = this.pos.x - center.x; 30 | var yo = this.pos.y - center.y; 31 | var dist = Math.sqrt(xo*xo + yo*yo); 32 | var force = pow / dist; 33 | this.vel.add({ 34 | x: force * -yo / dist, 35 | y: force * xo / dist 36 | }); 37 | } 38 | }; 39 | 40 | var dots = []; 41 | 42 | plask.simpleWindow({ 43 | settings: { 44 | width: 1000, 45 | height: 600 46 | }, 47 | 48 | init: function() { 49 | var canvas = this.canvas, paint = this.paint; 50 | 51 | canvas.clear(0, 0, 0, 255); 52 | paint.setAntiAlias(true); 53 | paint.setXfermodeMode(paint.kPlusMode); 54 | 55 | this.framerate(60); 56 | 57 | this.mouse_down = false; 58 | this.mouse_pos = new plask.Vec2(0, 0); 59 | 60 | this.on('leftMouseDown', function(e) { 61 | this.mouse_down = true; 62 | this.mouse_pos.set(e.x, e.y); 63 | }); 64 | this.on('leftMouseDragged', function(e) { 65 | this.mouse_pos.set(e.x, e.y); 66 | }); 67 | this.on('leftMouseUp', function(e) { 68 | this.mouse_down = false; 69 | }); 70 | 71 | while (dots.length < 1000) { 72 | var p = new Particle(new plask.Vec2( 73 | Math.random() * this.width, 74 | Math.random() * this.height 75 | )); 76 | p.vel.add({ 77 | x: Math.random() * 2 - 1, 78 | y: Math.random() * 2 - 1 79 | }); 80 | dots.push(p); 81 | } 82 | }, 83 | 84 | draw: function() { 85 | var canvas = this.canvas, paint = this.paint; 86 | 87 | canvas.clear(0, 0, 0, 255); 88 | 89 | paint.setFill(); 90 | paint.setXfermodeMode(paint.kPlusMode); 91 | 92 | for (var i = dots.length; --i >= 0;) { 93 | var dot = dots[i]; 94 | dot.gravity(this.mouse_pos, 150, 10); 95 | dot.orbit(this.mouse_pos, dot.bias * 150); 96 | dot.update(); 97 | dot.damp(0.95); 98 | var u = Math.min(1, dot.vel.length() / 15); 99 | var b = plask.lerp(0, 255, Math.abs(dot.bias)); 100 | paint.setColor(b, b, 255, plask.lerp(0, 64, u)); 101 | canvas.drawCircle(paint, 102 | dot.pos.x, 103 | dot.pos.y, 104 | plask.lerp(20, 2, u) 105 | ); 106 | } 107 | } 108 | }); 109 | -------------------------------------------------------------------------------- /examples/101_thatcher_drops.js: -------------------------------------------------------------------------------- 1 | // (c) Thatcher Ulrich 2 | 3 | var plask = require('plask'); 4 | 5 | // *Symmetric* sigmoid, range: [-1,1] 6 | function sigmoid(x) { 7 | return (1 / (1 + Math.exp(-x))) * 2 - 1; 8 | } 9 | 10 | var G = 1/1000000; 11 | var F = 1/1000; 12 | var P = 2; 13 | 14 | function envelope(t) { 15 | return G * Math.pow(t, P) / (1 + Math.exp(t * F)); 16 | } 17 | 18 | 19 | var particles = []; 20 | var MAX_PARTICLES = 100; 21 | function init_particles() { 22 | for (var i = 0; i < MAX_PARTICLES; i++) { 23 | particles.push({x: 0, y: 0, w: 0, a: 0, r: 0, g: 0, b: 0, t: 100 }); 24 | } 25 | } 26 | init_particles(); 27 | var next_particle = 0; 28 | 29 | var PARTICLE_LIFE = 50; 30 | 31 | function emit_particle(x, y) { 32 | if (particles.length >= MAX_PARTICLES) { 33 | next_particle = (next_particle + 1) % MAX_PARTICLES; 34 | } 35 | var p = particles[next_particle]; 36 | 37 | p.x = x; 38 | p.y = y; 39 | p.w = 50; 40 | p.r = (Math.random() * 255) >> 0; 41 | p.g = (Math.random() * 255) >> 0; 42 | p.b = (Math.random() * 255) >> 0; 43 | p.a = (Math.random() * 255) >> 0; 44 | p.t = 0; 45 | } 46 | 47 | function draw_particles(canvas, paint) { 48 | for (var i = 0; i < particles.length; i++) { 49 | var p = particles[i]; 50 | if (p.t < PARTICLE_LIFE) { 51 | var radius = sigmoid(envelope(p.t * 100)) * 200 + 1; 52 | 53 | paint.setColor(p.r, p.g, p.b, p.a); 54 | canvas.drawCircle(paint, p.x, p.y, radius /*p.w*/); 55 | 56 | // Update 57 | p.a *= 0.9; 58 | p.w *= 0.93; 59 | p.y += 5 + Math.random() * 10; 60 | p.x += (Math.random() - 0.5) * 10; 61 | p.t++; 62 | } 63 | } 64 | } 65 | 66 | plask.simpleWindow({ 67 | settings: { 68 | width: 800, 69 | height: 600 70 | }, 71 | 72 | init: function() { 73 | var canvas = this.canvas, paint = this.paint; 74 | 75 | this.framerate(60); 76 | 77 | canvas.clear(100, 100, 100, 255); // Initial background. 78 | paint.setAntiAlias(true); 79 | paint.setXfermodeMode(paint.kPlusMode); // Additive blending. 80 | 81 | this.mousedown = false; 82 | this.mouse_x = 0; 83 | this.mouse_y = 0; 84 | 85 | this.on('leftMouseDown', function(e) { 86 | this.mousedown = true; 87 | this.mouse_x = e.x; 88 | this.mouse_y = e.y; 89 | }); 90 | this.on('leftMouseDragged', function(e) { 91 | this.mouse_x = e.x; 92 | this.mouse_y = e.y; 93 | }); 94 | this.on('leftMouseUp', function(e) { 95 | this.mousedown = false; 96 | }); 97 | }, 98 | 99 | draw: function draw() { 100 | var canvas = this.canvas, paint = this.paint; 101 | 102 | canvas.drawColor(100, 100, 100, 10); // Blur. 103 | 104 | if (this.mousedown) 105 | emit_particle(this.mouse_x, this.mouse_y); 106 | draw_particles(canvas, paint); 107 | } 108 | }); 109 | -------------------------------------------------------------------------------- /examples/104_chainreaction.js: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2010. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | var plask = require('plask'); 23 | 24 | // Integer between 0 and max (but not including max). 25 | function irand(max) { 26 | return (Math.random() * max) >> 0; 27 | } 28 | 29 | function Ball(position, direction, color) { 30 | this.p = position; 31 | this.d = direction; 32 | this.c = color; 33 | } 34 | 35 | function Explosion(position) { 36 | this.p = position; 37 | this.r = 0; // Current radius. 38 | } 39 | 40 | var kBallRadius = 7; 41 | var kExplosionRadius = 30; 42 | 43 | var balls; 44 | 45 | function initializeBalls() { 46 | balls = Array(30); 47 | for (var i = 0, il = balls.length; i < il; ++i) { 48 | var p = new plask.Vec2(irand(400 - kBallRadius * 4) + kBallRadius * 2, 49 | irand(300 - kBallRadius * 4) + kBallRadius * 2); 50 | 51 | var d = new plask.Vec2(Math.random() - 0.5, Math.random() - 0.5); 52 | d.normalize(); 53 | 54 | // NOTE: You can be unlucky and get a completely black ball. Good luck :) 55 | balls[i] = new Ball(p, d, {r: irand(255), 56 | g: irand(255), 57 | b: irand(255), 58 | a: 128}); 59 | } 60 | } 61 | 62 | initializeBalls(); 63 | 64 | var explosions = [ ]; 65 | 66 | function step(dt) { 67 | for (var i = 0, il = balls.length; i < il; ++i) { 68 | var ball = balls[i]; 69 | ball.p.add(ball.d.scaled(dt / 5)); 70 | } 71 | 72 | // Collision detection. Our circles all have a constant radius, so this 73 | // is pretty easy. You can just picture the collision box inset from the 74 | // screen by the radius, so we are just collisioning the center point. 75 | for (var i = 0, il = balls.length; i < il; ++i) { 76 | var ball = balls[i]; 77 | if (ball.p.x < kBallRadius) { 78 | ball.d.reflect(new plask.Vec2(1, 0)); 79 | } else if (ball.p.x > (400 - kBallRadius)) { 80 | ball.d.reflect(new plask.Vec2(-1, 0)); 81 | } 82 | 83 | if (ball.p.y < kBallRadius) { 84 | ball.d.reflect(new plask.Vec2(0, 1)); 85 | } else if (ball.p.y > (300 - kBallRadius)) { 86 | ball.d.reflect(new plask.Vec2(0, -1)); 87 | } 88 | } 89 | 90 | // Grow / remove dead explosions. 91 | for (var i = 0, il = explosions.length; i < il; ++i) { 92 | var ex = explosions[i]; 93 | ex.r += (dt / 20); 94 | } 95 | 96 | // We modify explosions in this loop, so we need to check length each time. 97 | for (var i = 0; i < explosions.length; ++i) { 98 | var ex = explosions[i]; 99 | // TODO(deanm): This could be done better by just swapping the last entry 100 | // of the array and removing that. Not really performance critical. 101 | if (ex.r > kExplosionRadius) { 102 | explosions.splice(i, 1); 103 | --i; 104 | } 105 | } 106 | 107 | // Check to see if any balls should be turned into explosions. 108 | for (var i = 0, il = explosions.length; i < il; ++i) { 109 | var ex = explosions[i]; 110 | var dist2 = (ex.r + kBallRadius) * (ex.r + kBallRadius); 111 | // TODO(deanm): n^2... doom. 112 | // We modify balls in this loop, so we need to check length each time. 113 | for (var j = 0; j < balls.length; ++j) { 114 | var ball = balls[j]; 115 | if (ball.p.distSquared(ex.p) < dist2) { 116 | // TODO(deanm): We could just tag the ball as dead, that would be 117 | // simpler and wouldn't require any array shifting. 118 | balls.splice(j, 1); 119 | // We cached explosion length, so we can append to it for next update. 120 | explosions.push(new Explosion(ball.p)); 121 | } 122 | } 123 | } 124 | } 125 | 126 | plask.simpleWindow({ 127 | settings: { 128 | width: 400, 129 | height: 300 130 | }, 131 | 132 | init: function() { 133 | this.framerate(60); 134 | this.on('leftMouseDown', function(e) { 135 | // Only allow you to add an explosion if there are no others happening. 136 | if (explosions.length === 0) 137 | explosions.push(new Explosion({x: e.x, y: e.y})); 138 | }); 139 | 140 | // Global paint settings, set them once. 141 | var ball_paint = new plask.SkPaint; 142 | ball_paint.setStyle(ball_paint.kFillStyle); 143 | ball_paint.setFlags(ball_paint.kAntiAliasFlag); 144 | this.ball_paint = ball_paint; 145 | }, 146 | 147 | draw: function() { 148 | var canvas = this.canvas, paint = this.paint, ball_paint = this.ball_paint; 149 | step(1000 / 60); // Constant time step physics, not the best way to do it. 150 | 151 | canvas.clear(0, 0, 0, 255); // Black background. 152 | 153 | // Draw balls. 154 | for (var i = 0, il = balls.length; i < il; ++i) { 155 | var ball = balls[i]; 156 | ball_paint.setColor(ball.c.r, ball.c.g, ball.c.b, ball.c.a); 157 | canvas.drawCircle(ball_paint, ball.p.x, ball.p.y, kBallRadius); 158 | } 159 | 160 | // Draw explosions. 161 | for (var i = 0, il = explosions.length; i < il; ++i) { 162 | var ex = explosions[i]; 163 | ball_paint.setColor(255, 140, 0, 128); 164 | canvas.drawCircle(ball_paint, ex.p.x, ex.p.y, ex.r); 165 | } 166 | 167 | if (balls.length === 0 && explosions.length === 0) { 168 | // Start another game. 169 | initializeBalls(); 170 | } 171 | } 172 | }); 173 | -------------------------------------------------------------------------------- /examples/105_fontMetrics.js: -------------------------------------------------------------------------------- 1 | // (c) 2013 Marcin Ignac 2 | 3 | var plask = require('plask'); 4 | var fs = require('fs'); 5 | 6 | plask.simpleWindow({ 7 | settings: { 8 | width: 1280, 9 | height: 720, 10 | }, 11 | init: function() { 12 | var canvas = this.canvas; 13 | var paint = this.paint; 14 | 15 | canvas.clear(255, 255, 255, 255); 16 | 17 | var fontSize = 200; 18 | paint.setFontFamily("Arial"); 19 | paint.setTextSize(fontSize); 20 | paint.setFlags(paint.kAntiAliasFlag); 21 | paint.setFill(); 22 | paint.setColor(0, 0, 0, 255); 23 | 24 | var text = "abcdefgÄÆŚŹ"; 25 | 26 | var lineBounds = this.getTextBounds(paint, text); 27 | var fontMetrics = paint.getFontMetrics(); 28 | var lineHeight = fontMetrics.descent - fontMetrics.ascent + fontMetrics.leading; 29 | 30 | var x = (this.width - lineBounds.w) / 2; 31 | var y = this.height / 2; 32 | 33 | canvas.drawText(paint, text, x, y); 34 | 35 | paint.setColor(230, 230, 230, 255); 36 | canvas.drawText(paint, text, x, y + lineHeight); 37 | 38 | paint.setTextSize(12); 39 | paint.setFill(); 40 | paint.setColor(255, 0, 0, 255); 41 | 42 | canvas.drawLine(paint, x, y, x + lineBounds.w, y); 43 | canvas.drawText(paint, "BASELINE", x + 10, y + 16); 44 | 45 | paint.setColor(0, 150, 0, 255); 46 | canvas.drawLine(paint, x, y + fontMetrics.ascent, x + lineBounds.w, y + fontMetrics.ascent); 47 | canvas.drawText(paint, "ASCENT", x + 10, y + 16 + fontMetrics.ascent); 48 | 49 | canvas.drawLine(paint, x, y + fontMetrics.descent, x + lineBounds.w, y + fontMetrics.descent); 50 | canvas.drawText(paint, "DESCENT", x + 10, y + 16 + fontMetrics.descent); 51 | 52 | paint.setColor(0, 0, 200, 255); 53 | canvas.drawLine(paint, x, y + fontMetrics.top, x + lineBounds.w, y + fontMetrics.top); 54 | canvas.drawText(paint, "TOP", x + 10, y + 16 + fontMetrics.top); 55 | 56 | canvas.drawLine(paint, x, y + fontMetrics.bottom, x + lineBounds.w, y + fontMetrics.bottom); 57 | canvas.drawText(paint, "BOTTOM", x + 10, y + 16 + fontMetrics.bottom); 58 | 59 | paint.setColor(255, 100, 0, 255); 60 | canvas.drawLine(paint, x - 10, y + fontMetrics.descent, x - 10, y + fontMetrics.descent - fontSize); 61 | canvas.drawLine(paint, x - 15, y, x - 15, y - fontMetrics.xheight); 62 | 63 | paint.setColor(0, 255, 255, 128); 64 | paint.setStroke(); 65 | canvas.drawRect(paint, x + lineBounds.x, y + lineBounds.y, x + lineBounds.x + lineBounds.w, y + lineBounds.y + lineBounds.h); 66 | canvas.drawText(paint, "BOUNDS", lineBounds.x, lineBounds.y); 67 | 68 | paint.setColor(100, 100, 100, 255); 69 | canvas.drawLine(paint, x, y + lineHeight, x + lineBounds.w, y + lineHeight); 70 | canvas.drawText(paint, "BASELINE", x + 10, y + 20 + lineHeight); 71 | }, 72 | getTextBounds: function(paint, str, x, y) { 73 | x = x || 0; 74 | y = y || 0; 75 | //bounds [left, top, right, bottom] 76 | var bounds = paint.measureTextBounds(str); 77 | return { 78 | x1 : x + bounds[0], 79 | y1 : y + bounds[3], 80 | x2 : x + bounds[2], 81 | y2 : y + bounds[1], 82 | x : x + bounds[0], 83 | y : y + bounds[1], 84 | w : bounds[2] - bounds[0], 85 | h : bounds[3] - bounds[1] 86 | }; 87 | }, 88 | draw: function() { 89 | return; 90 | var canvas = this.canvas; 91 | var paint = this.paint; 92 | canvas.clear(255, 255, 255, 255); 93 | paint.setFill(); 94 | paint.setColor(0, 0, 0, 255); 95 | paint.setFlags(paint.kAntiAliasFlag); 96 | var fontFamily = this.fontFamilies[this.framenum % this.fontFamilies.length]; 97 | fontFamily = this.fontFamilies[0]; 98 | 99 | var str = "abcdefghijklmnopqrstuvwxyz"; 100 | var str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 101 | var h = 100; 102 | var w = paint.measureText(str); 103 | var x = (this.width - w)/2; 104 | var y = (this.height - h)/2; 105 | var fontMetrics = paint.getFontMetrics(); 106 | 107 | console.log(fontMetrics); 108 | 109 | var bounds = this.getTextBounds(paint, str, x, y); 110 | canvas.drawText(paint, str, x, y); 111 | 112 | var bounds2 = this.getTextBounds(paint, str, x, y); 113 | 114 | var lineHeight = fontMetrics.descent - fontMetrics.ascent + fontMetrics.leading; 115 | 116 | canvas.drawText(paint, str2, x, y + lineHeight); 117 | canvas.drawText(paint, str2, x, y + lineHeight * 2); 118 | 119 | console.log(bounds); 120 | 121 | paint.setStroke(); 122 | paint.setColor(255, 0, 0, 255); 123 | canvas.drawRect(paint, bounds.x1, bounds.y1, bounds.x2, bounds.y2); 124 | 125 | paint.setColor(0, 255, 0, 255); 126 | canvas.drawRect(paint, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 127 | 128 | paint.setColor(255, 0, 0, 128); 129 | canvas.drawLine(paint, x, y, x + bounds.w, y); 130 | 131 | canvas.drawLine(paint, x, y + lineHeight, x + bounds.w, y + lineHeight); 132 | 133 | canvas.drawLine(paint, x, y + lineHeight * 2, x + bounds.w, y + lineHeight * 2); 134 | } 135 | }); 136 | -------------------------------------------------------------------------------- /examples/500_triangle/app.fshader: -------------------------------------------------------------------------------- 1 | // (c) dean@gmail.com 2 | 3 | void main() { 4 | gl_FragColor = vec4(0.314, 0.0, 0.0, 1.0); 5 | } 6 | -------------------------------------------------------------------------------- /examples/500_triangle/app.js: -------------------------------------------------------------------------------- 1 | // (c) dean@gmail.com 2 | 3 | var plask = require('plask'); 4 | 5 | plask.simpleWindow({ 6 | settings: { 7 | width: 800, 8 | height: 600, 9 | type: '3d', // Create an OpenGL window. 10 | vsync: true, // Prevent tearing. 11 | multisample: true // Anti-alias. 12 | }, 13 | 14 | init: function() { 15 | var gl = this.gl; 16 | 17 | this.framerate(30); 18 | 19 | // Read/compile/link the shaders into a MagicProgram. The |mprogram| 20 | // object created has methods to set the shader uniform variables. 21 | this.mprogram = plask.gl.MagicProgram.createFromBasename( 22 | gl, __dirname, 'app'); 23 | 24 | // Create the three 3d (xyz) vertices for the triangle. This creates the 25 | // geometry and loads it into an Vertex Buffer Object (VBO). 26 | function makeMesh() { 27 | var buffer = gl.createBuffer(); 28 | var data = new Float32Array([ 0, 1, 0, 29 | -0.5, 0, 0, 30 | 0.5, 0, 0]); 31 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 32 | gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); 33 | return {buffer: buffer, num: data.length / 3, data: data}; 34 | } 35 | 36 | gl.viewport(0, 0, this.width, this.height); 37 | gl.clearColor(230/255, 230/255, 230/255, 1.0); 38 | 39 | this.mesh = makeMesh(); 40 | 41 | this.zoom = 0.5; 42 | this.rotate_x = 0; 43 | this.rotate_y = 0; 44 | 45 | this.on('leftMouseDragged', function(e) { 46 | this.rotate_x += e.dx / 100.0 47 | this.rotate_y += e.dy / 100.0 48 | }); 49 | 50 | this.on('scrollWheel', function(e) { 51 | this.zoom = plask.clamp(this.zoom - e.dy/10.0, 0, 1); 52 | }); 53 | }, 54 | 55 | draw: function() { 56 | var gl = this.gl; 57 | var mesh = this.mesh; 58 | var mprogram = this.mprogram; 59 | 60 | // Clear the background to gray. The depth buffer isn't really needed for 61 | // a single triangle, but generally the depth buffer should also be cleared. 62 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 63 | 64 | // Build the "model-view" matrix, which will rotate the triangle based on 65 | // the mouse controls. 66 | var mv = new plask.Mat4(); 67 | mv.translate(0, 0, -4 - this.zoom*16); 68 | mv.rotate(this.rotate_y, 1, 0, 0); 69 | mv.rotate(this.rotate_x, 0, 1, 0); 70 | 71 | // Build the "perspective" matrix, which will apply the aspect ratio, 72 | // perspective divide, and clipping planes. 73 | var persp = new plask.Mat4(); 74 | persp.perspective(27, this.width / this.height, 0.1, 20); 75 | 76 | // Set the shaders to be used during drawing, and pass the current 77 | // transformation matrices to them. 78 | mprogram.use(); 79 | mprogram.set_u_p(persp); 80 | mprogram.set_u_mv(mv); 81 | 82 | // Draw the geometry from the VBO, passing the vertices to the vertex 83 | // shader as a vec3 named |a_xyz|. 84 | gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffer); 85 | gl.vertexAttribPointer(mprogram.location_a_xyz, 86 | 3, 87 | gl.FLOAT, 88 | false, 0, 0); 89 | gl.enableVertexAttribArray(mprogram.location_a_xyz); 90 | gl.drawArrays(gl.TRIANGLES, 0, mesh.num); 91 | } 92 | }); 93 | -------------------------------------------------------------------------------- /examples/500_triangle/app.vshader: -------------------------------------------------------------------------------- 1 | // (c) dean@gmail.com 2 | 3 | uniform mat4 u_p; // Projection. 4 | uniform mat4 u_mv; // Model view. 5 | 6 | attribute vec3 a_xyz; 7 | 8 | void main() { 9 | gl_Position = u_p * u_mv * vec4(a_xyz, 1.0); 10 | } 11 | -------------------------------------------------------------------------------- /examples/505_perlin/app.fshader: -------------------------------------------------------------------------------- 1 | // 3d perlin noise implementation, based on GPU Gems 2 implementation by Green. 2 | // (c) dean@gmail.com 3 | 4 | uniform sampler2D u_permgrad_tex; 5 | uniform sampler2D u_perm2d_tex; 6 | 7 | varying vec3 v_norm; 8 | 9 | vec3 fade(vec3 t) { 10 | return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); // new curve 11 | } 12 | 13 | vec4 perm2d(vec2 p) { 14 | return texture2D(u_perm2d_tex, p); 15 | } 16 | 17 | float gradperm(float x, vec3 p) { 18 | return dot(texture2D(u_permgrad_tex, vec2(x, 0.0)).xyz * 2.0 - 1.0, p); 19 | } 20 | 21 | // 3D noise 22 | // optimized version 23 | float inoise(vec3 p) { 24 | vec3 P = mod(floor(p), 256.0); // FIND UNIT CUBE THAT CONTAINS POINT 25 | p -= floor(p); // FIND RELATIVE X,Y,Z OF POINT IN CUBE 26 | vec3 f = fade(p); // COMPUTE FADE CURVES FOR EACH OF X,Y,Z 27 | 28 | P = P / 256.0; 29 | const float one = 1.0 / 256.0; 30 | 31 | // HASH COORDINATES OF THE 8 CUBE CORNERS 32 | vec4 AA = perm2d(P.xy) + P.z; 33 | 34 | // AND ADD BLENDED RESULTS FROM 8 CORNERS OF CUBE 35 | return mix(mix(mix(gradperm(AA.x, p), 36 | gradperm(AA.z, p + vec3(-1, 0, 0)), f.x), 37 | mix(gradperm(AA.y, p + vec3(0, -1, 0)), 38 | gradperm(AA.w, p + vec3(-1, -1, 0)), f.x), f.y), 39 | 40 | mix(mix(gradperm(AA.x+one, p + vec3(0, 0, -1)), 41 | gradperm(AA.z+one, p + vec3(-1, 0, -1)), f.x), 42 | mix(gradperm(AA.y+one, p + vec3(0, -1, -1)), 43 | gradperm(AA.w+one, p + vec3(-1, -1, -1)), f.x), f.y), f.z); 44 | } 45 | 46 | void main() { 47 | float n = (inoise(v_norm) + inoise(v_norm * 5.0)*0.07) * 0.5 + 0.5; 48 | n *= 1.1; // Small boost towards white. 49 | gl_FragColor = vec4(n, n, n, 1.0); 50 | } 51 | -------------------------------------------------------------------------------- /examples/505_perlin/app.js: -------------------------------------------------------------------------------- 1 | // (c) dean@gmail.com 2 | 3 | var plask = require('plask'); 4 | 5 | // From PreGL: 6 | // Generate a 2-component triangle strip of a 2 dimensional grid. 7 | // 8 | // If you were to draw a bad ascii diagram of a 3 column by 2 row 9 | // tessellation, it would look something like this. Y increase down starting 10 | // at |start_y| and ending at |end_y|. X increase right from |start_x| to 11 | // |end_x|. The triangles are in counter-clockwise order, facing out of the 12 | // page. 13 | // __ __ __ 14 | // Y | /| /| /| 15 | // |/ |/ |/ | 16 | // | -- -- -- 17 | // V |\ |\ |\ | 18 | // | \| \| \| 19 | // -- -- -- 20 | // X -> 21 | // 22 | function makeTristripGrid2D(start_y, end_y, num_rows, 23 | start_x, end_x, num_columns) { 24 | // Every row takes 2 points per cell, plus an extra point at the end. 25 | // The first row takes an additional point. Every point is 2 components. 26 | var fa = new Float32Array((num_columns * 4 + 2) * num_rows + 2); 27 | var y_step = (end_y - start_y) / num_rows; 28 | var pos_x_step = (end_x - start_x) / num_columns; 29 | var neg_x_step = -pos_x_step; 30 | 31 | // You could see the algorithm looking like this. You have a grid of 32 | // quads, each quad is divided into two triangles by a diagonal. The 33 | // diagonal switches direction every row, as we zig back and forth every 34 | // row. So the first row starts at start_x and ends at end_x, and the next 35 | // row starts at end_x, and ends and start_x. For every row, we start by 36 | // omiting the first point at the start of the first diagonal. For every 37 | // cell we are just emiting a vertical line, forming the diagonal connection 38 | // across the face inbetween the vertical lines. These vertical lines are 39 | // the edge of the cell, going towards which every direction we as zagging. 40 | 41 | var y0 = start_y, y1 = start_y; 42 | for (var i = 0, k = 0; i < num_rows; ++i) { 43 | y0 = y1; y1 += y_step; 44 | 45 | // Swap the direction, we zig zag every row. 46 | var x0 = (i & 1) === 0 ? start_x : end_x; 47 | var x_step = (i & 1) === 0 ? pos_x_step : neg_x_step; 48 | 49 | // For the first row, we have to emit an extra point, the first point. 50 | if (i === 0) { fa[k++] = y0; fa[k++] = x0; } 51 | fa[k++] = y1; fa[k++] = x0; // The starting point of the first diagonal. 52 | 53 | for (var j = 0; j < num_columns; ++j) { 54 | x0 += x_step; 55 | fa[k++] = y0; fa[k++] = x0; 56 | fa[k++] = y1; fa[k++] = x0; 57 | } 58 | } 59 | 60 | return fa; 61 | } 62 | 63 | 64 | // Create the permutation tables that get loaded into the shaders as textures. 65 | function makePerlinDataTextures(gl) { 66 | var kPermutation = [151,160,137,91,90,15, 67 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 68 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 69 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 70 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 71 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 72 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 73 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 74 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 75 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 76 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 77 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 78 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; 79 | 80 | var kGradient = [ 81 | 1,1,0, 82 | -1,1,0, 83 | 1,-1,0, 84 | -1,-1,0, 85 | 1,0,1, 86 | -1,0,1, 87 | 1,0,-1, 88 | -1,0,-1, 89 | 0,1,1, 90 | 0,-1,1, 91 | 0,1,-1, 92 | 0,-1,-1, 93 | 1,1,0, 94 | 0,-1,1, 95 | -1,1,0, 96 | 0,-1,-1]; 97 | for (var i = 0, il = kGradient.length; i < il; ++i) 98 | kGradient[i] = ((kGradient[i] + 1) * 127.5) >> 0; 99 | 100 | function perm(i) { return kPermutation[i & 0xff]; } 101 | 102 | var permgrad = new plask.SkCanvas(256, 1); 103 | for (var x = 0; x < 256; ++x) { 104 | var i = (kPermutation[x] & 0xf) * 3; 105 | permgrad[x*4 + 2] = kGradient[i]; // R 106 | permgrad[x*4 + 1] = kGradient[i + 1]; // G 107 | permgrad[x*4] = kGradient[i + 2]; // B 108 | } 109 | 110 | var permgrad_tex = gl.createTexture(); 111 | gl.activeTexture(gl.TEXTURE0); 112 | gl.bindTexture(gl.TEXTURE_2D, permgrad_tex); 113 | gl.texImage2DSkCanvasNoFlip(gl.TEXTURE_2D, 0, permgrad); 114 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 115 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 116 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); 117 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); 118 | 119 | var perm2d = new plask.SkCanvas(256, 256); 120 | for (var x = 0; x < 256; ++x) { 121 | for (var y = 0; y < 256; ++y) { 122 | var A = perm(x) + y; 123 | var AA = perm(A); 124 | var AB = perm(A + 1); 125 | var B = perm(x + 1) + y; 126 | var BA = perm(B); 127 | var BB = perm(B + 1); 128 | perm2d[y*256*4 + x*4 + 2] = AA; // R 129 | perm2d[y*256*4 + x*4 + 1] = AB; // G 130 | perm2d[y*256*4 + x*4] = BA; // B 131 | perm2d[y*256*4 + x*4 + 3] = BB; // A 132 | } 133 | } 134 | 135 | var perm2d_tex = gl.createTexture(); 136 | gl.activeTexture(gl.TEXTURE1); 137 | gl.bindTexture(gl.TEXTURE_2D, perm2d_tex); 138 | gl.texImage2DSkCanvasNoFlip(gl.TEXTURE_2D, 0, perm2d); 139 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 140 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 141 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); 142 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); 143 | } 144 | 145 | 146 | plask.simpleWindow({ 147 | settings: { 148 | width: 800, 149 | height: 600, 150 | type: '3d', 151 | vsync: true, // Prevent tearing. 152 | multisample: true // Anti-alias. 153 | }, 154 | 155 | init: function() { 156 | var gl = this.gl; 157 | 158 | this.mprogram = new plask.gl.MagicProgram.createFromBasename( 159 | gl, __dirname, 'app'); 160 | 161 | // Create a 2d grid (xy) of theta and phi. The vertex shader will map 162 | // these vertices to the 3d position on the sphere. 163 | function makeSphere() { 164 | var kEp = 0.000001; // Create holes at the poles. 165 | var buffer = gl.createBuffer(); 166 | var data = makeTristripGrid2D(kEp, plask.kPI-kEp, 72, 167 | 0, plask.k2PI, 72); 168 | // Bind in and load our data. 169 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 170 | gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); 171 | return {buffer: buffer, num: data.length / 2}; 172 | } 173 | 174 | this.sphere = makeSphere(); 175 | makePerlinDataTextures(this.gl); 176 | 177 | this.framerate(60); 178 | }, 179 | 180 | draw: function() { 181 | var gl = this.gl; 182 | var sphere = this.sphere; 183 | var mprogram = this.mprogram; 184 | var t = this.frametime * 50; 185 | 186 | gl.clearColor(0, 0, 0, 0); 187 | gl.enable(gl.DEPTH_TEST); 188 | gl.disable(gl.BLEND); 189 | 190 | gl.cullFace(gl.BACK); 191 | gl.enable(gl.CULL_FACE); 192 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 193 | 194 | var mv = new plask.Mat4(); 195 | mv.translate(0, 0, -10 + Math.sin(t/50)); 196 | mv.rotate(t / 50, 0, 1, 0); 197 | mv.rotate(t / 79, 0, 0, 1); 198 | 199 | var persp = new plask.Mat4(); 200 | persp.perspective(10, this.width / this.height, 0.01, 1000); 201 | 202 | mprogram.use(); 203 | // Set the transformation matrices. 204 | mprogram.set_u_p(persp); 205 | mprogram.set_u_mv(mv); 206 | // Set the texture IDs. 207 | mprogram.set_u_permgrad_tex(0); 208 | mprogram.set_u_perm2d_tex(1); 209 | 210 | // Draw the grid geometry, which will be transformed to a sphere by the 211 | // vertex shader. 212 | gl.bindBuffer(gl.ARRAY_BUFFER, sphere.buffer); 213 | gl.vertexAttribPointer(mprogram.location_a_theta_phi, 214 | 2, 215 | gl.FLOAT, 216 | false, 0, 0); 217 | gl.enableVertexAttribArray(mprogram.location_a_theta_phi); 218 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, sphere.num); 219 | } 220 | }); 221 | -------------------------------------------------------------------------------- /examples/505_perlin/app.vshader: -------------------------------------------------------------------------------- 1 | // (c) dean@gmail.com 2 | 3 | uniform mat4 u_p; // Projection. 4 | uniform mat4 u_mv; // Model view. 5 | 6 | varying vec3 v_norm; 7 | 8 | attribute vec2 a_theta_phi; 9 | 10 | void main() { 11 | float theta = a_theta_phi.x; 12 | float phi = a_theta_phi.y; 13 | float r = 1.0; 14 | 15 | // The mathy defintion is based on +Z pointing "up", but the graphicsy 16 | // definition would be +Y (and our texure maps follow this). Keep a right 17 | // handed coordinate system and map XYZ -> YZX. 18 | vec4 pos = vec4(r * sin(theta) * sin(phi), // Math-Y 19 | r * cos(theta), // Math-Z 20 | r * sin(theta) * cos(phi), // Math-X 21 | 1.0); 22 | 23 | // Map to eye space and project. 24 | gl_Position = u_p * u_mv * pos; 25 | v_norm = (u_mv * pos).xyz; 26 | } 27 | -------------------------------------------------------------------------------- /fetch_deps.sh: -------------------------------------------------------------------------------- 1 | NAME=deps_v3_005 2 | rm -rf deps 3 | curl -L -O https://googledrive.com/host/0B4M1ew30nMnnMFo2WVFrVDliU1U/$NAME.tar.bz2 4 | tar jxvf $NAME.tar.bz2 5 | #rm $NAME.tar.bz2 6 | -------------------------------------------------------------------------------- /libev.patch: -------------------------------------------------------------------------------- 1 | diff -u A/ev.c B/ev.c 2 | --- A/ev.c 2010-09-17 19:34:16.000000000 +0100 3 | +++ B/ev.c 2010-09-27 23:19:38.000000000 +0100 4 | @@ -2226,6 +2226,13 @@ 5 | } 6 | } 7 | 8 | +ev_tstamp next_waittime = 0.; 9 | + 10 | +ev_tstamp 11 | +ev_next_waittime() { 12 | + return next_waittime; 13 | +} 14 | + 15 | void 16 | ev_loop (EV_P_ int flags) 17 | { 18 | @@ -2370,6 +2377,25 @@ 19 | #if EV_MINIMAL < 2 20 | --loop_depth; 21 | #endif 22 | + 23 | + // Compute the next waiting time. 24 | + ev_tstamp waittime = MAX_BLOCKTIME; 25 | + 26 | + if (timercnt) 27 | + { 28 | + ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now + backend_fudge; 29 | + if (waittime > to) waittime = to; 30 | + } 31 | + 32 | +#if EV_PERIODIC_ENABLE 33 | + if (periodiccnt) 34 | + { 35 | + ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now + backend_fudge; 36 | + if (waittime > to) waittime = to; 37 | + } 38 | +#endif 39 | + 40 | + next_waittime = waittime; 41 | } 42 | 43 | void 44 | @@ -2378,6 +2404,16 @@ 45 | loop_done = how; 46 | } 47 | 48 | +int ev_backend_fd() 49 | +{ 50 | + return backend_fd; 51 | +} 52 | + 53 | +int ev_backend_changecount() 54 | +{ 55 | + return kqueue_changecnt; 56 | +} 57 | + 58 | void 59 | ev_ref (EV_P) 60 | { 61 | diff -u A/ev.h B/ev.h 62 | --- A/ev.h 2010-09-17 19:34:16.000000000 +0100 63 | +++ B/ev.h 2010-09-27 23:19:46.000000000 +0100 64 | @@ -530,6 +530,10 @@ 65 | void ev_loop (EV_P_ int flags); 66 | void ev_unloop (EV_P_ int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */ 67 | 68 | +int ev_backend_fd(); 69 | +int ev_backend_changecount(); 70 | +ev_tstamp ev_next_waittime(); 71 | + 72 | /* 73 | * ref/unref can be used to add or remove a refcount on the mainloop. every watcher 74 | * keeps one reference. if you have a long-running watcher you never unregister that 75 | -------------------------------------------------------------------------------- /main.mm: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2010. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | // This file is a bit tricky, for the following main reasons. 23 | // 24 | // - We run nib-less, so we have more control of startup and can run the main 25 | // loop ourselves. This also allows our executable to be a bit more 26 | // contained and not require nibs in the bundle. 27 | // 28 | // - We must integrate the Cocoa event loop with Node's event loop (libuv). 29 | // This requires a bit of care and the general approach follows below. 30 | // 31 | // The CFRunLoop (and Cocoa's run loop) is needed for UI messages, and needs 32 | // to be run on the main thread. We always want everything to run on the main 33 | // thread, all JavaScript, UI, etc. It would be best if we could have a 34 | // completely single threaded approach to combine the two runloops. However, 35 | // CFRunLoop is mach-port based, and can't wait on a mixture of both mach ports 36 | // and file descriptors. The way CFSocket is implemented on a CFRunLoop uses a 37 | // helper process and select() to proxy over a mach message to wake up the 38 | // CFRunLoop. Our approach is similar but managed manually. In theory it 39 | // is possible to wrap the kqueue in a CFFileDescriptor or CFSocket, and then 40 | // this would be handled within the run-loop. However, a few attempts at this 41 | // had some unreliable results, and it is clearer to handled the threading 42 | // ourselves then try to understand the implementation details of the internal 43 | // helper process of CFRunLoop(). This also allows us to send the NSEvent 44 | // required to wake up the loop directly from the helper thread, which should 45 | // be safe since postEvent can be called from "subthreads". 46 | // 47 | // There is one additional complication in terms of integrating with libuv. 48 | // We can select() on the kqueue for notifications, but we also need to make 49 | // sure that all pending changes (additions, removals, etc) from within libuv 50 | // have been committed to the kqueue. Normally this happens during the uv loop 51 | // right before blocking on the kqueue. The run through the loop can cause 52 | // timers to fire and other callbacks, which can create more new pending events 53 | // to be updated. Instead of trying to track if there are pending events and 54 | // seeing if we need to run through the loop to update the kqueue, we hook into 55 | // libuv's kevent call. This allows us to see when changes are being made and 56 | // when it's about to block. When it goes for a blocking kevent() call, we 57 | // make sure any pending changes are committed and then pump the Cocoa event 58 | // loop while our helper thread select()s on the kqueue to see if there is 59 | // anything ready. If the kqueue wakes before the Cocoa loop, we send a 60 | // synthentic event into the Cocoa loop to wake up the main thread, and we will 61 | // then again call kevent() and return back into libuv. This effectively means 62 | // we've replaced libuv's core kevent() blocking call with a call to the Cocoa 63 | // eventloop which will be woken up also if there is any activity on the 64 | // kqueue, allowing us to block on the set of both Cocoa and libuv events. 65 | 66 | #import 67 | 68 | // For kevent. 69 | #include 70 | #include 71 | #include 72 | 73 | // For select. 74 | #include 75 | 76 | #import "plaskAppDelegate.h" 77 | 78 | #include "plask_bindings.h" 79 | 80 | #include "v8.h" 81 | #include "node.h" 82 | #include "uv.h" 83 | 84 | #define EVENTLOOP_DEBUG 0 85 | 86 | #define EVENTLOOP_BYPASS_CUSTOM 0 87 | 88 | #if EVENTLOOP_DEBUG 89 | #define EVENTLOOP_DEBUG_C(x) x 90 | #else 91 | #define EVENTLOOP_DEBUG_C(x) do { } while(0) 92 | #endif 93 | 94 | static bool g_should_quit = false; 95 | static int g_kqueue_fd = 0; 96 | static int g_main_thread_pipe_fd = 0; 97 | static int g_kqueue_thread_pipe_fd = 0; 98 | 99 | // We're running nibless, so we don't have the typical MainMenu.nib. This code 100 | // sets up the "Apple Menu", the menu in the menu bar with your application 101 | // title, next to the actual apple logo menu. It is a bit of a mess to create 102 | // it programmatically. For example, see: 103 | // http://lapcatsoftware.com/blog/2007/06/17/ 104 | static void InitMenuBar() { 105 | // Our NSApplication is created with a nil mainMenu. 106 | [NSApp setMainMenu:[[NSMenu alloc] init]]; 107 | 108 | NSMenu* menu = [[NSMenu alloc] initWithTitle:@""]; 109 | 110 | [menu addItemWithTitle:@"About Plask" 111 | action:@selector(orderFrontStandardAboutPanel:) 112 | keyEquivalent:@""]; 113 | 114 | [menu addItem:[NSMenuItem separatorItem]]; 115 | 116 | [menu addItemWithTitle:@"Hide Plask" 117 | action:@selector(hide:) 118 | keyEquivalent:@"h"]; 119 | 120 | [menu addItemWithTitle:@"Hide Others" 121 | action:@selector(hideOtherApplications:) 122 | keyEquivalent:@"h"]; 123 | 124 | [menu addItemWithTitle:@"Show All" 125 | action:@selector(unhideAllApplications:) 126 | keyEquivalent:@""]; 127 | 128 | [menu addItem:[NSMenuItem separatorItem]]; 129 | 130 | [menu addItemWithTitle:@"Quit Plask" 131 | action:@selector(terminate:) 132 | keyEquivalent:@"q"]; 133 | 134 | // The actual "Apple Menu" is the first sub-menu of the mainMenu menu. 135 | NSMenuItem* container_item = [[NSMenuItem alloc] initWithTitle:@"" 136 | action: nil 137 | keyEquivalent:@""]; 138 | [container_item setSubmenu:menu]; 139 | [[NSApp mainMenu] addItem:container_item]; 140 | // Call the undocumented setAppleMenu to make the menu the "Apple Menu". 141 | [NSApp setAppleMenu:menu]; 142 | [container_item release]; 143 | [menu release]; 144 | } 145 | 146 | #if EVENTLOOP_DEBUG 147 | void dump_kevent(const struct kevent* k) { 148 | const char* f = NULL; 149 | switch (k->filter) { 150 | case EVFILT_READ: f = "EVFILT_READ"; break; 151 | case EVFILT_WRITE: f = "EVFILT_WRITE"; break; 152 | case EVFILT_AIO: f = "EVFILT_AIO"; break; 153 | case EVFILT_VNODE: f = "EVFILT_VNODE"; break; 154 | case EVFILT_PROC: f = "EVFILT_PROC"; break; 155 | case EVFILT_SIGNAL: f = "EVFILT_SIGNAL"; break; 156 | case EVFILT_TIMER: f = "EVFILT_TIMER"; break; 157 | case EVFILT_MACHPORT: f = "EVFILT_MACHPORT"; break; 158 | case EVFILT_FS: f = "EVFILT_FS"; break; 159 | case EVFILT_USER: f = "EVFILT_USER"; break; 160 | case EVFILT_VM: f = "EVFILT_VM"; break; 161 | } 162 | printf("%d %s (%d) %d %d\n", 163 | k->ident, 164 | f, k->filter, 165 | k->flags, 166 | k->fflags); 167 | } 168 | #endif 169 | 170 | void kqueue_checker_thread(void* arg) { 171 | bool check_kqueue = false; 172 | 173 | NSAutoreleasePool* pool = [NSAutoreleasePool new]; // To avoid the warning. 174 | NSEvent* e = [NSEvent otherEventWithType:NSApplicationDefined 175 | location:NSMakePoint(0, 0) 176 | modifierFlags:0 177 | timestamp:0 178 | windowNumber:0 179 | context:nil 180 | subtype:8 // Arbitrary 181 | data1:0 182 | data2:0]; 183 | 184 | while (true) { 185 | int nfds = g_kqueue_thread_pipe_fd + 1; 186 | fd_set fds; 187 | FD_ZERO(&fds); 188 | FD_SET(g_kqueue_thread_pipe_fd, &fds); 189 | if (check_kqueue) { 190 | FD_SET(g_kqueue_fd, &fds); 191 | if (g_kqueue_fd + 1 > nfds) nfds = g_kqueue_fd + 1; 192 | } 193 | 194 | EVENTLOOP_DEBUG_C((printf("Calling select: %d\n", check_kqueue))); 195 | int res = select(nfds, &fds, NULL, NULL, NULL); 196 | if (res <= 0) abort(); // TODO(deanm): Handle signals, etc. 197 | 198 | if (FD_ISSET(g_kqueue_fd, &fds)) { 199 | EVENTLOOP_DEBUG_C((printf("postEvent\n"))); 200 | [NSApp postEvent:e atStart:YES]; 201 | check_kqueue = false; 202 | } 203 | 204 | if (FD_ISSET(g_kqueue_thread_pipe_fd, &fds)) { 205 | char msg; 206 | ssize_t amt = read(g_kqueue_thread_pipe_fd, &msg, 1); 207 | if (amt != 1) abort(); // TODO(deanm): Handle errors. 208 | if (msg == 'q') { // quit. 209 | EVENTLOOP_DEBUG_C((printf("quitting kqueue helper\n"))); 210 | break; 211 | } 212 | check_kqueue = msg == '~'; // ~ - start, ! - stop. 213 | } 214 | } 215 | 216 | [pool drain]; 217 | } 218 | 219 | int 220 | kevent_hook(int kq, const struct kevent *changelist, int nchanges, 221 | struct kevent *eventlist, int nevents, 222 | const struct timespec *timeout) { 223 | int res; 224 | 225 | EVENTLOOP_DEBUG_C((printf("KQUEUE--- fd: %d changes: %d\n", kq, nchanges))); 226 | 227 | #if EVENTLOOP_DEBUG 228 | for (int i = 0; i < nchanges; ++i) { 229 | dump_kevent(&changelist[i]); 230 | } 231 | #endif 232 | 233 | #if EVENTLOOP_BYPASS_CUSTOM 234 | int res = kevent(kq, changelist, nchanges, eventlist, nevents, timeout); 235 | printf("---> results: %d\n", res); 236 | for (int i = 0; i < res; ++i) { 237 | dump_kevent(&eventlist[i]); 238 | } 239 | return res; 240 | #endif 241 | 242 | if (eventlist == NULL) // Just updating the state. 243 | return kevent(kq, changelist, nchanges, eventlist, nevents, timeout); 244 | 245 | struct timespec zerotimeout; 246 | memset(&zerotimeout, 0, sizeof(zerotimeout)); 247 | 248 | // Going for a poll. A bit less optimial but we break it into two system 249 | // calls to make sure that the kqueue state is up to date. We might as well 250 | // also peek since we basically get it for free w/ the same call. 251 | EVENTLOOP_DEBUG_C((printf("-- Updating kqueue state and peek\n"))); 252 | res = kevent(kq, changelist, nchanges, eventlist, nevents, &zerotimeout); 253 | if (res != 0) return res; 254 | 255 | /* 256 | printf("kevent() blocking\n"); 257 | res = kevent(kq, NULL, 0, eventlist, nevents, timeout); 258 | if (res != 0) return res; 259 | return res; 260 | */ 261 | 262 | /* 263 | printf("Going for it...\n"); 264 | res = kevent(kq, changelist, nchanges, eventlist, nevents, timeout); 265 | printf("<- %d\n", res); 266 | return res; 267 | */ 268 | 269 | double ts = 9999; // Timeout in seconds. Default to some "future". 270 | if (timeout != NULL) 271 | ts = timeout->tv_sec + (timeout->tv_nsec / 1000000000.0); 272 | 273 | // NOTE(deanm): We only ever make a single pass, because we need to make 274 | // sure that any user code (which could update timers, etc) is reflected 275 | // and we have a proper timeout value. Since user code can run in response 276 | // to [NSApp sendEvent] (mouse movement, keypress, etc, etc), we wind down 277 | // and go back through the uv loop again to make sure to update everything. 278 | 279 | EVENTLOOP_DEBUG_C((printf("-> Running NSApp iteration: timeout %f\n", ts))); 280 | 281 | // Have the helper thread start select()ing on the kqueue. 282 | write(g_main_thread_pipe_fd, "~", 1); 283 | 284 | // Run the event loop (blocking on the mach port for window messages). 285 | NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask 286 | untilDate:[NSDate dateWithTimeIntervalSinceNow:ts] 287 | inMode:NSDefaultRunLoopMode // kCFRunLoopDefaultMode 288 | dequeue:YES]; 289 | 290 | // Stop the helper thread if it hasn't already woken up (in which case it 291 | // would have already stopped itself). 292 | write(g_main_thread_pipe_fd, "!", 1); 293 | 294 | EVENTLOOP_DEBUG_C((printf("<- Finished NSApp iteration\n"))); 295 | 296 | if (event != nil) { // event is nil on a timeout. 297 | EVENTLOOP_DEBUG_C((NSLog(@"Event: %@\n", event))); 298 | 299 | // A custom event to terminate, see applicationShouldTerminate. 300 | if ([event type] == NSApplicationDefined && [event subtype] == 37) { 301 | EVENTLOOP_DEBUG_C((printf("* Application Terminate event.\n"))); 302 | g_should_quit = true; 303 | write(g_main_thread_pipe_fd, "q", 1); 304 | return 0; 305 | } else if ([event type] == NSApplicationDefined && [event subtype] == 8) { 306 | // A wakeup after the kqueue callback. 307 | EVENTLOOP_DEBUG_C((printf("* Wakeup event.\n"))); 308 | } else { 309 | [event retain]; 310 | [NSApp sendEvent:event]; 311 | [event release]; 312 | } 313 | } 314 | 315 | // Do the actual kqueue call now (ignore the timeout, don't block). 316 | res = kevent(kq, NULL, 0, eventlist, nevents, &zerotimeout); 317 | // libuv makes an assert that if it calls kevent without a timeout, it 318 | // should never return 0. One approach is to always have a timer somewhere 319 | // in libuv, so that the timeout will never be indefinite. Hopefully simpler 320 | // here is just to pretend that the kevent was interrupted. Haven't checked 321 | // how this case is handled in libuv, but seems okay. 322 | if (timeout == NULL && res == 0) { 323 | errno = EINTR; 324 | res = -1; 325 | } 326 | return res; 327 | } 328 | 329 | int main(int argc, char** argv) { 330 | NSAutoreleasePool* pool = [NSAutoreleasePool new]; 331 | [NSApplication sharedApplication]; // Make sure NSApp is initialized. 332 | 333 | InitMenuBar(); 334 | plaskAppDelegate* app_delegate = [[plaskAppDelegate alloc] init]; 335 | [[NSApplication sharedApplication] setDelegate:app_delegate]; 336 | 337 | // Mavericks introduced "App Nap" which implements timer coalescing and 338 | // delaying in order to save power. This results in nextEventMatchingMask 339 | // being for example 10 seconds more over the specified timeout. This should 340 | // probably be somehow controllable from JavaScript, but until then just 341 | // disable napping and keep our timers reliable. 342 | NSProcessInfo* process_info = [NSProcessInfo processInfo]; 343 | if ([process_info respondsToSelector:@selector(beginActivityWithOptions:reason:)]) { 344 | [process_info beginActivityWithOptions:(NSActivityUserInitiatedAllowingIdleSystemSleep | 345 | NSActivityLatencyCritical) 346 | reason:@"Plask"]; 347 | } 348 | 349 | char* bundled_argv[2]; 350 | NSString* bundled_main_js = 351 | [[NSBundle mainBundle] pathForResource:@"main" ofType:@"js"]; 352 | if (bundled_main_js != nil) { 353 | // Comply to libuv expectation that argv strings are in memory back to back. 354 | const char* bundled_js_path = [bundled_main_js UTF8String]; 355 | size_t bundled_js_path_len = strlen(bundled_js_path) + 1; // Include NULL. 356 | size_t argv0_len = strlen(argv[0]) + 1; // Include NULL. 357 | bundled_argv[0] = new char[bundled_js_path_len + argv0_len]; // Leaked. 358 | bundled_argv[1] = bundled_argv[0] + argv0_len; 359 | memcpy(bundled_argv[0], argv[0], argv0_len); 360 | memcpy(bundled_argv[1], bundled_js_path, bundled_js_path_len); 361 | argc = 2; 362 | argv = bundled_argv; 363 | NSLog(@"loading from bundled: %@", bundled_main_js); 364 | } 365 | 366 | argv = uv_setup_args(argc, argv); 367 | 368 | int exec_argc; 369 | const char** exec_argv; 370 | node::Init(&argc, const_cast(argv), &exec_argc, &exec_argv); 371 | 372 | v8::Isolate* isolate = v8::Isolate::New(); 373 | 374 | int exit_code = 0; 375 | 376 | { 377 | v8::Isolate::Scope isolate_scope(isolate); 378 | v8::V8::Initialize(); 379 | 380 | v8::Locker locker(isolate); 381 | v8::HandleScope handle_scope(isolate); 382 | 383 | v8::Local context = v8::Context::New(isolate); 384 | v8::Context::Scope context_scope(context); 385 | 386 | v8::Handle plask_raw = v8::ObjectTemplate::New(); 387 | plask_setup_bindings(isolate, plask_raw); 388 | context->Global()->Set(v8::String::NewFromUtf8(isolate, "PlaskRawMac"), 389 | plask_raw->NewInstance()); 390 | 391 | node::Environment* env = node::CreateEnvironment( 392 | isolate, context, argc, argv, exec_argc, exec_argv); 393 | 394 | { 395 | 396 | #if EVENTLOOP_BYPASS_CUSTOM 397 | uv_run(uv_default_loop()); 398 | #else 399 | // [NSApp run]; 400 | [NSApp finishLaunching]; 401 | // It is usually desired to activate the app and bring it up as the 402 | // front application, but allow this behaviour to be overriden. This 403 | // happens pretty early so it is probably best done via the environment. 404 | if (!getenv("PLASK_DONT_ACTIVATE")) 405 | [NSApp activateIgnoringOtherApps:YES]; 406 | [NSApp setWindowsNeedUpdate:YES]; 407 | 408 | int pipefds[2]; 409 | if (pipe(pipefds) != 0) abort(); 410 | 411 | g_kqueue_thread_pipe_fd = pipefds[0]; 412 | g_main_thread_pipe_fd = pipefds[1]; 413 | 414 | uv_loop_t* uvloop = uv_default_loop(); 415 | uvloop->keventfunc = (void*)&kevent_hook; 416 | 417 | g_kqueue_fd = uv_backend_fd(uvloop); 418 | 419 | uv_thread_t checker; 420 | uv_thread_create(&checker, &kqueue_checker_thread, NULL); 421 | 422 | bool more = true; 423 | while (!g_should_quit && more) { 424 | NSAutoreleasePool* looppool = [NSAutoreleasePool new]; 425 | EVENTLOOP_DEBUG_C((printf("-> uv_run_once\n"))); 426 | more = uv_run(uvloop, UV_RUN_ONCE); 427 | EVENTLOOP_DEBUG_C((printf("<- uv_run_once\n"))); 428 | EVENTLOOP_DEBUG_C((printf(" - handles: %d\n", uvloop->active_handles))); 429 | if (more == false) { 430 | node::EmitBeforeExit(env); 431 | more = uv_loop_alive(uvloop); 432 | if (uv_run(uvloop, UV_RUN_NOWAIT) != 0) 433 | more = true; 434 | } 435 | [looppool drain]; 436 | } 437 | #endif 438 | 439 | exit_code = node::EmitExit(env); 440 | // NOTE(deanm): Only used for DeleteSlabAllocator? 441 | // node::RunAtExit(env); 442 | 443 | plask_teardown_bindings(); 444 | 445 | //env->Dispose(); 446 | env = NULL; 447 | } 448 | #ifndef NDEBUG 449 | context.Clear(); 450 | #endif // NDEBUG 451 | } 452 | 453 | #ifndef NDEBUG 454 | isolate->Dispose(); 455 | #endif // NDEBUG 456 | 457 | [pool release]; 458 | return 0; 459 | } 460 | -------------------------------------------------------------------------------- /node-libuv.diff: -------------------------------------------------------------------------------- 1 | commit 6913f8b92dd44a525152afd3ae770bc429f133e5 2 | Author: Dean McNamee 3 | Date: Fri Dec 21 16:11:34 2012 +0100 4 | 5 | Patch libuv to allow hooking into the kqueue calls. 6 | 7 | diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h 8 | index 57ce8ae..b02d767 100644 9 | --- a/deps/uv/include/uv.h 10 | +++ b/deps/uv/include/uv.h 11 | @@ -1933,6 +1933,7 @@ struct uv_loop_s { 12 | unsigned int active_handles; 13 | ngx_queue_t handle_queue; 14 | ngx_queue_t active_reqs; 15 | + void* keventfunc; 16 | UV_LOOP_PRIVATE_FIELDS 17 | }; 18 | 19 | diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c 20 | index af9078e..4e42222 100644 21 | --- a/deps/uv/src/unix/kqueue.c 22 | +++ b/deps/uv/src/unix/kqueue.c 23 | @@ -66,6 +66,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { 24 | int fd; 25 | int op; 26 | int i; 27 | + int (*keventfunc)(int kq, const struct kevent *changelist, int nchanges, 28 | + struct kevent *eventlist, int nevents, const struct timespec *timeout) = 29 | + loop->keventfunc ? loop->keventfunc : &kevent; 30 | 31 | if (loop->nfds == 0) { 32 | assert(ngx_queue_empty(&loop->watcher_queue)); 33 | @@ -105,7 +108,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { 34 | EV_SET(events + nevents, w->fd, filter, op, fflags, 0, 0); 35 | 36 | if (++nevents == ARRAY_SIZE(events)) { 37 | - if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) 38 | + if (keventfunc(loop->backend_fd, events, nevents, NULL, 0, NULL)) 39 | abort(); 40 | nevents = 0; 41 | } 42 | @@ -115,7 +118,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { 43 | EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); 44 | 45 | if (++nevents == ARRAY_SIZE(events)) { 46 | - if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) 47 | + if (keventfunc(loop->backend_fd, events, nevents, NULL, 0, NULL)) 48 | abort(); 49 | nevents = 0; 50 | } 51 | @@ -134,7 +137,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { 52 | spec.tv_nsec = (timeout % 1000) * 1000000; 53 | } 54 | 55 | - nfds = kevent(loop->backend_fd, 56 | + nfds = keventfunc(loop->backend_fd, 57 | events, 58 | nevents, 59 | events, 60 | @@ -173,7 +176,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { 61 | struct kevent events[1]; 62 | 63 | EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); 64 | - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) 65 | + if (keventfunc(loop->backend_fd, events, 1, NULL, 0, NULL)) 66 | if (errno != EBADF && errno != ENOENT) 67 | abort(); 68 | 69 | @@ -197,7 +200,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { 70 | /* TODO batch up */ 71 | struct kevent events[1]; 72 | EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); 73 | - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) 74 | + if (keventfunc(loop->backend_fd, events, 1, NULL, 0, NULL)) 75 | if (errno != ENOENT) 76 | abort(); 77 | } 78 | @@ -210,7 +213,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { 79 | /* TODO batch up */ 80 | struct kevent events[1]; 81 | EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); 82 | - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) 83 | + if (keventfunc(loop->backend_fd, events, 1, NULL, 0, NULL)) 84 | if (errno != ENOENT) 85 | abort(); 86 | } 87 | @@ -260,6 +263,9 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { 88 | uv_fs_event_t* handle; 89 | struct kevent ev; 90 | int events; 91 | + int (*keventfunc)(int kq, const struct kevent *changelist, int nchanges, 92 | + struct kevent *eventlist, int nevents, const struct timespec *timeout) = 93 | + loop->keventfunc ? loop->keventfunc : &kevent; 94 | 95 | handle = container_of(w, uv_fs_event_t, event_watcher); 96 | 97 | @@ -279,7 +285,7 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { 98 | 99 | EV_SET(&ev, w->fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, fflags, 0, 0); 100 | 101 | - if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) 102 | + if (keventfunc(loop->backend_fd, &ev, 1, NULL, 0, NULL)) 103 | abort(); 104 | } 105 | 106 | diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c 107 | index e63f12a..c09d68b 100644 108 | --- a/deps/uv/src/unix/loop.c 109 | +++ b/deps/uv/src/unix/loop.c 110 | @@ -56,6 +56,7 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) { 111 | loop->signal_pipefd[1] = -1; 112 | loop->backend_fd = -1; 113 | loop->emfile_fd = -1; 114 | + loop->keventfunc = NULL; 115 | 116 | if (uv__platform_loop_init(loop, default_loop)) 117 | return -1; 118 | -------------------------------------------------------------------------------- /node-load.diff: -------------------------------------------------------------------------------- 1 | commit f6385e5e70868b1b39fb9d4b5325b47b2c42c79e 2 | Author: Dean McNamee 3 | Date: Fri Dec 21 16:12:45 2012 +0100 4 | 5 | Move symbol caching to Load(). 6 | 7 | diff --git a/src/node.cc b/src/node.cc 8 | index 3e8d2d6..ae189d5 100644 9 | --- a/src/node.cc 10 | +++ b/src/node.cc 11 | @@ -2374,6 +2374,9 @@ static void SignalExit(int signal) { 12 | 13 | 14 | void Load(Handle process_l) { 15 | + process_symbol = NODE_PSYMBOL("process"); 16 | + domain_symbol = NODE_PSYMBOL("domain"); 17 | + 18 | // Compile, execute the src/node.js file. (Which was included as static C 19 | // string in node_natives.h. 'natve_node' is the string containing that 20 | // source code.) 21 | @@ -2983,9 +2986,6 @@ int Start(int argc, char *argv[]) { 22 | Persistent context = Context::New(); 23 | Context::Scope context_scope(context); 24 | 25 | - process_symbol = NODE_PSYMBOL("process"); 26 | - domain_symbol = NODE_PSYMBOL("domain"); 27 | - 28 | // Use original argv, as we're just copying values out of it. 29 | Handle process_l = SetupProcessObject(argc, argv); 30 | v8_typed_array::AttachBindings(context->Global()); 31 | -------------------------------------------------------------------------------- /plask-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | Plask 11 | CFBundleIdentifier 12 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSPrincipalClass 28 | NSApplication 29 | 30 | 31 | -------------------------------------------------------------------------------- /plask.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 256AC3DA0F4B6AC300CF3369 /* plaskAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* plaskAppDelegate.mm */; }; 11 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 12 | 8D11072D0486CEB800E47090 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.mm */; settings = {ATTRIBUTES = (); }; }; 13 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 14 | C51CAD0E133AACE900FF807C /* Syphon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C51CAD0D133AACE900FF807C /* Syphon.framework */; }; 15 | C51CAD17133AACF300FF807C /* Syphon.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C51CAD0D133AACE900FF807C /* Syphon.framework */; }; 16 | C51CE4521B53C5350024FBCE /* libsfntly.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C51CE4511B53C5350024FBCE /* libsfntly.a */; }; 17 | C52D4CFD1993EB0500AB37F3 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C52D4CFC1993EB0500AB37F3 /* CoreMedia.framework */; }; 18 | C542EFDC1987F06600E9013B /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C542EFDB1987F06600E9013B /* AVFoundation.framework */; }; 19 | C54480A9133CDB760074124E /* Plask.icns in Resources */ = {isa = PBXBuildFile; fileRef = C54480A8133CDB760074124E /* Plask.icns */; }; 20 | C55215F71B53C77B00046F3D /* libicuuc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C55215F61B53C77B00046F3D /* libicuuc.a */; }; 21 | C5573ED21987F50700981CEB /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5573ED11987F50700981CEB /* CoreVideo.framework */; }; 22 | C5703517124FFED40082AA14 /* plask_bindings.mm in Sources */ = {isa = PBXBuildFile; fileRef = C5703516124FFED40082AA14 /* plask_bindings.mm */; }; 23 | C570353B125003630082AA14 /* v8_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = C5703539125003630082AA14 /* v8_utils.cc */; }; 24 | C570361A1250EB5E0082AA14 /* libfreeimage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C57036191250EB5E0082AA14 /* libfreeimage.framework */; }; 25 | C58108C912FC55920053FB3A /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C58108C812FC55920053FB3A /* CoreMIDI.framework */; }; 26 | C5A5260B12561A2200C0F632 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5A5260A12561A2200C0F632 /* OpenGL.framework */; }; 27 | C5BADEE8196C7B73007328B8 /* libSkKTX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5BADEE7196C7B73007328B8 /* libSkKTX.a */; }; 28 | C5C83E12140A9D78006E6DAE /* ScriptingBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5C83E11140A9D78006E6DAE /* ScriptingBridge.framework */; }; 29 | C5D8EA081295C268003479AA /* libfreeimage.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C57036191250EB5E0082AA14 /* libfreeimage.framework */; }; 30 | C5DA2225168378CB00929928 /* libcares.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA221D168378CB00929928 /* libcares.a */; }; 31 | C5DA2226168378CB00929928 /* libchrome_zlib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA221E168378CB00929928 /* libchrome_zlib.a */; }; 32 | C5DA2227168378CB00929928 /* libhttp_parser.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA221F168378CB00929928 /* libhttp_parser.a */; }; 33 | C5DA2228168378CB00929928 /* libnode.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA2220168378CB00929928 /* libnode.a */; }; 34 | C5DA2229168378CB00929928 /* libopenssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA2221168378CB00929928 /* libopenssl.a */; }; 35 | C5DA222A168378CB00929928 /* libuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA2222168378CB00929928 /* libuv.a */; }; 36 | C5DA222B168378CB00929928 /* libv8_base.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA2223168378CB00929928 /* libv8_base.a */; }; 37 | C5DA222C168378CC00929928 /* libv8_snapshot.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DA2224168378CB00929928 /* libv8_snapshot.a */; }; 38 | C5EB3AB2196C6B4800F1165A /* libskia_core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AA3196C6B4600F1165A /* libskia_core.a */; }; 39 | C5EB3AB3196C6B4800F1165A /* libskia_effects.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AA4196C6B4600F1165A /* libskia_effects.a */; }; 40 | C5EB3AB4196C6B4800F1165A /* libskia_images.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AA5196C6B4700F1165A /* libskia_images.a */; }; 41 | C5EB3AB5196C6B4800F1165A /* libskia_opts_sse41.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AA6196C6B4700F1165A /* libskia_opts_sse41.a */; }; 42 | C5EB3AB6196C6B4800F1165A /* libskia_opts_ssse3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AA7196C6B4700F1165A /* libskia_opts_ssse3.a */; }; 43 | C5EB3AB7196C6B4800F1165A /* libskia_opts.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AA8196C6B4700F1165A /* libskia_opts.a */; }; 44 | C5EB3AB8196C6B4900F1165A /* libskia_pdf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AA9196C6B4700F1165A /* libskia_pdf.a */; }; 45 | C5EB3AB9196C6B4900F1165A /* libskia_ports.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AAA196C6B4700F1165A /* libskia_ports.a */; }; 46 | C5EB3ABA196C6B4900F1165A /* libskia_sfnt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AAB196C6B4800F1165A /* libskia_sfnt.a */; }; 47 | C5EB3ABB196C6B4900F1165A /* libskia_skgpu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AAC196C6B4800F1165A /* libskia_skgpu.a */; }; 48 | C5EB3ABD196C6B4900F1165A /* libskia_utils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AAE196C6B4800F1165A /* libskia_utils.a */; }; 49 | C5EB3AD5196C6E8600F1165A /* libskflate.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3ACA196C6E8600F1165A /* libskflate.a */; }; 50 | C5EB3ADB196C6EA300F1165A /* libetc1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3AD7196C6EA300F1165A /* libetc1.a */; }; 51 | C5EB3C6812FC55A60009FA7C /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5EB3C6712FC55A60009FA7C /* CoreAudio.framework */; }; 52 | /* End PBXBuildFile section */ 53 | 54 | /* Begin PBXCopyFilesBuildPhase section */ 55 | C5D8EA071295C237003479AA /* CopyFiles */ = { 56 | isa = PBXCopyFilesBuildPhase; 57 | buildActionMask = 2147483647; 58 | dstPath = ""; 59 | dstSubfolderSpec = 10; 60 | files = ( 61 | C51CAD17133AACF300FF807C /* Syphon.framework in CopyFiles */, 62 | C5D8EA081295C268003479AA /* libfreeimage.framework in CopyFiles */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXCopyFilesBuildPhase section */ 67 | 68 | /* Begin PBXFileReference section */ 69 | 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 70 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 71 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; 72 | 256AC3D80F4B6AC300CF3369 /* plaskAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = plaskAppDelegate.h; sourceTree = ""; }; 73 | 256AC3D90F4B6AC300CF3369 /* plaskAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = plaskAppDelegate.mm; sourceTree = ""; }; 74 | 256AC3F00F4B6AF500CF3369 /* plask_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = plask_Prefix.pch; sourceTree = ""; }; 75 | 29B97316FDCFA39411CA2CEA /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; 76 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 77 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 78 | 8D1107310486CEB800E47090 /* plask-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "plask-Info.plist"; sourceTree = ""; }; 79 | 8D1107320486CEB800E47090 /* Plask.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Plask.app; sourceTree = BUILT_PRODUCTS_DIR; }; 80 | C51CAD0D133AACE900FF807C /* Syphon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Syphon.framework; path = deps/Syphon.framework; sourceTree = ""; }; 81 | C51CE4511B53C5350024FBCE /* libsfntly.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsfntly.a; path = deps/libsfntly.a; sourceTree = ""; }; 82 | C52D4CFC1993EB0500AB37F3 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = ../../../../System/Library/Frameworks/CoreMedia.framework; sourceTree = ""; }; 83 | C542EFDB1987F06600E9013B /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = /System/Library/Frameworks/AVFoundation.framework; sourceTree = ""; }; 84 | C54480A8133CDB760074124E /* Plask.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Plask.icns; sourceTree = ""; }; 85 | C55215F61B53C77B00046F3D /* libicuuc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libicuuc.a; path = deps/libicuuc.a; sourceTree = ""; }; 86 | C5573ED11987F50700981CEB /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = /System/Library/Frameworks/CoreVideo.framework; sourceTree = ""; }; 87 | C5703515124FFED40082AA14 /* plask_bindings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = plask_bindings.h; sourceTree = ""; }; 88 | C5703516124FFED40082AA14 /* plask_bindings.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = plask_bindings.mm; sourceTree = ""; }; 89 | C5703539125003630082AA14 /* v8_utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = v8_utils.cc; sourceTree = ""; }; 90 | C570353A125003630082AA14 /* v8_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v8_utils.h; sourceTree = ""; }; 91 | C57036191250EB5E0082AA14 /* libfreeimage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libfreeimage.framework; path = deps/libfreeimage.framework; sourceTree = SOURCE_ROOT; }; 92 | C58108C812FC55920053FB3A /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = /System/Library/Frameworks/CoreMIDI.framework; sourceTree = ""; }; 93 | C5A5260A12561A2200C0F632 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 94 | C5BADEE7196C7B73007328B8 /* libSkKTX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSkKTX.a; path = deps/libSkKTX.a; sourceTree = ""; }; 95 | C5C83E11140A9D78006E6DAE /* ScriptingBridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScriptingBridge.framework; path = System/Library/Frameworks/ScriptingBridge.framework; sourceTree = SDKROOT; }; 96 | C5DA221D168378CB00929928 /* libcares.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcares.a; path = deps/libcares.a; sourceTree = ""; }; 97 | C5DA221E168378CB00929928 /* libchrome_zlib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libchrome_zlib.a; path = deps/libchrome_zlib.a; sourceTree = ""; }; 98 | C5DA221F168378CB00929928 /* libhttp_parser.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhttp_parser.a; path = deps/libhttp_parser.a; sourceTree = ""; }; 99 | C5DA2220168378CB00929928 /* libnode.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libnode.a; path = deps/libnode.a; sourceTree = ""; }; 100 | C5DA2221168378CB00929928 /* libopenssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopenssl.a; path = deps/libopenssl.a; sourceTree = ""; }; 101 | C5DA2222168378CB00929928 /* libuv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libuv.a; path = deps/libuv.a; sourceTree = ""; }; 102 | C5DA2223168378CB00929928 /* libv8_base.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libv8_base.a; path = deps/libv8_base.a; sourceTree = ""; }; 103 | C5DA2224168378CB00929928 /* libv8_snapshot.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libv8_snapshot.a; path = deps/libv8_snapshot.a; sourceTree = ""; }; 104 | C5EB3AA3196C6B4600F1165A /* libskia_core.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_core.a; path = deps/libskia_core.a; sourceTree = ""; }; 105 | C5EB3AA4196C6B4600F1165A /* libskia_effects.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_effects.a; path = deps/libskia_effects.a; sourceTree = ""; }; 106 | C5EB3AA5196C6B4700F1165A /* libskia_images.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_images.a; path = deps/libskia_images.a; sourceTree = ""; }; 107 | C5EB3AA6196C6B4700F1165A /* libskia_opts_sse41.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_opts_sse41.a; path = deps/libskia_opts_sse41.a; sourceTree = ""; }; 108 | C5EB3AA7196C6B4700F1165A /* libskia_opts_ssse3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_opts_ssse3.a; path = deps/libskia_opts_ssse3.a; sourceTree = ""; }; 109 | C5EB3AA8196C6B4700F1165A /* libskia_opts.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_opts.a; path = deps/libskia_opts.a; sourceTree = ""; }; 110 | C5EB3AA9196C6B4700F1165A /* libskia_pdf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_pdf.a; path = deps/libskia_pdf.a; sourceTree = ""; }; 111 | C5EB3AAA196C6B4700F1165A /* libskia_ports.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_ports.a; path = deps/libskia_ports.a; sourceTree = ""; }; 112 | C5EB3AAB196C6B4800F1165A /* libskia_sfnt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_sfnt.a; path = deps/libskia_sfnt.a; sourceTree = ""; }; 113 | C5EB3AAC196C6B4800F1165A /* libskia_skgpu.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_skgpu.a; path = deps/libskia_skgpu.a; sourceTree = ""; }; 114 | C5EB3AAE196C6B4800F1165A /* libskia_utils.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskia_utils.a; path = deps/libskia_utils.a; sourceTree = ""; }; 115 | C5EB3ACA196C6E8600F1165A /* libskflate.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libskflate.a; path = deps/libskflate.a; sourceTree = ""; }; 116 | C5EB3AD7196C6EA300F1165A /* libetc1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libetc1.a; path = deps/libetc1.a; sourceTree = ""; }; 117 | C5EB3C6712FC55A60009FA7C /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; 118 | /* End PBXFileReference section */ 119 | 120 | /* Begin PBXFrameworksBuildPhase section */ 121 | 8D11072E0486CEB800E47090 /* Frameworks */ = { 122 | isa = PBXFrameworksBuildPhase; 123 | buildActionMask = 2147483647; 124 | files = ( 125 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 126 | C570361A1250EB5E0082AA14 /* libfreeimage.framework in Frameworks */, 127 | C5A5260B12561A2200C0F632 /* OpenGL.framework in Frameworks */, 128 | C58108C912FC55920053FB3A /* CoreMIDI.framework in Frameworks */, 129 | C5EB3C6812FC55A60009FA7C /* CoreAudio.framework in Frameworks */, 130 | C51CAD0E133AACE900FF807C /* Syphon.framework in Frameworks */, 131 | C5C83E12140A9D78006E6DAE /* ScriptingBridge.framework in Frameworks */, 132 | C5DA2225168378CB00929928 /* libcares.a in Frameworks */, 133 | C5DA2226168378CB00929928 /* libchrome_zlib.a in Frameworks */, 134 | C5DA2227168378CB00929928 /* libhttp_parser.a in Frameworks */, 135 | C5DA2228168378CB00929928 /* libnode.a in Frameworks */, 136 | C5DA2229168378CB00929928 /* libopenssl.a in Frameworks */, 137 | C5DA222A168378CB00929928 /* libuv.a in Frameworks */, 138 | C5DA222B168378CB00929928 /* libv8_base.a in Frameworks */, 139 | C5DA222C168378CC00929928 /* libv8_snapshot.a in Frameworks */, 140 | C5EB3AB2196C6B4800F1165A /* libskia_core.a in Frameworks */, 141 | C5EB3AB3196C6B4800F1165A /* libskia_effects.a in Frameworks */, 142 | C55215F71B53C77B00046F3D /* libicuuc.a in Frameworks */, 143 | C5EB3AB4196C6B4800F1165A /* libskia_images.a in Frameworks */, 144 | C5EB3AB5196C6B4800F1165A /* libskia_opts_sse41.a in Frameworks */, 145 | C5EB3AB6196C6B4800F1165A /* libskia_opts_ssse3.a in Frameworks */, 146 | C5EB3AB7196C6B4800F1165A /* libskia_opts.a in Frameworks */, 147 | C5EB3AB8196C6B4900F1165A /* libskia_pdf.a in Frameworks */, 148 | C51CE4521B53C5350024FBCE /* libsfntly.a in Frameworks */, 149 | C5EB3AB9196C6B4900F1165A /* libskia_ports.a in Frameworks */, 150 | C5EB3ABA196C6B4900F1165A /* libskia_sfnt.a in Frameworks */, 151 | C5EB3ABB196C6B4900F1165A /* libskia_skgpu.a in Frameworks */, 152 | C5EB3ABD196C6B4900F1165A /* libskia_utils.a in Frameworks */, 153 | C5EB3AD5196C6E8600F1165A /* libskflate.a in Frameworks */, 154 | C5EB3ADB196C6EA300F1165A /* libetc1.a in Frameworks */, 155 | C5BADEE8196C7B73007328B8 /* libSkKTX.a in Frameworks */, 156 | C542EFDC1987F06600E9013B /* AVFoundation.framework in Frameworks */, 157 | C5573ED21987F50700981CEB /* CoreVideo.framework in Frameworks */, 158 | C52D4CFD1993EB0500AB37F3 /* CoreMedia.framework in Frameworks */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXFrameworksBuildPhase section */ 163 | 164 | /* Begin PBXGroup section */ 165 | 080E96DDFE201D6D7F000001 /* Classes */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 256AC3D80F4B6AC300CF3369 /* plaskAppDelegate.h */, 169 | 256AC3D90F4B6AC300CF3369 /* plaskAppDelegate.mm */, 170 | ); 171 | name = Classes; 172 | sourceTree = ""; 173 | }; 174 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | C51CAD0D133AACE900FF807C /* Syphon.framework */, 178 | C5DA221D168378CB00929928 /* libcares.a */, 179 | C5DA221E168378CB00929928 /* libchrome_zlib.a */, 180 | C5DA221F168378CB00929928 /* libhttp_parser.a */, 181 | C5DA2220168378CB00929928 /* libnode.a */, 182 | C5DA2221168378CB00929928 /* libopenssl.a */, 183 | C5DA2222168378CB00929928 /* libuv.a */, 184 | C5DA2223168378CB00929928 /* libv8_base.a */, 185 | C5DA2224168378CB00929928 /* libv8_snapshot.a */, 186 | C5EB3AA3196C6B4600F1165A /* libskia_core.a */, 187 | C5EB3AA4196C6B4600F1165A /* libskia_effects.a */, 188 | C5EB3AA5196C6B4700F1165A /* libskia_images.a */, 189 | C5EB3AA6196C6B4700F1165A /* libskia_opts_sse41.a */, 190 | C5EB3AA7196C6B4700F1165A /* libskia_opts_ssse3.a */, 191 | C5EB3AA8196C6B4700F1165A /* libskia_opts.a */, 192 | C5EB3AA9196C6B4700F1165A /* libskia_pdf.a */, 193 | C5EB3AAA196C6B4700F1165A /* libskia_ports.a */, 194 | C5EB3AAB196C6B4800F1165A /* libskia_sfnt.a */, 195 | C5EB3AAC196C6B4800F1165A /* libskia_skgpu.a */, 196 | C5EB3AAE196C6B4800F1165A /* libskia_utils.a */, 197 | C5EB3ACA196C6E8600F1165A /* libskflate.a */, 198 | C5EB3AD7196C6EA300F1165A /* libetc1.a */, 199 | C5BADEE7196C7B73007328B8 /* libSkKTX.a */, 200 | C51CE4511B53C5350024FBCE /* libsfntly.a */, 201 | C55215F61B53C77B00046F3D /* libicuuc.a */, 202 | C57036191250EB5E0082AA14 /* libfreeimage.framework */, 203 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, 204 | C5A5260A12561A2200C0F632 /* OpenGL.framework */, 205 | C5C83E11140A9D78006E6DAE /* ScriptingBridge.framework */, 206 | C58108C812FC55920053FB3A /* CoreMIDI.framework */, 207 | C5EB3C6712FC55A60009FA7C /* CoreAudio.framework */, 208 | C542EFDB1987F06600E9013B /* AVFoundation.framework */, 209 | C5573ED11987F50700981CEB /* CoreVideo.framework */, 210 | C52D4CFC1993EB0500AB37F3 /* CoreMedia.framework */, 211 | ); 212 | name = "Linked Frameworks"; 213 | sourceTree = ""; 214 | }; 215 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { 216 | isa = PBXGroup; 217 | children = ( 218 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */, 219 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, 220 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */, 221 | ); 222 | name = "Other Frameworks"; 223 | sourceTree = ""; 224 | }; 225 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 226 | isa = PBXGroup; 227 | children = ( 228 | 8D1107320486CEB800E47090 /* Plask.app */, 229 | ); 230 | name = Products; 231 | sourceTree = ""; 232 | }; 233 | 29B97314FDCFA39411CA2CEA /* plask */ = { 234 | isa = PBXGroup; 235 | children = ( 236 | 080E96DDFE201D6D7F000001 /* Classes */, 237 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 238 | 29B97317FDCFA39411CA2CEA /* Resources */, 239 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 240 | 19C28FACFE9D520D11CA2CBB /* Products */, 241 | ); 242 | name = plask; 243 | sourceTree = ""; 244 | }; 245 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | C5703539125003630082AA14 /* v8_utils.cc */, 249 | C570353A125003630082AA14 /* v8_utils.h */, 250 | C5703515124FFED40082AA14 /* plask_bindings.h */, 251 | C5703516124FFED40082AA14 /* plask_bindings.mm */, 252 | 256AC3F00F4B6AF500CF3369 /* plask_Prefix.pch */, 253 | 29B97316FDCFA39411CA2CEA /* main.mm */, 254 | ); 255 | name = "Other Sources"; 256 | sourceTree = ""; 257 | }; 258 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 259 | isa = PBXGroup; 260 | children = ( 261 | C54480A8133CDB760074124E /* Plask.icns */, 262 | 8D1107310486CEB800E47090 /* plask-Info.plist */, 263 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, 264 | ); 265 | name = Resources; 266 | sourceTree = ""; 267 | }; 268 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 269 | isa = PBXGroup; 270 | children = ( 271 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 272 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, 273 | ); 274 | name = Frameworks; 275 | sourceTree = ""; 276 | }; 277 | /* End PBXGroup section */ 278 | 279 | /* Begin PBXNativeTarget section */ 280 | 8D1107260486CEB800E47090 /* Plask */ = { 281 | isa = PBXNativeTarget; 282 | buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Plask" */; 283 | buildPhases = ( 284 | 8D1107290486CEB800E47090 /* Resources */, 285 | 8D11072C0486CEB800E47090 /* Sources */, 286 | 8D11072E0486CEB800E47090 /* Frameworks */, 287 | C5D8EA071295C237003479AA /* CopyFiles */, 288 | C5D8EA0E1295C2AF003479AA /* ShellScript */, 289 | ); 290 | buildRules = ( 291 | ); 292 | dependencies = ( 293 | ); 294 | name = Plask; 295 | productInstallPath = "$(HOME)/Applications"; 296 | productName = plask; 297 | productReference = 8D1107320486CEB800E47090 /* Plask.app */; 298 | productType = "com.apple.product-type.application"; 299 | }; 300 | /* End PBXNativeTarget section */ 301 | 302 | /* Begin PBXProject section */ 303 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 304 | isa = PBXProject; 305 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "plask" */; 306 | compatibilityVersion = "Xcode 3.1"; 307 | developmentRegion = English; 308 | hasScannedForEncodings = 1; 309 | knownRegions = ( 310 | English, 311 | Japanese, 312 | French, 313 | German, 314 | ); 315 | mainGroup = 29B97314FDCFA39411CA2CEA /* plask */; 316 | projectDirPath = ""; 317 | projectRoot = ""; 318 | targets = ( 319 | 8D1107260486CEB800E47090 /* Plask */, 320 | ); 321 | }; 322 | /* End PBXProject section */ 323 | 324 | /* Begin PBXResourcesBuildPhase section */ 325 | 8D1107290486CEB800E47090 /* Resources */ = { 326 | isa = PBXResourcesBuildPhase; 327 | buildActionMask = 2147483647; 328 | files = ( 329 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, 330 | C54480A9133CDB760074124E /* Plask.icns in Resources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | /* End PBXResourcesBuildPhase section */ 335 | 336 | /* Begin PBXShellScriptBuildPhase section */ 337 | C5D8EA0E1295C2AF003479AA /* ShellScript */ = { 338 | isa = PBXShellScriptBuildPhase; 339 | buildActionMask = 2147483647; 340 | files = ( 341 | ); 342 | inputPaths = ( 343 | ); 344 | outputPaths = ( 345 | ); 346 | runOnlyForDeploymentPostprocessing = 0; 347 | shellPath = /bin/sh; 348 | shellScript = "mkdir -p \"$BUILT_PRODUCTS_DIR/plask.app/Contents/lib/node/\"\nln -sf \"$SRCROOT/plask.js\" \"$BUILT_PRODUCTS_DIR/plask.app/Contents/lib/node/plask.js\""; 349 | showEnvVarsInLog = 0; 350 | }; 351 | /* End PBXShellScriptBuildPhase section */ 352 | 353 | /* Begin PBXSourcesBuildPhase section */ 354 | 8D11072C0486CEB800E47090 /* Sources */ = { 355 | isa = PBXSourcesBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | 8D11072D0486CEB800E47090 /* main.mm in Sources */, 359 | 256AC3DA0F4B6AC300CF3369 /* plaskAppDelegate.mm in Sources */, 360 | C5703517124FFED40082AA14 /* plask_bindings.mm in Sources */, 361 | C570353B125003630082AA14 /* v8_utils.cc in Sources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | /* End PBXSourcesBuildPhase section */ 366 | 367 | /* Begin PBXVariantGroup section */ 368 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { 369 | isa = PBXVariantGroup; 370 | children = ( 371 | 089C165DFE840E0CC02AAC07 /* English */, 372 | ); 373 | name = InfoPlist.strings; 374 | sourceTree = ""; 375 | }; 376 | /* End PBXVariantGroup section */ 377 | 378 | /* Begin XCBuildConfiguration section */ 379 | C01FCF4B08A954540054247B /* Debug */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ALWAYS_SEARCH_USER_PATHS = NO; 383 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 384 | CLANG_CXX_LANGUAGE_STANDARD = "c++11"; 385 | CLANG_CXX_LIBRARY = "libc++"; 386 | COPY_PHASE_STRIP = NO; 387 | FRAMEWORK_SEARCH_PATHS = ( 388 | "$(inherited)", 389 | "\"$(SRCROOT)/deps\"", 390 | ); 391 | GCC_DYNAMIC_NO_PIC = NO; 392 | GCC_ENABLE_FIX_AND_CONTINUE = YES; 393 | GCC_MODEL_TUNING = G5; 394 | GCC_OPTIMIZATION_LEVEL = 0; 395 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 396 | GCC_PREFIX_HEADER = plask_Prefix.pch; 397 | INFOPLIST_FILE = "plask-Info.plist"; 398 | INSTALL_PATH = "$(HOME)/Applications"; 399 | LIBRARY_SEARCH_PATHS = ( 400 | "$(inherited)", 401 | "\"$(SRCROOT)/deps\"", 402 | ); 403 | ONLY_ACTIVE_ARCH = YES; 404 | PRODUCT_NAME = Plask; 405 | }; 406 | name = Debug; 407 | }; 408 | C01FCF4C08A954540054247B /* Release */ = { 409 | isa = XCBuildConfiguration; 410 | buildSettings = { 411 | ALWAYS_SEARCH_USER_PATHS = NO; 412 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 413 | CLANG_CXX_LANGUAGE_STANDARD = "c++11"; 414 | CLANG_CXX_LIBRARY = "libc++"; 415 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 416 | FRAMEWORK_SEARCH_PATHS = ( 417 | "$(inherited)", 418 | "\"$(SRCROOT)/deps\"", 419 | ); 420 | GCC_MODEL_TUNING = G5; 421 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 422 | GCC_PREFIX_HEADER = plask_Prefix.pch; 423 | INFOPLIST_FILE = "plask-Info.plist"; 424 | INSTALL_PATH = "$(HOME)/Applications"; 425 | LIBRARY_SEARCH_PATHS = ( 426 | "$(inherited)", 427 | "\"$(SRCROOT)/deps\"", 428 | ); 429 | ONLY_ACTIVE_ARCH = YES; 430 | PRODUCT_NAME = Plask; 431 | }; 432 | name = Release; 433 | }; 434 | C01FCF4F08A954540054247B /* Debug */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 438 | GCC_C_LANGUAGE_STANDARD = gnu99; 439 | GCC_OPTIMIZATION_LEVEL = 0; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 441 | GCC_WARN_UNUSED_VARIABLE = YES; 442 | GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = "PLASK_OSX=1 PLASK_SYPHON=1 PLASK_COREMIDI=1 PLASK_WEBGL2=1 PLASK_GPUSKIA=1 SK_RELEASE=1 SK_GAMMA_SRGB SK_SUPPORT_GPU=1 SK_BUILD_FOR_MAC SK_SAMPLES_FOR_X"; 443 | HEADER_SEARCH_PATHS = ( 444 | deps/libfreeimage.framework/Headers, 445 | deps/Syphon.framework/Headers, 446 | deps/, 447 | deps/skia/include/config, 448 | deps/skia/include/core, 449 | deps/skia/include/gpu, 450 | deps/skia/include/utils, 451 | deps/v8/include, 452 | deps/uv, 453 | deps/node, 454 | ); 455 | MACOSX_DEPLOYMENT_TARGET = 10.7; 456 | ONLY_ACTIVE_ARCH = YES; 457 | OTHER_LDFLAGS = ( 458 | "-lz", 459 | "-ldl", 460 | "-force_load", 461 | "\"$(SRCROOT)/deps/libnode.a\"", 462 | ); 463 | PREBINDING = NO; 464 | SDKROOT = macosx; 465 | }; 466 | name = Debug; 467 | }; 468 | C01FCF5008A954540054247B /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 472 | GCC_C_LANGUAGE_STANDARD = gnu99; 473 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 474 | GCC_WARN_UNUSED_VARIABLE = YES; 475 | GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = "PLASK_OSX=1 PLASK_SYPHON=1 PLASK_COREMIDI=1 PLASK_WEBGL2=1 PLASK_GPUSKIA=1 SK_RELEASE=1 SK_GAMMA_SRGB SK_SUPPORT_GPU=1 SK_BUILD_FOR_MAC SK_SAMPLES_FOR_X"; 476 | HEADER_SEARCH_PATHS = ( 477 | deps/libfreeimage.framework/Headers, 478 | deps/Syphon.framework/Headers, 479 | deps/, 480 | deps/skia/include/config, 481 | deps/skia/include/core, 482 | deps/skia/include/gpu, 483 | deps/skia/include/utils, 484 | deps/v8/include, 485 | deps/uv, 486 | deps/node, 487 | ); 488 | MACOSX_DEPLOYMENT_TARGET = 10.7; 489 | OTHER_LDFLAGS = ( 490 | "-lz", 491 | "-ldl", 492 | "-force_load", 493 | "\"$(SRCROOT)/deps/libnode.a\"", 494 | ); 495 | PREBINDING = NO; 496 | SDKROOT = macosx; 497 | }; 498 | name = Release; 499 | }; 500 | /* End XCBuildConfiguration section */ 501 | 502 | /* Begin XCConfigurationList section */ 503 | C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Plask" */ = { 504 | isa = XCConfigurationList; 505 | buildConfigurations = ( 506 | C01FCF4B08A954540054247B /* Debug */, 507 | C01FCF4C08A954540054247B /* Release */, 508 | ); 509 | defaultConfigurationIsVisible = 0; 510 | defaultConfigurationName = Release; 511 | }; 512 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "plask" */ = { 513 | isa = XCConfigurationList; 514 | buildConfigurations = ( 515 | C01FCF4F08A954540054247B /* Debug */, 516 | C01FCF5008A954540054247B /* Release */, 517 | ); 518 | defaultConfigurationIsVisible = 0; 519 | defaultConfigurationName = Release; 520 | }; 521 | /* End XCConfigurationList section */ 522 | }; 523 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 524 | } 525 | -------------------------------------------------------------------------------- /plaskAppDelegate.h: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2010. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | #import 23 | 24 | @interface plaskAppDelegate : NSObject { 25 | NSWindow *window; 26 | } 27 | 28 | @property (assign) IBOutlet NSWindow *window; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /plaskAppDelegate.mm: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2010. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | #import "plaskAppDelegate.h" 23 | 24 | @implementation plaskAppDelegate 25 | 26 | @synthesize window; 27 | 28 | 29 | -(void)applicationWillFinishLaunching:(NSNotification *)aNotification { 30 | } 31 | 32 | -(void)applicationDidFinishLaunching:(NSNotification *)aNotification { 33 | } 34 | 35 | - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app { 36 | // Handle shutdown by leaving the main loop instead of the default behavior 37 | // of exit() being called. 38 | [app postEvent:[NSEvent otherEventWithType:NSApplicationDefined 39 | location:NSMakePoint(0, 0) 40 | modifierFlags:0 41 | timestamp:0 42 | windowNumber:0 43 | context:nil 44 | subtype:37 // Arbitrary 45 | data1:0 46 | data2:0] atStart:YES]; 47 | return NSTerminateCancel; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /plask_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'plask' target in the 'plask' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /plask_bindings.h: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2010. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | #include "v8.h" 23 | 24 | // Create and install bindings on |obj|. 25 | void plask_setup_bindings(v8::Isolate* isolate, 26 | v8::Handle obj); 27 | void plask_teardown_bindings(); 28 | -------------------------------------------------------------------------------- /tests/gradient_alpha.js: -------------------------------------------------------------------------------- 1 | // Test that a linear gradient with alpha is written out to a PNG and read 2 | // back correctly. This is a bit tricky because Skia uses premultiplied 3 | // alpha but PNG doesn't. The conversion generally will not be exact. 4 | 5 | var plask = require('plask'); 6 | 7 | var canvas = plask.SkCanvas.create(200, 200); 8 | var paint = new plask.SkPaint(); 9 | paint.setLinearGradientShader(0, 100, 200, 100, [0, 255, 0, 0, 255, 1, 255, 0, 0, 0]); 10 | canvas.drawRect(paint, 0, 0, 200, 200); 11 | 12 | canvas.writeImage('png', 'gradient_alpha.png'); 13 | 14 | var canvas2 = plask.SkCanvas.createFromImage('gradient_alpha.png'); 15 | 16 | for (var i = 0, il = 200 * 200 * 4; i < il; ++i) { 17 | var Δ = Math.abs(canvas[i] - canvas2[i]); 18 | if (Δ != 0) throw 'Error in pixel, difference: ' + Δ; 19 | } 20 | -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | var plask = require('plask'); 2 | 3 | function assert_eq(a, b) { 4 | if (a !== b) { 5 | var m = 'assert_eq: ' + JSON.stringify(a) + ' !== ' + JSON.stringify(b); 6 | console.trace(m); throw m; 7 | } 8 | } 9 | 10 | function assert_throws(estr, cb) { 11 | try { 12 | cb(); 13 | } catch(e) { 14 | assert_eq(estr, e.toString()); 15 | return; 16 | } 17 | throw 'Expected an exception.'; 18 | } 19 | 20 | function test_path() { 21 | var path = new plask.SkPath(); 22 | path.moveTo(1, 2); 23 | path.lineTo(12, 15); 24 | path.cubicTo(16, 17, 18, 19, 20, 21); 25 | assert_eq("M1 2L12 15C16 17 18 19 20 21", path.toSVGString()); 26 | path.transform(1, 0, 0, 0, 1, 0, 0, 0, 1); 27 | assert_eq("M1 2L12 15C16 17 18 19 20 21", path.toSVGString()); 28 | path.transform(1, 0, 3, 0, 1, 7, 0, 0, 1); // translate by (3, 7) 29 | assert_eq("M4 9L15 22C19 24 21 26 23 28", path.toSVGString()); 30 | assert_eq(true, path.fromSVGString(" M 5 2L12-15C16 17 18 19 20 21")); 31 | assert_eq("M5 2L12 -15C16 17 18 19 20 21", path.toSVGString()); 32 | // assert_eq(false, path.fromSVGString("M 5")); // crashes Skia (bug 3491). 33 | } 34 | 35 | function test_fracts() { 36 | assert_eq( 0.25, plask.fract( 1.25)); 37 | assert_eq( 0.25, plask.fract( -1.75)); 38 | assert_eq( 0.25, plask.fract2( 1.25)); 39 | assert_eq( 0.25, plask.fract2(-1.25)); 40 | assert_eq( 0.25, plask.fract3( 1.25)); 41 | assert_eq(-0.25, plask.fract3(-1.25)); 42 | } 43 | 44 | test_path(); 45 | test_fracts(); 46 | -------------------------------------------------------------------------------- /v8_utils.cc: -------------------------------------------------------------------------------- 1 | #include "v8_utils.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace v8_utils { 8 | 9 | // Taken from the Chromium V8 bindings. 10 | int ToInt32(v8::Handle value, bool* ok) { 11 | *ok = true; 12 | 13 | // Fast case. The value is already a 32-bit integer. 14 | if (value->IsInt32()) { 15 | return value->Int32Value(); 16 | } 17 | 18 | // Can the value be converted to a number? 19 | v8::Local number_object = value->ToNumber(); 20 | if (number_object.IsEmpty()) { 21 | *ok = false; 22 | return 0; 23 | } 24 | 25 | // Does the value convert to nan or to an infinity? 26 | double number_value = number_object->Value(); 27 | if (isnan(number_value) || isinf(number_value)) { 28 | *ok = false; 29 | return 0; 30 | } 31 | 32 | // Can the value be converted to a 32-bit integer? 33 | v8::Local int_value = value->ToInt32(); 34 | if (int_value.IsEmpty()) { 35 | *ok = false; 36 | return 0; 37 | } 38 | 39 | // Return the result of the int32 conversion. 40 | return int_value->Value(); 41 | } 42 | 43 | int ToInt32(v8::Handle value) { 44 | bool ok; 45 | return ToInt32(value, &ok); 46 | } 47 | 48 | int ToInt32WithDefault(v8::Handle value, int def) { 49 | bool ok; 50 | int res = ToInt32(value, &ok); 51 | return ok ? res : def; 52 | } 53 | 54 | double ToNumberWithDefault(v8::Handle value, double def) { 55 | return value->IsNumber() ? value->NumberValue() : def; 56 | } 57 | 58 | void ThrowError(v8::Isolate* isolate, const char* msg) { 59 | isolate->ThrowException( 60 | v8::Exception::Error(v8::String::NewFromUtf8(isolate, msg))); 61 | } 62 | 63 | void ThrowTypeError(v8::Isolate* isolate, const char* msg) { 64 | isolate->ThrowException( 65 | v8::Exception::TypeError(v8::String::NewFromUtf8(isolate, msg))); 66 | } 67 | 68 | } // namespace v8_utils 69 | -------------------------------------------------------------------------------- /v8_utils.h: -------------------------------------------------------------------------------- 1 | // Plask. 2 | // (c) Dean McNamee , 2010. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to 6 | // deal in the Software without restriction, including without limitation the 7 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | // sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | // IN THE SOFTWARE. 21 | 22 | #include 23 | 24 | namespace v8 { 25 | typedef FunctionCallbackInfo Arguments; 26 | } 27 | 28 | namespace v8_utils { 29 | 30 | int ToInt32(v8::Handle value, bool* ok); 31 | int ToInt32(v8::Handle value); 32 | int ToInt32WithDefault(v8::Handle value, int def); 33 | double ToNumberWithDefault(v8::Handle value, double def); 34 | 35 | void ThrowError(v8::Isolate* isolate, const char* msg); 36 | void ThrowTypeError(v8::Isolate* isolate, const char* msg); 37 | 38 | } // namespace v8_utils 39 | --------------------------------------------------------------------------------