1 /* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org> 5 * Copyright (C) 2009 Dirk Schulze <krit (at) webkit.org> 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 7 * Copyright (C) 2013 Google Inc. All rights reserved. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Library General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Library General Public License for more details. 18 * 19 * You should have received a copy of the GNU Library General Public License 20 * along with this library; see the file COPYING.LIB. If not, write to 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 * Boston, MA 02110-1301, USA. 23 */ 24 25 #include "config.h" 26 #include "platform/graphics/filters/FEMorphology.h" 27 28 #include "SkMorphologyImageFilter.h" 29 #include "platform/graphics/GraphicsContext.h" 30 #include "platform/graphics/Image.h" 31 #include "platform/graphics/filters/ParallelJobs.h" 32 #include "platform/graphics/filters/SkiaImageFilterBuilder.h" 33 #include "platform/text/TextStream.h" 34 #include "wtf/Uint8ClampedArray.h" 35 36 namespace blink { 37 38 FEMorphology::FEMorphology(Filter* filter, MorphologyOperatorType type, float radiusX, float radiusY) 39 : FilterEffect(filter) 40 , m_type(type) 41 , m_radiusX(radiusX) 42 , m_radiusY(radiusY) 43 { 44 } 45 46 PassRefPtr<FEMorphology> FEMorphology::create(Filter* filter, MorphologyOperatorType type, float radiusX, float radiusY) 47 { 48 return adoptRef(new FEMorphology(filter, type, radiusX, radiusY)); 49 } 50 51 MorphologyOperatorType FEMorphology::morphologyOperator() const 52 { 53 return m_type; 54 } 55 56 bool FEMorphology::setMorphologyOperator(MorphologyOperatorType type) 57 { 58 if (m_type == type) 59 return false; 60 m_type = type; 61 return true; 62 } 63 64 float FEMorphology::radiusX() const 65 { 66 return m_radiusX; 67 } 68 69 bool FEMorphology::setRadiusX(float radiusX) 70 { 71 if (m_radiusX == radiusX) 72 return false; 73 m_radiusX = radiusX; 74 return true; 75 } 76 77 float FEMorphology::radiusY() const 78 { 79 return m_radiusY; 80 } 81 82 FloatRect FEMorphology::mapRect(const FloatRect& rect, bool) 83 { 84 FloatRect result = rect; 85 result.inflateX(filter()->applyHorizontalScale(m_radiusX)); 86 result.inflateY(filter()->applyVerticalScale(m_radiusY)); 87 return result; 88 } 89 90 bool FEMorphology::setRadiusY(float radiusY) 91 { 92 if (m_radiusY == radiusY) 93 return false; 94 m_radiusY = radiusY; 95 return true; 96 } 97 98 void FEMorphology::applySoftware() 99 { 100 ImageBuffer* resultImage = createImageBufferResult(); 101 if (!resultImage) 102 return; 103 104 FilterEffect* in = inputEffect(0); 105 106 IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); 107 108 setIsAlphaImage(in->isAlphaImage()); 109 110 float radiusX = filter()->applyHorizontalScale(m_radiusX); 111 float radiusY = filter()->applyVerticalScale(m_radiusY); 112 113 RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); 114 115 SkPaint paint; 116 GraphicsContext* dstContext = resultImage->context(); 117 if (m_type == FEMORPHOLOGY_OPERATOR_DILATE) 118 paint.setImageFilter(SkDilateImageFilter::Create(radiusX, radiusY))->unref(); 119 else if (m_type == FEMORPHOLOGY_OPERATOR_ERODE) 120 paint.setImageFilter(SkErodeImageFilter::Create(radiusX, radiusY))->unref(); 121 122 SkRect bounds = SkRect::MakeWH(absolutePaintRect().width(), absolutePaintRect().height()); 123 dstContext->saveLayer(&bounds, &paint); 124 dstContext->drawImage(image.get(), drawingRegion.location(), CompositeCopy); 125 dstContext->restoreLayer(); 126 } 127 128 PassRefPtr<SkImageFilter> FEMorphology::createImageFilter(SkiaImageFilterBuilder* builder) 129 { 130 RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace())); 131 SkScalar radiusX = SkFloatToScalar(filter()->applyHorizontalScale(m_radiusX)); 132 SkScalar radiusY = SkFloatToScalar(filter()->applyVerticalScale(m_radiusY)); 133 SkImageFilter::CropRect rect = getCropRect(builder->cropOffset()); 134 if (m_type == FEMORPHOLOGY_OPERATOR_DILATE) 135 return adoptRef(SkDilateImageFilter::Create(radiusX, radiusY, input.get(), &rect)); 136 return adoptRef(SkErodeImageFilter::Create(radiusX, radiusY, input.get(), &rect)); 137 } 138 139 static TextStream& operator<<(TextStream& ts, const MorphologyOperatorType& type) 140 { 141 switch (type) { 142 case FEMORPHOLOGY_OPERATOR_UNKNOWN: 143 ts << "UNKNOWN"; 144 break; 145 case FEMORPHOLOGY_OPERATOR_ERODE: 146 ts << "ERODE"; 147 break; 148 case FEMORPHOLOGY_OPERATOR_DILATE: 149 ts << "DILATE"; 150 break; 151 } 152 return ts; 153 } 154 155 TextStream& FEMorphology::externalRepresentation(TextStream& ts, int indent) const 156 { 157 writeIndent(ts, indent); 158 ts << "[feMorphology"; 159 FilterEffect::externalRepresentation(ts); 160 ts << " operator=\"" << morphologyOperator() << "\" " 161 << "radius=\"" << radiusX() << ", " << radiusY() << "\"]\n"; 162 inputEffect(0)->externalRepresentation(ts, indent + 1); 163 return ts; 164 } 165 166 } // namespace blink 167