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 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 Loading... | |
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 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* 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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |