|
Server : Apache/2.4.62 System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64 User : www ( 80) PHP Version : 8.3.8 Disable Function : NONE Directory : /domains/mandarintools/download/ |
Upload File : |
package HBF;
require Exporter;
use subs qw(loadFont getChar);
BEGIN { }
sub new {
return bless {};
}
sub loadFont {
my($self) = shift;
my $fontname = shift;
if ($fontname !~ /\.hbf/i) {
$fontname .= ".hbf";
}
if (-e $fontname) {
# $fontname works as is
$self->{'LOADPATH'} = ".";
} else {
if (defined($ENV{'HBFPATH'})) {
my $splitchar;
if ($ENV{'HBFPATH'} =~ m/\//) {
$splitchar = ":";
} else {
$splitchar = ";";
}
@hbfpaths = split(/$splitchar/, $ENV{'HBFPATH'});
foreach $hbfpath (@hbfpaths) {
if (-e $hbfpath . "/" . $fontname) {
$fontname = $hbfpath . "/" . $fontname;
$self->{'LOADPATH'} = $hbfpath;
$foundhbf = 1;
last;
}
}
if ($foundhbf != 1) {
print STDERR "Unable to open HBF file $fontname.\n";
return 0;
}
} else {
print STDERR "Unable to open HBF file $fontname.\n";
return 0;
}
}
$self->{'fontname'} = $fontname;
open(FD, $fontname);
while (<FD>) {
chomp;
if (m/^HBF_START_FONT/) {
my($desc, $format) = split(/\s+/, $_, 2);
$self->{'HBF_START_FONT'} = $format;
} elsif (m/^HBF_CODE_SCHEME/) {
my($desc, $format) = split(/\s+/, $_, 2);
$self->{'HBF_CODE_SCHEME'} = $format;
} elsif (m/^FONT/) {
my($desc, $format) = split(/\s+/, $_, 2);
$self->{'FONT'} = $format;
} elsif (m/^SIZE/) {
my($desc, $format) = split(/\s+/, $_, 2);
$self->{'SIZE'} = $format;
} elsif (m/^HBF_BITMAP_BOUNDING_BOX/) {
my($desc, $format) = split(/\s+/, $_, 2);
$self->{'HBF_BITMAP_BOUNDING_BOX'} = $format;
($self->{'width'}, $self->{'height'}, $self->{'xd'}, $self->{'yd'}) =
split(/\s+/, $format);
$self->{'bytes'} = $self->{'height'} * int(($self->{'width'} + 7) / 8)
} elsif (m/^FONTBOUDINGBOX/) {
my($desc, $format) = split(/\s+/, $_, 2);
$self->{'FONTBOUNDINGBOX'} = $format;
} elsif (m/^STARTPROPERTIES/) {
my($desc, $total) = split(/\s+/, $_, 2);
my($line);
for ($i = 0; $i < $total and $desc ne "ENDPROPERTIES"; $i++) {
chomp($line = <FD>);
($desc, $format) = split(/\s+/, $line, 2);
if ($desc eq "COMMENT")
{
$i--;
}
else
{
$self->{"$desc"} = $format;
}
}
} elsif (m/^CHARS/) {
my($desc, $format) = split(/\s+/, $_, 2);
$self->{'CHARS'} = $format;
} elsif (m/^HBF_START_BYTE_2_RANGES/) {
my($desc, $total) = split(/\s+/, $_, 2);
$self->{'HBF_BYTE_2_RANGES'} = $total;
$self->{'HBF_BYTE_2_RANGE'} = [];
my($line);
for ($i = 0; $i < $total and $desc ne 'HBF_END_BYTE_2_RANGES'; $i++) {
chomp($line = <FD>);
my($desc, $content) = split(/\s+/, $line, 2);
my($start, $end) = split(/\-/, $content);
${$self->{'HBF_BYTE_2_RANGE'}}[$i][0] = $start;
${$self->{'HBF_BYTE_2_RANGE'}}[$i][1] = $end;
$self->{'chars_per_level'} += 1 + oct($end) - oct($start);
}
} elsif (m/^HBF_START_CODE_RANGES/) {
my($desc, $total) = split(/\s+/, $_, 2);
$self->{'HBF_CODE_RANGES'} = $total;
$self->{'HBF_CODE_RANGE'} = [];
my($line);
for ($i = 0; $i < $total and $desc ne 'HBF_END_CODE_RANGES'; $i++) {
chomp($line = <FD>);
if ($line =~ m/^COMMENT/) { $i--; next; }
my($desc, $content) = split(/\s+/, $line, 2);
my($start, $end, $srcfile, $offset) = split(/\-|\s+/, $content);
${$self->{'HBF_CODE_RANGE'}}[$i][0] = $start;
${$self->{'HBF_CODE_RANGE'}}[$i][1] = $end;
${$self->{'HBF_CODE_RANGE'}}[$i][2] = $srcfile;
${$self->{'HBF_CODE_RANGE'}}[$i][3] = $offset;
}
}
}
$self->{'CACHE'} = {};
return 1;
}
# Look up $char in HBF file and return the bitmap for it, if available
sub getChar {
my($self, $char) = @_;
my($hexval, $i, $offset);
my($byte1, $byte2, $byte3) = ("", "", "");
if (length($char) == 1) {
$byte1 = substr($char, 0, 1);
$byte1val = vec($byte1, 0, 8);
$hexval = vec($char, 0, 8);
} elsif (length($char) == 2) {
$byte1 = substr($char, 0, 1);
$byte1val = vec($byte1, 0, 8);
$byte2 = substr($char, 1, 1);
$byte2val = vec($byte2, 0, 8);
$hexval = vec($char, 0, 16);
} elsif (length($char) == 3) {
$byte1 = substr($char, 0, 1);
$byte1val = vec($byte1, 0, 8);
$byte2 = substr($char, 1, 1);
$byte2val = vec($byte2, 0, 8);
$byte3 = substr($char, 2, 1);
$byte3val = vec($byte3, 0, 8);
$hexval = vec($char, 0, 24);
}
if (defined(${$self->{'CACHE'}}{$char})) {
return unpack("B*", ${$self->{'CACHE'}}{$char});
}
for ($i = 0; $i < $self->{'HBF_CODE_RANGES'}; $i++) {
#print ${$self->{'HBF_CODE_RANGE'}}[$i][3], "\n";
if ($hexval >= oct(${$self->{'HBF_CODE_RANGE'}}[$i][0]) and
$hexval <= oct(${$self->{'HBF_CODE_RANGE'}}[$i][1]))
{
open(FONT, $self->{'LOADPATH'} . "/" . ${$self->{'HBF_CODE_RANGE'}}[$i][2]) or
die $self->{'LOADPATH'} . "/" . ${$self->{'HBF_CODE_RANGE'}}[$i][2];
binmode(FONT);
$offset = ${$self->{'HBF_CODE_RANGE'}}[$i][3];
# print "Initial offset $offset\n";
my $offsetchars = 0;
$srangebyte1 = substr(${$self->{'HBF_CODE_RANGE'}}[$i][0], 2, 2);
$srangebyte2 = substr(${$self->{'HBF_CODE_RANGE'}}[$i][0], 4, 2);
$srangebyte1val = oct("0x" . $srangebyte1);
$srangebyte2val = oct("0x" . $srangebyte2);
$erangebyte1 = substr(${$self->{'HBF_CODE_RANGE'}}[$i][1], 2, 2);
$erangebyte2 = substr(${$self->{'HBF_CODE_RANGE'}}[$i][1], 4, 2);
$erangebyte1val = oct("0x" . $erangebyte1);
$erangebyte2val = oct("0x" . $erangebyte2);
my $byte2base = 0;
# printf("%x\t%x\t%x\t%x\n", $srangebyte1val, $byte1val, $srangebyte2val, $byte2val);
if ($srangebyte1val == $byte1val) {
if ($srangebyte2val == $byte2val) {
# Character is first in code range
seek(FONT, $offset, 0);
read(FONT, $returnval, $self->{'bytes'});
} else {
for ($j = 0; $j < $self->{'HBF_BYTE_2_RANGES'}; $j++) {
if ($srangebyte2val >= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0]) and
$srangebyte2val <= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]))
{
if ($byte2val >= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0]) and
$byte2val <= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]))
{
$offset += ($byte2val - $srangebyte2val) * $self->{'bytes'};
last;
}
else
{
$offset += (oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]) -
$srangebyte2val) * $self->{'bytes'};
for ($j++; $j < $self->{'HBF_BYTE_2_RANGES'}; $j++) {
if ($byte2val >= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0]) and
$byte2val <= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]))
{
$offset += (1 + $byte2val - oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0])) *
$self->{'bytes'};
last;
}
else {
$offset += (oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]) -
oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0])) *
$self->{'bytes'};
}
}
}
}
}
seek(FONT, $offset, 0);
read(FONT, $returnval, $self->{'bytes'});
}
} else { # Byte 1 of character greater than byte one of range start
# Find no. of characters from srangebyte2 to next byte1
for ($j = 0; $j < $self->{'HBF_BYTE_2_RANGES'}; $j++) {
if ($srangebyte2val >= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0]) and
$srangebyte2val <= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]))
{
$offset += (1 + oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]) - $srangebyte2val) *
$self->{'bytes'};
for ($j++; $j < $self->{'HBF_BYTE_2_RANGES'}; $j++) {
$offset += (1 + oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]) -
oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0])) *
$self->{'bytes'};
}
}
}
# print "Offset after first byte2 $offset\n";
# Find no. of characters between byte1 ranges
$offset +=($byte1val - ($srangebyte1val + 1)) * $self->{'chars_per_level'} *
$self->{'bytes'};
# print "Offset after byte1 subtraction $offset\n";
# Find no. of characters to byte2val
for ($j = 0; $j < $self->{'HBF_BYTE_2_RANGES'}; $j++) {
if ($byte2val >= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0]) and
$byte2val <= oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1])) {
$offset += ($byte2val - oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0])) *
$self->{'bytes'};
last;
}
else {
$offset += (1 + oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][1]) -
oct(${$self->{'HBF_BYTE_2_RANGE'}}[$j][0])) *
$self->{'bytes'};
}
}
# print "Final offset $offset\n";
seek(FONT, $offset, 0);
read(FONT, $returnval, $self->{'bytes'});
}
last;
}
}
if ($returnval ne "") {
${$self->{'CACHE'}}{$char} = $returnval;
}
close FONT;
# Return a string of ASCII 1's and 0's representing character
# Done this way rather than use vec to access data to avoid
# byte ordering problems
unpack("B*", $returnval);
}
END { }
1;