#include "Theme.hpp" #include Theme::Theme() : square_radius(10) { // Load config CONFIG_OPEN(config); std::string piece = config->Read("board/theme/pieces/path", "default").ToStdString(); wxFileName piece_file(piece); std::string square = config->Read("board/theme/squares/path", "default").ToStdString(); wxFileName square_file(square); CONFIG_CLOSE(config); // Piece if (piece == "default" || !piece_file.FileExists()) { wxLogDebug("Loading piece skin from binres"); LoadPiecesSkin(LoadPNG("cburnett").ConvertToImage()); } else { wxLogDebug("Loading piece skin: %s", piece); LoadPiecesSkin(wxImage(piece, wxBITMAP_TYPE_PNG)); } // Square if (square == "default" || !square_file.FileExists()) { wxLogDebug("Loading square skin from binres"); LoadSquaresSkin(LoadPNG("chesscom_8bits").ConvertToImage()); } else { wxLogDebug("Loading square skin: %s", square); LoadSquaresSkin(wxImage(square, wxBITMAP_TYPE_PNG)); } } Theme::Theme(std::string piece, std::string square) : square_radius(10) { wxLogDebug("Loading piece skin: %s", piece); LoadPiecesSkin(wxImage(piece, wxBITMAP_TYPE_PNG)); wxLogDebug("Loading square skin: %s", square); LoadSquaresSkin(wxImage(square, wxBITMAP_TYPE_PNG)); } Theme::~Theme() { for (std::pair c : skin_scaled) { delete c.second; } } std::uint8_t Theme::GetSquareRadius() { return (square_radius); } void Theme::LoadPiecesSkin(wxImage iskin) { if (iskin.GetWidth() != 2 * ELT_DIM || iskin.GetHeight() != 6 * ELT_DIM) { throw "Invalid piece theme"; } int offset = 0; // Kings skin['k'] = iskin.GetSubImage(wxRect(0, offset, ELT_DIM, ELT_DIM)); skin['K'] = iskin.GetSubImage(wxRect(ELT_DIM, offset, ELT_DIM, ELT_DIM)); // Queen offset = ELT_DIM; skin['q'] = iskin.GetSubImage(wxRect(0, offset, ELT_DIM, ELT_DIM)); skin['Q'] = iskin.GetSubImage(wxRect(ELT_DIM, offset, ELT_DIM, ELT_DIM)); // Rook offset = ELT_DIM * 2; skin['r'] = iskin.GetSubImage(wxRect(0, offset, ELT_DIM, ELT_DIM)); skin['R'] = iskin.GetSubImage(wxRect(ELT_DIM, offset, ELT_DIM, ELT_DIM)); // Bishop offset = ELT_DIM * 3; skin['b'] = iskin.GetSubImage(wxRect(0, offset, ELT_DIM, ELT_DIM)); skin['B'] = iskin.GetSubImage(wxRect(ELT_DIM, offset, ELT_DIM, ELT_DIM)); // Knight offset = ELT_DIM * 4; skin['n'] = iskin.GetSubImage(wxRect(0, offset, ELT_DIM, ELT_DIM)); skin['N'] = iskin.GetSubImage(wxRect(ELT_DIM, offset, ELT_DIM, ELT_DIM)); // Pawn offset = ELT_DIM * 5; skin['p'] = iskin.GetSubImage(wxRect(0, offset, ELT_DIM, ELT_DIM)); skin['P'] = iskin.GetSubImage(wxRect(ELT_DIM, offset, ELT_DIM, ELT_DIM)); // Update scaled version ResizePieces(DEFAULT_SIZE * PIECE_SIZE_FACTOR); } void Theme::LoadSquaresSkin(wxImage iskin) { if (iskin.GetWidth() != 2 * ELT_DIM || iskin.GetHeight() != ELT_DIM) { throw "Invalid piece theme"; } // Square skin['s'] = iskin.GetSubImage(wxRect(0, 0, ELT_DIM, ELT_DIM)); skin['S'] = iskin.GetSubImage(wxRect(ELT_DIM, 0, ELT_DIM, ELT_DIM)); // Update scaled version ResizeSquares(DEFAULT_SIZE); } wxBitmap *Theme::Get(char c) { return (skin_scaled[c]); } void Theme::ResizePieces(std::uint32_t width) { for (std::pair c : skin) { if (c.first != 's' && c.first != 'S') { if (skin_scaled.count(c.first)) delete skin_scaled[c.first]; skin_scaled[c.first] = new wxBitmap(c.second.Scale(width, width, wxIMAGE_QUALITY_HIGH)); } } } void Theme::ResizeSquaresAndPieces(std::uint32_t width) { ResizeSquares(width); ResizePieces(width * PIECE_SIZE_FACTOR); } void Theme::ResizeSquares(std::uint32_t width) { if (skin_scaled.count('s')) delete skin_scaled['s']; skin_scaled['s'] = new wxBitmap(skin['s'].Scale(width, width, wxIMAGE_QUALITY_HIGH)); if (skin_scaled.count('S')) delete skin_scaled['S']; skin_scaled['S'] = new wxBitmap(skin['S'].Scale(width, width, wxIMAGE_QUALITY_HIGH)); skin_scaled['0'] = new wxBitmap(*skin_scaled['S']); skin_scaled['1'] = new wxBitmap(*skin_scaled['s']); skin_scaled['2'] = new wxBitmap(*skin_scaled['s']); skin_scaled['3'] = new wxBitmap(*skin_scaled['S']); skin_scaled['0']->SetMask(RoundedMask(width, 0)); skin_scaled['1']->SetMask(RoundedMask(width, 1)); skin_scaled['2']->SetMask(RoundedMask(width, 2)); skin_scaled['3']->SetMask(RoundedMask(width, 3)); } void Theme::Zoom(int amount) { double width = skin_scaled['s']->GetWidth() + amount; ResizeSquares(std::max(width, 1.0)); ResizePieces(std::max(width * PIECE_SIZE_FACTOR, 1.0)); } void Theme::SetSquareRadius(std::uint8_t radius) { square_radius = radius; Zoom(0); // Refresh scale } /** * This will never fail since k entry always exists (cf constructor and * ResizePieces) */ double Theme::GetPiecesSizes() { return (skin_scaled['k']->GetWidth()); } /** * This will never fail since s entry always exists (cf constructor and * ResizeSquares) */ double Theme::GetSquaresSizes() { return (skin_scaled['s']->GetWidth()); } wxMask *Theme::RoundedMask(std::uint32_t width, std::uint8_t corner) { wxBitmap b(width, width, 1); wxMemoryDC dc; dc.SelectObject(b); dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxBLACK_BRUSH); dc.DrawRectangle(0, 0, width, width); dc.SetBrush(*wxWHITE_BRUSH); dc.SetPen(*wxWHITE_PEN); dc.DrawRoundedRectangle(0, 0, width, width, square_radius); dc.SetBrush(*wxWHITE_BRUSH); dc.SetPen(*wxWHITE_PEN); if (corner == 0) { dc.DrawRectangle(0, width / 2, width, width); dc.DrawRectangle(width / 2, 0, width, width); } else if (corner == 1) { dc.DrawRectangle(0, 0, width / 2, width); dc.DrawRectangle(0, width / 2, width, width); } else if (corner == 2) { dc.DrawRectangle(0, 0, width, width / 2); dc.DrawRectangle(width / 2, 0, width, width); } else if (corner == 3) { dc.DrawRectangle(0, 0, width / 2, width); dc.DrawRectangle(0, 0, width, width / 2); } return (new wxMask(b)); }