<?php
/* $Id: glyphinfo.php,v 1.5.2.1 2010/07/28 12:38:55 rjs Exp $
 *
 *  Simple PDF glyph dumper based on PDFlib TET
 */


/* global option list */
$globaloptlist = "searchpath={../data ../../data ../../../resource/cmap}";

/* document-specific option list */
$docoptlist = "";

/* page-specific option list */
$pageoptlist = "granularity=word";

# TET_char_info character types with real geometry info.
define("TET_CT__REAL", 0);
define("TET_CT_NORMAL", 0);
define("TET_CT_SEQ_START", 1);

# TET_char_info character types with artificial geometry info.
define("TET_CT__ARTIFICIAL", 10);
define("TET_CT_SEQ_CONT", 10);
define("TET_CT_INSERTED", 12);


# TET_char_info text rendering modes.
define("TET_TR_FILL", 0);		# fill text
define("TET_TR_STROKE", 1);		# stroke text (outline)
define("TET_TR_FILLSTROKE", 2);		# fill and stroke text
define("TET_TR_INVISIBLE", 3);		# invisible text
define("TET_TR_FILL_CLIP", 4);		# fill text and
                                        # add it to the clipping path
define("TET_TR_STROKE_CLIP", 5);	# stroke text and
                                        #  add it to the clipping path
define("TET_TR_FILLSTROKE_CLIP", 6);    # fill and stroke text and
                                        #  add it to the clipping path
define("TET_TR_CLIP", 7);		# add text to the clipping path

# TET_char_info attributes
define("TET_ATTR_NONE", 0x00000000);
define("TET_ATTR_SUB", 0x00000001);	# subscript
define("TET_ATTR_SUP", 0x00000002);	# superscript
define("TET_ATTR_DROPCAP", 0x00000004);	# initial large letter
define("TET_ATTR_SHADOW", 0x00000008);	# shadowed text
# character before hyphenation
define("TET_ATTR_DEHYPHENATION_PRE", 0x00000010);
# hyphenation artifact, i.e. the dash
define("TET_ATTR_DEHYPHENATION_ARTIFACT", 0x00000020);
# character after hyphenation
define("TET_ATTR_DEHYPHENATION_POST", 0x00000040);

$pageno = 0;

try {
    $infilename = "FontReporter.pdf";
    $outfilename = "FontReporter.info.txt";

    $tet = new TET();

    if (!$outfp = fopen($outfilename, "wb")) {
	die("Couldn't open output file '" . $outfilename . "'\n");
    }


    $tet->set_option($globaloptlist);

    $doc = $tet->open_document($infilename, $docoptlist);

    if ($doc == -1) {
	die("Error ". $tet->get_errnum() . " in " . $tet->get_apiname()
	    . "(): " . $tet->get_errmsg() . "\n");
    }

    /* get number of pages in the document */
    $n_pages = $tet->pcos_get_number($doc, "length:pages");

    /* loop over pages in the document */
    for ($pageno = 1; $pageno <= $n_pages; ++$pageno) {

	$page = $tet->open_page($doc, $pageno, $pageoptlist);

	if ($page == -1) {
	    fwrite(STDERR, "Error ". $tet->get_errnum() ." in ".
		$tet->get_apiname() . "(): " . $tet->get_errmsg() . "\n");
	    next;                        # try next page
	}

	# print UTF-8 BOM
	fprintf($outfp, "%c%c%c\n", 0xef, 0xbb, 0xbf);

	# Administrative information
	fprintf($outfp, "[ Document: '%s' ]\n",
		$tet->pcos_get_string($doc, "filename"));

	fprintf($outfp, "[ Document options: '%s' ]\n", $docoptlist);

	fprintf($outfp, "[ Page options: '%s' ]\n", $pageoptlist);

	fprintf($outfp, "[ ----- Page %d ----- ]\n", $pageno);


	# Retrieve all text fragments
	while (($text = $tet->get_text($page)) != "")
	{
	    fprintf($outfp, "[%s]\n", $text);  # print the retrieved text


	    # Loop over all glyphs and print their details
	    while ($ci = $tet->get_char_info($page))
	    {
		# Fetch the font name with pCOS (based on its ID)
		$fontname = $tet->pcos_get_string($doc,
			"fonts[" . $ci->{"fontid"} . "]/name");


		# Print the character
		fprintf($outfp, "U+%04X", $ci->{"uv"});

		# ...and its ASCII representation if appropriate
		if ($ci->{"uv"} >= 0x20 && $ci->{"uv"} <= 0x7F) {
		    fprintf($outfp, " '%c'", $ci->{"uv"});
		}

		# Print font name, size, and position
		fprintf($outfp, " %s size=%.2f x=%.2f y=%.2f",
		    $fontname, $ci->{"fontsize"}, $ci->{"x"}, $ci->{"y"});

		# Examine the "type" member
		if ($ci->{"type"} == TET_CT_SEQ_START) {
		    fprintf($outfp, " ligature_start");
		}
		elseif ($ci->{"type"} == TET_CT_SEQ_CONT) {
		    fprintf($outfp, " ligature_cont");
		}

		# Separators are only inserted for granularity > word
		elseif ($ci->{"type"} == TET_CT_INSERTED) {
		    fprintf($outfp, " inserted");
		}

		# Examine the bit flags in the "attributes" member
		if ($ci->{"attributes"} != TET_ATTR_NONE)
		{
		    if ($ci->{"attributes"} & TET_ATTR_SUB) {
			fprintf($outfp, "/sub");
		    }
		    if ($ci->{"attributes"} & TET_ATTR_SUP) {
			fprintf($outfp, "/sup");
		    }
		    if ($ci->{"attributes"} & TET_ATTR_DROPCAP) {
			fprintf($outfp, "/dropcap");
		    }
		    if ($ci->{"attributes"} & TET_ATTR_SHADOW) {
			fprintf($outfp, "/shadow");
		    }
		    if ($ci->{"attributes"} & TET_ATTR_DEHYPHENATION_PRE) {
			fprintf($outfp, "/dehyphenation_pre");
		    }
		    if ($ci->{"attributes"} & TET_ATTR_DEHYPHENATION_ARTIFACT) {
			fprintf($outfp, "/dehyphenation_artifact");
		    }
		    if ($ci->{"attributes"} & TET_ATTR_DEHYPHENATION_POST) {
			fprintf($outfp, "/dehyphenation_post");
		    }
		}

		fprintf($outfp, "\n");
	    }

	    fprintf($outfp, "\n");
	}
	if ($tet->get_errnum() != 0) {
	    print("Error ". $tet->get_errnum() . " in " . 
		    $tet->get_apiname() . "(): on page $pageno" 
		    . $tet->get_errmsg() . "\n");
	}

	$tet->close_page($page);
    }

    fclose($outfp);

    $tet->close_document($doc);
}
catch (TETException $e) {
    if ($pageno == 0) {
	die("TET exception occurred in extractor sample:\n" .
	    "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " .
	    $e->get_errmsg() . "\n");
    } else {
	die("TET exception occurred in extractor sample:\n" .
	    "[" . $e->get_errnum() . "] " . $e->get_apiname() .
	    "on page $pageno: " .  $e->get_errmsg() . "\n");
    }
}
catch (Exception $e) {
    die($e);
}

$tet = 0;
?>
