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

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

Issue 18585002: Implemented transparent gradients (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: 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
« src/pdf/SkPDFGraphicState.cpp ('K') | « src/pdf/SkPDFShader.h ('k') | no next file » | 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 "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
vandebo (ex-Chrome) 2013/07/03 17:07:01 Full sentences please.
ducky 2013/07/03 23:32:09 Done.
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,
411 const SkIRect& bbox); 414 const SkIRect& bbox);
415 State(const State& other);
vandebo (ex-Chrome) 2013/07/03 17:07:01 Make this private.
ducky 2013/07/03 23:32:09 Done.
416
417 SkPDFShader::State* CreateAlphaToRGBState() const;
vandebo (ex-Chrome) 2013/07/03 17:07:01 nit: CreateLuminosityState()?
vandebo (ex-Chrome) 2013/07/03 17:07:01 nit: Put these methods after the operator== method
ducky 2013/07/03 23:32:09 Changed to CreateAlphaToLuminosityState(). I think
ducky 2013/07/03 23:32:09 Done.
418 SkPDFShader::State* CreateOpaqueState() const;
412 bool operator==(const State& b) const; 419 bool operator==(const State& b) const;
420
421 bool GradientHasAlpha() const;
413 }; 422 };
414 423
415 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { 424 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader {
416 public: 425 public:
417 explicit SkPDFFunctionShader(SkPDFShader::State* state); 426 explicit SkPDFFunctionShader(SkPDFShader::State* state);
418 virtual ~SkPDFFunctionShader() { 427 virtual ~SkPDFFunctionShader() {
419 if (isValid()) { 428 if (isValid()) {
420 RemoveShader(this); 429 RemoveShader(this);
421 } 430 }
422 fResources.unrefAll(); 431 fResources.unrefAll();
423 } 432 }
424 433
425 virtual bool isValid() { return fResources.count() > 0; } 434 virtual bool isValid() { return fResources.count() > 0; }
426 435
427 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 436 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
428 SkTSet<SkPDFObject*>* newResourceObjects) { 437 SkTSet<SkPDFObject*>* newResourceObjects) {
429 GetResourcesHelper(&fResources, 438 GetResourcesHelper(&fResources,
430 knownResourceObjects, 439 knownResourceObjects,
431 newResourceObjects); 440 newResourceObjects);
432 } 441 }
433 442
443 SkPDFFunctionShader* CreateAlphaToRGBShader();
444
434 private: 445 private:
435 static SkPDFObject* RangeObject(); 446 static SkPDFObject* RangeObject();
436 447
437 SkTDArray<SkPDFObject*> fResources; 448 SkTDArray<SkPDFObject*> fResources;
438 SkAutoTDelete<const SkPDFShader::State> fState; 449 SkAutoTDelete<const SkPDFShader::State> fState;
439 450
440 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); 451 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain);
441 }; 452 };
442 453
454 /**
455 * A shader for PDF gradients. This encapsulates the function shader
456 * inside a tiling pattern while providing a common pattern interface.
457 * The encapsulation allows the use of a SMask for transparency gradients.
458 */
459 class SkPDFGradientShader : public SkPDFStream, public SkPDFShader {
460 public:
461 explicit SkPDFGradientShader(SkPDFShader::State* state);
462 virtual ~SkPDFGradientShader() {
463 RemoveShader(this);
464 }
465
466 virtual bool isValid() { return size() > 0; }
467
468 private:
469 SkAutoTDelete<const SkPDFShader::State> fState;
470
471 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
472 SkTSet<SkPDFObject*>* newResourceObjects) {
473 GetResourcesHelper(&fResources,
474 knownResourceObjects,
475 newResourceObjects);
476 }
477 SkTDArray<SkPDFObject*> fResources;
478
479 SkAutoTUnref<SkPDFObject> fColorPattern;
480 SkAutoTUnref<SkPDFGraphicState> fAlphaGs;
481
482 SkAutoTUnref<SkPDFDict> fResourceDict;
483 };
484
443 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { 485 class SkPDFImageShader : public SkPDFStream, public SkPDFShader {
444 public: 486 public:
445 explicit SkPDFImageShader(SkPDFShader::State* state); 487 explicit SkPDFImageShader(SkPDFShader::State* state);
446 virtual ~SkPDFImageShader() { 488 virtual ~SkPDFImageShader() {
447 RemoveShader(this); 489 RemoveShader(this);
448 fResources.unrefAll(); 490 fResources.unrefAll();
449 } 491 }
450 492
451 virtual bool isValid() { return size() > 0; } 493 virtual bool isValid() { return size() > 0; }
452 494
(...skipping 14 matching lines...) Expand all
467 // static 509 // static
468 void SkPDFShader::RemoveShader(SkPDFObject* shader) { 510 void SkPDFShader::RemoveShader(SkPDFObject* shader) {
469 SkAutoMutexAcquire lock(CanonicalShadersMutex()); 511 SkAutoMutexAcquire lock(CanonicalShadersMutex());
470 ShaderCanonicalEntry entry(shader, NULL); 512 ShaderCanonicalEntry entry(shader, NULL);
471 int index = CanonicalShaders().find(entry); 513 int index = CanonicalShaders().find(entry);
472 SkASSERT(index >= 0); 514 SkASSERT(index >= 0);
473 CanonicalShaders().removeShuffle(index); 515 CanonicalShaders().removeShuffle(index);
474 } 516 }
475 517
476 // static 518 // static
477 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, 519 // This is an internal method. CanonicalShadersMutex() should already be acquire d.
478 const SkMatrix& matrix, 520 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) {
vandebo (ex-Chrome) 2013/07/03 17:07:01 Definition order should match declaration order, s
ducky 2013/07/03 23:32:09 Done.
vandebo (ex-Chrome) 2013/07/08 19:02:25 Not done
479 const SkIRect& surfaceBBox) {
480 SkPDFObject* result; 521 SkPDFObject* result;
481 SkAutoMutexAcquire lock(CanonicalShadersMutex()); 522
482 SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox)); 523 SkAutoTDelete<State> shaderState(inState);
483 if (shaderState.get()->fType == SkShader::kNone_GradientType && 524 if (shaderState.get()->fType == SkShader::kNone_GradientType &&
484 shaderState.get()->fImage.isNull()) { 525 shaderState.get()->fImage.isNull()) {
485 // TODO(vandebo) This drops SKComposeShader on the floor. We could 526 // TODO(vandebo) This drops SKComposeShader on the floor. We could
486 // handle compose shader by pulling things up to a layer, drawing with 527 // 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 528 // the first shader, applying the xfer mode and drawing again with the
488 // second shader, then applying the layer to the original drawing. 529 // second shader, then applying the layer to the original drawing.
489 return NULL; 530 return NULL;
490 } 531 }
491 532
492 ShaderCanonicalEntry entry(NULL, shaderState.get()); 533 ShaderCanonicalEntry entry(NULL, shaderState.get());
493 int index = CanonicalShaders().find(entry); 534 int index = CanonicalShaders().find(entry);
494 if (index >= 0) { 535 if (index >= 0) {
495 result = CanonicalShaders()[index].fPDFShader; 536 result = CanonicalShaders()[index].fPDFShader;
496 result->ref(); 537 result->ref();
497 return result; 538 return result;
498 } 539 }
499 540
500 bool valid = false; 541 bool valid = false;
501 // The PDFShader takes ownership of the shaderSate. 542 // The PDFShader takes ownership of the shaderSate.
502 if (shaderState.get()->fType == SkShader::kNone_GradientType) { 543 if (shaderState.get()->fType == SkShader::kNone_GradientType) {
503 SkPDFImageShader* imageShader = 544 SkPDFImageShader* imageShader =
504 new SkPDFImageShader(shaderState.detach()); 545 new SkPDFImageShader(shaderState.detach());
505 valid = imageShader->isValid(); 546 valid = imageShader->isValid();
506 result = imageShader; 547 result = imageShader;
507 } else { 548 } else {
508 SkPDFFunctionShader* functionShader = 549 if (shaderState.get()->GradientHasAlpha()) {
509 new SkPDFFunctionShader(shaderState.detach()); 550 SkPDFGradientShader* gradientShader =
510 valid = functionShader->isValid(); 551 new SkPDFGradientShader(shaderState.detach());
511 result = functionShader; 552 valid = gradientShader->isValid();
553 result = gradientShader;
554 } else {
555 SkPDFFunctionShader* functionShader =
556 new SkPDFFunctionShader(shaderState.detach());
557 valid = functionShader->isValid();
558 result = functionShader;
559 }
512 } 560 }
513 if (!valid) { 561 if (!valid) {
514 delete result; 562 delete result;
515 return NULL; 563 return NULL;
516 } 564 }
517 entry.fPDFShader = result; 565 entry.fPDFShader = result;
518 CanonicalShaders().push(entry); 566 CanonicalShaders().push(entry);
519 return result; // return the reference that came from new. 567 return result; // return the reference that came from new.
520 } 568 }
521 569
522 // static 570 // static
571 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
572 const SkMatrix& matrix,
573 const SkIRect& surfaceBBox) {
574 SkAutoMutexAcquire lock(CanonicalShadersMutex());
575 return GetPDFShaderByState(new State(shader, matrix, surfaceBBox));
576 }
577
578 // static
523 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { 579 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() {
524 // This initialization is only thread safe with gcc. 580 // This initialization is only thread safe with gcc.
525 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; 581 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders;
526 return gCanonicalShaders; 582 return gCanonicalShaders;
527 } 583 }
528 584
529 // static 585 // static
530 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { 586 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() {
531 // This initialization is only thread safe with gcc or when 587 // This initialization is only thread safe with gcc or when
532 // POD-style mutex initialization is used. 588 // POD-style mutex initialization is used.
(...skipping 13 matching lines...) Expand all
546 range->appendInt(0); 602 range->appendInt(0);
547 range->appendInt(1); 603 range->appendInt(1);
548 range->appendInt(0); 604 range->appendInt(0);
549 range->appendInt(1); 605 range->appendInt(1);
550 range->appendInt(0); 606 range->appendInt(0);
551 range->appendInt(1); 607 range->appendInt(1);
552 } 608 }
553 return range; 609 return range;
554 } 610 }
555 611
612 static SkPDFDict* getGradientResourceDict(
613 SkPDFObject* functionShader,
614 SkPDFObject* gState) {
615 SkPDFDict* dict = new SkPDFDict();
616
617 if (functionShader != NULL) {
618 SkAutoTUnref<SkPDFDict> patterns(new SkPDFDict());
619 patterns->insert("P0", new SkPDFObjRef(functionShader))->unref();
620 dict->insert("Pattern", patterns.get());
621 }
622
623 if (gState != NULL) {
624 SkAutoTUnref<SkPDFDict> extGState(new SkPDFDict());
625 extGState->insert("G0", new SkPDFObjRef(gState))->unref();
626 dict->insert("ExtGState", extGState.get());
627 }
628
vandebo (ex-Chrome) 2013/07/03 17:07:01 Should this also include a ProcSet entry?
ducky 2013/07/03 23:32:09 Done.
629 return dict;
630 }
631
632 static void writePatternFillContent(SkWStream* content, SkRect bounds) {
633 // set pattern
634 content->writeText("/Pattern CS /Pattern cs /P0 SCN /P0 scn ");
vandebo (ex-Chrome) 2013/07/03 17:07:01 nit: omit extra whitespace.
ducky 2013/07/03 23:32:09 Done.
635 // draw rectangle and fill
636 content->writeScalarAsText(bounds.left());
vandebo (ex-Chrome) 2013/07/03 17:07:01 SkPDFUtils::AppendRectangle() SkPDFUtils::PaintPat
ducky 2013/07/03 23:32:09 Done.
637 content->writeText(" ");
638 content->writeScalarAsText(bounds.top());
639 content->writeText(" ");
640 content->writeScalarAsText(bounds.right());
641 content->writeText(" ");
642 content->writeScalarAsText(bounds.bottom());
643 content->writeText(" re f");
644 }
645
646 SkPDFGradientShader::SkPDFGradientShader(SkPDFShader::State* state) : fState(sta te) {
647 SkRect bbox;
648 bbox.set(fState.get()->fBBox);
649
650 fColorPattern.reset(SkPDFShader::GetPDFShaderByState(
651 state->CreateOpaqueState()));
652 fResources.push(fColorPattern.get());
653
654 // create alpha graphics state, including SMask and alpha luminosity pattern
655 SkAutoTUnref<SkPDFObject>
vandebo (ex-Chrome) 2013/07/03 17:07:01 nit indent: SkAutoTUnref<SkPDFObject> alphaSha
ducky 2013/07/03 23:32:09 Done.
656 alphaShader(SkPDFShader::GetPDFShaderByState(
657 state->CreateAlphaToRGBState()));
658 SkAutoTUnref<SkPDFDict>
659 alphaResources(getGradientResourceDict(alphaShader.get(), NULL));
660 SkTSet<SkPDFObject*> resourcesArray;
661 resourcesArray.add(alphaShader.get());
662
663 SkAutoTDelete<SkDynamicMemoryWStream> alphaContent(new SkDynamicMemoryWStrea m());
664 writePatternFillContent(alphaContent.get(), bbox);
665 SkAutoTUnref<SkData> alphaData(alphaContent->copyToData());
vandebo (ex-Chrome) 2013/07/03 17:07:01 This mess is caused by incomplete conversion of Sk
ducky 2013/07/03 23:32:09 Done.
666 SkAutoTUnref<SkMemoryStream> alphaStream(new SkMemoryStream());
667 alphaStream->setData(alphaData.get());
668 SkAutoTUnref<SkPDFFormXObject>
669 alphaMask(new SkPDFFormXObject(alphaStream.get(), alphaResources.get(), resourcesArray, bbox));
670
671 fAlphaGs.reset(SkPDFGraphicState::GetSMaskGraphicState(alphaMask.get(), fals e, false));
vandebo (ex-Chrome) 2013/07/03 17:07:01 Not sure, but I think you want to pull this all ou
ducky 2013/07/03 23:32:09 Done.
672 fResources.push(fAlphaGs.get());
673
674 fResourceDict.reset(getGradientResourceDict(fColorPattern.get(), fAlphaGs.ge t()));
675
676 SkAutoTUnref<SkPDFArray> bboxArray(new SkPDFArray);
vandebo (ex-Chrome) 2013/07/03 17:07:01 Use rectToArray here as well.
ducky 2013/07/03 23:32:09 Done.
677 bboxArray->reserve(4);
678 bboxArray->appendScalar(bbox.fLeft);
679 bboxArray->appendScalar(bbox.fTop);
680 bboxArray->appendScalar(bbox.fRight);
681 bboxArray->appendScalar(bbox.fBottom);
682
683 SkAutoTDelete<SkDynamicMemoryWStream> colorContent(new SkDynamicMemoryWStrea m());
684 colorContent->writeText("/G0 gs ");
685 writePatternFillContent(colorContent.get(), bbox);
vandebo (ex-Chrome) 2013/07/03 17:07:01 Make this method return an SkDyrnamicMemoryWStream
ducky 2013/07/03 23:32:09 Done.
686 SkAutoTUnref<SkData> colorData(colorContent->copyToData());
687 SkAutoTUnref<SkMemoryStream> colorStream(new SkMemoryStream());
688 colorStream->setData(colorData.get());
689 setData(colorStream.get());
690
691 insertName("Type", "Pattern");
vandebo (ex-Chrome) 2013/07/03 17:07:01 Most of this can get pulled out and shared with Sk
ducky 2013/07/03 23:32:09 Done.
692 insertInt("PatternType", 1);
693 insertInt("PaintType", 1);
694 insertInt("TilingType", 1);
695 insert("BBox", bboxArray.get());
696 insertScalar("XStep", bbox.width());
697 insertScalar("YStep", bbox.height());
698 insert("Resources", fResourceDict.get());
699 }
700
556 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) 701 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state)
557 : SkPDFDict("Pattern"), 702 : SkPDFDict("Pattern"),
558 fState(state) { 703 fState(state) {
559 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; 704 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL;
560 SkPoint transformPoints[2]; 705 SkPoint transformPoints[2];
561 706
562 // Depending on the type of the gradient, we want to transform the 707 // Depending on the type of the gradient, we want to transform the
563 // coordinate space in different ways. 708 // coordinate space in different ways.
564 const SkShader::GradientInfo* info = &fState.get()->fInfo; 709 const SkShader::GradientInfo* info = &fState.get()->fInfo;
565 transformPoints[0] = info->fPoint[0]; 710 transformPoints[0] = info->fPoint[0];
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 797
653 SkPDFStream* function = makePSFunction(functionCode, domain.get()); 798 SkPDFStream* function = makePSFunction(functionCode, domain.get());
654 pdfShader->insert("Function", new SkPDFObjRef(function))->unref(); 799 pdfShader->insert("Function", new SkPDFObjRef(function))->unref();
655 fResources.push(function); // Pass ownership to resource list. 800 fResources.push(function); // Pass ownership to resource list.
656 801
657 insertInt("PatternType", 2); 802 insertInt("PatternType", 2);
658 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); 803 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref();
659 insert("Shading", pdfShader.get()); 804 insert("Shading", pdfShader.get());
660 } 805 }
661 806
807 /**
808 * Creates a copy of this gradient PDF shader, with the alpha channel
809 * mapped to RGB luminosity. Intended to be used as a SMask for gradients
810 * with transparency.
811 */
812 SkPDFFunctionShader* SkPDFFunctionShader::CreateAlphaToRGBShader() {
vandebo (ex-Chrome) 2013/07/03 17:07:01 This isn't used, remove.
ducky 2013/07/03 23:32:09 D'oh.
813 // copy the current state, allocating new storage
814 return new SkPDFFunctionShader(fState.get()->CreateAlphaToRGBState());
815 }
816
662 SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { 817 SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) {
663 fState.get()->fImage.lockPixels(); 818 fState.get()->fImage.lockPixels();
664 819
665 SkMatrix finalMatrix = fState.get()->fCanvasTransform; 820 SkMatrix finalMatrix = fState.get()->fCanvasTransform;
vandebo (ex-Chrome) 2013/07/03 17:07:01 Do you not need to do this stuff for the gradient
ducky 2013/07/03 23:32:09 Matrix transforms are handled in the color and alp
666 finalMatrix.preConcat(fState.get()->fShaderTransform); 821 finalMatrix.preConcat(fState.get()->fShaderTransform);
667 SkRect surfaceBBox; 822 SkRect surfaceBBox;
668 surfaceBBox.set(fState.get()->fBBox); 823 surfaceBBox.set(fState.get()->fBBox);
669 if (!transformBBox(finalMatrix, &surfaceBBox)) { 824 if (!transformBBox(finalMatrix, &surfaceBBox)) {
670 return; 825 return;
671 } 826 }
672 827
673 SkMatrix unflip; 828 SkMatrix unflip;
674 unflip.setTranslate(0, SkScalarRoundToScalar(surfaceBBox.height())); 829 unflip.setTranslate(0, SkScalarRoundToScalar(surfaceBBox.height()));
675 unflip.preScale(SK_Scalar1, -SK_Scalar1); 830 unflip.preScale(SK_Scalar1, -SK_Scalar1);
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 fPixelGeneration = fImage.getGenerationID(); 1110 fPixelGeneration = fImage.getGenerationID();
956 } else { 1111 } else {
957 fColorData.set(sk_malloc_throw( 1112 fColorData.set(sk_malloc_throw(
958 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); 1113 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
959 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); 1114 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
960 fInfo.fColorOffsets = 1115 fInfo.fColorOffsets =
961 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); 1116 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount);
962 shader.asAGradient(&fInfo); 1117 shader.asAGradient(&fInfo);
963 } 1118 }
964 } 1119 }
1120
1121 SkPDFShader::State::State(const SkPDFShader::State& other)
1122 : fType(other.fType),
1123 fCanvasTransform(other.fCanvasTransform),
1124 fShaderTransform(other.fShaderTransform),
1125 fBBox(other.fBBox)
vandebo (ex-Chrome) 2013/07/03 17:07:01 Also need to copy over fImageTileModes
ducky 2013/07/03 23:32:09 That seems to be for image shaders only, and that
1126 {
1127 if (fType != SkShader::kNone_GradientType) {
1128 fInfo = other.fInfo;
1129
1130 // allocate new storage to prevent pointer aliasing
vandebo (ex-Chrome) 2013/07/03 17:07:01 nit: comment unnecessary.
ducky 2013/07/03 23:32:09 I would actually say that this piece of code is pr
1131 fColorData.set(sk_malloc_throw(
vandebo (ex-Chrome) 2013/07/03 17:07:01 All this allocation is the same as the other const
ducky 2013/07/03 23:32:09 Done.
1132 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
1133 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
1134 fInfo.fColorOffsets =
1135 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColor Count);
1136 for (int i = 0; i < fInfo.fColorCount; i++) {
1137 fInfo.fColors[i] = other.fInfo.fColors[i];
1138 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i];
1139 }
1140 } else {
1141 // if needed, image state copy constructor can be added here later...
1142 // but only gradients supported for now
1143 SkASSERT(fType != SkShader::kNone_GradientType);
vandebo (ex-Chrome) 2013/07/03 17:07:01 Put this after line 1126
ducky 2013/07/03 23:32:09 Done.
1144 }
1145 }
1146
1147 /**
1148 * Create a copy of this gradient state with alpha assigned to RGB luminousity.
1149 * Only valid for gradient states!
1150 */
1151 SkPDFShader::State* SkPDFShader::State::CreateAlphaToRGBState() const {
1152 SkASSERT(fType != SkShader::kNone_GradientType);
1153
1154 SkPDFShader::State* newState = new SkPDFShader::State(*this);
1155
1156 for (int i = 0; i < fInfo.fColorCount; i++) {
1157 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]);
1158 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha);
1159 }
1160
1161 return newState;
1162 }
1163
1164 /**
1165 * Create a copy of this gradient state with alpha set to fully opaque
1166 * Only valid for gradient states!
1167 */
1168 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const {
1169 SkASSERT(fType != SkShader::kNone_GradientType);
1170
1171 SkPDFShader::State* newState = new SkPDFShader::State(*this);
1172 SkAlpha opaque = SkColorGetA(SK_ColorBLACK);
1173 for (int i = 0; i < fInfo.fColorCount; i++) {
1174 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], opaque);
1175 }
1176
1177 return newState;
1178 }
1179
1180 /**
1181 * Returns true if state is a gradient and the gradient has alpha.
1182 */
1183 bool SkPDFShader::State::GradientHasAlpha() const {
1184 if (fType == SkShader::kNone_GradientType) {
1185 return false;
1186 }
1187
1188 SkAlpha opaque = SkColorGetA(SK_ColorBLACK);
1189 for (int i = 1; i < fInfo.fColorCount; i++) {
1190 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]);
1191 if (alpha != opaque) {
1192 return true;
1193 }
1194 }
1195 return false;
1196 }
OLDNEW
« src/pdf/SkPDFGraphicState.cpp ('K') | « src/pdf/SkPDFShader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698