/*
	Copyright (C) 2016-2026 Mark Tyler

	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 in the file COPYING.
*/

#include <string.h>
#include <math.h>
#include <time.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>

#include <cairo-pdf.h>
#include <cairo-ps.h>
#include <cairo-svg.h>
#include <pango/pangoft2.h>
#include <pango/pangocairo.h>

#include "mtpixy_cairo.h"



#ifndef DEBUG
#pragma GCC visibility push ( hidden )
#endif



#ifdef __cplusplus
extern "C" {
#endif

// C API

struct mtPixmap
{
	int		width;
	int		height;

	int		bpp;		// Bytes per pixel: 1=Indexed 3=RGB
	int		palette_file;	// 1=Palette loaded from file

	unsigned char	* canvas;
	unsigned char	* alpha;

	mtPalette	palette;
};



mtPixmap * pixy_pixmap_from_data (
	int		type,		// 0=Alpha only 1=Indexed 3=RGB
	int		width,
	int		height,
	unsigned char	* canvas,
	unsigned char	* alpha
	);

int pixy_pixmap_copy_alpha (
	mtPixmap	* dest,
	mtPixmap const	* src
	);

mtPixmap * pixy_pixmap_resize_trim_by_alpha (
	mtPixmap const	* pixmap,
	int		* minx,
	int		* miny
	);

int pixy_pixmap_move_alpha (
	mtPixmap	* dest,	// Move alpha to this image (same geometry)
	mtPixmap	* src
	);

int pixy_palette_merge_duplicates (
	mtPixmap	* pixmap,	// Must be INDEXED image
	int		* tot
	);

int pixy_palette_remove_unused (
	mtPixmap	* pixmap,	// Must be INDEXED image
	int		* tot
	);

int pixmap_palette_create_from_canvas (
	mtPixmap	* pixmap	// Must be RGB image
	);

int pixmap_pixmap_quantize_pnn (
	mtPixmap	* pixmap,	// Must be RGB image
	int		coltot,		// Total colours to quantize to
	mtPalette	* pal,		// Destination palette,NULL= Use image
	int		contrast,	// -100..100
	int		saturation,	// -100..100
	int		posterize	// 1..8
	);



/// PAINTING -------------------------------------------------------------------

void pixy_paint_flow (
	mtPixmap	* alpha_mask,
	int		flow		// brush.get_flow ();
	);



#ifdef __cplusplus
}

// C++ API

namespace mtPixy
{

mtPixmap * text_render_paste (
	int bpp,
	Brush &bru,
	char const * utf8,
	char const * font_name,
	int size,
	int bold,
	int italics,
	Font::StyleUnderline underline,
	int strikethrough
	);

int paste_alpha_pattern (	// Paste using src alpha channel to
	mtPixmap * dest,	// blend canvas pixels with brush
	mtPixmap const * src,	// pattern. Alpha unchanged.
	Brush &bru,		// Paste src onto dest starting here
	int x,
	int y
	);

int paint_flood_fill (
	mtPixmap * pixmap,
	Brush &brush,
	int x,
	int y
	);

}		// namespace mtPixy



namespace mtPixyUI
{

class UndoStep
{
public:
	explicit UndoStep ( mtPixmap * pim );
	~UndoStep ();

	void insert_after ( UndoStep * us );
	int step_restore ( mtPixy::Pixmap & ppim ) const;

	inline mtPixmap * get_pixmap () const { return m_pixmap.get(); }

	UndoStep * get_step_previous () const;
	UndoStep * get_step_next () const;
	int64_t get_canvas_bytes () const;
	void delete_steps_next ();

private:
	void set_canvas_bytes ();

/// ----------------------------------------------------------------------------

	UndoStep	* m_step_previous	= nullptr;
	UndoStep	* m_step_next		= nullptr;

	mtPixy::Pixmap	const m_pixmap;

	// Bytes used by m_pixmap canvas
	int64_t		m_canvas_bytes		= 0;
};

}		// namespace mtPixyUI



#endif		// C++ API



#define PASTE_SETUP						\
	if ( x <= -src->width || y <= -src->height )		\
	{							\
		return 0;					\
	}							\
	int dx1 = x;						\
	int dy1 = y;						\
	int dx2 = x + src->width;				\
	int dy2 = y + src->height;				\
	int sx1 = 0;						\
	int sy1 = 0;						\
	/* Clip copy rectangle to destination */		\
	if ( dx1 < 0 )						\
	{							\
		sx1 = -dx1;					\
		dx1 = 0;					\
	}							\
	if ( dy1 < 0 )						\
	{							\
		sy1 = -dy1;					\
		dy1 = 0;					\
	}							\
	dx2 = MIN ( dx2, dest->width );				\
	dy2 = MIN ( dy2, dest->height );			\
	if (	sx1 >= src->width	||			\
		sy1 >= src->height	||			\
		dx2 < dx1		||			\
		dy2 < dy1					\
		)						\
	{							\
		/* No rectangle overlap so nothing to paste */	\
		return 0;					\
	}							\





#ifndef DEBUG
#pragma GCC visibility pop
#endif

