#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include <cairo.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
#include <glib.h>

int main(int argc, char **argv){
  if(argc != 4){
    fprintf(stderr,"Usage:\n  "
      "pango-test \"[FAMILY-LIST] [STYLE-OPTIONS] [SIZE]\"  GLYPH-INDEX  FILENAME.PNG\n");
    return 1;
  }
  
  char       *desc_text = argv[1];
  PangoGlyph  glyph     = (PangoGlyph)strtol(argv[2],NULL,0);
  char       *output    = argv[3];
  PangoFont  *font      = NULL;
  
  // getting the PangoFont from the description:
  {
    PangoContext *context = pango_cairo_font_map_create_context(
      (PangoCairoFontMap*)pango_cairo_font_map_get_default());
    
    PangoFontDescription *desc = pango_font_description_from_string(desc_text);
    PangoAttrList *tmp_attrs = pango_attr_list_new();
    PangoAttribute *attr     = pango_attr_font_desc_new(desc);
    attr->start_index = 0;
    attr->end_index   = 1;
    pango_attr_list_insert_before(tmp_attrs, attr);
    
    GList *items = pango_itemize(context, "a", 0, 1, tmp_attrs, NULL);
    font = ((PangoItem*)items->data)->analysis.font;
    
    g_list_free(items);
    pango_attr_list_unref(tmp_attrs);
    pango_font_description_free(desc);
    g_object_unref(context);
  }
  
  if(!font){
    fprintf(stderr, "No appropriate font `%s` found.\n", desc_text);
    //g_object_unref(context);
    return 1;
  }
  
  // glyph extends + output:
  PangoRectangle ink;
  PangoRectangle logic;
  pango_font_get_glyph_extents(font, glyph, &ink, &logic);
  {
    printf("\nglyph %d\n", glyph);
    printf("ink-rect:\n"
           "  x      = %8d (%3.0fpt)\n"
           "  y      = %8d (%3.0fpt)\n"
           "  width  = %8d (%3.0fpt)\n"
           "  height = %8d (%3.0fpt)\n",
           ink.x,      (double) ink.x      / PANGO_SCALE,
           ink.y,      (double) ink.y      / PANGO_SCALE,
           ink.width,  (double) ink.width  / PANGO_SCALE,
           ink.height, (double) ink.height / PANGO_SCALE);
    printf("logic-rect:\n"
           "  x      = %8d (%3.0fpt)\n"
           "  y      = %8d (%3.0fpt)\n"
           "  width  = %8d (%3.0fpt)\n"
           "  height = %8d (%3.0fpt)\n",
           logic.x,      (double) logic.x      / PANGO_SCALE,
           logic.y,      (double) logic.y      / PANGO_SCALE,
           logic.width,  (double) logic.width  / PANGO_SCALE,
           logic.height, (double) logic.height / PANGO_SCALE);
  }

  cairo_surface_t *surface = cairo_image_surface_create(
    CAIRO_FORMAT_ARGB32,
    logic.width  / PANGO_SCALE, 
    logic.height / PANGO_SCALE);
    
  cairo_t *cr = cairo_create(surface);
  cairo_set_line_width(cr, 1);
  cairo_set_source_rgb(cr, 1, 1, 1);
  cairo_paint(cr);
  
  {
    // ink rect:
    cairo_move_to(cr, (double) ink.x  / PANGO_SCALE, (double)(-logic.y+ink.y) / PANGO_SCALE);
    cairo_rel_line_to(cr, (double) ink.width / PANGO_SCALE, 0);
    cairo_rel_line_to(cr, 0, (double) ink.height / PANGO_SCALE);
    cairo_rel_line_to(cr, (double) -ink.width / PANGO_SCALE, 0);
    cairo_rel_line_to(cr, 0, (double) -ink.height / PANGO_SCALE);
    cairo_set_source_rgb(cr, 0.5, 1, 0.5);
    cairo_fill(cr);
    
    // manually setting the glyph string:
    PangoGlyphInfo glyph_info;
    memset(&glyph_info, 0, sizeof(PangoGlyphInfo));
    glyph_info.glyph = glyph;
    
    PangoGlyphString glyph_string;
    glyph_string.num_glyphs = 1;
    glyph_string.glyphs = &glyph_info;
    
    // showing the glyph:
    cairo_move_to(cr, (double) logic.x / PANGO_SCALE, (double)-logic.y / PANGO_SCALE);
    cairo_set_source_rgb(cr, 0, 0, 0);
    pango_cairo_show_glyph_string(cr, font, &glyph_string);
    
    // the base line:
    cairo_move_to(cr, 0.5, 0.5 + (double)-logic.y / PANGO_SCALE);
    cairo_rel_line_to(cr, (double) logic.width / PANGO_SCALE, 0);
    cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
    cairo_stroke(cr);
  }
  
  cairo_destroy(cr);
  cairo_status_t status = cairo_surface_write_to_png(surface, output);
  cairo_surface_destroy(surface);
  
  if(status != CAIRO_STATUS_SUCCESS){
    fprintf(stderr, "Cannot save PNG to '%s'\n", output);
    return 1;
  }
  
  return 0;
}
