1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkCoreBlitters_DEFINED 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkCoreBlitters_DEFINED 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkBitmapProcShader.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h" 14a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkShader.h" 15a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkSmallAllocator.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkRasterBlitter : public SkBlitter { 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1941e010cb901c0da9066c4df562030808c9ccd7f8reed SkRasterBlitter(const SkPixmap& device) : fDevice(device) {} 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 2241e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap fDevice; 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkBlitter INHERITED; 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkShaderBlitter : public SkRasterBlitter { 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org /** 3187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org * The storage for shaderContext is owned by the caller, but the object itself is not. 3287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org * The blitter only ensures that the storage always holds a live object, but it may 3387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org * exchange that object. 3487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org */ 3541e010cb901c0da9066c4df562030808c9ccd7f8reed SkShaderBlitter(const SkPixmap& device, const SkPaint& paint, 3687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~SkShaderBlitter(); 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org /** 4087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org * Create a new shader context and uses it instead of the old one if successful. 4187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org * Will create the context at the same location as the old one (this is safe 4287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org * because the shader itself is unchanged). 4387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org */ 4436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool resetShaderContext(const SkShader::ContextRec&) override; 4587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 4636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkShader::Context* getShaderContext() const override { return fShaderContext; } 4787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 4987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org uint32_t fShaderFlags; 5087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkShader* fShader; 5187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* fShaderContext; 52a34be68a7eff0ae475b194f8a29975460cf3e456reed bool fConstInY; 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // illegal 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShaderBlitter& operator=(const SkShaderBlitter&); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkRasterBlitter INHERITED; 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 63126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comclass SkA8_Coverage_Blitter : public SkRasterBlitter { 64126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.compublic: 6541e010cb901c0da9066c4df562030808c9ccd7f8reed SkA8_Coverage_Blitter(const SkPixmap& device, const SkPaint& paint); 6636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitH(int x, int y, int width) override; 6736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override; 6836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitV(int x, int y, int height, SkAlpha alpha) override; 6936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitRect(int x, int y, int width, int height) override; 7036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitMask(const SkMask&, const SkIRect&) override; 7141e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* justAnOpaqueColor(uint32_t*) override; 72126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com}; 73126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkA8_Blitter : public SkRasterBlitter { 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 7641e010cb901c0da9066c4df562030808c9ccd7f8reed SkA8_Blitter(const SkPixmap& device, const SkPaint& paint); 773dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitH(int x, int y, int width) override; 783dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override; 793dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitV(int x, int y, int height, SkAlpha alpha) override; 803dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitRect(int x, int y, int width, int height) override; 813dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitMask(const SkMask&, const SkIRect&) override; 823dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed const SkPixmap* justAnOpaqueColor(uint32_t*) override; 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned fSrcA; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // illegal 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkA8_Blitter& operator=(const SkA8_Blitter&); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkRasterBlitter INHERITED; 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkA8_Shader_Blitter : public SkShaderBlitter { 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 9541e010cb901c0da9066c4df562030808c9ccd7f8reed SkA8_Shader_Blitter(const SkPixmap& device, const SkPaint& paint, 9687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext); 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~SkA8_Shader_Blitter(); 983dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitH(int x, int y, int width) override; 993dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override; 1003dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitMask(const SkMask&, const SkIRect&) override; 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXfermode* fXfermode; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* fBuffer; 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* fAAExpand; 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // illegal 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkA8_Shader_Blitter& operator=(const SkA8_Shader_Blitter&); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShaderBlitter INHERITED; 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////// 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkARGB32_Blitter : public SkRasterBlitter { 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 11741e010cb901c0da9066c4df562030808c9ccd7f8reed SkARGB32_Blitter(const SkPixmap& device, const SkPaint& paint); 1183dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitH(int x, int y, int width) override; 1193dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override; 1203dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitV(int x, int y, int height, SkAlpha alpha) override; 1213dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitRect(int x, int y, int width, int height) override; 1223dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitMask(const SkMask&, const SkIRect&) override; 1233dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed const SkPixmap* justAnOpaqueColor(uint32_t*) override; 1246983f66d8b3a489133b751e2cef03e72a03bfeaereed void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override; 1256983f66d8b3a489133b751e2cef03e72a03bfeaereed void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 128ee467ee79d449ebe6ae7f7946e613cc70a479c69reed@google.com SkColor fColor; 129ee467ee79d449ebe6ae7f7946e613cc70a479c69reed@google.com SkPMColor fPMColor; 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned fSrcA, fSrcR, fSrcG, fSrcB; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // illegal 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkARGB32_Blitter& operator=(const SkARGB32_Blitter&); 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkRasterBlitter INHERITED; 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 140dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.comclass SkARGB32_Opaque_Blitter : public SkARGB32_Blitter { 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 14241e010cb901c0da9066c4df562030808c9ccd7f8reed SkARGB32_Opaque_Blitter(const SkPixmap& device, const SkPaint& paint) 143dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com : INHERITED(device, paint) { SkASSERT(paint.getAlpha() == 0xFF); } 1443dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitMask(const SkMask&, const SkIRect&) override; 1456983f66d8b3a489133b751e2cef03e72a03bfeaereed void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override; 1466983f66d8b3a489133b751e2cef03e72a03bfeaereed void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override; 147dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkARGB32_Blitter INHERITED; 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 152dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.comclass SkARGB32_Black_Blitter : public SkARGB32_Opaque_Blitter { 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 15441e010cb901c0da9066c4df562030808c9ccd7f8reed SkARGB32_Black_Blitter(const SkPixmap& device, const SkPaint& paint) 155dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com : INHERITED(device, paint) {} 1563dfd133882fe9d9dc9db0897deac1ac1f4c99e01reed void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override; 1576983f66d8b3a489133b751e2cef03e72a03bfeaereed void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override; 1586983f66d8b3a489133b751e2cef03e72a03bfeaereed void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override; 159b602b8e5334edc0bfcdf086c2ea58e2b5d5f1f3breed@android.com 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 161dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com typedef SkARGB32_Opaque_Blitter INHERITED; 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkARGB32_Shader_Blitter : public SkShaderBlitter { 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 16641e010cb901c0da9066c4df562030808c9ccd7f8reed SkARGB32_Shader_Blitter(const SkPixmap& device, const SkPaint& paint, 16787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~SkARGB32_Shader_Blitter(); 16936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitH(int x, int y, int width) override; 17036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitV(int x, int y, int height, SkAlpha alpha) override; 17136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitRect(int x, int y, int width, int height) override; 17236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitAntiH(int x, int y, const SkAlpha[], const int16_t[]) override; 17336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitMask(const SkMask&, const SkIRect&) override; 174395eabeb0e72334c45324874c6e009b54634df21reed 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 176c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com SkXfermode* fXfermode; 177c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com SkPMColor* fBuffer; 178c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com SkBlitRow::Proc32 fProc32; 179c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com SkBlitRow::Proc32 fProc32Blend; 18013201e74f43b9c5fa173339eb36de515370e6973reed@google.com bool fShadeDirectlyIntoDevice; 181395eabeb0e72334c45324874c6e009b54634df21reed 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // illegal 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkARGB32_Shader_Blitter& operator=(const SkARGB32_Shader_Blitter&); 184395eabeb0e72334c45324874c6e009b54634df21reed 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShaderBlitter INHERITED; 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188a34be68a7eff0ae475b194f8a29975460cf3e456reedSkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint, 189a34be68a7eff0ae475b194f8a29975460cf3e456reed SkShader::Context* shaderContext, 190a34be68a7eff0ae475b194f8a29975460cf3e456reed SkTBlitterAllocator* allocator); 191a34be68a7eff0ae475b194f8a29975460cf3e456reed 192a34be68a7eff0ae475b194f8a29975460cf3e456reedSkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint, 193a34be68a7eff0ae475b194f8a29975460cf3e456reed SkShader::Context* shaderContext, 194a34be68a7eff0ae475b194f8a29975460cf3e456reed SkTBlitterAllocator* allocator); 195395eabeb0e72334c45324874c6e009b54634df21reed 1961fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com/////////////////////////////////////////////////////////////////////////////// 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1981fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com/* These return the correct subclass of blitter for their device config. 1991fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com 2001fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com Currently, they make the following assumptions about the state of the 2011fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com paint: 202981d4798007b91e2e19c13b171583927a56df63breed@google.com 2031fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com 1. If there is an xfermode, there will also be a shader 2041fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com 2. If there is a colorfilter, there will be a shader that itself handles 2051fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com calling the filter, so the blitter can always ignore the colorfilter obj 2061fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com 2071fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com These pre-conditions must be handled by the caller, in our case 2081fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com SkBlitter::Choose(...) 2091fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com */ 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21141e010cb901c0da9066c4df562030808c9ccd7f8reedSkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint, 21287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext, 213a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator* allocator); 2141fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 216