stil / gd-text

PHP class making it easy to type text on pictures. Supports multi-lined text, horizontal and vertical alignment.
400 stars 131 forks source link

Reverse lines order in Persian and Arabic text wrap #53

Open tayyebi opened 4 years ago

tayyebi commented 4 years ago

Maybe this is not an issue but it can be a helpful answer that can save time for programmers who are speaking Persian (Farsi) or Arabic.

As you know, we cannot directly pass Persian (or Arabic) to $box->draw which $box is an instance of GDText::Box.

For example, if we have a text like:

همدان قدیمی‌ترین شهر ایران و از کهن‌ترین شهرهای جهان است. نخستین باری که اسم این شهر برده شد، در حدود ۱۱۰۰ سال پیش از میلاد بود که نام همدان را اَمدانه ذکر شده‌است.

and we directly pass it to the box, it will be like:

Bang

So we have to use a library like persian phpgd by @slashmili which will return an output like:

Reverse

Natives know that the output is in reverse order.

را امدانه ذکر شده است از میلاد بود که نام همدان در حدود ۱۱۰۰ سال پیش که اسم این شهر برده شد، جهان است. نخستین باری ایران و از کهن‌ترین شهرهای همدان قدیمی‌ترین شهر

It should be:

همدان قدیمی‌ترین شهر ایران و از کهن‌ترین شهرهای جهان است. نخستین باری که اسم این شهر برده شد، در حدود ۱۱۰۰ سال پیش از میلاد بود که نام همدان را امدانه ذکر شده است

Solution

So changes are required in Box.php:

+     /**
+     * @var reverse_text_lines_order
+     */
+    protected $reverse_text_lines_order = false;
+     /**
+     * @param bool $reverse_text_lines_order To Reverse Lines Order
+     */
+    public function setReverseTextLinesOrder($reverse_text_lines_order)
+    {
+        $this->reverse_text_lines_order = $reverse_text_lines_order;
+    }

Then use the new prop inside draw function:

             }
             $lines[] = $line;
         }
+        if ($this->reverse_text_lines_order == true)
+            $lines = array_reverse($lines);
         return $lines;
     }

In your main class you have to detect Persian (or Arabic) with following regex and then pass a parameter to $box:

   if (preg_match('/.*[چﺞﺤﺨﻬﻌﻐﻔﻘﺜﺼﻀﺸﺳیﺏﻼﺘﻨﻣکگﻭپﺩﺫﺭﺰﻄﻇژ].*/u', $text)){
       $text = fagd($input,'fa','vazir');
       $box->setReverseTextLinesOrder(true);
   }

So the output will correctly be: Correct

eissasoubhi commented 3 years ago

Unless the Class was refactored, this following change must be in the wrapTextWithOverflow function not draw

             }
             $lines[] = $line;
         }
+        if ($this->reverse_text_lines_order == true)
+            $lines = array_reverse($lines);
         return $lines;
     }
eissasoubhi commented 3 years ago

Until this issue is resolved you can implement these changes in your code by extending the Box class:

<?php

class GdBox extends \GDText\Box
{
    /**
     * @var bool
     */
    protected $reverse_text_lines_order = false;

    /**
     * @param bool $reverse_text_lines_order To Reverse Lines Order
     */
    public function setReverseTextLinesOrder($reverse_text_lines_order)
    {
        $this->reverse_text_lines_order = $reverse_text_lines_order;
    }

    /**
     * Splits overflowing text into array of strings.
     * @param string $text
     * @return string[]
     */
    protected function wrapTextWithOverflow($text)
    {
        $lines = parent::wrapTextWithOverflow($text);

        if ($this->reverse_text_lines_order == true) {
            $lines = array_reverse($lines);
        }

        return $lines;
    }
}

// example:

$box = new GdBox($image);
//...
$box->setReverseTextLinesOrder(true);
$box->draw('!وا تشا فييين اعشيري');
Lukasss93 commented 3 years ago

Until this issue is resolved you can implement these changes in your code by extending the Box class:

<?php

class GdBox extends \GDText\Box
{
    /**
     * @var bool
     */
    protected $reverse_text_lines_order = false;

    /**
     * @param bool $reverse_text_lines_order To Reverse Lines Order
     */
    public function setReverseTextLinesOrder($reverse_text_lines_order)
    {
        $this->reverse_text_lines_order = $reverse_text_lines_order;
    }

    /**
     * Splits overflowing text into array of strings.
     * @param string $text
     * @return string[]
     */
    protected function wrapTextWithOverflow($text)
    {
        $lines = parent::wrapTextWithOverflow($text);

        if ($this->reverse_text_lines_order == true) {
            $lines = array_reverse($lines);
        }

        return $lines;
    }
}

// example:

$box = new GdBox($image);
//...
$box->setReverseTextLinesOrder(true);
$box->draw('!وا تشا فييين اعشيري');

It's better to detect Arabic words to set automatically "setReverseTextLinesOrder(true)"

tayyebi commented 3 years ago

@eissasoubhi Thanks

Just implemented here: https://github.com/Pressz/Sariab-V2/blob/7d6445d48e366b12d8cb055f42e3b50a5dd3b687/Libs/gd-text-master/src/BoxPatched.php