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

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

Issue 18585002: Implemented transparent gradients (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Fixes isValid() in SkPDFGradientShader, fixes tinybitmap regression 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
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 "SkPDFFormXObject.h"
17 #include "SkPDFGraphicState.h"
16 #include "SkPDFTypes.h" 18 #include "SkPDFTypes.h"
17 #include "SkPDFUtils.h" 19 #include "SkPDFUtils.h"
18 #include "SkScalar.h" 20 #include "SkScalar.h"
19 #include "SkStream.h" 21 #include "SkStream.h"
20 #include "SkTemplates.h" 22 #include "SkTemplates.h"
21 #include "SkThread.h" 23 #include "SkThread.h"
24 #include "SkTSet.h"
22 #include "SkTypes.h" 25 #include "SkTypes.h"
23 26
24 static bool transformBBox(const SkMatrix& matrix, SkRect* bbox) { 27 static bool transformBBox(const SkMatrix& matrix, SkRect* bbox) {
25 SkMatrix inverse; 28 SkMatrix inverse;
26 if (!matrix.invert(&inverse)) { 29 if (!matrix.invert(&inverse)) {
27 return false; 30 return false;
28 } 31 }
29 inverse.mapRect(bbox); 32 inverse.mapRect(bbox);
30 return true; 33 return true;
31 } 34 }
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 tileModeCode(info.fTileMode, &function); 394 tileModeCode(info.fTileMode, &function);
392 gradientFunctionCode(info, &function); 395 gradientFunctionCode(info, &function);
393 function.append("}"); 396 function.append("}");
394 return function; 397 return function;
395 } 398 }
396 399
397 class SkPDFShader::State { 400 class SkPDFShader::State {
398 public: 401 public:
399 SkShader::GradientType fType; 402 SkShader::GradientType fType;
400 SkShader::GradientInfo fInfo; 403 SkShader::GradientInfo fInfo;
401 SkAutoFree fColorData; 404 SkAutoFree fColorData; // This provides storage for arrays in fInfo.
402 SkMatrix fCanvasTransform; 405 SkMatrix fCanvasTransform;
403 SkMatrix fShaderTransform; 406 SkMatrix fShaderTransform;
404 SkIRect fBBox; 407 SkIRect fBBox;
405 408
406 SkBitmap fImage; 409 SkBitmap fImage;
407 uint32_t fPixelGeneration; 410 uint32_t fPixelGeneration;
408 SkShader::TileMode fImageTileModes[2]; 411 SkShader::TileMode fImageTileModes[2];
409 412
410 explicit State(const SkShader& shader, const SkMatrix& canvasTransform, 413 explicit State(const SkShader& shader, const SkMatrix& canvasTransform,
vandebo (ex-Chrome) 2013/07/08 19:02:25 nit: remove explicit
ducky 2013/07/09 02:56:23 Done.
411 const SkIRect& bbox); 414 const SkIRect& bbox);
415
412 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);
vandebo (ex-Chrome) 2013/07/08 19:02:25 The Rule of three says you should also declare an
ducky 2013/07/09 02:56:23 Done.
425 void AllocateGradientInfoStorage();
413 }; 426 };
414 427
415 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { 428 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader {
416 public: 429 public:
417 explicit SkPDFFunctionShader(SkPDFShader::State* state); 430 explicit SkPDFFunctionShader(SkPDFShader::State* state);
418 virtual ~SkPDFFunctionShader() { 431 virtual ~SkPDFFunctionShader() {
419 if (isValid()) { 432 if (isValid()) {
420 RemoveShader(this); 433 RemoveShader(this);
421 } 434 }
422 fResources.unrefAll(); 435 fResources.unrefAll();
423 } 436 }
424 437
425 virtual bool isValid() { return fResources.count() > 0; } 438 virtual bool isValid() { return fResources.count() > 0; }
426 439
427 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 440 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
428 SkTSet<SkPDFObject*>* newResourceObjects) { 441 SkTSet<SkPDFObject*>* newResourceObjects) {
429 GetResourcesHelper(&fResources, 442 GetResourcesHelper(&fResources,
430 knownResourceObjects, 443 knownResourceObjects,
431 newResourceObjects); 444 newResourceObjects);
432 } 445 }
433 446
447 SkPDFFunctionShader* CreateAlphaToLuminosityShader();
vandebo (ex-Chrome) 2013/07/08 19:02:25 unused
ducky 2013/07/09 02:56:23 Done.
448
434 private: 449 private:
435 static SkPDFObject* RangeObject(); 450 static SkPDFObject* RangeObject();
436 451
437 SkTDArray<SkPDFObject*> fResources; 452 SkTDArray<SkPDFObject*> fResources;
438 SkAutoTDelete<const SkPDFShader::State> fState; 453 SkAutoTDelete<const SkPDFShader::State> fState;
439 454
440 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); 455 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain);
441 }; 456 };
442 457
458 /**
459 * A shader for PDF gradients. This encapsulates the function shader
460 * inside a tiling pattern while providing a common pattern interface.
461 * The encapsulation allows the use of a SMask for transparency gradients.
462 */
463 class SkPDFGradientShader : public SkPDFStream, public SkPDFShader {
vandebo (ex-Chrome) 2013/07/08 19:02:25 nit: There's probably a better name for this... Fu
ducky 2013/07/09 02:56:23 There probably is a better name. SkPDFAlphaGradien
vandebo (ex-Chrome) 2013/07/09 17:47:44 SkPDFFunctionShaderWithAlpha ?
ducky 2013/07/10 21:42:26 Also pretty long... how about SkPDFAlphaFunctionSh
vandebo (ex-Chrome) 2013/07/11 22:22:23 SGTM
464 public:
465 explicit SkPDFGradientShader(SkPDFShader::State* state);
466 virtual ~SkPDFGradientShader() {
467 if (isValid()) {
468 RemoveShader(this);
469 }
470 }
471
472 virtual bool isValid() {
473 return fColorPattern.get() != NULL;
474 }
475
476 private:
477 SkAutoTDelete<const SkPDFShader::State> fState;
478
479 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
480 SkTSet<SkPDFObject*>* newResourceObjects) {
481 fResourceDict->getResources(knownResourceObjects,
482 newResourceObjects);
483 }
484
485 SkAutoTUnref<SkPDFObject> fColorPattern;
486 SkAutoTUnref<SkPDFGraphicState> fAlphaGs;
487
488 SkAutoTUnref<SkPDFResourceDict> fResourceDict;
489 };
490
443 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { 491 class SkPDFImageShader : public SkPDFStream, public SkPDFShader {
444 public: 492 public:
445 explicit SkPDFImageShader(SkPDFShader::State* state); 493 explicit SkPDFImageShader(SkPDFShader::State* state);
446 virtual ~SkPDFImageShader() { 494 virtual ~SkPDFImageShader() {
447 RemoveShader(this); 495 RemoveShader(this);
448 fResources.unrefAll(); 496 fResources.unrefAll();
449 } 497 }
450 498
451 virtual bool isValid() { return size() > 0; } 499 virtual bool isValid() { return size() > 0; }
452 500
(...skipping 17 matching lines...) Expand all
470 ShaderCanonicalEntry entry(shader, NULL); 518 ShaderCanonicalEntry entry(shader, NULL);
471 int index = CanonicalShaders().find(entry); 519 int index = CanonicalShaders().find(entry);
472 SkASSERT(index >= 0); 520 SkASSERT(index >= 0);
473 CanonicalShaders().removeShuffle(index); 521 CanonicalShaders().removeShuffle(index);
474 } 522 }
475 523
476 // static 524 // static
477 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, 525 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
478 const SkMatrix& matrix, 526 const SkMatrix& matrix,
479 const SkIRect& surfaceBBox) { 527 const SkIRect& surfaceBBox) {
528 SkAutoMutexAcquire lock(CanonicalShadersMutex());
529 return GetPDFShaderByState(new State(shader, matrix, surfaceBBox));
530 }
531
532 // static
533 // This is an internal method. CanonicalShadersMutex() should already be acquire d.
vandebo (ex-Chrome) 2013/07/08 19:02:25 Also comment that this method takes ownership of |
ducky 2013/07/09 02:56:23 Done.
534 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) {
480 SkPDFObject* result; 535 SkPDFObject* result;
481 SkAutoMutexAcquire lock(CanonicalShadersMutex()); 536
482 SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox)); 537 SkAutoTDelete<State> shaderState(inState);
483 if (shaderState.get()->fType == SkShader::kNone_GradientType && 538 if (shaderState.get()->fType == SkShader::kNone_GradientType &&
484 shaderState.get()->fImage.isNull()) { 539 shaderState.get()->fImage.isNull()) {
485 // TODO(vandebo) This drops SKComposeShader on the floor. We could 540 // TODO(vandebo) This drops SKComposeShader on the floor. We could
486 // handle compose shader by pulling things up to a layer, drawing with 541 // handle compose shader by pulling things up to a layer, drawing with
487 // the first shader, applying the xfer mode and drawing again with the 542 // the first shader, applying the xfer mode and drawing again with the
488 // second shader, then applying the layer to the original drawing. 543 // second shader, then applying the layer to the original drawing.
489 return NULL; 544 return NULL;
490 } 545 }
491 546
492 ShaderCanonicalEntry entry(NULL, shaderState.get()); 547 ShaderCanonicalEntry entry(NULL, shaderState.get());
493 int index = CanonicalShaders().find(entry); 548 int index = CanonicalShaders().find(entry);
494 if (index >= 0) { 549 if (index >= 0) {
495 result = CanonicalShaders()[index].fPDFShader; 550 result = CanonicalShaders()[index].fPDFShader;
496 result->ref(); 551 result->ref();
497 return result; 552 return result;
498 } 553 }
499 554
500 bool valid = false; 555 bool valid = false;
501 // The PDFShader takes ownership of the shaderSate. 556 // The PDFShader takes ownership of the shaderSate.
502 if (shaderState.get()->fType == SkShader::kNone_GradientType) { 557 if (shaderState.get()->fType == SkShader::kNone_GradientType) {
503 SkPDFImageShader* imageShader = 558 SkPDFImageShader* imageShader =
504 new SkPDFImageShader(shaderState.detach()); 559 new SkPDFImageShader(shaderState.detach());
505 valid = imageShader->isValid(); 560 valid = imageShader->isValid();
506 result = imageShader; 561 result = imageShader;
507 } else { 562 } else {
508 SkPDFFunctionShader* functionShader = 563 if (shaderState.get()->GradientHasAlpha()) {
509 new SkPDFFunctionShader(shaderState.detach()); 564 SkPDFGradientShader* gradientShader =
510 valid = functionShader->isValid(); 565 new SkPDFGradientShader(shaderState.detach());
511 result = functionShader; 566 valid = gradientShader->isValid();
567 result = gradientShader;
568 } else {
569 SkPDFFunctionShader* functionShader =
570 new SkPDFFunctionShader(shaderState.detach());
571 valid = functionShader->isValid();
572 result = functionShader;
573 }
512 } 574 }
513 if (!valid) { 575 if (!valid) {
514 delete result; 576 delete result;
515 return NULL; 577 return NULL;
516 } 578 }
517 entry.fPDFShader = result; 579 entry.fPDFShader = result;
518 CanonicalShaders().push(entry); 580 CanonicalShaders().push(entry);
519 return result; // return the reference that came from new. 581 return result; // return the reference that came from new.
520 } 582 }
521 583
(...skipping 24 matching lines...) Expand all
546 range->appendInt(0); 608 range->appendInt(0);
547 range->appendInt(1); 609 range->appendInt(1);
548 range->appendInt(0); 610 range->appendInt(0);
549 range->appendInt(1); 611 range->appendInt(1);
550 range->appendInt(0); 612 range->appendInt(0);
551 range->appendInt(1); 613 range->appendInt(1);
552 } 614 }
553 return range; 615 return range;
554 } 616 }
555 617
618 static SkPDFResourceDict* getGradientResourceDict(
vandebo (ex-Chrome) 2013/07/08 19:02:25 static helper functions are named with underscores
ducky 2013/07/09 02:56:23 Done. Though the functions generating postscript c
vandebo (ex-Chrome) 2013/07/09 17:47:44 That was before the style guide was codified. You
619 SkPDFObject* functionShader,
620 SkPDFObject* gState) {
621 SkPDFResourceDict* dict = new SkPDFResourceDict();
622
623 if (functionShader != NULL) {
624 dict->insertResourceAsRef("Pattern", "P0", functionShader);
625 }
626 if (gState != NULL) {
627 dict->insertResourceAsRef("ExtGState", "G0", gState);
628 }
629
630 dict->insert("ProcSet", SkPDFUtils::CreateFullProcSetsArray())->unref();
vandebo (ex-Chrome) 2013/07/08 19:02:25 Is this needed, I wasn't sure if it was. If it is
ducky 2013/07/09 02:56:23 ProcSet is no longer used in current versions of t
vandebo (ex-Chrome) 2013/07/09 17:47:44 Well, it's optimizing for size. Though I guess th
631
632 return dict;
633 }
634
635 static void populateTilingPatternDict(SkPDFDict* pattern,
vandebo (ex-Chrome) 2013/07/08 19:02:25 Here too and below...
ducky 2013/07/09 02:56:23 Done.
636 SkRect& bbox, SkPDFDict* resources,
637 const SkMatrix& matrix) {
638 pattern->insertName("Type", "Pattern");
639 pattern->insertInt("PatternType", 1);
640 pattern->insertInt("PaintType", 1);
641 pattern->insertInt("TilingType", 1);
642 pattern->insert("BBox", SkPDFUtils::RectToArray(bbox))->unref();
643 pattern->insertScalar("XStep", bbox.width());
644 pattern->insertScalar("YStep", bbox.height());
645 pattern->insert("Resources", resources);
646 if (!matrix.isIdentity()) {
647 pattern->insert("Matrix", SkPDFUtils::MatrixToArray(matrix))->unref();
648 }
649 }
650
651 /**
652 * Creates a content stream which fills the pattern P0 across bounds.
653 * If setGs0 is true, this additionally sets the graphics state to G0.
654 */
655 static SkData* createPatternFillContent(bool setGs0, SkRect& bounds) {
vandebo (ex-Chrome) 2013/07/08 19:02:25 setGs0 feels odd. Maybe pass a SkString stream_se
ducky 2013/07/09 02:56:23 Done. Yeah, that was ugly.
656 SkDynamicMemoryWStream content;
657 if (setGs0) {
658 content.writeText("/G0 gs");
659 }
660 content.writeText("/Pattern CS/Pattern cs/P0 SCN/P0 scn\n");
661
662 SkPDFUtils::AppendRectangle(bounds, &content);
663 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, &cont ent);
664
665 return content.copyToData();
666 }
667
668 /**
669 * Creates a ExtGState with the SMask set to the luminosityShader in
670 * luminosity mode. The shader pattern extends to the bbox.
671 */
672 static SkPDFGraphicState* createSMaskGraphicState(SkPDFObject* luminosityShader, SkRect& bbox) {
vandebo (ex-Chrome) 2013/07/08 19:02:25 I think if this function takes ownership of |lumin
ducky 2013/07/09 02:56:23 But doesn't that just shift the unref code from th
vandebo (ex-Chrome) 2013/07/09 17:47:44 Fair. What about making it a member of the class a
ducky 2013/07/10 21:42:26 That also seems a bit inelegant, where you have on
vandebo (ex-Chrome) 2013/07/11 22:22:23 You're only thinking of it as a helper function be
ducky 2013/07/12 03:39:59 Ah, I see. Done. On 2013/07/11 22:22:23, vandebo
673 SkAutoTUnref<SkPDFResourceDict>
vandebo (ex-Chrome) 2013/07/08 19:02:25 Move this to line 679. - Generally, define variabl
ducky 2013/07/09 02:56:23 Done.
674 resources(getGradientResourceDict(luminosityShader, NULL));
675 SkTSet<SkPDFObject*> resourcesArray;
vandebo (ex-Chrome) 2013/07/08 19:02:25 This isn't used...
ducky 2013/07/09 02:56:23 Done.
676 resourcesArray.add(luminosityShader);
677
678 SkAutoTUnref<SkData> alphaData(createPatternFillContent(false, bbox));
vandebo (ex-Chrome) 2013/07/08 19:02:25 Event though this is of type SkData, I would call
ducky 2013/07/09 02:56:23 Done, and similarly for colorStream below.
679
680 SkAutoTUnref<SkPDFFormXObject> alphaMask(
681 new SkPDFFormXObject(alphaData.get(), bbox, resources.get()));
682
683 return SkPDFGraphicState::GetSMaskGraphicState(
684 alphaMask.get(), false,
685 SkPDFGraphicState::kLuminosity_SMaskMode);
686 }
687
688 SkPDFGradientShader::SkPDFGradientShader(SkPDFShader::State* state) : fState(sta te) {
689 SkRect bbox;
690 bbox.set(fState.get()->fBBox);
691
692 fColorPattern.reset(SkPDFShader::GetPDFShaderByState(state->CreateOpaqueStat e()));
693
694 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState(
695 state->CreateAlphaToLuminosityState()));
696 fAlphaGs.reset(createSMaskGraphicState(luminosityShader.get(), bbox));
697
698 fResourceDict.reset(getGradientResourceDict(fColorPattern.get(), fAlphaGs.ge t()));
699
700 SkAutoTUnref<SkData> colorData(createPatternFillContent(true, bbox));
701 setData(colorData.get());
vandebo (ex-Chrome) 2013/07/08 19:02:25 Can you combine lines 700 and 701?
ducky 2013/07/09 02:56:23 Not unless the definition for setData is changed t
vandebo (ex-Chrome) 2013/07/09 17:47:44 Fair.
ducky 2013/07/10 21:42:26 setData could return its input parameter (which in
vandebo (ex-Chrome) 2013/07/11 22:22:23 If you like.
ducky 2013/07/12 03:39:59 Actually, I think I'm going to leave this as-is. I
702
703 populateTilingPatternDict(this, bbox, fResourceDict.get(), SkMatrix::I());
704 }
705
556 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) 706 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state)
557 : SkPDFDict("Pattern"), 707 : SkPDFDict("Pattern"),
558 fState(state) { 708 fState(state) {
559 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; 709 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL;
560 SkPoint transformPoints[2]; 710 SkPoint transformPoints[2];
561 711
562 // Depending on the type of the gradient, we want to transform the 712 // Depending on the type of the gradient, we want to transform the
563 // coordinate space in different ways. 713 // coordinate space in different ways.
564 const SkShader::GradientInfo* info = &fState.get()->fInfo; 714 const SkShader::GradientInfo* info = &fState.get()->fInfo;
565 transformPoints[0] = info->fPoint[0]; 715 transformPoints[0] = info->fPoint[0];
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 971
822 if (tileModes[0] == SkShader::kMirror_TileMode) { 972 if (tileModes[0] == SkShader::kMirror_TileMode) {
823 bottomMatrix.postScale(-1, 1); 973 bottomMatrix.postScale(-1, 1);
824 bottomMatrix.postTranslate(2 * width, 0); 974 bottomMatrix.postTranslate(2 * width, 0);
825 canvas.drawBitmapMatrix(bottom, bottomMatrix); 975 canvas.drawBitmapMatrix(bottom, bottomMatrix);
826 } 976 }
827 patternBBox.fBottom = surfaceBBox.height(); 977 patternBBox.fBottom = surfaceBBox.height();
828 } 978 }
829 } 979 }
830 980
831 SkAutoTUnref<SkPDFArray> patternBBoxArray(new SkPDFArray);
832 patternBBoxArray->reserve(4);
833 patternBBoxArray->appendScalar(patternBBox.fLeft);
834 patternBBoxArray->appendScalar(patternBBox.fTop);
835 patternBBoxArray->appendScalar(patternBBox.fRight);
836 patternBBoxArray->appendScalar(patternBBox.fBottom);
837
838 // Put the canvas into the pattern stream (fContent). 981 // Put the canvas into the pattern stream (fContent).
839 SkAutoTUnref<SkStream> content(pattern.content()); 982 SkAutoTUnref<SkStream> content(pattern.content());
840 setData(content.get()); 983 setData(content.get());
841 pattern.getResources(fResources, &fResources, false); 984 pattern.getResources(fResources, &fResources, false);
842 985
843 insertName("Type", "Pattern"); 986 populateTilingPatternDict(this, patternBBox,
844 insertInt("PatternType", 1); 987 pattern.getResourceDict(), finalMatrix);
845 insertInt("PaintType", 1);
846 insertInt("TilingType", 1);
847 insert("BBox", patternBBoxArray.get());
848 insertScalar("XStep", patternBBox.width());
849 insertScalar("YStep", patternBBox.height());
850 insert("Resources", pattern.getResourceDict());
851 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref();
852 988
853 fState.get()->fImage.unlockPixels(); 989 fState.get()->fImage.unlockPixels();
854 } 990 }
855 991
856 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, 992 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode,
857 SkPDFArray* domain) { 993 SkPDFArray* domain) {
858 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), 994 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(),
859 psCode.size())); 995 psCode.size()));
860 SkPDFStream* result = new SkPDFStream(funcData.get()); 996 SkPDFStream* result = new SkPDFStream(funcData.get());
861 result->insertInt("FunctionType", 4); 997 result->insertInt("FunctionType", 4);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 SkShader::BitmapType bitmapType; 1083 SkShader::BitmapType bitmapType;
948 SkMatrix matrix; 1084 SkMatrix matrix;
949 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); 1085 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes);
950 if (bitmapType != SkShader::kDefault_BitmapType) { 1086 if (bitmapType != SkShader::kDefault_BitmapType) {
951 fImage.reset(); 1087 fImage.reset();
952 return; 1088 return;
953 } 1089 }
954 SkASSERT(matrix.isIdentity()); 1090 SkASSERT(matrix.isIdentity());
955 fPixelGeneration = fImage.getGenerationID(); 1091 fPixelGeneration = fImage.getGenerationID();
956 } else { 1092 } else {
957 fColorData.set(sk_malloc_throw( 1093 AllocateGradientInfoStorage();
958 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
959 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
960 fInfo.fColorOffsets =
961 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount);
962 shader.asAGradient(&fInfo); 1094 shader.asAGradient(&fInfo);
963 } 1095 }
964 } 1096 }
1097
1098 SkPDFShader::State::State(const SkPDFShader::State& other)
1099 : fType(other.fType),
1100 fCanvasTransform(other.fCanvasTransform),
1101 fShaderTransform(other.fShaderTransform),
1102 fBBox(other.fBBox)
1103 {
1104 // Only gradients supported for now, since that is all that is used.
1105 // If needed, image state copy constructor can be added here later.
1106 SkASSERT(fType != SkShader::kNone_GradientType);
1107
1108 if (fType != SkShader::kNone_GradientType) {
1109 fInfo = other.fInfo;
1110
1111 AllocateGradientInfoStorage();
1112 for (int i = 0; i < fInfo.fColorCount; i++) {
1113 fInfo.fColors[i] = other.fInfo.fColors[i];
1114 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i];
1115 }
1116 }
1117 }
1118
1119 /**
1120 * Create a copy of this gradient state with alpha assigned to RGB luminousity.
1121 * Only valid for gradient states!
vandebo (ex-Chrome) 2013/07/08 19:02:25 nit: ! not needed, a . will suffice.
ducky 2013/07/09 02:56:23 Done.
vandebo (ex-Chrome) 2013/07/09 17:47:44 Not done.
ducky 2013/07/10 21:42:26 No, it is done. I think you're looking at an outda
vandebo (ex-Chrome) 2013/07/11 22:22:23 In patch set 5 (and 7) line 1120 (1123) has a !
ducky 2013/07/12 03:39:59 I see. There were two. D'oh.
1122 */
1123 SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const {
1124 SkASSERT(fType != SkShader::kNone_GradientType);
1125
1126 SkPDFShader::State* newState = new SkPDFShader::State(*this);
1127
1128 for (int i = 0; i < fInfo.fColorCount; i++) {
1129 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]);
1130 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha);
1131 }
1132
1133 return newState;
1134 }
1135
1136 /**
1137 * Create a copy of this gradient state with alpha set to fully opaque
1138 * Only valid for gradient states!
1139 */
1140 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const {
1141 SkASSERT(fType != SkShader::kNone_GradientType);
1142
1143 SkPDFShader::State* newState = new SkPDFShader::State(*this);
1144 SkAlpha opaque = SkColorGetA(SK_ColorBLACK);
1145 for (int i = 0; i < fInfo.fColorCount; i++) {
1146 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], opaque);
1147 }
1148
1149 return newState;
1150 }
1151
1152 /**
1153 * Returns true if state is a gradient and the gradient has alpha.
1154 */
1155 bool SkPDFShader::State::GradientHasAlpha() const {
1156 if (fType == SkShader::kNone_GradientType) {
1157 return false;
1158 }
1159
1160 SkAlpha opaque = SkColorGetA(SK_ColorBLACK);
1161 for (int i = 0; i < fInfo.fColorCount; i++) {
1162 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]);
1163 if (alpha != opaque) {
1164 return true;
1165 }
1166 }
1167 return false;
1168 }
1169
1170 void SkPDFShader::State::AllocateGradientInfoStorage() {
1171 fColorData.set(sk_malloc_throw(
1172 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
1173 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
1174 fInfo.fColorOffsets =
1175 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCoun t);
1176 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698