From 68c39139f742315c9d8050383c91b736ce1d74e6 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Fri, 19 Jun 2009 21:27:21 +0200 Subject: [PATCH] Improved shogi theme. Add shadows. --- lib/ext/loader.rb | 6 +++- lib/mainwindow.rb | 4 +-- lib/qtutils.rb | 20 ++++++----- lib/themes/celtic/celtic.rb | 11 +++--- lib/themes/fantasy/fantasy.rb | 11 +++--- lib/themes/loader.rb | 2 +- lib/themes/shadow.rb | 46 +++++++++++++++++++++++++ lib/themes/shogi/nude_tile.svg | 76 ++++++++++++++++++++++++++++++++---------- lib/themes/shogi/shogi.rb | 44 +++++++++++++++++------- lib/themes/svg_theme.rb | 14 +++++--- lib/themes/theme.rb | 2 +- 11 files changed, 181 insertions(+), 55 deletions(-) create mode 100644 lib/themes/shadow.rb diff --git a/lib/ext/loader.rb b/lib/ext/loader.rb index 18a13e0..a9415c2 100644 --- a/lib/ext/loader.rb +++ b/lib/ext/loader.rb @@ -6,13 +6,17 @@ rescue LoadError => e end $ext = $qApp.findChild(Qt::Object, "kaya extensions") if $qApp -unless $ext +fake = unless $ext # install fake implementations of the extension functions $ext = Qt::Object.new class << $ext def exp_blur(img, radius) end end + true +end +$ext.metaclass_eval do + define_method(:fake) { fake } end # conveniently install extension functions in the appropriate places diff --git a/lib/mainwindow.rb b/lib/mainwindow.rb index d3d9bfa..70aea68 100644 --- a/lib/mainwindow.rb +++ b/lib/mainwindow.rb @@ -33,8 +33,8 @@ private config = KDE::Global.config.group('themes') theme = Theme.new - theme.pieces = @loader.get_matching(nil, game, - (game.keywords || []) + ['pieces'], []) + theme.pieces = @loader.get_matching('Celtic', game, + (game.keywords || []) + ['pieces'], [], :shadow => true) theme.board = @loader.get_matching(nil, game, ['board'], game.keywords || []) diff --git a/lib/qtutils.rb b/lib/qtutils.rb index 9d854cf..475d702 100644 --- a/lib/qtutils.rb +++ b/lib/qtutils.rb @@ -43,6 +43,17 @@ class Qt::Image Qt::Painter.new(img).paint(&blk) end end + + def self.from_renderer(size, renderer, id = nil) + img = Qt::Image.painted(size) do |p| + if id + renderer.render(p, id) + else + renderer.render(p) + end + end + img + end end module PrintablePoint @@ -95,14 +106,7 @@ class Qt::Pixmap end def self.from_renderer(size, renderer, id = nil) - img = Qt::Image.painted(size) do |p| - if id - renderer.render(p, id) - else - renderer.render(p) - end - end - img.to_pix + Qt::Image.from_renderer(size, renderer, id).to_pix end end diff --git a/lib/themes/celtic/celtic.rb b/lib/themes/celtic/celtic.rb index aea0c92..e55a387 100644 --- a/lib/themes/celtic/celtic.rb +++ b/lib/themes/celtic/celtic.rb @@ -1,12 +1,15 @@ require 'qtutils' require 'themes/svg_theme' -class CelticTheme - include SvgTheme - +class CelticTheme < SvgTheme + include Theme theme :name => 'Celtic', :keywords => %w(chess pieces) - + + def initialize(opts = {}) + super(opts) + end + def filename File.join(File.dirname(__FILE__), 'celtic.svg') end diff --git a/lib/themes/fantasy/fantasy.rb b/lib/themes/fantasy/fantasy.rb index 44c1475..f6671c9 100644 --- a/lib/themes/fantasy/fantasy.rb +++ b/lib/themes/fantasy/fantasy.rb @@ -1,12 +1,15 @@ require 'qtutils' require 'themes/svg_theme' -class FantasyTheme - include SvgTheme - +class FantasyTheme < SvgTheme + include Theme theme :name => 'Fantasy', :keywords => %w(chess pieces) - + + def initialize(opts = {}) + super(opts) + end + def filename File.join(File.dirname(__FILE__), 'fantasy.svg') end diff --git a/lib/themes/loader.rb b/lib/themes/loader.rb index b3b00d5..8555300 100644 --- a/lib/themes/loader.rb +++ b/lib/themes/loader.rb @@ -13,7 +13,7 @@ class ThemeLoader @themes = {} ObjectSpace::each_object(Class) do |k| - if k.include? Theme + if k.include?(Theme) and k.theme_name @themes[k.theme_name] = k end end diff --git a/lib/themes/shadow.rb b/lib/themes/shadow.rb new file mode 100644 index 0000000..4dbdbb8 --- /dev/null +++ b/lib/themes/shadow.rb @@ -0,0 +1,46 @@ +require 'ext/loader' + +module Shadower + ShadowData = Struct.new(:radius, :color, :grow, :offset) + DEFAULT_SHADOW_DATA = + ShadowData.new(7.0, Qt::Color.new(0x40, 0x40, 0x50), 5, Qt::PointF.new(6, 4)) + + def with_shadow(loader, data = DEFAULT_SHADOW_DATA) + lambda do |piece, size| + isz = size * 100 / (100 + data.grow) + Qt::PointF.new(0.5, 0.5) + off = Qt::PointF.new( + data.offset.x * isz.x / 200.0, + data.offset.y * isz.x / 200.0) + img = loader[piece, isz] + scaled_data = ShadowData.new(data.radius * isz.x / 100.0, + data.color, + size.x - isz.x, + off) + s = shadow(img, scaled_data) + Qt::Painter.new(s).paint do |p| + dst = Qt::RectF.new((size.x - isz.x) / 2 - off.x, + (size.y - isz.y) / 2 - off.y, + isz.x, isz.y) + p.draw_image(dst, img, Qt::RectF.new(Qt::PointF.new(0, 0), isz)) + end + s + end + end + + private + + def shadow(img, data) + img = Qt::Image.painted(Qt::Point.new(img.width + data.grow, + img.height + data.grow)) do |p| + px = (data.grow * 0.5 + data.offset.x).to_i + py = (data.grow * 0.5 + data.offset.y).to_i + + p.composition_mode = Qt::Painter::CompositionMode_Source + p.fill_rect Qt::Rect.new(px, py, img.width, img.height), data.color + p.composition_mode = Qt::Painter::CompositionMode_DestinationAtop + p.draw_image Qt::Point.new(px, py), img + end + img.exp_blur(data.radius) + img + end +end diff --git a/lib/themes/shogi/nude_tile.svg b/lib/themes/shogi/nude_tile.svg index 0d1074e..cab3227 100644 --- a/lib/themes/shogi/nude_tile.svg +++ b/lib/themes/shogi/nude_tile.svg @@ -1,11 +1,12 @@ + sodipodi:docname="nude_tile.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + id="defs1464"> + + + + + + + + inkscape:zoom="0.9041297" + inkscape:cx="415.28328" + inkscape:cy="297.17742" + inkscape:window-x="-3" + inkscape:window-y="33" + inkscape:current-layer="svg1447" + showgrid="false" /> Created by potrace 1.7, written by Peter Selinger 2001-2005 @@ -47,11 +80,18 @@ Created by potrace 1.7, written by Peter Selinger 2001-2005 + id="g3173"> + id="path2391" + d="M 32.505197,452.68415 C 32.78198,451.04969 36.096287,421.11503 39.870297,386.16267 C 49.634071,295.73685 70.194993,110.84531 72.053389,96.759927 L 73.621739,84.872924 L 78.006087,82.773141 C 86.312777,78.794853 181.34059,37.938636 195.46203,32.27417 C 214.50463,24.635702 234.91605,17.66565 238.2422,17.66565 C 241.70618,17.66565 267.37247,28.467852 371.61759,73.799587 L 395.80476,84.317532 L 397.37545,94.653471 C 399.36593,107.7497 437.33366,449.94344 437.33366,454.78555 C 437.33366,455.33381 362.33657,455.65591 234.66777,455.65591 L 32.001866,455.65591 L 32.505197,452.68415 z" + style="opacity:1;fill:url(#radialGradient3169);fill-opacity:1;stroke:none;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + + + diff --git a/lib/themes/shogi/shogi.rb b/lib/themes/shogi/shogi.rb index 2592b19..3ce8c76 100644 --- a/lib/themes/shogi/shogi.rb +++ b/lib/themes/shogi/shogi.rb @@ -1,30 +1,50 @@ require 'qtutils' require 'themes/theme' +require 'themes/shadow' class ShogiTheme include Theme + include Shadower + BASE_DIR = File.dirname(__FILE__) TYPES = { :knight => 'n' } NUDE_TILE = File.join(BASE_DIR, 'nude_tile.svg') + RATIOS = { + :king => 1.0, + :rook => 0.96, + :bishop => 0.93, + :gold => 0.9, + :silver => 0.9, + :knight => 0.86, + :lance => 0.83, + :pawn => 0.8 } theme :name => 'Shogi', :keywords => %w(shogi pieces) - def initialize(opts) + def initialize(opts = {}) + @loader = lambda do |piece, size| + tile = Qt::SvgRenderer.new(NUDE_TILE) + kanji = Qt::SvgRenderer.new(filename(piece)) + ratio = RATIOS[piece.type] || 0.9 + img = Qt::Image.painted(size) do |p| + p.scale(ratio, ratio) + p.translate(size * (1 - ratio) / 2) + if piece.color == :white + p.translate(size) + p.rotate(180) + end + tile.render(p) + kanji.render(p) + end + end + if opts.has_key? :shadow + @loader = with_shadow(@loader) + end end def pixmap(piece, size) - tile = Qt::SvgRenderer.new(NUDE_TILE) - kanji = Qt::SvgRenderer.new(filename(piece)) - img = Qt::Image.painted(size) do |p| - if piece.color == :white - p.translate(size) - p.rotate(180) - end - kanji.render(p) - tile.render(p) - end - img.to_pix + @loader[piece, size].to_pix end def filename(piece) diff --git a/lib/themes/svg_theme.rb b/lib/themes/svg_theme.rb index f4eec78..874ca51 100644 --- a/lib/themes/svg_theme.rb +++ b/lib/themes/svg_theme.rb @@ -1,14 +1,20 @@ require 'qtutils' require 'themes/theme' -module SvgTheme - include Theme +class SvgTheme + include Shadower - def initialize(opts) + def initialize(opts = {}) + @loader = lambda do |piece, size| + Qt::Image.from_renderer(size, renderer, piece_id(piece)) + end + if opts.has_key?(:shadow) + @loader = with_shadow(@loader) + end end def pixmap(piece, size) - Qt::Pixmap.from_renderer(size, renderer, piece_id(piece)) + @loader[piece, size].to_pix end def renderer diff --git a/lib/themes/theme.rb b/lib/themes/theme.rb index 2217388..fadf3fc 100644 --- a/lib/themes/theme.rb +++ b/lib/themes/theme.rb @@ -15,7 +15,7 @@ module Theme end def theme_name - (@theme_data || {})[:name] || name + @theme_data[:name] if @theme_data end def matches?(keywords) -- 2.11.4.GIT