1 /* _______ __ __ __ ______ __ __ _______ __ __ 2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 8 * 9 * Copyright (c) 2004 - 2008 Olof Naess�n and Per Larsson 10 * 11 * 12 * Per Larsson a.k.a finalman 13 * Olof Naess�n a.k.a jansem/yakslem 14 * 15 * Visit: http://guichan.sourceforge.net 16 * 17 * License: (BSD) 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in 25 * the documentation and/or other materials provided with the 26 * distribution. 27 * 3. Neither the name of Guichan nor the names of its contributors may 28 * be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 37 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 39 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 /* 45 * For comments regarding functions please see the header file. 46 */ 47 48 #include "guichan/graphics.hpp" 49 50 #include "guichan/exception.hpp" 51 #include "guichan/font.hpp" 52 #include "guichan/image.hpp" 53 54 namespace gcn 55 { 56 Graphics()57 Graphics::Graphics() 58 { 59 mFont = NULL; 60 } 61 pushClipArea(Rectangle area)62 bool Graphics::pushClipArea(Rectangle area) 63 { 64 // Ignore area with a negate width or height 65 // by simple pushing an empty clip area 66 // to the stack. 67 if (area.width < 0 || area.height < 0) 68 { 69 ClipRectangle carea; 70 mClipStack.push(carea); 71 return true; 72 } 73 74 if (mClipStack.empty()) 75 { 76 ClipRectangle carea; 77 carea.x = area.x; 78 carea.y = area.y; 79 carea.width = area.width; 80 carea.height = area.height; 81 carea.xOffset = area.x; 82 carea.yOffset = area.y; 83 mClipStack.push(carea); 84 return true; 85 } 86 87 const ClipRectangle &top = mClipStack.top(); 88 ClipRectangle carea; 89 carea = area; 90 carea.xOffset = top.xOffset + carea.x; 91 carea.yOffset = top.yOffset + carea.y; 92 carea.x += top.xOffset; 93 carea.y += top.yOffset; 94 95 // Clamp the pushed clip rectangle. 96 if (carea.x < top.x) 97 { 98 carea.x = top.x; 99 } 100 101 if (carea.y < top.y) 102 { 103 carea.y = top.y; 104 } 105 106 if (carea.x + carea.width > top.x + top.width) 107 { 108 carea.width = top.x + top.width - carea.x; 109 110 if (carea.width < 0) 111 { 112 carea.width = 0; 113 } 114 } 115 116 if (carea.y + carea.height > top.y + top.height) 117 { 118 carea.height = top.y + top.height - carea.y; 119 120 if (carea.height < 0) 121 { 122 carea.height = 0; 123 } 124 } 125 126 bool result = carea.isIntersecting(top); 127 128 mClipStack.push(carea); 129 130 return result; 131 } 132 popClipArea()133 void Graphics::popClipArea() 134 { 135 136 if (mClipStack.empty()) 137 { 138 throw GCN_EXCEPTION("Tried to pop clip area from empty stack."); 139 } 140 141 mClipStack.pop(); 142 } 143 getCurrentClipArea()144 const ClipRectangle& Graphics::getCurrentClipArea() 145 { 146 if (mClipStack.empty()) 147 { 148 throw GCN_EXCEPTION("The clip area stack is empty."); 149 } 150 151 return mClipStack.top(); 152 } 153 drawImage(const Image * image,int dstX,int dstY)154 void Graphics::drawImage(const Image* image, int dstX, int dstY) 155 { 156 drawImage(image, 0, 0, dstX, dstY, image->getWidth(), image->getHeight()); 157 } 158 setFont(Font * font)159 void Graphics::setFont(Font* font) 160 { 161 mFont = font; 162 } 163 drawText(const std::string & text,int x,int y,Alignment alignment)164 void Graphics::drawText(const std::string& text, int x, int y, 165 Alignment alignment) 166 { 167 if (mFont == NULL) 168 { 169 throw GCN_EXCEPTION("No font set."); 170 } 171 172 switch (alignment) 173 { 174 case LEFT: 175 mFont->drawString(this, text, x, y); 176 break; 177 case CENTER: 178 mFont->drawString(this, text, x - mFont->getWidth(text) / 2, y); 179 break; 180 case RIGHT: 181 mFont->drawString(this, text, x - mFont->getWidth(text), y); 182 break; 183 default: 184 throw GCN_EXCEPTION("Unknown alignment."); 185 } 186 } 187 } 188