<?php

/*******************************************************************************

 WINBINDER - The native Windows binding for PHP for PHP

 Copyright © Hypervisual - see LICENSE.TXT for details
 Author: Rubem Pechansky (http://winbinder.org/contact.php)

 Code sample: TrueType data reader application

*******************************************************************************/

//------------------------------------------------------------ SYSTEM PARAMETERS

define("PATH_SCRIPT",	dirname(__FILE__) . "/");
define("PATH_DATA",		PATH_SCRIPT);
define("PATH_INC",		PATH_SCRIPT . "../include/");
define("PATH_RES",		PATH_SCRIPT . "../resources/");

//----------------------------------------------------------------- DEPENDENCIES

include PATH_INC . "winbinder.php";

//-------------------------------------------------------------------- CONSTANTS

define("APPNAME",			"TrueType Data Reader");
define("VERSION",			"0.17");

// Identifiers for main window

define("ID_ABOUT", 		1001);
define("ID_CLEAR", 		1002);
define("ID_OPEN", 		1003);
define("ID_SELECT",		1004);
define("ID_WEBSITE",	1006);
define("ID_VENDORID",	1051);
define("ID_FONTNAME",	1052);
define("ID_FAMILY",		1053);
define("ID_SUBFAMILY",	1054);
define("ID_PSNAME",		1055);
define("ID_UNIQUEID",	1056);
define("ID_COPYRIGHT",	1057);
define("ID_TRADEMARK",	1058);
define("ID_VERSION",	1059);
define("ID_WEIGHT",		1060);

// Control identifiers for Select Font dialog

define("ID_SYSFONT",	2001);

//-------------------------------------------------------------- EXECUTABLE CODE

create_main_window();
wb_main_loop();

//-------------------------------------------------------- MAIN WINDOW FUNCTIONS

/* Create main window */

function create_main_window()
{
	global $mainwin, $toolbar, $mainmenu;

	// Create main window (invisible) and controls

	$mainwin = wb_create_window(NULL, AppWindow, "TTF Data", WBC_CENTER, WBC_CENTER, 475, 370, WBC_INVISIBLE);

	// Insert controls

	wb_create_control($mainwin, Frame, "", -1, 29, 524, 3, 0, 0);

	wb_create_control($mainwin, Frame, "Font data", 10, 42, 449, 144, 0, 0);
	wb_create_control($mainwin, Label, "Full font name:", 13, 66, 94, 21, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 119, 63, 325, 21, ID_FONTNAME, WBC_READONLY);
	wb_create_control($mainwin, Label, "Family / weight:", 13, 95, 94, 16, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 119, 92, 160, 21, ID_FAMILY, WBC_READONLY);
	wb_create_control($mainwin, EditBox, "", 286, 92, 65, 21, ID_SUBFAMILY, WBC_READONLY);
	wb_create_control($mainwin, EditBox, "", 356, 92, 88, 21, ID_WEIGHT, WBC_READONLY);
	wb_create_control($mainwin, Label, "PostScript name:", 17, 125, 91, 21, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 119, 123, 325, 21, ID_PSNAME, WBC_READONLY);
	wb_create_control($mainwin, Label, "Unique font ID:", 17, 154, 91, 21, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 119, 152, 325, 21, ID_UNIQUEID, WBC_READONLY);

	wb_create_control($mainwin, Frame, "Identifiers and legal information", 10, 195, 449, 120, 0, WBC_ENABLED);
	wb_create_control($mainwin, Label, "Vendor ID:", 16, 222, 94, 19, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 119, 219, 106, 21, ID_VENDORID, WBC_READONLY);
	wb_create_control($mainwin, Label, "Version:", 235, 222, 67, 19, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 305, 219, 139, 21, ID_VERSION, WBC_READONLY);
	wb_create_control($mainwin, Label, "Copyright:", 16, 251, 92, 16, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 119, 250, 325, 21, ID_COPYRIGHT, WBC_READONLY);
	wb_create_control($mainwin, Label, "Trademark:", 16, 281, 92, 16, 0, WBC_RIGHT);
	wb_create_control($mainwin, EditBox, "", 119, 279, 325, 21, ID_TRADEMARK, WBC_READONLY);

	// Create main menu

	$mainmenu = wb_create_control($mainwin, Menu, array(
	"&Font",
		array(ID_OPEN,		"&Open Font File...\tCtrl+O", "", PATH_RES . "menu_open.bmp", "Ctrl+O"),
		array(ID_SELECT,	"Select Installed &Font...\tCtrl+F", "", "", "Ctrl+F"),
		null,
		array(ID_CLEAR,		"&Clear Data\tCtrl+Del", "", "", "Ctrl+Del"),
		null,
		array(IDCLOSE,		"E&xit\tAlt+F4", "", PATH_RES . "menu_exit.bmp"),

	"&Help",
		array(ID_WEBSITE,	"&Web site"),
		null,
		array(ID_ABOUT,		"&About...", "", PATH_RES . "menu_help.bmp"),

	), $mainwin);

	// Create toolbar

	$toolbar = wb_create_control($mainwin, ToolBar, array(
		null,
	  	array(ID_OPEN,		NULL, "Open Font File (Ctrl+O)",		1),
	  	array(ID_SELECT,	NULL, "Select Installed Font (Ctrl+F)",	5),
	  	array(ID_CLEAR,		NULL, "Clear Data",						12),
		null,
	  	array(ID_WEBSITE,	NULL, "Go to the WinBinder web site", 	11),
	), 0, 0, 16, 15, 0, 0, PATH_RES . "toolbar.bmp");

	clear_screen($mainwin);

	// Show window

	wb_set_image($mainwin, PATH_RES . "ttf.ico");
	wb_set_handler($mainwin, "process_main");
	wb_set_text($mainwin, APPNAME);
	wb_set_visible($mainwin, true);
}

/* Main window handler */

function process_main($window, $id)
{
	static $font_mask = array(
		array("TrueType Fonts",		"*.ttf"),
		array("All files",			"*.*")
	);

	switch($id) {

		case ID_CLEAR:
			clear_screen($window);
			break;

		case ID_OPEN:
			$file = wb_sys_dlg_open($window, "Open Font File", $font_mask);
			if($file)
				get_ttf_values($file);
			break;

		case ID_SELECT:
			create_select_dlg($window);
			break;

		case ID_WEBSITE:
			if(!wb_exec("http://winbinder.org/"))
				wb_message_box($window, "Problem opening web site.");
			break;

		case ID_ABOUT:
			wb_message_box($window,
				"WinBinder version " . WBC_VERSION . "\nPHP version " . PHP_VERSION .  "\n" . wb_get_system_info("osversion"),
				"About " . APPNAME . " v. " . VERSION);
			break;

		case IDCLOSE:
			wb_destroy_window($window);
			break;
	}
}

/* Clear data fields */

function clear_screen($window)
{
	global $toolbar, $mainmenu;

	$controls = array(ID_WEIGHT, ID_VENDORID, ID_FONTNAME, ID_FAMILY, ID_SUBFAMILY,
		ID_UNIQUEID, ID_PSNAME, ID_COPYRIGHT, ID_VERSION, ID_TRADEMARK);

	foreach($controls as $id)
		wb_set_text(wb_get_control($window, $id), "");

	// Enable controls

	wb_set_enabled(wb_get_control($toolbar, ID_CLEAR), false);
	wb_set_enabled(wb_get_control($mainmenu, ID_CLEAR), false);

	// Reset title bar string

	wb_set_text($window, APPNAME);
}

//------------------------------------------------- FONT SELECT DIALOG FUNCTIONS

// Create the Select Font dialog

function create_select_dlg($parent)
{
	global $filedir;

	// Create window

	$seldlg = wb_create_window($parent, ModalDialog, "Select a font file", WBC_CENTER, WBC_CENTER, 211, 232, WBC_INVISIBLE | WBC_NOTIFY, WBC_DBLCLICK);

	// Insert controls

	wb_create_control($seldlg, ListBox,	   "",         4,  19, 200, 160, ID_SYSFONT);
	wb_create_control($seldlg, PushButton, "OK",      22, 175,  70,  26, IDOK);
	wb_create_control($seldlg, PushButton, "Cancel", 109, 175,  70,  26, IDCANCEL);

	// Fill up listbox with the list of installed font files

	$listctrl = wb_get_control($seldlg, ID_SYSFONT);
	$filedir = wb_get_system_info("fontpath");
	$files = get_folder_files($filedir, false, false, "/.*\.ttf/i");
	sort($files);
	wb_set_text($listctrl, $files);

	// Show dialog

	wb_set_handler($seldlg, "process_select_dlg");
	wb_set_focus($listctrl);
	wb_set_enabled(wb_get_control($seldlg, IDOK), false);
	wb_set_visible($seldlg, true);
}

// Window handler

function process_select_dlg($window, $id, $ctrl=0, $lparam=0)
{
	global $filedir;

	switch($id) {

		case ID_SYSFONT:
			if($lparam != WBC_DBLCLICK) {
				wb_set_enabled(wb_get_control($window, IDOK), true);
				return true;
			}
			// Fall-through

		case IDOK:
			$font = wb_get_text(wb_get_control($window, ID_SYSFONT));
			if($font)
				get_ttf_values($filedir . $font);

			// Fall-through

		case IDCANCEL:
			wb_destroy_window($window);
			return true;

	}
	return false;
}

//------------------------------------------------------ TRUETYPE DATA FUNCTIONS

/* Read TTF values from file $fontfile and fill out data fields */

function get_ttf_values($fontfile)
{
	global $mainwin, $toolbar, $mainmenu;

	static $weights = array(
		"Don't care" =>	0,
		"Thin"=>		100,
		"Extra Light"=>	200,
		"Light"=>		300,
		"Normal"=>		400,
		"Medium"=>		500,
		"Demi Bold"=>	600,
		"Bold"=>		700,
		"Extra Bold"=>	800,
		"Black"=>		900,
	);

	static $stringnames = array(
		"COPYRIGHT",
		"FACENAME",
		"SUBFAMILY",
		"UNIQUEFONTID",
		"FAMILY",
		"VERSION",
		"PSNAME",
		"TRADEMARK",
		"UC_COPYRIGHT",
		"UC_FAMILY",
		"UC_SUBFAMILY",
		"UC_UNIQUEFONTID",
		"UC_FACENAME",
		"UC_VERSION",
		"UC_PSNAME",
		"UC_TRADEMARK"
	);

	//---------------------------------------- Open TTF file

	$fh = fopen($fontfile, "rb");
	if(!$fh) {
		wb_message_box($mainwin, "Cannot open file $fontfile.");
		return;
	}

	//---------------------------------------- Read file and header data

	fseek($fh, 0);
	$data = fread($fh, 12);
	$ttf_head = unpack("nsfntVersion" , $data);
	if($ttf_head["sfntVersion"] != 1) {
		wb_message_box($mainwin, "The file $fontfile does not seem to be a TrueType font.");
		return;
	}

	//---------------------------------------- Read the offsets

	fseek($fh, 0);
	$data = fread($fh, 1024);
	$os2pos = strpos($data, "OS/2");
	$namepos = strpos($data, "name");
	$cmappos = strpos($data, "cmap");

	//---------------------------------------- Read "name" data

	fseek($fh, $namepos);
	$data = fread($fh, 16);
	$ttf_name = unpack("a4/N/Noffset", $data);
	fseek($fh, $ttf_name["offset"]);
	$data = fread($fh, 6);
	$ttf_name = unpack("n/ncount/nstringoffset", $data);
	$strstart = ftell($fh) - 6 + $ttf_name["stringoffset"];

	//---------------------------------------- Names loop

	$names = min($ttf_name["count"], 16);
	for($i = 0; $i < $names; $i++) {
		$data = fread($fh, 12);
		$fpos = ftell($fh);
		$ttf_name = unpack("n4/nLengthID/nOffsetID", $data);
		$len = $ttf_name["LengthID"];
		if($len) {
			fseek($fh, $strstart + $ttf_name["OffsetID"]);
			$data = fread($fh, $len);
			fseek($fh, $fpos);
			$name = unpack("a" . $len . "Data", $data);
			$ttf_strings[$stringnames[$i]] = unicode2ansi($name["Data"]);
		} else {
			$ttf_strings[$stringnames[$i]] = "";
		}
	}

	//---------------------------------------- Read "os2" data

	fseek($fh, $os2pos);
	$data = fread($fh, 16);
	$ttf_os2 = unpack("a4id/N/Noffset/Nlength", $data);
	fseek($fh, $ttf_os2["offset"]);
	$data = fread($fh, $ttf_os2["length"]);
	$ttf_os2 = unpack("n2/nusWeightClass/n26/a4achVendID", $data);

	//---------------------------------------- End data read

	fclose($fh);

	//---------------------------------------- Fiil out controls with values

	// OS/2 data

	wb_set_text(wb_get_control($mainwin, ID_WEIGHT),	array_search($ttf_os2["usWeightClass"], $weights));
	wb_set_text(wb_get_control($mainwin, ID_VENDORID),	$ttf_os2["achVendID"]);

	// Strings

	wb_set_text(wb_get_control($mainwin, ID_FONTNAME),	$ttf_strings["FACENAME"]);
	wb_set_text(wb_get_control($mainwin, ID_FAMILY),	@$ttf_strings["FAMILY"]);
	wb_set_text(wb_get_control($mainwin, ID_SUBFAMILY),	@$ttf_strings["SUBFAMILY"]);
	wb_set_text(wb_get_control($mainwin, ID_UNIQUEID),	@$ttf_strings["UNIQUEFONTID"]);
	wb_set_text(wb_get_control($mainwin, ID_PSNAME),	@$ttf_strings["PSNAME"]);
	wb_set_text(wb_get_control($mainwin, ID_COPYRIGHT),	@$ttf_strings["COPYRIGHT"]);
	wb_set_text(wb_get_control($mainwin, ID_VERSION),	@$ttf_strings["VERSION"]);
	wb_set_text(wb_get_control($mainwin, ID_TRADEMARK),	@$ttf_strings["TRADEMARK"]);

	// Enable controls

	wb_set_enabled(wb_get_control($toolbar, ID_CLEAR), true);
	wb_set_enabled(wb_get_control($mainmenu, ID_CLEAR), true);

	// Set title bar with font name

	wb_set_text($mainwin, basename($fontfile) . " - " . APPNAME);
}

//---------------------------------------------------- GENERAL-PURPOSE FUNCTIONS

// utf8_decode dos not work for TrueType fonts

function unicode2ansi($string)
{
	$string = (string)$string;

	if(!is_string($string))
		return $string;

	// Is it an empty string?

	if(strlen($string) == 0)
		return $string;

	// Is it Unicode?

	if(ord($string[0]) != 0)
		return $string;

	// Do the conversion

	$len = strlen($string);
	$out = "";

	for($i = 0; $i < $len; $i += 2) {
		if(ord($string[$i]) == 0 && ord($string[$i + 1]) != 0)
			$out .= $string[$i + 1];
	}
	return $out;
}

//-------------------------------------------------------------------------- END

?>