|
2 | 2 | * Gradient
|
3 | 3 | * class to create linear/radial/elliptical/conic gradients as bitmaps even without canvas
|
4 | 4 | *
|
5 |
| -* @version 1.2.3 |
| 5 | +* @version 1.2.4 |
6 | 6 | * https://github.com/foo123/Gradient
|
7 | 7 | *
|
8 | 8 | **/
|
@@ -89,7 +89,7 @@ function Gradient(grad_color_at)
|
89 | 89 | return bmp;
|
90 | 90 | };
|
91 | 91 | }
|
92 |
| -Gradient.VERSION = "1.2.3"; |
| 92 | +Gradient.VERSION = "1.2.4"; |
93 | 93 | Gradient.prototype = {
|
94 | 94 | constructor: Gradient,
|
95 | 95 | transform: null,
|
@@ -303,69 +303,306 @@ Pattern.prototype = {
|
303 | 303 | Pattern.createPattern = function(imageData, repetition) {
|
304 | 304 | if (imageData && imageData.data && imageData.width && imageData.height && (imageData.data.length === 4*imageData.width*imageData.height))
|
305 | 305 | {
|
306 |
| - var width = imageData.width, height = imageData.height; |
| 306 | + var width = imageData.width, |
| 307 | + height = imageData.height, |
| 308 | + z = [0, 0, 0, 0], |
| 309 | + pt = function(x, y) { |
| 310 | + if (0 <= x && 0 <= y && x < width && y < height) |
| 311 | + { |
| 312 | + var index = (x + width*y) << 2; |
| 313 | + return [ |
| 314 | + imageData.data[index ], |
| 315 | + imageData.data[index+1], |
| 316 | + imageData.data[index+2], |
| 317 | + imageData.data[index+3] |
| 318 | + ]; |
| 319 | + } |
| 320 | + return z; |
| 321 | + } |
| 322 | + ; |
307 | 323 | switch (repetition)
|
308 | 324 | {
|
309 | 325 | case 'no-repeat':
|
310 | 326 | return new Pattern(function(x, y, pixel, i) {
|
311 |
| - x = stdMath.round(x); |
312 |
| - y = stdMath.round(y); |
313 |
| - if (0 <= x && x < width && 0 <= y && y < height) |
| 327 | + //x = stdMath.round(x); |
| 328 | + //y = stdMath.round(y); |
| 329 | + if (-1 < x && x < width && -1 < y && y < height) |
314 | 330 | {
|
315 |
| - var j = (x + y*width) << 2; |
316 |
| - pixel[i + 0] = imageData.data[j + 0]; |
317 |
| - pixel[i + 1] = imageData.data[j + 1]; |
318 |
| - pixel[i + 2] = imageData.data[j + 2]; |
319 |
| - pixel[i + 3] = imageData.data[j + 3]; |
| 331 | + var fx = stdMath.floor(x), |
| 332 | + fy = stdMath.floor(y), |
| 333 | + deltax = stdMath.abs(x-fx), |
| 334 | + deltay = stdMath.abs(y-fy); |
| 335 | + x = fx; y = fy; |
| 336 | + /* |
| 337 | + // bilinear |
| 338 | + var p00 = pt(x ,y ), p10 = pt(x+1,y ), |
| 339 | + p01 = pt(x ,y+1), p11 = pt(x+1,y+1); |
| 340 | + pixel[i + 0] = clamp(stdMath.round(linear( |
| 341 | + linear(p00[0], p10[0], deltax), |
| 342 | + linear(p10[0], p11[0], deltax), |
| 343 | + deltay)), 0, 255); |
| 344 | + pixel[i + 1] = clamp(stdMath.round(linear( |
| 345 | + linear(p00[1], p10[1], deltax), |
| 346 | + linear(p10[1], p11[1], deltax), |
| 347 | + deltay)), 0, 255); |
| 348 | + pixel[i + 2] = clamp(stdMath.round(linear( |
| 349 | + linear(p00[2], p10[2], deltax), |
| 350 | + linear(p10[2], p11[2], deltax), |
| 351 | + deltay)), 0, 255); |
| 352 | + pixel[i + 3] = clamp(stdMath.round(linear( |
| 353 | + linear(p00[3], p10[3], deltax), |
| 354 | + linear(p10[3], p11[3], deltax), |
| 355 | + deltay)), 0, 255); |
| 356 | + */ |
| 357 | + // bicubic |
| 358 | + var p00 = pt(x-1,y-1), p10 = pt(x ,y-1), p20 = pt(x+1,y-1), p30 = pt(x+2,y-1), |
| 359 | + p01 = pt(x-1,y ), p11 = pt(x ,y ), p21 = pt(x+1,y ), p31 = pt(x+2,y ), |
| 360 | + p02 = pt(x-1,y+1), p12 = pt(x ,y+1), p22 = pt(x+1,y+1), p32 = pt(x+2,y+1), |
| 361 | + p03 = pt(x-1,y+2), p13 = pt(x ,y+2), p23 = pt(x+1,y+2), p33 = pt(x+2,y+2); |
| 362 | + pixel[i + 0] = clamp(stdMath.round(cubic( |
| 363 | + cubic(p00[0], p10[0], p20[0], p30[0], deltax), |
| 364 | + cubic(p01[0], p11[0], p21[0], p31[0], deltax), |
| 365 | + cubic(p02[0], p12[0], p22[0], p32[0], deltax), |
| 366 | + cubic(p03[0], p13[0], p23[0], p33[0], deltax), |
| 367 | + deltay)), 0, 255); |
| 368 | + pixel[i + 1] = clamp(stdMath.round(cubic( |
| 369 | + cubic(p00[1], p10[1], p20[1], p30[1], deltax), |
| 370 | + cubic(p01[1], p11[1], p21[1], p31[1], deltax), |
| 371 | + cubic(p02[1], p12[1], p22[1], p32[1], deltax), |
| 372 | + cubic(p03[1], p13[1], p23[1], p33[1], deltax), |
| 373 | + deltay)), 0, 255); |
| 374 | + pixel[i + 2] = clamp(stdMath.round(cubic( |
| 375 | + cubic(p00[2], p10[2], p20[2], p30[2], deltax), |
| 376 | + cubic(p01[2], p11[2], p21[2], p31[2], deltax), |
| 377 | + cubic(p02[2], p12[2], p22[2], p32[2], deltax), |
| 378 | + cubic(p03[2], p13[2], p23[2], p33[2], deltax), |
| 379 | + deltay)), 0, 255); |
| 380 | + pixel[i + 3] = clamp(stdMath.round(cubic( |
| 381 | + cubic(p00[3], p10[3], p20[3], p30[3], deltax), |
| 382 | + cubic(p01[3], p11[3], p21[3], p31[3], deltax), |
| 383 | + cubic(p02[3], p12[3], p22[3], p32[3], deltax), |
| 384 | + cubic(p03[3], p13[3], p23[3], p33[3], deltax), |
| 385 | + deltay)), 0, 255); |
| 386 | + } |
| 387 | + else |
| 388 | + { |
| 389 | + pixel[i + 0] = 0; |
| 390 | + pixel[i + 1] = 0; |
| 391 | + pixel[i + 2] = 0; |
| 392 | + pixel[i + 3] = 0; |
320 | 393 | }
|
321 | 394 | return pixel;
|
322 | 395 | });
|
323 | 396 | case 'repeat-x':
|
324 | 397 | return new Pattern(function(x, y, pixel, i) {
|
325 |
| - x = stdMath.round(x); |
326 |
| - y = stdMath.round(y); |
327 |
| - if (0 <= y && y < height) |
| 398 | + //x = stdMath.round(x); |
| 399 | + //y = stdMath.round(y); |
| 400 | + if (-1 < y && y < height) |
| 401 | + { |
| 402 | + if (x > width) x -= stdMath.floor(x/width)*width; |
| 403 | + if (x < 0) x += stdMath.ceil(-x/width)*width; |
| 404 | + var fx = stdMath.floor(x), |
| 405 | + fy = stdMath.floor(y), |
| 406 | + deltax = stdMath.abs(x-fx), |
| 407 | + deltay = stdMath.abs(y-fy); |
| 408 | + x = fx; y = fy; |
| 409 | + /* |
| 410 | + // bilinear |
| 411 | + var p00 = pt(x ,y ), p10 = pt(x+1,y ), |
| 412 | + p01 = pt(x ,y+1), p11 = pt(x+1,y+1); |
| 413 | + pixel[i + 0] = clamp(stdMath.round(linear( |
| 414 | + linear(p00[0], p10[0], deltax), |
| 415 | + linear(p10[0], p11[0], deltax), |
| 416 | + deltay)), 0, 255); |
| 417 | + pixel[i + 1] = clamp(stdMath.round(linear( |
| 418 | + linear(p00[1], p10[1], deltax), |
| 419 | + linear(p10[1], p11[1], deltax), |
| 420 | + deltay)), 0, 255); |
| 421 | + pixel[i + 2] = clamp(stdMath.round(linear( |
| 422 | + linear(p00[2], p10[2], deltax), |
| 423 | + linear(p10[2], p11[2], deltax), |
| 424 | + deltay)), 0, 255); |
| 425 | + pixel[i + 3] = clamp(stdMath.round(linear( |
| 426 | + linear(p00[3], p10[3], deltax), |
| 427 | + linear(p10[3], p11[3], deltax), |
| 428 | + deltay)), 0, 255); |
| 429 | + */ |
| 430 | + // bicubic |
| 431 | + var p00 = pt(x-1,y-1), p10 = pt(x ,y-1), p20 = pt(x+1,y-1), p30 = pt(x+2,y-1), |
| 432 | + p01 = pt(x-1,y ), p11 = pt(x ,y ), p21 = pt(x+1,y ), p31 = pt(x+2,y ), |
| 433 | + p02 = pt(x-1,y+1), p12 = pt(x ,y+1), p22 = pt(x+1,y+1), p32 = pt(x+2,y+1), |
| 434 | + p03 = pt(x-1,y+2), p13 = pt(x ,y+2), p23 = pt(x+1,y+2), p33 = pt(x+2,y+2); |
| 435 | + pixel[i + 0] = clamp(stdMath.round(cubic( |
| 436 | + cubic(p00[0], p10[0], p20[0], p30[0], deltax), |
| 437 | + cubic(p01[0], p11[0], p21[0], p31[0], deltax), |
| 438 | + cubic(p02[0], p12[0], p22[0], p32[0], deltax), |
| 439 | + cubic(p03[0], p13[0], p23[0], p33[0], deltax), |
| 440 | + deltay)), 0, 255); |
| 441 | + pixel[i + 1] = clamp(stdMath.round(cubic( |
| 442 | + cubic(p00[1], p10[1], p20[1], p30[1], deltax), |
| 443 | + cubic(p01[1], p11[1], p21[1], p31[1], deltax), |
| 444 | + cubic(p02[1], p12[1], p22[1], p32[1], deltax), |
| 445 | + cubic(p03[1], p13[1], p23[1], p33[1], deltax), |
| 446 | + deltay)), 0, 255); |
| 447 | + pixel[i + 2] = clamp(stdMath.round(cubic( |
| 448 | + cubic(p00[2], p10[2], p20[2], p30[2], deltax), |
| 449 | + cubic(p01[2], p11[2], p21[2], p31[2], deltax), |
| 450 | + cubic(p02[2], p12[2], p22[2], p32[2], deltax), |
| 451 | + cubic(p03[2], p13[2], p23[2], p33[2], deltax), |
| 452 | + deltay)), 0, 255); |
| 453 | + pixel[i + 3] = clamp(stdMath.round(cubic( |
| 454 | + cubic(p00[3], p10[3], p20[3], p30[3], deltax), |
| 455 | + cubic(p01[3], p11[3], p21[3], p31[3], deltax), |
| 456 | + cubic(p02[3], p12[3], p22[3], p32[3], deltax), |
| 457 | + cubic(p03[3], p13[3], p23[3], p33[3], deltax), |
| 458 | + deltay)), 0, 255); |
| 459 | + } |
| 460 | + else |
328 | 461 | {
|
329 |
| - x = x % width; |
330 |
| - if (0 > x) x += width; |
331 |
| - var j = (x + y*width) << 2; |
332 |
| - pixel[i + 0] = imageData.data[j + 0]; |
333 |
| - pixel[i + 1] = imageData.data[j + 1]; |
334 |
| - pixel[i + 2] = imageData.data[j + 2]; |
335 |
| - pixel[i + 3] = imageData.data[j + 3]; |
| 462 | + pixel[i + 0] = 0; |
| 463 | + pixel[i + 1] = 0; |
| 464 | + pixel[i + 2] = 0; |
| 465 | + pixel[i + 3] = 0; |
336 | 466 | }
|
337 | 467 | return pixel;
|
338 | 468 | });
|
339 | 469 | case 'repeat-y':
|
340 | 470 | return new Pattern(function(x, y, pixel, i) {
|
341 |
| - x = stdMath.round(x); |
342 |
| - y = stdMath.round(y); |
343 |
| - if (0 <= x && x < width) |
| 471 | + //x = stdMath.round(x); |
| 472 | + //y = stdMath.round(y); |
| 473 | + if (-1 < x && x < width) |
344 | 474 | {
|
345 |
| - y = y % height; |
346 |
| - if (0 > y) y += height; |
347 |
| - var j = (x + y*width) << 2; |
348 |
| - pixel[i + 0] = imageData.data[j + 0]; |
349 |
| - pixel[i + 1] = imageData.data[j + 1]; |
350 |
| - pixel[i + 2] = imageData.data[j + 2]; |
351 |
| - pixel[i + 3] = imageData.data[j + 3]; |
| 475 | + if (y > height) y -= stdMath.floor(y/height)*height; |
| 476 | + if (y < 0) y += stdMath.ceil(-y/height)*height; |
| 477 | + var fx = stdMath.floor(x), |
| 478 | + fy = stdMath.floor(y), |
| 479 | + deltax = stdMath.abs(x-fx), |
| 480 | + deltay = stdMath.abs(y-fy); |
| 481 | + x = fx; y = fy; |
| 482 | + /* |
| 483 | + // bilinear |
| 484 | + var p00 = pt(x ,y ), p10 = pt(x+1,y ), |
| 485 | + p01 = pt(x ,y+1), p11 = pt(x+1,y+1); |
| 486 | + pixel[i + 0] = clamp(stdMath.round(linear( |
| 487 | + linear(p00[0], p10[0], deltax), |
| 488 | + linear(p10[0], p11[0], deltax), |
| 489 | + deltay)), 0, 255); |
| 490 | + pixel[i + 1] = clamp(stdMath.round(linear( |
| 491 | + linear(p00[1], p10[1], deltax), |
| 492 | + linear(p10[1], p11[1], deltax), |
| 493 | + deltay)), 0, 255); |
| 494 | + pixel[i + 2] = clamp(stdMath.round(linear( |
| 495 | + linear(p00[2], p10[2], deltax), |
| 496 | + linear(p10[2], p11[2], deltax), |
| 497 | + deltay)), 0, 255); |
| 498 | + pixel[i + 3] = clamp(stdMath.round(linear( |
| 499 | + linear(p00[3], p10[3], deltax), |
| 500 | + linear(p10[3], p11[3], deltax), |
| 501 | + deltay)), 0, 255); |
| 502 | + */ |
| 503 | + // bicubic |
| 504 | + var p00 = pt(x-1,y-1), p10 = pt(x ,y-1), p20 = pt(x+1,y-1), p30 = pt(x+2,y-1), |
| 505 | + p01 = pt(x-1,y ), p11 = pt(x ,y ), p21 = pt(x+1,y ), p31 = pt(x+2,y ), |
| 506 | + p02 = pt(x-1,y+1), p12 = pt(x ,y+1), p22 = pt(x+1,y+1), p32 = pt(x+2,y+1), |
| 507 | + p03 = pt(x-1,y+2), p13 = pt(x ,y+2), p23 = pt(x+1,y+2), p33 = pt(x+2,y+2); |
| 508 | + pixel[i + 0] = clamp(stdMath.round(cubic( |
| 509 | + cubic(p00[0], p10[0], p20[0], p30[0], deltax), |
| 510 | + cubic(p01[0], p11[0], p21[0], p31[0], deltax), |
| 511 | + cubic(p02[0], p12[0], p22[0], p32[0], deltax), |
| 512 | + cubic(p03[0], p13[0], p23[0], p33[0], deltax), |
| 513 | + deltay)), 0, 255); |
| 514 | + pixel[i + 1] = clamp(stdMath.round(cubic( |
| 515 | + cubic(p00[1], p10[1], p20[1], p30[1], deltax), |
| 516 | + cubic(p01[1], p11[1], p21[1], p31[1], deltax), |
| 517 | + cubic(p02[1], p12[1], p22[1], p32[1], deltax), |
| 518 | + cubic(p03[1], p13[1], p23[1], p33[1], deltax), |
| 519 | + deltay)), 0, 255); |
| 520 | + pixel[i + 2] = clamp(stdMath.round(cubic( |
| 521 | + cubic(p00[2], p10[2], p20[2], p30[2], deltax), |
| 522 | + cubic(p01[2], p11[2], p21[2], p31[2], deltax), |
| 523 | + cubic(p02[2], p12[2], p22[2], p32[2], deltax), |
| 524 | + cubic(p03[2], p13[2], p23[2], p33[2], deltax), |
| 525 | + deltay)), 0, 255); |
| 526 | + pixel[i + 3] = clamp(stdMath.round(cubic( |
| 527 | + cubic(p00[3], p10[3], p20[3], p30[3], deltax), |
| 528 | + cubic(p01[3], p11[3], p21[3], p31[3], deltax), |
| 529 | + cubic(p02[3], p12[3], p22[3], p32[3], deltax), |
| 530 | + cubic(p03[3], p13[3], p23[3], p33[3], deltax), |
| 531 | + deltay)), 0, 255); |
| 532 | + } |
| 533 | + else |
| 534 | + { |
| 535 | + pixel[i + 0] = 0; |
| 536 | + pixel[i + 1] = 0; |
| 537 | + pixel[i + 2] = 0; |
| 538 | + pixel[i + 3] = 0; |
352 | 539 | }
|
353 | 540 | return pixel;
|
354 | 541 | });
|
355 | 542 | case 'repeat':
|
356 | 543 | default:
|
357 | 544 | return new Pattern(function(x, y, pixel, i) {
|
358 |
| - x = stdMath.round(x); |
359 |
| - y = stdMath.round(y); |
360 |
| - x = x % width; |
361 |
| - if (0 > x) x += width; |
362 |
| - y = y % height; |
363 |
| - if (0 > y) y += height; |
364 |
| - var j = (x + y*width) << 2; |
365 |
| - pixel[i + 0] = imageData.data[j + 0]; |
366 |
| - pixel[i + 1] = imageData.data[j + 1]; |
367 |
| - pixel[i + 2] = imageData.data[j + 2]; |
368 |
| - pixel[i + 3] = imageData.data[j + 3]; |
| 545 | + //x = stdMath.round(x); |
| 546 | + //y = stdMath.round(y); |
| 547 | + if (x > width) x -= stdMath.floor(x/width)*width; |
| 548 | + if (x < 0) x += stdMath.ceil(-x/width)*width; |
| 549 | + if (y > height) y -= stdMath.floor(y/height)*height; |
| 550 | + if (y < 0) y += stdMath.ceil(-y/height)*height; |
| 551 | + var fx = stdMath.floor(x), |
| 552 | + fy = stdMath.floor(y), |
| 553 | + deltax = stdMath.abs(x-fx), |
| 554 | + deltay = stdMath.abs(y-fy); |
| 555 | + x = fx; y = fy; |
| 556 | + /* |
| 557 | + // bilinear |
| 558 | + var p00 = pt(x ,y ), p10 = pt(x+1,y ), |
| 559 | + p01 = pt(x ,y+1), p11 = pt(x+1,y+1); |
| 560 | + pixel[i + 0] = clamp(stdMath.round(linear( |
| 561 | + linear(p00[0], p10[0], deltax), |
| 562 | + linear(p10[0], p11[0], deltax), |
| 563 | + deltay)), 0, 255); |
| 564 | + pixel[i + 1] = clamp(stdMath.round(linear( |
| 565 | + linear(p00[1], p10[1], deltax), |
| 566 | + linear(p10[1], p11[1], deltax), |
| 567 | + deltay)), 0, 255); |
| 568 | + pixel[i + 2] = clamp(stdMath.round(linear( |
| 569 | + linear(p00[2], p10[2], deltax), |
| 570 | + linear(p10[2], p11[2], deltax), |
| 571 | + deltay)), 0, 255); |
| 572 | + pixel[i + 3] = clamp(stdMath.round(linear( |
| 573 | + linear(p00[3], p10[3], deltax), |
| 574 | + linear(p10[3], p11[3], deltax), |
| 575 | + deltay)), 0, 255); |
| 576 | + */ |
| 577 | + // bicubic |
| 578 | + var p00 = pt(x-1,y-1), p10 = pt(x ,y-1), p20 = pt(x+1,y-1), p30 = pt(x+2,y-1), |
| 579 | + p01 = pt(x-1,y ), p11 = pt(x ,y ), p21 = pt(x+1,y ), p31 = pt(x+2,y ), |
| 580 | + p02 = pt(x-1,y+1), p12 = pt(x ,y+1), p22 = pt(x+1,y+1), p32 = pt(x+2,y+1), |
| 581 | + p03 = pt(x-1,y+2), p13 = pt(x ,y+2), p23 = pt(x+1,y+2), p33 = pt(x+2,y+2); |
| 582 | + pixel[i + 0] = clamp(stdMath.round(cubic( |
| 583 | + cubic(p00[0], p10[0], p20[0], p30[0], deltax), |
| 584 | + cubic(p01[0], p11[0], p21[0], p31[0], deltax), |
| 585 | + cubic(p02[0], p12[0], p22[0], p32[0], deltax), |
| 586 | + cubic(p03[0], p13[0], p23[0], p33[0], deltax), |
| 587 | + deltay)), 0, 255); |
| 588 | + pixel[i + 1] = clamp(stdMath.round(cubic( |
| 589 | + cubic(p00[1], p10[1], p20[1], p30[1], deltax), |
| 590 | + cubic(p01[1], p11[1], p21[1], p31[1], deltax), |
| 591 | + cubic(p02[1], p12[1], p22[1], p32[1], deltax), |
| 592 | + cubic(p03[1], p13[1], p23[1], p33[1], deltax), |
| 593 | + deltay)), 0, 255); |
| 594 | + pixel[i + 2] = clamp(stdMath.round(cubic( |
| 595 | + cubic(p00[2], p10[2], p20[2], p30[2], deltax), |
| 596 | + cubic(p01[2], p11[2], p21[2], p31[2], deltax), |
| 597 | + cubic(p02[2], p12[2], p22[2], p32[2], deltax), |
| 598 | + cubic(p03[2], p13[2], p23[2], p33[2], deltax), |
| 599 | + deltay)), 0, 255); |
| 600 | + pixel[i + 3] = clamp(stdMath.round(cubic( |
| 601 | + cubic(p00[3], p10[3], p20[3], p30[3], deltax), |
| 602 | + cubic(p01[3], p11[3], p21[3], p31[3], deltax), |
| 603 | + cubic(p02[3], p12[3], p22[3], p32[3], deltax), |
| 604 | + cubic(p03[3], p13[3], p23[3], p33[3], deltax), |
| 605 | + deltay)), 0, 255); |
369 | 606 | return pixel;
|
370 | 607 | });
|
371 | 608 | }
|
@@ -603,6 +840,17 @@ Matrix.skewY = function(s) {
|
603 | 840 | Gradient.Matrix = Matrix;
|
604 | 841 |
|
605 | 842 | // utils
|
| 843 | +function linear(A, B, t) |
| 844 | +{ |
| 845 | + // linear bezier |
| 846 | + return A*(1-t) + B*(t); |
| 847 | +} |
| 848 | +function cubic(A, B, C, D, t) |
| 849 | +{ |
| 850 | + // cubic hermite |
| 851 | + var t2 = t*t; |
| 852 | + return (-A / 2.0 + (3.0*B) / 2.0 - (3.0*C) / 2.0 + D / 2.0)*t2*t + (A - (5.0*B) / 2.0 + 2.0*C - D / 2.0)*t2 + (-A / 2.0 + C / 2.0)*t + (B); |
| 853 | +} |
606 | 854 | function is_strictly_equal(a, b)
|
607 | 855 | {
|
608 | 856 | return stdMath.abs(a - b) < Number.EPSILON;
|
|
0 commit comments