1 /*************************************************************************** 2 * Copyright (c) 2017-2019 by the fifechan team * 3 * https://github.com/fifengine/fifechan * 4 * This file is part of fifechan. * 5 * * 6 * fifechan is free software; you can redistribute it and/or * 7 * modify it under the terms of the GNU Lesser General Public * 8 * License as published by the Free Software Foundation; either * 9 * version 2.1 of the License, or (at your option) any later version. * 10 * * 11 * This library is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 14 * Lesser General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU Lesser General Public * 17 * License along with this library; if not, write to the * 18 * Free Software Foundation, Inc., * 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 20 ***************************************************************************/ 21 22 /* _______ __ __ __ ______ __ __ _______ __ __ 23 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 24 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 25 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 26 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 27 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 28 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 29 * 30 * Copyright (c) 2008 Mehdi Abbad a.k.a slyf0x 31 * 32 * 33 * Per Larsson a.k.a finalman 34 * Olof Naess�n a.k.a jansem/yakslem 35 * 36 * Visit: http://guichan.sourceforge.net 37 * 38 * License: (BSD) 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in 46 * the documentation and/or other materials provided with the 47 * distribution. 48 * 3. Neither the name of Guichan nor the names of its contributors may 49 * be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 53 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 54 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 55 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 56 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 57 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 58 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 59 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 60 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 61 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 62 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 63 */ 64 65 #include "fifechan/cairo/cairographics.hpp" 66 67 #include "fifechan/exception.hpp" 68 #include "fifechan/cairo/cairofont.hpp" 69 #include "fifechan/cairo/cairoimage.hpp" 70 71 namespace fcn 72 { 73 CairoGraphics(cairo_surface_t * TargetSurface,int Width,int Height)74 CairoGraphics::CairoGraphics(cairo_surface_t* TargetSurface,int Width,int Height) 75 { 76 if (!TargetSurface) 77 { 78 FCN_EXCEPTION("Specified reference to target cairo surface is null!"); 79 } 80 mCairoContext=cairo_create(TargetSurface); 81 mTargetSurface=TargetSurface; 82 mHeight=Height; 83 mWidth=Width; 84 } 85 ~CairoGraphics()86 CairoGraphics::~CairoGraphics() 87 { 88 cairo_destroy(mCairoContext); 89 } _beginDraw()90 void CairoGraphics::_beginDraw() 91 { 92 pushClipArea(Rectangle(0,0,mWidth,mHeight)); 93 cairo_push_group(mCairoContext); 94 } 95 _endDraw()96 void CairoGraphics::_endDraw() 97 { 98 cairo_pop_group_to_source(mCairoContext); 99 cairo_paint(mCairoContext); 100 popClipArea(); 101 } 102 pushClipArea(Rectangle area)103 bool CairoGraphics::pushClipArea(Rectangle area) 104 { 105 bool result=Graphics::pushClipArea(area); 106 ClipRectangle& mCurrentDrawingArea=mClipStack.top(); 107 108 //saves the current context options including clipping area 109 // ! Actualy saves all drawing options. 110 cairo_save(mCairoContext); 111 //create a rectangle corresponding to the clipping area 112 cairo_rectangle(mCairoContext, 113 mCurrentDrawingArea.xOffset, 114 mCurrentDrawingArea.yOffset, 115 area.width, 116 area.height); 117 cairo_clip(mCairoContext); 118 return result; 119 } 120 popClipArea()121 void CairoGraphics::popClipArea() 122 { 123 Graphics::popClipArea(); 124 //restore drawing options 125 cairo_restore(mCairoContext); 126 } 127 drawImage(const Image * image,int srcX,int srcY,int dstX,int dstY,int width,int height)128 void CairoGraphics::drawImage(const Image* image, 129 int srcX, 130 int srcY, 131 int dstX, 132 int dstY, 133 int width, 134 int height) 135 { 136 const CairoImage *srcImage=dynamic_cast<const CairoImage*>(image); 137 if (!srcImage) 138 { 139 throw FCN_EXCEPTION("Passed image reference is null or not of type fcn::CairoImage*."); 140 } 141 const ClipRectangle& top=mClipStack.top(); 142 143 cairo_save(mCairoContext); 144 145 cairo_set_source_surface(mCairoContext, 146 srcImage->mCairoSurface, 147 top.xOffset + (dstX - srcX), 148 top.yOffset + (dstY - srcY)); 149 //sets the clipping area 150 cairo_rectangle(mCairoContext, 151 top.xOffset + dstX, 152 top.yOffset + dstY, 153 width,height); 154 cairo_clip(mCairoContext); 155 156 //paint and restore the context 157 cairo_paint(mCairoContext); 158 cairo_restore (mCairoContext); 159 } 160 drawRectangle(const Rectangle & rectangle)161 void CairoGraphics::drawRectangle(const Rectangle& rectangle) 162 { 163 ClipRectangle& mCurrentDrawingArea=mClipStack.top(); 164 cairo_rectangle(mCairoContext, 165 mCurrentDrawingArea.xOffset+rectangle.x, 166 mCurrentDrawingArea.yOffset+rectangle.y, 167 rectangle.width, 168 rectangle.height); 169 SetCurrentColorAsSource(); 170 cairo_stroke(mCairoContext); 171 } 172 fillRectangle(const Rectangle & rectangle)173 void CairoGraphics::fillRectangle(const Rectangle& rectangle) 174 { 175 ClipRectangle& mCurrentDrawingArea=mClipStack.top(); 176 cairo_rectangle(mCairoContext, 177 mCurrentDrawingArea.xOffset+rectangle.x, 178 mCurrentDrawingArea.yOffset+rectangle.y, 179 rectangle.width, 180 rectangle.height); 181 SetCurrentColorAsSource(); 182 cairo_fill(mCairoContext); 183 } 184 drawPoint(int x,int y)185 void CairoGraphics::drawPoint(int x, int y) 186 { 187 ClipRectangle& mCurrentDrawingArea=mClipStack.top(); 188 cairo_rectangle(mCairoContext, 189 mCurrentDrawingArea.xOffset+x, 190 mCurrentDrawingArea.yOffset+y, 191 1,1); 192 SetCurrentColorAsSource(); 193 cairo_fill(mCairoContext); 194 } 195 drawLine(int x1,int y1,int x2,int y2)196 void CairoGraphics::drawLine(int x1, int y1, int x2, int y2) 197 { 198 ClipRectangle& mCurrentDrawingArea=mClipStack.top(); 199 cairo_move_to(mCairoContext, 200 mCurrentDrawingArea.xOffset+x1, 201 mCurrentDrawingArea.yOffset+y1); 202 203 cairo_line_to(mCairoContext, 204 mCurrentDrawingArea.xOffset+x2, 205 mCurrentDrawingArea.yOffset+y2); 206 SetCurrentColorAsSource(); 207 cairo_set_line_width(mCairoContext,1.0f); 208 cairo_set_line_cap(mCairoContext, CAIRO_LINE_CAP_SQUARE); 209 cairo_stroke(mCairoContext); 210 } 211 setColor(const Color & color)212 void CairoGraphics::setColor(const Color& color) 213 { 214 mColor = color; 215 mColorR= mColor.r/255.0; 216 mColorG= mColor.g/255.0; 217 mColorB= mColor.b/255.0; 218 mColorA= mColor.a/255.0; 219 } 220 getColor() const221 const Color& CairoGraphics::getColor() const 222 { 223 return mColor; 224 } 225 SetCurrentColorAsSource()226 void CairoGraphics::SetCurrentColorAsSource() 227 { 228 cairo_set_source_rgba(mCairoContext, mColorR, mColorG, mColorB, mColorA); 229 } 230 GetContext()231 cairo_t* CairoGraphics::GetContext() 232 { 233 return mCairoContext; 234 } 235 } 236