
// SPDX-License-Identifier: CC-BY-NC-SA-4.0
//
// Copyright (C) 2026 Bit by Bit Signal Processing LLC (https://bxbsp.com)
//
// This work is placed under the "Creative Commons Attribution
// NonCommercial ShareAlike 4.0 International" license, known
// by the shortened acronym "CC-BY-NC-SA-4.0".
//
// This work 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.
//
// A CC-BY-NC-SA-4.0 license allows you to use this work for
// noncommercial purposes so long as attribution is made to the
// original author.  Modified versions of this work may be distributed,
// but only under the same license.  For further details, see the
// Creative Commons License "CC-BY-NC-SA-4.0".
//
// You should have received a copy of the CC-BY-NC-SA-4.0 license
// along with this work. If not, see
// <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
//


#include <stdint.h>

#include "panel.hh"
#include "backing_panel.hh"
#include "color.hh"
#include "all_svg.hh"
#include "string.h"

/*
 *
 * Removed this so we can refer SVG drawing to the lowest level, the display, so that
 * it can be passed off over a websocket link to be drawn on the other side.
 *
panel* new_panel_from_svg(const char* filename, int max_width, int max_height, color bg)
{
  RsvgDimensionData  dim;
  GError * gerror = 0;
  int width;
  int height;
  
  //RsvgHandle *svgh = rsvg_handle_new_from_data(svg_data, svg_data_length, &gerror);
  RsvgHandle *svgh = rsvg_handle_new_from_file(filename, &gerror); 

  if(!svgh)
    {
      printf("Couldn't create RSVG handle.\n");
      return 0;
    }
    
  rsvg_handle_get_dimensions(svgh, &dim);


  // Keep aspect ratio, but size as big as possible within specified dimensions
  if(max_height==0 || float(dim.width)/dim.height > float(max_width)/max_height)
    {
      // Object is wider than panel in aspect.  Scale object to match width.

      width  = max_width;
      height = dim.height * max_width / dim.width;
    }
  else
    {
      // Object is narrower than panel in aspect.  Scale object to match height.
	  
      width  = dim.width * max_height / dim.height;
      height = max_height;
    }

  
  //  printf("SVG Dimensions are %dx%d\n", dim.width, dim.height);

  // CAIRO_FORMAT_RGB16_565
  // CAIRO_FORMAT_ARGB32
  cairo_surface_t* cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  
  if(!cs)
    {
      printf("Couldn't create cairo surface.\n");
      g_object_unref(svgh);
      return 0;
    }

  cairo_t *cr = cairo_create(cs);

  if(!cr)
    {
      printf("Couldn't create cairo renderer.\n");
      cairo_surface_destroy(cs);
      g_object_unref(svgh);
      return 0;
    }

  //cairo_translate(cr, 1, 1);
  cairo_scale(cr, float(width)/dim.width, float(height)/dim.height);
  
  rsvg_handle_render_cairo(svgh, cr);

  cairo_surface_flush(cs);

  uint32_t* data = (uint32_t*) cairo_image_surface_get_data(cs);

  backing_panel* pan = new backing_panel(width, height);

  pan->clear(bg);
  
  for(int x=0; x<width; x++)
    for(int y=0; y<height; y++)
      {
	uint32_t pixel_data = data[x+y*width];
	uint32_t alpha = (pixel_data>>24) & 0xff;
	uint32_t red   = (pixel_data>>16) & 0xff;
	uint32_t green = (pixel_data>> 8) & 0xff;
	uint32_t blue  = (pixel_data>> 0) & 0xff;

	color c = RGB(red, green, blue);
	point p(x, y);
	float frac = float(alpha)/255;
	
	pan->draw_point_antialiased(p, c, frac);
      }

  //cairo_surface_mark_dirty(cs);  // For if we modify the image data ourselves
  //int cerror = cairo_surface_write_to_png(cs, "out.png");  // To write to a PNG file
  //  if(cerror==CAIRO_STATUS_SUCCESS)
  //    printf("PNG write reports success.\n");
  //  else
  //    printf("PNG write reports failure.\n");
    
  cairo_surface_destroy(cs);
  g_object_unref(svgh);

  return pan;
}
*/
















#ifdef NOTDEF
void panel::draw_rect_with_curved_edges(color c, int x, int y, int w, int h, int circle_width)
{
  backing_panel whc(circle_width, circle_width);
  whc.clear(BLACK);
  
  whc.draw_svg(white_circle_svg, white_circle_svg_length);

  draw_color_with_panel_green_as_alpha(c, &whc, x, y);
  draw_color_with_panel_green_as_alpha(c, &whc, x, y+h-circle_width-1);
  draw_color_with_panel_green_as_alpha(c, &whc, x+w-circle_width-1, y);
  draw_color_with_panel_green_as_alpha(c, &whc, x+w-circle_width-1, y+h-circle_width-1);


  clear_rect(c,
	     point(x+circle_width/2,     y),
	     point(x+w-circle_width/2-1, y+h-1));
  
  clear_rect(c,
	     point(x,                    y+circle_width/2),
	     point(x+circle_width/2,  y+h-circle_width/2-1));
  
  clear_rect(c,
	     point(x+w-circle_width/2-1,   y+circle_width/2),
	     point(x+w-1,                y+h-circle_width/2-1));
}
#endif


void panel::draw_rect_with_curved_edges(color c, int x, int y, int w, int h, int circle_width)
{
  int circle_radius = circle_width/2;
  
  draw_circle( pointf(     x+circle_radius,     y+circle_radius), circle_radius, c);
  draw_circle( pointf(     x+circle_radius, y+h-circle_radius-1), circle_radius, c);
  draw_circle( pointf( x+w-circle_radius-1,     y+circle_radius), circle_radius, c);
  draw_circle( pointf( x+w-circle_radius-1, y+h-circle_radius-1), circle_radius, c);

  clear_rect(c,
	     point(x+circle_radius,     y),
	     point(x+w-circle_radius-1, y+h-1));
  
  clear_rect(c,
	     point(x,                   y+circle_radius),
	     point(x+circle_radius+1,   y+h-circle_radius-1));
  
  clear_rect(c,
	     point(x+w-circle_radius-2, y+circle_radius),
	     point(x+w-1,               y+h-circle_radius-1));
}





void panel::draw_circle(pointf p0, float radius, color c)
{
  uint32_t cc = RGB_to_RGBA(c);

  float a = (cc & 0xFF) / 255;
  int b = (cc & 0xFF00) >> 8;
  int g = (cc & 0xFF0000) >> 16;
  int r = (cc & 0xFF000000) >> 24;

  char circle[500];

  int len = sprintf(circle,
		    "<svg version=\"1.1\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n"
		    "<circle cx=\"50\" cy=\"50\" r=\"50\" fill=\"rgba(%d, %d, %d, %f)\"/>\n"
		    "</svg>\n",
		    r, g, b, a);
  
  draw_svg_from_data((uint8_t*)circle, len, p0.x-radius, p0.y-radius, 2*radius, 2*radius);
}
 


void panel::draw_triangle(pointf p0, pointf p1, pointf p2, color c)
{
  float minx = min(p0.x, min(p1.x, p2.x));
  float maxx = max(p0.x, max(p1.x, p2.x));
  float miny = min(p0.y, min(p1.y, p2.y));
  float maxy = max(p0.y, max(p1.y, p2.y));

  float w = maxx - minx;
  float h = maxy - miny;
  
  uint32_t cc = RGB_to_RGBA(c);

  float a = (cc & 0xFF) / 255;
  int b = (cc & 0xFF00) >> 8;
  int g = (cc & 0xFF0000) >> 16;
  int r = (cc & 0xFF000000) >> 24;

  char triangle[500];
  
  int len = sprintf(triangle,
		    "<svg version=\"1.1\" width=\"%f\" height=\"%f\" viewBox=\"0 0 %f %f\" xmlns=\"http://www.w3.org/2000/svg\">\n"
		    "<polygon points=\"%f %f %f %f %f %f\" fill=\"rgba(%d, %d, %d, %f)\"/>\n"
		    "</svg>\n",
		    w, h, w, h, p0.x-minx, p0.y-miny, p1.x-minx, p1.y-miny, p2.x-minx, p2.y-miny, r, g, b, a);


  //printf("triangle=\n\n%s\n", triangle);
  
  draw_svg_from_data((uint8_t*)triangle, len, minx, miny, w, h);

}

