package fontdlg;
=pod
=head1 NAME
examples/fontdlg.pl - An alternate font selection window
=head1 FEATURES
Demonstrates Prima font API and its usage.
Note the inability to set a font with a particular size and width factor in one
call ( in $re_sample sub ). A font size and width is accepted, however.
Tests the Prima font interface implementation. A constant pain here is the
correspondence of a font metrics before and after the font load. X is known
for the problem, that can not be solved easily and without certain compromises.
See L<prima-gp-problems> manpage for details.
Note the left-mouse drag effect from a font screen widget.
=cut
use strict;
use warnings;
use Carp;
use Prima;
use Prima::Application name => "Font Dialog";
use Prima qw(Lists Sliders Buttons Dialog::FileDialog);
use Encode;
# try to use perl5.8 glyph names
eval "use charnames qw(:full);";
my $use_charnames = $@ ? 0 : 1;
sub run {
my $w = 0;
my @fontItems = ();
my %fontList = ();
my $displayRes;
my $fs = 0;
my $fd = 0;
my $fpitch = fp::Default;
my $fvector = fv::Default;
my $fwidth = 0;
our %languages = (
'aa' => q(Afar),
'ab' => q(Abkhazia),
'af' => q(Afrikaans),
'ak' => q(Akan),
'am' => q(Amharic),
'an' => q(Aragonese),
'ar' => q(Arabic),
'as' => q(Assamese),
'ast' => q(Asturian),
'av' => q(Avaric),
'ay' => q(Aymara),
'az-az' => q(Azerbaijani in Azerbaijan),
'az-ir' => q(Azerbaijani in Iran),
'ba' => q(Bashkir),
'be' => q(Byelorussian),
'ber-dz' => q(Berber in Algeria),
'ber-ma' => q(Berber in Morocco),
'bg' => q(Bulgarian),
'bh' => q(Bihari),
'bho' => q(Bhojpuri),
'bi' => q(Bislama),
'bin' => q(Edo or Bini),
'bm' => q(Bambara),
'bn' => q(Bengali),
'bo' => q(Tibetan),
'br' => q(Breton),
'brx' => q(Bodo),
'bs' => q(Bosnian),
'bua' => q(Buriat),
'byn' => q(Blin),
'ca' => q(Catalan),
'ce' => q(Chechen),
'ch' => q(Chamorro),
'chm' => q(Mari),
'chr' => q(Cherokee),
'co' => q(Corsican),
'crh' => q(Crimean Tatar),
'cs' => q(Czech),
'csb' => q(Kashubian),
'cu' => q(Old Church Slavonic),
'cv' => q(Chuvash),
'cy' => q(Welsh),
'da' => q(Danish),
'de' => q(German),
'doi' => q(Dogri),
'dv' => q(Divehi),
'dz' => q(Dzongkha),
'ee' => q(Ewe),
'el' => q(Greek),
'en' => q(English),
'eo' => q(Esperanto),
'es' => q(Spanish),
'et' => q(Estonian),
'eu' => q(Basque),
'fa' => q(Persian),
'fat' => q(Fanti),
'ff' => q(Fulah),
'fi' => q(Finnish),
'fil' => q(Filipino),
'fj' => q(Fijian),
'fo' => q(Faroese),
'fr' => q(French),
'fur' => q(Friulian),
'fy' => q(Frisian),
'ga' => q(Irish),
'gd' => q(Scots Gaelic),
'gez' => q(Ethiopic),
'gl' => q(Galician),
'gn' => q(Guaraní),
'gu' => q(Gujarati),
'gv' => q(Manx Gaelic),
'ha' => q(Hausa),
'haw' => q(Hawaiian),
'he' => q(Hebrew),
'hi' => q(Hindi),
'hne' => q(Chhattisgarhi),
'ho' => q(Hiri Motu),
'hr' => q(Croatian),
'hsb' => q(Upper Sorbian),
'ht' => q(Haitian),
'hu' => q(Hungarian),
'hy' => q(Armenian),
'hz' => q(Herero),
'ia' => q(Interlingua),
'id' => q(Indonesian),
'ie' => q(Interlingue),
'ig' => q(Igbo),
'ii' => q(Sichuan Yi),
'ik' => q(Inupiaq),
'io' => q(Ido),
'is' => q(Icelandic),
'it' => q(Italian),
'iu' => q(Inuktitut),
'ja' => q(Coverage from JIS X 0208),
'jv' => q(Javanese),
'ka' => q(Georgian),
'kaa' => q(Kara-Kalpak),
'kab' => q(Kabyle),
'ki' => q(Kikuyu),
'kj' => q(Kuanyama),
'kk' => q(Kazakh),
'kl' => q(Greenlandic),
'km' => q(Central Khmer),
'kn' => q(Kannada),
'ko' => q(Korean),
'kok' => q(Kokani),
'kr' => q(Kanuri),
'ks' => q(Kashmiri),
'ku-am' => q(Kurdish in Armenia),
'ku-iq' => q(Kurdish in Iraq),
'ku-ir' => q(Kurdish in Iran),
'ku-tr' => q(Kurdish in Turkey),
'kum' => q(Kumyk),
'kv' => q(Komi),
'kw' => q(Cornish),
'kwm' => q(Kwambi),
'ky' => q(Kirgiz),
'la' => q(Latin),
'lah' => q(Lahnda),
'lb' => q(Luxembourgish),
'lez' => q(Lezghian),
'lg' => q(Ganda),
'li' => q(Limburgan),
'ln' => q(Lingala),
'lo' => q(Lao),
'lt' => q(Lithuanian),
'lv' => q(Latvian),
'mai' => q(Maithili),
'mg' => q(Malagasy),
'mh' => q(Marshallese),
'mi' => q(Maori),
'mk' => q(Macedonian),
'ml' => q(Malayalam),
'mn-cn' => q(Mongolian in China),
'mn-mn' => q(Mongolian in Mongolia),
'mni' => q(Maniputi),
'mo' => q(Moldavian),
'mr' => q(Marathi),
'ms' => q(Malay),
'mt' => q(Maltese),
'my' => q(Burmese),
'na' => q(Nauru),
'nb' => q(Norwegian Bokmål),
'nds' => q(Low Saxon),
'ne' => q(Nepali),
'ng' => q(Ndonga),
'nl' => q(Dutch),
'nn' => q(Norwegian Nynorsk),
'no' => q(Norwegian),
'nqo' => q(N'Ko),
'nr' => q(Ndebele, South),
'nso' => q(Northern Sotho),
'nv' => q(Navajo),
'ny' => q(Chichewa),
'oc' => q(Occitan),
'om' => q(Oromo or Galla),
'or' => q(Oriya),
'os' => q(Ossetic),
'ota' => q(Ottoman Turkish),
'pa' => q(Panjabi),
'pa-pk' => q(Panjabi),
'pap-an' => q(Papiamento in Netherlands Antilles),
'pap-aw' => q(Papiamento in Aruba),
'pes' => q(Western Farsi),
'pl' => q(Polish),
'prs' => q(Dari),
'ps-af' => q(Pashto in Afghanistan),
'ps-pk' => q(Pashto in Pakistan),
'pt' => q(Portuguese),
'qu' => q(Quechua),
'quz' => q(Cusco Quechua),
'rm' => q(Rhaeto-Romance),
'rn' => q(Rundi),
'ro' => q(Romanian),
'ru' => q(Russian),
'rw' => q(Kinyarwanda),
'sa' => q(Sanskrit),
'sah' => q(Yakut),
'sat' => q(Santali),
'sc' => q(Sardinian),
'sco' => q(Scots),
'sd' => q(Sindhi),
'se' => q(North Sámi),
'sel' => q(Selkup),
'sg' => q(Sango),
'sh' => q(Serbo-Croatian),
'shs' => q(Secwepemctsin),
'si' => q(Sinhala),
'sid' => q(Sidamo),
'sk' => q(Slovak),
'sl' => q(Slovenian),
'sm' => q(Samoan),
'sma' => q(South Sámi),
'smj' => q(Lule Sámi),
'smn' => q(Inari Sámi),
'sms' => q(Skolt Sámi),
'sn' => q(Shona),
'so' => q(Somali),
'sq' => q(Albanian),
'sr' => q(Serbian),
'ss' => q(Swati),
'st' => q(Sotho, Southern),
'su' => q(Sundanese),
'sv' => q(Swedish),
'sw' => q(Swahili),
'syr' => q(Syriac),
'ta' => q(Tamil),
'te' => q(Telugu),
'tg' => q(Tajik),
'th' => q(Thai),
'ti-er' => q(Eritrean Tigrinya),
'ti-et' => q(Ethiopian Tigrinya),
'tig' => q(Tigre),
'tk' => q(Turkmen),
'tl' => q(Tagalog),
'tn' => q(Tswana),
'to' => q(Tonga),
'tr' => q(Turkish),
'ts' => q(Tsonga),
'tt' => q(Tatar),
'tw' => q(Twi),
'ty' => q(Tahitian),
'tyv' => q(Tuvinian),
'ug' => q(Uyghur),
'uk' => q(Ukrainian),
'ur' => q(Urdu),
'uz' => q(Uzbek),
've' => q(Venda),
'vi' => q(Vietnamese),
'vo' => q(Volapük),
'vot' => q(Votic),
'wa' => q(Walloon),
'wal' => q(Wolaitta),
'wen' => q(Sorbian languages),
'wo' => q(Wolof),
'xh' => q(Xhosa),
'yap' => q(Yapese),
'yi' => q(Yiddish),
'yo' => q(Yoruba),
'za' => q(Zhuang),
'zh-cn' => q(Chinese),
'zh-hk' => q(Chinese Hong Kong Supplementary Character Set),
'zh-mo' => q(Chinese in Macau),
'zh-sg' => q(Chinese in Singapore),
'zh-tw' => q(Chinese),
'zu' => q(Zulu),
);
my $re_sample = sub {
return if $w-> {exampleFontSet};
my $fid = $w-> NameList-> get_item_text( $w-> NameList-> focusedItem);
my $fn = ($fid =~ /not defined/) ? 'Default' : $fontList{$fid}{name};
$w-> {exampleFontSet} = 1;
my $i = $w-> SizeList-> focusedItem;
my $enc = $w-> Encoding-> get_item_text( $w-> Encoding-> focusedItem);
$enc = '' if $enc eq '(any)';
$w-> Example-> lock;
my %font = (
name => $fn,
size => $w-> SizeList-> get_item_text( $i),
style => $fs,
direction => $fd,
pitch => $fpitch,
vector => $fvector,
encoding => $enc,
);
$w-> Example-> font( %font,
width => 0,
);
$w-> Example-> font( %font,
width => $w-> Example-> font-> width * $fwidth,
) if $fwidth;
$w-> Example-> unlock;
$w-> {exampleFontSet} = undef;
};
my $lastSizeSel = 12;
my $lastEncSel = "";
my $re_size = sub {
my $name_changed = $_[0];
my $fid = $w-> NameList-> get_item_text( $w-> NameList-> focusedItem);
my $fn = ($fid =~ /not defined/) ? undef : $fontList{$fid}{name};
my @sizes = ();
my $current_encoding = ( $lastEncSel eq '(any)' || $name_changed) ? '' : $lastEncSel;
my @list = $fn ?
@{$::application-> fonts( $fn, $name_changed ? '' : $current_encoding)} :
({vector => 1});
if ( $name_changed) {
my %enc;
my @enc_items;
for ( grep { defined } map { $_-> {encoding}} @list) {
next if $enc{$_};
push ( @enc_items, $_ );
$enc{$_} = 1;
}
unshift @enc_items, "(any)";
my $found = 0;
my $i = 0;
for ( @enc_items) {
$found = $i, last if $_ eq $lastEncSel;
$i++;
}
$w-> Encoding-> set_items( \@enc_items);
$w-> Encoding-> set_focused_item( $found);
}
for ( @list)
{
next if length( $current_encoding) && ( $current_encoding ne $_-> {encoding});
if ( $_-> { vector})
{
@sizes = qw( 8 9 10 11 12 14 16 18 20 22 24 26 28 32 48 72);
last;
} else {
push ( @sizes, $_-> {size});
}
}
my %k = map { $_ => 1 } @sizes;
@sizes = sort { $a <=> $b } keys %k;
@sizes = (10) unless scalar @sizes;
my $i;
my $found = 0;
for ( $i = 0; $i < scalar @sizes; $i++)
{
if ( $sizes[$i] == $lastSizeSel)
{
$found = 1;
last;
}
}
unless ( $found)
{
for ( $i = 0; $i < scalar @sizes; $i++)
{
last if ( $sizes[$i] > $lastSizeSel);
}
$i-- if $i = scalar @sizes;
}
$w-> SizeList-> set_items(\@sizes);
$w-> SizeList-> set_focused_item($i);
};
$w = Prima::MainWindow-> create( text => "Font Window",
origin => [ 200, 200],
size => [ 500, 590],
designScale => [7,16],
borderStyle => bs::Dialog,
);
sub create_info_window
{
my $w = shift;
my $f = $w-> Example-> font;
my $ww = Prima::Window-> create(
size => [ 500, $f-> height * 3 + $f-> externalLeading + $f-> descent + 450 ],
font => $f,
text => $f-> size.'.['.$f-> height.'x'.$f-> width.']'.$f-> name,
onPaint => sub {
my ( $self, $p) = @_;
my @size = $p-> size;
$p-> clear;
$p-> font-> direction(0);
my $m = $p-> get_font;
my $xtext = Encode::decode('latin1', "\x{c5}Mg");
my $s = $size[1] - $m-> {height} - $m-> {externalLeading} - 20;
my $w = $p-> get_text_width($xtext) + 66;
$p-> textOutBaseline(1);
$p-> text_out($xtext, 20, $s);
my $cachedFacename = $p-> font-> name;
my $hsf = $p-> font-> height / 6;
$hsf = 10 if $hsf < 10;
$p-> font-> set(
height => $hsf,
style => fs::Italic,
name => '',
encoding => '',
);
$p-> line( 2, $s, $w, $s);
$p-> textOutBaseline(0);
$p-> text_out( "Baseline", $w - 8, $s);
my $sd = $s - $m-> {descent};
$p-> line( 2, $sd, $w, $sd);
$p-> text_out( "Descent", $w - 8, $sd);
$sd = $s + $m-> {ascent};
$p-> line( 2, $sd, $w, $sd);
$p-> text_out( "Ascent", $w - 8, $sd);
$sd = $s + $m-> {ascent} + $m-> {externalLeading};
if ( $m-> {ascent} > 4) {
$p-> line( $w - 12, $s + 1, $w - 12, $s + $m-> {ascent});
$p-> line( $w - 12, $s + $m-> {ascent}, $w - 14, $s + $m-> {ascent} - 2);
$p-> line( $w - 12, $s + $m-> {ascent}, $w - 10, $s + $m-> {ascent} - 2);
}
if ( ($m-> {ascent}-$m-> {internalLeading}) > 4) {
my $pt = $m-> {ascent}-$m-> {internalLeading};
$p-> line( $w - 16, $s + 1, $w - 16, $s + $pt);
$p-> line( $w - 16, $s + $pt, $w - 18, $s + $pt - 2);
$p-> line( $w - 16, $s + $pt, $w - 14, $s + $pt - 2);
}
if ( $m-> {descent} > 4) {
$p-> line( $w - 13, $s - 1, $w - 13, $s - $m-> {descent});
$p-> line( $w - 13, $s - $m-> {descent}, $w - 15, $s - $m-> {descent} + 2);
$p-> line( $w - 13, $s - $m-> {descent}, $w - 11, $s - $m-> {descent} + 2)
}
my $str;
$p-> text_out( "External Leading", 2, $sd);
$p-> line( 2, $sd, $w, $sd);
$sd = $s + $m-> {ascent} - $m-> {internalLeading};
$str = "Point size in device units";
$p-> text_out( $str, $w - 16 - $p-> get_text_width( $str), $sd);
$p-> linePattern( lp::Dash);
$p-> line( 2, $sd, $w, $sd);
$p-> font-> set(
height => 16,
pitch => fp::Fixed,
);
my $fh = $p-> font-> height;
$sd = $s - $m-> {descent} - $fh * 3;
$p-> text_out( 'nominal size : '.$m-> {size}, 2, $sd); $sd -= $fh;
$p-> text_out( 'cell height : '.$m-> {height }, 2, $sd); $sd -= $fh;
$p-> text_out( 'average width : '.$m-> {width }, 2, $sd); $sd -= $fh;
$p-> text_out( 'ascent : '.$m-> {ascent }, 2, $sd); $sd -= $fh;
$p-> text_out( 'descent : '.$m-> {descent }, 2, $sd); $sd -= $fh;
$p-> text_out( 'weight : '.$m-> {weight }, 2, $sd); $sd -= $fh;
$p-> text_out( 'internal leading : '.$m-> {internalLeading}, 2, $sd); $sd -= $fh;
$p-> text_out( 'external leading : '.$m-> {externalLeading}, 2, $sd); $sd -= $fh;
$p-> text_out( 'maximal width : '.$m-> {maximalWidth}, 2, $sd); $sd -= $fh;
$p-> text_out( 'vector : '.$m-> {vector}, 2, $sd); $sd -= $fh;
$p-> text_out( 'horizontal dev.res. : '.$m-> {xDeviceRes}, 2, $sd); $sd -= $fh;
$p-> text_out( 'vertical dev.res. : '.$m-> {yDeviceRes}, 2, $sd); $sd -= $fh;
$p-> text_out( 'first char : '.$m-> {firstChar}, 2, $sd); $sd -= $fh;
$p-> text_out( 'last char : '.$m-> {lastChar }, 2, $sd); $sd -= $fh;
$p-> text_out( 'break char : '.$m-> {breakChar}, 2, $sd); $sd -= $fh;
$p-> text_out( 'default char : '.$m-> {defaultChar}, 2, $sd); $sd -= $fh;
$p-> text_out( 'family : '.$m-> {family }, 2, $sd); $sd -= $fh;
$p-> text_out( 'face name : '.$cachedFacename, 2, $sd); $sd -= $fh;
unless ( $p-> Languages-> visible ) {
my $l = $p-> Languages;
my $em = $p->get_text_width('m');
$l->origin( 2 + $em * 22, $sd );
$l->font( $p-> font );
$l->size( $em * 30, $fh);
$l->show;
}
$p-> text_out( 'languages : ', 2, $sd); $sd -= $fh;
},
);
$ww-> insert( ComboBox =>
name => 'Languages',
style => cs::DropDownList,
items => [
sort map { $languages{$_} // $_ }
@{$ww->get_font_languages // ['<none>']}
],
growMode => gm::GrowLoY,
visible => 0,
text => '',
);
my %wf = ( %$f, direction => 0 );
my @gsize= ( $f->maximalWidth + 10 , $f->height + 10 );
my $glyph = $ww-> insert( Widget =>
text => ' ',
font => \%wf,
size => \@gsize,
origin => [ $ww-> width - $gsize[0] - 10, $ww-> height - $gsize[1] - 10 ],
growMode => gm::GrowLoX|gm::GrowLoY,
backColor => cl::White,
#buffered => 1,
name => 'Glyph',
textOutBaseline => 1,
onPaint => sub {
my $self = shift;
$self-> clear;
my $C = $self-> text;
my ( $a, $b, $c ) = @{ $self->get_font_abc( ord($C), ord($C), utf8::is_utf8($C)) };
my ( $d, $e, $f ) = @{ $self->get_font_def( ord($C), ord($C), utf8::is_utf8($C)) };
my $w = (( $a < 0 ) ? 0 : $a) + $b + (( $c < 0 ) ? 0 : $c);
my $h = (( $d < 0 ) ? 0 : $d) + $e + (( $f < 0 ) ? 0 : $f);
$w = ( $self-> width - $w ) / 2;
$h = ( $self-> height - $h ) / 2;
$self-> translate($w, $h);
my $dx = 0;
my $dy = 0;
$dx -= $a if $a < 0;
$dy -= $d if $d < 0;
my $fh = $self-> font->height;
$self-> text_out( $C, $dx, $dy + $self->font-> descent);
$dx = abs($a);
$dy = abs($d);
$self-> linePattern(lp::Dot);
$self-> line($dx, 0, $dx, $self->height);
$dx = (( $a < 0 ) ? 0 : $a) + $b + (( $c < 0 ) ? 0 : $c) - abs($c);
$self-> line($dx, 0, $dx, $self->height);
$self-> line(-$w, $self->font->descent, $self->width, $self->font->descent);
$self-> line(0, $dy, $self->width, $dy);
$dy = (( $d < 0 ) ? 0 : $d) + $e + (( $f < 0 ) ? 0 : $f) - abs($f);
$self-> line(0, $dy, $self->width, $dy);
$self-> linePattern(lp::Solid);
$self-> color(cl::LightRed);
my $path = $self-> new_path;
$path->translate( -$a, 0 ) if $a < 0;
$path-> text( $C, baseline => 0 );
$path->stroke;
},
);
my @ranges = ([]);
for ( @{$w-> Example-> get_font_ranges}) {
( 2 > scalar @{$ranges[-1]}) ?
push @{$ranges[-1]}, $_ :
push @ranges, [$_];
}
@ranges = sort { $a->[0] <=> $b-> [0] } @ranges;
my %charmap;
my $count = 0;
for ( @ranges) {
$charmap{$count++} = $_ for $$_[0] .. $$_[1];
}
my $ih = int($f-> height * 1.5);
my $l = $ww-> insert( AbstractListViewer =>
origin => [0,0],
size => [$ww-> width, $ww-> height - $f-> height - $f-> externalLeading - $f-> descent - 360],
growMode => gm::Client,
font => $f,
multiColumn => 1,
itemWidth => $ih,
itemHeight => $ih,
gridColor => cl::Back,
hScroll => 1,
onSelectItem => sub {
my ( $self, $item, $sel) = @_;
if ( defined( my $c = $charmap{$item->[0]} )) {
my $pretty = sprintf( "0x%x", $c);
if ( $use_charnames) {
my $x = charnames::viacode($c);
$pretty .= " - $x" if defined $x;
}
$self-> hint( $pretty );
$self-> hintVisible(1);
$glyph->text(chr($c));
$glyph->repaint;
}
},
onDrawItem => sub {
my ($self, $canvas, $itemIndex, $x, $y, $x2, $y2, $selected, $focused, $prelight) = @_;
$canvas-> line( $x, $y, $x2, $y);
$canvas-> line( $x2+1, $y, $x2+1, $y2);
my @cs;
if ( $focused || $prelight) {
@cs = ( $canvas-> color, $canvas-> backColor);
my $fo = $focused ? $canvas-> hiliteColor : $canvas-> color ;
my $bk = $focused ? $canvas-> hiliteBackColor : $canvas-> backColor ;
$canvas-> set( color => $fo, backColor => $bk );
}
$self-> draw_item_background( $canvas, $x, $y + 1, $x2, $y2, $prelight );
if ( defined( my $c = $charmap{$itemIndex} )) {
$canvas-> text_out( chr($c), $x + $ih / 4, $y + $ih / 4);
}
$canvas-> set( color => $cs[0], backColor => $cs[1]) if $focused || $prelight;
},
);
$l-> count( $count);
$ww-> select;
return $ww;
}
$displayRes = ($w-> resolution)[1];
my $load_fonts = sub {
%fontList = ();
@fontItems = ("<not defined>");
for ( sort { $a-> {name} cmp $b-> {name}} @{$::application-> fonts})
{
$fontList{$_-> {name}} = $_;
push ( @fontItems, $_-> {name});
}
};
$load_fonts->();
$w-> insert( ListBox =>
name => "NameList",
origin => [25, 25],
size => [ 225, 315],
items => [@fontItems],
onSelectItem => sub {
&$re_size(1);
&$re_sample;
},
);
$w-> insert( ListBox =>
name => 'SizeList',
origin => [ 270, 230],
size => [ 200, 110],
onSelectItem => sub {
$lastSizeSel = $_[0]-> get_item_text( $_[0]-> focusedItem);
&$re_sample;
},
);
$w-> insert( ListBox =>
origin => [ 270, 160],
size => [ 200, 55],
name => 'Encoding',
onSelectItem => sub {
$lastEncSel = $_[0]-> get_item_text( $_[0]-> focusedItem);
&$re_size(0);
&$re_sample;
},
);
my $scaling = $::application->font->height / ($w->designScale)[1];
$w-> insert( Button =>
origin => [ 24, 348],
size => [ 32, 32],
text => 'B',
name => 'Bold',
selectable => 0,
font => {
height => 20 * $scaling,
style => fs::Bold,
},
checkable => 1,
onClick => sub {
$fs = ( $fs & fs::Bold ? $fs & ~fs::Bold : $fs | fs::Bold);
&$re_sample;
},
);
$w-> insert( Button =>
origin => [ 60, 348],
size => [ 32, 32],
text => 'I',
name => 'Italic',
selectable => 0,
font => {
height => 20 * $scaling,
style => fs::Italic,
},
checkable => 1,
onClick => sub {
$fs = (( $fs & fs::Italic) ? ($fs & ~fs::Italic) : ($fs | fs::Italic));
&$re_sample;
},
);
$w-> insert( Button =>
origin => [ 96, 348],
size => [ 32, 32],
text => 'U',
selectable => 0,
name => 'Underlined',
font => {
height => 20 * $scaling,
style => fs::Underlined,
},
checkable => 1,
onClick => sub {
$fs = (( $fs & fs::Underlined) ? ($fs & ~fs::Underlined) : ($fs | fs::Underlined));
&$re_sample;
},
);
$w-> insert( Button =>
origin => [ 142, 348],
size => [ 32, 32],
text => 'i',
selectable => 0,
name => 'Info',
color => cl::Blue,
font => { height => 28 * $scaling, style => fs::Bold },
onClick => sub { create_info_window($w) },
);
$w-> insert( Button =>
origin => [ 180, 348],
size => [ 32, 32],
text => '+',
hint => 'Add new font',
selectable => 0,
name => 'Load',
font => { height => 20 * $scaling },
onClick => sub {
my $d = Prima::Dialog::FileDialog-> new;
my $f = $d->execute;
return unless defined $f;
my $error = '';
local $SIG{__WARN__} = sub { $error = ": @_" };
unless ($::application->load_font($d->fileName)) {
$error =~ s/at examples.*//;
return Prima::message("Error loading font$error");
}
$load_fonts->();
$w->NameList->items(\@fontItems);
}
);
my $csl = $w-> insert( CircularSlider =>
origin => [ 370, 348],
size => [ 100, 100],
name => 'Angle',
buttons => 0,
font => {size => 5},
min => -180,
max => 180,
scheme => ss::Axis,
increment => 30,
step => 10,
onChange => sub { $fd = $_[0]-> value; &$re_sample; },
);
$csl-> insert( Button =>
origin => [ 10, 10],
size => [ 14, 14],
text => 'o',
onClick => sub { $_[0]-> owner-> value(0); },
);
my $rg = $w-> insert( RadioGroup =>
origin => [ 25, 525],
size => [ 445, 58],
name => 'Pitch',
);
$rg-> insert( Radio =>
name => 'Default',
origin => [ 15, 5],
onClick => sub { $fpitch = fp::Default; &$re_sample; },
checked => 1,
);
$rg-> insert( Radio =>
name => 'Fixed',
origin => [ 160, 5],
onClick => sub { $fpitch = fp::Fixed; &$re_sample; },
font => { style => fs::Bold, pitch => fp::Fixed},
);
$rg-> insert( Radio =>
name => 'Variable',
origin => [ 305, 5],
font => { style => fs::Bold|fs::Italic, pitch => fp::Variable},
onClick => sub { $fpitch = fp::Variable; &$re_sample; },
);
my $rg2 = $w-> insert( RadioGroup =>
origin => [ 25, 460],
size => [ 445, 58],
name => 'Vector',
);
$rg2-> insert( Radio =>
name => 'Default',
origin => [ 15, 5],
onClick => sub { $fvector = fv::Default; &$re_sample; },
checked => 1,
);
$rg2-> insert( Radio =>
name => 'Bitmap',
origin => [ 160, 5],
onClick => sub { $fvector = fv::Bitmap; &$re_sample; },
font => { style => fs::Bold, pitch => fp::Fixed}, # yes, fixed
);
$rg2-> insert( Radio =>
name => 'Outline',
origin => [ 305, 5],
font => { vector => fv::Outline, style => fs::Italic },
onClick => sub { $fvector = fv::Outline; &$re_sample; },
);
$w-> insert( Slider =>
name => 'Stretcher',
origin => [ 25, 382],
size => [ 225, 58],
vertical => 0,
min => -5,
max => 5,
scheme => ss::Axis,
step => 0.5,
increment=> 5,
value => 0,
onChange => sub {
$fwidth = $_[0]-> value;
if ( $fwidth > 0) {
$fwidth += 1;
} elsif ( $fwidth < 0) {
$fwidth = -1 / ( $fwidth - 1);
}
&$re_sample;
},
);
$w-> insert( Button =>
origin => [ 130, 440],
size => [ 14, 14],
text => 'o',
font => {size => 5},
onClick => sub { $w-> Stretcher-> value(0); },
);
$w-> insert( Widget =>
name => 'Example',
origin => [ 270, 25],
size => [ 200, 120],
backColor => cl::White,
onPaint => sub {
my ($fore, $back, $x, $y) =
($_[0]-> color, $_[0]-> backColor, $_[1]-> width, $_[1]-> height);
$_[1]-> color( $back);
$_[1]-> bar( 0, 0, $x, $y);
$_[1]-> color( $fore);
my $m = $_[1]-> get_font;
my $probe;
my @ranges = @{$_[1]-> get_font_ranges};
my $vec = '';
my ($i,$j);
my ($latin,$non_latin)=('','');
RANGES: for ( $i = 0; $i < @ranges; $i += 2) {
for ( $j = $ranges[$i]; $j < $ranges[$i+1]; $j++) {
$latin .= chr($j) if $j > 45 && $j < 128;
$non_latin .= chr($j) if $j > 256 && ( !$use_charnames || (charnames::viacode($j) || '') !~
/(space|punctuation|mark|accent|point|combining|modifier)/i);
last RANGES if length($latin) > 32 || length($non_latin) > 32;
}
}
$probe = (length($latin) > 32) ? $_[1]-> font-> size.".".$_[1]-> font-> name : substr($non_latin, 0, 12);
my @box = @{$_[1]-> get_text_box( $probe)};
pop @box;
pop @box;
my $width = $_[1]-> get_text_width( $probe);
my ( $ox, $oy) = (( $x - $width) / 2, ( $y - $_[1]-> font-> height) / 2);
$box[$_] += $ox for 0,2,4,6;
$box[$_] += $oy for 1,3,5,7;
@box[4,5,6,7] = @box[6,7,4,5];
$_[1]-> color( cl::Yellow);
$_[1]-> fillpoly(\@box);
$_[1]-> color( cl::Black);
$_[1]-> text_out( $probe, $ox, $oy);
},
onFontChanged => sub {
unless ( defined $w-> {exampleFontSet})
{
my $font = $_[0]-> font;
my $name = $font-> name;
my $size = $font-> size;
$fs = $font-> style;
$fd = $font-> direction;
my ( $i, $j);
for ( $i = 0; $i < scalar @fontItems; $i++)
{
last if $name eq $fontItems[ $i];
}
$w-> NameList-> set_focused_item( $i);
my @sizes = @{$w-> SizeList-> items};
for ( $j = 0; $j < scalar @sizes; $j++)
{
last if $size == $sizes[ $j];
}
$w-> SizeList-> set_focused_item( $j);
$w-> Bold-> checked( $fs & fs::Bold);
$w-> Italic-> checked( $fs & fs::Italic);
$w-> Underlined-> checked( $fs & fs::Underlined);
$w-> Angle-> value( $fd);
}
},
onMouseDown => sub {
return if $_[0]-> {drag};
$_[0]-> {drag} = 1;
$_[0]-> capture(1);
$_[0]-> pointer( cr::Invalid)
},
onMouseUp => sub {
return unless $_[0]-> {drag};
$_[0]-> capture(0);
$_[0]-> {drag} = 0;
$_[0]-> pointer( cr::Default);
my $x = $::application-> get_widget_from_point(
$_[0]-> client_to_screen( $_[3], $_[4])
);
return unless $x;
$x-> font( $_[0]-> font);
},
);
&$re_size(1);
&$re_sample;
#$w->NameList->focusedItem($#fontItems);
#create_info_window($w)->size(800, 800);
}
run;
run Prima;