Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Side by Side Diff: sky/engine/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 922893002: Merge the Sky Engine changes from the SkyDart branch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved. 8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved.
9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
10 * 10 *
(...skipping 16 matching lines...) Expand all
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33 #include "sky/engine/config.h" 33 #include "sky/engine/config.h"
34 #include "sky/engine/core/html/canvas/CanvasRenderingContext2D.h" 34 #include "sky/engine/core/html/canvas/CanvasRenderingContext2D.h"
35 35
36 #include "gen/sky/core/CSSPropertyNames.h" 36 #include "gen/sky/core/CSSPropertyNames.h"
37 #include "sky/engine/bindings/core/v8/ExceptionMessages.h" 37 #include "sky/engine/bindings2/exception_messages.h"
38 #include "sky/engine/bindings/core/v8/ExceptionState.h" 38 #include "sky/engine/bindings2/exception_state.h"
39 #include "sky/engine/bindings/core/v8/ExceptionStatePlaceholder.h" 39 #include "sky/engine/bindings2/exception_state_placeholder.h"
40 #include "sky/engine/core/css/CSSFontSelector.h" 40 #include "sky/engine/core/css/CSSFontSelector.h"
41 #include "sky/engine/core/css/StylePropertySet.h" 41 #include "sky/engine/core/css/StylePropertySet.h"
42 #include "sky/engine/core/css/parser/BisonCSSParser.h" 42 #include "sky/engine/core/css/parser/BisonCSSParser.h"
43 #include "sky/engine/core/css/resolver/StyleResolver.h" 43 #include "sky/engine/core/css/resolver/StyleResolver.h"
44 #include "sky/engine/core/dom/ExceptionCode.h" 44 #include "sky/engine/core/dom/ExceptionCode.h"
45 #include "sky/engine/core/dom/StyleEngine.h" 45 #include "sky/engine/core/dom/StyleEngine.h"
46 #include "sky/engine/core/events/Event.h" 46 #include "sky/engine/core/events/Event.h"
47 #include "sky/engine/core/fetch/ImageResource.h" 47 #include "sky/engine/core/fetch/ImageResource.h"
48 #include "sky/engine/core/frame/ImageBitmap.h" 48 #include "sky/engine/core/frame/ImageBitmap.h"
49 #include "sky/engine/core/html/HTMLCanvasElement.h" 49 #include "sky/engine/core/html/HTMLCanvasElement.h"
(...skipping 729 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 if (!c) 779 if (!c)
780 return; 780 return;
781 781
782 if (!std::isfinite(m11) | !std::isfinite(m21) | !std::isfinite(dx) | !std::i sfinite(m12) | !std::isfinite(m22) | !std::isfinite(dy)) 782 if (!std::isfinite(m11) | !std::isfinite(m21) | !std::isfinite(dx) | !std::i sfinite(m12) | !std::isfinite(m22) | !std::isfinite(dy))
783 return; 783 return;
784 784
785 resetTransform(); 785 resetTransform();
786 transform(m11, m12, m21, m22, dx, dy); 786 transform(m11, m12, m21, m22, dx, dy);
787 } 787 }
788 788
789 String CanvasRenderingContext2D::strokeColor()
790 {
791 return strokeStyle()->color();
792 }
793
789 void CanvasRenderingContext2D::setStrokeColor(const String& color) 794 void CanvasRenderingContext2D::setStrokeColor(const String& color)
790 { 795 {
791 if (color == state().m_unparsedStrokeColor) 796 if (color == state().m_unparsedStrokeColor)
792 return; 797 return;
793 realizeSaves(0); 798 realizeSaves(0);
794 setStrokeStyle(CanvasStyle::createFromString(color)); 799 setStrokeStyle(CanvasStyle::createFromString(color));
795 modifiableState().m_unparsedStrokeColor = color; 800 modifiableState().m_unparsedStrokeColor = color;
796 } 801 }
797 802
798 void CanvasRenderingContext2D::setStrokeColor(float grayLevel) 803 void CanvasRenderingContext2D::setStrokeColor(float grayLevel)
(...skipping 22 matching lines...) Expand all
821 setStrokeStyle(CanvasStyle::createFromRGBAChannels(r, g, b, a)); 826 setStrokeStyle(CanvasStyle::createFromRGBAChannels(r, g, b, a));
822 } 827 }
823 828
824 void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k , float a) 829 void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k , float a)
825 { 830 {
826 if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentCMYKA(c, m, y, k, a)) 831 if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentCMYKA(c, m, y, k, a))
827 return; 832 return;
828 setStrokeStyle(CanvasStyle::createFromCMYKAChannels(c, m, y, k, a)); 833 setStrokeStyle(CanvasStyle::createFromCMYKAChannels(c, m, y, k, a));
829 } 834 }
830 835
836 String CanvasRenderingContext2D::fillColor()
837 {
838 return fillStyle()->color();
839 }
840
831 void CanvasRenderingContext2D::setFillColor(const String& color) 841 void CanvasRenderingContext2D::setFillColor(const String& color)
832 { 842 {
833 if (color == state().m_unparsedFillColor) 843 if (color == state().m_unparsedFillColor)
834 return; 844 return;
835 realizeSaves(0); 845 realizeSaves(0);
836 setFillStyle(CanvasStyle::createFromString(color)); 846 setFillStyle(CanvasStyle::createFromString(color));
837 modifiableState().m_unparsedFillColor = color; 847 modifiableState().m_unparsedFillColor = color;
838 } 848 }
839 849
840 void CanvasRenderingContext2D::setFillColor(float grayLevel) 850 void CanvasRenderingContext2D::setFillColor(float grayLevel)
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 float sx, float sy, float sw, float sh, 1319 float sx, float sy, float sw, float sh,
1310 float dx, float dy, float dw, float dh, ExceptionState& exceptionState, 1320 float dx, float dy, float dw, float dh, ExceptionState& exceptionState,
1311 CompositeOperator op, blink::WebBlendMode blendMode, GraphicsContext* c) 1321 CompositeOperator op, blink::WebBlendMode blendMode, GraphicsContext* c)
1312 { 1322 {
1313 RefPtr<Image> image; 1323 RefPtr<Image> image;
1314 SourceImageStatus sourceImageStatus = InvalidSourceImageStatus; 1324 SourceImageStatus sourceImageStatus = InvalidSourceImageStatus;
1315 if (!imageSource->isVideoElement()) { 1325 if (!imageSource->isVideoElement()) {
1316 SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolati le : DontCopySourceImage; // Thunking for == 1326 SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolati le : DontCopySourceImage; // Thunking for ==
1317 image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus); 1327 image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus);
1318 if (sourceImageStatus == UndecodableSourceImageStatus) 1328 if (sourceImageStatus == UndecodableSourceImageStatus)
1319 exceptionState.throwDOMException(InvalidStateError, "The HTMLImageEl ement provided is in the 'broken' state."); 1329 exceptionState.ThrowDOMException(InvalidStateError, "The HTMLImageEl ement provided is in the 'broken' state.");
1320 if (!image || !image->width() || !image->height()) 1330 if (!image || !image->width() || !image->height())
1321 return; 1331 return;
1322 } 1332 }
1323 1333
1324 if (!c) 1334 if (!c)
1325 c = drawingContext(); 1335 c = drawingContext();
1326 if (!c) 1336 if (!c)
1327 return; 1337 return;
1328 1338
1329 if (!state().m_invertibleCTM) 1339 if (!state().m_invertibleCTM)
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1400 1410
1401 PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1) 1411 PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
1402 { 1412 {
1403 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); 1413 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1));
1404 return gradient.release(); 1414 return gradient.release();
1405 } 1415 }
1406 1416
1407 PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState& exceptionS tate) 1417 PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState& exceptionS tate)
1408 { 1418 {
1409 if (r0 < 0 || r1 < 0) { 1419 if (r0 < 0 || r1 < 0) {
1410 exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); 1420 exceptionState.ThrowDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1"));
1411 return nullptr; 1421 return nullptr;
1412 } 1422 }
1413 1423
1414 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); 1424 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
1415 return gradient.release(); 1425 return gradient.release();
1416 } 1426 }
1417 1427
1418 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(CanvasImageSou rce* imageSource, 1428 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(CanvasImageSou rce* imageSource,
1419 const String& repetitionType, ExceptionState& exceptionState) 1429 const String& repetitionType, ExceptionState& exceptionState)
1420 { 1430 {
1421 Pattern::RepeatMode repeatMode = CanvasPattern::parseRepetitionType(repetiti onType, exceptionState); 1431 Pattern::RepeatMode repeatMode = CanvasPattern::parseRepetitionType(repetiti onType, exceptionState);
1422 if (exceptionState.hadException()) 1432 if (exceptionState.had_exception())
1423 return nullptr; 1433 return nullptr;
1424 1434
1425 SourceImageStatus status; 1435 SourceImageStatus status;
1426 RefPtr<Image> imageForRendering = imageSource->getSourceImageForCanvas(CopyS ourceImageIfVolatile, &status); 1436 RefPtr<Image> imageForRendering = imageSource->getSourceImageForCanvas(CopyS ourceImageIfVolatile, &status);
1427 1437
1428 switch (status) { 1438 switch (status) {
1429 case NormalSourceImageStatus: 1439 case NormalSourceImageStatus:
1430 break; 1440 break;
1431 case ZeroSizeCanvasSourceImageStatus: 1441 case ZeroSizeCanvasSourceImageStatus:
1432 exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", imageSource->sourceSize().width() ? "height" : "width")); 1442 exceptionState.ThrowDOMException(InvalidStateError, String::format("The canvas %s is 0.", imageSource->sourceSize().width() ? "height" : "width"));
1433 return nullptr; 1443 return nullptr;
1434 case UndecodableSourceImageStatus: 1444 case UndecodableSourceImageStatus:
1435 exceptionState.throwDOMException(InvalidStateError, "Source image is in the 'broken' state."); 1445 exceptionState.ThrowDOMException(InvalidStateError, "Source image is in the 'broken' state.");
1436 return nullptr; 1446 return nullptr;
1437 case InvalidSourceImageStatus: 1447 case InvalidSourceImageStatus:
1438 imageForRendering = Image::nullImage(); 1448 imageForRendering = Image::nullImage();
1439 break; 1449 break;
1440 case IncompleteSourceImageStatus: 1450 case IncompleteSourceImageStatus:
1441 return nullptr; 1451 return nullptr;
1442 default: 1452 default:
1443 case ExternalSourceImageStatus: // should not happen when mode is CopySource ImageIfVolatile 1453 case ExternalSourceImageStatus: // should not happen when mode is CopySource ImageIfVolatile
1444 ASSERT_NOT_REACHED(); 1454 ASSERT_NOT_REACHED();
1445 return nullptr; 1455 return nullptr;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 } 1514 }
1505 1515
1506 PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtr<Image Data> imageData) const 1516 PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtr<Image Data> imageData) const
1507 { 1517 {
1508 return createEmptyImageData(imageData->size()); 1518 return createEmptyImageData(imageData->size());
1509 } 1519 }
1510 1520
1511 PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const 1521 PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const
1512 { 1522 {
1513 if (!sw || !sh) { 1523 if (!sw || !sh) {
1514 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width")); 1524 exceptionState.ThrowDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width"));
1515 return nullptr; 1525 return nullptr;
1516 } 1526 }
1517 1527
1518 FloatSize logicalSize(fabs(sw), fabs(sh)); 1528 FloatSize logicalSize(fabs(sw), fabs(sh));
1519 if (!logicalSize.isExpressibleAsIntSize()) 1529 if (!logicalSize.isExpressibleAsIntSize())
1520 return nullptr; 1530 return nullptr;
1521 1531
1522 IntSize size = expandedIntSize(logicalSize); 1532 IntSize size = expandedIntSize(logicalSize);
1523 if (size.width() < 1) 1533 if (size.width() < 1)
1524 size.setWidth(1); 1534 size.setWidth(1);
1525 if (size.height() < 1) 1535 if (size.height() < 1)
1526 size.setHeight(1); 1536 size.setHeight(1);
1527 1537
1528 return createEmptyImageData(size); 1538 return createEmptyImageData(size);
1529 } 1539 }
1530 1540
1531 PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const 1541 PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const
1532 { 1542 {
1533 if (!sw || !sh) 1543 if (!sw || !sh)
1534 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width")); 1544 exceptionState.ThrowDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width"));
1535 1545
1536 if (exceptionState.hadException()) 1546 if (exceptionState.had_exception())
1537 return nullptr; 1547 return nullptr;
1538 1548
1539 if (sw < 0) { 1549 if (sw < 0) {
1540 sx += sw; 1550 sx += sw;
1541 sw = -sw; 1551 sw = -sw;
1542 } 1552 }
1543 if (sh < 0) { 1553 if (sh < 0) {
1544 sy += sh; 1554 sy += sh;
1545 sh = -sh; 1555 sh = -sh;
1546 } 1556 }
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
2116 c->clearShadow(); 2126 c->clearShadow();
2117 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal); 2127 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
2118 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); 2128 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2119 c->restore(); 2129 c->restore();
2120 validateStateStack(); 2130 validateStateStack();
2121 didDraw(dirtyRect); 2131 didDraw(dirtyRect);
2122 } 2132 }
2123 2133
2124 void CanvasRenderingContext2D::addHitRegion(ExceptionState& exceptionState) 2134 void CanvasRenderingContext2D::addHitRegion(ExceptionState& exceptionState)
2125 { 2135 {
2126 addHitRegion(Dictionary(), exceptionState);
2127 }
2128
2129 void CanvasRenderingContext2D::addHitRegion(const Dictionary& options, Exception State& exceptionState)
2130 {
2131 HitRegionOptions passOptions; 2136 HitRegionOptions passOptions;
2132 2137
2133 options.getWithUndefinedOrNullCheck("id", passOptions.id);
2134 options.getWithUndefinedOrNullCheck("control", passOptions.control);
2135 if (passOptions.id.isEmpty() && !passOptions.control) {
2136 exceptionState.throwDOMException(NotSupportedError, "Both id and control are null.");
2137 return;
2138 }
2139
2140 RefPtr<Path2D> path2d; 2138 RefPtr<Path2D> path2d;
2141 options.getWithUndefinedOrNullCheck("path", path2d);
2142 Path hitRegionPath = path2d ? path2d->path() : m_path; 2139 Path hitRegionPath = path2d ? path2d->path() : m_path;
2143 2140
2144 FloatRect clipBounds; 2141 FloatRect clipBounds;
2145 GraphicsContext* context = drawingContext(); 2142 GraphicsContext* context = drawingContext();
2146 2143
2147 if (hitRegionPath.isEmpty() || !context || !state().m_invertibleCTM 2144 if (hitRegionPath.isEmpty() || !context || !state().m_invertibleCTM
2148 || !context->getTransformedClipBounds(&clipBounds)) { 2145 || !context->getTransformedClipBounds(&clipBounds)) {
2149 exceptionState.throwDOMException(NotSupportedError, "The specified path has no pixels."); 2146 exceptionState.ThrowDOMException(NotSupportedError, "The specified path has no pixels.");
2150 return; 2147 return;
2151 } 2148 }
2152 2149
2153 hitRegionPath.transform(state().m_transform); 2150 hitRegionPath.transform(state().m_transform);
2154 2151
2155 if (hasClip()) { 2152 if (hasClip()) {
2156 // FIXME: The hit regions should take clipping region into account. 2153 // FIXME: The hit regions should take clipping region into account.
2157 // However, we have no way to get the region from canvas state stack by now. 2154 // However, we have no way to get the region from canvas state stack by now.
2158 // See http://crbug.com/387057 2155 // See http://crbug.com/387057
2159 exceptionState.throwDOMException(NotSupportedError, "The specified path has no pixels."); 2156 exceptionState.ThrowDOMException(NotSupportedError, "The specified path has no pixels.");
2160 return; 2157 return;
2161 } 2158 }
2162 2159
2163 passOptions.path = hitRegionPath; 2160 passOptions.path = hitRegionPath;
2164 2161
2165 String fillRuleString; 2162 // FIXME(Dictionary): Way to specify fillRule
2166 options.getWithUndefinedOrNullCheck("fillRule", fillRuleString); 2163 passOptions.fillRule = RULE_NONZERO;
2167 if (fillRuleString.isEmpty() || fillRuleString != "evenodd")
2168 passOptions.fillRule = RULE_NONZERO;
2169 else
2170 passOptions.fillRule = RULE_EVENODD;
2171 2164
2172 addHitRegionInternal(passOptions, exceptionState); 2165 addHitRegionInternal(passOptions, exceptionState);
2173 } 2166 }
2174 2167
2175 void CanvasRenderingContext2D::addHitRegionInternal(const HitRegionOptions& opti ons, ExceptionState& exceptionState) 2168 void CanvasRenderingContext2D::addHitRegionInternal(const HitRegionOptions& opti ons, ExceptionState& exceptionState)
2176 { 2169 {
2177 if (!m_hitRegionManager) 2170 if (!m_hitRegionManager)
2178 m_hitRegionManager = HitRegionManager::create(); 2171 m_hitRegionManager = HitRegionManager::create();
2179 2172
2180 // Remove previous region (with id or control) 2173 // Remove previous region (with id or control)
(...skipping 27 matching lines...) Expand all
2208 2201
2209 unsigned CanvasRenderingContext2D::hitRegionsCount() const 2202 unsigned CanvasRenderingContext2D::hitRegionsCount() const
2210 { 2203 {
2211 if (m_hitRegionManager) 2204 if (m_hitRegionManager)
2212 return m_hitRegionManager->getHitRegionsCount(); 2205 return m_hitRegionManager->getHitRegionsCount();
2213 2206
2214 return 0; 2207 return 0;
2215 } 2208 }
2216 2209
2217 } // namespace blink 2210 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/core/html/canvas/CanvasRenderingContext2D.h ('k') | sky/engine/core/html/canvas/CanvasRenderingContext2D.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698