| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBlitter.h" | 8 #include "SkBlitter.h" |
| 9 #include "SkAntiRun.h" | 9 #include "SkAntiRun.h" |
| 10 #include "SkColor.h" | 10 #include "SkColor.h" |
| 11 #include "SkColorFilter.h" | 11 #include "SkColorFilter.h" |
| 12 #include "SkCoreBlitters.h" | 12 #include "SkCoreBlitters.h" |
| 13 #include "SkFilterShader.h" | 13 #include "SkFilterShader.h" |
| 14 #include "SkReadBuffer.h" | 14 #include "SkReadBuffer.h" |
| 15 #include "SkWriteBuffer.h" | 15 #include "SkWriteBuffer.h" |
| 16 #include "SkMask.h" | 16 #include "SkMask.h" |
| 17 #include "SkMaskFilter.h" | 17 #include "SkMaskFilter.h" |
| 18 #include "SkString.h" | 18 #include "SkString.h" |
| 19 #include "SkTLazy.h" | 19 #include "SkTLazy.h" |
| 20 #include "SkUtils.h" | 20 #include "SkUtils.h" |
| 21 #include "SkXfermode.h" | 21 #include "SkXfermode.h" |
| 22 #include "SkXfermodeInterpretation.h" |
| 22 | 23 |
| 23 SkBlitter::~SkBlitter() {} | 24 SkBlitter::~SkBlitter() {} |
| 24 | 25 |
| 25 bool SkBlitter::isNullBlitter() const { return false; } | 26 bool SkBlitter::isNullBlitter() const { return false; } |
| 26 | 27 |
| 27 bool SkBlitter::resetShaderContext(const SkShader::ContextRec&) { | 28 bool SkBlitter::resetShaderContext(const SkShader::ContextRec&) { |
| 28 return true; | 29 return true; |
| 29 } | 30 } |
| 30 | 31 |
| 31 SkShader::Context* SkBlitter::getShaderContext() const { | 32 SkShader::Context* SkBlitter::getShaderContext() const { |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 private: | 771 private: |
| 771 // Both pointers are unowned. They will be deleted by SkSmallAllocator. | 772 // Both pointers are unowned. They will be deleted by SkSmallAllocator. |
| 772 SkBlitter* fProxy; | 773 SkBlitter* fProxy; |
| 773 SkShader::Context* fShaderContext; | 774 SkShader::Context* fShaderContext; |
| 774 }; | 775 }; |
| 775 | 776 |
| 776 /////////////////////////////////////////////////////////////////////////////// | 777 /////////////////////////////////////////////////////////////////////////////// |
| 777 | 778 |
| 778 #include "SkCoreBlitters.h" | 779 #include "SkCoreBlitters.h" |
| 779 | 780 |
| 780 static bool just_solid_color(const SkPaint& paint) { | |
| 781 if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) { | |
| 782 SkShader* shader = paint.getShader(); | |
| 783 if (NULL == shader) { | |
| 784 return true; | |
| 785 } | |
| 786 } | |
| 787 return false; | |
| 788 } | |
| 789 | |
| 790 /** By analyzing the paint (with an xfermode), we may decide we can take | |
| 791 special action. This enum lists our possible actions | |
| 792 */ | |
| 793 enum XferInterp { | |
| 794 kNormal_XferInterp, // no special interpretation, draw normally | |
| 795 kSrcOver_XferInterp, // draw as if in srcover mode | |
| 796 kSkipDrawing_XferInterp // draw nothing | |
| 797 }; | |
| 798 | |
| 799 static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer, | |
| 800 SkColorType deviceCT) { | |
| 801 SkXfermode::Mode mode; | |
| 802 | |
| 803 if (SkXfermode::AsMode(xfer, &mode)) { | |
| 804 switch (mode) { | |
| 805 case SkXfermode::kSrc_Mode: | |
| 806 if (just_solid_color(paint)) { | |
| 807 return kSrcOver_XferInterp; | |
| 808 } | |
| 809 break; | |
| 810 case SkXfermode::kDst_Mode: | |
| 811 return kSkipDrawing_XferInterp; | |
| 812 case SkXfermode::kSrcOver_Mode: | |
| 813 return kSrcOver_XferInterp; | |
| 814 case SkXfermode::kDstOver_Mode: | |
| 815 if (kRGB_565_SkColorType == deviceCT) { | |
| 816 return kSkipDrawing_XferInterp; | |
| 817 } | |
| 818 break; | |
| 819 case SkXfermode::kSrcIn_Mode: | |
| 820 if (kRGB_565_SkColorType == deviceCT && | |
| 821 just_solid_color(paint)) { | |
| 822 return kSrcOver_XferInterp; | |
| 823 } | |
| 824 break; | |
| 825 case SkXfermode::kDstIn_Mode: | |
| 826 if (just_solid_color(paint)) { | |
| 827 return kSkipDrawing_XferInterp; | |
| 828 } | |
| 829 break; | |
| 830 default: | |
| 831 break; | |
| 832 } | |
| 833 } | |
| 834 return kNormal_XferInterp; | |
| 835 } | |
| 836 | |
| 837 SkBlitter* SkBlitter::Choose(const SkBitmap& device, | 781 SkBlitter* SkBlitter::Choose(const SkBitmap& device, |
| 838 const SkMatrix& matrix, | 782 const SkMatrix& matrix, |
| 839 const SkPaint& origPaint, | 783 const SkPaint& origPaint, |
| 840 SkTBlitterAllocator* allocator, | 784 SkTBlitterAllocator* allocator, |
| 841 bool drawCoverage) { | 785 bool drawCoverage) { |
| 842 SkASSERT(allocator != NULL); | 786 SkASSERT(allocator != NULL); |
| 843 | 787 |
| 844 // which check, in case we're being called by a client with a dummy device | 788 // which check, in case we're being called by a client with a dummy device |
| 845 // (e.g. they have a bounder that always aborts the draw) | 789 // (e.g. they have a bounder that always aborts the draw) |
| 846 if (kUnknown_SkColorType == device.colorType() || | 790 if (kUnknown_SkColorType == device.colorType() || |
| (...skipping 10 matching lines...) Expand all Loading... |
| 857 | 801 |
| 858 if (origPaint.getMaskFilter() != NULL && | 802 if (origPaint.getMaskFilter() != NULL && |
| 859 origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) { | 803 origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) { |
| 860 shader3D = SkNEW_ARGS(Sk3DShader, (shader)); | 804 shader3D = SkNEW_ARGS(Sk3DShader, (shader)); |
| 861 // we know we haven't initialized lazyPaint yet, so just do it | 805 // we know we haven't initialized lazyPaint yet, so just do it |
| 862 paint.writable()->setShader(shader3D)->unref(); | 806 paint.writable()->setShader(shader3D)->unref(); |
| 863 shader = shader3D; | 807 shader = shader3D; |
| 864 } | 808 } |
| 865 | 809 |
| 866 if (mode) { | 810 if (mode) { |
| 867 switch (interpret_xfermode(*paint, mode, device.colorType())) { | 811 bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType(); |
| 868 case kSrcOver_XferInterp: | 812 switch (SkInterpretXfermode(*paint, deviceIsOpaque)) { |
| 813 case kSrcOver_SkXfermodeInterpretation: |
| 869 mode = NULL; | 814 mode = NULL; |
| 870 paint.writable()->setXfermode(NULL); | 815 paint.writable()->setXfermode(NULL); |
| 871 break; | 816 break; |
| 872 case kSkipDrawing_XferInterp:{ | 817 case kSkipDrawing_SkXfermodeInterpretation:{ |
| 873 return allocator->createT<SkNullBlitter>(); | 818 return allocator->createT<SkNullBlitter>(); |
| 874 } | 819 } |
| 875 default: | 820 default: |
| 876 break; | 821 break; |
| 877 } | 822 } |
| 878 } | 823 } |
| 879 | 824 |
| 880 /* | 825 /* |
| 881 * If the xfermode is CLEAR, then we can completely ignore the installed | 826 * If the xfermode is CLEAR, then we can completely ignore the installed |
| 882 * color/shader/colorfilter, and just pretend we're SRC + color==0. This | 827 * color/shader/colorfilter, and just pretend we're SRC + color==0. This |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 fShaderContext->~Context(); | 969 fShaderContext->~Context(); |
| 1025 SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext); | 970 SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext); |
| 1026 if (NULL == ctx) { | 971 if (NULL == ctx) { |
| 1027 // Need a valid context in fShaderContext's storage, so we can later (or
our caller) call | 972 // Need a valid context in fShaderContext's storage, so we can later (or
our caller) call |
| 1028 // the in-place destructor. | 973 // the in-place destructor. |
| 1029 SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShad
er, rec)); | 974 SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShad
er, rec)); |
| 1030 return false; | 975 return false; |
| 1031 } | 976 } |
| 1032 return true; | 977 return true; |
| 1033 } | 978 } |
| OLD | NEW |