#!/usr/bin/python3
# Author: Martin Pitt <martin.pitt@ubuntu.com>
# (C) 2011 Canonical Ltd.
# License: Apache (see debian/copyright)

'''Fuzzy-comparison of two SVGs. If their rendered bitmaps differ by more than
a given threshold (default: 0.05%), or have different dimensions, exit with 1,
otherwise exit with 0.'''

import sys
try:
    import gi
    gi.require_version('Rsvg', '2.0')
    from gi.repository import Rsvg
except (ImportError, ValueError):
    sys.stderr.write('cmpsvg: gir1.2-rsvg-2.0 or python3-gi not installed, cannot compare SVG images\n')
    sys.exit(0)
try:
    import cairo
except ImportError:
    sys.stderr.write('cmpsvg: python3-cairo not installed, cannot compare SVG images\n')
    sys.exit(0)

DEFAULT_TRESHOLD=0.0005

if len(sys.argv) not in [3, 4]:
    sys.stderr.write('Usage: %s <file1.svg> <file2.svg> [diff threshold (default %0.4f)]\n' % (
        sys.argv[0], DEFAULT_TRESHOLD))
    sys.exit(2)

if len(sys.argv) == 4:
    threshold = float(sys.argv[3])
else:
    threshold = DEFAULT_TRESHOLD

def svg_bitmap(svgfile):
    '''Convert an SVG file into a raw bitmap

    Return a tuple (width, height, data).
    '''
    svg = Rsvg.Handle.new_from_file(svgfile)
    s = cairo.ImageSurface(cairo.FORMAT_ARGB32, svg.props.width,
            svg.props.height)
    viewport = Rsvg.Rectangle()
    viewport.width = svg.props.width
    viewport.height = svg.props.height
    svg.render_document(cairo.Context(s), viewport)

    return (svg.props.width, svg.props.height, s.get_data())

(w1, h1, d1) = svg_bitmap(sys.argv[1])
(w2, h2, d2) = svg_bitmap(sys.argv[2])

if w1 != w2 or h1 != h2:
    sys.stderr.write('Images differ in size: %s (%ix%i),  %s (%ix%i)\n' %
            (sys.argv[1], w1, h1, sys.argv[2], w2, h2))
    sys.exit(1)

diff = 0
for i in range(len(d1)):
    diff += abs(d1[i] - d2[i])
sumd1 = sum(d1)
if sumd1 > 0:
    diff /= float(sumd1)
else:
    # for empty pictures, any difference at all is a total failure, so don't
    # scale it down
    pass
print('difference: %.3f%%' % (diff*100))
if diff > threshold:
    sys.stderr.write('Images differ by more than %.3f%%\n' % (threshold*100))
    sys.exit(1)
