#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Plug-in:      Scale Layer to Image Size
# Version:      1.4
# Date:         30.01.2015
# Author:       Dmitry Dubyaga <dmitry.dubyaga@gmail.com>
# Tested with:  GIMP 2.8.14
# Location:     <Image>/Layer/Scale Layer to Image Size...

# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

from gimpfu import *

def find_layers_in_group(group, elements):
    gr_items = pdb.gimp_item_get_children(group)
    for id in gr_items[1]:
        sublayer = gimp.Item.from_id(id)
        if pdb.gimp_item_is_group(sublayer):
            find_layers_in_group(sublayer, elements)
        else:
            elements.append(sublayer)
    return elements

def align_layer_to_center(image, layer):
    offset_x = (image.width - layer.width) / 2
    offset_y = (image.height - layer.height) / 2
    return layer.set_offsets(offset_x, offset_y)

def python_fu_scale_layer_to_image_size(image, drawable, scaling_type, other_scaling_type, scale_separately, addition, interpolation, align_method, crop):
    gimp.context_push()
    image.undo_group_start()

    pdb.gimp_message_get_handler(ERROR_CONSOLE)

    if pdb.gimp_item_is_layer(drawable):
        pdb.gimp_context_set_interpolation(interpolation)
        asp_ratio_image = image.width / float(image.height)
        if pdb.gimp_item_is_group(drawable) and scale_separately:
            sublayers_list = find_layers_in_group(drawable, elements = [])
            for sublayer in sublayers_list:
                asp_ratio_sublayer = sublayer.width / float(sublayer.height)
                if scaling_type == "st_fit_inside":
                    if asp_ratio_image > asp_ratio_sublayer:
                        sublayer_height = image.height + image.height * addition / 100
                        sublayer_width = sublayer_height * asp_ratio_sublayer
                    else:
                        sublayer_width = image.width + image.width * addition / 100
                        sublayer_height = sublayer_width / asp_ratio_sublayer
                elif scaling_type == "st_fit_outside":
                    if asp_ratio_image > asp_ratio_sublayer:
                        sublayer_width = image.width + image.width * addition / 100
                        sublayer_height = sublayer_width / asp_ratio_sublayer
                    else:
                        sublayer_height = image.height + image.height * addition / 100
                        sublayer_width = sublayer_height * asp_ratio_sublayer
                elif scaling_type == "st_scale_to_width_and_height":
                    sublayer_width = image.width + image.width * addition / 100
                    sublayer_height = image.height + image.height * addition / 100
                else:
                    if other_scaling_type == 0:
                        sublayer_width = image.width + image.width * addition / 100
                        sublayer_height = sublayer.height
                    elif other_scaling_type == 1:
                        sublayer_height = image.height + image.height * addition / 100
                        sublayer_width = sublayer.width
                    else:
                        sublayer_width = sublayer.width + sublayer.width * addition / 100
                        sublayer_height = sublayer.height + sublayer.height * addition / 100
                pdb.gimp_layer_scale(sublayer, sublayer_width, sublayer_height, TRUE)
                if align_method == 1:
                    align_layer_to_center(image, sublayer)
            if align_method == 0:
                align_layer_to_center(image, drawable)
            if crop:
                if drawable.width > image.width or drawable.height > image.height:
                    pdb.gimp_layer_resize_to_image_size(drawable)
                    pdb.plug_in_autocrop_layer(image, drawable)
            gimp.displays_flush()
            image.undo_group_end()
            gimp.context_pop()
            return
        asp_ratio_drawable = drawable.width / float(drawable.height)
        if scaling_type == "st_fit_inside":
            if asp_ratio_image > asp_ratio_drawable:
                layer_height = image.height + image.height * addition / 100
                layer_width = layer_height * asp_ratio_drawable
            else:
                layer_width = image.width + image.width * addition / 100
                layer_height = layer_width / asp_ratio_drawable
        elif scaling_type == "st_fit_outside":
            if asp_ratio_image > asp_ratio_drawable:
                layer_width = image.width + image.width * addition / 100
                layer_height = layer_width / asp_ratio_drawable
            else:
                layer_height = image.height + image.height * addition / 100
                layer_width = layer_height * asp_ratio_drawable
        elif scaling_type == "st_scale_to_width_and_height":
            layer_width = image.width + image.width * addition / 100
            layer_height = image.height + image.height * addition / 100
        else:
            if other_scaling_type == 0:
                layer_width = image.width + image.width * addition / 100
                layer_height = drawable.height
            elif other_scaling_type == 1:
                layer_height = image.height + image.height * addition / 100
                layer_width = drawable.width
            else:
                layer_width = drawable.width + drawable.width * addition / 100
                layer_height = drawable.height + drawable.height * addition / 100
        pdb.gimp_layer_scale(drawable, layer_width, layer_height, TRUE)
        if align_method != 2:
            align_layer_to_center(image, drawable)
        if crop:
            if drawable.width > image.width or drawable.height > image.height:
                pdb.gimp_layer_resize_to_image_size(drawable)
                pdb.plug_in_autocrop_layer(image, drawable)
        gimp.displays_flush()
        image.undo_group_end()
        gimp.context_pop()
        return
    else:
        pdb.gimp_message("The layer or layer group is not selected.")
        image.undo_group_end()
        gimp.context_pop()
        return

register (
    "python-fu-scale-layer-to-image-size",
    "Scale Layer to Image Size\nVersion 1.4\nScaling a group of layers is also supported.",
    "Scale Layer to Image Size\nVersion 1.4\nScaling a group of layers is also supported.",
    "Dmirty Dubyaga",
    "Dmitry Dubyaga <dmitry.dubyaga@gmail.com>",
    "30.01.2015",
    "Scale Layer to Image Size...",
    "*",
    [
        (PF_IMAGE, "image", "", None),
        (PF_DRAWABLE, "drawable", "", None),
        (PF_RADIO, "scaling_type", "Scaling type:", "st_fit_inside",
            (
                ("Fit inside", "st_fit_inside"),
                ("Fit outside", "st_fit_outside"),
                ("Scale to width and height", "st_scale_to_width_and_height"),
                ("Other", "st_other")
            )
        ),
        (PF_OPTION, "other_scaling_type", "Other scaling type:", 2,
            ("Scale to width", "Scale to height", "None")
        ),
        (PF_TOGGLE, "scale_separately", "Scale separately each layer\nin the selected group:", True),
        (PF_SPINNER, "addition", "Addition (%):", 0,
            (-99, 100, 1)
        ),
        (PF_OPTION, "interpolation", "Interpolation:", 2,
            ("None", "Linear", "Cubic", "Sinc (Lanczos3)")
        ),
        (PF_OPTION, "align_method", "Align to image center:", 1,
            ("Group as a whole", "Each layer separately", "None")
        ),
        (PF_TOGGLE, "crop", "Crop to image size:", False)
    ],
    [],
    python_fu_scale_layer_to_image_size, menu="<Image>/Layer/"
    )

main()
