diff --git a/README.md b/README.md index 1ec3787..9610703 100644 --- a/README.md +++ b/README.md @@ -106,8 +106,6 @@ embed_font: false # Optional (default: true) **Symbols Available for Mana Cost:** -Hybrid Mana, coming soon! - **Mana Symbols:** - `W` - White mana - `B` - Black mana @@ -116,12 +114,16 @@ Hybrid Mana, coming soon! - `U` - Blue mana - `C` - Colorless mana - `S` - Snow mana -- `{C/P}` - Colorless Phyrexian mana -- `{R/P}` - Red Phyrexian mana -- `{G/P}` - Green Phyrexian mana -- `{U/P}` - Blue Phyrexian mana -- `{B/P}` - Black Phyrexian mana -- `{W/P}` - White Phyrexian mana +- `{C/P}` - Colorless Phyrexian mana +- `{R/P}` - Red Phyrexian mana +- `{G/P}` - Green Phyrexian mana +- `{U/P}` - Blue Phyrexian mana +- `{B/P}` - Black Phyrexian mana +- `{W/P}` - White Phyrexian mana + +Hybrid and Phyrexian mana are now available! See all the notations below in the rule text section, the notation is the same. Just like the Phyrexian mana, you simply use curly braces in your notation: +- `{R/G}` Red / Green Mana +- `{G/W/P}` Green / White Phyrexian Mana **Numeric Symbols:** - `0` through `99` - Generic mana costs (0-99) @@ -132,7 +134,7 @@ Hybrid Mana, coming soon! - `XG` - X generic + 1 green - `X3R` - X generic + 3 generic + 1 red - `3WU` - 3 generic + 1 white + 1 blue -- `WU{B/P}RG` White, Blue, Phyrexian Black, Red, Green +- `WU{B/P}RG` White, Blue, Phyrexian Black, Red, Green - `X` - X generic only - `3` - 3 generic only - `B` - black only @@ -149,12 +151,40 @@ You can use MTG symbols in your rules text by wrapping them in curly braces "{C} - `{U}` - Blue mana - `{C}` - Colorless mana - `{S}` - Snow mana symbol -- `{C/P}` - Colorless Phyrexian mana -- `{R/P}` - Red Phyrexian mana -- `{G/P}` - Green Phyrexian mana -- `{U/P}` - Blue Phyrexian mana -- `{B/P}` - Black Phyrexian mana -- `{W/P}` - White Phyrexian mana +- `{C/P}` - Colorless Phyrexian mana +- `{R/P}` - Red Phyrexian mana +- `{G/P}` - Green Phyrexian mana +- `{U/P}` - Blue Phyrexian mana +- `{B/P}` - Black Phyrexian mana +- `{W/P}` - White Phyrexian mana + +**Hybrid Mana Symbols:** + +**White hybrid:** `{W/B}` `{W/R}` `{W/G}` `{W/U}` - + +**Black hybrid:** `{B/W}` `{B/R}` `{B/G}` `{B/U}` - + +**Red hybrid:** `{R/W}` `{R/B}` `{R/G}` `{R/U}` - + +**Green hybrid:** `{G/W}` `{G/B}` `{G/R}` `{G/U}` - + +**Blue hybrid:** `{U/W}` `{U/B}` `{U/R}` `{U/G}` - + +**"Two-brids":** `{2/W}` `{2/B}` `{2/R}` `{2/G}` `{2/U}` - + +**Colorless hybrid:** `{C/W}` `{C/B}` `{C/R}` `{C/G}` `{C/U}` - + +**Phyrexian Hybrid Mana Symbols:** + +**White Phyrexian hybrid:** `{W/B/P}` `{W/R/P}` `{W/G/P}` `{W/U/P}` - + +**Black Phyrexian hybrid:** `{B/W/P}` `{B/R/P}` `{B/G/P}` `{B/U/P}` - + +**Red Phyrexian hybrid:** `{R/W/P}` `{R/B/P}` `{R/G/P}` `{R/U/P}` - + +**Green Phyrexian hybrid:** `{G/W/P}` `{G/B/P}` `{G/R/P}` `{G/U/P}` - + +**Blue Phyrexian hybrid:** `{U/W/P}` `{U/B/P}` `{U/R/P}` `{U/G/P}` - **Numeric Symbols:** - `{0}` through `{99}` - Generic mana costs (0-99) diff --git a/images/icons/hybrid/2-black.svg b/images/icons/hybrid/2-black.svg new file mode 100644 index 0000000..c36cd4f --- /dev/null +++ b/images/icons/hybrid/2-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/images/icons/hybrid/2-blue.svg b/images/icons/hybrid/2-blue.svg new file mode 100644 index 0000000..cfb2e91 --- /dev/null +++ b/images/icons/hybrid/2-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/images/icons/hybrid/2-green.svg b/images/icons/hybrid/2-green.svg new file mode 100644 index 0000000..387e54f --- /dev/null +++ b/images/icons/hybrid/2-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/images/icons/hybrid/2-red.svg b/images/icons/hybrid/2-red.svg new file mode 100644 index 0000000..7cb246d --- /dev/null +++ b/images/icons/hybrid/2-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/images/icons/hybrid/2-white.svg b/images/icons/hybrid/2-white.svg new file mode 100644 index 0000000..66f0757 --- /dev/null +++ b/images/icons/hybrid/2-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/images/icons/hybrid/black-blue.svg b/images/icons/hybrid/black-blue.svg new file mode 100644 index 0000000..0992726 --- /dev/null +++ b/images/icons/hybrid/black-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/black-green.svg b/images/icons/hybrid/black-green.svg new file mode 100644 index 0000000..da07367 --- /dev/null +++ b/images/icons/hybrid/black-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/black-red.svg b/images/icons/hybrid/black-red.svg new file mode 100644 index 0000000..fc7fca4 --- /dev/null +++ b/images/icons/hybrid/black-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/black-white.svg b/images/icons/hybrid/black-white.svg new file mode 100644 index 0000000..b1755a3 --- /dev/null +++ b/images/icons/hybrid/black-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/blue-black.svg b/images/icons/hybrid/blue-black.svg new file mode 100644 index 0000000..1c55aa3 --- /dev/null +++ b/images/icons/hybrid/blue-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/blue-green.svg b/images/icons/hybrid/blue-green.svg new file mode 100644 index 0000000..e64e2f4 --- /dev/null +++ b/images/icons/hybrid/blue-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/blue-red.svg b/images/icons/hybrid/blue-red.svg new file mode 100644 index 0000000..4447c92 --- /dev/null +++ b/images/icons/hybrid/blue-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/blue-white.svg b/images/icons/hybrid/blue-white.svg new file mode 100644 index 0000000..bc80447 --- /dev/null +++ b/images/icons/hybrid/blue-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/colorless-black.svg b/images/icons/hybrid/colorless-black.svg new file mode 100644 index 0000000..8ad2f01 --- /dev/null +++ b/images/icons/hybrid/colorless-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/colorless-blue.svg b/images/icons/hybrid/colorless-blue.svg new file mode 100644 index 0000000..ae919ab --- /dev/null +++ b/images/icons/hybrid/colorless-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/colorless-green.svg b/images/icons/hybrid/colorless-green.svg new file mode 100644 index 0000000..cd4ea6e --- /dev/null +++ b/images/icons/hybrid/colorless-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/colorless-red.svg b/images/icons/hybrid/colorless-red.svg new file mode 100644 index 0000000..bd103a7 --- /dev/null +++ b/images/icons/hybrid/colorless-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/colorless-white.svg b/images/icons/hybrid/colorless-white.svg new file mode 100644 index 0000000..502b113 --- /dev/null +++ b/images/icons/hybrid/colorless-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/green-black.svg b/images/icons/hybrid/green-black.svg new file mode 100644 index 0000000..d4c2551 --- /dev/null +++ b/images/icons/hybrid/green-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/green-blue.svg b/images/icons/hybrid/green-blue.svg new file mode 100644 index 0000000..c3ab0cc --- /dev/null +++ b/images/icons/hybrid/green-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/green-red.svg b/images/icons/hybrid/green-red.svg new file mode 100644 index 0000000..17997bd --- /dev/null +++ b/images/icons/hybrid/green-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/green-white.svg b/images/icons/hybrid/green-white.svg new file mode 100644 index 0000000..0c5fbc8 --- /dev/null +++ b/images/icons/hybrid/green-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/red-black.svg b/images/icons/hybrid/red-black.svg new file mode 100644 index 0000000..31e12a8 --- /dev/null +++ b/images/icons/hybrid/red-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/red-blue.svg b/images/icons/hybrid/red-blue.svg new file mode 100644 index 0000000..368ff35 --- /dev/null +++ b/images/icons/hybrid/red-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/red-green.svg b/images/icons/hybrid/red-green.svg new file mode 100644 index 0000000..e6dc89d --- /dev/null +++ b/images/icons/hybrid/red-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/red-white.svg b/images/icons/hybrid/red-white.svg new file mode 100644 index 0000000..d94b705 --- /dev/null +++ b/images/icons/hybrid/red-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/white-black.svg b/images/icons/hybrid/white-black.svg new file mode 100644 index 0000000..a87a489 --- /dev/null +++ b/images/icons/hybrid/white-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/white-blue.svg b/images/icons/hybrid/white-blue.svg new file mode 100644 index 0000000..e17312c --- /dev/null +++ b/images/icons/hybrid/white-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/white-green.svg b/images/icons/hybrid/white-green.svg new file mode 100644 index 0000000..143201a --- /dev/null +++ b/images/icons/hybrid/white-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/hybrid/white-red.svg b/images/icons/hybrid/white-red.svg new file mode 100644 index 0000000..2edcee0 --- /dev/null +++ b/images/icons/hybrid/white-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/jsharp.svg b/images/icons/jsharp.svg deleted file mode 100644 index f2f7b6d..0000000 --- a/images/icons/jsharp.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/images/icons/phyrexian.svg b/images/icons/phyrexian.svg deleted file mode 100644 index 1cf4973..0000000 --- a/images/icons/phyrexian.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/images/icons/phyrexian/black-blue.svg b/images/icons/phyrexian/black-blue.svg new file mode 100644 index 0000000..becaaf7 --- /dev/null +++ b/images/icons/phyrexian/black-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/black-green.svg b/images/icons/phyrexian/black-green.svg new file mode 100644 index 0000000..be55ed7 --- /dev/null +++ b/images/icons/phyrexian/black-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/black-red.svg b/images/icons/phyrexian/black-red.svg new file mode 100644 index 0000000..ae18385 --- /dev/null +++ b/images/icons/phyrexian/black-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/black-white.svg b/images/icons/phyrexian/black-white.svg new file mode 100644 index 0000000..f391860 --- /dev/null +++ b/images/icons/phyrexian/black-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian-black.svg b/images/icons/phyrexian/black.svg similarity index 100% rename from images/icons/phyrexian-black.svg rename to images/icons/phyrexian/black.svg diff --git a/images/icons/phyrexian/blue-black.svg b/images/icons/phyrexian/blue-black.svg new file mode 100644 index 0000000..9bafd5b --- /dev/null +++ b/images/icons/phyrexian/blue-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/blue-green.svg b/images/icons/phyrexian/blue-green.svg new file mode 100644 index 0000000..5238275 --- /dev/null +++ b/images/icons/phyrexian/blue-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/blue-red.svg b/images/icons/phyrexian/blue-red.svg new file mode 100644 index 0000000..2451b14 --- /dev/null +++ b/images/icons/phyrexian/blue-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/blue-white.svg b/images/icons/phyrexian/blue-white.svg new file mode 100644 index 0000000..d239022 --- /dev/null +++ b/images/icons/phyrexian/blue-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian-blue.svg b/images/icons/phyrexian/blue.svg similarity index 100% rename from images/icons/phyrexian-blue.svg rename to images/icons/phyrexian/blue.svg diff --git a/images/icons/phyrexian-colorless.svg b/images/icons/phyrexian/colorless.svg similarity index 100% rename from images/icons/phyrexian-colorless.svg rename to images/icons/phyrexian/colorless.svg diff --git a/images/icons/phyrexian/green-black.svg b/images/icons/phyrexian/green-black.svg new file mode 100644 index 0000000..7ac11b4 --- /dev/null +++ b/images/icons/phyrexian/green-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/green-blue.svg b/images/icons/phyrexian/green-blue.svg new file mode 100644 index 0000000..5f27caa --- /dev/null +++ b/images/icons/phyrexian/green-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/green-red.svg b/images/icons/phyrexian/green-red.svg new file mode 100644 index 0000000..d322f33 --- /dev/null +++ b/images/icons/phyrexian/green-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/green-white.svg b/images/icons/phyrexian/green-white.svg new file mode 100644 index 0000000..e544f22 --- /dev/null +++ b/images/icons/phyrexian/green-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian-green.svg b/images/icons/phyrexian/green.svg similarity index 100% rename from images/icons/phyrexian-green.svg rename to images/icons/phyrexian/green.svg diff --git a/images/icons/phyrexian/red-black.svg b/images/icons/phyrexian/red-black.svg new file mode 100644 index 0000000..50255d9 --- /dev/null +++ b/images/icons/phyrexian/red-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/red-blue.svg b/images/icons/phyrexian/red-blue.svg new file mode 100644 index 0000000..3f50d75 --- /dev/null +++ b/images/icons/phyrexian/red-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/red-green.svg b/images/icons/phyrexian/red-green.svg new file mode 100644 index 0000000..3bf935b --- /dev/null +++ b/images/icons/phyrexian/red-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/red-white.svg b/images/icons/phyrexian/red-white.svg new file mode 100644 index 0000000..32a7a2d --- /dev/null +++ b/images/icons/phyrexian/red-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian-red.svg b/images/icons/phyrexian/red.svg similarity index 100% rename from images/icons/phyrexian-red.svg rename to images/icons/phyrexian/red.svg diff --git a/images/icons/phyrexian/white-black.svg b/images/icons/phyrexian/white-black.svg new file mode 100644 index 0000000..ed17c2e --- /dev/null +++ b/images/icons/phyrexian/white-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/white-blue.svg b/images/icons/phyrexian/white-blue.svg new file mode 100644 index 0000000..1bc4836 --- /dev/null +++ b/images/icons/phyrexian/white-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/white-green.svg b/images/icons/phyrexian/white-green.svg new file mode 100644 index 0000000..d788833 --- /dev/null +++ b/images/icons/phyrexian/white-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian/white-red.svg b/images/icons/phyrexian/white-red.svg new file mode 100644 index 0000000..131aa1c --- /dev/null +++ b/images/icons/phyrexian/white-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/phyrexian-white.svg b/images/icons/phyrexian/white.svg similarity index 100% rename from images/icons/phyrexian-white.svg rename to images/icons/phyrexian/white.svg diff --git a/images/icons/qrcode.svg b/images/icons/qrcode.svg deleted file mode 100644 index e9eace5..0000000 --- a/images/icons/qrcode.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/lib/mtg_card_maker.rb b/lib/mtg_card_maker.rb index 2227ac8..0e9bbdf 100644 --- a/lib/mtg_card_maker.rb +++ b/lib/mtg_card_maker.rb @@ -120,6 +120,7 @@ def svg require_relative 'mtg_card_maker/svg_gradient_service' require_relative 'mtg_card_maker/text_rendering_service' require_relative 'mtg_card_maker/symbol_replacement_service' + require_relative 'mtg_card_maker/icon_filename_service' require_relative 'mtg_card_maker/css_service' require_relative 'mtg_card_maker/sprite_sheet_assets' require_relative 'mtg_card_maker/sprite_sheet_builder' diff --git a/lib/mtg_card_maker/icon_filename_service.rb b/lib/mtg_card_maker/icon_filename_service.rb new file mode 100644 index 0000000..e6e0f06 --- /dev/null +++ b/lib/mtg_card_maker/icon_filename_service.rb @@ -0,0 +1,118 @@ +# frozen_string_literal: true + +module MtgCardMaker + # IconFilenameService provides symbol mapping for MTG mana costs and symbols. + # This service maps symbol notation (like {W}, {2}, {T}) to icon types. + # + # @example + # service = MtgCardMaker::IconFilenameService.new + # icon_type = service.symbol_to_icon_type("{W}") + # icon_type = service.symbol_to_icon_type("{2}") + # + # @since 0.1.0 + class IconFilenameService + # Basic mana colors and their symbols + BASIC_COLORS = { + '{W}' => :white, + '{B}' => :black, + '{R}' => :red, + '{G}' => :green, + '{U}' => :blue, + '{C}' => :colorless + }.freeze + + # Special symbols, cannot be combined with other symbols + SPECIAL_SYMBOLS = { + '{S}' => :snow, + '{X}' => :x, + '{T}' => :tap, + '{Q}' => :untap, + '{E}' => :energy + }.freeze + + # Get the complete symbol map + # + # @return [Hash] the complete mapping of symbols to icon types + def symbol_map + @symbol_map ||= generate_symbol_map + end + + # Convert a symbol to an icon type + # + # @param symbol [String] the symbol to convert (e.g., "{W}", "{2}", "{T}") + # @return [Symbol, nil] the icon type or nil if not found + def symbol_to_icon_type(symbol) + symbol_map[symbol] + end + + private + + # Generate the complete symbol map from basic definitions + def generate_symbol_map + BASIC_COLORS + .merge(SPECIAL_SYMBOLS) + .merge(generate_hybrid_symbols) + .merge(generate_numeric_symbols) + .merge(generate_phyrexian_symbols) + .merge(generate_phyrexian_hybrid_symbols) + end + + # Generate numeric symbols (0-9 single-digit, 10-99 double-digit) + def generate_numeric_symbols + (0..99).to_h { |num| ["{#{num}}", :numeric] } + end + + # Generate phyrexian mana symbols + def generate_phyrexian_symbols + BASIC_COLORS.transform_keys { |symbol| symbol.gsub('}', '/P}') } + .transform_values { |color| :"phyrexian-#{color}" } + end + + # Generate hybrid mana symbols + def generate_hybrid_symbols + # Hybrid symbols are combinations of two basic colors + generate_color_combinations.merge( + # Twobrids are a colorless "2" plus a basic color + generate_twobrid_symbols + ) + end + + # Generate two-color hybrid combinations + def generate_color_combinations + color_symbols = color_symbols_without_braces + + color_symbols.combination(2).flat_map do |color1, color2| + [ + ["{#{color1}/#{color2}}", :"hybrid-#{BASIC_COLORS["{#{color1}}"]}-#{BASIC_COLORS["{#{color2}}"]}"], + ["{#{color2}/#{color1}}", :"hybrid-#{BASIC_COLORS["{#{color2}}"]}-#{BASIC_COLORS["{#{color1}}"]}"] + ] + end.to_h + end + + # Generate 2/color symbols (twobrid) + def generate_twobrid_symbols + BASIC_COLORS.transform_keys { |symbol| "{2/#{strip_braces(symbol)}}" } + .transform_values { |color| :"hybrid-2-#{color}" } + end + + # Generate phyrexian hybrid mana symbols + def generate_phyrexian_hybrid_symbols + color_symbols = color_symbols_without_braces + + color_symbols.combination(2).flat_map do |color1, color2| + [ + ["{#{color1}/#{color2}/P}", :"phyrexian-#{BASIC_COLORS["{#{color1}}"]}-#{BASIC_COLORS["{#{color2}}"]}"], + ["{#{color2}/#{color1}/P}", :"phyrexian-#{BASIC_COLORS["{#{color2}}"]}-#{BASIC_COLORS["{#{color1}}"]}"] + ] + end.to_h + end + + def color_symbols_without_braces + BASIC_COLORS.keys.map { |symbol| strip_braces(symbol) } + end + + def strip_braces(symbol) + symbol.gsub(/[{}]/, '') + end + end +end diff --git a/lib/mtg_card_maker/icon_service.rb b/lib/mtg_card_maker/icon_service.rb index d51b7a3..b268d33 100644 --- a/lib/mtg_card_maker/icon_service.rb +++ b/lib/mtg_card_maker/icon_service.rb @@ -2,6 +2,7 @@ require 'fileutils' require 'nokogiri' +require_relative 'icon_filename_service' module MtgCardMaker # IconService loads and renders SVG icons for mana costs. @@ -10,8 +11,9 @@ module MtgCardMaker # # @example # service = MtgCardMaker::IconService.new - # svg = service.icon_svg(:red, size: 24) - # svg = service.numeric_icon_svg(5, size: 24) + # svg = service.symbol_svg("{W}", size: 24) + # svg = service.symbol_svg("{2}", size: 24) + # svg = service.symbol_svg("{W/B}", size: 24) # # @since 0.1.0 class IconService @@ -26,12 +28,21 @@ class IconService def initialize(icon_set = :default) @icon_set = icon_set @cached_icons = {} + @filename_service = IconFilenameService.new end - # Returns the SVG content for a given icon type and icon set - def icon_svg(icon_type, size: 30) - return nil unless valid_icon?(icon_type) + # Returns the SVG content for a given symbol string + # @param symbol_string [String] the symbol string (e.g., "{W}", "{2}", "{W/B}", "{C/P}") + # @param size [Integer] the size of the icon in pixels + # @return [String, nil] the SVG content or nil if symbol not found + def symbol_svg(symbol_string, size: 30) + icon_type = @filename_service.symbol_to_icon_type(symbol_string) + return nil unless icon_type + # Handle numeric icons specially since they need dynamic content + return render_numeric_icon(symbol_string, size) if icon_type == :numeric + + # Handle regular icons icon_path = icon_path_for_type(icon_type) return nil unless File.exist?(icon_path) @@ -39,8 +50,12 @@ def icon_svg(icon_type, size: 30) resize_svg(svg_content, size) end - # Returns the SVG content for a numeric icon with the specified number - def numeric_icon_svg(number, size: 30) + # Renders a numeric icon with the specified number + # @param symbol_string [String] the numeric symbol string (e.g., "{2}", "{42}") + # @param size [Integer] the size of the icon in pixels + # @return [String, nil] the SVG content or nil if symbol not found + def render_numeric_icon(symbol_string, size) + number = extract_number_from_symbol(symbol_string) return nil unless number.is_a?(Integer) && number >= 0 # Determine which template to use based on digit count @@ -86,13 +101,35 @@ def self.icon_sets private + def extract_number_from_symbol(symbol_string) + # Extract the number from symbols like "{2}", "{42}", etc. + match = symbol_string.match(/\{(\d{1,2})\}/) + return 'X' unless match + + match[1].to_i + end + def valid_icon?(icon_type) # Check if the SVG file exists File.exist?(icon_path_for_type(icon_type)) end def icon_path_for_type(icon_type) - # Auto-map any symbol to {symbol}.svg + icon_type_str = icon_type.to_s + + if (match = icon_type_str.match(/^(phyrexian|hybrid)-(.*)$/)) + subdirectory_icon_path(icon_type: match[2], subdirectory: match[1]) + else + standard_icon_path(icon_type) + end + end + + def subdirectory_icon_path(icon_type:, subdirectory:) + filename = "#{icon_type}.svg" + File.join(ICONS_DIR, subdirectory, filename) + end + + def standard_icon_path(icon_type) filename = "#{icon_type}.svg" File.join(ICONS_DIR, filename) end diff --git a/lib/mtg_card_maker/icons/hybrid/2-black.svg b/lib/mtg_card_maker/icons/hybrid/2-black.svg new file mode 100644 index 0000000..c36cd4f --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/2-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/2-blue.svg b/lib/mtg_card_maker/icons/hybrid/2-blue.svg new file mode 100644 index 0000000..cfb2e91 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/2-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/2-green.svg b/lib/mtg_card_maker/icons/hybrid/2-green.svg new file mode 100644 index 0000000..387e54f --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/2-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/2-red.svg b/lib/mtg_card_maker/icons/hybrid/2-red.svg new file mode 100644 index 0000000..7cb246d --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/2-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/2-white.svg b/lib/mtg_card_maker/icons/hybrid/2-white.svg new file mode 100644 index 0000000..66f0757 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/2-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + 2 + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/black-blue.svg b/lib/mtg_card_maker/icons/hybrid/black-blue.svg new file mode 100644 index 0000000..0992726 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/black-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/black-green.svg b/lib/mtg_card_maker/icons/hybrid/black-green.svg new file mode 100644 index 0000000..da07367 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/black-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/black-red.svg b/lib/mtg_card_maker/icons/hybrid/black-red.svg new file mode 100644 index 0000000..fc7fca4 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/black-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/black-white.svg b/lib/mtg_card_maker/icons/hybrid/black-white.svg new file mode 100644 index 0000000..b1755a3 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/black-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/blue-black.svg b/lib/mtg_card_maker/icons/hybrid/blue-black.svg new file mode 100644 index 0000000..1c55aa3 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/blue-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/blue-green.svg b/lib/mtg_card_maker/icons/hybrid/blue-green.svg new file mode 100644 index 0000000..e64e2f4 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/blue-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/blue-red.svg b/lib/mtg_card_maker/icons/hybrid/blue-red.svg new file mode 100644 index 0000000..4447c92 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/blue-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/blue-white.svg b/lib/mtg_card_maker/icons/hybrid/blue-white.svg new file mode 100644 index 0000000..bc80447 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/blue-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/colorless-black.svg b/lib/mtg_card_maker/icons/hybrid/colorless-black.svg new file mode 100644 index 0000000..8ad2f01 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/colorless-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/colorless-blue.svg b/lib/mtg_card_maker/icons/hybrid/colorless-blue.svg new file mode 100644 index 0000000..ae919ab --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/colorless-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/colorless-green.svg b/lib/mtg_card_maker/icons/hybrid/colorless-green.svg new file mode 100644 index 0000000..cd4ea6e --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/colorless-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/colorless-red.svg b/lib/mtg_card_maker/icons/hybrid/colorless-red.svg new file mode 100644 index 0000000..bd103a7 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/colorless-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/colorless-white.svg b/lib/mtg_card_maker/icons/hybrid/colorless-white.svg new file mode 100644 index 0000000..502b113 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/colorless-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/green-black.svg b/lib/mtg_card_maker/icons/hybrid/green-black.svg new file mode 100644 index 0000000..d4c2551 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/green-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/green-blue.svg b/lib/mtg_card_maker/icons/hybrid/green-blue.svg new file mode 100644 index 0000000..c3ab0cc --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/green-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/green-red.svg b/lib/mtg_card_maker/icons/hybrid/green-red.svg new file mode 100644 index 0000000..17997bd --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/green-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/green-white.svg b/lib/mtg_card_maker/icons/hybrid/green-white.svg new file mode 100644 index 0000000..0c5fbc8 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/green-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/red-black.svg b/lib/mtg_card_maker/icons/hybrid/red-black.svg new file mode 100644 index 0000000..31e12a8 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/red-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/red-blue.svg b/lib/mtg_card_maker/icons/hybrid/red-blue.svg new file mode 100644 index 0000000..368ff35 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/red-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/red-green.svg b/lib/mtg_card_maker/icons/hybrid/red-green.svg new file mode 100644 index 0000000..e6dc89d --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/red-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/red-white.svg b/lib/mtg_card_maker/icons/hybrid/red-white.svg new file mode 100644 index 0000000..d94b705 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/red-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/white-black.svg b/lib/mtg_card_maker/icons/hybrid/white-black.svg new file mode 100644 index 0000000..a87a489 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/white-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/white-blue.svg b/lib/mtg_card_maker/icons/hybrid/white-blue.svg new file mode 100644 index 0000000..e17312c --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/white-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/white-green.svg b/lib/mtg_card_maker/icons/hybrid/white-green.svg new file mode 100644 index 0000000..143201a --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/white-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/hybrid/white-red.svg b/lib/mtg_card_maker/icons/hybrid/white-red.svg new file mode 100644 index 0000000..2edcee0 --- /dev/null +++ b/lib/mtg_card_maker/icons/hybrid/white-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian.svg b/lib/mtg_card_maker/icons/phyrexian.svg deleted file mode 100644 index 1cf4973..0000000 --- a/lib/mtg_card_maker/icons/phyrexian.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/mtg_card_maker/icons/phyrexian/black-blue.svg b/lib/mtg_card_maker/icons/phyrexian/black-blue.svg new file mode 100644 index 0000000..becaaf7 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/black-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/black-green.svg b/lib/mtg_card_maker/icons/phyrexian/black-green.svg new file mode 100644 index 0000000..be55ed7 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/black-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/black-red.svg b/lib/mtg_card_maker/icons/phyrexian/black-red.svg new file mode 100644 index 0000000..ae18385 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/black-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/black-white.svg b/lib/mtg_card_maker/icons/phyrexian/black-white.svg new file mode 100644 index 0000000..f391860 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/black-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian-black.svg b/lib/mtg_card_maker/icons/phyrexian/black.svg similarity index 100% rename from lib/mtg_card_maker/icons/phyrexian-black.svg rename to lib/mtg_card_maker/icons/phyrexian/black.svg diff --git a/lib/mtg_card_maker/icons/phyrexian/blue-black.svg b/lib/mtg_card_maker/icons/phyrexian/blue-black.svg new file mode 100644 index 0000000..9bafd5b --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/blue-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/blue-green.svg b/lib/mtg_card_maker/icons/phyrexian/blue-green.svg new file mode 100644 index 0000000..5238275 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/blue-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/blue-red.svg b/lib/mtg_card_maker/icons/phyrexian/blue-red.svg new file mode 100644 index 0000000..2451b14 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/blue-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/blue-white.svg b/lib/mtg_card_maker/icons/phyrexian/blue-white.svg new file mode 100644 index 0000000..d239022 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/blue-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian-blue.svg b/lib/mtg_card_maker/icons/phyrexian/blue.svg similarity index 100% rename from lib/mtg_card_maker/icons/phyrexian-blue.svg rename to lib/mtg_card_maker/icons/phyrexian/blue.svg diff --git a/lib/mtg_card_maker/icons/phyrexian-colorless.svg b/lib/mtg_card_maker/icons/phyrexian/colorless.svg similarity index 100% rename from lib/mtg_card_maker/icons/phyrexian-colorless.svg rename to lib/mtg_card_maker/icons/phyrexian/colorless.svg diff --git a/lib/mtg_card_maker/icons/phyrexian/green-black.svg b/lib/mtg_card_maker/icons/phyrexian/green-black.svg new file mode 100644 index 0000000..7ac11b4 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/green-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/green-blue.svg b/lib/mtg_card_maker/icons/phyrexian/green-blue.svg new file mode 100644 index 0000000..5f27caa --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/green-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/green-red.svg b/lib/mtg_card_maker/icons/phyrexian/green-red.svg new file mode 100644 index 0000000..d322f33 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/green-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/green-white.svg b/lib/mtg_card_maker/icons/phyrexian/green-white.svg new file mode 100644 index 0000000..e544f22 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/green-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian-green.svg b/lib/mtg_card_maker/icons/phyrexian/green.svg similarity index 100% rename from lib/mtg_card_maker/icons/phyrexian-green.svg rename to lib/mtg_card_maker/icons/phyrexian/green.svg diff --git a/lib/mtg_card_maker/icons/phyrexian/red-black.svg b/lib/mtg_card_maker/icons/phyrexian/red-black.svg new file mode 100644 index 0000000..50255d9 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/red-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/red-blue.svg b/lib/mtg_card_maker/icons/phyrexian/red-blue.svg new file mode 100644 index 0000000..3f50d75 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/red-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/red-green.svg b/lib/mtg_card_maker/icons/phyrexian/red-green.svg new file mode 100644 index 0000000..3bf935b --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/red-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/red-white.svg b/lib/mtg_card_maker/icons/phyrexian/red-white.svg new file mode 100644 index 0000000..32a7a2d --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/red-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian-red.svg b/lib/mtg_card_maker/icons/phyrexian/red.svg similarity index 100% rename from lib/mtg_card_maker/icons/phyrexian-red.svg rename to lib/mtg_card_maker/icons/phyrexian/red.svg diff --git a/lib/mtg_card_maker/icons/phyrexian/white-black.svg b/lib/mtg_card_maker/icons/phyrexian/white-black.svg new file mode 100644 index 0000000..ed17c2e --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/white-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/white-blue.svg b/lib/mtg_card_maker/icons/phyrexian/white-blue.svg new file mode 100644 index 0000000..1bc4836 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/white-blue.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/white-green.svg b/lib/mtg_card_maker/icons/phyrexian/white-green.svg new file mode 100644 index 0000000..d788833 --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/white-green.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian/white-red.svg b/lib/mtg_card_maker/icons/phyrexian/white-red.svg new file mode 100644 index 0000000..131aa1c --- /dev/null +++ b/lib/mtg_card_maker/icons/phyrexian/white-red.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/lib/mtg_card_maker/icons/phyrexian-white.svg b/lib/mtg_card_maker/icons/phyrexian/white.svg similarity index 100% rename from lib/mtg_card_maker/icons/phyrexian-white.svg rename to lib/mtg_card_maker/icons/phyrexian/white.svg diff --git a/lib/mtg_card_maker/mana_cost.rb b/lib/mtg_card_maker/mana_cost.rb index 070cef7..2786efe 100644 --- a/lib/mtg_card_maker/mana_cost.rb +++ b/lib/mtg_card_maker/mana_cost.rb @@ -17,25 +17,7 @@ module MtgCardMaker # # @since 0.1.0 class ManaCost - # Mapping of MTG notation to icon types - SYMBOL_MAP = { - 'B' => :black, - 'U' => :blue, - 'G' => :green, - 'W' => :white, - 'R' => :red, - 'C' => :colorless, - 'S' => :snow, - 'X' => :x, - '{C/P}' => :'phyrexian-colorless', - '{R/P}' => :'phyrexian-red', - '{G/P}' => :'phyrexian-green', - '{U/P}' => :'phyrexian-blue', - '{B/P}' => :'phyrexian-black', - '{W/P}' => :'phyrexian-white' - }.freeze - - # @return [Array] the parsed mana elements + # @return [Array] the parsed mana elements (symbol strings) attr_reader :elements # @return [Integer, nil] the integer value for generic mana @@ -66,8 +48,8 @@ def initialize(mana_string = nil, icon_set = :default) def to_svg circle_spacing = layer_config.mana_cost_config[:circle_spacing] - mana_icons = @elements.each_with_index.map do |icon_type, i| - render_mana_icon(i * circle_spacing, 0, icon_type) + mana_icons = @elements.each_with_index.map do |symbol, i| + render_mana_icon(i * circle_spacing, 0, symbol) end.join <<~SVG.delete("\n") @@ -91,7 +73,7 @@ def parse_mana_string(mana_string) end def parse_x_cost(mana_string) - @elements << :x + @elements << '{X}' remaining_string = mana_string[1..] # Check if the remaining string starts with a number @@ -107,10 +89,10 @@ def parse_numeric_cost(mana_string) if numeric_value >= 100 @int_val = nil - @elements << :x + @elements << '{X}' else @int_val = numeric_value - @elements << :numeric + @elements << "{#{numeric_value}}" end parse_colored_mana(mana_string[numeric_value.to_s.length..]) @@ -119,8 +101,11 @@ def parse_numeric_cost(mana_string) def parse_colored_mana(mana_string) # Use regex to match symbols: single letters, 1-2 digits, or {anything between curly braces} mana_string.scan(/([A-Z]|\d{1,2}|\{[^}]+\})/).flatten.each do |symbol| - icon_type = SYMBOL_MAP[symbol] - @elements << icon_type if icon_type + # Add curly braces if not already present + formatted_symbol = symbol.start_with?('{') ? symbol : "{#{symbol}}" + + # Allow any symbol - IconService will handle validation + @elements << formatted_symbol end end @@ -129,14 +114,14 @@ def limit_elements @elements = @elements.first(max_circles) end - def render_mana_icon(x, y, icon_type) - icon_size = if icon_type.to_s.match?(/phyrexian|hybrid/) + def render_mana_icon(x, y, symbol) + icon_size = if symbol.match?(%r{\{.*/.*\}}) # Hybrid or phyrexian symbols layer_config.mana_cost_config[:hybrid_icon_size] else layer_config.mana_cost_config[:icon_size] end - icon_svg = get_icon_svg(icon_type, icon_size) + icon_svg = @icon_service.symbol_svg(symbol, size: icon_size) return unless icon_svg icon_x = x - (icon_size / 2) @@ -145,15 +130,6 @@ def render_mana_icon(x, y, icon_type) "#{icon_svg}" end - def get_icon_svg(icon_type, size) - case icon_type - when :numeric - @icon_service.numeric_icon_svg(@int_val, size: size) - else - @icon_service.icon_svg(icon_type, size: size) - end - end - def drop_shadow_filter drop_shadow = layer_config.drop_shadow_config <<~SVG.delete("\n") diff --git a/lib/mtg_card_maker/symbol_replacement_service.rb b/lib/mtg_card_maker/symbol_replacement_service.rb index f7bfb52..00f400f 100644 --- a/lib/mtg_card_maker/symbol_replacement_service.rb +++ b/lib/mtg_card_maker/symbol_replacement_service.rb @@ -6,26 +6,6 @@ module MtgCardMaker # SymbolReplacementService handles the parsing and rendering of MTG symbols in text # It converts text with symbol notation (like {W}, {2}, {T}) into HTML with inline SVG icons class SymbolReplacementService - # Mapping of mtg notation to icons - SYMBOL_MAP = { - 'B' => :black, - 'U' => :blue, - 'G' => :green, - 'W' => :white, - 'R' => :red, - 'C' => :colorless, - 'T' => :tap, - 'Q' => :untap, - 'E' => :energy, - 'S' => :snow, - 'X' => :x, - 'C/P' => :'phyrexian-colorless', - 'R/P' => :'phyrexian-red', - 'G/P' => :'phyrexian-green', - 'U/P' => :'phyrexian-blue', - 'B/P' => :'phyrexian-black', - 'W/P' => :'phyrexian-white' - }.freeze attr_reader :font_size, :icon_service, :layer_config def initialize @@ -95,17 +75,13 @@ def render_html_line_with_symbols(parts, _text_width) # @param symbol [String] the symbol in {symbol} format # @return [String, nil] HTML string for the symbol or nil if not found def render_symbol_html(symbol) - # Convert symbol to mana cost format and use IconService - symbol = symbol.gsub(/[{}]/, '') - # Get the SVG content from IconService - icon_svg = get_icon_svg_for_symbol(symbol) + icon_svg = icon_service.symbol_svg(symbol) return unless icon_svg - # Determine icon size based on icon type - icon_type = SYMBOL_MAP[symbol] - icon_size = get_icon_size_for_type(icon_type) + # Determine icon size based on symbol type using IconService + icon_size = get_icon_size_for_symbol(symbol) # Use the SVG content directly with proper styling icon_svg.gsub(/width="[^"]*"/, "width='#{icon_size}'") @@ -113,34 +89,14 @@ def render_symbol_html(symbol) .gsub('= 100 - icon_service.icon_svg(:x) - else - icon_service.numeric_icon_svg(numeric_value) - end - end end end diff --git a/spec/mtg_card_maker/icon_filename_service_spec.rb b/spec/mtg_card_maker/icon_filename_service_spec.rb new file mode 100644 index 0000000..802cab3 --- /dev/null +++ b/spec/mtg_card_maker/icon_filename_service_spec.rb @@ -0,0 +1,151 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe MtgCardMaker::IconFilenameService do + let(:service) { described_class.new } + + describe '#symbol_to_icon_type' do + context 'with basic mana colors' do + it 'maps basic colors correctly', :aggregate_failures do + expect(service.symbol_to_icon_type('{W}')).to eq(:white) + expect(service.symbol_to_icon_type('{B}')).to eq(:black) + expect(service.symbol_to_icon_type('{R}')).to eq(:red) + expect(service.symbol_to_icon_type('{G}')).to eq(:green) + expect(service.symbol_to_icon_type('{U}')).to eq(:blue) + expect(service.symbol_to_icon_type('{C}')).to eq(:colorless) + end + end + + context 'with special symbols' do + it 'maps special symbols correctly', :aggregate_failures do + expect(service.symbol_to_icon_type('{S}')).to eq(:snow) + expect(service.symbol_to_icon_type('{X}')).to eq(:x) + expect(service.symbol_to_icon_type('{T}')).to eq(:tap) + expect(service.symbol_to_icon_type('{Q}')).to eq(:untap) + expect(service.symbol_to_icon_type('{E}')).to eq(:energy) + end + end + + context 'with numeric symbols' do + it 'maps single digit numbers to numeric' do + (0..9).each do |num| + expect(service.symbol_to_icon_type("{#{num}}")).to eq(:numeric) + end + end + + it 'maps double digit numbers to numeric', :aggregate_failures do + expect(service.symbol_to_icon_type('{10}')).to eq(:numeric) + expect(service.symbol_to_icon_type('{25}')).to eq(:numeric) + expect(service.symbol_to_icon_type('{99}')).to eq(:numeric) + end + + it 'returns nil for numbers 100+', :aggregate_failures do + expect(service.symbol_to_icon_type('{100}')).to be_nil + expect(service.symbol_to_icon_type('{999}')).to be_nil + end + end + + context 'with phyrexian symbols' do + it 'maps phyrexian mana symbols correctly', :aggregate_failures do + expect(service.symbol_to_icon_type('{W/P}')).to eq(:'phyrexian-white') + expect(service.symbol_to_icon_type('{B/P}')).to eq(:'phyrexian-black') + expect(service.symbol_to_icon_type('{R/P}')).to eq(:'phyrexian-red') + expect(service.symbol_to_icon_type('{G/P}')).to eq(:'phyrexian-green') + expect(service.symbol_to_icon_type('{U/P}')).to eq(:'phyrexian-blue') + expect(service.symbol_to_icon_type('{C/P}')).to eq(:'phyrexian-colorless') + end + end + + context 'with hybrid symbols' do + it 'maps two-color hybrid symbols correctly', :aggregate_failures do + expect(service.symbol_to_icon_type('{W/B}')).to eq(:'hybrid-white-black') + expect(service.symbol_to_icon_type('{B/W}')).to eq(:'hybrid-black-white') + expect(service.symbol_to_icon_type('{U/R}')).to eq(:'hybrid-blue-red') + expect(service.symbol_to_icon_type('{R/U}')).to eq(:'hybrid-red-blue') + expect(service.symbol_to_icon_type('{G/C}')).to eq(:'hybrid-green-colorless') + expect(service.symbol_to_icon_type('{C/G}')).to eq(:'hybrid-colorless-green') + end + end + + context 'with twobrid symbols' do + it 'maps 2/hybrid symbols correctly', :aggregate_failures do + expect(service.symbol_to_icon_type('{2/W}')).to eq(:'hybrid-2-white') + expect(service.symbol_to_icon_type('{2/B}')).to eq(:'hybrid-2-black') + expect(service.symbol_to_icon_type('{2/R}')).to eq(:'hybrid-2-red') + expect(service.symbol_to_icon_type('{2/G}')).to eq(:'hybrid-2-green') + expect(service.symbol_to_icon_type('{2/U}')).to eq(:'hybrid-2-blue') + expect(service.symbol_to_icon_type('{2/C}')).to eq(:'hybrid-2-colorless') + end + end + + context 'with phyrexian hybrid symbols' do + it 'maps phyrexian hybrid symbols correctly', :aggregate_failures do + expect(service.symbol_to_icon_type('{W/B/P}')).to eq(:'phyrexian-white-black') + expect(service.symbol_to_icon_type('{B/W/P}')).to eq(:'phyrexian-black-white') + expect(service.symbol_to_icon_type('{U/R/P}')).to eq(:'phyrexian-blue-red') + expect(service.symbol_to_icon_type('{R/U/P}')).to eq(:'phyrexian-red-blue') + expect(service.symbol_to_icon_type('{G/C/P}')).to eq(:'phyrexian-green-colorless') + expect(service.symbol_to_icon_type('{C/G/P}')).to eq(:'phyrexian-colorless-green') + end + end + + context 'with invalid symbols' do + it 'returns nil for unknown symbols', :aggregate_failures do + expect(service.symbol_to_icon_type('{Z}')).to be_nil + expect(service.symbol_to_icon_type('{W/B/C}')).to be_nil + expect(service.symbol_to_icon_type('W')).to be_nil + expect(service.symbol_to_icon_type('')).to be_nil + expect(service.symbol_to_icon_type(nil)).to be_nil + end + end + end + + describe '#symbol_map' do + it 'returns a hash with all symbol mappings', :aggregate_failures do + map = service.symbol_map + expect(map).to be_a(Hash) + expect(map).not_to be_empty + end + + it 'includes all basic colors', :aggregate_failures do + map = service.symbol_map + expect(map['{W}']).to eq(:white) + expect(map['{B}']).to eq(:black) + expect(map['{R}']).to eq(:red) + expect(map['{G}']).to eq(:green) + expect(map['{U}']).to eq(:blue) + expect(map['{C}']).to eq(:colorless) + end + + it 'includes all special symbols', :aggregate_failures do + map = service.symbol_map + expect(map['{S}']).to eq(:snow) + expect(map['{X}']).to eq(:x) + expect(map['{T}']).to eq(:tap) + expect(map['{Q}']).to eq(:untap) + expect(map['{E}']).to eq(:energy) + end + + it 'includes numeric symbols', :aggregate_failures do + map = service.symbol_map + expect(map['{0}']).to eq(:numeric) + expect(map['{5}']).to eq(:numeric) + expect(map['{10}']).to eq(:numeric) + expect(map['{99}']).to eq(:numeric) + expect(map['{100}']).to be_nil + end + + it 'includes hybrid symbols', :aggregate_failures do + map = service.symbol_map + expect(map['{W/B}']).to eq(:'hybrid-white-black') + expect(map['{2/W}']).to eq(:'hybrid-2-white') + end + + it 'includes phyrexian symbols', :aggregate_failures do + map = service.symbol_map + expect(map['{W/P}']).to eq(:'phyrexian-white') + expect(map['{W/B/P}']).to eq(:'phyrexian-white-black') + end + end +end diff --git a/spec/mtg_card_maker/icon_service_spec.rb b/spec/mtg_card_maker/icon_service_spec.rb index 260fd25..ec30336 100644 --- a/spec/mtg_card_maker/icon_service_spec.rb +++ b/spec/mtg_card_maker/icon_service_spec.rb @@ -3,11 +3,11 @@ require 'spec_helper' RSpec.describe MtgCardMaker::IconService do - let(:icon_service) { described_class.new } + let(:service) { described_class.new } describe '#initialize' do it 'creates an instance with default icon set' do - expect(icon_service.icon_set).to eq(:default) + expect(service.icon_set).to eq(:default) end it 'creates an instance with custom icon set' do @@ -16,136 +16,131 @@ end end - describe '#available_icon_types' do - it 'returns available icon types for default icon set' do - expected_types = %i[white blue black red green colorless single-digit double-digit] - expect(icon_service.available_icon_types).to include(*expected_types) - end - end - - describe '#available_icon_sets' do - it 'returns available icon sets' do - expect(icon_service.available_icon_sets).to include(:default) - end - end - - describe '#icon_svg' do - it 'returns SVG content for white mana', :aggregate_failures do - svg = icon_service.icon_svg(:white) + describe '#symbol_svg' do + it 'returns SVG content for basic mana symbols', :aggregate_failures do + svg = service.symbol_svg('{W}', size: 24) + expect(svg).to be_a(String) expect(svg).to include('5<') + expect(svg).to include('width="24px"') + expect(svg).to include('height="24px"') end - it 'returns SVG content for colorless mana', :aggregate_failures do - svg = icon_service.icon_svg(:colorless) + it 'returns SVG content for double digit numeric symbols', :aggregate_failures do + svg = service.symbol_svg('{42}', size: 24) + expect(svg).to be_a(String) expect(svg).to include('42<') + expect(svg).to include('width="24px"') + expect(svg).to include('height="24px"') end - it 'caches loaded icons' do - # First call should load from file - allow(File).to receive(:read).and_return('') - - icon_service.icon_svg(:white) - icon_service.icon_svg(:white) # Second call should use cache - - expect(File).to have_received(:read).once + it 'returns SVG content for hybrid symbols', :aggregate_failures do + svg = service.symbol_svg('{W/B}', size: 24) + expect(svg).to be_a(String) + expect(svg).to include('5<') + expect(svg).to include('width="24px"') + expect(svg).to include('height="24px"') end - it 'returns SVG content for double digit number', :aggregate_failures do - svg = icon_service.numeric_icon_svg(16) + it 'returns SVG content for twobrid symbols', :aggregate_failures do + svg = service.symbol_svg('{2/W}', size: 24) + expect(svg).to be_a(String) expect(svg).to include('16<') + expect(svg).to include('width="24px"') + expect(svg).to include('height="24px"') end - it 'returns nil for negative number' do - expect(icon_service.numeric_icon_svg(-1)).to be_nil + it 'returns SVG content for special symbols', :aggregate_failures do + svg = service.symbol_svg('{X}', size: 24) + expect(svg).to be_a(String) + expect(svg).to include('3') - - svg = icon_service.numeric_icon_svg(5) - expect(svg).to include('>5<') + it 'resizes SVG to specified size', :aggregate_failures do + svg = service.symbol_svg('{U}', size: 48) + expect(svg).to include('width="48px"') + expect(svg).to include('height="48px"') end + end - it 'uses double-digit template for double digit numbers' do - allow(File).to receive(:read).with(described_class::DOUBLE_DIGIT_PATH).and_return('16') - - svg = icon_service.numeric_icon_svg(42) - expect(svg).to include('>42<') + describe '#available_icon_types' do + it 'returns available icon types for default icon set', :aggregate_failures do + types = service.available_icon_types + expect(types).to be_an(Array) + expect(types).to include(:white, :black, :red, :green, :blue, :colorless) end + end - it 'returns nil if template files do not exist' do - allow(File).to receive(:exist?).and_return(false) - expect(icon_service.numeric_icon_svg(5)).to be_nil + describe '#available_icon_sets' do + it 'returns available icon sets', :aggregate_failures do + sets = service.available_icon_sets + expect(sets).to be_an(Array) + expect(sets).to include(:default) end end describe '#qr_code_svg' do - it 'returns nil if the QR code SVG file does not exist' do - allow(File).to receive(:exist?).with(MtgCardMaker::IconService::QR_CODE_PATH).and_return(false) - expect(icon_service.qr_code_svg).to be_nil + it 'returns QR code SVG content', :aggregate_failures do + svg = service.qr_code_svg + expect(svg).to be_a(String) + expect(svg).to include('red') + allow(icon_service).to receive(:symbol_svg).with('{R}').and_return('red') service = described_class.new result = service.send(:render_symbol_html, '{R}') @@ -256,8 +256,7 @@ it 'falls back to numeric icons for numbers' do icon_service = instance_double(MtgCardMaker::IconService) allow(MtgCardMaker::IconService).to receive(:new).and_return(icon_service) - allow(icon_service).to receive(:icon_svg).with(nil).and_return(nil) - allow(icon_service).to receive(:numeric_icon_svg).with(1).and_return('1') + allow(icon_service).to receive(:symbol_svg).with('{1}').and_return('1') service = described_class.new result = service.send(:render_symbol_html, '{1}')