OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkPDFShader.h" | 10 #include "SkPDFShader.h" |
11 | 11 |
12 #include "SkCanvas.h" | 12 #include "SkCanvas.h" |
13 #include "SkData.h" | 13 #include "SkData.h" |
14 #include "SkPDFCatalog.h" | 14 #include "SkPDFCatalog.h" |
15 #include "SkPDFDevice.h" | 15 #include "SkPDFDevice.h" |
16 #include "SkPDFTypes.h" | 16 #include "SkPDFFormXObject.h" |
| 17 #include "SkPDFGraphicState.h" |
17 #include "SkPDFResourceDict.h" | 18 #include "SkPDFResourceDict.h" |
18 #include "SkPDFUtils.h" | 19 #include "SkPDFUtils.h" |
19 #include "SkScalar.h" | 20 #include "SkScalar.h" |
20 #include "SkStream.h" | 21 #include "SkStream.h" |
21 #include "SkTemplates.h" | 22 #include "SkTemplates.h" |
22 #include "SkThread.h" | 23 #include "SkThread.h" |
| 24 #include "SkTSet.h" |
23 #include "SkTypes.h" | 25 #include "SkTypes.h" |
24 | 26 |
25 static bool transformBBox(const SkMatrix& matrix, SkRect* bbox) { | 27 static bool transformBBox(const SkMatrix& matrix, SkRect* bbox) { |
26 SkMatrix inverse; | 28 SkMatrix inverse; |
27 if (!matrix.invert(&inverse)) { | 29 if (!matrix.invert(&inverse)) { |
28 return false; | 30 return false; |
29 } | 31 } |
30 inverse.mapRect(bbox); | 32 inverse.mapRect(bbox); |
31 return true; | 33 return true; |
32 } | 34 } |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 tileModeCode(info.fTileMode, &function); | 394 tileModeCode(info.fTileMode, &function); |
393 gradientFunctionCode(info, &function); | 395 gradientFunctionCode(info, &function); |
394 function.append("}"); | 396 function.append("}"); |
395 return function; | 397 return function; |
396 } | 398 } |
397 | 399 |
398 class SkPDFShader::State { | 400 class SkPDFShader::State { |
399 public: | 401 public: |
400 SkShader::GradientType fType; | 402 SkShader::GradientType fType; |
401 SkShader::GradientInfo fInfo; | 403 SkShader::GradientInfo fInfo; |
402 SkAutoFree fColorData; | 404 SkAutoFree fColorData; // This provides storage for arrays in fInfo. |
403 SkMatrix fCanvasTransform; | 405 SkMatrix fCanvasTransform; |
404 SkMatrix fShaderTransform; | 406 SkMatrix fShaderTransform; |
405 SkIRect fBBox; | 407 SkIRect fBBox; |
406 | 408 |
407 SkBitmap fImage; | 409 SkBitmap fImage; |
408 uint32_t fPixelGeneration; | 410 uint32_t fPixelGeneration; |
409 SkShader::TileMode fImageTileModes[2]; | 411 SkShader::TileMode fImageTileModes[2]; |
410 | 412 |
411 explicit State(const SkShader& shader, const SkMatrix& canvasTransform, | 413 State(const SkShader& shader, const SkMatrix& canvasTransform, |
412 const SkIRect& bbox); | 414 const SkIRect& bbox); |
| 415 |
413 bool operator==(const State& b) const; | 416 bool operator==(const State& b) const; |
| 417 |
| 418 SkPDFShader::State* CreateAlphaToLuminosityState() const; |
| 419 SkPDFShader::State* CreateOpaqueState() const; |
| 420 |
| 421 bool GradientHasAlpha() const; |
| 422 |
| 423 private: |
| 424 State(const State& other); |
| 425 State operator=(const State& rhs); |
| 426 void AllocateGradientInfoStorage(); |
414 }; | 427 }; |
415 | 428 |
416 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { | 429 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { |
417 public: | 430 public: |
418 explicit SkPDFFunctionShader(SkPDFShader::State* state); | 431 explicit SkPDFFunctionShader(SkPDFShader::State* state); |
419 virtual ~SkPDFFunctionShader() { | 432 virtual ~SkPDFFunctionShader() { |
420 if (isValid()) { | 433 if (isValid()) { |
421 RemoveShader(this); | 434 RemoveShader(this); |
422 } | 435 } |
423 fResources.unrefAll(); | 436 fResources.unrefAll(); |
(...skipping 10 matching lines...) Expand all Loading... |
434 | 447 |
435 private: | 448 private: |
436 static SkPDFObject* RangeObject(); | 449 static SkPDFObject* RangeObject(); |
437 | 450 |
438 SkTDArray<SkPDFObject*> fResources; | 451 SkTDArray<SkPDFObject*> fResources; |
439 SkAutoTDelete<const SkPDFShader::State> fState; | 452 SkAutoTDelete<const SkPDFShader::State> fState; |
440 | 453 |
441 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); | 454 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); |
442 }; | 455 }; |
443 | 456 |
| 457 /** |
| 458 * A shader for PDF gradients. This encapsulates the function shader |
| 459 * inside a tiling pattern while providing a common pattern interface. |
| 460 * The encapsulation allows the use of a SMask for transparency gradients. |
| 461 */ |
| 462 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { |
| 463 public: |
| 464 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state); |
| 465 virtual ~SkPDFAlphaFunctionShader() { |
| 466 if (isValid()) { |
| 467 RemoveShader(this); |
| 468 } |
| 469 } |
| 470 |
| 471 virtual bool isValid() { |
| 472 return fColorShader.get() != NULL; |
| 473 } |
| 474 |
| 475 private: |
| 476 SkAutoTDelete<const SkPDFShader::State> fState; |
| 477 |
| 478 SkPDFGraphicState* CreateSMaskGraphicState(); |
| 479 |
| 480 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 481 SkTSet<SkPDFObject*>* newResourceObjects) { |
| 482 fResourceDict->getReferencedResources(knownResourceObjects, |
| 483 newResourceObjects, |
| 484 true); |
| 485 } |
| 486 |
| 487 SkAutoTUnref<SkPDFObject> fColorShader; |
| 488 SkAutoTUnref<SkPDFResourceDict> fResourceDict; |
| 489 }; |
| 490 |
444 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { | 491 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { |
445 public: | 492 public: |
446 explicit SkPDFImageShader(SkPDFShader::State* state); | 493 explicit SkPDFImageShader(SkPDFShader::State* state); |
447 virtual ~SkPDFImageShader() { | 494 virtual ~SkPDFImageShader() { |
448 if (isValid()) { | 495 if (isValid()) { |
449 RemoveShader(this); | 496 RemoveShader(this); |
450 } | 497 } |
451 fResources.unrefAll(); | 498 fResources.unrefAll(); |
452 } | 499 } |
453 | 500 |
454 virtual bool isValid() { return size() > 0; } | 501 virtual bool isValid() { return size() > 0; } |
455 | 502 |
456 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 503 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
457 SkTSet<SkPDFObject*>* newResourceObjects) { | 504 SkTSet<SkPDFObject*>* newResourceObjects) { |
458 GetResourcesHelper(&fResources.toArray(), | 505 GetResourcesHelper(&fResources.toArray(), |
459 knownResourceObjects, | 506 knownResourceObjects, |
460 newResourceObjects); | 507 newResourceObjects); |
461 } | 508 } |
462 | 509 |
463 private: | 510 private: |
464 SkTSet<SkPDFObject*> fResources; | 511 SkTSet<SkPDFObject*> fResources; |
465 SkAutoTDelete<const SkPDFShader::State> fState; | 512 SkAutoTDelete<const SkPDFShader::State> fState; |
466 }; | 513 }; |
467 | 514 |
468 SkPDFShader::SkPDFShader() {} | 515 SkPDFShader::SkPDFShader() {} |
469 | 516 |
470 // static | 517 // static |
471 void SkPDFShader::RemoveShader(SkPDFObject* shader) { | 518 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { |
472 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | 519 SkPDFObject* result; |
473 ShaderCanonicalEntry entry(shader, NULL); | |
474 int index = CanonicalShaders().find(entry); | |
475 SkASSERT(index >= 0); | |
476 CanonicalShaders().removeShuffle(index); | |
477 } | |
478 | 520 |
479 // static | 521 SkAutoTDelete<State> shaderState(inState); |
480 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, | |
481 const SkMatrix& matrix, | |
482 const SkIRect& surfaceBBox) { | |
483 SkPDFObject* result; | |
484 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
485 SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox)); | |
486 if (shaderState.get()->fType == SkShader::kNone_GradientType && | 522 if (shaderState.get()->fType == SkShader::kNone_GradientType && |
487 shaderState.get()->fImage.isNull()) { | 523 shaderState.get()->fImage.isNull()) { |
488 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 524 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
489 // handle compose shader by pulling things up to a layer, drawing with | 525 // handle compose shader by pulling things up to a layer, drawing with |
490 // the first shader, applying the xfer mode and drawing again with the | 526 // the first shader, applying the xfer mode and drawing again with the |
491 // second shader, then applying the layer to the original drawing. | 527 // second shader, then applying the layer to the original drawing. |
492 return NULL; | 528 return NULL; |
493 } | 529 } |
494 | 530 |
495 ShaderCanonicalEntry entry(NULL, shaderState.get()); | 531 ShaderCanonicalEntry entry(NULL, shaderState.get()); |
496 int index = CanonicalShaders().find(entry); | 532 int index = CanonicalShaders().find(entry); |
497 if (index >= 0) { | 533 if (index >= 0) { |
498 result = CanonicalShaders()[index].fPDFShader; | 534 result = CanonicalShaders()[index].fPDFShader; |
499 result->ref(); | 535 result->ref(); |
500 return result; | 536 return result; |
501 } | 537 } |
502 | 538 |
503 bool valid = false; | 539 bool valid = false; |
504 // The PDFShader takes ownership of the shaderSate. | 540 // The PDFShader takes ownership of the shaderSate. |
505 if (shaderState.get()->fType == SkShader::kNone_GradientType) { | 541 if (shaderState.get()->fType == SkShader::kNone_GradientType) { |
506 SkPDFImageShader* imageShader = | 542 SkPDFImageShader* imageShader = |
507 new SkPDFImageShader(shaderState.detach()); | 543 new SkPDFImageShader(shaderState.detach()); |
508 valid = imageShader->isValid(); | 544 valid = imageShader->isValid(); |
509 result = imageShader; | 545 result = imageShader; |
510 } else { | 546 } else { |
511 SkPDFFunctionShader* functionShader = | 547 if (shaderState.get()->GradientHasAlpha()) { |
512 new SkPDFFunctionShader(shaderState.detach()); | 548 SkPDFAlphaFunctionShader* gradientShader = |
513 valid = functionShader->isValid(); | 549 SkNEW_ARGS(SkPDFAlphaFunctionShader, (shaderState.detach())); |
514 result = functionShader; | 550 valid = gradientShader->isValid(); |
| 551 result = gradientShader; |
| 552 } else { |
| 553 SkPDFFunctionShader* functionShader = |
| 554 SkNEW_ARGS(SkPDFFunctionShader, (shaderState.detach())); |
| 555 valid = functionShader->isValid(); |
| 556 result = functionShader; |
| 557 } |
515 } | 558 } |
516 if (!valid) { | 559 if (!valid) { |
517 delete result; | 560 delete result; |
518 return NULL; | 561 return NULL; |
519 } | 562 } |
520 entry.fPDFShader = result; | 563 entry.fPDFShader = result; |
521 CanonicalShaders().push(entry); | 564 CanonicalShaders().push(entry); |
522 return result; // return the reference that came from new. | 565 return result; // return the reference that came from new. |
523 } | 566 } |
524 | 567 |
525 // static | 568 // static |
| 569 void SkPDFShader::RemoveShader(SkPDFObject* shader) { |
| 570 SkAutoMutexAcquire lock(CanonicalShadersMutex()); |
| 571 ShaderCanonicalEntry entry(shader, NULL); |
| 572 int index = CanonicalShaders().find(entry); |
| 573 SkASSERT(index >= 0); |
| 574 CanonicalShaders().removeShuffle(index); |
| 575 } |
| 576 |
| 577 // static |
| 578 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, |
| 579 const SkMatrix& matrix, |
| 580 const SkIRect& surfaceBBox) { |
| 581 SkAutoMutexAcquire lock(CanonicalShadersMutex()); |
| 582 return GetPDFShaderByState( |
| 583 SkNEW_ARGS(State, (shader, matrix, surfaceBBox))); |
| 584 } |
| 585 |
| 586 // static |
526 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { | 587 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { |
527 // This initialization is only thread safe with gcc. | 588 // This initialization is only thread safe with gcc. |
528 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; | 589 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; |
529 return gCanonicalShaders; | 590 return gCanonicalShaders; |
530 } | 591 } |
531 | 592 |
532 // static | 593 // static |
533 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { | 594 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { |
534 // This initialization is only thread safe with gcc or when | 595 // This initialization is only thread safe with gcc or when |
535 // POD-style mutex initialization is used. | 596 // POD-style mutex initialization is used. |
(...skipping 13 matching lines...) Expand all Loading... |
549 range->appendInt(0); | 610 range->appendInt(0); |
550 range->appendInt(1); | 611 range->appendInt(1); |
551 range->appendInt(0); | 612 range->appendInt(0); |
552 range->appendInt(1); | 613 range->appendInt(1); |
553 range->appendInt(0); | 614 range->appendInt(0); |
554 range->appendInt(1); | 615 range->appendInt(1); |
555 } | 616 } |
556 return range; | 617 return range; |
557 } | 618 } |
558 | 619 |
| 620 static SkPDFResourceDict* get_gradient_resource_dict( |
| 621 SkPDFObject* functionShader, |
| 622 SkPDFObject* gState) { |
| 623 SkPDFResourceDict* dict = new SkPDFResourceDict(); |
| 624 |
| 625 if (functionShader != NULL) { |
| 626 dict->insertResourceAsReference( |
| 627 SkPDFResourceDict::kPattern_ResourceType, 0, functionShader); |
| 628 } |
| 629 if (gState != NULL) { |
| 630 dict->insertResourceAsReference( |
| 631 SkPDFResourceDict::kExtGState_ResourceType, 0, gState); |
| 632 } |
| 633 |
| 634 return dict; |
| 635 } |
| 636 |
| 637 static void populate_tiling_pattern_dict(SkPDFDict* pattern, |
| 638 SkRect& bbox, SkPDFDict* resources, |
| 639 const SkMatrix& matrix) { |
| 640 const int kTiling_PatternType = 1; |
| 641 const int kColoredTilingPattern_PaintType = 1; |
| 642 const int kConstantSpacing_TilingType = 1; |
| 643 |
| 644 pattern->insertName("Type", "Pattern"); |
| 645 pattern->insertInt("PatternType", kTiling_PatternType); |
| 646 pattern->insertInt("PaintType", kColoredTilingPattern_PaintType); |
| 647 pattern->insertInt("TilingType", kConstantSpacing_TilingType); |
| 648 pattern->insert("BBox", SkPDFUtils::RectToArray(bbox))->unref(); |
| 649 pattern->insertScalar("XStep", bbox.width()); |
| 650 pattern->insertScalar("YStep", bbox.height()); |
| 651 pattern->insert("Resources", resources); |
| 652 if (!matrix.isIdentity()) { |
| 653 pattern->insert("Matrix", SkPDFUtils::MatrixToArray(matrix))->unref(); |
| 654 } |
| 655 } |
| 656 |
| 657 /** |
| 658 * Creates a content stream which fills the pattern P0 across bounds. |
| 659 * @param gsIndex A graphics state resource index to apply, or <0 if no |
| 660 * graphics state to apply. |
| 661 */ |
| 662 static SkStream* create_pattern_fill_content(int gsIndex, SkRect& bounds) { |
| 663 SkDynamicMemoryWStream content; |
| 664 if (gsIndex >= 0) { |
| 665 SkPDFUtils::ApplyGraphicState(gsIndex, &content); |
| 666 } |
| 667 SkPDFUtils::ApplyPattern(0, &content); |
| 668 SkPDFUtils::AppendRectangle(bounds, &content); |
| 669 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, |
| 670 &content); |
| 671 |
| 672 return content.detachAsStream(); |
| 673 } |
| 674 |
| 675 /** |
| 676 * Creates a ExtGState with the SMask set to the luminosityShader in |
| 677 * luminosity mode. The shader pattern extends to the bbox. |
| 678 */ |
| 679 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { |
| 680 SkRect bbox; |
| 681 bbox.set(fState.get()->fBBox); |
| 682 |
| 683 SkAutoTUnref<SkPDFObject> luminosityShader( |
| 684 SkPDFShader::GetPDFShaderByState( |
| 685 fState->CreateAlphaToLuminosityState())); |
| 686 |
| 687 SkAutoTUnref<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); |
| 688 |
| 689 SkAutoTUnref<SkPDFResourceDict> |
| 690 resources(get_gradient_resource_dict(luminosityShader, NULL)); |
| 691 |
| 692 SkAutoTUnref<SkPDFFormXObject> alphaMask( |
| 693 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); |
| 694 |
| 695 return SkPDFGraphicState::GetSMaskGraphicState( |
| 696 alphaMask.get(), false, |
| 697 SkPDFGraphicState::kLuminosity_SMaskMode); |
| 698 } |
| 699 |
| 700 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) |
| 701 : fState(state) { |
| 702 SkRect bbox; |
| 703 bbox.set(fState.get()->fBBox); |
| 704 |
| 705 fColorShader.reset( |
| 706 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); |
| 707 |
| 708 // Create resource dict with alpha graphics state as G0 and |
| 709 // pattern shader as P0, then write content stream. |
| 710 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); |
| 711 fResourceDict.reset( |
| 712 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); |
| 713 |
| 714 SkAutoTUnref<SkStream> colorStream( |
| 715 create_pattern_fill_content(0, bbox)); |
| 716 setData(colorStream.get()); |
| 717 |
| 718 populate_tiling_pattern_dict(this, bbox, fResourceDict.get(), |
| 719 SkMatrix::I()); |
| 720 } |
| 721 |
559 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) | 722 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
560 : SkPDFDict("Pattern"), | 723 : SkPDFDict("Pattern"), |
561 fState(state) { | 724 fState(state) { |
562 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; | 725 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; |
563 SkPoint transformPoints[2]; | 726 SkPoint transformPoints[2]; |
564 | 727 |
565 // Depending on the type of the gradient, we want to transform the | 728 // Depending on the type of the gradient, we want to transform the |
566 // coordinate space in different ways. | 729 // coordinate space in different ways. |
567 const SkShader::GradientInfo* info = &fState.get()->fInfo; | 730 const SkShader::GradientInfo* info = &fState.get()->fInfo; |
568 transformPoints[0] = info->fPoint[0]; | 731 transformPoints[0] = info->fPoint[0]; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 | 987 |
825 if (tileModes[0] == SkShader::kMirror_TileMode) { | 988 if (tileModes[0] == SkShader::kMirror_TileMode) { |
826 bottomMatrix.postScale(-1, 1); | 989 bottomMatrix.postScale(-1, 1); |
827 bottomMatrix.postTranslate(2 * width, 0); | 990 bottomMatrix.postTranslate(2 * width, 0); |
828 canvas.drawBitmapMatrix(bottom, bottomMatrix); | 991 canvas.drawBitmapMatrix(bottom, bottomMatrix); |
829 } | 992 } |
830 patternBBox.fBottom = surfaceBBox.height(); | 993 patternBBox.fBottom = surfaceBBox.height(); |
831 } | 994 } |
832 } | 995 } |
833 | 996 |
834 SkAutoTUnref<SkPDFArray> patternBBoxArray(new SkPDFArray); | |
835 patternBBoxArray->reserve(4); | |
836 patternBBoxArray->appendScalar(patternBBox.fLeft); | |
837 patternBBoxArray->appendScalar(patternBBox.fTop); | |
838 patternBBoxArray->appendScalar(patternBBox.fRight); | |
839 patternBBoxArray->appendScalar(patternBBox.fBottom); | |
840 | |
841 // Put the canvas into the pattern stream (fContent). | 997 // Put the canvas into the pattern stream (fContent). |
842 SkAutoTUnref<SkStream> content(pattern.content()); | 998 SkAutoTUnref<SkStream> content(pattern.content()); |
843 setData(content.get()); | 999 setData(content.get()); |
844 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); | 1000 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); |
845 resourceDict->getReferencedResources(fResources, &fResources, false); | 1001 resourceDict->getReferencedResources(fResources, &fResources, false); |
846 | 1002 |
847 insertName("Type", "Pattern"); | 1003 populate_tiling_pattern_dict(this, patternBBox, |
848 insertInt("PatternType", 1); | 1004 pattern.getResourceDict(), finalMatrix); |
849 insertInt("PaintType", 1); | |
850 insertInt("TilingType", 1); | |
851 insert("BBox", patternBBoxArray.get()); | |
852 insertScalar("XStep", patternBBox.width()); | |
853 insertScalar("YStep", patternBBox.height()); | |
854 insert("Resources", resourceDict); | |
855 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); | |
856 | 1005 |
857 fState.get()->fImage.unlockPixels(); | 1006 fState.get()->fImage.unlockPixels(); |
858 } | 1007 } |
859 | 1008 |
860 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, | 1009 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, |
861 SkPDFArray* domain) { | 1010 SkPDFArray* domain) { |
862 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), | 1011 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), |
863 psCode.size())); | 1012 psCode.size())); |
864 SkPDFStream* result = new SkPDFStream(funcData.get()); | 1013 SkPDFStream* result = new SkPDFStream(funcData.get()); |
865 result->insertInt("FunctionType", 4); | 1014 result->insertInt("FunctionType", 4); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 SkShader::BitmapType bitmapType; | 1100 SkShader::BitmapType bitmapType; |
952 SkMatrix matrix; | 1101 SkMatrix matrix; |
953 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); | 1102 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); |
954 if (bitmapType != SkShader::kDefault_BitmapType) { | 1103 if (bitmapType != SkShader::kDefault_BitmapType) { |
955 fImage.reset(); | 1104 fImage.reset(); |
956 return; | 1105 return; |
957 } | 1106 } |
958 SkASSERT(matrix.isIdentity()); | 1107 SkASSERT(matrix.isIdentity()); |
959 fPixelGeneration = fImage.getGenerationID(); | 1108 fPixelGeneration = fImage.getGenerationID(); |
960 } else { | 1109 } else { |
961 fColorData.set(sk_malloc_throw( | 1110 AllocateGradientInfoStorage(); |
962 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | |
963 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | |
964 fInfo.fColorOffsets = | |
965 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | |
966 shader.asAGradient(&fInfo); | 1111 shader.asAGradient(&fInfo); |
967 } | 1112 } |
968 } | 1113 } |
| 1114 |
| 1115 SkPDFShader::State::State(const SkPDFShader::State& other) |
| 1116 : fType(other.fType), |
| 1117 fCanvasTransform(other.fCanvasTransform), |
| 1118 fShaderTransform(other.fShaderTransform), |
| 1119 fBBox(other.fBBox) |
| 1120 { |
| 1121 // Only gradients supported for now, since that is all that is used. |
| 1122 // If needed, image state copy constructor can be added here later. |
| 1123 SkASSERT(fType != SkShader::kNone_GradientType); |
| 1124 |
| 1125 if (fType != SkShader::kNone_GradientType) { |
| 1126 fInfo = other.fInfo; |
| 1127 |
| 1128 AllocateGradientInfoStorage(); |
| 1129 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1130 fInfo.fColors[i] = other.fInfo.fColors[i]; |
| 1131 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; |
| 1132 } |
| 1133 } |
| 1134 } |
| 1135 |
| 1136 /** |
| 1137 * Create a copy of this gradient state with alpha assigned to RGB luminousity. |
| 1138 * Only valid for gradient states. |
| 1139 */ |
| 1140 SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const { |
| 1141 SkASSERT(fType != SkShader::kNone_GradientType); |
| 1142 |
| 1143 SkPDFShader::State* newState = new SkPDFShader::State(*this); |
| 1144 |
| 1145 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1146 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
| 1147 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); |
| 1148 } |
| 1149 |
| 1150 return newState; |
| 1151 } |
| 1152 |
| 1153 /** |
| 1154 * Create a copy of this gradient state with alpha set to fully opaque |
| 1155 * Only valid for gradient states. |
| 1156 */ |
| 1157 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const { |
| 1158 SkASSERT(fType != SkShader::kNone_GradientType); |
| 1159 |
| 1160 SkPDFShader::State* newState = new SkPDFShader::State(*this); |
| 1161 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1162 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], |
| 1163 SK_AlphaOPAQUE); |
| 1164 } |
| 1165 |
| 1166 return newState; |
| 1167 } |
| 1168 |
| 1169 /** |
| 1170 * Returns true if state is a gradient and the gradient has alpha. |
| 1171 */ |
| 1172 bool SkPDFShader::State::GradientHasAlpha() const { |
| 1173 if (fType == SkShader::kNone_GradientType) { |
| 1174 return false; |
| 1175 } |
| 1176 |
| 1177 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1178 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
| 1179 if (alpha != SK_AlphaOPAQUE) { |
| 1180 return true; |
| 1181 } |
| 1182 } |
| 1183 return false; |
| 1184 } |
| 1185 |
| 1186 void SkPDFShader::State::AllocateGradientInfoStorage() { |
| 1187 fColorData.set(sk_malloc_throw( |
| 1188 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
| 1189 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
| 1190 fInfo.fColorOffsets = |
| 1191 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
| 1192 } |
OLD | NEW |