/* * The Mana Client * Copyright (C) 2004-2009 The Mana World Development Team * Copyright (C) 2009-2012 The Mana Developers * * This file is part of The Mana Client. * * 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 of the License, or * 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "graphics.h" #include "gui/truetypefont.h" #include "resources/theme.h" #include void Graphics::updateSize(int width, int height, float /*scale*/) { mWidth = width; mHeight = height; } bool Graphics::drawImage(const Image *image, int x, int y) { if (!image) return false; return drawImage(image, 0, 0, x, y, image->getWidth(), image->getHeight()); } bool Graphics::drawImageF(const Image *image, float x, float y) { if (!image) return false; return drawImageF(image, 0, 0, x, y, image->getWidth(), image->getHeight()); } bool Graphics::drawRescaledImage(const Image *image, int x, int y, int width, int height) { if (!image) return false; return drawRescaledImage(image, 0, 0, x, y, image->getWidth(), image->getHeight(), width, height); } bool Graphics::drawRescaledImageF(const Image *image, int srcX, int srcY, float dstX, float dstY, int width, int height, float desiredWidth, float desiredHeight, bool useColor) { return drawRescaledImage(image, srcX, srcY, static_cast(dstX), static_cast(dstY), width, height, static_cast(desiredWidth), static_cast(desiredHeight), useColor); } bool Graphics::drawImage(const Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height, bool useColor) { return drawRescaledImage(image, srcX, srcY, dstX, dstY, width, height, width, height, useColor); } bool Graphics::drawImageF(const Image *image, int srcX, int srcY, float dstX, float dstY, int width, int height, bool useColor) { return drawRescaledImageF(image, srcX, srcY, dstX, dstY, width, height, width, height, useColor); } void Graphics::drawImagePattern(const Image *image, int x, int y, int w, int h) { if (!image) return; drawRescaledImagePattern(image, x, y, w, h, image->getWidth(), image->getHeight()); } void Graphics::drawRescaledImagePattern(const Image *image, int x, int y, int w, int h, int scaledWidth, int scaledHeight) { drawRescaledImagePattern(image, 0, 0, image->getWidth(), image->getHeight(), x, y, w, h, scaledWidth, scaledHeight); } void Graphics::drawImageRect(const ImageRect &imgRect, int x, int y, int w, int h) { const int srcGridX[4] = {0, imgRect.left, imgRect.image->getWidth() - imgRect.right, imgRect.image->getWidth()}; const int srcGridY[4] = {0, imgRect.top, imgRect.image->getHeight() - imgRect.bottom, imgRect.image->getHeight()}; const int dstGridX[4] = {x, x + imgRect.left, x + w - imgRect.right, x + w}; const int dstGridY[4] = {y, y + imgRect.top, y + h - imgRect.bottom, y + h}; for (unsigned ix = 0; ix < 3; ix++) { for (unsigned iy = 0; iy < 3; iy++) { const int srcW = srcGridX[ix + 1] - srcGridX[ix]; const int srcH = srcGridY[iy + 1] - srcGridY[iy]; const int dstW = dstGridX[ix + 1] - dstGridX[ix]; const int dstH = dstGridY[iy + 1] - dstGridY[iy]; if (srcW <= 0 || srcH <= 0 || dstW <= 0 || dstH <= 0) continue; switch (imgRect.fillMode) { case FillMode::Stretch: drawRescaledImage(imgRect.image.get(), srcGridX[ix], srcGridY[iy], dstGridX[ix], dstGridY[iy], srcW, srcH, dstW, dstH); break; case FillMode::Repeat: drawRescaledImagePattern(imgRect.image.get(), srcGridX[ix], srcGridY[iy], srcW, srcH, dstGridX[ix], dstGridY[iy], dstW, dstH, srcW, srcH); break; } } } } void Graphics::drawText(const std::string &text, int x, int y, gcn::Graphics::Alignment alignment, const gcn::Color &color, gcn::Font *font, bool outline, bool shadow, const std::optional &outlineColor, const std::optional &shadowColor) { switch (alignment) { case gcn::Graphics::LEFT: break; case gcn::Graphics::CENTER: x -= font->getWidth(text) / 2; break; case gcn::Graphics::RIGHT: x -= font->getWidth(text); break; default: throw GCN_EXCEPTION("Unknown alignment."); } auto realOutlineColor = outlineColor; auto realShadowColor = shadowColor; if (shadow && !realShadowColor) { auto sc = Theme::getThemeColor(Theme::SHADOW); sc.a = color.a / 2; realShadowColor = sc; } if (outline && !realOutlineColor) { auto oc = Theme::getThemeColor(Theme::OUTLINE); oc.a = color.a; realOutlineColor = oc; } setColor(color); static_cast(font)->drawString(graphics, text, x, y, realOutlineColor, realShadowColor); } void Graphics::drawText(const std::string &text, int x, int y, gcn::Graphics::Alignment align, gcn::Font *font, const TextFormat &format) { drawText(text, x, y, align, format.color, font, format.outlineColor.has_value(), format.shadowColor.has_value(), format.outlineColor, format.shadowColor); } void Graphics::_beginDraw() { pushClipArea(gcn::Rectangle(0, 0, mWidth, mHeight)); } void Graphics::_endDraw() { popClipArea(); } void Graphics::pushClipRect(const gcn::Rectangle &rect) { const gcn::ClipRectangle &carea = mClipStack.top(); mClipRects.emplace(rect.x + carea.xOffset, rect.y + carea.yOffset, rect.width, rect.height); updateClipRect(); } void Graphics::popClipRect() { mClipRects.pop(); updateClipRect(); }