Панго: Поиск позиций в строках деванагари - PullRequest
3 голосов
/ 15 октября 2019

Я использую Pango для набора текста Деванагари. Рассмотрим строку उम्कन्छौ, состоящую из Письма DEVANAGARI U, Письма DEVANAGARI MA, Знака DEVANAGARI SIGN VIRAMA, Письма DEVANAGARI KA, Письма DEVANAGARI NA, Письма DEVANAGARI SIGN VIRAMA, Письма DEVAAGARI CHA, DEVANAGARI VOWEL SIGN A. При наборе этой строки я хочу знать начальную точку छ (CHA), чтобы поставить визуальную метку.

Для обычных строк я бы взял длину предыдущей части, here но здесь это не работаетпоскольку, как вы можете видеть, न् (половина न) объединяется с छ, поэтому результат немного отличается.

Есть ли способ получить правильную начальную точку буквы, когда используются комбинации?

Я пытался запросить макет 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 Ответ

2 голосов
/ 17 октября 2019

Вы не можете измерить частичный рендеринг. Вместо этого измерьте весь рендеринг и переберите строку графически, чтобы найти позицию. Также см .: https://gankra.github.io/blah/text-hates-you/#style-can-change-mid-ligature

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;
...