#! /usr/bin/env ruby
#
# Change text and line sizes of a mapnik style, to allow printing at different dpi settings. If file is not provided, use stdin.
#
# Command line:		ruby scalestyle.rb --scale <factor> [<file>]
#
# (c) 2009 Holger Schöner
# This script is provided as is, without any warranty for any purpose. You may use it under the terms of the BSD license
# (http://www.opensource.org/licenses/bsd-license.php)
#

# ==============================================================================================================================
# Global variables

$files      = []
$scale      = 4

# ==============================================================================================================================
# Command line parsing

require 'getoptlong'
# specify the options we accept and initialize the option parser
opts = GetoptLong.new(
  [ "--scale",		"-s",		GetoptLong::REQUIRED_ARGUMENT ]
#  [ "--linenums",	"-l",		GetoptLong::NO_ARGUMENT ],
#  [ "--markmatch",	"-p",		GetoptLong::NO_ARGUMENT ],
#  [ "--multiline",	"-m",		GetoptLong::NO_ARGUMENT ]
)
# process the parsed options
opts.each do |opt, arg|
    puts "Option: #{opt}, arg #{arg.inspect}"
    case opt
    when "--scale" then   $scale = arg.to_f
    end
end

$files = ARGV

if $files.length < 1
    $files << "-"
end

# ==============================================================================================================================
# Main program

print("*** Scaling width and size parameters by factor '#{$scale}'\n")
$files.each do |filename|
    file = (filename == "-") ? $stdin : File.open(filename)
    lines = file.readlines
    #if ($files.length > 1)
        print("=== #{filename} " + ("=" * ([79-filename.length-5,0].max)) + "\n")
    #end
    lines.collect! { |row|
        row.gsub!( /<CssParameter name="stroke-width">([0-9.]+)<\/CssParameter>/) { |val| "<CssParameter name=\"stroke-width\">#{($scale * $1.to_f).round}</CssParameter>" }
        row.gsub!( /<CssParameter name="stroke-dasharray">([0-9.,]+)<\/CssParameter>/) { |val| res = $1.split(',').collect {|x| ($scale * x.to_f).round}.join(','); "<CssParameter name=\"stroke-dasharray\">#{res}</CssParameter>" }
        row.gsub!( /<ShieldSymbolizer (.*)size="([0-9.]+)"/) { |val| "<ShieldSymbolizer #{$1}size=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<ShieldSymbolizer (.*)min_distance="([0-9.]+)"/) { |val| "<ShieldSymbolizer #{$1}min_distance=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<ShieldSymbolizer (.*)width="([0-9.]+)"/) { |val| "<ShieldSymbolizer #{$1}width=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<ShieldSymbolizer (.*)height="([0-9.]+)"/) { |val| "<ShieldSymbolizer #{$1}height=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<TextSymbolizer (.*)size="([0-9.]+)"/) { |val| "<TextSymbolizer #{$1}size=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<TextSymbolizer (.*)wrap_width="([0-9.]+)"/) { |val| "<TextSymbolizer #{$1}wrap_width=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<TextSymbolizer (.*)halo_radius="([0-9.]+)"/) { |val| "<TextSymbolizer #{$1}halo_radius=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<TextSymbolizer (.*)min_distance="([0-9.]+)"/) { |val| "<TextSymbolizer #{$1}min_distance=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<PointSymbolizer (.*)width="([0-9.]+)"/) { |val| "<PointSymbolizer #{$1}width=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<PointSymbolizer (.*)height="([0-9.]+)"/) { |val| "<PointSymbolizer #{$1}height=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<LinePatternSymbolizer (.*)width="([0-9.]+)"/) { |val| "<LinePatternSymbolizer #{$1}width=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<LinePatternSymbolizer (.*)height="([0-9.]+)"/) { |val| "<LinePatternSymbolizer #{$1}height=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<PolygonPatternSymbolizer (.*)width="([0-9.]+)"/) { |val| "<PolygonPatternSymbolizer #{$1}width=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<PolygonPatternSymbolizer (.*)height="([0-9.]+)"/) { |val| "<PolygonPatternSymbolizer #{$1}height=\"#{($scale * $2.to_i).round}\"" }
        row.gsub!( /<MaxScaleDenominator>(\d+)<\/MaxScaleDenominator>/) { |val| "<MaxScaleDenominator>#{($1.to_i / $scale).round}</MaxScaleDenominator>" }
        row.gsub!( /<MinScaleDenominator>(\d+)<\/MinScaleDenominator>/) { |val| "<MinScaleDenominator>#{($1.to_i / $scale).round}</MinScaleDenominator>" }
        row.gsub!( /dx="([-0-9.]+)"/) { |val| "dx=\"#{($scale * $1.to_i).round}\"" }
        row.gsub!( /dy="([-0-9.]+)"/) { |val| "dy=\"#{($scale * $1.to_i).round}\"" }
#        print("----------\nold: '#{row.strip}'\nnew: '#{res.strip}'\n") unless res === row
        row
    }
    file.close if filename != "-"
#    File.rename(filename, filename+".bak")
    File.unlink(filename)
    File.open(filename, "w") { |file| file.print(lines.to_s) }
end

