الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مكتبة لاصلاح العربية في برامج اندرويد

بدأه .S.T.A.L.K.E.R في 7 ديسمبر 2011 · 10 رد · 4,957 مشاهدة · في Android
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

انتهيت منذ اشهر عديدة من مكتبة لاصلاح اللغة العربية في البرامج للاجهزة التي لا تدعم اللغة العربية و تظهر الاحرف متقطعة (غير متصلة)

و كانت فيها مشكلة بسيطة قمت باصلاحها اليوم

و احببت ان اشاركها لتكون مفتوحة المصدر

بشرط عند استخدامها الرجاء ذكر المصدر :)

arabicmosh.jar

package com.mosh.arabicfix;

/**
 (Mosh Arabic Shaper) this API should fix Arabic shapes used within Android views, and canvas.
 Copyright (C) 2011  Mohammad Mshari Ersan (mosh_java@yahoo.com)

 * IF YOU LIKED IT, DONATE BY HIRING ME, OR LET ME MAKE YOUR PROJECT.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * 
 * @author Mohammad Ersan
 */
public final class ArabicMosh {

	private static int[][] letters = new int[][] { { 65152, 65152, 65152, 65152, 1569, 0 },
			{ 65153, 65154, 65153, 65154, 1570, 1 }, { 65155, 65156, 65155, 65156, 1571, 1 },
			{ 65157, 65158, 65157, 65158, 1572, 1 }, { 65159, 65160, 65159, 65160, 1573, 1 },
			{ 65161, 65162, 65163, 65164, 1574, 3 }, { 65165, 65166, 65165, 65166, 1575, 1 },
			{ 65167, 65168, 65169, 65170, 1576, 3 }, { 65171, 65172, 65171, 65172, 1577, 1 },
			{ 65173, 65174, 65175, 65176, 1578, 3 }, { 65177, 65178, 65179, 65180, 1579, 3 },
			{ 65181, 65182, 65183, 65184, 1580, 3 }, { 65185, 65186, 65187, 65188, 1581, 3 },
			{ 65189, 65190, 65191, 65192, 1582, 3 }, { 65193, 65194, 65193, 65194, 1583, 1 },
			{ 65195, 65196, 65195, 65196, 1584, 1 }, { 65197, 65198, 65197, 65198, 1585, 1 },
			{ 65199, 65200, 65199, 65200, 1586, 1 }, { 65201, 65202, 65203, 65204, 1587, 3 },
			{ 65205, 65206, 65207, 65208, 1588, 3 }, { 65209, 65210, 65211, 65212, 1589, 3 },
			{ 65213, 65214, 65215, 65216, 1590, 3 }, { 65217, 65218, 65219, 65220, 1591, 3 },
			{ 65221, 65222, 65223, 65224, 1592, 3 }, { 65225, 65226, 65227, 65228, 1593, 3 },
			{ 65229, 65230, 65231, 65232, 1594, 3 }, { 1600, 1600, 1600, 1600, 1600, 3 },
			{ 65233, 65234, 65235, 65236, 1601, 3 }, { 65237, 65238, 65239, 65240, 1602, 3 },
			{ 65241, 65242, 65243, 65244, 1603, 3 }, { 65245, 65246, 65247, 65248, 1604, 3 },
			{ 65249, 65250, 65251, 65252, 1605, 3 }, { 65253, 65254, 65255, 65256, 1606, 3 },
			{ 65257, 65258, 65259, 65260, 1607, 3 }, { 65261, 65262, 65261, 65262, 1608, 1 },
			{ 65263, 65264, 65263, 65264, 1609, 1 }, { 65265, 65266, 65267, 65268, 1610, 3 } };
	private static int[][] harakat = new int[][] { { 65136, 65136, 65136, 65137, 1611, 3 },
			{ 65138, 65138, 65138, 65138, 1612, 3 }, { 65140, 65140, 65140, 65140, 1613, 3 },
			{ 65142, 65142, 65142, 65143, 1614, 3 }, { 65144, 65144, 65144, 65145, 1615, 3 },
			{ 65146, 65146, 65146, 65147, 1616, 3 }, { 65148, 65148, 65148, 65149, 1617, 3 },
			{ 65150, 65150, 65150, 65151, 1618, 3 } };
	private static int POSITION_ALONE = 0;
	private static int POSITION_END = 1;
	private static int POSITION_START = 2;
	private static int POSITION_MIDDLE = 3;
	private static final int COUNT = 1569;
	private static final int DIFF = 5;
	private static boolean needReverse = false;

	public static String getFix(String strText, boolean reverse) {
		if (strText.indexOf('\n') > 0) {
			StringBuffer stringBuffer = new StringBuffer(strText.length());
			String[] strb = strText.split("\n");
			for (String s : strb) {
				stringBuffer.append(fixString(s, reverse));
				stringBuffer.append('\n');
			}
			return stringBuffer.toString();

		} else {
			return fixString(strText, reverse);
		}

	}

	private static String fixString(String strText, boolean reverse) {
		needReverse = reverse;

		char[] txtChars = strText.toCharArray();
		StringBuffer stringBuffer = new StringBuffer(txtChars.length);
		char[] result;
		char currentChar;
		for (int s = 0; s < txtChars.length; s++) {
			currentChar = txtChars;
			if ((currentChar >= 1569 && currentChar <= 1610) || (currentChar >= 1611 && currentChar <= 1618)) {
				s += getArabic(stringBuffer, txtChars, s);
			} else {
				s += getOther(stringBuffer, txtChars, s);
			}
		}
		result = stringBuffer.toString().toCharArray();
		if (needReverse) {
			reverse(result);
		}
		return new String(result);
	}

	private static int arabicCounter = 0;

	private static int getArabic(StringBuffer org, char[] cs, int pos) {

		StringBuffer buffer = new StringBuffer();
		arabicCounter = 0;
		while ((pos + arabicCounter < cs.length)
				&& ((cs[pos + arabicCounter] >= 1569 && cs[pos + arabicCounter] <= 1610) || (cs[pos + arabicCounter] >= 1611 && cs[pos
						+ arabicCounter] <= 1618))) {

			if (cs[pos + arabicCounter] >= 1611 && cs[pos + arabicCounter] <= 1618) {
				char c = getHarkeh(cs[pos + arabicCounter]);
				buffer.append(c);
				arabicCounter++;
				continue;
			}
			buffer.append(getChar(((pos + arabicCounter) == 0 ? (char) 0 : cs[pos + arabicCounter - 1]), cs[pos
					+ arabicCounter],
					((pos + arabicCounter + 1) >= cs.length ? (char) 0 : cs[pos + arabicCounter + 1]), cs, pos
							+ arabicCounter));
			arabicCounter++;

			if ((pos + arabicCounter < cs.length) && (cs[pos + arabicCounter] < 1569 || cs[pos + arabicCounter] > 1610)) {
				if ((pos + arabicCounter + 1 < cs.length)
						&& (cs[pos + arabicCounter + 1] < 1569 || cs[pos + arabicCounter + 1] > 1610)) {
					arabicCounter += getOther(org, cs, pos + arabicCounter);
				} else {
					buffer.append(cs[pos + arabicCounter]);
					arabicCounter++;
				}
			}

		}

		buffer = reverse(buffer);
		org.append(buffer);

		if (arabicCounter > 0) {
			arabicCounter -= 1;
		}
		return arabicCounter;
	}

	private static int getOther(StringBuffer org, char[] cs, int pos) {
		StringBuffer numberBuffer = new StringBuffer();
		int count = 0;
		while ((pos + count < cs.length) && (cs[pos + count] < 1569 || cs[pos + count] > 1610)) {
			numberBuffer.append(cs[pos + count]);
			count++;
		}
		if (needReverse) {
			numberBuffer = reverse(numberBuffer);
		}
		org.append(numberBuffer);

		if (count > 0) {
			count -= 1;
		}
		return count;
	}

	private static char getHarkeh(char org) {
		return (char) harakat[(int) org - 1611][POSITION_ALONE];
	}

	private static void reverse(char[] array) {
		if (array == null) {
			return;
		}
		int i = 0;
		int j = array.length - 1;
		char tmp;
		while (j > i) {
			tmp = array[j];
			array[j] = array;
			array = tmp;
			j--;
			i++;
		}
	}

	private static StringBuffer reverse(StringBuffer buffer) {
		if (buffer == null) {
			return buffer;
		}
		char[] array = buffer.toString().toCharArray();
		reverse(array);
		return new StringBuffer(new String(array));
	}

	private static char getChar(char before, char c, char after, char[] chars, int currentPos) {
		if (c < 1569 || c > 1610) {
			return c;
		}

		boolean isBeforeIsHarkeh = false;
		if (before >= 1611 && before <= 1618) {
			isBeforeIsHarkeh = true;
		}

		boolean isAfterIsHarkeh = false;
		if (after >= 1611 && after <= 1618) {
			isAfterIsHarkeh = true;
		}
		if (c == 1604 && (after == 1570 || after == 1571 || after == 1573 || after == 1575)) {
			arabicCounter++;
			int beforePos = POSITION_END;
			if (before >= 1569 && before <= 1618) {
				beforePos = (!isBeforeIsHarkeh ? letters[(before - COUNT)][5] : harakat[(before - 1611)][5]);
			}

			if (after == 1570) {
				if (beforePos == POSITION_ALONE || beforePos == POSITION_END) {
					return (char) 65269;
				} else {
					return (char) 65270;
				}
			}
			if (after == 1571) {
				if (beforePos == POSITION_ALONE || beforePos == POSITION_END) {
					return (char) 65271;
				} else {
					return (char) 65272;
				}
			}
			if (after == 1573) {// إ
				if (beforePos == POSITION_ALONE || beforePos == POSITION_END) {
					return (char) 65273;
				} else {
					return (char) 65274;
				}
			}
			if (after == 1575) {
				if (beforePos == POSITION_ALONE || beforePos == POSITION_END) {
					return (char) 65275;
				} else {
					return (char) 65276;
				}
			}
		}

		if (c > 1599) {
			c -= DIFF;
		}
		if (after > 1599 && after <= 1610) {
			after -= DIFF;
		}

		if (before > 1599 && before <= 1610) {
			before -= DIFF;
		}

		int position = POSITION_ALONE;

		if (before < 1569 || before > 1618) {
			position = POSITION_START;
		}
		if ((before < 1569 || before > 1618) && (after < 1569 || after > 1618)) {
			position = POSITION_ALONE;
		}
		if (before >= 1569 && before <= 1618 && after >= 1569 && after <= 1618) {
			position = POSITION_MIDDLE;
			int beforePos = (!isBeforeIsHarkeh ? letters[(before - COUNT)][5] : harakat[(before - 1611)][5]);
			if (beforePos == POSITION_END) {
				position = POSITION_START;
				if (isAfterIsHarkeh) {
					if ((currentPos + 2) >= chars.length || (chars[(currentPos + 2)] < 1569)
							|| (chars[(currentPos + 2)] > 1618)) {
						position = POSITION_ALONE;// needs to add support for 2
													// harakeh in same time
					}
				}
			}

		}
		if (before >= 1569 && before <= 1618 && (after < 1569 || after > 1618)) {
			position = POSITION_END;
			int beforePos = (!isBeforeIsHarkeh ? letters[(before - COUNT)][5] : harakat[(before - 1611)][5]);
			if (beforePos == POSITION_END) {
				position = POSITION_ALONE;
			}

		}
		return (char) letters[c - COUNT][position];

	}
}

كيفية الاستخدام:

import com.mosh.arabicfix;

---

String s= "محمد عرسان";
s=ArabicMosh.getFix(s, true);

--

Reveres =true اذا كنت تتعامل مع Views

false اذا كنت تستخدم Canvas

---

النسخة 1:

- تدعم الحركات (حركة واحدة فقط لكل حرف) من المخطط له دعم اكثر من حركة في نفس الوقت

تم تعديل هذه المشاركة بواسطة .S.T.A.L.K.E.R في 7 ديسمبر 2011 في 21:32

5
#2

مكتبة مفيدة فعلاً. أنا استعمل في تطبيقي على الأندرويد مكتبة كانت مطروحة من قبل عبد العزيز الحسين (اذا اسعفتني الذاكرة باسمه)، وهي تعمل بشكل فعّال ولكن المشكلة أنها لا تدعم الخطوط العربية، وإنما خط واحد فقط، فهل تدعم هذه المكتبة خطوطاً متعددة أم لا؟

WebColorsLogo.png

#3

محمد هل تتكلم عن مشكلة التقطيع المعتادة

أم أن هناك مشكلة لا أعرفها؟

إن كانت مشكلة جديدة ما هي الأجهزة التي تعانيها إن كان هناك شريحة معينة

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#4
khr2003 كتب:

مكتبة مفيدة فعلاً. أنا استعمل في تطبيقي على الأندرويد مكتبة كانت مطروحة من قبل عبد العزيز الحسين (اذا اسعفتني الذاكرة باسمه)، وهي تعمل بشكل فعّال ولكن المشكلة أنها لا تدعم الخطوط العربية، وإنما خط واحد فقط، فهل تدعم هذه المكتبة خطوطاً متعددة أم لا؟

- هل من الممكن فحص المكتبة التي تحدثت عنها ان كانت تدعم الحركات؟

- بالنسبة للخطوط، اظن هذه و المكتبة التي تحدثت انت عنها تدعم الخطوط، لكن يظهر الخط العادي بسبب ان لكل حرف رقم مقابل له في الخط، و الارقام هنا تمثل ال Unicode لذلك لن تطابق الارقام الاعتيادية، لحل هذه المشكلة عليك بتعديل الخطوط نفسها و ارقامها (لم اجربها لكن شبه متأكد)

علاء الصالحي كتب:

محمد هل تتكلم عن مشكلة التقطيع المعتادة

أم أن هناك مشكلة لا أعرفها؟

إن كانت مشكلة جديدة ما هي الأجهزة التي تعانيها إن كان هناك شريحة معينة

تحياتي

- نعم مشكلة التقطيع المعتادة

- قد تكون هذه المكتبة لا تضيف الجديد، لكن بحثت عن مكتبات، جميعها لا تدعم الحركات، او ان تداخلت اكثر من لغة يتشوه النص، و بنفس الوقت اغلبها بطيئة

قم بفحص سرعة هذا الكود ستجد انه سريع جدا مقارنة بغيره (شبك 8000 حرف في 1 ملي ثانية على هاتف 1000MHz)

#5

شكراً ، مكتبة مهمة . أستخدم مكتبة ( المبرمج عبدالعزيز حسين ) ، ولكن لاحظت فيها بعض الأخطاء خصوصاً عندما يتم استخدام مزيج من الأرقام مع الحروف العربية الخ .. في بعض الخطوط.

سأجرب مكتبتك ، وأقترح إضافتها تحت source control معين مثل git ، في github حتى لا تموت المكتبة مع الوقت ،

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#6
Abdullah.Alshammeri كتب:

شكراً ، مكتبة مهمة . أستخدم مكتبة ( المبرمج عبدالعزيز حسين ) ، ولكن لاحظت فيها بعض الأخطاء خصوصاً عندما يتم استخدام مزيج من الأرقام مع الحروف العربية الخ .. في بعض الخطوط.

سأجرب مكتبتك ، وأقترح إضافتها تحت source control معين مثل git ، في github حتى لا تموت المكتبة مع الوقت ،

اتمنى ان تقوم بتجربتها٫ انتظر ردك

#7

هل تشرح لي آلية الحل؟

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#8
علاء الصالحي كتب:

هل تشرح لي آلية الحل؟

تحياتي

تأخذ قيمة كل حرف في النص، و تأخذ موقعه و تضع بدل له قيمة الحرف المقابل له في ال Unicode

انا حاليا في العمل، ان حصل عندي وقت مناسب، سوف احاول شرحها بشكل افضل

تم تعديل هذه المشاركة بواسطة .S.T.A.L.K.E.R في 11 ديسمبر 2011 في 10:43

#9

يا اخوان ارجو منكم تجربتها :)

اريد ان اعرف اكثر عدد اجهزة تقوم بتغطيتها

Please :blush:

#10

السلام عليكم ورحمة الله وبركاته

تحية طيبة على هذا المجهود الرائع

اخي الكريم ممكن طلب بسيط : الا وهو ممكن ان يشرح اكثر حول كيفية استخدام هذا الملف لمعالجة تقطع اللغة العربية حيث اني جديد في هذا المجال فلم استوعب مجمل الذي قلته . ارجو ان يتسع صدرك لطلبي هذا .

ولك جزيل الشكر والتقدير

سؤال اخر : لدي جهاز droid incredible 2 تظهر فيه اللغة العربية متقطعة ايضا ، هل هذا الملف سوف يحل هذه المشكلة فيه ؟

شكرا مقدما لتفهمك ولسعة صدرك

مستجد حائر

#11

انصحك بعدم استخدام الكود الحالي

هناك مشكلة فيه

قمت باصلاحها و سوف اقوم بارفاق الكود الجديد

---

بالنسبة لجهازك

هذا الكود مخصص للاستخدام ضمن البرامج

ولا يقوم باصلاح العربية على مستوى الجهاز

مواضيع مشابهة