Card.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2020, Till Mayer <till.mayer@web.de>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Card.h"
  7. #include <LibGUI/Widget.h>
  8. #include <LibGfx/Font.h>
  9. #include <LibGfx/FontDatabase.h>
  10. namespace Cards {
  11. static const NonnullRefPtr<Gfx::CharacterBitmap> s_diamond = Gfx::CharacterBitmap::create_from_ascii(
  12. " # "
  13. " ### "
  14. " ##### "
  15. " ####### "
  16. "#########"
  17. " ####### "
  18. " ##### "
  19. " ### "
  20. " # ",
  21. 9, 9);
  22. static const NonnullRefPtr<Gfx::CharacterBitmap> s_heart = Gfx::CharacterBitmap::create_from_ascii(
  23. " # # "
  24. " ### ### "
  25. "#########"
  26. "#########"
  27. "#########"
  28. " ####### "
  29. " ##### "
  30. " ### "
  31. " # ",
  32. 9, 9);
  33. static const NonnullRefPtr<Gfx::CharacterBitmap> s_spade = Gfx::CharacterBitmap::create_from_ascii(
  34. " # "
  35. " ### "
  36. " ##### "
  37. " ####### "
  38. "#########"
  39. "#########"
  40. " ## # ## "
  41. " ### "
  42. " ### ",
  43. 9, 9);
  44. static const NonnullRefPtr<Gfx::CharacterBitmap> s_club = Gfx::CharacterBitmap::create_from_ascii(
  45. " ### "
  46. " ##### "
  47. " ##### "
  48. " ## ### ## "
  49. "###########"
  50. "###########"
  51. "#### # ####"
  52. " ## ### ## "
  53. " ### ",
  54. 11, 9);
  55. static RefPtr<Gfx::Bitmap> s_background;
  56. static RefPtr<Gfx::Bitmap> s_background_inverted;
  57. Card::Card(Type type, uint8_t value)
  58. : m_rect(Gfx::IntRect({}, { width, height }))
  59. , m_front(*Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { width, height }))
  60. , m_type(type)
  61. , m_value(value)
  62. {
  63. VERIFY(value < card_count);
  64. Gfx::IntRect paint_rect({ 0, 0 }, { width, height });
  65. if (s_background.is_null()) {
  66. s_background = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { width, height });
  67. Gfx::Painter bg_painter(*s_background);
  68. auto image = Gfx::Bitmap::load_from_file("/res/icons/cards/buggie-deck.png");
  69. VERIFY(!image.is_null());
  70. float aspect_ratio = image->width() / static_cast<float>(image->height());
  71. auto target_size = Gfx::IntSize(static_cast<int>(aspect_ratio * (height - 5)), height - 5);
  72. bg_painter.fill_rect_with_rounded_corners(paint_rect, Color::Black, card_radius);
  73. auto inner_paint_rect = paint_rect.shrunken(2, 2);
  74. bg_painter.fill_rect_with_rounded_corners(inner_paint_rect, Color::White, card_radius - 1);
  75. bg_painter.draw_scaled_bitmap(
  76. { { (width - target_size.width()) / 2, (height - target_size.height()) / 2 }, target_size },
  77. *image, image->rect());
  78. s_background_inverted = invert_bitmap(*s_background);
  79. }
  80. Gfx::Painter painter(m_front);
  81. auto& font = Gfx::FontDatabase::default_font().bold_variant();
  82. auto label = labels[value];
  83. painter.fill_rect_with_rounded_corners(paint_rect, Color::Black, card_radius);
  84. paint_rect.shrink(2, 2);
  85. painter.fill_rect_with_rounded_corners(paint_rect, Color::White, card_radius - 1);
  86. paint_rect.set_height(paint_rect.height() / 2);
  87. paint_rect.shrink(10, 6);
  88. auto text_rect = Gfx::IntRect { 4, 6, font.width("10"), font.glyph_height() };
  89. painter.draw_text(text_rect, label, font, Gfx::TextAlignment::Center, color());
  90. NonnullRefPtr<Gfx::CharacterBitmap> symbol = s_diamond;
  91. switch (m_type) {
  92. case Diamonds:
  93. symbol = s_diamond;
  94. break;
  95. case Clubs:
  96. symbol = s_club;
  97. break;
  98. case Spades:
  99. symbol = s_spade;
  100. break;
  101. case Hearts:
  102. symbol = s_heart;
  103. break;
  104. default:
  105. VERIFY_NOT_REACHED();
  106. }
  107. painter.draw_bitmap(
  108. { text_rect.x() + (text_rect.width() - symbol->size().width()) / 2, text_rect.bottom() + 5 },
  109. symbol, color());
  110. for (int y = height / 2; y < height; ++y) {
  111. for (int x = 0; x < width; ++x) {
  112. m_front->set_pixel(x, y, m_front->get_pixel(width - x - 1, height - y - 1));
  113. }
  114. }
  115. m_front_inverted = invert_bitmap(*m_front);
  116. }
  117. Card::~Card()
  118. {
  119. }
  120. void Card::draw(GUI::Painter& painter) const
  121. {
  122. VERIFY(!s_background.is_null());
  123. if (m_inverted)
  124. painter.blit(position(), m_upside_down ? *s_background_inverted : *m_front_inverted, m_front_inverted->rect());
  125. else
  126. painter.blit(position(), m_upside_down ? *s_background : *m_front, m_front->rect());
  127. }
  128. void Card::clear(GUI::Painter& painter, const Color& background_color) const
  129. {
  130. painter.fill_rect({ old_position(), { width, height } }, background_color);
  131. }
  132. void Card::save_old_position()
  133. {
  134. m_old_position = m_rect.location();
  135. m_old_position_valid = true;
  136. }
  137. void Card::clear_and_draw(GUI::Painter& painter, const Color& background_color)
  138. {
  139. if (is_old_position_valid())
  140. clear(painter, background_color);
  141. draw(painter);
  142. save_old_position();
  143. }
  144. NonnullRefPtr<Gfx::Bitmap> Card::invert_bitmap(Gfx::Bitmap& bitmap)
  145. {
  146. auto inverted_bitmap = bitmap.clone();
  147. VERIFY(inverted_bitmap);
  148. for (int y = 0; y < inverted_bitmap->height(); y++) {
  149. for (int x = 0; x < inverted_bitmap->width(); x++) {
  150. inverted_bitmap->set_pixel(x, y, inverted_bitmap->get_pixel(x, y).inverted());
  151. }
  152. }
  153. return *inverted_bitmap;
  154. }
  155. }