Панго: поиск позиций в струнах деванагари
Я использую Панго для набора Деванагари. Рассмотрим строку ठ‰ à¤®à ¥ ठ• à¤¨à ¥ ठ›à ¥ Œ, состоящую из ДЕВАНАГАРИ БУКВА U, ДЕВАНАГАРИ ПИСЬМО MA, ДЕВАНАГАРИ ЗНАК ВИРАМА, ДЕВАНАГАРИ ПИСЬМО КА, ДЕВАНАГАРИ ПИСЬМО ДЕВАНАГАРИ НА,, ДЕВАНАГАРИ БУКВА ЧА, ДЕВАНАГАРИ ГЛАВНЫЙ ЗНАК AU. При наборе этой строки я хочу знать начальную точку ठ›(CHA), чтобы поставить визуальную отметку.
Для обычных струн я бы взял длину предыдущей части, ठ‰ à¤®à ¥ ठ• à¤¨à ¥, но здесь это не работает, поскольку, как вы можете видеть, à¤¨à ¥ (половина ठ¨) сочетается с ठ›, поэтому результат немного нечеткий.
Есть ли способ получить правильную начальную точку буквы при использовании комбинаций?
Я пробовал запрашивать макет Pango с помощью index_to_pos(), но, похоже, это работает на уровне байтов (а не символов).
Эта небольшая программа на Perl показывает проблему. Вертикальная линия смещена вправо.
use strict;
use warnings;
use utf8;
use Cairo;
use Pango;
my $surface = Cairo::PdfSurface->create ("out.pdf", 595, 842);
my $cr = Cairo::Context->create ($surface);
my $layout = Pango::Cairo::create_layout($cr);
my $font = Pango::FontDescription->from_string('Lohit Devanagari');
$layout->set_font_description($font);
# Two parts of the phrase. Phrase1 ends in न् (half न).
my $phrase1 = 'उम्कन्';
my $phrase2 = 'छौ';
# Set the first part of the phrase, and get its width.
$layout->set_markup($phrase1);
my $w = ($layout->get_size)[0]/1024;
# Set the complete phrase.
$layout->set_markup($phrase1.$phrase2);
my ($x, $y ) = ( 100, 100 );
# Show phrase.
$cr->move_to( $x, $y );
$cr->set_source_rgba( 0, 0, 0, 1 );
Pango::Cairo::show_layout($cr, $layout);
# Show marker at width.
$cr->set_line_width(0.25);
$cr->move_to( $x + $w, $y-10 );
$cr->line_to( $x + $w, $y+50 );
$cr->stroke;
$cr->show_page;
1 ответ
Вы не можете измерить частичную визуализацию. Вместо этого измерьте всю визуализацию и переберите строку по графеме, чтобы найти позицию. См. Также: https://gankra.github.io/blah/text-hates-you/
use strict;
use warnings;
use utf8;
use Cairo;
use Pango;
use List::Util qw(uniq);
use Encode qw(encode);
my $surface = Cairo::PdfSurface->create('out.pdf', 595, 842);
my $cr = Cairo::Context->create ($surface);
my $layout = Pango::Cairo::create_layout($cr);
my $font = Pango::FontDescription->from_string('Lohit Devanagari');
$layout->set_font_description($font);
my $phrase = 'उम्कन्छौ';
my @octets = split '', encode 'UTF-8', $phrase; # index_to_pos operates on octets
$layout->set_markup($phrase);
my ($x, $y) = (100, 100);
$cr->move_to($x, $y);
$cr->set_source_rgba(0, 0, 0, 1);
Pango::Cairo::show_layout($cr, $layout);
$cr->set_line_width(0.25);
my @offsets = uniq map { $layout->index_to_pos($_)->{x}/1024 } 0..$#octets;
# (0, 9.859375, 16.09375, 27.796875, 33.953125, 49.1875)
for my $offset (@offsets) {
$cr->move_to($x+$offset, $y-5);
$cr->line_to($x+$offset, $y+25);
$cr->stroke;
}
my @graphemes = $phrase =~ /\X/g; # qw(उ म् क न् छौ)
while (my ($idx, $g) = each @graphemes) {
if ($g =~ /^छ/) {
$cr->move_to($x+$offsets[$idx], $y-10);
$cr->line_to($x+$offsets[$idx], $y+50);
$cr->stroke;
last;
}
}
$cr->show_page;