/* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2006-03-02 * Description : DColor methods for composing * * Copyright (C) 2006-2007 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ // Integer arithmetic inspired by DirectFB, // src/gfx/generic/generic.c and src/display/idirectfbsurface.c: /* (c) Copyright 2000-2002 convergence integrated media GmbH (c) Copyright 2002-2005 convergence GmbH. All rights reserved. Written by Denis Oliver Kropp , Andreas Hundt , Sven Neumann , Ville Syrj�l� and Claudio Ciccani . */ // C++ includes. #include // Local includes. #include "dcolorcomposer.h" namespace Digikam { class DColorComposerPorterDuffNone : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffClear : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); virtual void compose(DColor &dest, DColor src, MultiplicationFlags multiplicationFlags); }; class DColorComposerPorterDuffSrc : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); virtual void compose(DColor &dest, DColor src, MultiplicationFlags multiplicationFlags); }; class DColorComposerPorterDuffSrcOver : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffDstOver : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffSrcIn : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffDstIn : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffSrcOut : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffDstOut : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffSrcAtop : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffDstAtop : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; class DColorComposerPorterDuffXor : public DColorComposer { public: virtual void compose(DColor &dest, DColor src); }; // Porter-Duff None // component = (source * sa + destination * (1-sa)) // Src blending function Src Alpha // Dst blending function Inv Src Alpha void DColorComposerPorterDuffNone::compose(DColor &dest, DColor src) { // preserve src alpha value for dest blending, // src.alpha() will be changed after blending src int sa = src.alpha(); if (dest.sixteenBit()) { src.blendAlpha16(sa); dest.blendInvAlpha16(sa); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendAlpha8(sa); dest.blendInvAlpha8(sa); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Clear // component = (source * 0 + destination * 0) // Src blending function Zero // Dst blending function Zero void DColorComposerPorterDuffClear::compose(DColor &dest, DColor src) { src.blendZero(); dest.blendZero(); dest.blendAdd(src); } void DColorComposerPorterDuffClear::compose(DColor &dest, DColor src, MultiplicationFlags) { // skip pre- and demultiplication compose(dest, src); } // Porter-Duff Src // Normal Painter's algorithm // component = (source * 1 + destination * 0) // Src blending function One // Dst blending function Zero void DColorComposerPorterDuffSrc::compose(DColor &dest, DColor src) { // src: no-op dest.blendZero(); dest.blendAdd(src); } void DColorComposerPorterDuffSrc::compose(DColor &dest, DColor src, MultiplicationFlags) { // skip pre- and demultiplication compose(dest, src); } // Porter-Duff Src Over // component = (source * 1 + destination * (1-sa)) // Src blending function One // Dst blending function Inv Src Alpha void DColorComposerPorterDuffSrcOver::compose(DColor &dest, DColor src) { if (dest.sixteenBit()) { // src: no-op dest.blendInvAlpha16(src.alpha()); dest.blendAdd(src); dest.blendClamp16(); } else { // src: no-op dest.blendInvAlpha8(src.alpha()); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Dst over // component = (source * (1.0-da) + destination * 1) // Src blending function Inv Dst Alpha // Dst blending function One void DColorComposerPorterDuffDstOver::compose(DColor &dest, DColor src) { if (dest.sixteenBit()) { src.blendInvAlpha16(dest.alpha()); // dest: no-op dest.blendAdd(src); dest.blendClamp16(); } else { src.blendInvAlpha8(dest.alpha()); // dest: no-op dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Src In // component = (source * da + destination * 0) // Src blending function Dst Alpha // Dst blending function Zero void DColorComposerPorterDuffSrcIn::compose(DColor &dest, DColor src) { if (dest.sixteenBit()) { src.blendAlpha16(dest.alpha()); dest.blendZero(); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendAlpha8(dest.alpha()); dest.blendZero(); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Dst In // component = (source * 0 + destination * sa) // Src blending function Zero // Dst blending function Src Alpha void DColorComposerPorterDuffDstIn::compose(DColor &dest, DColor src) { int sa = src.alpha(); if (dest.sixteenBit()) { src.blendZero(); dest.blendAlpha16(sa); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendZero(); dest.blendAlpha8(sa); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Src Out // component = (source * (1-da) + destination * 0) // Src blending function Inv Dst Alpha // Dst blending function Zero void DColorComposerPorterDuffSrcOut::compose(DColor &dest, DColor src) { if (dest.sixteenBit()) { src.blendInvAlpha16(dest.alpha()); dest.blendZero(); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendInvAlpha8(dest.alpha()); dest.blendZero(); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Dst Out // component = (source * 0 + destination * (1-sa)) // Src blending function Zero // Dst blending function Inv Src Alpha void DColorComposerPorterDuffDstOut::compose(DColor &dest, DColor src) { int sa = src.alpha(); if (dest.sixteenBit()) { src.blendZero(); dest.blendInvAlpha16(sa); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendZero(); dest.blendInvAlpha8(sa); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Src Atop // component = (source * da + destination * (1-sa)) // Src blending function Dst Alpha // Dst blending function Inv Src Alpha void DColorComposerPorterDuffSrcAtop::compose(DColor &dest, DColor src) { int sa = src.alpha(); if (dest.sixteenBit()) { src.blendAlpha16(dest.alpha()); dest.blendInvAlpha16(sa); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendAlpha8(dest.alpha()); dest.blendInvAlpha8(sa); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Dst Atop // component = (source * (1-da) + destination * sa) // Src blending function Inv Dest Alpha // Dst blending function Src Alpha void DColorComposerPorterDuffDstAtop::compose(DColor &dest, DColor src) { int sa = src.alpha(); if (dest.sixteenBit()) { src.blendInvAlpha16(dest.alpha()); dest.blendAlpha16(sa); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendInvAlpha8(dest.alpha()); dest.blendInvAlpha8(sa); dest.blendAdd(src); dest.blendClamp8(); } } // Porter-Duff Xor // component = (source * (1-da) + destination * (1-sa)) // Src blending function Inv Dst Alpha // Dst blending function Inv Src Alpha void DColorComposerPorterDuffXor::compose(DColor &dest, DColor src) { int sa = src.alpha(); if (dest.sixteenBit()) { src.blendInvAlpha16(dest.alpha()); dest.blendInvAlpha16(sa); dest.blendAdd(src); dest.blendClamp16(); } else { src.blendInvAlpha8(dest.alpha()); dest.blendInvAlpha8(sa); dest.blendAdd(src); dest.blendClamp8(); } } // ----------------------------------------------------------------------- void DColorComposer::compose(DColor &dest, DColor src, DColorComposer::MultiplicationFlags multiplicationFlags) { if (multiplicationFlags & PremultiplySrc) src.premultiply(); if (multiplicationFlags & PremultiplyDst) dest.premultiply(); compose(dest, src); if (multiplicationFlags & DemultiplyDst) dest.demultiply(); } DColorComposer *DColorComposer::getComposer(DColorComposer::CompositingOperation rule) { switch(rule) { case PorterDuffNone: return new DColorComposerPorterDuffNone; case PorterDuffClear: return new DColorComposerPorterDuffClear; case PorterDuffSrc: return new DColorComposerPorterDuffSrc; case PorterDuffSrcOver: return new DColorComposerPorterDuffSrcOver; case PorterDuffDstOver: return new DColorComposerPorterDuffDstOver; case PorterDuffSrcIn: return new DColorComposerPorterDuffSrcIn; case PorterDuffDstIn: return new DColorComposerPorterDuffDstIn; case PorterDuffSrcOut: return new DColorComposerPorterDuffSrcOut; case PorterDuffDstOut: return new DColorComposerPorterDuffDstOut; case PorterDuffSrcAtop: return new DColorComposerPorterDuffDstOut; case PorterDuffDstAtop: return new DColorComposerPorterDuffDstOut; case PorterDuffXor: return new DColorComposerPorterDuffDstOut; } return 0; } } // namespace DigiKam