├── .gitignore
├── mandelbrot-tiled
├── Makefile
├── index.html
└── mandelbrot.cpp
├── mandelbrot-simple
├── Makefile
├── index.html
└── mandelbrot.cpp
├── lyff
├── solution
│ ├── build.sh
│ └── index.html
└── lyff.c
├── CONTRIBUTING.md
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | output.*
3 |
--------------------------------------------------------------------------------
/mandelbrot-tiled/Makefile:
--------------------------------------------------------------------------------
1 | export EMCC_DEBUG=1
2 |
3 | mandelbrot.js: mandelbrot.cpp
4 | em++ --bind --std=c++11 mandelbrot.cpp -s WASM=1 -o mandelbrot.js
5 |
6 | clean:
7 | rm *.js *.wasm
--------------------------------------------------------------------------------
/mandelbrot-simple/Makefile:
--------------------------------------------------------------------------------
1 | export EMCC_DEBUG=1
2 |
3 | mandelbrot.js: mandelbrot.cpp
4 | em++ --bind --std=c++11 mandelbrot.cpp -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -o mandelbrot.js
5 |
6 | clean:
7 | rm *.js *.wasm
--------------------------------------------------------------------------------
/lyff/solution/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # nb. this differs from the codelab, as we compile code from the parent folder
4 | emcc \
5 | -o output.js ../*.c \
6 | -s WASM=1 -s ONLY_MY_CODE=1 -s EXPORTED_FUNCTIONS="['_board_step','_board_init','_board_ref']"
7 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
--------------------------------------------------------------------------------
/mandelbrot-simple/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
20 |
21 |
22 |
23 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/mandelbrot-tiled/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
20 |
21 |
22 |
23 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/lyff/solution/index.html:
--------------------------------------------------------------------------------
1 |
68 |
74 |
75 |
77 |
--------------------------------------------------------------------------------
/lyff/lyff.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | typedef unsigned char byte;
18 |
19 | #define DIM 100
20 | #define SIZE ((DIM + 2) * (DIM + 2) / 8) // byte size
21 |
22 | static byte boardA[SIZE], boardB[SIZE];
23 | static byte *board = (byte *) &boardA;
24 |
25 | // Gets the cell on the default board.
26 | byte get_cell(int x, int y) {
27 | int pos = (y * (DIM + 2)) + x;
28 | int i = pos / 8;
29 | byte off = 1 << (pos % 8);
30 | return board[i] & off;
31 | }
32 |
33 | // Sets a cell on a board.
34 | void set_cell_ref(byte *b, int x, int y) {
35 | int pos = (y * (DIM + 2)) + x;
36 | int i = pos / 8;
37 | byte off = 1 << (pos % 8);
38 | b[i] |= off;
39 | }
40 |
41 | // Clears a board.
42 | void clear_board_ref(byte *b) {
43 | for (int i = 0; i < SIZE; ++i) {
44 | b[i] = 0;
45 | }
46 | }
47 |
48 | // Steps through one iteration of Conway's Game of Life. Returns the number of now alive cells, or
49 | // -1 if no cells changed this iteration: i.e., stable game.
50 | int board_step() {
51 | int total_alive = 0;
52 | int change = 0;
53 |
54 | // place output in A/B board
55 | byte *next = (byte *) &boardA;
56 | if (board == next) {
57 | next = (byte *) &boardB;
58 | }
59 | clear_board_ref(next);
60 |
61 | for (int x = 1; x <= DIM; ++x) {
62 | for (int y = 1; y <= DIM; ++y) {
63 | byte alive = get_cell(x, y);
64 | byte out = 0;
65 |
66 | int count = 0;
67 | for (int off = 0; off < 9; ++off) {
68 | if (off == 4) { continue; } // this is 'us'
69 |
70 | int dx = (off % 3) - 1;
71 | int dy = (off / 3) - 1;
72 |
73 | if (!get_cell(x + dx, y + dy)) { continue; }
74 | if (++count > 3) { break; }
75 | }
76 |
77 | if (count == 3 || (count == 2 && alive)) {
78 | out = 1;
79 | }
80 | if (out) {
81 | set_cell_ref(next, x, y); // TODO: hold onto index, pass around?
82 | ++total_alive;
83 | }
84 | if (out != alive) {
85 | ++change;
86 | }
87 | }
88 | }
89 |
90 | board = next;
91 | if (change == 0) {
92 | return -1; // we're stable
93 | }
94 | return total_alive;
95 | }
96 |
97 | // Count the total number of alive cells.
98 | int board_count() {
99 | int count = 0;
100 | for (int i = 0; i < SIZE; ++i) {
101 | byte v = board[i];
102 | while (v) {
103 | count += v & 1;
104 | v >>= 1;
105 | }
106 | }
107 | return count;
108 | }
109 |
110 | // Returns the pointer location of the rendered board.
111 | byte *board_ref() {
112 | return board;
113 | }
114 |
115 | // Clears the board.
116 | void board_init() {
117 | clear_board_ref(board);
118 |
119 | // TODO: dummy board setup
120 | board[85] = 255;
121 | board[120] = 255;
122 | board[132] = 255;
123 | board[800] = 255;
124 | board[720] = 254;
125 | board[700] = 255;
126 | board[600] = 255;
127 | board[601] = 255;
128 | board[602] = 255;
129 | board[603] = 255;
130 | board[604] = 255;
131 | board[605] = 255;
132 | board[606] = 255;
133 | }
134 |
135 |
--------------------------------------------------------------------------------
/mandelbrot-simple/mandelbrot.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google Inc. All rights reserved.
3 | *
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6 | * file except in compliance with the License. You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software distributed under
11 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12 | * ANY KIND, either express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | // CSV to RGB conversion from http://stackoverflow.com/questions/3018313/
21 | typedef struct
22 | {
23 | double r; // a fraction between 0 and 1
24 | double g; // a fraction between 0 and 1
25 | double b; // a fraction between 0 and 1
26 | } rgb;
27 |
28 | typedef struct
29 | {
30 | double h; // angle in degrees
31 | double s; // a fraction between 0 and 1
32 | double v; // a fraction between 0 and 1
33 | } hsv;
34 |
35 | static rgb hsv2rgb(hsv in);
36 |
37 | rgb hsv2rgb(hsv in)
38 | {
39 | double hh, p, q, t, ff;
40 | long i;
41 | rgb out;
42 |
43 | if (in.s <= 0.0)
44 | { // < is bogus, just shuts up warnings
45 | out.r = in.v;
46 | out.g = in.v;
47 | out.b = in.v;
48 | return out;
49 | }
50 | hh = in.h;
51 | if (hh >= 360.0)
52 | hh = 0.0;
53 | hh /= 60.0;
54 | i = (long)hh;
55 | ff = hh - i;
56 | p = in.v * (1.0 - in.s);
57 | q = in.v * (1.0 - (in.s * ff));
58 | t = in.v * (1.0 - (in.s * (1.0 - ff)));
59 |
60 | switch (i)
61 | {
62 | case 0:
63 | out.r = in.v;
64 | out.g = t;
65 | out.b = p;
66 | break;
67 | case 1:
68 | out.r = q;
69 | out.g = in.v;
70 | out.b = p;
71 | break;
72 | case 2:
73 | out.r = p;
74 | out.g = in.v;
75 | out.b = t;
76 | break;
77 |
78 | case 3:
79 | out.r = p;
80 | out.g = q;
81 | out.b = in.v;
82 | break;
83 | case 4:
84 | out.r = t;
85 | out.g = p;
86 | out.b = in.v;
87 | break;
88 | case 5:
89 | default:
90 | out.r = in.v;
91 | out.g = p;
92 | out.b = q;
93 | break;
94 | }
95 | return out;
96 | }
97 |
98 | uint8_t *buffer = nullptr;
99 | size_t bufferSize = 0;
100 |
101 | // Mandlebrot definition from http://lodev.org/cgtutor/juliamandelbrot.html
102 |
103 | emscripten::val mandelbrot(int w, int h, double zoom, double moveX, double moveY)
104 | {
105 | if (buffer != nullptr)
106 | {
107 | free(buffer);
108 | }
109 |
110 | // The image format that imageData expects is four unsigned bytes: red, green, blue, alpha
111 | bufferSize = w * h * 4;
112 | buffer = (uint8_t *)malloc(bufferSize);
113 | if (buffer == nullptr)
114 | {
115 | // Following the JavaScript idiom that undefined is error
116 | return emscripten::val::undefined();
117 | }
118 |
119 | // each iteration, it calculates: newz = oldz*oldz + p, where p is the current pixel, and oldz stars at the origin
120 | double pr, pi; // real and imaginary part of the pixel p
121 | double newRe, newIm, oldRe, oldIm; // real and imaginary parts of new and old z
122 | rgb color; // the RGB color value for the pixel
123 | int maxIterations = 360; // after how much iterations the function should stop. Chosen to make take up full HSV hue range.
124 |
125 | // loop through every pixel
126 | for (int y = 0; y < h; y++)
127 | for (int x = 0; x < w; x++)
128 | {
129 | // calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
130 | pr = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
131 | pi = (y - h / 2) / (0.5 * zoom * h) + moveY;
132 | newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
133 | // "i" will represent the number of iterations
134 | int i;
135 | // start the iteration process
136 | for (i = 0; i < maxIterations; i++)
137 | {
138 | // remember value of previous iteration
139 | oldRe = newRe;
140 | oldIm = newIm;
141 | // the actual iteration, the real and imaginary part are calculated
142 | newRe = oldRe * oldRe - oldIm * oldIm + pr;
143 | newIm = 2 * oldRe * oldIm + pi;
144 | // if the point is outside the circle with radius 2: stop
145 | if ((newRe * newRe + newIm * newIm) > 4)
146 | break;
147 | }
148 | // use color model conversion to get rainbow palette, make brightness black if maxIterations reached
149 | hsv hsvColor;
150 | hsvColor.h = i;
151 | hsvColor.s = 1; // fully saturated.
152 | hsvColor.v = i < maxIterations;
153 | color = hsv2rgb(hsvColor);
154 | //draw the pixel
155 | size_t bufferOffset = (x + y * w) * 4;
156 | buffer[bufferOffset + 0] = color.r * 255;
157 | buffer[bufferOffset + 1] = color.g * 255;
158 | buffer[bufferOffset + 2] = color.b * 255;
159 | buffer[bufferOffset + 3] = 255;
160 | }
161 |
162 | return emscripten::val(emscripten::typed_memory_view(bufferSize, buffer));
163 | }
164 |
165 | EMSCRIPTEN_BINDINGS(hello)
166 | {
167 | emscripten::function("mandelbrot", &mandelbrot);
168 | }
169 |
--------------------------------------------------------------------------------
/mandelbrot-tiled/mandelbrot.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Google Inc. All rights reserved.
3 | *
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6 | * file except in compliance with the License. You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software distributed under
11 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12 | * ANY KIND, either express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | // CSV to RGB conversion from http://stackoverflow.com/questions/3018313/
21 | typedef struct {
22 | double r; // a fraction between 0 and 1
23 | double g; // a fraction between 0 and 1
24 | double b; // a fraction between 0 and 1
25 | } rgb;
26 |
27 | typedef struct {
28 | double h; // angle in degrees
29 | double s; // a fraction between 0 and 1
30 | double v; // a fraction between 0 and 1
31 | } hsv;
32 |
33 | static rgb hsv2rgb(hsv in);
34 |
35 | rgb hsv2rgb(hsv in) {
36 | double hh, p, q, t, ff;
37 | long i;
38 | rgb out;
39 |
40 | if (in.s <= 0.0) { // < is bogus, just shuts up warnings
41 | out.r = in.v;
42 | out.g = in.v;
43 | out.b = in.v;
44 | return out;
45 | }
46 | hh = in.h;
47 | if (hh >= 360.0)
48 | hh = 0.0;
49 | hh /= 60.0;
50 | i = (long)hh;
51 | ff = hh - i;
52 | p = in.v * (1.0 - in.s);
53 | q = in.v * (1.0 - (in.s * ff));
54 | t = in.v * (1.0 - (in.s * (1.0 - ff)));
55 |
56 | switch (i) {
57 | case 0:
58 | out.r = in.v;
59 | out.g = t;
60 | out.b = p;
61 | break;
62 | case 1:
63 | out.r = q;
64 | out.g = in.v;
65 | out.b = p;
66 | break;
67 | case 2:
68 | out.r = p;
69 | out.g = in.v;
70 | out.b = t;
71 | break;
72 |
73 | case 3:
74 | out.r = p;
75 | out.g = q;
76 | out.b = in.v;
77 | break;
78 | case 4:
79 | out.r = t;
80 | out.g = p;
81 | out.b = in.v;
82 | break;
83 | case 5:
84 | default:
85 | out.r = in.v;
86 | out.g = p;
87 | out.b = q;
88 | break;
89 | }
90 | return out;
91 | }
92 |
93 | const int TILE_SIZE = 64;
94 |
95 | class Mandelbrot {
96 | private:
97 | int width;
98 | int height;
99 | double zoom;
100 | double moveX;
101 | double moveY;
102 |
103 | // generate mandelbrot image in tiles
104 | int currentTileX = 0;
105 | int currentTileY = 0;
106 |
107 | // The image buffer handed back to JS for rendering into canvas
108 | // The image format that imageData expects is four unsigned bytes: red,
109 | // green, blue, alpha
110 | uint8_t buffer[TILE_SIZE * TILE_SIZE * 4];
111 |
112 | public:
113 | Mandelbrot(int width, int height, double zoom, double moveX, double moveY)
114 | : width(width), height(height), zoom(zoom), moveX(moveX), moveY(moveY) {}
115 |
116 | // Mandlebrot definition adapted from
117 | // http://lodev.org/cgtutor/juliamandelbrot.html
118 |
119 | emscripten::val nextTile() {
120 | if (this->currentTileY * TILE_SIZE > this->height) {
121 | // If we have generated all of the tiles, return undefined
122 | // so that the JS will stop calling us.
123 | return emscripten::val::undefined();
124 | }
125 |
126 | // each iteration, it calculates: newz = oldz*oldz + p, where p is the
127 | // current pixel, and oldz stars at the origin
128 |
129 | // real and imaginary part of the pixel p
130 | double pr, pi;
131 | // real and imaginary parts of new and old z
132 | double newRe, newIm, oldRe, oldIm;
133 | // the RGB color value for the pixel
134 | rgb color;
135 | // after how much iterations the function should stop.
136 | int maxIterations = 180;
137 |
138 | // Generate a TILE_SIZE x TILE_SIZE array of pixels
139 | for (int y = this->currentTileY * TILE_SIZE;
140 | y < (this->currentTileY + 1) * TILE_SIZE; y++) {
141 | for (int x = this->currentTileX * TILE_SIZE;
142 | x < (this->currentTileX + 1) * TILE_SIZE; x++) {
143 | // calculate the initial real and imaginary part of z, based on the
144 | // pixel location and zoom and position values
145 | pr = 1.5 * (x - this->width / 2) / (0.5 * this->zoom * this->width) +
146 | this->moveX;
147 | pi = (y - this->height / 2) / (0.5 * this->zoom * this->height) +
148 | this->moveY;
149 | newRe = newIm = oldRe = oldIm = 0; // these should start at 0,0
150 | // "i" will represent the number of iterations
151 | int i;
152 | // start the iteration process
153 | for (i = 0; i < maxIterations; i++) {
154 | // remember value of previous iteration
155 | oldRe = newRe;
156 | oldIm = newIm;
157 | // the actual iteration, the real and imaginary part are calculated
158 | newRe = oldRe * oldRe - oldIm * oldIm + pr;
159 | newIm = 2 * oldRe * oldIm + pi;
160 | // if the point is outside the circle with radius 2: stop
161 | if ((newRe * newRe + newIm * newIm) > 4)
162 | break;
163 | }
164 | // use color model conversion to get rainbow palette, make brightness
165 | // black if maxIterations reached
166 | hsv hsvColor;
167 | hsvColor.h = i * 2;
168 | hsvColor.s = 1; // fully saturated.
169 | hsvColor.v = i < maxIterations;
170 | color = hsv2rgb(hsvColor);
171 | // draw the pixel
172 | size_t bufferOffset =
173 | ((x - this->currentTileX * TILE_SIZE) +
174 | (y - this->currentTileY * TILE_SIZE) * TILE_SIZE) *
175 | 4;
176 | this->buffer[bufferOffset + 0] = color.r * 255;
177 | this->buffer[bufferOffset + 1] = color.g * 255;
178 | this->buffer[bufferOffset + 2] = color.b * 255;
179 | this->buffer[bufferOffset + 3] = 255;
180 | }
181 | }
182 |
183 | emscripten::val returnVal = emscripten::val::object();
184 | returnVal.set("data", emscripten::val(emscripten::typed_memory_view(
185 | TILE_SIZE * TILE_SIZE * 4, this->buffer)));
186 | returnVal.set("width", emscripten::val(TILE_SIZE));
187 | returnVal.set("height", emscripten::val(TILE_SIZE));
188 | returnVal.set("x", emscripten::val(this->currentTileX * TILE_SIZE));
189 | returnVal.set("y", emscripten::val(this->currentTileY * TILE_SIZE));
190 |
191 | // Increment to the next tile
192 | this->currentTileX++;
193 | if (this->currentTileX * TILE_SIZE > this->width) {
194 | this->currentTileX = 0;
195 | this->currentTileY++;
196 | }
197 |
198 | return returnVal;
199 | }
200 | };
201 |
202 | EMSCRIPTEN_BINDINGS(hello) {
203 | emscripten::class_("Mandelbrot")
204 | .constructor()
205 | .function("nextTile", &Mandelbrot::nextTile);
206 | }
207 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------