├── .travis.yml ├── CHANGELOG.md ├── CSXS └── manifest.xml ├── LICENSE ├── README.md ├── css ├── dark.css ├── light.css ├── style.css └── theme.css ├── docs └── draw2script_screenshot_ellipse_pixi_tiny.png ├── font ├── LICENSE.txt ├── SourceCodePro-Black.otf ├── SourceCodePro-Bold.otf ├── SourceCodePro-ExtraLight.otf ├── SourceCodePro-Light.otf ├── SourceCodePro-Regular.otf ├── SourceCodePro-Semibold.otf ├── SourceSansPro-Black.otf ├── SourceSansPro-BlackIt.otf ├── SourceSansPro-Bold.otf ├── SourceSansPro-BoldIt.otf ├── SourceSansPro-ExtraLight.otf ├── SourceSansPro-ExtraLightIt.otf ├── SourceSansPro-It.otf ├── SourceSansPro-Light.otf ├── SourceSansPro-LightIt.otf ├── SourceSansPro-Regular.otf ├── SourceSansPro-Semibold.otf └── SourceSansPro-SemiboldIt.otf ├── host └── main.jsx ├── index.html ├── js ├── eventHandler.js ├── parser │ ├── createjs.js │ ├── pixigraphics.js │ └── pixitiny.js └── themeManager.js ├── lib ├── CSInterface.js └── jquery-2.1.4.min.js ├── my.conf.js └── spec ├── createjs.spec.js ├── index.html ├── jasmine ├── boot.js ├── console.js ├── jasmine-html.js ├── jasmine.css └── jasmine.js ├── pixigraphics.spec.js ├── pixitiny.spec.js └── support └── jasmine.json /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_s 2 | python: "0.12" 3 | install: 4 | - npm install -g jasmine 5 | script: 6 | - jasmine 7 | after_success: 8 | coveralls 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ROADMAP 2 | * CompoundPath Support 3 | 4 | # History 5 | * 2015-07-13: Alpha release 0.0.1 6 | * 2015-07-15: Alpha release 0.0.2 7 | * Support for [PIXI_tiny](https://github.com/GreyRook/PIXI_tiny) 8 | * RGB Color Support 9 | * 2015-07-17: Alpha release 0.0.3 10 | * Support for JSON 11 | * Better UI 12 | * Error handling for "nothing selected" and "overflow" 13 | * 2015-07-20: Beta release 0.1.07 14 | * Support for PIXI_graphics 15 | * Unit tests 16 | 17 | -------------------------------------------------------------------------------- /CSXS/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ./index.html 25 | ./host/main.jsx 26 | 27 | 28 | true 29 | 30 | 31 | Panel 32 | Draw2Script 33 | 34 | 35 | 400 36 | 200 37 | 38 | 39 | 400 40 | 200 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Draw2Script 4 | Export Source Code from Adobe Illustrator. Inspired by [DrawScript](http://drawscri.pt/) 5 | 6 | ## Features 7 | 8 | * Supported Export Formats 9 | * EaselJS tiny API 10 | * PIXI_tiny API 11 | * PIXI_graphics 12 | * JSON 13 | 14 | ## Screenshot 15 | 16 | ![Ellipse PIXI_tiny](docs/draw2script_screenshot_ellipse_pixi_tiny.png) 17 | 18 | 19 | ## Installation 20 | 21 | ### Adobe Illustrator CC 22 | 23 | * Visit [Adobe Add-ons](https://creative.adobe.com/addons/products/12429) 24 | * Search for Draw2Script 25 | * Click install 26 | * Draw2Script should be copied to your local drive via the Creative Cloud Desktop App 27 | * If you encounter problems visit https://www.adobeexchange.com/resources/19 28 | 29 | ### Adobe CC2014 and CS6 (using Extension Manager) 30 | * Install [Extension Manager](https://www.adobe.com/exchange/em_download/) 31 | * Run Draw2Script.zxp 32 | * If you have both CS6 and CC2014 installed together, Draw2Script may use the wrong version of Adobe Extension Manager and install the plugin for CS6 instead of CC2014, or vice versa 33 | 34 | ### Manual Installation 35 | * Download [Zip](https://github.com/GreyRook/Draw2Script/archive/master.zip) 36 | * Extract Zip to 37 | * System extension folder 38 | * Win: C:\Program Files (x86)\Common Files\Adobe\CEP\extensions 39 | * Mac: /Library/Application Support/Adobe/CEP/extensions 40 | * or Per-user extension folder 41 | * Win: C:\Users\\[username]\AppData\Roaming\Adobe\CEP\extensions 42 | * Mac: ~/Library/Application Support/Adobe/CEP/extensions 43 | 44 | ## State 45 | 46 | Beta State. 47 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | height: 100%; 4 | background-color: #333; 5 | padding: 5px; 6 | } 7 | 8 | textarea { 9 | width: 96%; 10 | } 11 | 12 | input[type=text] { 13 | height: 16px; 14 | } 15 | 16 | p { 17 | font-family: Helvetica, Arial, "Lucida Grande", sans-serif; 18 | color: #eee; 19 | font-size: 14px; 20 | margin-right: 30px; 21 | } 22 | 23 | #content { 24 | height: 100%; 25 | width: 100%; 26 | padding: 3px; 27 | } -------------------------------------------------------------------------------- /css/theme.css: -------------------------------------------------------------------------------- 1 | body{ 2 | position: absolute; 3 | top: 0; 4 | right: 0; 5 | left: 0; 6 | bottom: 0; 7 | } 8 | 9 | #content { 10 | padding: 5px; 11 | } 12 | 13 | textarea { 14 | width: 100%; 15 | height: 100%; 16 | } -------------------------------------------------------------------------------- /docs/draw2script_screenshot_ellipse_pixi_tiny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/docs/draw2script_screenshot_ellipse_pixi_tiny.png -------------------------------------------------------------------------------- /font/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /font/SourceCodePro-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceCodePro-Black.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceCodePro-Bold.otf -------------------------------------------------------------------------------- /font/SourceCodePro-ExtraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceCodePro-ExtraLight.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceCodePro-Light.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceCodePro-Regular.otf -------------------------------------------------------------------------------- /font/SourceCodePro-Semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceCodePro-Semibold.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-Black.otf -------------------------------------------------------------------------------- /font/SourceSansPro-BlackIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-BlackIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-Bold.otf -------------------------------------------------------------------------------- /font/SourceSansPro-BoldIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-BoldIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-ExtraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-ExtraLight.otf -------------------------------------------------------------------------------- /font/SourceSansPro-ExtraLightIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-ExtraLightIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-It.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-It.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-Light.otf -------------------------------------------------------------------------------- /font/SourceSansPro-LightIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-LightIt.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-Regular.otf -------------------------------------------------------------------------------- /font/SourceSansPro-Semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-Semibold.otf -------------------------------------------------------------------------------- /font/SourceSansPro-SemiboldIt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/font/SourceSansPro-SemiboldIt.otf -------------------------------------------------------------------------------- /host/main.jsx: -------------------------------------------------------------------------------- 1 | //Minified JSON2 2 | "object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(t){return 10>t?"0"+t:t}function this_value(){return this.valueOf()}function quote(t){return rx_escapable.lastIndex=0,rx_escapable.test(t)?'"'+t.replace(rx_escapable,function(t){var e=meta[t];return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var r,n,o,u,f,a=gap,i=e[t];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(t)),"function"==typeof rep&&(i=rep.call(e,t,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,f=[],"[object Array]"===Object.prototype.toString.apply(i)){for(u=i.length,r=0;u>r;r+=1)f[r]=str(r,i)||"null";return o=0===f.length?"[]":gap?"[\n"+gap+f.join(",\n"+gap)+"\n"+a+"]":"["+f.join(",")+"]",gap=a,o}if(rep&&"object"==typeof rep)for(u=rep.length,r=0;u>r;r+=1)"string"==typeof rep[r]&&(n=rep[r],o=str(n,i),o&&f.push(quote(n)+(gap?": ":":")+o));else for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(o=str(n,i),o&&f.push(quote(n)+(gap?": ":":")+o));return o=0===f.length?"{}":gap?"{\n"+gap+f.join(",\n"+gap)+"\n"+a+"}":"{"+f.join(",")+"}",gap=a,o}}var rx_one=/^[\],:{}\s]*$/,rx_two=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,rx_three=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,rx_four=/(?:^|:|,)(?:\s*\[)+/g,rx_escapable=/[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,rx_dangerous=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},Boolean.prototype.toJSON=this_value,Number.prototype.toJSON=this_value,String.prototype.toJSON=this_value);var gap,indent,meta,rep;"function"!=typeof JSON.stringify&&(meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(t,e,r){var n;if(gap="",indent="","number"==typeof r)for(n=0;r>n;n+=1)indent+=" ";else"string"==typeof r&&(indent=r);if(rep=e,e&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw new Error("JSON.stringify");return str("",{"":t})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(t,e){var r,n,o=t[e];if(o&&"object"==typeof o)for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(n=walk(o,r),void 0!==n?o[r]=n:delete o[r]);return reviver.call(t,e,o)}var j;if(text=String(text),rx_dangerous.lastIndex=0,rx_dangerous.test(text)&&(text=text.replace(rx_dangerous,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),rx_one.test(text.replace(rx_two,"@").replace(rx_three,"]").replace(rx_four,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(); 3 | 4 | function generateJSON() { 5 | var objects = app.activeDocument.selection; 6 | var json = {}; 7 | json.cropBox = app.activeDocument.cropBox; 8 | json.selection = []; 9 | for(var i = 0; i < objects.length; i++) { 10 | if(objects[i].typename == "PathItem") { 11 | json.selection.push(parsePathItem(objects[i])); 12 | } else if(objects[i].typename == "GroupItem") { 13 | json.selection.push(parseGroupItem(objects[i])); 14 | } else if(objects[i].typename == "CompoundPathItem") { 15 | json.selection.push(parseCompoundPathItem(objects[i])); 16 | } 17 | } 18 | return JSON.stringify(json,null,2); 19 | } 20 | 21 | function parsePathItem(pathItem) { 22 | var json = {}; 23 | json.typename = "PathItem"; 24 | json.closed = pathItem.closed; 25 | json.filled = pathItem.filled; 26 | json.fillColor = pathItem.fillColor; 27 | json.opacity = pathItem.opacity; 28 | json.stroked = pathItem.stroked; 29 | json.strokeColor = pathItem.strokeColor; 30 | json.strokeDashes = pathItem.strokeDashes; 31 | json.strokeDashOffset = pathItem.strokeDashOffset; 32 | json.strokeCap = pathItem.strokeCap; 33 | json.strokeJoin = pathItem.strokeJoin; 34 | json.strokeMiter = pathItem.strokeMiter; 35 | json.strokeMiterLimit = pathItem.strokeMiterLimit; 36 | json.strokeWidth = pathItem.strokeWidth; 37 | json.pathPoints = []; 38 | var pathPoints = pathItem.selectedPathPoints; 39 | for(var i = 0; i < pathPoints.length; i++) { 40 | var jsonPathPoint = {}; 41 | jsonPathPoint.anchor = pathPoints[i].anchor; 42 | jsonPathPoint.leftDirection = pathPoints[i].leftDirection; 43 | jsonPathPoint.rightDirection = pathPoints[i].rightDirection; 44 | json.pathPoints.push(jsonPathPoint); 45 | } 46 | return json; 47 | } 48 | 49 | function parseGroupItem(groupItem) { 50 | var json = {}; 51 | json.typename = "GroupItem"; 52 | json.groupItems = []; 53 | json.pathItems = []; 54 | json.compoundPathItems = []; 55 | for(var i = 0; i < groupItem.groupItems.length; i++) { 56 | json.groupItems.push(parseGroupItem(groupItem.groupItems[i])); 57 | } 58 | for(var i = 0; i < groupItem.pathItems.length; i++) { 59 | json.pathItems.push(parsePathItem(groupItem.pathItems[i])); 60 | } 61 | for(var i = 0; i < groupItem.compoundPathItems.length; i++) { 62 | json.compoundPathItems.push(parseCompoundPathItem(groupItem.compoundPathItems[i])); 63 | } 64 | return json; 65 | } 66 | 67 | function parseCompoundPathItem(compoundPathItem) { 68 | var json = {}; 69 | json.typename = "CompoundPathItem"; 70 | json.pathItems = []; 71 | for(var i = 0; i < compoundPathItem.pathItems.length; i++) { 72 | json.pathItems.push(parsePathItem(compoundPathItem.pathItems[i])); 73 | } 74 | return json; 75 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Draw2Script 12 | 13 | 14 | 15 |
16 |
17 | 23 | 24 |

25 |
26 | 27 | 28 |

29 |
30 | 31 |

32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /js/eventHandler.js: -------------------------------------------------------------------------------- 1 | function onClickButtonSelect() { 2 | var textField = document.getElementById("output"); 3 | textField.select(); 4 | } 5 | 6 | function onClickWrap() { 7 | var textField = document.getElementById("output"); 8 | var checkboxWrap = document.getElementById("wrap"); 9 | if(checkboxWrap.checked) { 10 | textField.wrap = hard; 11 | } else { 12 | textField.wrap = soft; 13 | } 14 | } 15 | 16 | function onClickButtonGenerate() { 17 | var scriptTypesElement = document.getElementById("scriptType"); 18 | var scriptTypesValue = scriptTypesElement.options[scriptTypesElement.selectedIndex].value; 19 | var textField = document.getElementById("output"); 20 | var prefixField = document.getElementById("prefix"); 21 | new CSInterface().evalScript("generateJSON()", function(json) { 22 | if(scriptTypesValue == scriptTypesElement.options[0].value) { 23 | textField.value = prefixField.value + (new Createjs()).generate(JSON.parse(json)); 24 | } else if(scriptTypesValue == scriptTypesElement.options[1].value) { 25 | textField.value = prefixField.value + (new Pixitiny()).generate(JSON.parse(json)); 26 | } else if(scriptTypesValue == scriptTypesElement.options[2].value) { 27 | textField.value = (new Pixigraphics()).generate(JSON.parse(json)); 28 | } else if(scriptTypesValue == scriptTypesElement.options[3].value) { 29 | textField.value = json; 30 | } 31 | }); 32 | } 33 | 34 | function onLoaded() { 35 | themeManager.init(); 36 | } -------------------------------------------------------------------------------- /js/parser/createjs.js: -------------------------------------------------------------------------------- 1 | var Createjs = function () {}; 2 | 3 | Createjs.prototype.BASE_64 = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", 4 | "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", 5 | "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", 6 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"]; 7 | 8 | //Map instructions to values 9 | Createjs.prototype.instructions = { 10 | "moveTo" : "000", 11 | "lineTo" : "001", 12 | "quadraticCurveTo" : "010", 13 | "bezierCurveTo" : "011", 14 | "closePath" : "100" 15 | }; 16 | 17 | //Map instructions to parameter count 18 | Createjs.prototype.paramCount = { 19 | "moveTo" : 2, 20 | "lineTo" : 2, 21 | "quadraticCurveTo" : 4, 22 | "bezierCurveTo" : 6, 23 | "closePath" : 0 24 | }; 25 | 26 | //Map size of position property to bits 27 | Createjs.prototype.sizeOfPositions = { 28 | "12" : 0, 29 | "18" : 1 30 | }; 31 | 32 | Createjs.prototype.unusedBits = "00"; 33 | 34 | Createjs.prototype.cropBox; 35 | 36 | 37 | /** 38 | * Generates a CreateJS Tiny API String from a giving JSON-Object. 39 | * 40 | * @param json 41 | * @return CreateJS Tiny API String 42 | */ 43 | Createjs.prototype.generate = function (json) { 44 | var objects = json.selection; 45 | var instruction = ""; 46 | this.cropBox = json.cropBox; 47 | for (var i = objects.length - 1; i >= 0; i--) { 48 | if (objects[i].typename == "PathItem") { 49 | instruction += this.parsePathItem(objects[i]); 50 | } else if (objects[i].typename == "GroupItem") { 51 | instruction += this.parseGroupItem(objects[i]); 52 | } else if (objects[i].typename == "CompoundPathItem") { 53 | instruction += this.parseCompoundPathItem(objects[i]); 54 | } 55 | } 56 | if (objects.length > 0) { 57 | instruction += ".cp()"; 58 | } 59 | return instruction; 60 | } 61 | 62 | /** 63 | * Generates a CreateJS Tiny API String from a givin PathItem Object. 64 | * 65 | * @param pathItem 66 | * @return CreateJS Tiny API String 67 | */ 68 | Createjs.prototype.parsePathItem = function (pathItem) { 69 | var instruction = ""; 70 | var pathPoints = pathItem.pathPoints; 71 | 72 | if (pathItem.filled) { 73 | instruction += ".f(" + this.getColor(pathItem.fillColor, pathItem.opacity) + ")"; 74 | } 75 | if (pathItem.stroked) { 76 | instruction += ".ss(" + this.getStrokeStyle(pathItem) + ")"; 77 | instruction += ".s(" + this.getColor(pathItem.strokeColor, pathItem.opacity) + ")"; 78 | } 79 | if (pathItem.stroked) { 80 | var strokeDashes = pathItem.strokeDashes; 81 | var strokeDashOffset = 0; 82 | instruction += ".sd([" + strokeDashes + "]," + strokeDashOffset + ")"; 83 | } 84 | if (pathPoints.length > 0) { 85 | instruction += ".p('" + this.convertPathItemToPathInstruction(pathItem) + "')"; 86 | } 87 | if (pathItem.stroked) { 88 | //End stroke 89 | instruction += ".es()"; 90 | } 91 | if (pathItem.filled) { 92 | //End fill 93 | instruction += ".ef()"; 94 | } 95 | return instruction; 96 | } 97 | 98 | Createjs.prototype.parseGroupItem = function (groupItem) { 99 | var instruction = ""; 100 | for (var i = 0; i < groupItem.groupItems.length; i++) { 101 | instruction += this.parseGroupItem(groupItem.groupItems[i]); 102 | } 103 | for (var i = 0; i < groupItem.pathItems.length; i++) { 104 | instruction += this.parsePathItem(groupItem.pathItems[i]); 105 | } 106 | for (var i = 0; i < groupItem.compoundPathItems.length; i++) { 107 | instruction += this.parseCompoundPathItem(groupItem.compoundPathItems[i]); 108 | } 109 | return instruction; 110 | } 111 | 112 | Createjs.prototype.parseCompoundPathItem = function (compoundPathItem) { 113 | var instruction = ""; 114 | for (var i = 0; i < compoundPathItem.pathItems.length; i++) { 115 | instruction += this.parsePathItem(compoundPathItem.pathItems[i]); 116 | } 117 | return instruction; 118 | } 119 | 120 | /** 121 | * Generates a encoded path string by converting a series of pathPoints to an bit string, which is 122 | * then encoded to a BASE_64 string. 123 | * 124 | * @param pathItem 125 | * @return a encoded path string 126 | */ 127 | Createjs.prototype.convertPathItemToPathInstruction = function (pathItem) { 128 | 129 | var pathPoints = pathItem.pathPoints; 130 | 131 | //Easeljs uses absolute movement for the first command 132 | var moveToX = pathPoints[0].anchor[0] + this.cropBox[0]; 133 | var moveToY = -1 * pathPoints[0].anchor[1] + this.cropBox[1]; 134 | 135 | //12 bits you can used numbers up to 2047, 18 bits you can use numbers up to 131071. 136 | var sizeOfPosition = 18; 137 | 138 | var bitInstruction = this.instructions["moveTo"] + this.sizeOfPositions[sizeOfPosition] + 139 | this.unusedBits + this.convertNumberToBits(moveToX, sizeOfPosition) + 140 | this.convertNumberToBits(moveToY, sizeOfPosition); 141 | 142 | var pathInstruction = this.convertBitToBase64(bitInstruction); 143 | 144 | if (pathPoints.length > 1) { 145 | for (var i = 0; i < (pathItem.closed ? pathPoints.length : (pathPoints.length - 1)); i++) { 146 | var previousPoint = pathPoints[i % pathPoints.length]; 147 | var currentPoint = pathPoints[(i + 1) % pathPoints.length]; 148 | 149 | if (currentPoint.anchor[0] == currentPoint.leftDirection[0] && 150 | currentPoint.anchor[0] == currentPoint.rightDirection[0] && 151 | currentPoint.anchor[1] == currentPoint.leftDirection[1] && 152 | currentPoint.anchor[1] == currentPoint.rightDirection[1]) { 153 | var lineToX = currentPoint.anchor[0] - previousPoint.anchor[0]; 154 | var lineToY = -1 * currentPoint.anchor[1] + previousPoint.anchor[1]; 155 | 156 | bitInstruction = this.instructions["lineTo"] + this.sizeOfPositions[sizeOfPosition] + this.unusedBits + 157 | this.convertNumberToBits(lineToX, sizeOfPosition) + this.convertNumberToBits(lineToY, sizeOfPosition); 158 | 159 | pathInstruction += this.convertBitToBase64(bitInstruction); 160 | } else { 161 | var anchorX = currentPoint.anchor[0] - currentPoint.leftDirection[0]; 162 | var anchorY = -1 * currentPoint.anchor[1] + currentPoint.leftDirection[1]; 163 | 164 | var leftDirectionX = currentPoint.leftDirection[0] - previousPoint.rightDirection[0]; 165 | var leftDirectionY = -1 * currentPoint.leftDirection[1] + previousPoint.rightDirection[1]; 166 | 167 | var rightDirectionX = previousPoint.rightDirection[0] - previousPoint.anchor[0]; 168 | var rightDirectionY = -1 * previousPoint.rightDirection[1] + previousPoint.anchor[1]; 169 | 170 | bitInstruction = this.instructions["bezierCurveTo"] + 171 | this.sizeOfPositions[sizeOfPosition] + this.unusedBits + 172 | this.convertNumberToBits(rightDirectionX, sizeOfPosition) + 173 | this.convertNumberToBits(rightDirectionY, sizeOfPosition) + 174 | this.convertNumberToBits(leftDirectionX, sizeOfPosition) + 175 | this.convertNumberToBits(leftDirectionY, sizeOfPosition) + 176 | this.convertNumberToBits(anchorX, sizeOfPosition) + 177 | this.convertNumberToBits(anchorY, sizeOfPosition); 178 | 179 | pathInstruction += this.convertBitToBase64(bitInstruction); 180 | } 181 | } 182 | } 183 | return pathInstruction; 184 | } 185 | 186 | /** 187 | * Converts an color object to a css compatible rgba string. 188 | * 189 | * @param color an color object in the format {typename: "RGBColor", red: 0-255, green: 0-255, blue: 0-255} or 190 | * {typename: "CMYKColor", cyan: 0-1, yellow: 0-1, magenta: 0-1, black: 0-1} 191 | * @param opacity the alpha component of the rgba string. 0 is transparent, 1 is opaque. 192 | * @return a css compatible color string in the format "rgba(255,255,255,1)" 193 | */ 194 | Createjs.prototype.getColor = function (color, opacity) { 195 | var r, 196 | g, 197 | b; 198 | var a = opacity / 100; 199 | 200 | if (color.typename == "RGBColor") { 201 | r = color.red; 202 | g = color.green; 203 | b = color.blue; 204 | } else if (color.typename == "CMYKColor") { 205 | //CYMK Color Codes 206 | var k = color.black; 207 | var c = color.cyan; 208 | var m = color.magenta; 209 | var y = color.yellow; 210 | 211 | //RGB Color Codes 212 | r = 255 * (1 - c / 100) * (1 - k / 100); 213 | g = 255 * (1 - m / 100) * (1 - k / 100); 214 | b = 255 * (1 - y / 100) * (1 - k / 100); 215 | } 216 | return "'rgba(" + Math.round(r) + "," + Math.round(g) + "," + Math.round(b) + "," + a + ")'"; 217 | } 218 | 219 | /** 220 | * Filters needed properties from a pathItem and converts them to arguments for the ss method. 221 | * 222 | * @return ss arguments 223 | */ 224 | Createjs.prototype.getStrokeStyle = function (pathItem) { 225 | var strokeWidth = pathItem.strokeWidth; 226 | var strokeCap; 227 | var strokeJoin; 228 | var strokeMiterLimit = pathItem.strokeMiterLimit; 229 | 230 | if (pathItem.strokeCap == "StrokeCap.BUTTENDCAP") { 231 | strokeCap = 0; 232 | } else if (pathItem.strokeCap == "StrokeCap.PROJECTINGENDCAP") { 233 | strokeCap = 1; 234 | } else if (pathItem.strokeCap == "StrokeCap.ROUNDENDCAP") { 235 | strokeCap = 2; 236 | } 237 | 238 | if (pathItem.strokeJoin == "StrokeJoin.MITERENDJOIN") { 239 | strokeJoin = 0; 240 | } else if (pathItem.strokeJoin == "StrokeJoin.ROUNDENDJOIN") { 241 | strokeJoin = 1; 242 | } else if (pathItem.strokeJoin == "StrokeJoin.BEVELENDJOIN") { 243 | strokeJoin = 2; 244 | } 245 | return strokeWidth + "," + strokeCap + "," + strokeJoin + "," + strokeMiterLimit; 246 | } 247 | 248 | /* 249 | * Converts a string of bits to a base64 string 250 | */ 251 | Createjs.prototype.convertBitToBase64 = function (bits) { 252 | var base64String = ""; 253 | var loops = bits.length / 6; 254 | for (var i = 0; i < loops; i++) { 255 | var bitsChunk = bits.substring(i * 6, i * 6 + 6); 256 | var intFromBitsChunk = parseInt(bitsChunk, 2); 257 | var base64Char = this.BASE_64[intFromBitsChunk]; 258 | base64String += base64Char; 259 | } 260 | return base64String; 261 | } 262 | 263 | /** 264 | * Floors a number an then converts it to a bit String. When the number is negative the MSB will 265 | * be 1, when it is positive the MSB will be 0. 266 | * 267 | * @param number Number which will be converted to a bit String 268 | * @param size Number of bits which will be used to represent number 269 | * @return bit string 270 | */ 271 | Createjs.prototype.convertNumberToBits = function (number, size) { 272 | //Easeljs has an accuracy of 1/10 of a pixel. 273 | number = number * 10; 274 | var sign = (number < 0 ? "1" : "0"); 275 | var result = Math.abs(Math.round(number)).toString(2); 276 | while (result.length < size - 1) { 277 | result = "0" + result; 278 | } 279 | if(result.length - 1 > size) { 280 | return "overflow"; 281 | } 282 | return sign + result; 283 | } -------------------------------------------------------------------------------- /js/parser/pixigraphics.js: -------------------------------------------------------------------------------- 1 | var Pixigraphics = function () {}; 2 | 3 | Pixigraphics.prototype = Object.create(Pixitiny.prototype); 4 | 5 | /** 6 | * Generates a PIXI_graphics API String from a giving JSON-Object. 7 | * 8 | * @param json 9 | * @return PIXI_graphics API String 10 | */ 11 | Pixigraphics.prototype.generate = function (json) { 12 | var objects = json.selection; 13 | var data = []; 14 | var type = "graphics"; 15 | var instructions = { 16 | type : type 17 | }; 18 | this.cropBox = json.cropBox; 19 | for (var i = objects.length - 1; i >= 0; i--) { 20 | if (objects[i].typename == "PathItem") { 21 | data = data.concat(this.parsePathItem(objects[i])); 22 | } else if (objects[i].typename == "GroupItem") { 23 | data = data.concat(this.parseGroupItem(objects[i])); 24 | } else if (objects[i].typename == "CompoundPathItem") { 25 | data = data.concat(this.parseCompoundPathItem(objects[i])); 26 | } 27 | } 28 | instructions.data = data; 29 | return JSON.stringify(instructions, null, 2); 30 | } 31 | 32 | /** 33 | * Generates a PIXI_graphics API String from a givin PathItem Object. 34 | * 35 | * @param pathItem 36 | * @return PIXI_graphics API String 37 | */ 38 | Pixigraphics.prototype.parsePathItem = function (pathItem) { 39 | var data = []; 40 | var pathPoints = pathItem.pathPoints; 41 | 42 | if (pathItem.filled) { 43 | data.push(this.makeDataItem("f", this.getColor(pathItem.fillColor, pathItem.opacity))); 44 | } 45 | if (pathItem.stroked) { 46 | data.push(this.makeDataItem("ss", pathItem.strokeWidth)); 47 | data.push(this.makeDataItem("s", this.getColor(pathItem.strokeColor, pathItem.opacity))); 48 | } 49 | if (pathPoints.length > 0) { 50 | data.push(this.makeDataItem("p", this.convertPathItemToPathInstruction(pathItem))); 51 | } 52 | if (pathItem.stroked) { 53 | //End stroke 54 | data.push(this.makeDataItem("es", "")); 55 | } 56 | if (pathItem.filled) { 57 | //End fill 58 | data.push(this.makeDataItem("ef", "")); 59 | } 60 | return data; 61 | } 62 | 63 | Pixigraphics.prototype.parseGroupItem = function (groupItem) { 64 | var data = []; 65 | for (var i = 0; i < groupItem.groupItems.length; i++) { 66 | data = data.concat(this.parseGroupItem(groupItem.groupItems[i])); 67 | } 68 | for (var i = 0; i < groupItem.pathItems.length; i++) { 69 | data = data.concat(this.parsePathItem(groupItem.pathItems[i])); 70 | } 71 | for (var i = 0; i < groupItem.compoundPathItems.length; i++) { 72 | data = data.concat(this.parseCompoundPathItem(groupItem.compoundPathItems[i])); 73 | } 74 | return data; 75 | } 76 | 77 | Pixigraphics.prototype.parseCompoundPathItem = function (compoundPathItem) { 78 | var data = []; 79 | for (var i = 0; i < compoundPathItem.pathItems.length; i++) { 80 | data = data.concat(this.parsePathItem(compoundPathItem.pathItems[i])); 81 | } 82 | return data; 83 | } 84 | 85 | /** 86 | * Converts an PIXI_tiny method call to an json object. 87 | * 88 | * @param cmd method to call in PIXI_tiny 89 | * @param args arguments for the call 90 | * @return json 91 | */ 92 | Pixigraphics.prototype.makeDataItem = function (cmd, args) { 93 | var dataItem = {}; 94 | dataItem.cmd = cmd; 95 | dataItem.args = args; 96 | return dataItem; 97 | } -------------------------------------------------------------------------------- /js/parser/pixitiny.js: -------------------------------------------------------------------------------- 1 | var Pixitiny = function () {}; 2 | 3 | Pixitiny.prototype = Object.create(Createjs.prototype); 4 | 5 | /** 6 | * Generates a PIXI_tiny API String from a givin PathItem Object. 7 | * 8 | * @param pathItem 9 | * @return PIXI_tiny API String 10 | */ 11 | Pixitiny.prototype.parsePathItem = function (pathItem) { 12 | var instruction = ""; 13 | var pathPoints = pathItem.pathPoints; 14 | 15 | if (pathItem.filled) { 16 | instruction += ".f(" + this.getColor(pathItem.fillColor, pathItem.opacity) + ")"; 17 | } 18 | if (pathItem.stroked) { 19 | instruction += ".ss(" +pathItem.strokeWidth + ")"; 20 | instruction += ".s(" + this.getColor(pathItem.strokeColor, pathItem.opacity) + ")"; 21 | } 22 | if (pathPoints.length > 0) { 23 | instruction += ".p('" + this.convertPathItemToPathInstruction(pathItem) + "')"; 24 | } 25 | if (pathItem.stroked) { 26 | //End stroke 27 | instruction += ".es()"; 28 | } 29 | if (pathItem.filled) { 30 | //End fill 31 | instruction += ".ef()"; 32 | } 33 | return instruction; 34 | } 35 | 36 | /** 37 | * Converts an color object to a PIXI_tiny compatible hex value. 38 | * 39 | * @param color an color object in the format {typename: "RGBColor", red: 0-255, green: 0-255, blue: 0-255} or 40 | * {typename: "CMYKColor", cyan: 0-1, yellow: 0-1, magenta: 0-1, black: 0-1} 41 | * @param opacity the alpha component of the rgba string. 0 is transparent, 1 is opaque. 42 | * @return hex value in the format "0xFFFFFF" 43 | */ 44 | Pixitiny.prototype.getColor = function (color, opacity) { 45 | var r; 46 | var g; 47 | var b; 48 | var a = opacity / 100; 49 | 50 | if (color.typename == "RGBColor") { 51 | r = color.red; 52 | g = color.green; 53 | b = color.blue; 54 | } else if (color.typename == "CMYKColor") { 55 | //CYMK Color Codes 56 | var k = color.black; 57 | var c = color.cyan; 58 | var m = color.magenta; 59 | var y = color.yellow; 60 | 61 | //RGB Color Codes 62 | r = 255 * (1 - c / 100) * (1 - k / 100); 63 | g = 255 * (1 - m / 100) * (1 - k / 100); 64 | b = 255 * (1 - y / 100) * (1 - k / 100); 65 | } 66 | return "0x" + this.convertToHex(r) + this.convertToHex(g) + this.convertToHex(b); 67 | } 68 | 69 | /* 70 | * Convers a number to a two letter hex value 71 | */ 72 | Pixitiny.prototype.convertToHex = function (number) { 73 | var hex = Math.round(number).toString(16); 74 | if (hex.length < 2) { 75 | hex = "0" + hex; 76 | } 77 | return hex; 78 | } -------------------------------------------------------------------------------- /js/themeManager.js: -------------------------------------------------------------------------------- 1 | var themeManager = (function () { 2 | 'use strict'; 3 | 4 | /* Convert the Color object to string in hexadecimal format; */ 5 | function toHex(color, delta) { 6 | function computeValue(value, delta) { 7 | var computedValue = !isNaN(delta) ? value + delta : value; 8 | if (computedValue < 0) { 9 | computedValue = 0; 10 | } else if (computedValue > 255) { 11 | computedValue = 255; 12 | } 13 | computedValue = Math.floor(computedValue); 14 | computedValue = computedValue.toString(16); 15 | return computedValue.length === 1 ? "0" + computedValue : computedValue; 16 | } 17 | var hex = ""; 18 | if (color) { 19 | hex = computeValue(color.red, delta) + computeValue(color.green, delta) + computeValue(color.blue, delta); 20 | } 21 | return hex; 22 | } 23 | 24 | function addRule(stylesheetId, selector, rule) { 25 | var stylesheet = document.getElementById(stylesheetId); 26 | if (stylesheet) { 27 | stylesheet = stylesheet.sheet; 28 | if (stylesheet.addRule) { 29 | stylesheet.addRule(selector, rule); 30 | } else if (stylesheet.insertRule) { 31 | stylesheet.insertRule(selector + ' { ' + rule + ' }', stylesheet.cssRules.length); 32 | } 33 | } 34 | } 35 | 36 | /* Update the theme with the AppSkinInfo retrieved from the host product. */ 37 | function updateThemeWithAppSkinInfo(appSkinInfo) { 38 | // console.log(appSkinInfo) 39 | var panelBgColor = appSkinInfo.panelBackgroundColor.color; 40 | var bgdColor = toHex(panelBgColor); 41 | var fontColor = "F0F0F0"; 42 | if (panelBgColor.red > 122) { 43 | fontColor = "000000"; 44 | } 45 | 46 | var styleId = "hostStyle"; 47 | addRule(styleId, "body", "background-color:" + "#" + bgdColor); 48 | addRule(styleId, "body", "color:" + "#" + fontColor); 49 | 50 | var isLight = appSkinInfo.panelBackgroundColor.color.red >= 127; 51 | if (isLight) { 52 | $("#theme").attr("href", "css/light.css"); 53 | } else { 54 | $("#theme").attr("href", "css/dark.css"); 55 | } 56 | } 57 | 58 | function onAppThemeColorChanged(event) { 59 | var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; 60 | updateThemeWithAppSkinInfo(skinInfo); 61 | } 62 | 63 | function init() { 64 | var csInterface = new CSInterface(); 65 | updateThemeWithAppSkinInfo(csInterface.hostEnvironment.appSkinInfo); 66 | csInterface.addEventListener(CSInterface.THEME_COLOR_CHANGED_EVENT, onAppThemeColorChanged); 67 | } 68 | 69 | return { 70 | init: init 71 | }; 72 | 73 | }()); -------------------------------------------------------------------------------- /lib/CSInterface.js: -------------------------------------------------------------------------------- 1 | /************************************************************************************************** 2 | * 3 | * ADOBE SYSTEMS INCORPORATED 4 | * Copyright 2013 Adobe Systems Incorporated 5 | * All Rights Reserved. 6 | * 7 | * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the 8 | * terms of the Adobe license agreement accompanying it. If you have received this file from a 9 | * source other than Adobe, then your use, modification, or distribution of it requires the prior 10 | * written permission of Adobe. 11 | * 12 | **************************************************************************************************/ 13 | 14 | /** CSInterface - v5.2.0 */ 15 | 16 | /** 17 | * Stores constants for the window types supported by the CSXS infrastructure. 18 | */ 19 | function CSXSWindowType() 20 | { 21 | }; 22 | 23 | /** Constant for the CSXS window type Panel. */ 24 | CSXSWindowType._PANEL = "Panel"; 25 | 26 | /** Constant for the CSXS window type Modeless. */ 27 | CSXSWindowType._MODELESS = "Modeless"; 28 | 29 | /** Constant for the CSXS window type ModalDialog. */ 30 | CSXSWindowType._MODAL_DIALOG = "ModalDialog"; 31 | 32 | /** EvalScript error message */ 33 | EvalScript_ErrMessage = "EvalScript error."; 34 | 35 | /** 36 | * @class Version 37 | * Defines a version number with major, minor, micro, and special 38 | * components. The major, minor and micro values are numeric; the special 39 | * value can be any string. 40 | * 41 | * @param major The major version component, a positive integer up to nine digits long. 42 | * @param minor The minor version component, a positive integer up to nine digits long. 43 | * @param micro The micro version component, a positive integer up to nine digits long. 44 | * @param special The special version component, an arbitrary string. 45 | * 46 | * @return A new \c Version object. 47 | */ 48 | function Version(major, minor, micro, special) 49 | { 50 | this.major = major; 51 | this.minor = minor; 52 | this.micro = micro; 53 | this.special = special; 54 | }; 55 | 56 | /** 57 | * The maximum value allowed for a numeric version component. 58 | * This reflects the maximum value allowed in PlugPlug and the manifest schema. 59 | */ 60 | Version.MAX_NUM = 999999999; 61 | 62 | /** 63 | * @class VersionBound 64 | * Defines a boundary for a version range, which associates a \c Version object 65 | * with a flag for whether it is an inclusive or exclusive boundary. 66 | * 67 | * @param version The \c #Version object. 68 | * @param inclusive True if this boundary is inclusive, false if it is exclusive. 69 | * 70 | * @return A new \c VersionBound object. 71 | */ 72 | function VersionBound(version, inclusive) 73 | { 74 | this.version = version; 75 | this.inclusive = inclusive; 76 | }; 77 | 78 | /** 79 | * @class VersionRange 80 | * Defines a range of versions using a lower boundary and optional upper boundary. 81 | * 82 | * @param lowerBound The \c #VersionBound object. 83 | * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary. 84 | * 85 | * @return A new \c VersionRange object. 86 | */ 87 | function VersionRange(lowerBound, upperBound) 88 | { 89 | this.lowerBound = lowerBound; 90 | this.upperBound = upperBound; 91 | }; 92 | 93 | /** 94 | * @class Runtime 95 | * Represents a runtime related to the CEP infrastructure. 96 | * Extensions can declare dependencies on particular 97 | * CEP runtime versions in the extension manifest. 98 | * 99 | * @param name The runtime name. 100 | * @param version A \c #VersionRange object that defines a range of valid versions. 101 | * 102 | * @return A new \c Runtime object. 103 | */ 104 | function Runtime(name, versionRange) 105 | { 106 | this.name = name; 107 | this.versionRange = versionRange; 108 | }; 109 | 110 | /** 111 | * @class Extension 112 | * Encapsulates a CEP-based extension to an Adobe application. 113 | * 114 | * @param id The unique identifier of this extension. 115 | * @param name The localizable display name of this extension. 116 | * @param mainPath The path of the "index.html" file. 117 | * @param basePath The base path of this extension. 118 | * @param windowType The window type of the main window of this extension. 119 | Valid values are defined by \c #CSXSWindowType. 120 | * @param width The default width in pixels of the main window of this extension. 121 | * @param height The default height in pixels of the main window of this extension. 122 | * @param minWidth The minimum width in pixels of the main window of this extension. 123 | * @param minHeight The minimum height in pixels of the main window of this extension. 124 | * @param maxWidth The maximum width in pixels of the main window of this extension. 125 | * @param maxHeight The maximum height in pixels of the main window of this extension. 126 | * @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest. 127 | * @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest. 128 | * @param requiredRuntimeList An array of \c Runtime objects for runtimes required by this extension. 129 | * @param isAutoVisible True if this extension is visible on loading. 130 | * @param isPluginExtension True if this extension has been deployed in the Plugins folder of the host application. 131 | * 132 | * @return A new \c Extension object. 133 | */ 134 | function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight, 135 | defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension) 136 | { 137 | this.id = id; 138 | this.name = name; 139 | this.mainPath = mainPath; 140 | this.basePath = basePath; 141 | this.windowType = windowType; 142 | this.width = width; 143 | this.height = height; 144 | this.minWidth = minWidth; 145 | this.minHeight = minHeight; 146 | this.maxWidth = maxWidth; 147 | this.maxHeight = maxHeight; 148 | this.defaultExtensionDataXml = defaultExtensionDataXml; 149 | this.specialExtensionDataXml = specialExtensionDataXml; 150 | this.requiredRuntimeList = requiredRuntimeList; 151 | this.isAutoVisible = isAutoVisible; 152 | this.isPluginExtension = isPluginExtension; 153 | }; 154 | 155 | /** 156 | * @class CSEvent 157 | * A standard JavaScript event, the base class for CEP events. 158 | * 159 | * @param type The name of the event type. 160 | * @param scope The scope of event, can be "GLOBAL" or "APPLICATION". 161 | * @param appId The unique identifier of the application that generated the event. 162 | * @param extensionId The unique identifier of the extension that generated the event. 163 | * 164 | * @return A new \c CSEvent object 165 | */ 166 | function CSEvent(type, scope, appId, extensionId) 167 | { 168 | this.type = type; 169 | this.scope = scope; 170 | this.appId = appId; 171 | this.extensionId = extensionId; 172 | }; 173 | 174 | /** Event-specific data. */ 175 | CSEvent.prototype.data = ""; 176 | 177 | /** 178 | * @class SystemPath 179 | * Stores operating-system-specific location constants for use in the 180 | * \c #CSInterface.getSystemPath() method. 181 | * @return A new \c SystemPath object. 182 | */ 183 | function SystemPath() 184 | { 185 | }; 186 | 187 | /** The path to user data. */ 188 | SystemPath.USER_DATA = "userData"; 189 | 190 | /** The path to common files for Adobe applications. */ 191 | SystemPath.COMMON_FILES = "commonFiles"; 192 | 193 | /** The path to the user's default document folder. */ 194 | SystemPath.MY_DOCUMENTS = "myDocuments"; 195 | 196 | /** @deprecated. Use \c #SystemPath.Extension. */ 197 | SystemPath.APPLICATION = "application"; 198 | 199 | /** The path to current extension. */ 200 | SystemPath.EXTENSION = "extension"; 201 | 202 | /** The path to hosting application's executable. */ 203 | SystemPath.HOST_APPLICATION = "hostApplication"; 204 | 205 | /** 206 | * @class ColorType 207 | * Stores color-type constants. 208 | */ 209 | function ColorType() 210 | { 211 | }; 212 | 213 | /** RGB color type. */ 214 | ColorType.RGB = "rgb"; 215 | 216 | /** Gradient color type. */ 217 | ColorType.GRADIENT = "gradient"; 218 | 219 | /** Null color type. */ 220 | ColorType.NONE = "none"; 221 | 222 | /** 223 | * @class RGBColor 224 | * Stores an RGB color with red, green, blue, and alpha values. 225 | * All values are in the range [0.0 to 255.0]. Invalid numeric values are 226 | * converted to numbers within this range. 227 | * 228 | * @param red The red value, in the range [0.0 to 255.0]. 229 | * @param green The green value, in the range [0.0 to 255.0]. 230 | * @param blue The blue value, in the range [0.0 to 255.0]. 231 | * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0]. 232 | * The default, 255.0, means that the color is fully opaque. 233 | * 234 | * @return A new RGBColor object. 235 | */ 236 | function RGBColor(red, green, blue, alpha) 237 | { 238 | this.red = red; 239 | this.green = green; 240 | this.blue = blue; 241 | this.alpha = alpha; 242 | }; 243 | 244 | /** 245 | * @class Direction 246 | * A point value in which the y component is 0 and the x component 247 | * is positive or negative for a right or left direction, 248 | * or the x component is 0 and the y component is positive or negative for 249 | * an up or down direction. 250 | * 251 | * @param x The horizontal component of the point. 252 | * @param y The vertical component of the point. 253 | * 254 | * @return A new \c Direction object. 255 | */ 256 | function Direction(x, y) 257 | { 258 | this.x = x; 259 | this.y = y; 260 | }; 261 | 262 | /** 263 | * @class GradientStop 264 | * Stores gradient stop information. 265 | * 266 | * @param offset The offset of the gradient stop, in the range [0.0 to 1.0]. 267 | * @param rgbColor The color of the gradient at this point, an \c #RGBColor object. 268 | * 269 | * @return GradientStop object. 270 | */ 271 | function GradientStop(offset, rgbColor) 272 | { 273 | this.offset = offset; 274 | this.rgbColor = rgbColor; 275 | }; 276 | 277 | /** 278 | * @class GradientColor 279 | * Stores gradient color information. 280 | * 281 | * @param type The gradient type, must be "linear". 282 | * @param direction A \c #Direction object for the direction of the gradient 283 | (up, down, right, or left). 284 | * @param numStops The number of stops in the gradient. 285 | * @param gradientStopList An array of \c #GradientStop objects. 286 | * 287 | * @return A new \c GradientColor object. 288 | */ 289 | function GradientColor(type, direction, numStops, arrGradientStop) 290 | { 291 | this.type = type; 292 | this.direction = direction; 293 | this.numStops = numStops; 294 | this.arrGradientStop = arrGradientStop; 295 | }; 296 | 297 | /** 298 | * @class UIColor 299 | * Stores color information, including the type, anti-alias level, and specific color 300 | * values in a color object of an appropriate type. 301 | * 302 | * @param type The color type, 1 for "rgb" and 2 for "gradient". 303 | The supplied color object must correspond to this type. 304 | * @param antialiasLevel The anti-alias level constant. 305 | * @param color A \c #RGBColor or \c #GradientColor object containing specific color information. 306 | * 307 | * @return A new \c UIColor object. 308 | */ 309 | function UIColor(type, antialiasLevel, color) 310 | { 311 | this.type = type; 312 | this.antialiasLevel = antialiasLevel; 313 | this.color = color; 314 | }; 315 | 316 | /** 317 | * @class AppSkinInfo 318 | * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object. 319 | * 320 | * @param baseFontFamily The base font family of the application. 321 | * @param baseFontSize The base font size of the application. 322 | * @param appBarBackgroundColor The application bar background color. 323 | * @param panelBackgroundColor The background color of the extension panel. 324 | * @param appBarBackgroundColorSRGB The application bar background color, as sRGB. 325 | * @param panelBackgroundColorSRGB The background color of the extension panel, as sRGB. 326 | * @param systemHighlightColor The operating-system highlight color, as sRGB. 327 | * 328 | * @return AppSkinInfo object. 329 | */ 330 | function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor) 331 | { 332 | this.baseFontFamily = baseFontFamily; 333 | this.baseFontSize = baseFontSize; 334 | this.appBarBackgroundColor = appBarBackgroundColor; 335 | this.panelBackgroundColor = panelBackgroundColor; 336 | this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB; 337 | this.panelBackgroundColorSRGB = panelBackgroundColorSRGB; 338 | this.systemHighlightColor = systemHighlightColor; 339 | }; 340 | 341 | /** 342 | * @class HostEnvironment 343 | * Stores information about the environment in which the extension is loaded. 344 | * 345 | * @param appName The application's name. 346 | * @param appVersion The application's version. 347 | * @param appLocale The application's current license locale. 348 | * @param appUILocale The application's current UI locale. 349 | * @param appId The application's unique identifier. 350 | * @param isAppOnline True if the application is currently online. 351 | * @param appSkinInfo An \c #AppSkinInfo object containing the application's default color and font styles. 352 | * 353 | * @return A new \c HostEnvironment object. 354 | */ 355 | function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo) 356 | { 357 | this.appName = appName; 358 | this.appVersion = appVersion; 359 | this.appLocale = appLocale; 360 | this.appUILocale = appUILocale; 361 | this.appId = appId; 362 | this.isAppOnline = isAppOnline; 363 | this.appSkinInfo = appSkinInfo; 364 | }; 365 | 366 | /** 367 | * @class HostCapabilities 368 | * Stores information about the host capabilities. 369 | * 370 | * @param EXTENDED_PANEL_MENU True if the application supports panel menu. 371 | * @param EXTENDED_PANEL_ICONS True if the application supports panel icon. 372 | * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine. 373 | * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions. 374 | * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions. 375 | * 376 | * @return A new \c HostCapabilities object. 377 | */ 378 | function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS) 379 | { 380 | this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU; 381 | this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS; 382 | this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE; 383 | this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS; 384 | this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0 385 | }; 386 | 387 | /** 388 | * @class ApiVersion 389 | * Stores current api version. 390 | * 391 | * Since 4.2.0 392 | * 393 | * @param major The major version 394 | * @param minor The minor version. 395 | * @param micro The micro version. 396 | * 397 | * @return ApiVersion object. 398 | */ 399 | function ApiVersion(major, minor, micro) 400 | { 401 | this.major = major; 402 | this.minor = minor; 403 | this.micro = micro; 404 | }; 405 | 406 | /** 407 | * @class MenuItemStatus 408 | * Stores flyout menu item status 409 | * 410 | * Since 5.2.0 411 | * 412 | * @param menuItemLabel The menu item label. 413 | * @param enabled True if user wants to enable the menu item. 414 | * @param checked True if user wants to check the menu item. 415 | * 416 | * @return MenuItemStatus object. 417 | */ 418 | function MenuItemStatus(menuItemLabel, enabled, checked) 419 | { 420 | this.menuItemLabel = menuItemLabel; 421 | this.enabled = enabled; 422 | this.checked = checked; 423 | }; 424 | 425 | /** 426 | * @class ContextMenuItemStatus 427 | * Stores the status of the context menu item. 428 | * 429 | * Since 5.2.0 430 | * 431 | * @param menuItemID The menu item id. 432 | * @param enabled True if user wants to enable the menu item. 433 | * @param checked True if user wants to check the menu item. 434 | * 435 | * @return MenuItemStatus object. 436 | */ 437 | function ContextMenuItemStatus(menuItemID, enabled, checked) 438 | { 439 | this.menuItemID = menuItemID; 440 | this.enabled = enabled; 441 | this.checked = checked; 442 | }; 443 | //------------------------------ CSInterface ---------------------------------- 444 | 445 | /** 446 | * @class CSInterface 447 | * This is the entry point to the CEP extensibility infrastructure. 448 | * Instantiate this object and use it to: 449 | * 454 | * 455 | * @return A new \c CSInterface object 456 | */ 457 | function CSInterface() 458 | { 459 | }; 460 | 461 | /** 462 | * User can add this event listener to handle native application theme color changes. 463 | * Callback function gives extensions ability to fine-tune their theme color after the 464 | * global theme color has been changed. 465 | * The callback function should be like below: 466 | * 467 | * @example 468 | * // event is a CSEvent object, but user can ignore it. 469 | * function OnAppThemeColorChanged(event) 470 | * { 471 | * // Should get a latest HostEnvironment object from application. 472 | * var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; 473 | * // Gets the style information such as color info from the skinInfo, 474 | * // and redraw all UI controls of your extension according to the style info. 475 | * } 476 | */ 477 | CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged"; 478 | 479 | /** The host environment data object. */ 480 | CSInterface.prototype.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); 481 | 482 | /** Retrieves information about the host environment in which the 483 | * extension is currently running. 484 | * 485 | * @return A \c #HostEnvironment object. 486 | */ 487 | CSInterface.prototype.getHostEnvironment = function() 488 | { 489 | this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); 490 | return this.hostEnvironment; 491 | }; 492 | 493 | /** Closes this extension. */ 494 | CSInterface.prototype.closeExtension = function() 495 | { 496 | window.__adobe_cep__.closeExtension(); 497 | }; 498 | 499 | /** 500 | * Retrieves a path for which a constant is defined in the system. 501 | * 502 | * @param pathType The path-type constant defined in \c #SystemPath , 503 | * 504 | * @return The platform-specific system path string. 505 | */ 506 | CSInterface.prototype.getSystemPath = function(pathType) 507 | { 508 | var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType)); 509 | var OSVersion = this.getOSInformation(); 510 | if (OSVersion.indexOf("Windows") >= 0) 511 | { 512 | path = path.replace("file:///", ""); 513 | } 514 | else if (OSVersion.indexOf("Mac") >= 0) 515 | { 516 | path = path.replace("file://", ""); 517 | } 518 | return path; 519 | }; 520 | 521 | /** 522 | * Evaluates a JavaScript script, which can use the JavaScript DOM 523 | * of the host application. 524 | * 525 | * @param script The JavaScript script. 526 | * @param callback Optional. A callback function that receives the result of execution. 527 | * If execution fails, the callback function receives the error message \c EvalScript_ErrMessage. 528 | */ 529 | CSInterface.prototype.evalScript = function(script, callback) 530 | { 531 | if(callback == null || callback == undefined) 532 | { 533 | callback = function(result){}; 534 | } 535 | window.__adobe_cep__.evalScript(script, callback); 536 | }; 537 | 538 | /** 539 | * Retrieves the unique identifier of the application. 540 | * in which the extension is currently running. 541 | * 542 | * @return The unique ID string. 543 | */ 544 | CSInterface.prototype.getApplicationID = function() 545 | { 546 | var appId = this.hostEnvironment.appId; 547 | return appId; 548 | }; 549 | 550 | /** 551 | * Retrieves host capability information for the application 552 | * in which the extension is currently running. 553 | * 554 | * @return A \c #HostCapabilities object. 555 | */ 556 | CSInterface.prototype.getHostCapabilities = function() 557 | { 558 | var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities() ); 559 | return hostCapabilities; 560 | }; 561 | 562 | /** 563 | * Triggers a CEP event programmatically. Yoy can use it to dispatch 564 | * an event of a predefined type, or of a type you have defined. 565 | * 566 | * @param event A \c CSEvent object. 567 | */ 568 | CSInterface.prototype.dispatchEvent = function(event) 569 | { 570 | if (typeof event.data == "object") 571 | { 572 | event.data = JSON.stringify(event.data); 573 | } 574 | 575 | window.__adobe_cep__.dispatchEvent(event); 576 | }; 577 | 578 | /** 579 | * Registers an interest in a CEP event of a particular type, and 580 | * assigns an event handler. 581 | * The event infrastructure notifies your extension when events of this type occur, 582 | * passing the event object to the registered handler function. 583 | * 584 | * @param type The name of the event type of interest. 585 | * @param listener The JavaScript handler function or method. 586 | * @param obj Optional, the object containing the handler method, if any. 587 | * Default is null. 588 | */ 589 | CSInterface.prototype.addEventListener = function(type, listener, obj) 590 | { 591 | window.__adobe_cep__.addEventListener(type, listener, obj); 592 | }; 593 | 594 | /** 595 | * Removes a registered event listener. 596 | * 597 | * @param type The name of the event type of interest. 598 | * @param listener The JavaScript handler function or method that was registered. 599 | * @param obj Optional, the object containing the handler method, if any. 600 | * Default is null. 601 | */ 602 | CSInterface.prototype.removeEventListener = function(type, listener, obj) 603 | { 604 | window.__adobe_cep__.removeEventListener(type, listener, obj); 605 | }; 606 | 607 | /** 608 | * Loads and launches another extension, or activates the extension if it is already loaded. 609 | * 610 | * @param extensionId The extension's unique identifier. 611 | * @param startupParams Not currently used, pass "". 612 | * 613 | * @example 614 | * To launch the extension "help" with ID "HLP" from this extension, call: 615 | * requestOpenExtension("HLP", ""); 616 | * 617 | */ 618 | CSInterface.prototype.requestOpenExtension = function(extensionId, params) 619 | { 620 | window.__adobe_cep__.requestOpenExtension(extensionId, params); 621 | }; 622 | 623 | /** 624 | * Retrieves the list of extensions currently loaded in the current host application. 625 | * The extension list is initialized once, and remains the same during the lifetime 626 | * of the CEP session. 627 | * 628 | * @param extensionIds Optional, an array of unique identifiers for extensions of interest. 629 | * If omitted, retrieves data for all extensions. 630 | * 631 | * @return Zero or more \c #Extension objects. 632 | */ 633 | CSInterface.prototype.getExtensions = function(extensionIds) 634 | { 635 | var extensionIdsStr = JSON.stringify(extensionIds); 636 | var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr); 637 | 638 | var extensions = JSON.parse(extensionsStr); 639 | return extensions; 640 | }; 641 | 642 | /** 643 | * Retrieves network-related preferences. 644 | * 645 | * @return A JavaScript object containing network preferences. 646 | */ 647 | CSInterface.prototype.getNetworkPreferences = function() 648 | { 649 | var result = window.__adobe_cep__.getNetworkPreferences(); 650 | var networkPre = JSON.parse(result); 651 | 652 | return networkPre; 653 | }; 654 | 655 | /** 656 | * Initializes the resource bundle for this extension with property values 657 | * for the current application and locale. 658 | * To support multiple locales, you must define a property file for each locale, 659 | * containing keyed display-string values for that locale. 660 | * See localization documentation for Extension Builder and related products. 661 | * 662 | * Keys can be in the 663 | * form key.value="localized string", for use in HTML text elements. 664 | * For example, in this input element, the localized \c key.value string is displayed 665 | * instead of the empty \c value string: 666 | * 667 | * 668 | * 669 | * @return An object containing the resource bundle information. 670 | */ 671 | CSInterface.prototype.initResourceBundle = function() 672 | { 673 | var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle()); 674 | var resElms = document.querySelectorAll('[data-locale]'); 675 | for (var n = 0; n < resElms.length; n++) 676 | { 677 | var resEl = resElms[n]; 678 | // Get the resource key from the element. 679 | var resKey = resEl.getAttribute('data-locale'); 680 | if (resKey) 681 | { 682 | // Get all the resources that start with the key. 683 | for (var key in resourceBundle) 684 | { 685 | if (key.indexOf(resKey) == 0) 686 | { 687 | var resValue = resourceBundle[key]; 688 | if (key.length == resKey.length) 689 | { 690 | resEl.innerHTML = resValue; 691 | } 692 | else if ('.' == key.charAt(resKey.length)) 693 | { 694 | var attrKey = key.substring(resKey.length + 1); 695 | resEl[attrKey] = resValue; 696 | } 697 | } 698 | } 699 | } 700 | } 701 | return resourceBundle; 702 | }; 703 | 704 | /** 705 | * Writes installation information to a file. 706 | * 707 | * @return The file path. 708 | */ 709 | CSInterface.prototype.dumpInstallationInfo = function() 710 | { 711 | return window.__adobe_cep__.dumpInstallationInfo(); 712 | }; 713 | 714 | /** 715 | * Retrieves version information for the current Operating System, 716 | * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values. 717 | * 718 | * @return A string containing the OS version, or "unknown Operation System". 719 | * If user customizes the User Agent by setting CEF command parameter "--user-agent", only 720 | * "Mac OS X" or "Windows" will be returned. 721 | */ 722 | CSInterface.prototype.getOSInformation = function() 723 | { 724 | var userAgent = navigator.userAgent; 725 | 726 | if ((navigator.platform == "Win32") || (navigator.platform == "Windows")) 727 | { 728 | var winVersion = "Windows"; 729 | var winBit = ""; 730 | if (userAgent.indexOf("Windows") > -1) 731 | { 732 | if (userAgent.indexOf("Windows NT 5.0") > -1) 733 | { 734 | winVersion = "Windows 2000 "; 735 | } 736 | else if (userAgent.indexOf("Windows NT 5.1") > -1) 737 | { 738 | winVersion = "Windows XP "; 739 | } 740 | else if (userAgent.indexOf("Windows NT 5.2") > -1) 741 | { 742 | winVersion = "Windows Server 2003 "; 743 | } 744 | else if (userAgent.indexOf("Windows NT 6.0") > -1) 745 | { 746 | winVersion = "Windows Vista "; 747 | } 748 | else if (userAgent.indexOf("Windows NT 6.1") > -1) 749 | { 750 | winVersion = "Windows 7 "; 751 | } 752 | else if (userAgent.indexOf("Windows NT 6.2") > -1) 753 | { 754 | winVersion = "Windows 8 "; 755 | } 756 | 757 | if (userAgent.indexOf("WOW64") > -1) 758 | { 759 | winBit = "64-bit"; 760 | } 761 | else 762 | { 763 | winBit = "32-bit"; 764 | } 765 | } 766 | 767 | return winVersion + winBit; 768 | } 769 | else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh")) 770 | { 771 | var result = "Mac OS X"; 772 | var agentStr = new String(); 773 | agentStr = userAgent; 774 | if (agentStr.indexOf("Mac OS X") > -1) 775 | { 776 | var verLength = agentStr.indexOf(")") - agentStr.indexOf("Mac OS X"); 777 | var verStr = agentStr.substr(agentStr.indexOf("Mac OS X"), verLength); 778 | result = verStr.replace("_", "."); 779 | result = result.replace("_", "."); 780 | } 781 | 782 | return result; 783 | } 784 | 785 | return "Unknown Operation System"; 786 | }; 787 | 788 | /** 789 | * Opens a page in the default system browser. 790 | * 791 | * Since 4.2.0 792 | * 793 | * @param url The URL of the page/file to open, or the email address. 794 | * Must use HTTP/HTTPS/file/mailto protocol. For example: 795 | * "http://www.adobe.com" 796 | * "https://github.com" 797 | * "file:///C:/log.txt" 798 | * "mailto:test@adobe.com" 799 | * 800 | * @return One of these error codes:\n 801 | * \n 807 | */ 808 | CSInterface.prototype.openURLInDefaultBrowser = function(url) 809 | { 810 | return cep.util.openURLInDefaultBrowser(url); 811 | }; 812 | 813 | /** 814 | * Retrieves extension ID. 815 | * 816 | * Since 4.2.0 817 | * 818 | * @return extension ID. 819 | */ 820 | CSInterface.prototype.getExtensionID = function() 821 | { 822 | return window.__adobe_cep__.getExtensionId(); 823 | }; 824 | 825 | /** 826 | * Retrieves the scale factor of screen. 827 | * On Windows platform, the value of scale factor might be different from operating system's scale factor, 828 | * since host application may use its self-defined scale factor. 829 | * 830 | * Since 4.2.0 831 | * 832 | * @return One of the following integer. 833 | * \n 838 | */ 839 | CSInterface.prototype.getScaleFactor = function() 840 | { 841 | return window.__adobe_cep__.getScaleFactor(); 842 | }; 843 | 844 | /** 845 | * Set a handler to detect any changes of scale factor. This only works on Mac. 846 | * 847 | * Since 4.2.0 848 | * 849 | * @param handler The function to be called when scale factor is changed. 850 | * 851 | */ 852 | CSInterface.prototype.setScaleFactorChangedHandler = function(handler) 853 | { 854 | window.__adobe_cep__.setScaleFactorChangedHandler(handler); 855 | }; 856 | 857 | /** 858 | * Retrieves current API version. 859 | * 860 | * Since 4.2.0 861 | * 862 | * @return ApiVersion object. 863 | * 864 | */ 865 | CSInterface.prototype.getCurrentApiVersion = function() 866 | { 867 | var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion()); 868 | return apiVersion; 869 | }; 870 | 871 | /** 872 | * Set panel flyout menu by an XML. 873 | * 874 | * Since 5.2.0 875 | * 876 | * If user wants to be noticed when clicking an menu item, user needs to register "com.adobe.csxs.events.flyoutMenuClicked" Event by calling AddEventListener. 877 | * When an menu item is clicked, the event callback function will be called. 878 | * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes. 879 | * 880 | * @param menu A XML string which describes menu structure. 881 | * An example menu XML: 882 | * 883 | * 884 | * 885 | * 886 | * 887 | * 888 | * 889 | * 890 | * 891 | * 892 | * 893 | * 894 | */ 895 | CSInterface.prototype.setPanelFlyoutMenu = function(menu) 896 | { 897 | if ("string" != typeof menu) 898 | { 899 | return; 900 | } 901 | 902 | window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu); 903 | }; 904 | 905 | /** 906 | * Updates a menu item in the extension window's flyout menu, by setting the enabled 907 | * and selection status. 908 | * 909 | * Since 5.2.0 910 | * 911 | * @param menuItemLabel The menu item label. 912 | * @param enabled True to enable the item, false to disable it (gray it out). 913 | * @param checked True to select the item, false to deselect it. 914 | * 915 | * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false). 916 | * Fails silently if menu label is invalid. 917 | * 918 | * @see HostCapabilities.EXTENDED_PANEL_MENU 919 | */ 920 | CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked) 921 | { 922 | var ret = false; 923 | if (this.getHostCapabilities().EXTENDED_PANEL_MENU) 924 | { 925 | var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked); 926 | ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus)); 927 | } 928 | return ret; 929 | }; 930 | 931 | 932 | /** 933 | * Set context menu by XML string. 934 | * 935 | * Since 5.2.0 936 | * 937 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 938 | * - an item without menu ID or menu name is disabled and is not shown. 939 | * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 940 | * - Checkable attribute takes precedence over Checked attribute. 941 | * 942 | * @param menu A XML string which describes menu structure. 943 | * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. 944 | * 945 | * An example menu XML: 946 | * 947 | * 948 | * 949 | * 950 | * 951 | * 952 | * 953 | * 954 | * 955 | * 956 | * 957 | */ 958 | CSInterface.prototype.setContextMenu = function(menu, callback) 959 | { 960 | if ("string" != typeof menu) 961 | { 962 | return; 963 | } 964 | 965 | window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback); 966 | }; 967 | 968 | /** 969 | * Updates a context menu item by setting the enabled and selection status. 970 | * 971 | * Since 5.2.0 972 | * 973 | * @param menuItemID The menu item ID. 974 | * @param enabled True to enable the item, false to disable it (gray it out). 975 | * @param checked True to select the item, false to deselect it. 976 | */ 977 | CSInterface.prototype.updateContextMenuItem = function(menuItemID, enabled, checked) 978 | { 979 | var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked); 980 | ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus)); 981 | }; -------------------------------------------------------------------------------- /my.conf.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreyRook/Draw2Script/ea0bf8253a2df27926cd8bf295429c062ba37dcc/my.conf.js -------------------------------------------------------------------------------- /spec/createjs.spec.js: -------------------------------------------------------------------------------- 1 | // hack for executing code on node.js 2 | if(typeof module !== 'undefined') { 3 | fs = require('fs'); 4 | var code = fs.readFileSync('js/parser/createjs.js', 'utf-8'); 5 | eval(code); 6 | } 7 | 8 | 9 | // actual test-case 10 | describe("Createjs Parser Test Suite", function() { 11 | 12 | var createjs = new Createjs(); 13 | 14 | it("testGenerate", function() { 15 | var pathItem = { 16 | "typename" : "PathItem", 17 | "closed" : true, 18 | "filled" : true, 19 | "fillColor" : { 20 | "red" : 0, 21 | "green" : 0, 22 | "blue" : 0, 23 | "typename" : "RGBColor" 24 | }, 25 | "opacity" : 100, 26 | "stroked" : false, 27 | "strokeColor" : { 28 | "cyan" : 0, 29 | "magenta" : 0, 30 | "yellow" : 0, 31 | "black" : 100, 32 | "typename" : "CMYKColor" 33 | }, 34 | "strokeDashes" : [ 35 | 36 | ], 37 | "strokeDashOffset" : 0, 38 | "strokeCap" : {}, 39 | "strokeJoin" : {}, 40 | "strokeMiterLimit" : 10, 41 | "strokeWidth" : 6, 42 | "pathPoints" : [{ 43 | "anchor" : [ 44 | 0, 45 | 0 46 | ], 47 | "leftDirection" : [ 48 | 0, 49 | 0 50 | ], 51 | "rightDirection" : [ 52 | 0, 53 | 0 54 | ] 55 | }, { 56 | "anchor" : [ 57 | 10, 58 | 0 59 | ], 60 | "leftDirection" : [ 61 | 10, 62 | 0 63 | ], 64 | "rightDirection" : [ 65 | 10, 66 | 0 67 | ] 68 | }, { 69 | "anchor" : [ 70 | 10, 71 | 10 72 | ], 73 | "leftDirection" : [ 74 | 10, 75 | 10 76 | ], 77 | "rightDirection" : [ 78 | 10, 79 | 10 80 | ] 81 | }, { 82 | "anchor" : [ 83 | 0, 84 | 10 85 | ], 86 | "leftDirection" : [ 87 | 0, 88 | 10 89 | ], 90 | "rightDirection" : [ 91 | 0, 92 | 10 93 | ] 94 | } 95 | ] 96 | }; 97 | 98 | var groupItem = { 99 | "typename": "GroupItem", 100 | "groupItems": [], 101 | "pathItems": [pathItem], 102 | "compoundPathItems": [] 103 | }; 104 | 105 | var json = { 106 | "cropBox" : [0,0], 107 | "selection" : [groupItem] 108 | } 109 | 110 | createjs.cropBox = json.cropBox; 111 | 112 | var expectedResult = ".f('rgba(0,0,0,1)').p('" + 113 | createjs.convertPathItemToPathInstruction(pathItem) + "').ef().cp()" 114 | this.cropBox = json.cropBox; 115 | var result = createjs.generate(json); 116 | expect(result).toBe(expectedResult); 117 | 118 | }); 119 | 120 | it("testConvertPathItemToPathInstruction", function() { 121 | createjs.cropBox = [0,0]; 122 | var pathItem = { 123 | "pathPoints" : [{ 124 | "anchor" : [ 125 | 0, 126 | 0 127 | ], 128 | "leftDirection" : [ 129 | 0, 130 | 0 131 | ], 132 | "rightDirection" : [ 133 | 0, 134 | 0 135 | ] 136 | } 137 | ] 138 | }; 139 | expect(createjs.convertPathItemToPathInstruction(pathItem)).toBe("EAAAAAA"); 140 | 141 | pathItem = { 142 | "pathPoints" : [{ 143 | "anchor" : [ 144 | 0, 145 | 0 146 | ], 147 | "leftDirection" : [ 148 | 0, 149 | 0 150 | ], 151 | "rightDirection" : [ 152 | 0, 153 | 0 154 | ] 155 | }, { 156 | "anchor" : [ 157 | 10, 158 | 0 159 | ], 160 | "leftDirection" : [ 161 | 10, 162 | 0 163 | ], 164 | "rightDirection" : [ 165 | 10, 166 | 0 167 | ] 168 | } 169 | ] 170 | }; 171 | expect(createjs.convertPathItemToPathInstruction(pathItem)).toBe("EAAAAAAMABkAAA"); 172 | }); 173 | 174 | it("testGetColor", function () { 175 | var testColor = { 176 | typename: 'RGBColor', 177 | red: '0', 178 | green: '0', 179 | blue: '0' 180 | }; 181 | 182 | var testOpactiy = 100; 183 | expect(createjs.getColor(testColor, testOpactiy)).toBe("'rgba(0,0,0,1)'"); 184 | 185 | testColor = { 186 | typename: 'RGBColor', 187 | red: '255', 188 | green: '255', 189 | blue: '255' 190 | }; 191 | expect(createjs.getColor(testColor, testOpactiy)).toBe("'rgba(255,255,255,1)'"); 192 | 193 | testColor = { 194 | typename: 'CMYKColor', 195 | cyan: '0', 196 | black: '100', 197 | magenta: '0', 198 | yellow: '0' 199 | } 200 | expect(createjs.getColor(testColor, testOpactiy)).toBe("'rgba(0,0,0,1)'"); 201 | }); 202 | 203 | it('testGetStrokeStyle', function() { 204 | var pathItem = { 205 | "typename" : "PathItem", 206 | "closed" : true, 207 | "filled" : false, 208 | "fillColor" : { 209 | "gray" : 0, 210 | "typename" : "GrayColor" 211 | }, 212 | "opacity" : 100, 213 | "stroked" : true, 214 | "strokeColor" : { 215 | "cyan" : 0, 216 | "magenta" : 0, 217 | "yellow" : 0, 218 | "black" : 100, 219 | "typename" : "CMYKColor" 220 | }, 221 | "strokeDashes" : [ 222 | 223 | ], 224 | "strokeDashOffset" : 0, 225 | "strokeCap" : "StrokeCap.BUTTENDCAP", 226 | "strokeJoin" : "StrokeJoin.MITERENDJOIN", 227 | "strokeMiterLimit" : 10, 228 | "strokeWidth" : 6, 229 | "pathPoints" : [{ 230 | "anchor" : [ 231 | 0, 232 | 0 233 | ], 234 | "leftDirection" : [ 235 | 0, 236 | 0 237 | ], 238 | "rightDirection" : [ 239 | 0, 240 | 0 241 | ] 242 | }, { 243 | "anchor" : [ 244 | 10, 245 | 0 246 | ], 247 | "leftDirection" : [ 248 | 10, 249 | 0 250 | ], 251 | "rightDirection" : [ 252 | 10, 253 | 0 254 | ] 255 | }, { 256 | "anchor" : [ 257 | 10, 258 | 10 259 | ], 260 | "leftDirection" : [ 261 | 10, 262 | 10 263 | ], 264 | "rightDirection" : [ 265 | 10, 266 | 10 267 | ] 268 | }, { 269 | "anchor" : [ 270 | 0, 271 | 10 272 | ], 273 | "leftDirection" : [ 274 | 0, 275 | 10 276 | ], 277 | "rightDirection" : [ 278 | 0, 279 | 10 280 | ] 281 | } 282 | ] 283 | }; 284 | 285 | expect(createjs.getStrokeStyle(pathItem)).toBe("6,0,0,10"); 286 | }); 287 | 288 | 289 | it('testConvertBitToBase64', function () { 290 | var bits = ["000000", "000001", "111111000000"]; 291 | var base64 = ["A", "B", "/A"]; 292 | for(var i = 0; i < bits.length; i++) { 293 | expect(createjs.convertBitToBase64(bits[i])).toBe(base64[i]); 294 | } 295 | }); 296 | 297 | it('testConvertNumberToBits', function () { 298 | var number = [0,0.2,0.4,0.6,0.8,10.0,100.0,200000.0,-0.1,-2.0]; 299 | var bits12 = ["000000000000","000000000010","000000000100","000000000110","000000001000", 300 | "000001100100","001111101000","overflow","100000000001","100000010100"]; 301 | var bits18 = ["000000000000000000","000000000000000010","000000000000000100", 302 | "000000000000000110","000000000000001000","000000000001100100", 303 | "000000001111101000","overflow","100000000000000001","100000000000010100"]; 304 | for(var i = 0; i < number.length; i++) { 305 | expect(createjs.convertNumberToBits(number[i],12)).toBe(bits12[i]); 306 | expect(createjs.convertNumberToBits(number[i],18)).toBe(bits18[i]); 307 | } 308 | }); 309 | }); 310 | -------------------------------------------------------------------------------- /spec/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Insert title here 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /spec/jasmine/boot.js: -------------------------------------------------------------------------------- 1 | /** 2 | Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. 3 | 4 | If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. 5 | 6 | The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. 7 | 8 | [jasmine-gem]: http://github.com/pivotal/jasmine-gem 9 | */ 10 | 11 | (function() { 12 | 13 | /** 14 | * ## Require & Instantiate 15 | * 16 | * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. 17 | */ 18 | window.jasmine = jasmineRequire.core(jasmineRequire); 19 | 20 | /** 21 | * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. 22 | */ 23 | jasmineRequire.html(jasmine); 24 | 25 | /** 26 | * Create the Jasmine environment. This is used to run all specs in a project. 27 | */ 28 | var env = jasmine.getEnv(); 29 | 30 | /** 31 | * ## The Global Interface 32 | * 33 | * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. 34 | */ 35 | var jasmineInterface = jasmineRequire.interface(jasmine, env); 36 | 37 | /** 38 | * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. 39 | */ 40 | extend(window, jasmineInterface); 41 | 42 | /** 43 | * ## Runner Parameters 44 | * 45 | * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. 46 | */ 47 | 48 | var queryString = new jasmine.QueryString({ 49 | getWindowLocation: function() { return window.location; } 50 | }); 51 | 52 | var catchingExceptions = queryString.getParam("catch"); 53 | env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); 54 | 55 | var throwingExpectationFailures = queryString.getParam("throwFailures"); 56 | env.throwOnExpectationFailure(throwingExpectationFailures); 57 | 58 | /** 59 | * ## Reporters 60 | * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). 61 | */ 62 | var htmlReporter = new jasmine.HtmlReporter({ 63 | env: env, 64 | onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); }, 65 | onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); }, 66 | addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); }, 67 | getContainer: function() { return document.body; }, 68 | createElement: function() { return document.createElement.apply(document, arguments); }, 69 | createTextNode: function() { return document.createTextNode.apply(document, arguments); }, 70 | timer: new jasmine.Timer() 71 | }); 72 | 73 | /** 74 | * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. 75 | */ 76 | env.addReporter(jasmineInterface.jsApiReporter); 77 | env.addReporter(htmlReporter); 78 | 79 | /** 80 | * Filter which specs will be run by matching the start of the full name against the `spec` query param. 81 | */ 82 | var specFilter = new jasmine.HtmlSpecFilter({ 83 | filterString: function() { return queryString.getParam("spec"); } 84 | }); 85 | 86 | env.specFilter = function(spec) { 87 | return specFilter.matches(spec.getFullName()); 88 | }; 89 | 90 | /** 91 | * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. 92 | */ 93 | window.setTimeout = window.setTimeout; 94 | window.setInterval = window.setInterval; 95 | window.clearTimeout = window.clearTimeout; 96 | window.clearInterval = window.clearInterval; 97 | 98 | /** 99 | * ## Execution 100 | * 101 | * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. 102 | */ 103 | var currentWindowOnload = window.onload; 104 | 105 | window.onload = function() { 106 | if (currentWindowOnload) { 107 | currentWindowOnload(); 108 | } 109 | htmlReporter.initialize(); 110 | env.execute(); 111 | }; 112 | 113 | /** 114 | * Helper function for readability above. 115 | */ 116 | function extend(destination, source) { 117 | for (var property in source) destination[property] = source[property]; 118 | return destination; 119 | } 120 | 121 | }()); 122 | -------------------------------------------------------------------------------- /spec/jasmine/console.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2015 Pivotal Labs 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | function getJasmineRequireObj() { 24 | if (typeof module !== 'undefined' && module.exports) { 25 | return exports; 26 | } else { 27 | window.jasmineRequire = window.jasmineRequire || {}; 28 | return window.jasmineRequire; 29 | } 30 | } 31 | 32 | getJasmineRequireObj().console = function(jRequire, j$) { 33 | j$.ConsoleReporter = jRequire.ConsoleReporter(); 34 | }; 35 | 36 | getJasmineRequireObj().ConsoleReporter = function() { 37 | 38 | var noopTimer = { 39 | start: function(){}, 40 | elapsed: function(){ return 0; } 41 | }; 42 | 43 | function ConsoleReporter(options) { 44 | var print = options.print, 45 | showColors = options.showColors || false, 46 | onComplete = options.onComplete || function() {}, 47 | timer = options.timer || noopTimer, 48 | specCount, 49 | failureCount, 50 | failedSpecs = [], 51 | pendingCount, 52 | ansi = { 53 | green: '\x1B[32m', 54 | red: '\x1B[31m', 55 | yellow: '\x1B[33m', 56 | none: '\x1B[0m' 57 | }, 58 | failedSuites = []; 59 | 60 | print('ConsoleReporter is deprecated and will be removed in a future version.'); 61 | 62 | this.jasmineStarted = function() { 63 | specCount = 0; 64 | failureCount = 0; 65 | pendingCount = 0; 66 | print('Started'); 67 | printNewline(); 68 | timer.start(); 69 | }; 70 | 71 | this.jasmineDone = function() { 72 | printNewline(); 73 | for (var i = 0; i < failedSpecs.length; i++) { 74 | specFailureDetails(failedSpecs[i]); 75 | } 76 | 77 | if(specCount > 0) { 78 | printNewline(); 79 | 80 | var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + 81 | failureCount + ' ' + plural('failure', failureCount); 82 | 83 | if (pendingCount) { 84 | specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); 85 | } 86 | 87 | print(specCounts); 88 | } else { 89 | print('No specs found'); 90 | } 91 | 92 | printNewline(); 93 | var seconds = timer.elapsed() / 1000; 94 | print('Finished in ' + seconds + ' ' + plural('second', seconds)); 95 | printNewline(); 96 | 97 | for(i = 0; i < failedSuites.length; i++) { 98 | suiteFailureDetails(failedSuites[i]); 99 | } 100 | 101 | onComplete(failureCount === 0); 102 | }; 103 | 104 | this.specDone = function(result) { 105 | specCount++; 106 | 107 | if (result.status == 'pending') { 108 | pendingCount++; 109 | print(colored('yellow', '*')); 110 | return; 111 | } 112 | 113 | if (result.status == 'passed') { 114 | print(colored('green', '.')); 115 | return; 116 | } 117 | 118 | if (result.status == 'failed') { 119 | failureCount++; 120 | failedSpecs.push(result); 121 | print(colored('red', 'F')); 122 | } 123 | }; 124 | 125 | this.suiteDone = function(result) { 126 | if (result.failedExpectations && result.failedExpectations.length > 0) { 127 | failureCount++; 128 | failedSuites.push(result); 129 | } 130 | }; 131 | 132 | return this; 133 | 134 | function printNewline() { 135 | print('\n'); 136 | } 137 | 138 | function colored(color, str) { 139 | return showColors ? (ansi[color] + str + ansi.none) : str; 140 | } 141 | 142 | function plural(str, count) { 143 | return count == 1 ? str : str + 's'; 144 | } 145 | 146 | function repeat(thing, times) { 147 | var arr = []; 148 | for (var i = 0; i < times; i++) { 149 | arr.push(thing); 150 | } 151 | return arr; 152 | } 153 | 154 | function indent(str, spaces) { 155 | var lines = (str || '').split('\n'); 156 | var newArr = []; 157 | for (var i = 0; i < lines.length; i++) { 158 | newArr.push(repeat(' ', spaces).join('') + lines[i]); 159 | } 160 | return newArr.join('\n'); 161 | } 162 | 163 | function specFailureDetails(result) { 164 | printNewline(); 165 | print(result.fullName); 166 | 167 | for (var i = 0; i < result.failedExpectations.length; i++) { 168 | var failedExpectation = result.failedExpectations[i]; 169 | printNewline(); 170 | print(indent(failedExpectation.message, 2)); 171 | print(indent(failedExpectation.stack, 2)); 172 | } 173 | 174 | printNewline(); 175 | } 176 | 177 | function suiteFailureDetails(result) { 178 | for (var i = 0; i < result.failedExpectations.length; i++) { 179 | printNewline(); 180 | print(colored('red', 'An error was thrown in an afterAll')); 181 | printNewline(); 182 | print(colored('red', 'AfterAll ' + result.failedExpectations[i].message)); 183 | 184 | } 185 | printNewline(); 186 | } 187 | } 188 | 189 | return ConsoleReporter; 190 | }; 191 | -------------------------------------------------------------------------------- /spec/jasmine/jasmine-html.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2015 Pivotal Labs 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | jasmineRequire.html = function(j$) { 24 | j$.ResultsNode = jasmineRequire.ResultsNode(); 25 | j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); 26 | j$.QueryString = jasmineRequire.QueryString(); 27 | j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); 28 | }; 29 | 30 | jasmineRequire.HtmlReporter = function(j$) { 31 | 32 | var noopTimer = { 33 | start: function() {}, 34 | elapsed: function() { return 0; } 35 | }; 36 | 37 | function HtmlReporter(options) { 38 | var env = options.env || {}, 39 | getContainer = options.getContainer, 40 | createElement = options.createElement, 41 | createTextNode = options.createTextNode, 42 | onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, 43 | onThrowExpectationsClick = options.onThrowExpectationsClick || function() {}, 44 | addToExistingQueryString = options.addToExistingQueryString || defaultQueryString, 45 | timer = options.timer || noopTimer, 46 | results = [], 47 | specsExecuted = 0, 48 | failureCount = 0, 49 | pendingSpecCount = 0, 50 | htmlReporterMain, 51 | symbols, 52 | failedSuites = []; 53 | 54 | this.initialize = function() { 55 | clearPrior(); 56 | htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, 57 | createDom('div', {className: 'banner'}, 58 | createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}), 59 | createDom('span', {className: 'version'}, j$.version) 60 | ), 61 | createDom('ul', {className: 'symbol-summary'}), 62 | createDom('div', {className: 'alert'}), 63 | createDom('div', {className: 'results'}, 64 | createDom('div', {className: 'failures'}) 65 | ) 66 | ); 67 | getContainer().appendChild(htmlReporterMain); 68 | 69 | symbols = find('.symbol-summary'); 70 | }; 71 | 72 | var totalSpecsDefined; 73 | this.jasmineStarted = function(options) { 74 | totalSpecsDefined = options.totalSpecsDefined || 0; 75 | timer.start(); 76 | }; 77 | 78 | var summary = createDom('div', {className: 'summary'}); 79 | 80 | var topResults = new j$.ResultsNode({}, '', null), 81 | currentParent = topResults; 82 | 83 | this.suiteStarted = function(result) { 84 | currentParent.addChild(result, 'suite'); 85 | currentParent = currentParent.last(); 86 | }; 87 | 88 | this.suiteDone = function(result) { 89 | if (result.status == 'failed') { 90 | failedSuites.push(result); 91 | } 92 | 93 | if (currentParent == topResults) { 94 | return; 95 | } 96 | 97 | currentParent = currentParent.parent; 98 | }; 99 | 100 | this.specStarted = function(result) { 101 | currentParent.addChild(result, 'spec'); 102 | }; 103 | 104 | var failures = []; 105 | this.specDone = function(result) { 106 | if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') { 107 | console.error('Spec \'' + result.fullName + '\' has no expectations.'); 108 | } 109 | 110 | if (result.status != 'disabled') { 111 | specsExecuted++; 112 | } 113 | 114 | symbols.appendChild(createDom('li', { 115 | className: noExpectations(result) ? 'empty' : result.status, 116 | id: 'spec_' + result.id, 117 | title: result.fullName 118 | } 119 | )); 120 | 121 | if (result.status == 'failed') { 122 | failureCount++; 123 | 124 | var failure = 125 | createDom('div', {className: 'spec-detail failed'}, 126 | createDom('div', {className: 'description'}, 127 | createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) 128 | ), 129 | createDom('div', {className: 'messages'}) 130 | ); 131 | var messages = failure.childNodes[1]; 132 | 133 | for (var i = 0; i < result.failedExpectations.length; i++) { 134 | var expectation = result.failedExpectations[i]; 135 | messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message)); 136 | messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack)); 137 | } 138 | 139 | failures.push(failure); 140 | } 141 | 142 | if (result.status == 'pending') { 143 | pendingSpecCount++; 144 | } 145 | }; 146 | 147 | this.jasmineDone = function() { 148 | var banner = find('.banner'); 149 | var alert = find('.alert'); 150 | alert.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); 151 | 152 | banner.appendChild( 153 | createDom('div', { className: 'run-options' }, 154 | createDom('span', { className: 'trigger' }, 'Options'), 155 | createDom('div', { className: 'payload' }, 156 | createDom('div', { className: 'exceptions' }, 157 | createDom('input', { 158 | className: 'raise', 159 | id: 'raise-exceptions', 160 | type: 'checkbox' 161 | }), 162 | createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions')), 163 | createDom('div', { className: 'throw-failures' }, 164 | createDom('input', { 165 | className: 'throw', 166 | id: 'throw-failures', 167 | type: 'checkbox' 168 | }), 169 | createDom('label', { className: 'label', 'for': 'throw-failures' }, 'stop spec on expectation failure')) 170 | ) 171 | )); 172 | 173 | var raiseCheckbox = find('#raise-exceptions'); 174 | 175 | raiseCheckbox.checked = !env.catchingExceptions(); 176 | raiseCheckbox.onclick = onRaiseExceptionsClick; 177 | 178 | var throwCheckbox = find('#throw-failures'); 179 | throwCheckbox.checked = env.throwingExpectationFailures(); 180 | throwCheckbox.onclick = onThrowExpectationsClick; 181 | 182 | var optionsMenu = find('.run-options'), 183 | optionsTrigger = optionsMenu.querySelector('.trigger'), 184 | optionsPayload = optionsMenu.querySelector('.payload'), 185 | isOpen = /\bopen\b/; 186 | 187 | optionsTrigger.onclick = function() { 188 | if (isOpen.test(optionsPayload.className)) { 189 | optionsPayload.className = optionsPayload.className.replace(isOpen, ''); 190 | } else { 191 | optionsPayload.className += ' open'; 192 | } 193 | }; 194 | 195 | if (specsExecuted < totalSpecsDefined) { 196 | var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; 197 | alert.appendChild( 198 | createDom('span', {className: 'bar skipped'}, 199 | createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) 200 | ) 201 | ); 202 | } 203 | var statusBarMessage = ''; 204 | var statusBarClassName = 'bar '; 205 | 206 | if (totalSpecsDefined > 0) { 207 | statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); 208 | if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } 209 | statusBarClassName += (failureCount > 0) ? 'failed' : 'passed'; 210 | } else { 211 | statusBarClassName += 'skipped'; 212 | statusBarMessage += 'No specs found'; 213 | } 214 | 215 | alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage)); 216 | 217 | for(i = 0; i < failedSuites.length; i++) { 218 | var failedSuite = failedSuites[i]; 219 | for(var j = 0; j < failedSuite.failedExpectations.length; j++) { 220 | var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message; 221 | var errorBarClassName = 'bar errored'; 222 | alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage)); 223 | } 224 | } 225 | 226 | var results = find('.results'); 227 | results.appendChild(summary); 228 | 229 | summaryList(topResults, summary); 230 | 231 | function summaryList(resultsTree, domParent) { 232 | var specListNode; 233 | for (var i = 0; i < resultsTree.children.length; i++) { 234 | var resultNode = resultsTree.children[i]; 235 | if (resultNode.type == 'suite') { 236 | var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id}, 237 | createDom('li', {className: 'suite-detail'}, 238 | createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) 239 | ) 240 | ); 241 | 242 | summaryList(resultNode, suiteListNode); 243 | domParent.appendChild(suiteListNode); 244 | } 245 | if (resultNode.type == 'spec') { 246 | if (domParent.getAttribute('class') != 'specs') { 247 | specListNode = createDom('ul', {className: 'specs'}); 248 | domParent.appendChild(specListNode); 249 | } 250 | var specDescription = resultNode.result.description; 251 | if(noExpectations(resultNode.result)) { 252 | specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; 253 | } 254 | if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') { 255 | specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason; 256 | } 257 | specListNode.appendChild( 258 | createDom('li', { 259 | className: resultNode.result.status, 260 | id: 'spec-' + resultNode.result.id 261 | }, 262 | createDom('a', {href: specHref(resultNode.result)}, specDescription) 263 | ) 264 | ); 265 | } 266 | } 267 | } 268 | 269 | if (failures.length) { 270 | alert.appendChild( 271 | createDom('span', {className: 'menu bar spec-list'}, 272 | createDom('span', {}, 'Spec List | '), 273 | createDom('a', {className: 'failures-menu', href: '#'}, 'Failures'))); 274 | alert.appendChild( 275 | createDom('span', {className: 'menu bar failure-list'}, 276 | createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'), 277 | createDom('span', {}, ' | Failures '))); 278 | 279 | find('.failures-menu').onclick = function() { 280 | setMenuModeTo('failure-list'); 281 | }; 282 | find('.spec-list-menu').onclick = function() { 283 | setMenuModeTo('spec-list'); 284 | }; 285 | 286 | setMenuModeTo('failure-list'); 287 | 288 | var failureNode = find('.failures'); 289 | for (var i = 0; i < failures.length; i++) { 290 | failureNode.appendChild(failures[i]); 291 | } 292 | } 293 | }; 294 | 295 | return this; 296 | 297 | function find(selector) { 298 | return getContainer().querySelector('.jasmine_html-reporter ' + selector); 299 | } 300 | 301 | function clearPrior() { 302 | // return the reporter 303 | var oldReporter = find(''); 304 | 305 | if(oldReporter) { 306 | getContainer().removeChild(oldReporter); 307 | } 308 | } 309 | 310 | function createDom(type, attrs, childrenVarArgs) { 311 | var el = createElement(type); 312 | 313 | for (var i = 2; i < arguments.length; i++) { 314 | var child = arguments[i]; 315 | 316 | if (typeof child === 'string') { 317 | el.appendChild(createTextNode(child)); 318 | } else { 319 | if (child) { 320 | el.appendChild(child); 321 | } 322 | } 323 | } 324 | 325 | for (var attr in attrs) { 326 | if (attr == 'className') { 327 | el[attr] = attrs[attr]; 328 | } else { 329 | el.setAttribute(attr, attrs[attr]); 330 | } 331 | } 332 | 333 | return el; 334 | } 335 | 336 | function pluralize(singular, count) { 337 | var word = (count == 1 ? singular : singular + 's'); 338 | 339 | return '' + count + ' ' + word; 340 | } 341 | 342 | function specHref(result) { 343 | return addToExistingQueryString('spec', result.fullName); 344 | } 345 | 346 | function defaultQueryString(key, value) { 347 | return '?' + key + '=' + value; 348 | } 349 | 350 | function setMenuModeTo(mode) { 351 | htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); 352 | } 353 | 354 | function noExpectations(result) { 355 | return (result.failedExpectations.length + result.passedExpectations.length) === 0 && 356 | result.status === 'passed'; 357 | } 358 | } 359 | 360 | return HtmlReporter; 361 | }; 362 | 363 | jasmineRequire.HtmlSpecFilter = function() { 364 | function HtmlSpecFilter(options) { 365 | var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); 366 | var filterPattern = new RegExp(filterString); 367 | 368 | this.matches = function(specName) { 369 | return filterPattern.test(specName); 370 | }; 371 | } 372 | 373 | return HtmlSpecFilter; 374 | }; 375 | 376 | jasmineRequire.ResultsNode = function() { 377 | function ResultsNode(result, type, parent) { 378 | this.result = result; 379 | this.type = type; 380 | this.parent = parent; 381 | 382 | this.children = []; 383 | 384 | this.addChild = function(result, type) { 385 | this.children.push(new ResultsNode(result, type, this)); 386 | }; 387 | 388 | this.last = function() { 389 | return this.children[this.children.length - 1]; 390 | }; 391 | } 392 | 393 | return ResultsNode; 394 | }; 395 | 396 | jasmineRequire.QueryString = function() { 397 | function QueryString(options) { 398 | 399 | this.navigateWithNewParam = function(key, value) { 400 | options.getWindowLocation().search = this.fullStringWithNewParam(key, value); 401 | }; 402 | 403 | this.fullStringWithNewParam = function(key, value) { 404 | var paramMap = queryStringToParamMap(); 405 | paramMap[key] = value; 406 | return toQueryString(paramMap); 407 | }; 408 | 409 | this.getParam = function(key) { 410 | return queryStringToParamMap()[key]; 411 | }; 412 | 413 | return this; 414 | 415 | function toQueryString(paramMap) { 416 | var qStrPairs = []; 417 | for (var prop in paramMap) { 418 | qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); 419 | } 420 | return '?' + qStrPairs.join('&'); 421 | } 422 | 423 | function queryStringToParamMap() { 424 | var paramStr = options.getWindowLocation().search.substring(1), 425 | params = [], 426 | paramMap = {}; 427 | 428 | if (paramStr.length > 0) { 429 | params = paramStr.split('&'); 430 | for (var i = 0; i < params.length; i++) { 431 | var p = params[i].split('='); 432 | var value = decodeURIComponent(p[1]); 433 | if (value === 'true' || value === 'false') { 434 | value = JSON.parse(value); 435 | } 436 | paramMap[decodeURIComponent(p[0])] = value; 437 | } 438 | } 439 | 440 | return paramMap; 441 | } 442 | 443 | } 444 | 445 | return QueryString; 446 | }; 447 | -------------------------------------------------------------------------------- /spec/jasmine/jasmine.css: -------------------------------------------------------------------------------- 1 | body { overflow-y: scroll; } 2 | 3 | .jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; } 4 | .jasmine_html-reporter a { text-decoration: none; } 5 | .jasmine_html-reporter a:hover { text-decoration: underline; } 6 | .jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } 7 | .jasmine_html-reporter .banner, .jasmine_html-reporter .symbol-summary, .jasmine_html-reporter .summary, .jasmine_html-reporter .result-message, .jasmine_html-reporter .spec .description, .jasmine_html-reporter .spec-detail .description, .jasmine_html-reporter .alert .bar, .jasmine_html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } 8 | .jasmine_html-reporter .banner { position: relative; } 9 | .jasmine_html-reporter .banner .title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } 10 | .jasmine_html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; } 11 | .jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } 12 | .jasmine_html-reporter .version { color: #aaa; } 13 | .jasmine_html-reporter .banner { margin-top: 14px; } 14 | .jasmine_html-reporter .duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; } 15 | .jasmine_html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } 16 | .jasmine_html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } 17 | .jasmine_html-reporter .symbol-summary li.passed { font-size: 14px; } 18 | .jasmine_html-reporter .symbol-summary li.passed:before { color: #007069; content: "\02022"; } 19 | .jasmine_html-reporter .symbol-summary li.failed { line-height: 9px; } 20 | .jasmine_html-reporter .symbol-summary li.failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } 21 | .jasmine_html-reporter .symbol-summary li.disabled { font-size: 14px; } 22 | .jasmine_html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } 23 | .jasmine_html-reporter .symbol-summary li.pending { line-height: 17px; } 24 | .jasmine_html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } 25 | .jasmine_html-reporter .symbol-summary li.empty { font-size: 14px; } 26 | .jasmine_html-reporter .symbol-summary li.empty:before { color: #ba9d37; content: "\02022"; } 27 | .jasmine_html-reporter .run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; } 28 | .jasmine_html-reporter .run-options .trigger { cursor: pointer; padding: 8px 16px; } 29 | .jasmine_html-reporter .run-options .payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } 30 | .jasmine_html-reporter .run-options .payload.open { display: block; } 31 | .jasmine_html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } 32 | .jasmine_html-reporter .bar.failed { background-color: #ca3a11; } 33 | .jasmine_html-reporter .bar.passed { background-color: #007069; } 34 | .jasmine_html-reporter .bar.skipped { background-color: #bababa; } 35 | .jasmine_html-reporter .bar.errored { background-color: #ca3a11; } 36 | .jasmine_html-reporter .bar.menu { background-color: #fff; color: #aaa; } 37 | .jasmine_html-reporter .bar.menu a { color: #333; } 38 | .jasmine_html-reporter .bar a { color: white; } 39 | .jasmine_html-reporter.spec-list .bar.menu.failure-list, .jasmine_html-reporter.spec-list .results .failures { display: none; } 40 | .jasmine_html-reporter.failure-list .bar.menu.spec-list, .jasmine_html-reporter.failure-list .summary { display: none; } 41 | .jasmine_html-reporter .results { margin-top: 14px; } 42 | .jasmine_html-reporter .summary { margin-top: 14px; } 43 | .jasmine_html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } 44 | .jasmine_html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } 45 | .jasmine_html-reporter .summary li.passed a { color: #007069; } 46 | .jasmine_html-reporter .summary li.failed a { color: #ca3a11; } 47 | .jasmine_html-reporter .summary li.empty a { color: #ba9d37; } 48 | .jasmine_html-reporter .summary li.pending a { color: #ba9d37; } 49 | .jasmine_html-reporter .summary li.disabled a { color: #bababa; } 50 | .jasmine_html-reporter .description + .suite { margin-top: 0; } 51 | .jasmine_html-reporter .suite { margin-top: 14px; } 52 | .jasmine_html-reporter .suite a { color: #333; } 53 | .jasmine_html-reporter .failures .spec-detail { margin-bottom: 28px; } 54 | .jasmine_html-reporter .failures .spec-detail .description { background-color: #ca3a11; } 55 | .jasmine_html-reporter .failures .spec-detail .description a { color: white; } 56 | .jasmine_html-reporter .result-message { padding-top: 14px; color: #333; white-space: pre; } 57 | .jasmine_html-reporter .result-message span.result { display: block; } 58 | .jasmine_html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; } 59 | -------------------------------------------------------------------------------- /spec/pixigraphics.spec.js: -------------------------------------------------------------------------------- 1 | // hack for executing code on node.js 2 | if(typeof module !== 'undefined') { 3 | fs = require('fs'); 4 | var code = fs.readFileSync('js/parser/createjs.js', 'utf-8'); 5 | eval(code); 6 | code = fs.readFileSync('js/parser/pixitiny.js', 'utf-8'); 7 | eval(code); 8 | code = fs.readFileSync('js/parser/pixigraphics.js', 'utf-8'); 9 | eval(code); 10 | } 11 | 12 | 13 | // actual test-case 14 | describe("PIXI_graphics Parser Test Suite", function() { 15 | 16 | var pixigraphics = new Pixigraphics(); 17 | 18 | it("testGenerate", function() { 19 | var pathItem = { 20 | "typename" : "PathItem", 21 | "closed" : true, 22 | "filled" : true, 23 | "fillColor" : { 24 | "red" : 0, 25 | "green" : 0, 26 | "blue" : 0, 27 | "typename" : "RGBColor" 28 | }, 29 | "opacity" : 100, 30 | "stroked" : false, 31 | "strokeColor" : { 32 | "cyan" : 0, 33 | "magenta" : 0, 34 | "yellow" : 0, 35 | "black" : 100, 36 | "typename" : "CMYKColor" 37 | }, 38 | "strokeDashes" : [ 39 | 40 | ], 41 | "strokeDashOffset" : 0, 42 | "strokeCap" : {}, 43 | "strokeJoin" : {}, 44 | "strokeMiterLimit" : 10, 45 | "strokeWidth" : 6, 46 | "pathPoints" : [{ 47 | "anchor" : [ 48 | 0, 49 | 0 50 | ], 51 | "leftDirection" : [ 52 | 0, 53 | 0 54 | ], 55 | "rightDirection" : [ 56 | 0, 57 | 0 58 | ] 59 | }, { 60 | "anchor" : [ 61 | 10, 62 | 0 63 | ], 64 | "leftDirection" : [ 65 | 10, 66 | 0 67 | ], 68 | "rightDirection" : [ 69 | 10, 70 | 0 71 | ] 72 | }, { 73 | "anchor" : [ 74 | 10, 75 | 10 76 | ], 77 | "leftDirection" : [ 78 | 10, 79 | 10 80 | ], 81 | "rightDirection" : [ 82 | 10, 83 | 10 84 | ] 85 | }, { 86 | "anchor" : [ 87 | 0, 88 | 10 89 | ], 90 | "leftDirection" : [ 91 | 0, 92 | 10 93 | ], 94 | "rightDirection" : [ 95 | 0, 96 | 10 97 | ] 98 | } 99 | ] 100 | }; 101 | 102 | var groupItem = { 103 | "typename": "GroupItem", 104 | "groupItems": [], 105 | "pathItems": [pathItem], 106 | "compoundPathItems": [] 107 | }; 108 | 109 | var json = { 110 | "cropBox" : [0,0], 111 | "selection" : [groupItem] 112 | } 113 | 114 | pixigraphics.cropBox = json.cropBox; 115 | 116 | var expectedData = [{cmd : "f", args: "0x000000"},{ 117 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}, 118 | {cmd: "ef", args: ""}]; 119 | var expectedResult = { 120 | type : "graphics", 121 | data : expectedData 122 | }; 123 | this.cropBox = json.cropBox; 124 | var result = pixigraphics.generate(json); 125 | 126 | expect(result).toBe(JSON.stringify(expectedResult, null, 2)); 127 | }); 128 | 129 | it("testMakeDataItem", function() { 130 | var cmd = "p"; 131 | var args = "0x000000"; 132 | 133 | var expectedResult = { 134 | cmd: "p", 135 | args: "0x000000" 136 | } 137 | expect(JSON.stringify(pixigraphics.makeDataItem(cmd,args))).toBe(JSON.stringify(expectedResult)); 138 | }); 139 | 140 | it("testParsePathItem", function() { 141 | pixigraphics.cropBox = [0,0]; 142 | var pathItem = { 143 | "typename" : "PathItem", 144 | "closed" : true, 145 | "filled" : false, 146 | "fillColor" : { 147 | "gray" : 0, 148 | "typename" : "GrayColor" 149 | }, 150 | "opacity" : 100, 151 | "stroked" : true, 152 | "strokeColor" : { 153 | "cyan" : 0, 154 | "magenta" : 0, 155 | "yellow" : 0, 156 | "black" : 100, 157 | "typename" : "CMYKColor" 158 | }, 159 | "strokeDashes" : [ 160 | 161 | ], 162 | "strokeDashOffset" : 0, 163 | "strokeCap" : {}, 164 | "strokeJoin" : {}, 165 | "strokeMiterLimit" : 10, 166 | "strokeWidth" : 6, 167 | "pathPoints" : [{ 168 | "anchor" : [ 169 | 0, 170 | 0 171 | ], 172 | "leftDirection" : [ 173 | 0, 174 | 0 175 | ], 176 | "rightDirection" : [ 177 | 0, 178 | 0 179 | ] 180 | }, { 181 | "anchor" : [ 182 | 10, 183 | 0 184 | ], 185 | "leftDirection" : [ 186 | 10, 187 | 0 188 | ], 189 | "rightDirection" : [ 190 | 10, 191 | 0 192 | ] 193 | }, { 194 | "anchor" : [ 195 | 10, 196 | 10 197 | ], 198 | "leftDirection" : [ 199 | 10, 200 | 10 201 | ], 202 | "rightDirection" : [ 203 | 10, 204 | 10 205 | ] 206 | }, { 207 | "anchor" : [ 208 | 0, 209 | 10 210 | ], 211 | "leftDirection" : [ 212 | 0, 213 | 10 214 | ], 215 | "rightDirection" : [ 216 | 0, 217 | 10 218 | ] 219 | } 220 | ] 221 | }; 222 | 223 | var expectedResult = [{cmd: "ss", args:6},{cmd: "s", args :"0x000000"},{ 224 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}]; 225 | var result = pixigraphics.parsePathItem(pathItem); 226 | 227 | for(var i = 0; i < expectedResult.length; i++) { 228 | expect(result[i].cmd).toBe(expectedResult[i].cmd); 229 | expect(result[i].args).toBe(expectedResult[i].args); 230 | } 231 | 232 | pathItem = { 233 | "typename" : "PathItem", 234 | "closed" : true, 235 | "filled" : false, 236 | "fillColor" : { 237 | "gray" : 0, 238 | "typename" : "GrayColor" 239 | }, 240 | "opacity" : 100, 241 | "stroked" : false, 242 | "strokeColor" : { 243 | "cyan" : 0, 244 | "magenta" : 0, 245 | "yellow" : 0, 246 | "black" : 100, 247 | "typename" : "CMYKColor" 248 | }, 249 | "strokeDashes" : [ 250 | 251 | ], 252 | "strokeDashOffset" : 0, 253 | "strokeCap" : {}, 254 | "strokeJoin" : {}, 255 | "strokeMiterLimit" : 10, 256 | "strokeWidth" : 6, 257 | "pathPoints" : [{ 258 | "anchor" : [ 259 | 0, 260 | 0 261 | ], 262 | "leftDirection" : [ 263 | 0, 264 | 0 265 | ], 266 | "rightDirection" : [ 267 | 0, 268 | 0 269 | ] 270 | }, { 271 | "anchor" : [ 272 | 10, 273 | 0 274 | ], 275 | "leftDirection" : [ 276 | 10, 277 | 0 278 | ], 279 | "rightDirection" : [ 280 | 10, 281 | 0 282 | ] 283 | }, { 284 | "anchor" : [ 285 | 10, 286 | 10 287 | ], 288 | "leftDirection" : [ 289 | 10, 290 | 10 291 | ], 292 | "rightDirection" : [ 293 | 10, 294 | 10 295 | ] 296 | }, { 297 | "anchor" : [ 298 | 0, 299 | 10 300 | ], 301 | "leftDirection" : [ 302 | 0, 303 | 10 304 | ], 305 | "rightDirection" : [ 306 | 0, 307 | 10 308 | ] 309 | } 310 | ] 311 | }; 312 | 313 | expectedResult = [{ 314 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}]; 315 | result = pixigraphics.parsePathItem(pathItem); 316 | 317 | for(var i = 0; i < expectedResult.length; i++) { 318 | expect(result[i].cmd).toBe(expectedResult[i].cmd); 319 | expect(result[i].args).toBe(expectedResult[i].args); 320 | } 321 | 322 | pathItem = { 323 | "typename" : "PathItem", 324 | "closed" : true, 325 | "filled" : true, 326 | "fillColor" : { 327 | "red" : 0, 328 | "green" : 0, 329 | "blue" : 0, 330 | "typename" : "RGBColor" 331 | }, 332 | "opacity" : 100, 333 | "stroked" : false, 334 | "strokeColor" : { 335 | "cyan" : 0, 336 | "magenta" : 0, 337 | "yellow" : 0, 338 | "black" : 100, 339 | "typename" : "CMYKColor" 340 | }, 341 | "strokeDashes" : [ 342 | 343 | ], 344 | "strokeDashOffset" : 0, 345 | "strokeCap" : {}, 346 | "strokeJoin" : {}, 347 | "strokeMiterLimit" : 10, 348 | "strokeWidth" : 6, 349 | "pathPoints" : [{ 350 | "anchor" : [ 351 | 0, 352 | 0 353 | ], 354 | "leftDirection" : [ 355 | 0, 356 | 0 357 | ], 358 | "rightDirection" : [ 359 | 0, 360 | 0 361 | ] 362 | }, { 363 | "anchor" : [ 364 | 10, 365 | 0 366 | ], 367 | "leftDirection" : [ 368 | 10, 369 | 0 370 | ], 371 | "rightDirection" : [ 372 | 10, 373 | 0 374 | ] 375 | }, { 376 | "anchor" : [ 377 | 10, 378 | 10 379 | ], 380 | "leftDirection" : [ 381 | 10, 382 | 10 383 | ], 384 | "rightDirection" : [ 385 | 10, 386 | 10 387 | ] 388 | }, { 389 | "anchor" : [ 390 | 0, 391 | 10 392 | ], 393 | "leftDirection" : [ 394 | 0, 395 | 10 396 | ], 397 | "rightDirection" : [ 398 | 0, 399 | 10 400 | ] 401 | } 402 | ] 403 | }; 404 | 405 | expectedResult = [{cmd : "f", args: "0x000000"},{ 406 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}, 407 | {cmd: "ef", args: ""}]; 408 | result = pixigraphics.parsePathItem(pathItem); 409 | 410 | for(var i = 0; i < result.length; i++) { 411 | expect(result[i].cmd).toBe(expectedResult[i].cmd); 412 | expect(result[i].args).toBe(expectedResult[i].args); 413 | } 414 | }); 415 | 416 | it("testParseGroupItem", function() { 417 | pixigraphics.cropBox = [0,0]; 418 | var groupItem = { 419 | "typename": "GroupItem", 420 | "groupItems": [], 421 | "pathItems": [], 422 | "compoundPathItems": [] 423 | } 424 | var result = pixigraphics.parseGroupItem(groupItem); 425 | var expectedResult = []; 426 | for(var i = 0; i < result.length; i++) { 427 | expect(result[i]).toBe(expectedResult[i]); 428 | } 429 | 430 | pathItem = { 431 | "typename" : "PathItem", 432 | "closed" : true, 433 | "filled" : true, 434 | "fillColor" : { 435 | "red" : 0, 436 | "green" : 0, 437 | "blue" : 0, 438 | "typename" : "RGBColor" 439 | }, 440 | "opacity" : 100, 441 | "stroked" : false, 442 | "strokeColor" : { 443 | "cyan" : 0, 444 | "magenta" : 0, 445 | "yellow" : 0, 446 | "black" : 100, 447 | "typename" : "CMYKColor" 448 | }, 449 | "strokeDashes" : [ 450 | 451 | ], 452 | "strokeDashOffset" : 0, 453 | "strokeCap" : {}, 454 | "strokeJoin" : {}, 455 | "strokeMiterLimit" : 10, 456 | "strokeWidth" : 6, 457 | "pathPoints" : [{ 458 | "anchor" : [ 459 | 0, 460 | 0 461 | ], 462 | "leftDirection" : [ 463 | 0, 464 | 0 465 | ], 466 | "rightDirection" : [ 467 | 0, 468 | 0 469 | ] 470 | }, { 471 | "anchor" : [ 472 | 10, 473 | 0 474 | ], 475 | "leftDirection" : [ 476 | 10, 477 | 0 478 | ], 479 | "rightDirection" : [ 480 | 10, 481 | 0 482 | ] 483 | }, { 484 | "anchor" : [ 485 | 10, 486 | 10 487 | ], 488 | "leftDirection" : [ 489 | 10, 490 | 10 491 | ], 492 | "rightDirection" : [ 493 | 10, 494 | 10 495 | ] 496 | }, { 497 | "anchor" : [ 498 | 0, 499 | 10 500 | ], 501 | "leftDirection" : [ 502 | 0, 503 | 10 504 | ], 505 | "rightDirection" : [ 506 | 0, 507 | 10 508 | ] 509 | } 510 | ] 511 | }; 512 | 513 | groupItem = { 514 | "typename": "GroupItem", 515 | "groupItems": [], 516 | "pathItems": [pathItem,pathItem], 517 | "compoundPathItems": [] 518 | }; 519 | expectedResult = [{cmd : "f", args: "0x000000"},{ 520 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}, 521 | {cmd: "ef", args: ""},{cmd : "f", args: "0x000000"},{ 522 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}, 523 | {cmd: "ef", args: ""}]; 524 | 525 | result = pixigraphics.parseGroupItem(groupItem); 526 | 527 | for(var i = 0; i < result.length; i++) { 528 | expect(result[i].cmd).toBe(expectedResult[i].cmd); 529 | expect(result[i].args).toBe(expectedResult[i].args); 530 | } 531 | 532 | groupItem2 = { 533 | "typename": "GroupItem", 534 | "groupItems": [groupItem], 535 | "pathItems": [pathItem], 536 | "compoundPathItems": [] 537 | }; 538 | 539 | expectedResult = [{cmd : "f", args: "0x000000"},{ 540 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}, 541 | {cmd: "ef", args: ""},{cmd : "f", args: "0x000000"},{ 542 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}, 543 | {cmd: "ef", args: ""},{cmd : "f", args: "0x000000"},{ 544 | cmd: "p", args: pixigraphics.convertPathItemToPathInstruction(pathItem)}, 545 | {cmd: "ef", args: ""}]; 546 | 547 | result = pixigraphics.parseGroupItem(groupItem); 548 | 549 | for(var i = 0; i < result.length; i++) { 550 | expect(result[i].cmd).toBe(expectedResult[i].cmd); 551 | expect(result[i].args).toBe(expectedResult[i].args); 552 | } 553 | 554 | 555 | }); 556 | }); -------------------------------------------------------------------------------- /spec/pixitiny.spec.js: -------------------------------------------------------------------------------- 1 | // hack for executing code on node.js 2 | if(typeof module !== 'undefined') { 3 | fs = require('fs'); 4 | var code = fs.readFileSync('js/parser/createjs.js', 'utf-8'); 5 | eval(code); 6 | code = fs.readFileSync('js/parser/pixitiny.js', 'utf-8'); 7 | eval(code); 8 | } 9 | 10 | 11 | // actual test-case 12 | describe("PIXI_tiny Parser Test Suite", function() { 13 | 14 | var pixitiny = new Pixitiny(); 15 | 16 | it("testParsePathItem", function () { 17 | pixitiny.cropBox = [0,0]; 18 | var pathItem = { 19 | "typename" : "PathItem", 20 | "closed" : true, 21 | "filled" : false, 22 | "fillColor" : { 23 | "gray" : 0, 24 | "typename" : "GrayColor" 25 | }, 26 | "opacity" : 100, 27 | "stroked" : true, 28 | "strokeColor" : { 29 | "cyan" : 0, 30 | "magenta" : 0, 31 | "yellow" : 0, 32 | "black" : 100, 33 | "typename" : "CMYKColor" 34 | }, 35 | "strokeDashes" : [ 36 | 37 | ], 38 | "strokeDashOffset" : 0, 39 | "strokeCap" : {}, 40 | "strokeJoin" : {}, 41 | "strokeMiterLimit" : 10, 42 | "strokeWidth" : 6, 43 | "pathPoints" : [{ 44 | "anchor" : [ 45 | 0, 46 | 0 47 | ], 48 | "leftDirection" : [ 49 | 0, 50 | 0 51 | ], 52 | "rightDirection" : [ 53 | 0, 54 | 0 55 | ] 56 | }, { 57 | "anchor" : [ 58 | 10, 59 | 0 60 | ], 61 | "leftDirection" : [ 62 | 10, 63 | 0 64 | ], 65 | "rightDirection" : [ 66 | 10, 67 | 0 68 | ] 69 | }, { 70 | "anchor" : [ 71 | 10, 72 | 10 73 | ], 74 | "leftDirection" : [ 75 | 10, 76 | 10 77 | ], 78 | "rightDirection" : [ 79 | 10, 80 | 10 81 | ] 82 | }, { 83 | "anchor" : [ 84 | 0, 85 | 10 86 | ], 87 | "leftDirection" : [ 88 | 0, 89 | 10 90 | ], 91 | "rightDirection" : [ 92 | 0, 93 | 10 94 | ] 95 | } 96 | ] 97 | } 98 | 99 | expect(pixitiny.parsePathItem(pathItem)).toBe(".ss(6).s(0x000000).p('" + 100 | pixitiny.convertPathItemToPathInstruction(pathItem) +"').es()"); 101 | }); 102 | 103 | it("testGetColor", function () { 104 | var testColor = { 105 | typename: 'RGBColor', 106 | red: '0', 107 | green: '0', 108 | blue: '0' 109 | }; 110 | 111 | var testOpactiy = 100; 112 | expect(pixitiny.getColor(testColor, testOpactiy)).toBe("0x000000"); 113 | 114 | testColor = { 115 | typename: 'RGBColor', 116 | red: '255', 117 | green: '255', 118 | blue: '255' 119 | }; 120 | expect(pixitiny.getColor(testColor, testOpactiy)).toBe("0xffffff"); 121 | 122 | testColor = { 123 | typename: 'CMYKColor', 124 | cyan: '0', 125 | black: '100', 126 | magenta: '0', 127 | yellow: '0' 128 | } 129 | expect(pixitiny.getColor(testColor, testOpactiy)).toBe("0x000000"); 130 | }); 131 | 132 | it("testConvertToHex", function() { 133 | var number = [0,0.2,0.4,0.6,0.8,10.0,100.0,200000.0,-0.1,-2.0]; 134 | var bits12 = ["000000000000","000000000010","000000000100","000000000110","000000001000", 135 | "000001100100","001111101000","overflow","100000000001","100000010100"]; 136 | var bits18 = ["000000000000000000","000000000000000010","000000000000000100", 137 | "000000000000000110","000000000000001000","000000000001100100", 138 | "000000001111101000","overflow","100000000000000001","100000000000010100"]; 139 | for(var i = 0; i < number.length; i++) { 140 | expect(pixitiny.convertNumberToBits(number[i],12)).toBe(bits12[i]); 141 | expect(pixitiny.convertNumberToBits(number[i],18)).toBe(bits18[i]); 142 | } 143 | }); 144 | 145 | }); -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": "spec", 3 | "spec_files": [ 4 | "**/*[sS]pec.js" 5 | ], 6 | "helpers": [ 7 | "helpers/**/*.js", 8 | "../host/draw2script.jsx" 9 | ] 10 | } 11 | --------------------------------------------------------------------------------