Chromium Code Reviews| 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 "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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } | |
| OLD | NEW |