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. |
| 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 State(const SkShader& shader, const SkMatrix& canvasTransform, |
| 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); | |
| 425 State operator=(const State& rhs) { return State(rhs); } | |
|
vandebo (ex-Chrome)
2013/07/09 17:47:44
I don't think you need an implementation.
ducky
2013/07/10 21:42:26
Wait, wha?
So I need an assignment operator, but i
vandebo (ex-Chrome)
2013/07/11 22:22:23
See http://google-styleguide.googlecode.com/svn/tr
ducky
2013/07/12 03:40:00
Done.
| |
| 426 void AllocateGradientInfoStorage(); | |
| 413 }; | 427 }; |
| 414 | 428 |
| 415 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { | 429 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { |
| 416 public: | 430 public: |
| 417 explicit SkPDFFunctionShader(SkPDFShader::State* state); | 431 explicit SkPDFFunctionShader(SkPDFShader::State* state); |
| 418 virtual ~SkPDFFunctionShader() { | 432 virtual ~SkPDFFunctionShader() { |
| 419 if (isValid()) { | 433 if (isValid()) { |
| 420 RemoveShader(this); | 434 RemoveShader(this); |
| 421 } | 435 } |
| 422 fResources.unrefAll(); | 436 fResources.unrefAll(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 433 | 447 |
| 434 private: | 448 private: |
| 435 static SkPDFObject* RangeObject(); | 449 static SkPDFObject* RangeObject(); |
| 436 | 450 |
| 437 SkTDArray<SkPDFObject*> fResources; | 451 SkTDArray<SkPDFObject*> fResources; |
| 438 SkAutoTDelete<const SkPDFShader::State> fState; | 452 SkAutoTDelete<const SkPDFShader::State> fState; |
| 439 | 453 |
| 440 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); | 454 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); |
| 441 }; | 455 }; |
| 442 | 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 SkPDFGradientShader : public SkPDFStream, public SkPDFShader { | |
| 463 public: | |
| 464 explicit SkPDFGradientShader(SkPDFShader::State* state); | |
| 465 virtual ~SkPDFGradientShader() { | |
| 466 if (isValid()) { | |
| 467 RemoveShader(this); | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 virtual bool isValid() { | |
| 472 return fColorPattern.get() != NULL; | |
| 473 } | |
| 474 | |
| 475 private: | |
| 476 SkAutoTDelete<const SkPDFShader::State> fState; | |
| 477 | |
| 478 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | |
| 479 SkTSet<SkPDFObject*>* newResourceObjects) { | |
| 480 fResourceDict->getResources(knownResourceObjects, | |
| 481 newResourceObjects); | |
| 482 } | |
| 483 | |
| 484 SkAutoTUnref<SkPDFObject> fColorPattern; | |
| 485 SkAutoTUnref<SkPDFGraphicState> fAlphaGs; | |
| 486 | |
| 487 SkAutoTUnref<SkPDFResourceDict> fResourceDict; | |
| 488 }; | |
| 489 | |
| 443 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { | 490 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { |
| 444 public: | 491 public: |
| 445 explicit SkPDFImageShader(SkPDFShader::State* state); | 492 explicit SkPDFImageShader(SkPDFShader::State* state); |
| 446 virtual ~SkPDFImageShader() { | 493 virtual ~SkPDFImageShader() { |
| 447 RemoveShader(this); | 494 RemoveShader(this); |
| 448 fResources.unrefAll(); | 495 fResources.unrefAll(); |
| 449 } | 496 } |
| 450 | 497 |
| 451 virtual bool isValid() { return size() > 0; } | 498 virtual bool isValid() { return size() > 0; } |
| 452 | 499 |
| 453 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 500 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 454 SkTSet<SkPDFObject*>* newResourceObjects) { | 501 SkTSet<SkPDFObject*>* newResourceObjects) { |
| 455 GetResourcesHelper(&fResources.toArray(), | 502 GetResourcesHelper(&fResources.toArray(), |
| 456 knownResourceObjects, | 503 knownResourceObjects, |
| 457 newResourceObjects); | 504 newResourceObjects); |
| 458 } | 505 } |
| 459 | 506 |
| 460 private: | 507 private: |
| 461 SkTSet<SkPDFObject*> fResources; | 508 SkTSet<SkPDFObject*> fResources; |
| 462 SkAutoTDelete<const SkPDFShader::State> fState; | 509 SkAutoTDelete<const SkPDFShader::State> fState; |
| 463 }; | 510 }; |
| 464 | 511 |
| 465 SkPDFShader::SkPDFShader() {} | 512 SkPDFShader::SkPDFShader() {} |
| 466 | 513 |
| 467 // static | 514 // static |
| 468 void SkPDFShader::RemoveShader(SkPDFObject* shader) { | 515 // This is an internal method. CanonicalShadersMutex() should already be acquire d. |
| 469 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | 516 // This also takes ownership of inState, which is deleted on return. |
|
vandebo (ex-Chrome)
2013/07/09 17:47:44
nix "which is..." If it takes ownership than the c
ducky
2013/07/10 21:42:26
Done.
| |
| 470 ShaderCanonicalEntry entry(shader, NULL); | 517 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { |
| 471 int index = CanonicalShaders().find(entry); | 518 SkPDFObject* result; |
| 472 SkASSERT(index >= 0); | |
| 473 CanonicalShaders().removeShuffle(index); | |
| 474 } | |
| 475 | 519 |
| 476 // static | 520 SkAutoTDelete<State> shaderState(inState); |
| 477 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, | |
| 478 const SkMatrix& matrix, | |
| 479 const SkIRect& surfaceBBox) { | |
| 480 SkPDFObject* result; | |
| 481 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
| 482 SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox)); | |
| 483 if (shaderState.get()->fType == SkShader::kNone_GradientType && | 521 if (shaderState.get()->fType == SkShader::kNone_GradientType && |
| 484 shaderState.get()->fImage.isNull()) { | 522 shaderState.get()->fImage.isNull()) { |
| 485 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 523 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
| 486 // handle compose shader by pulling things up to a layer, drawing with | 524 // 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 | 525 // the first shader, applying the xfer mode and drawing again with the |
| 488 // second shader, then applying the layer to the original drawing. | 526 // second shader, then applying the layer to the original drawing. |
| 489 return NULL; | 527 return NULL; |
| 490 } | 528 } |
| 491 | 529 |
| 492 ShaderCanonicalEntry entry(NULL, shaderState.get()); | 530 ShaderCanonicalEntry entry(NULL, shaderState.get()); |
| 493 int index = CanonicalShaders().find(entry); | 531 int index = CanonicalShaders().find(entry); |
| 494 if (index >= 0) { | 532 if (index >= 0) { |
| 495 result = CanonicalShaders()[index].fPDFShader; | 533 result = CanonicalShaders()[index].fPDFShader; |
| 496 result->ref(); | 534 result->ref(); |
| 497 return result; | 535 return result; |
| 498 } | 536 } |
| 499 | 537 |
| 500 bool valid = false; | 538 bool valid = false; |
| 501 // The PDFShader takes ownership of the shaderSate. | 539 // The PDFShader takes ownership of the shaderSate. |
| 502 if (shaderState.get()->fType == SkShader::kNone_GradientType) { | 540 if (shaderState.get()->fType == SkShader::kNone_GradientType) { |
| 503 SkPDFImageShader* imageShader = | 541 SkPDFImageShader* imageShader = |
| 504 new SkPDFImageShader(shaderState.detach()); | 542 new SkPDFImageShader(shaderState.detach()); |
| 505 valid = imageShader->isValid(); | 543 valid = imageShader->isValid(); |
| 506 result = imageShader; | 544 result = imageShader; |
| 507 } else { | 545 } else { |
| 508 SkPDFFunctionShader* functionShader = | 546 if (shaderState.get()->GradientHasAlpha()) { |
| 509 new SkPDFFunctionShader(shaderState.detach()); | 547 SkPDFGradientShader* gradientShader = |
| 510 valid = functionShader->isValid(); | 548 new SkPDFGradientShader(shaderState.detach()); |
| 511 result = functionShader; | 549 valid = gradientShader->isValid(); |
| 550 result = gradientShader; | |
| 551 } else { | |
| 552 SkPDFFunctionShader* functionShader = | |
| 553 new SkPDFFunctionShader(shaderState.detach()); | |
| 554 valid = functionShader->isValid(); | |
| 555 result = functionShader; | |
| 556 } | |
| 512 } | 557 } |
| 513 if (!valid) { | 558 if (!valid) { |
| 514 delete result; | 559 delete result; |
| 515 return NULL; | 560 return NULL; |
| 516 } | 561 } |
| 517 entry.fPDFShader = result; | 562 entry.fPDFShader = result; |
| 518 CanonicalShaders().push(entry); | 563 CanonicalShaders().push(entry); |
| 519 return result; // return the reference that came from new. | 564 return result; // return the reference that came from new. |
| 520 } | 565 } |
| 521 | 566 |
| 522 // static | 567 // static |
| 568 void SkPDFShader::RemoveShader(SkPDFObject* shader) { | |
| 569 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
| 570 ShaderCanonicalEntry entry(shader, NULL); | |
| 571 int index = CanonicalShaders().find(entry); | |
| 572 SkASSERT(index >= 0); | |
| 573 CanonicalShaders().removeShuffle(index); | |
| 574 } | |
| 575 | |
| 576 // static | |
| 577 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, | |
| 578 const SkMatrix& matrix, | |
| 579 const SkIRect& surfaceBBox) { | |
| 580 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
| 581 return GetPDFShaderByState(new State(shader, matrix, surfaceBBox)); | |
| 582 } | |
| 583 | |
| 584 // static | |
| 523 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { | 585 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { |
| 524 // This initialization is only thread safe with gcc. | 586 // This initialization is only thread safe with gcc. |
| 525 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; | 587 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; |
| 526 return gCanonicalShaders; | 588 return gCanonicalShaders; |
| 527 } | 589 } |
| 528 | 590 |
| 529 // static | 591 // static |
| 530 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { | 592 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { |
| 531 // This initialization is only thread safe with gcc or when | 593 // This initialization is only thread safe with gcc or when |
| 532 // POD-style mutex initialization is used. | 594 // POD-style mutex initialization is used. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 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* get_gradient_resource_dict( | |
| 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(); | |
| 631 | |
| 632 return dict; | |
| 633 } | |
| 634 | |
| 635 static void populate_tiling_pattern_dict(SkPDFDict* pattern, | |
| 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 * The argument setup may contain any relevant PDF content stream operators | |
| 654 * and will be prepended to the output content stream. | |
| 655 */ | |
| 656 static SkData* create_pattern_fill_content(const char setup[], SkRect& bounds) { | |
| 657 SkDynamicMemoryWStream content; | |
| 658 if (NULL != setup) { | |
| 659 content.writeText(setup); | |
| 660 } | |
| 661 content.writeText("/Pattern CS/Pattern cs/P0 SCN/P0 scn\n"); | |
| 662 | |
| 663 SkPDFUtils::AppendRectangle(bounds, &content); | |
| 664 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, &cont ent); | |
| 665 | |
| 666 return content.copyToData(); | |
| 667 } | |
| 668 | |
| 669 /** | |
| 670 * Creates a ExtGState with the SMask set to the luminosityShader in | |
| 671 * luminosity mode. The shader pattern extends to the bbox. | |
| 672 */ | |
| 673 static SkPDFGraphicState* create_smask_graphic_state(SkPDFObject* luminosityShad er, SkRect& bbox) { | |
| 674 SkAutoTUnref<SkData> alphaStream(create_pattern_fill_content(NULL, bbox)); | |
| 675 | |
| 676 SkAutoTUnref<SkPDFResourceDict> | |
| 677 resources(get_gradient_resource_dict(luminosityShader, NULL)); | |
| 678 | |
| 679 SkAutoTUnref<SkPDFFormXObject> alphaMask( | |
| 680 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); | |
| 681 | |
| 682 return SkPDFGraphicState::GetSMaskGraphicState( | |
| 683 alphaMask.get(), false, | |
| 684 SkPDFGraphicState::kLuminosity_SMaskMode); | |
| 685 } | |
| 686 | |
| 687 SkPDFGradientShader::SkPDFGradientShader(SkPDFShader::State* state) : fState(sta te) { | |
| 688 SkRect bbox; | |
| 689 bbox.set(fState.get()->fBBox); | |
| 690 | |
| 691 fColorPattern.reset(SkPDFShader::GetPDFShaderByState(state->CreateOpaqueStat e())); | |
| 692 | |
| 693 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState( | |
| 694 state->CreateAlphaToLuminosityState())); | |
| 695 fAlphaGs.reset(create_smask_graphic_state(luminosityShader.get(), bbox)); | |
| 696 | |
| 697 fResourceDict.reset(get_gradient_resource_dict(fColorPattern.get(), fAlphaGs .get())); | |
| 698 | |
| 699 SkAutoTUnref<SkData> colorStream(create_pattern_fill_content("/G0 gs", bbox) ); | |
| 700 setData(colorStream.get()); | |
| 701 | |
| 702 populate_tiling_pattern_dict(this, bbox, fResourceDict.get(), SkMatrix::I()) ; | |
| 703 } | |
| 704 | |
| 556 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) | 705 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
| 557 : SkPDFDict("Pattern"), | 706 : SkPDFDict("Pattern"), |
| 558 fState(state) { | 707 fState(state) { |
| 559 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; | 708 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; |
| 560 SkPoint transformPoints[2]; | 709 SkPoint transformPoints[2]; |
| 561 | 710 |
| 562 // Depending on the type of the gradient, we want to transform the | 711 // Depending on the type of the gradient, we want to transform the |
| 563 // coordinate space in different ways. | 712 // coordinate space in different ways. |
| 564 const SkShader::GradientInfo* info = &fState.get()->fInfo; | 713 const SkShader::GradientInfo* info = &fState.get()->fInfo; |
| 565 transformPoints[0] = info->fPoint[0]; | 714 transformPoints[0] = info->fPoint[0]; |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 821 | 970 |
| 822 if (tileModes[0] == SkShader::kMirror_TileMode) { | 971 if (tileModes[0] == SkShader::kMirror_TileMode) { |
| 823 bottomMatrix.postScale(-1, 1); | 972 bottomMatrix.postScale(-1, 1); |
| 824 bottomMatrix.postTranslate(2 * width, 0); | 973 bottomMatrix.postTranslate(2 * width, 0); |
| 825 canvas.drawBitmapMatrix(bottom, bottomMatrix); | 974 canvas.drawBitmapMatrix(bottom, bottomMatrix); |
| 826 } | 975 } |
| 827 patternBBox.fBottom = surfaceBBox.height(); | 976 patternBBox.fBottom = surfaceBBox.height(); |
| 828 } | 977 } |
| 829 } | 978 } |
| 830 | 979 |
| 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). | 980 // Put the canvas into the pattern stream (fContent). |
| 839 SkAutoTUnref<SkStream> content(pattern.content()); | 981 SkAutoTUnref<SkStream> content(pattern.content()); |
| 840 setData(content.get()); | 982 setData(content.get()); |
| 841 pattern.getResources(fResources, &fResources, false); | 983 pattern.getResources(fResources, &fResources, false); |
| 842 | 984 |
| 843 insertName("Type", "Pattern"); | 985 populate_tiling_pattern_dict(this, patternBBox, |
| 844 insertInt("PatternType", 1); | 986 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 | 987 |
| 853 fState.get()->fImage.unlockPixels(); | 988 fState.get()->fImage.unlockPixels(); |
| 854 } | 989 } |
| 855 | 990 |
| 856 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, | 991 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, |
| 857 SkPDFArray* domain) { | 992 SkPDFArray* domain) { |
| 858 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), | 993 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), |
| 859 psCode.size())); | 994 psCode.size())); |
| 860 SkPDFStream* result = new SkPDFStream(funcData.get()); | 995 SkPDFStream* result = new SkPDFStream(funcData.get()); |
| 861 result->insertInt("FunctionType", 4); | 996 result->insertInt("FunctionType", 4); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 947 SkShader::BitmapType bitmapType; | 1082 SkShader::BitmapType bitmapType; |
| 948 SkMatrix matrix; | 1083 SkMatrix matrix; |
| 949 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); | 1084 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); |
| 950 if (bitmapType != SkShader::kDefault_BitmapType) { | 1085 if (bitmapType != SkShader::kDefault_BitmapType) { |
| 951 fImage.reset(); | 1086 fImage.reset(); |
| 952 return; | 1087 return; |
| 953 } | 1088 } |
| 954 SkASSERT(matrix.isIdentity()); | 1089 SkASSERT(matrix.isIdentity()); |
| 955 fPixelGeneration = fImage.getGenerationID(); | 1090 fPixelGeneration = fImage.getGenerationID(); |
| 956 } else { | 1091 } else { |
| 957 fColorData.set(sk_malloc_throw( | 1092 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); | 1093 shader.asAGradient(&fInfo); |
| 963 } | 1094 } |
| 964 } | 1095 } |
| 1096 | |
| 1097 SkPDFShader::State::State(const SkPDFShader::State& other) | |
| 1098 : fType(other.fType), | |
| 1099 fCanvasTransform(other.fCanvasTransform), | |
| 1100 fShaderTransform(other.fShaderTransform), | |
| 1101 fBBox(other.fBBox) | |
| 1102 { | |
| 1103 // Only gradients supported for now, since that is all that is used. | |
| 1104 // If needed, image state copy constructor can be added here later. | |
| 1105 SkASSERT(fType != SkShader::kNone_GradientType); | |
| 1106 | |
| 1107 if (fType != SkShader::kNone_GradientType) { | |
| 1108 fInfo = other.fInfo; | |
| 1109 | |
| 1110 AllocateGradientInfoStorage(); | |
| 1111 for (int i = 0; i < fInfo.fColorCount; i++) { | |
| 1112 fInfo.fColors[i] = other.fInfo.fColors[i]; | |
| 1113 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; | |
| 1114 } | |
| 1115 } | |
| 1116 } | |
| 1117 | |
| 1118 /** | |
| 1119 * Create a copy of this gradient state with alpha assigned to RGB luminousity. | |
| 1120 * Only valid for gradient states! | |
| 1121 */ | |
| 1122 SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const { | |
| 1123 SkASSERT(fType != SkShader::kNone_GradientType); | |
| 1124 | |
| 1125 SkPDFShader::State* newState = new SkPDFShader::State(*this); | |
| 1126 | |
| 1127 for (int i = 0; i < fInfo.fColorCount; i++) { | |
| 1128 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | |
| 1129 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); | |
| 1130 } | |
| 1131 | |
| 1132 return newState; | |
| 1133 } | |
| 1134 | |
| 1135 /** | |
| 1136 * Create a copy of this gradient state with alpha set to fully opaque | |
| 1137 * Only valid for gradient states. | |
| 1138 */ | |
| 1139 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const { | |
| 1140 SkASSERT(fType != SkShader::kNone_GradientType); | |
| 1141 | |
| 1142 SkPDFShader::State* newState = new SkPDFShader::State(*this); | |
| 1143 SkAlpha opaque = SkColorGetA(SK_ColorBLACK); | |
| 1144 for (int i = 0; i < fInfo.fColorCount; i++) { | |
| 1145 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], opaque); | |
| 1146 } | |
| 1147 | |
| 1148 return newState; | |
| 1149 } | |
| 1150 | |
| 1151 /** | |
| 1152 * Returns true if state is a gradient and the gradient has alpha. | |
| 1153 */ | |
| 1154 bool SkPDFShader::State::GradientHasAlpha() const { | |
| 1155 if (fType == SkShader::kNone_GradientType) { | |
| 1156 return false; | |
| 1157 } | |
| 1158 | |
| 1159 SkAlpha opaque = SkColorGetA(SK_ColorBLACK); | |
| 1160 for (int i = 0; i < fInfo.fColorCount; i++) { | |
| 1161 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | |
| 1162 if (alpha != opaque) { | |
| 1163 return true; | |
| 1164 } | |
| 1165 } | |
| 1166 return false; | |
| 1167 } | |
| 1168 | |
| 1169 void SkPDFShader::State::AllocateGradientInfoStorage() { | |
| 1170 fColorData.set(sk_malloc_throw( | |
| 1171 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | |
| 1172 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | |
| 1173 fInfo.fColorOffsets = | |
| 1174 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCoun t); | |
| 1175 } | |
| OLD | NEW |