| 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" |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 static SkPDFObject* get_pdf_shader_by_state( | 488 static SkPDFObject* get_pdf_shader_by_state( |
| 489 SkPDFCanon* canon, | 489 SkPDFCanon* canon, |
| 490 SkScalar dpi, | 490 SkScalar dpi, |
| 491 SkAutoTDelete<SkPDFShader::State>* autoState) { | 491 SkAutoTDelete<SkPDFShader::State>* autoState) { |
| 492 const SkPDFShader::State& state = **autoState; | 492 const SkPDFShader::State& state = **autoState; |
| 493 if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) { | 493 if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) { |
| 494 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 494 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
| 495 // handle compose shader by pulling things up to a layer, drawing with | 495 // handle compose shader by pulling things up to a layer, drawing with |
| 496 // the first shader, applying the xfer mode and drawing again with the | 496 // the first shader, applying the xfer mode and drawing again with the |
| 497 // second shader, then applying the layer to the original drawing. | 497 // second shader, then applying the layer to the original drawing. |
| 498 return NULL; | 498 return nullptr; |
| 499 } else if (state.fType == SkShader::kNone_GradientType) { | 499 } else if (state.fType == SkShader::kNone_GradientType) { |
| 500 SkPDFObject* shader = canon->findImageShader(state); | 500 SkPDFObject* shader = canon->findImageShader(state); |
| 501 return shader ? SkRef(shader) | 501 return shader ? SkRef(shader) |
| 502 : SkPDFImageShader::Create(canon, dpi, autoState); | 502 : SkPDFImageShader::Create(canon, dpi, autoState); |
| 503 } else if (state.GradientHasAlpha()) { | 503 } else if (state.GradientHasAlpha()) { |
| 504 SkPDFObject* shader = canon->findAlphaShader(state); | 504 SkPDFObject* shader = canon->findAlphaShader(state); |
| 505 return shader ? SkRef(shader) | 505 return shader ? SkRef(shader) |
| 506 : SkPDFAlphaFunctionShader::Create(canon, dpi, autoState); | 506 : SkPDFAlphaFunctionShader::Create(canon, dpi, autoState); |
| 507 } else { | 507 } else { |
| 508 SkPDFObject* shader = canon->findFunctionShader(state); | 508 SkPDFObject* shader = canon->findFunctionShader(state); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 526 SkPDFObject* functionShader, | 526 SkPDFObject* functionShader, |
| 527 SkPDFObject* gState) { | 527 SkPDFObject* gState) { |
| 528 SkTDArray<SkPDFObject*> patterns; | 528 SkTDArray<SkPDFObject*> patterns; |
| 529 if (functionShader) { | 529 if (functionShader) { |
| 530 patterns.push(functionShader); | 530 patterns.push(functionShader); |
| 531 } | 531 } |
| 532 SkTDArray<SkPDFObject*> graphicStates; | 532 SkTDArray<SkPDFObject*> graphicStates; |
| 533 if (gState) { | 533 if (gState) { |
| 534 graphicStates.push(gState); | 534 graphicStates.push(gState); |
| 535 } | 535 } |
| 536 return SkPDFResourceDict::Create(&graphicStates, &patterns, NULL, NULL); | 536 return SkPDFResourceDict::Create(&graphicStates, &patterns, nullptr, nullptr
); |
| 537 } | 537 } |
| 538 | 538 |
| 539 static void populate_tiling_pattern_dict(SkPDFDict* pattern, | 539 static void populate_tiling_pattern_dict(SkPDFDict* pattern, |
| 540 SkRect& bbox, | 540 SkRect& bbox, |
| 541 SkPDFDict* resources, | 541 SkPDFDict* resources, |
| 542 const SkMatrix& matrix) { | 542 const SkMatrix& matrix) { |
| 543 const int kTiling_PatternType = 1; | 543 const int kTiling_PatternType = 1; |
| 544 const int kColoredTilingPattern_PaintType = 1; | 544 const int kColoredTilingPattern_PaintType = 1; |
| 545 const int kConstantSpacing_TilingType = 1; | 545 const int kConstantSpacing_TilingType = 1; |
| 546 | 546 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 bbox.set(state.fBBox); | 585 bbox.set(state.fBBox); |
| 586 | 586 |
| 587 SkAutoTDelete<SkPDFShader::State> alphaToLuminosityState( | 587 SkAutoTDelete<SkPDFShader::State> alphaToLuminosityState( |
| 588 state.CreateAlphaToLuminosityState()); | 588 state.CreateAlphaToLuminosityState()); |
| 589 SkAutoTUnref<SkPDFObject> luminosityShader( | 589 SkAutoTUnref<SkPDFObject> luminosityShader( |
| 590 get_pdf_shader_by_state(canon, dpi, &alphaToLuminosityState)); | 590 get_pdf_shader_by_state(canon, dpi, &alphaToLuminosityState)); |
| 591 | 591 |
| 592 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); | 592 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); |
| 593 | 593 |
| 594 SkAutoTUnref<SkPDFDict> | 594 SkAutoTUnref<SkPDFDict> |
| 595 resources(get_gradient_resource_dict(luminosityShader, NULL)); | 595 resources(get_gradient_resource_dict(luminosityShader, nullptr)); |
| 596 | 596 |
| 597 SkAutoTUnref<SkPDFFormXObject> alphaMask( | 597 SkAutoTUnref<SkPDFFormXObject> alphaMask( |
| 598 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); | 598 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); |
| 599 | 599 |
| 600 return SkPDFGraphicState::GetSMaskGraphicState( | 600 return SkPDFGraphicState::GetSMaskGraphicState( |
| 601 alphaMask.get(), false, | 601 alphaMask.get(), false, |
| 602 SkPDFGraphicState::kLuminosity_SMaskMode); | 602 SkPDFGraphicState::kLuminosity_SMaskMode); |
| 603 } | 603 } |
| 604 | 604 |
| 605 SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( | 605 SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( |
| 606 SkPDFCanon* canon, | 606 SkPDFCanon* canon, |
| 607 SkScalar dpi, | 607 SkScalar dpi, |
| 608 SkAutoTDelete<SkPDFShader::State>* autoState) { | 608 SkAutoTDelete<SkPDFShader::State>* autoState) { |
| 609 const SkPDFShader::State& state = **autoState; | 609 const SkPDFShader::State& state = **autoState; |
| 610 SkRect bbox; | 610 SkRect bbox; |
| 611 bbox.set(state.fBBox); | 611 bbox.set(state.fBBox); |
| 612 | 612 |
| 613 SkAutoTDelete<SkPDFShader::State> opaqueState(state.CreateOpaqueState()); | 613 SkAutoTDelete<SkPDFShader::State> opaqueState(state.CreateOpaqueState()); |
| 614 | 614 |
| 615 SkAutoTUnref<SkPDFObject> colorShader( | 615 SkAutoTUnref<SkPDFObject> colorShader( |
| 616 get_pdf_shader_by_state(canon, dpi, &opaqueState)); | 616 get_pdf_shader_by_state(canon, dpi, &opaqueState)); |
| 617 if (!colorShader) { | 617 if (!colorShader) { |
| 618 return NULL; | 618 return nullptr; |
| 619 } | 619 } |
| 620 | 620 |
| 621 // Create resource dict with alpha graphics state as G0 and | 621 // Create resource dict with alpha graphics state as G0 and |
| 622 // pattern shader as P0, then write content stream. | 622 // pattern shader as P0, then write content stream. |
| 623 SkAutoTUnref<SkPDFObject> alphaGs( | 623 SkAutoTUnref<SkPDFObject> alphaGs( |
| 624 create_smask_graphic_state(canon, dpi, state)); | 624 create_smask_graphic_state(canon, dpi, state)); |
| 625 | 625 |
| 626 SkPDFAlphaFunctionShader* alphaFunctionShader = | 626 SkPDFAlphaFunctionShader* alphaFunctionShader = |
| 627 new SkPDFAlphaFunctionShader(autoState->detach()); | 627 new SkPDFAlphaFunctionShader(autoState->detach()); |
| 628 | 628 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 result->insertObject("Domain", SkRef(domain)); | 705 result->insertObject("Domain", SkRef(domain)); |
| 706 result->insertObject("Range", SkRef(rangeObject.get())); | 706 result->insertObject("Range", SkRef(rangeObject.get())); |
| 707 return result; | 707 return result; |
| 708 } | 708 } |
| 709 | 709 |
| 710 SkPDFFunctionShader* SkPDFFunctionShader::Create( | 710 SkPDFFunctionShader* SkPDFFunctionShader::Create( |
| 711 SkPDFCanon* canon, SkAutoTDelete<SkPDFShader::State>* autoState) { | 711 SkPDFCanon* canon, SkAutoTDelete<SkPDFShader::State>* autoState) { |
| 712 const SkPDFShader::State& state = **autoState; | 712 const SkPDFShader::State& state = **autoState; |
| 713 | 713 |
| 714 SkString (*codeFunction)(const SkShader::GradientInfo& info, | 714 SkString (*codeFunction)(const SkShader::GradientInfo& info, |
| 715 const SkMatrix& perspectiveRemover) = NULL; | 715 const SkMatrix& perspectiveRemover) = nullptr; |
| 716 SkPoint transformPoints[2]; | 716 SkPoint transformPoints[2]; |
| 717 | 717 |
| 718 // Depending on the type of the gradient, we want to transform the | 718 // Depending on the type of the gradient, we want to transform the |
| 719 // coordinate space in different ways. | 719 // coordinate space in different ways. |
| 720 const SkShader::GradientInfo* info = &state.fInfo; | 720 const SkShader::GradientInfo* info = &state.fInfo; |
| 721 transformPoints[0] = info->fPoint[0]; | 721 transformPoints[0] = info->fPoint[0]; |
| 722 transformPoints[1] = info->fPoint[1]; | 722 transformPoints[1] = info->fPoint[1]; |
| 723 switch (state.fType) { | 723 switch (state.fType) { |
| 724 case SkShader::kLinear_GradientType: | 724 case SkShader::kLinear_GradientType: |
| 725 codeFunction = &linearCode; | 725 codeFunction = &linearCode; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 736 break; | 736 break; |
| 737 } | 737 } |
| 738 case SkShader::kSweep_GradientType: | 738 case SkShader::kSweep_GradientType: |
| 739 transformPoints[1] = transformPoints[0]; | 739 transformPoints[1] = transformPoints[0]; |
| 740 transformPoints[1].fX += SK_Scalar1; | 740 transformPoints[1].fX += SK_Scalar1; |
| 741 codeFunction = &sweepCode; | 741 codeFunction = &sweepCode; |
| 742 break; | 742 break; |
| 743 case SkShader::kColor_GradientType: | 743 case SkShader::kColor_GradientType: |
| 744 case SkShader::kNone_GradientType: | 744 case SkShader::kNone_GradientType: |
| 745 default: | 745 default: |
| 746 return NULL; | 746 return nullptr; |
| 747 } | 747 } |
| 748 | 748 |
| 749 // Move any scaling (assuming a unit gradient) or translation | 749 // Move any scaling (assuming a unit gradient) or translation |
| 750 // (and rotation for linear gradient), of the final gradient from | 750 // (and rotation for linear gradient), of the final gradient from |
| 751 // info->fPoints to the matrix (updating bbox appropriately). Now | 751 // info->fPoints to the matrix (updating bbox appropriately). Now |
| 752 // the gradient can be drawn on on the unit segment. | 752 // the gradient can be drawn on on the unit segment. |
| 753 SkMatrix mapperMatrix; | 753 SkMatrix mapperMatrix; |
| 754 unitToPointsMatrix(transformPoints, &mapperMatrix); | 754 unitToPointsMatrix(transformPoints, &mapperMatrix); |
| 755 | 755 |
| 756 SkMatrix finalMatrix = state.fCanvasTransform; | 756 SkMatrix finalMatrix = state.fCanvasTransform; |
| 757 finalMatrix.preConcat(state.fShaderTransform); | 757 finalMatrix.preConcat(state.fShaderTransform); |
| 758 finalMatrix.preConcat(mapperMatrix); | 758 finalMatrix.preConcat(mapperMatrix); |
| 759 | 759 |
| 760 // Preserves as much as posible in the final matrix, and only removes | 760 // Preserves as much as posible in the final matrix, and only removes |
| 761 // the perspective. The inverse of the perspective is stored in | 761 // the perspective. The inverse of the perspective is stored in |
| 762 // perspectiveInverseOnly matrix and has 3 useful numbers | 762 // perspectiveInverseOnly matrix and has 3 useful numbers |
| 763 // (p0, p1, p2), while everything else is either 0 or 1. | 763 // (p0, p1, p2), while everything else is either 0 or 1. |
| 764 // In this way the shader will handle it eficiently, with minimal code. | 764 // In this way the shader will handle it eficiently, with minimal code. |
| 765 SkMatrix perspectiveInverseOnly = SkMatrix::I(); | 765 SkMatrix perspectiveInverseOnly = SkMatrix::I(); |
| 766 if (finalMatrix.hasPerspective()) { | 766 if (finalMatrix.hasPerspective()) { |
| 767 if (!split_perspective(finalMatrix, | 767 if (!split_perspective(finalMatrix, |
| 768 &finalMatrix, &perspectiveInverseOnly)) { | 768 &finalMatrix, &perspectiveInverseOnly)) { |
| 769 return NULL; | 769 return nullptr; |
| 770 } | 770 } |
| 771 } | 771 } |
| 772 | 772 |
| 773 SkRect bbox; | 773 SkRect bbox; |
| 774 bbox.set(state.fBBox); | 774 bbox.set(state.fBBox); |
| 775 if (!inverse_transform_bbox(finalMatrix, &bbox)) { | 775 if (!inverse_transform_bbox(finalMatrix, &bbox)) { |
| 776 return NULL; | 776 return nullptr; |
| 777 } | 777 } |
| 778 | 778 |
| 779 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); | 779 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); |
| 780 domain->reserve(4); | 780 domain->reserve(4); |
| 781 domain->appendScalar(bbox.fLeft); | 781 domain->appendScalar(bbox.fLeft); |
| 782 domain->appendScalar(bbox.fRight); | 782 domain->appendScalar(bbox.fRight); |
| 783 domain->appendScalar(bbox.fTop); | 783 domain->appendScalar(bbox.fTop); |
| 784 domain->appendScalar(bbox.fBottom); | 784 domain->appendScalar(bbox.fBottom); |
| 785 | 785 |
| 786 SkString functionCode; | 786 SkString functionCode; |
| 787 // The two point radial gradient further references | 787 // The two point radial gradient further references |
| 788 // state.fInfo | 788 // state.fInfo |
| 789 // in translating from x, y coordinates to the t parameter. So, we have | 789 // in translating from x, y coordinates to the t parameter. So, we have |
| 790 // to transform the points and radii according to the calculated matrix. | 790 // to transform the points and radii according to the calculated matrix. |
| 791 if (state.fType == SkShader::kConical_GradientType) { | 791 if (state.fType == SkShader::kConical_GradientType) { |
| 792 SkShader::GradientInfo twoPointRadialInfo = *info; | 792 SkShader::GradientInfo twoPointRadialInfo = *info; |
| 793 SkMatrix inverseMapperMatrix; | 793 SkMatrix inverseMapperMatrix; |
| 794 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | 794 if (!mapperMatrix.invert(&inverseMapperMatrix)) { |
| 795 return NULL; | 795 return nullptr; |
| 796 } | 796 } |
| 797 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | 797 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); |
| 798 twoPointRadialInfo.fRadius[0] = | 798 twoPointRadialInfo.fRadius[0] = |
| 799 inverseMapperMatrix.mapRadius(info->fRadius[0]); | 799 inverseMapperMatrix.mapRadius(info->fRadius[0]); |
| 800 twoPointRadialInfo.fRadius[1] = | 800 twoPointRadialInfo.fRadius[1] = |
| 801 inverseMapperMatrix.mapRadius(info->fRadius[1]); | 801 inverseMapperMatrix.mapRadius(info->fRadius[1]); |
| 802 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); | 802 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); |
| 803 } else { | 803 } else { |
| 804 functionCode = codeFunction(*info, perspectiveInverseOnly); | 804 functionCode = codeFunction(*info, perspectiveInverseOnly); |
| 805 } | 805 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 836 // in pattern cell space (no scaling on the bitmap, though there may be | 836 // in pattern cell space (no scaling on the bitmap, though there may be |
| 837 // translations so that all content is in the device, coordinates > 0). | 837 // translations so that all content is in the device, coordinates > 0). |
| 838 | 838 |
| 839 // Map clip bounds to shader space to ensure the device is large enough | 839 // Map clip bounds to shader space to ensure the device is large enough |
| 840 // to handle fake clamping. | 840 // to handle fake clamping. |
| 841 SkMatrix finalMatrix = state.fCanvasTransform; | 841 SkMatrix finalMatrix = state.fCanvasTransform; |
| 842 finalMatrix.preConcat(state.fShaderTransform); | 842 finalMatrix.preConcat(state.fShaderTransform); |
| 843 SkRect deviceBounds; | 843 SkRect deviceBounds; |
| 844 deviceBounds.set(state.fBBox); | 844 deviceBounds.set(state.fBBox); |
| 845 if (!inverse_transform_bbox(finalMatrix, &deviceBounds)) { | 845 if (!inverse_transform_bbox(finalMatrix, &deviceBounds)) { |
| 846 return NULL; | 846 return nullptr; |
| 847 } | 847 } |
| 848 | 848 |
| 849 const SkBitmap* image = &state.fImage; | 849 const SkBitmap* image = &state.fImage; |
| 850 SkRect bitmapBounds; | 850 SkRect bitmapBounds; |
| 851 image->getBounds(&bitmapBounds); | 851 image->getBounds(&bitmapBounds); |
| 852 | 852 |
| 853 // For tiling modes, the bounds should be extended to include the bitmap, | 853 // For tiling modes, the bounds should be extended to include the bitmap, |
| 854 // otherwise the bitmap gets clipped out and the shader is empty and awful. | 854 // otherwise the bitmap gets clipped out and the shader is empty and awful. |
| 855 // For clamp modes, we're only interested in the clip region, whether | 855 // For clamp modes, we're only interested in the clip region, whether |
| 856 // or not the main bitmap is in it. | 856 // or not the main bitmap is in it. |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 } | 1092 } |
| 1093 return true; | 1093 return true; |
| 1094 } | 1094 } |
| 1095 | 1095 |
| 1096 SkPDFShader::State::State(const SkShader& shader, const SkMatrix& canvasTransfor
m, | 1096 SkPDFShader::State::State(const SkShader& shader, const SkMatrix& canvasTransfor
m, |
| 1097 const SkIRect& bbox, SkScalar rasterScale) | 1097 const SkIRect& bbox, SkScalar rasterScale) |
| 1098 : fCanvasTransform(canvasTransform), | 1098 : fCanvasTransform(canvasTransform), |
| 1099 fBBox(bbox), | 1099 fBBox(bbox), |
| 1100 fPixelGeneration(0) { | 1100 fPixelGeneration(0) { |
| 1101 fInfo.fColorCount = 0; | 1101 fInfo.fColorCount = 0; |
| 1102 fInfo.fColors = NULL; | 1102 fInfo.fColors = nullptr; |
| 1103 fInfo.fColorOffsets = NULL; | 1103 fInfo.fColorOffsets = nullptr; |
| 1104 fShaderTransform = shader.getLocalMatrix(); | 1104 fShaderTransform = shader.getLocalMatrix(); |
| 1105 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; | 1105 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; |
| 1106 | 1106 |
| 1107 fType = shader.asAGradient(&fInfo); | 1107 fType = shader.asAGradient(&fInfo); |
| 1108 | 1108 |
| 1109 if (fType == SkShader::kNone_GradientType) { | 1109 if (fType == SkShader::kNone_GradientType) { |
| 1110 SkMatrix matrix; | 1110 SkMatrix matrix; |
| 1111 if (shader.isABitmap(&fImage, &matrix, fImageTileModes)) { | 1111 if (shader.isABitmap(&fImage, &matrix, fImageTileModes)) { |
| 1112 SkASSERT(matrix.isIdentity()); | 1112 SkASSERT(matrix.isIdentity()); |
| 1113 } else { | 1113 } else { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 return false; | 1229 return false; |
| 1230 } | 1230 } |
| 1231 | 1231 |
| 1232 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1232 void SkPDFShader::State::AllocateGradientInfoStorage() { |
| 1233 fColorData.set(sk_malloc_throw( | 1233 fColorData.set(sk_malloc_throw( |
| 1234 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1234 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
| 1235 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1235 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
| 1236 fInfo.fColorOffsets = | 1236 fInfo.fColorOffsets = |
| 1237 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | 1237 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
| 1238 } | 1238 } |
| OLD | NEW |