Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Side by Side Diff: src/pdf/SkPDFShader.cpp

Issue 18585002: Implemented transparent gradients (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Merge new SkPDFResourceDict method names Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/pdf/SkPDFShader.h ('k') | src/pdf/SkPDFUtils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFShader.h ('k') | src/pdf/SkPDFUtils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698