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->getResources(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 RemoveShader(this); | 495 RemoveShader(this); |
449 fResources.unrefAll(); | 496 fResources.unrefAll(); |
450 } | 497 } |
451 | 498 |
452 virtual bool isValid() { return size() > 0; } | 499 virtual bool isValid() { return size() > 0; } |
453 | 500 |
454 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 501 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
455 SkTSet<SkPDFObject*>* newResourceObjects) { | 502 SkTSet<SkPDFObject*>* newResourceObjects) { |
456 GetResourcesHelper(&fResources.toArray(), | 503 GetResourcesHelper(&fResources.toArray(), |
457 knownResourceObjects, | 504 knownResourceObjects, |
458 newResourceObjects); | 505 newResourceObjects); |
459 } | 506 } |
460 | 507 |
461 private: | 508 private: |
462 SkTSet<SkPDFObject*> fResources; | 509 SkTSet<SkPDFObject*> fResources; |
463 SkAutoTDelete<const SkPDFShader::State> fState; | 510 SkAutoTDelete<const SkPDFShader::State> fState; |
464 }; | 511 }; |
465 | 512 |
466 SkPDFShader::SkPDFShader() {} | 513 SkPDFShader::SkPDFShader() {} |
467 | 514 |
468 // static | 515 // static |
469 void SkPDFShader::RemoveShader(SkPDFObject* shader) { | 516 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { |
470 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | 517 SkPDFObject* result; |
471 ShaderCanonicalEntry entry(shader, NULL); | |
472 int index = CanonicalShaders().find(entry); | |
473 SkASSERT(index >= 0); | |
474 CanonicalShaders().removeShuffle(index); | |
475 } | |
476 | 518 |
477 // static | 519 SkAutoTDelete<State> shaderState(inState); |
478 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, | |
479 const SkMatrix& matrix, | |
480 const SkIRect& surfaceBBox) { | |
481 SkPDFObject* result; | |
482 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
483 SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox)); | |
484 if (shaderState.get()->fType == SkShader::kNone_GradientType && | 520 if (shaderState.get()->fType == SkShader::kNone_GradientType && |
485 shaderState.get()->fImage.isNull()) { | 521 shaderState.get()->fImage.isNull()) { |
486 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 522 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
487 // handle compose shader by pulling things up to a layer, drawing with | 523 // handle compose shader by pulling things up to a layer, drawing with |
488 // the first shader, applying the xfer mode and drawing again with the | 524 // the first shader, applying the xfer mode and drawing again with the |
489 // second shader, then applying the layer to the original drawing. | 525 // second shader, then applying the layer to the original drawing. |
490 return NULL; | 526 return NULL; |
491 } | 527 } |
492 | 528 |
493 ShaderCanonicalEntry entry(NULL, shaderState.get()); | 529 ShaderCanonicalEntry entry(NULL, shaderState.get()); |
494 int index = CanonicalShaders().find(entry); | 530 int index = CanonicalShaders().find(entry); |
495 if (index >= 0) { | 531 if (index >= 0) { |
496 result = CanonicalShaders()[index].fPDFShader; | 532 result = CanonicalShaders()[index].fPDFShader; |
497 result->ref(); | 533 result->ref(); |
498 return result; | 534 return result; |
499 } | 535 } |
500 | 536 |
501 bool valid = false; | 537 bool valid = false; |
502 // The PDFShader takes ownership of the shaderSate. | 538 // The PDFShader takes ownership of the shaderSate. |
503 if (shaderState.get()->fType == SkShader::kNone_GradientType) { | 539 if (shaderState.get()->fType == SkShader::kNone_GradientType) { |
504 SkPDFImageShader* imageShader = | 540 SkPDFImageShader* imageShader = |
505 new SkPDFImageShader(shaderState.detach()); | 541 new SkPDFImageShader(shaderState.detach()); |
506 valid = imageShader->isValid(); | 542 valid = imageShader->isValid(); |
507 result = imageShader; | 543 result = imageShader; |
508 } else { | 544 } else { |
509 SkPDFFunctionShader* functionShader = | 545 if (shaderState.get()->GradientHasAlpha()) { |
510 new SkPDFFunctionShader(shaderState.detach()); | 546 SkPDFAlphaFunctionShader* gradientShader = |
511 valid = functionShader->isValid(); | 547 new SkPDFAlphaFunctionShader(shaderState.detach()); |
512 result = functionShader; | 548 valid = gradientShader->isValid(); |
549 result = gradientShader; | |
550 } else { | |
551 SkPDFFunctionShader* functionShader = | |
552 new SkPDFFunctionShader(shaderState.detach()); | |
553 valid = functionShader->isValid(); | |
554 result = functionShader; | |
555 } | |
513 } | 556 } |
514 if (!valid) { | 557 if (!valid) { |
515 delete result; | 558 delete result; |
516 return NULL; | 559 return NULL; |
517 } | 560 } |
518 entry.fPDFShader = result; | 561 entry.fPDFShader = result; |
519 CanonicalShaders().push(entry); | 562 CanonicalShaders().push(entry); |
520 return result; // return the reference that came from new. | 563 return result; // return the reference that came from new. |
521 } | 564 } |
522 | 565 |
523 // static | 566 // static |
567 void SkPDFShader::RemoveShader(SkPDFObject* shader) { | |
568 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
569 ShaderCanonicalEntry entry(shader, NULL); | |
570 int index = CanonicalShaders().find(entry); | |
571 SkASSERT(index >= 0); | |
572 CanonicalShaders().removeShuffle(index); | |
573 } | |
574 | |
575 // static | |
576 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, | |
577 const SkMatrix& matrix, | |
578 const SkIRect& surfaceBBox) { | |
579 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
580 return GetPDFShaderByState(new State(shader, matrix, surfaceBBox)); | |
581 } | |
582 | |
583 // static | |
524 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { | 584 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { |
525 // This initialization is only thread safe with gcc. | 585 // This initialization is only thread safe with gcc. |
526 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; | 586 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; |
527 return gCanonicalShaders; | 587 return gCanonicalShaders; |
528 } | 588 } |
529 | 589 |
530 // static | 590 // static |
531 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { | 591 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { |
532 // This initialization is only thread safe with gcc or when | 592 // This initialization is only thread safe with gcc or when |
533 // POD-style mutex initialization is used. | 593 // POD-style mutex initialization is used. |
(...skipping 13 matching lines...) Expand all Loading... | |
547 range->appendInt(0); | 607 range->appendInt(0); |
548 range->appendInt(1); | 608 range->appendInt(1); |
549 range->appendInt(0); | 609 range->appendInt(0); |
550 range->appendInt(1); | 610 range->appendInt(1); |
551 range->appendInt(0); | 611 range->appendInt(0); |
552 range->appendInt(1); | 612 range->appendInt(1); |
553 } | 613 } |
554 return range; | 614 return range; |
555 } | 615 } |
556 | 616 |
617 static SkPDFResourceDict* get_gradient_resource_dict( | |
618 SkPDFObject* functionShader, | |
619 SkPDFObject* gState) { | |
620 SkPDFResourceDict* dict = new SkPDFResourceDict(); | |
621 | |
622 if (functionShader != NULL) { | |
623 dict->insertResourceAsRef(SkPDFResourceDict::kPattern_ResourceType, 0, | |
624 functionShader); | |
625 } | |
626 if (gState != NULL) { | |
627 dict->insertResourceAsRef(SkPDFResourceDict::kExtGState_ResourceType, 0, | |
628 gState); | |
629 } | |
630 | |
631 return dict; | |
632 } | |
633 | |
634 static void populate_tiling_pattern_dict(SkPDFDict* pattern, | |
635 SkRect& bbox, SkPDFDict* resources, | |
636 const SkMatrix& matrix) { | |
637 pattern->insertName("Type", "Pattern"); | |
638 pattern->insertInt("PatternType", 1); | |
639 pattern->insertInt("PaintType", 1); | |
640 pattern->insertInt("TilingType", 1); | |
641 pattern->insert("BBox", SkPDFUtils::RectToArray(bbox))->unref(); | |
642 pattern->insertScalar("XStep", bbox.width()); | |
643 pattern->insertScalar("YStep", bbox.height()); | |
644 pattern->insert("Resources", resources); | |
645 if (!matrix.isIdentity()) { | |
646 pattern->insert("Matrix", SkPDFUtils::MatrixToArray(matrix))->unref(); | |
647 } | |
648 } | |
649 | |
650 /** | |
651 * Creates a content stream which fills the pattern P0 across bounds. | |
652 * The argument setup may contain any relevant PDF content stream operators | |
653 * and will be prepended to the output content stream. | |
654 */ | |
655 static SkData* create_pattern_fill_content(const char* setup, SkRect& bounds) { | |
656 SkDynamicMemoryWStream content; | |
657 if (NULL != setup) { | |
658 content.writeText(setup); | |
659 } | |
660 content.writeText("/Pattern CS/Pattern cs/"); | |
661 content.writeText(SkPDFResourceDict::getResourceName( | |
662 SkPDFResourceDict::kPattern_ResourceType, 0).c_str()); | |
663 content.writeText(" SCN/"); | |
664 content.writeText(SkPDFResourceDict::getResourceName( | |
665 SkPDFResourceDict::kPattern_ResourceType, 0).c_str()); | |
666 content.writeText(" scn\n"); | |
667 | |
668 SkPDFUtils::AppendRectangle(bounds, &content); | |
669 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, | |
670 &content); | |
671 | |
672 return content.copyToData(); | |
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<SkData> alphaStream(create_pattern_fill_content(NULL, 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 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); | |
709 fResourceDict.reset( | |
710 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); | |
711 | |
712 SkString setGs = SkString(); | |
vandebo (ex-Chrome)
2013/07/15 16:40:06
nit: This has changed enough that I think the orig
ducky
2013/07/15 18:04:10
Done.
| |
713 setGs.append("/"); | |
714 setGs.append(SkPDFResourceDict::getResourceName( | |
715 SkPDFResourceDict::kExtGState_ResourceType, 0).c_str()); | |
716 setGs.append(" gs"); | |
717 SkAutoTUnref<SkData> colorStream( | |
718 create_pattern_fill_content(setGs.c_str(), bbox)); | |
719 setData(colorStream.get()); | |
720 | |
721 populate_tiling_pattern_dict(this, bbox, fResourceDict.get(), | |
722 SkMatrix::I()); | |
723 } | |
724 | |
557 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) | 725 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
558 : SkPDFDict("Pattern"), | 726 : SkPDFDict("Pattern"), |
559 fState(state) { | 727 fState(state) { |
560 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; | 728 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; |
561 SkPoint transformPoints[2]; | 729 SkPoint transformPoints[2]; |
562 | 730 |
563 // Depending on the type of the gradient, we want to transform the | 731 // Depending on the type of the gradient, we want to transform the |
564 // coordinate space in different ways. | 732 // coordinate space in different ways. |
565 const SkShader::GradientInfo* info = &fState.get()->fInfo; | 733 const SkShader::GradientInfo* info = &fState.get()->fInfo; |
566 transformPoints[0] = info->fPoint[0]; | 734 transformPoints[0] = info->fPoint[0]; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
822 | 990 |
823 if (tileModes[0] == SkShader::kMirror_TileMode) { | 991 if (tileModes[0] == SkShader::kMirror_TileMode) { |
824 bottomMatrix.postScale(-1, 1); | 992 bottomMatrix.postScale(-1, 1); |
825 bottomMatrix.postTranslate(2 * width, 0); | 993 bottomMatrix.postTranslate(2 * width, 0); |
826 canvas.drawBitmapMatrix(bottom, bottomMatrix); | 994 canvas.drawBitmapMatrix(bottom, bottomMatrix); |
827 } | 995 } |
828 patternBBox.fBottom = surfaceBBox.height(); | 996 patternBBox.fBottom = surfaceBBox.height(); |
829 } | 997 } |
830 } | 998 } |
831 | 999 |
832 SkAutoTUnref<SkPDFArray> patternBBoxArray(new SkPDFArray); | |
833 patternBBoxArray->reserve(4); | |
834 patternBBoxArray->appendScalar(patternBBox.fLeft); | |
835 patternBBoxArray->appendScalar(patternBBox.fTop); | |
836 patternBBoxArray->appendScalar(patternBBox.fRight); | |
837 patternBBoxArray->appendScalar(patternBBox.fBottom); | |
838 | |
839 // Put the canvas into the pattern stream (fContent). | 1000 // Put the canvas into the pattern stream (fContent). |
840 SkAutoTUnref<SkData> content(pattern.copyContentToData()); | 1001 SkAutoTUnref<SkData> content(pattern.copyContentToData()); |
841 setData(content.get()); | 1002 setData(content.get()); |
842 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); | 1003 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); |
843 resourceDict->getResources(fResources, &fResources, false); | 1004 resourceDict->getResources(fResources, &fResources, false); |
844 | 1005 |
845 insertName("Type", "Pattern"); | 1006 populate_tiling_pattern_dict(this, patternBBox, |
846 insertInt("PatternType", 1); | 1007 pattern.getResourceDict(), finalMatrix); |
847 insertInt("PaintType", 1); | |
848 insertInt("TilingType", 1); | |
849 insert("BBox", patternBBoxArray.get()); | |
850 insertScalar("XStep", patternBBox.width()); | |
851 insertScalar("YStep", patternBBox.height()); | |
852 insert("Resources", resourceDict); | |
853 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); | |
854 | 1008 |
855 fState.get()->fImage.unlockPixels(); | 1009 fState.get()->fImage.unlockPixels(); |
856 } | 1010 } |
857 | 1011 |
858 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, | 1012 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, |
859 SkPDFArray* domain) { | 1013 SkPDFArray* domain) { |
860 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), | 1014 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), |
861 psCode.size())); | 1015 psCode.size())); |
862 SkPDFStream* result = new SkPDFStream(funcData.get()); | 1016 SkPDFStream* result = new SkPDFStream(funcData.get()); |
863 result->insertInt("FunctionType", 4); | 1017 result->insertInt("FunctionType", 4); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
949 SkShader::BitmapType bitmapType; | 1103 SkShader::BitmapType bitmapType; |
950 SkMatrix matrix; | 1104 SkMatrix matrix; |
951 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); | 1105 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); |
952 if (bitmapType != SkShader::kDefault_BitmapType) { | 1106 if (bitmapType != SkShader::kDefault_BitmapType) { |
953 fImage.reset(); | 1107 fImage.reset(); |
954 return; | 1108 return; |
955 } | 1109 } |
956 SkASSERT(matrix.isIdentity()); | 1110 SkASSERT(matrix.isIdentity()); |
957 fPixelGeneration = fImage.getGenerationID(); | 1111 fPixelGeneration = fImage.getGenerationID(); |
958 } else { | 1112 } else { |
959 fColorData.set(sk_malloc_throw( | 1113 AllocateGradientInfoStorage(); |
960 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | |
961 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | |
962 fInfo.fColorOffsets = | |
963 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | |
964 shader.asAGradient(&fInfo); | 1114 shader.asAGradient(&fInfo); |
965 } | 1115 } |
966 } | 1116 } |
1117 | |
1118 SkPDFShader::State::State(const SkPDFShader::State& other) | |
1119 : fType(other.fType), | |
1120 fCanvasTransform(other.fCanvasTransform), | |
1121 fShaderTransform(other.fShaderTransform), | |
1122 fBBox(other.fBBox) | |
1123 { | |
1124 // Only gradients supported for now, since that is all that is used. | |
1125 // If needed, image state copy constructor can be added here later. | |
1126 SkASSERT(fType != SkShader::kNone_GradientType); | |
1127 | |
1128 if (fType != SkShader::kNone_GradientType) { | |
1129 fInfo = other.fInfo; | |
1130 | |
1131 AllocateGradientInfoStorage(); | |
1132 for (int i = 0; i < fInfo.fColorCount; i++) { | |
1133 fInfo.fColors[i] = other.fInfo.fColors[i]; | |
1134 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; | |
1135 } | |
1136 } | |
1137 } | |
1138 | |
1139 /** | |
1140 * Create a copy of this gradient state with alpha assigned to RGB luminousity. | |
1141 * Only valid for gradient states. | |
1142 */ | |
1143 SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const { | |
1144 SkASSERT(fType != SkShader::kNone_GradientType); | |
1145 | |
1146 SkPDFShader::State* newState = new SkPDFShader::State(*this); | |
1147 | |
1148 for (int i = 0; i < fInfo.fColorCount; i++) { | |
1149 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | |
1150 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); | |
1151 } | |
1152 | |
1153 return newState; | |
1154 } | |
1155 | |
1156 /** | |
1157 * Create a copy of this gradient state with alpha set to fully opaque | |
1158 * Only valid for gradient states. | |
1159 */ | |
1160 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const { | |
1161 SkASSERT(fType != SkShader::kNone_GradientType); | |
1162 | |
1163 SkPDFShader::State* newState = new SkPDFShader::State(*this); | |
1164 SkAlpha opaque = SkColorGetA(SK_ColorBLACK); | |
1165 for (int i = 0; i < fInfo.fColorCount; i++) { | |
1166 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], opaque); | |
1167 } | |
1168 | |
1169 return newState; | |
1170 } | |
1171 | |
1172 /** | |
1173 * Returns true if state is a gradient and the gradient has alpha. | |
1174 */ | |
1175 bool SkPDFShader::State::GradientHasAlpha() const { | |
1176 if (fType == SkShader::kNone_GradientType) { | |
1177 return false; | |
1178 } | |
1179 | |
1180 SkAlpha opaque = SkColorGetA(SK_ColorBLACK); | |
1181 for (int i = 0; i < fInfo.fColorCount; i++) { | |
1182 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | |
1183 if (alpha != opaque) { | |
1184 return true; | |
1185 } | |
1186 } | |
1187 return false; | |
1188 } | |
1189 | |
1190 void SkPDFShader::State::AllocateGradientInfoStorage() { | |
1191 fColorData.set(sk_malloc_throw( | |
1192 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | |
1193 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | |
1194 fInfo.fColorOffsets = | |
1195 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | |
1196 } | |
OLD | NEW |