fontservices/textbase/mglyph/mglyphtool.pl
changeset 45 662fa7de7023
equal deleted inserted replaced
41:ea44a32a96bc 45:662fa7de7023
       
     1 # Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 #
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 #
       
    11 # Contributors:
       
    12 #
       
    13 # Description:
       
    14 #
       
    15 
       
    16 use strict;
       
    17 
       
    18 ## Used as global variables, probably need to change and pass variables through as parameters.
       
    19 my %globalValues=();
       
    20 ##initialise filenames
       
    21 $globalValues{'inputFile'} = 'mglyphs.txt';
       
    22 $globalValues{'outputFileName'} = 'mglyphs.inl';
       
    23 $globalValues{'htmlFileName'} = 'mglyphs.html';
       
    24 $globalValues{'lgtablesize'} = 9; # Default tablesize value is 512
       
    25 $globalValues{'tablesize'} = 1 << $globalValues{'lgtablesize'};
       
    26 $globalValues{'storeashex'} = 0;
       
    27 $globalValues{'stepOffset'} = 72;
       
    28 $globalValues{'stepShift'} = 0;
       
    29 
       
    30 ## die if the correct number of argumements have not been entered
       
    31 &extractFlags(\@ARGV, \%globalValues);
       
    32 &printDebug("Remainder:$globalValues{'tablesize'}\n");
       
    33 &printDebug("StoreAsHex:$globalValues{'storeashex'}\n");
       
    34 
       
    35 if ($globalValues{"information"})
       
    36 	{
       
    37 	&dieShowingUsage();
       
    38 	}
       
    39 
       
    40 &printDebug("Creating HashTable....\n");
       
    41 my %hashTable = &createHashTable($globalValues{'inputFile'});
       
    42 if (!defined(%hashTable))
       
    43 	{
       
    44 	die("ERROR: Hash table was not created\n");
       
    45 	}
       
    46 if ($globalValues{"outputtohtml"})
       
    47 	{
       
    48 	my $htmlFileName = $globalValues{'htmlFileName'};
       
    49 	&printDebug("Creating HTML output to file: $htmlFileName\n");	
       
    50 	&createHTMLOfMappings($htmlFileName, %hashTable);
       
    51 	}
       
    52 my $outputFileName = $globalValues{'outputFileName'};
       
    53 &printDebug("Writing Hash table to file: $outputFileName\n");
       
    54 &writeHashTableToFile($outputFileName, %hashTable);
       
    55 &printDebug("$outputFileName created.");
       
    56 
       
    57 ##################### end of main section 
       
    58 sub extractFlags
       
    59 	{
       
    60 	my $aArgumentArray=shift;
       
    61 	my $aArguments=shift;
       
    62 	my $expectedArg = 'lgtablesize';
       
    63 	my $expectedExtension;
       
    64 	foreach my $argument (@$aArgumentArray)
       
    65 		{
       
    66 		if ($argument =~ m!^[-/]([a-zA-Z].*)$!)
       
    67 			{
       
    68 			my $switch = $1;
       
    69 			$expectedArg = 'lgtablesize';
       
    70 			$expectedExtension = undef;
       
    71 			if ($switch=~/^(x|hexoutput)$/i)
       
    72 				{
       
    73 				$$aArguments{'storeashex'}=1;
       
    74 				}
       
    75 			elsif ($switch=~/^(\?|help)$/i)
       
    76 				{
       
    77 				$$aArguments{'information'}=1;
       
    78 				}
       
    79 			elsif ($switch=~/^(v|verbose)$/i)
       
    80 				{
       
    81 				$$aArguments{'verbose'}=1;
       
    82 				}
       
    83 			elsif ($switch=~/^(h|outputtohtml)$/i)
       
    84 				{
       
    85 				$$aArguments{'outputtohtml'}=1;
       
    86 				$expectedArg = 'htmlFileName';
       
    87 				$expectedExtension = '.html';
       
    88 				}
       
    89 			elsif ($switch=~/^(i|input)$/i)
       
    90 				{
       
    91 				$expectedArg = 'inputFile';
       
    92 				}
       
    93 			elsif ($switch=~/^(o|output)$/i)
       
    94 				{
       
    95 				$expectedArg = 'outputFileName';
       
    96 				$expectedExtension = '.inl';
       
    97 				}
       
    98 			elsif ($switch=~/^(offset)$/i)
       
    99 				{
       
   100 				$expectedArg = 'stepOffset';
       
   101 				}
       
   102 			elsif ($switch=~/^(shift)$/i)
       
   103 				{
       
   104 				$expectedArg = 'stepShift';
       
   105 				}
       
   106 			}
       
   107 		else
       
   108 			{
       
   109 			if (defined $expectedExtension && $argument !~ m!\.[^/\\]*$!)
       
   110 				{
       
   111 				$argument .= $expectedExtension;
       
   112 				}
       
   113 			$$aArguments{$expectedArg} = $argument;
       
   114 			$expectedArg = 'lgtablesize';
       
   115 			}
       
   116 		}
       
   117 	$globalValues{'tablesize'} = 1 << $globalValues{'lgtablesize'};
       
   118 	$globalValues{'stepOffset'} &= 0xFFFFFE;
       
   119 	}
       
   120 #####################
       
   121 sub dieShowingUsage
       
   122 	{
       
   123 	print <<USAGE_EOF;
       
   124 
       
   125 Usage:
       
   126 
       
   127 perl -w mglyphtool.pl [-?] [<lg-table-size>] [-x] [-i <input-file-name>]
       
   128 		[-o <output-file-name>] [-h [<output-html-file-name]]
       
   129 		[-offset <value-for-offset>] [-shift <value-for-shift>]
       
   130 
       
   131 <lg-table-size> the default log(base 2) table size is 9. This gives a table
       
   132 size of 512 entries (2 to the power 9). So 7 gives a size of 128, 8 gives
       
   133 256, 9 gives 512, 10 gives 1024 and so on.
       
   134 
       
   135 options: -x -o -i -h
       
   136 
       
   137 	-? Shows help
       
   138 
       
   139 	The -x flag stores values into the .inl file in hex format: 
       
   140 		hex(OriginalKeyCodeMirrorGlyphCode), 
       
   141 	By default the values are stored in string hex format i.e 0x220C2209
       
   142 
       
   143 	The -h flag generates a html file displaying hash table information.
       
   144 	This may be followed by the filename to be output.
       
   145 	Default is 'mglyphs.html'
       
   146 
       
   147 	The -i file specifies input file name. Default is 'mglyphs.txt'.
       
   148 
       
   149 	The -o file specifies output file name. Default is 'mglyphs.inl'.
       
   150 
       
   151 	-shift and -offset alter the "step" hash algorithm.
       
   152 	
       
   153 USAGE_EOF
       
   154 	exit 0;
       
   155 	}
       
   156 ######### 
       
   157 #
       
   158 # Writes a hash table to file.
       
   159 # Current format:
       
   160 # 	Hex mode: 		"hex number created"
       
   161 #	Hex string mode:	"Original keyMapped key"
       
   162 #####################
       
   163 sub writeHashTableToFile
       
   164 	{
       
   165 	&printDebug("Writing to .inl file");
       
   166 	my ($aOutputFileName, %aHashTable) = @_;
       
   167 	open(OUTPUT_FILE, '> ' . $aOutputFileName) or die('Error: could not open $aOutputFileName to write to\n');
       
   168 	## Print comments at top of .inl file
       
   169 	printf(OUTPUT_FILE "\/\/ mGlyphs.inl\n");
       
   170 	printf(OUTPUT_FILE "\/\/\n");
       
   171 	printf(OUTPUT_FILE "\/\/ Generated by mglyphtool.pl from '$globalValues{'inputFile'}'\n");
       
   172 	printf(OUTPUT_FILE "\/\/\n\n");
       
   173 	## Declare array and fill in values
       
   174 	printf(OUTPUT_FILE "const unsigned long mGlyphArray[] = {\n\t");
       
   175 	for (my $counter = 0; $counter < $globalValues{'tablesize'}; $counter++)
       
   176 		{
       
   177 		my $storeValue = "00000000";
       
   178 		if (defined($aHashTable{$counter}))
       
   179 			{
       
   180 			$storeValue = $aHashTable{$counter};
       
   181 			}
       
   182 		$storeValue = ($globalValues{'storeashex'}) ? hex($storeValue) : "0x$storeValue";
       
   183 		print OUTPUT_FILE $storeValue;
       
   184 		if (($counter+1) < $globalValues{'tablesize'})
       
   185 			{
       
   186 			print OUTPUT_FILE (($counter + 1) % 8 == 0? ",\n\t" : ', ');
       
   187 			}
       
   188 		}
       
   189 	print(OUTPUT_FILE "};\n");
       
   190 	print(OUTPUT_FILE "\nconst int KLgMirrorTableSize=$globalValues{'lgtablesize'};\n");
       
   191 	print(OUTPUT_FILE "const int KMirrorTableSize=$globalValues{'tablesize'};\n");
       
   192 	# Inline functions
       
   193 	# Get a Hash value from a given key	
       
   194 	print(OUTPUT_FILE "\n// Returns the first index to probe for character aKey.\n");
       
   195 	print(OUTPUT_FILE "inline long MirrorStart(long aKey)\n");
       
   196 	print(OUTPUT_FILE "\t{ return aKey \& (KMirrorTableSize-1); }\n");
       
   197 	print(OUTPUT_FILE "\n// Returns the offset for further probes for character aKey.\n");
       
   198 	print(OUTPUT_FILE "inline long MirrorStep(long aKey)\n");
       
   199 	my $stepShift = $globalValues{'stepShift'};
       
   200 	print(OUTPUT_FILE "\t{ return (");
       
   201 	if ($stepShift == 0)
       
   202 		{
       
   203 		print(OUTPUT_FILE "aKey");
       
   204 		}
       
   205 	elsif (0 < $stepShift)
       
   206 		{
       
   207 		print(OUTPUT_FILE "(aKey >> $stepShift)");
       
   208 		}
       
   209 	else
       
   210 		{
       
   211 		$stepShift = -$stepShift;
       
   212 		print(OUTPUT_FILE "(aKey << $stepShift)");
       
   213 		}
       
   214 	print(OUTPUT_FILE " | 1) + $globalValues{'stepOffset'}; }\n\n");
       
   215 
       
   216 	close(OUTPUT_FILE);
       
   217 	}	
       
   218 ##################### listing of hash indexes values for original and mirrored glyphs
       
   219 sub createHTMLOfMappings
       
   220 	{
       
   221 	my ($aOutputFileName, %aHashTable )= @_;
       
   222 	open(OUTPUT_FILE, '> ' . $aOutputFileName) or die('Error: could not open $aOutputFileName to create HTML output');
       
   223 	printf(OUTPUT_FILE "<HTML><HEAD><TITLE>MirrorGlyph Hash Output<\/TITLE><\/HEAD><BODY>");
       
   224 ## print hash table details
       
   225 	printf(OUTPUT_FILE "<P>Values in hash Table - <B>(Hash Function: Key mod $globalValues{'tablesize'})<\/B><\/P><TABLE border=1>");
       
   226 	printf(OUTPUT_FILE "<TR><TD><B>---<\/B><\/TD><TD BGCOLOR=\#8888FF><B>Character code:<\/B><\/TD><TD><B>Hash Index:<\/B><\/TD><TD BGCOLOR=\#8888FF><B>Mirror Glyph Value:<\/B><\/TD><TD><b>Search Jump Count<\/b>");	
       
   227 	my %keySet;
       
   228 	foreach my $value (values %aHashTable)
       
   229 		{
       
   230 		$keySet{&getLower(hex $value)} = 1;
       
   231 		}
       
   232 	foreach my $key (32..127)
       
   233 		{
       
   234 		$keySet{$key} = 1;
       
   235 		}
       
   236 	my @keys = sort {$a <=> $b} (keys %keySet);
       
   237 	foreach my $key (@keys)
       
   238 		{
       
   239 		my $counter = 0;
       
   240 		my $HKey = &findHashTableIndex($key, \$counter, \%aHashTable);
       
   241 		my $stored = $aHashTable{$HKey};
       
   242 		my $storedValue = 'no change';
       
   243 		my $storedKey = $key;
       
   244 		if (defined $stored)
       
   245 			{
       
   246 			$storedValue = sprintf('%02x', &getLower(hex $stored));
       
   247 			$storedKey = &getUpper(hex $stored);
       
   248 			}
       
   249 		if ($storedKey)
       
   250 			{
       
   251 			die('incorrect key found in hash table') unless ($storedKey == $key);
       
   252 			printf(OUTPUT_FILE "<TR><TD>---<\/TD><TD BGCOLOR=\#8888FF><B>%02x<\/B><\/TD><TD>%02x<\/TD><TD BGCOLOR=\#8888FF><B>%s<\/B><\/TD><TD>%d<\/TD><\/TR>", $key, $HKey, $storedValue, $counter);
       
   253 			}
       
   254 		}
       
   255 	printf(OUTPUT_FILE "<\/TABLE>");
       
   256 	printf(OUTPUT_FILE "<\/BODY><\/HTML>");
       
   257 	close(OUTPUT_FILE);
       
   258 	}
       
   259 #####################
       
   260 # Hash Table functions	
       
   261 ##################### 
       
   262 
       
   263 #####################
       
   264 #Returns a new Hash Table 
       
   265 #####################
       
   266 sub createHashTable
       
   267 	{	
       
   268 	my $aInputFileName = shift;	
       
   269 	my $lineNumber = 1;
       
   270 	my %newHashTable = ();
       
   271 	open(INPUT_FILE, '< ' . $aInputFileName) or die('ERROR: Could not open $aInputFileName to read from');
       
   272 	while (my $line=<INPUT_FILE>)
       
   273 		{
       
   274 		if ($line=~/^(.*);\s(.*\w)\s\W.*$/) ## Grab Original glyph value and mirrored glyph value
       
   275 			{		
       
   276 			&updateHashTable($1, $2, \%newHashTable);
       
   277 			}
       
   278 		$lineNumber++;
       
   279 		}		
       
   280 	close(INPUT_FILE);
       
   281 	return %newHashTable;
       
   282 	}
       
   283 ##################### 
       
   284 #
       
   285 # Retrieves a HashKey which is not currently being used in a given HashTable
       
   286 #
       
   287 #####################
       
   288 sub findHashTableIndex
       
   289 	{
       
   290 	my ($aHashKey, $aCounter, $aHashTable) = @_;	
       
   291 	my $current = &hashFunction($aHashKey);
       
   292 	my $step = &hashStepFunction($aHashKey);
       
   293 	my $tableSize = $globalValues{'tablesize'};
       
   294 	while (defined($$aHashTable{$current}) && &getUpper(hex($$aHashTable{$current})) != $aHashKey)
       
   295 		{
       
   296 		++$$aCounter;
       
   297 		$current += $step;
       
   298 		$current &= $tableSize - 1;
       
   299 		}
       
   300 	if (2 < $$aCounter)
       
   301 		{
       
   302 		printf STDERR ("WARNING: Jumped $$aCounter times, inefficient hash for %02x ($current, $step)\n", $aHashKey);
       
   303 		}
       
   304 	return $current;
       
   305 	}
       
   306 
       
   307 #####################
       
   308 sub updateHashTable
       
   309 {
       
   310 	my ($aKey, $aValueToStore, $aHashTable) = @_;
       
   311 	my $counter = 0;
       
   312 	my $key = hex($aKey);
       
   313 	my $hashKey = &findHashTableIndex($key, \$counter, $aHashTable);
       
   314 	$$aHashTable{$hashKey} = "$aKey$aValueToStore";
       
   315 	return $hashKey;
       
   316 }
       
   317 ##################### 
       
   318 # Returns a hash key for a given key
       
   319 # Currently using a simple hash function 
       
   320 #####################
       
   321 sub hashFunction
       
   322 	{
       
   323 	my $aKey = shift;
       
   324 	return $aKey & ($globalValues{'tablesize'}-1);
       
   325 	}
       
   326 
       
   327 # Returns second hash value: used for the step size
       
   328 sub hashStepFunction
       
   329 	{
       
   330 	my $aKey = shift;
       
   331 	my $stepShift = $globalValues{'stepShift'};
       
   332 	if ($stepShift < 0)
       
   333 		{
       
   334 		$aKey <<= -$stepShift;
       
   335 		}
       
   336 	elsif (0 < $stepShift)
       
   337 		{
       
   338 		$aKey >>= $stepShift;
       
   339 		}
       
   340 	return ($aKey | 1) + $globalValues{'stepOffset'};
       
   341 	}
       
   342 	
       
   343 #####################
       
   344 # Utility functions 
       
   345 #####################
       
   346 sub getLower
       
   347 	{
       
   348 	my $aValue = shift;
       
   349 	return $aValue & hex("0000FFFF");
       
   350 	}
       
   351 sub getUpper
       
   352 	{
       
   353 	my $aValue = shift;
       
   354 	return ($aValue & hex("FFFF0000")) >> 16;				
       
   355 	}
       
   356 sub printDebug
       
   357 	{
       
   358 	my $string = shift;
       
   359 	if ($globalValues{'verbose'})
       
   360 		{
       
   361 		print $string;
       
   362 		}
       
   363 	}
       
   364