bug 84380 Need a component that generates thai presentation forms
Updates for *extensions*/ctl for prabhat@Sun, r=ftank for check-in A Incorporate frank's review fixes (08/07) B Bugfix in TIS620Encoder C Fix memory corruption D Makefile changes in pangoLite directory to install pango.modules git-svn-id: svn://10.0.0.236/trunk@103086 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
d9fd93b244
commit
1496fa7bc3
@ -30,9 +30,6 @@
|
||||
#include "nsISupports.h"
|
||||
#include "nsCtlCIID.h"
|
||||
|
||||
#include "pango-types.h"
|
||||
#include "pango-glyph.h"
|
||||
|
||||
/*
|
||||
* nsILE Interface declaration
|
||||
*/
|
||||
@ -41,13 +38,16 @@ public:
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILE_IID)
|
||||
|
||||
NS_IMETHOD GetPresentationForm(const PRUnichar*, PRUint32, PangoAnalysis*,
|
||||
PangoGlyphString*) = 0;
|
||||
|
||||
NS_IMETHOD GetPresentationForm(const PRUnichar*, PRUint32,
|
||||
const char*, char*, PRSize*) = 0;
|
||||
|
||||
NS_IMETHOD GetPresentationForm(const PRUnichar*, PRUint32,
|
||||
const char*, PRUint32*, PRSize*) = 0;
|
||||
NS_IMETHOD PrevCluster(const PRUnichar*, PRUint32,
|
||||
const PRInt32, PRInt32*) = 0;
|
||||
|
||||
NS_IMETHOD NextCluster(const PRUnichar*, PRUint32,
|
||||
const PRInt32, PRInt32*) = 0;
|
||||
|
||||
NS_IMETHOD GetRangeOfCluster(const PRUnichar*, PRUint32,
|
||||
const PRInt32, PRInt32*, PRInt32*) = 0;
|
||||
};
|
||||
#endif // nsILE_h
|
||||
|
||||
@ -46,14 +46,14 @@ PRInt32 g_InstanceCount = 0;
|
||||
PRInt32 g_LockCount = 0;
|
||||
|
||||
NS_IMPL_NSUCONVERTERREGSELF
|
||||
NS_UCONV_REG_UNREG(nsUnicodeToTIS620, "Unicode", "tis620", NS_UNICODETOTIS620_CID);
|
||||
NS_UCONV_REG_UNREG(nsUnicodeToTIS620, "Unicode", "tis620-2", NS_UNICODETOTIS620_CID);
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUnicodeToTIS620);
|
||||
|
||||
static nsModuleComponentInfo components[] =
|
||||
{
|
||||
{ ENCODER_NAME_BASE "tis620" , NS_UNICODETOTIS620_CID,
|
||||
NS_UNICODEENCODER_CONTRACTID_BASE "tis620",
|
||||
{ ENCODER_NAME_BASE "tis620-2" , NS_UNICODETOTIS620_CID,
|
||||
NS_UNICODEENCODER_CONTRACTID_BASE "tis620-2",
|
||||
nsUnicodeToTIS620Constructor,
|
||||
nsUnicodeToTIS620RegSelf, nsUnicodeToTIS620UnRegSelf },
|
||||
{ "Unicode Layout Engine", NS_ULE_CID, NS_ULE_PROGID,
|
||||
|
||||
@ -23,9 +23,6 @@
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h> /* isspace */
|
||||
|
||||
#include "nsULE.h"
|
||||
#include "nsString.h"
|
||||
|
||||
@ -34,6 +31,14 @@
|
||||
#include "pango-modules.h"
|
||||
#include "pango-utils.h"
|
||||
|
||||
#define CLEAN_RUN \
|
||||
aPtr = aRun.head; \
|
||||
for (int ct=0; (ct < aRun.numRuns); ct++) { \
|
||||
aTmpPtr = aPtr; \
|
||||
aPtr = aPtr->next; \
|
||||
delete(aTmpPtr); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Start of nsULE Public Functions
|
||||
*/
|
||||
@ -55,7 +60,7 @@ nsULE::GetShaper(const PRUnichar *inBuf,
|
||||
{
|
||||
PangoEngineShape *aEngine = NULL;
|
||||
PangoMap *aMap = NULL;
|
||||
guint engine_type_id = 0, render_type_id = 0;
|
||||
guint engine_type_id = 0, render_type_id = 0;
|
||||
PRUnichar wc = inBuf[0];
|
||||
|
||||
if ((inBuf == (PRUnichar*)NULL) || (aLength <= 0)) {
|
||||
@ -75,38 +80,93 @@ nsULE::GetShaper(const PRUnichar *inBuf,
|
||||
return aEngine;
|
||||
}
|
||||
|
||||
// Analysis needs to have valid direction and font charset
|
||||
NS_IMETHODIMP
|
||||
nsULE::GetPresentationForm(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
PangoAnalysis *aAnalysis,
|
||||
PangoGlyphString *aGlyphs)
|
||||
PRInt32
|
||||
nsULE::SeparateScript(const PRUnichar* aSrcBuf,
|
||||
PRInt32 aSrcLen,
|
||||
textRunList *aRunList)
|
||||
{
|
||||
PangoEngineShape *aShaper = aAnalysis->shape_engine;
|
||||
PRSize inLen = 0;
|
||||
char *utf8Str = NULL;
|
||||
int ct = 0, start = 0;
|
||||
PRBool isCtl = PR_FALSE;
|
||||
struct textRun *tmpChunk;
|
||||
PangoEngineShape *aEngine = NULL;
|
||||
PangoMap *aMap = NULL;
|
||||
guint engine_type_id = 0, render_type_id = 0;
|
||||
|
||||
if (aShaper != NULL) {
|
||||
engine_type_id = g_quark_from_static_string(PANGO_ENGINE_TYPE_SHAPE);
|
||||
render_type_id = g_quark_from_static_string(PANGO_RENDER_TYPE_X);
|
||||
aMap = pango_find_map("en_US", engine_type_id, render_type_id);
|
||||
|
||||
for (ct = 0; ct < aSrcLen;) {
|
||||
tmpChunk = new textRun;
|
||||
|
||||
if (aRunList->numRuns == 0)
|
||||
aRunList->head = tmpChunk;
|
||||
else
|
||||
aRunList->cur->next = tmpChunk;
|
||||
aRunList->cur = tmpChunk;
|
||||
aRunList->numRuns++;
|
||||
|
||||
nsAutoString strBuf(aString);
|
||||
tmpChunk->start = &aSrcBuf[ct];
|
||||
start = ct;
|
||||
aEngine = (PangoEngineShape*)
|
||||
pango_map_get_engine(aMap, (PRUint32)aSrcBuf[ct]);
|
||||
isCtl = (aEngine != NULL);
|
||||
|
||||
// Convert Unicode string to UTF8 and store in buffer
|
||||
utf8Str = strBuf.ToNewUTF8String();
|
||||
inLen = strlen(utf8Str);
|
||||
if (isCtl) {
|
||||
while (isCtl && ct < aSrcLen) {
|
||||
aEngine = (PangoEngineShape*)
|
||||
pango_map_get_engine(aMap, (PRUint32)aSrcBuf[ct]);
|
||||
isCtl = (aEngine != NULL);
|
||||
if (isCtl)
|
||||
ct++;
|
||||
}
|
||||
tmpChunk->isOther = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
while (!isCtl && ct < aSrcLen) {
|
||||
aEngine = (PangoEngineShape*)
|
||||
pango_map_get_engine(aMap, (PRUint32)aSrcBuf[ct]);
|
||||
isCtl = (aEngine != NULL);
|
||||
if (!isCtl)
|
||||
ct++;
|
||||
}
|
||||
tmpChunk->isOther = PR_TRUE;
|
||||
}
|
||||
|
||||
tmpChunk->length = ct - start;
|
||||
}
|
||||
return (PRInt32)aRunList->numRuns;
|
||||
}
|
||||
|
||||
aShaper->script_shape(aAnalysis->fontCharset, utf8Str, inLen,
|
||||
aAnalysis, aGlyphs);
|
||||
nsMemory::Free(utf8Str);
|
||||
// Analysis needs to have valid direction and font charset
|
||||
PRInt32
|
||||
nsULE::GetRawCtlData(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
PangoGlyphString *aGlyphs)
|
||||
{
|
||||
PangoEngineShape *aShaper = GetShaper(aString, aLength, (const char*)NULL);
|
||||
PangoAnalysis aAnalysis;
|
||||
|
||||
aAnalysis.shape_engine = aShaper;
|
||||
aAnalysis.aDir = PANGO_DIRECTION_LTR;
|
||||
// In future fontCharset hard-coding should be removed
|
||||
aAnalysis.fontCharset = strdup("tis620-2");
|
||||
|
||||
if (aShaper != NULL) {
|
||||
aShaper->script_shape(aAnalysis.fontCharset, aString, aLength,
|
||||
&aAnalysis, aGlyphs);
|
||||
nsMemory::Free(aAnalysis.fontCharset);
|
||||
}
|
||||
else {
|
||||
/* No Shaper - Copy Input to output */
|
||||
return 0;
|
||||
}
|
||||
return NS_OK;
|
||||
return aGlyphs->num_glyphs;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsULE::GetPresentationForm(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aLength,
|
||||
const char *fontCharset,
|
||||
char *aGlyphs,
|
||||
PRSize *aOutLength)
|
||||
@ -114,27 +174,15 @@ nsULE::GetPresentationForm(const PRUnichar *aString,
|
||||
PangoEngineShape *aShaper = GetShaper(aString, aLength, (const char*)NULL);
|
||||
PangoAnalysis aAnalysis;
|
||||
PangoGlyphString *tmpGlyphs = pango_glyph_string_new();
|
||||
PRSize inLen = 0;
|
||||
int aSize = 0;
|
||||
char *utf8Str = NULL;
|
||||
|
||||
aAnalysis.shape_engine = aShaper;
|
||||
aAnalysis.aDir = PANGO_DIRECTION_LTR;
|
||||
aAnalysis.fontCharset = (char*)fontCharset;
|
||||
|
||||
if (aShaper != NULL) {
|
||||
|
||||
nsAutoString strBuf;
|
||||
strBuf.Assign(aString, aLength);
|
||||
|
||||
// Convert Unicode string to UTF8 and store in buffer
|
||||
utf8Str = NULL;
|
||||
utf8Str = strBuf.ToNewUTF8String();
|
||||
inLen = strlen(utf8Str);
|
||||
|
||||
aShaper->script_shape(fontCharset, utf8Str, inLen,
|
||||
&aAnalysis, tmpGlyphs);
|
||||
nsMemory::Free(utf8Str);
|
||||
if (aShaper != NULL) {
|
||||
aShaper->script_shape(fontCharset, aString, aLength,
|
||||
&aAnalysis, tmpGlyphs);
|
||||
if (tmpGlyphs->num_glyphs > 0) {
|
||||
// Note : Does NOT handle 2 byte fonts
|
||||
aSize = tmpGlyphs->num_glyphs;
|
||||
@ -151,50 +199,246 @@ nsULE::GetPresentationForm(const PRUnichar *aString,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsULE::GetPresentationForm(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const char *fontCharset,
|
||||
PRUint32 *aGlyphs,
|
||||
PRSize *aOutLength)
|
||||
// This routine returns the string index of the next cluster
|
||||
// corresponding to the cluster at string index 'aIndex'
|
||||
// Note : Index returned is the end-offset
|
||||
// Cursor position iterates between 0 and (position - 1)
|
||||
NS_IMETHODIMP
|
||||
nsULE::NextCluster(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const PRInt32 aIndex,
|
||||
PRInt32 *nextOffset)
|
||||
{
|
||||
PangoEngineShape *aShaper = GetShaper(aString, aLength, (const char*)NULL);
|
||||
PangoAnalysis aAnalysis;
|
||||
PangoGlyphString *tmpGlyphs = pango_glyph_string_new();
|
||||
PRSize inLen = 0;
|
||||
int aSize = 0;
|
||||
char *utf8Str = NULL;
|
||||
textRunList aRun;
|
||||
textRun *aPtr, *aTmpPtr;
|
||||
PRInt32 aStrCt=0;
|
||||
PRBool isBoundary=PR_FALSE;
|
||||
PangoGlyphString *aGlyphData=pango_glyph_string_new();
|
||||
|
||||
if (aIndex >= aLength-1) {
|
||||
*nextOffset = aLength; // End
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aAnalysis.shape_engine = aShaper;
|
||||
aAnalysis.aDir = PANGO_DIRECTION_LTR;
|
||||
aAnalysis.fontCharset = (char*)fontCharset;
|
||||
aRun.numRuns = 0;
|
||||
SeparateScript(aString, aLength, &aRun);
|
||||
|
||||
if (aShaper != NULL) {
|
||||
aPtr = aRun.head;
|
||||
for (int i=0; (i < aRun.numRuns); i++) {
|
||||
PRInt32 runLen=0;
|
||||
|
||||
runLen = aPtr->length;
|
||||
|
||||
nsAutoString strBuf;
|
||||
strBuf.Assign(aString, aLength);
|
||||
if ((aStrCt+runLen) < aIndex) /* Skip Run and continue */
|
||||
aStrCt += runLen;
|
||||
|
||||
// Convert Unicode string to UTF8 and store in buffer
|
||||
utf8Str = NULL;
|
||||
utf8Str = strBuf.ToNewUTF8String();
|
||||
inLen = strlen(utf8Str);
|
||||
|
||||
aShaper->script_shape(fontCharset, utf8Str, inLen,
|
||||
&aAnalysis, tmpGlyphs);
|
||||
nsMemory::Free(utf8Str);
|
||||
if (tmpGlyphs->num_glyphs > 0) {
|
||||
aSize = tmpGlyphs->num_glyphs;
|
||||
// if (*aOutLength < aSize)
|
||||
// trouble
|
||||
for (int i = 0; i < aSize; i++)
|
||||
aGlyphs[i] = tmpGlyphs->glyphs[i].glyph;
|
||||
else if ((aStrCt+runLen) == aIndex) {
|
||||
isBoundary = PR_TRUE;/* Script Boundary - Skip a cell in next iteration */
|
||||
aStrCt += runLen;
|
||||
}
|
||||
*aOutLength = (PRSize)aSize;
|
||||
|
||||
else {
|
||||
if (aPtr->isOther) {
|
||||
*nextOffset = aIndex+1;
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
else { /* CTL Cell Movement */
|
||||
PRInt32 j, startCt, beg, end, numCur;
|
||||
|
||||
startCt=aStrCt;
|
||||
GetRawCtlData(aPtr->start, runLen, aGlyphData);
|
||||
|
||||
numCur=beg=0;
|
||||
for (j=0; j<aGlyphData->num_glyphs; j++) {
|
||||
while ((!aGlyphData->glyphs[j].attr.is_cluster_start) &&
|
||||
j<aGlyphData->num_glyphs)
|
||||
j++;
|
||||
if (j>=aGlyphData->num_glyphs)
|
||||
end=runLen;
|
||||
else
|
||||
end=aGlyphData->log_clusters[j];
|
||||
numCur += end-beg;
|
||||
if (startCt+numCur > aIndex)
|
||||
break;
|
||||
else
|
||||
beg=end;
|
||||
}
|
||||
|
||||
// Found Cluster - Start of Next == End Of Current
|
||||
*nextOffset = startCt+numCur;
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
aPtr = aPtr->next;
|
||||
}
|
||||
else {
|
||||
// Should not reach here are checks are set
|
||||
// in upper layers
|
||||
/* Alternately, if no Shaper - Copy Input to output */
|
||||
}
|
||||
return NS_OK;
|
||||
/* UNUSED */
|
||||
CLEAN_RUN
|
||||
}
|
||||
|
||||
// This routine returns the end-offset of the previous block
|
||||
// corresponding to string index 'aIndex'
|
||||
NS_IMETHODIMP
|
||||
nsULE::PrevCluster(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const PRInt32 aIndex,
|
||||
PRInt32 *prevOffset)
|
||||
{
|
||||
textRunList aRun;
|
||||
textRun *aPtr, *aTmpPtr;
|
||||
PRInt32 aStrCt=0, startCt=0, glyphct=0;
|
||||
PangoGlyphString *aGlyphData=pango_glyph_string_new();
|
||||
|
||||
if (aIndex<=1) {
|
||||
*prevOffset=0; // End
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aRun.numRuns=0;
|
||||
SeparateScript(aString, aLength, &aRun);
|
||||
|
||||
// Get the index of current cluster
|
||||
aPtr=aRun.head;
|
||||
for (int i=0; i<aRun.numRuns; i++) {
|
||||
PRInt32 runLen=aPtr->length;
|
||||
|
||||
if ((aStrCt+runLen) < aIndex) /* Skip Run */
|
||||
aStrCt += runLen;
|
||||
|
||||
else if ((aStrCt+runLen) == aIndex) {
|
||||
if (aPtr->isOther) {
|
||||
*prevOffset=aIndex-1;
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
else { /* Move back a cluster */
|
||||
startCt=aStrCt;
|
||||
GetRawCtlData(aPtr->start, runLen, aGlyphData);
|
||||
|
||||
glyphct=aGlyphData->num_glyphs-1;
|
||||
while (glyphct > 0) {
|
||||
if (aGlyphData->glyphs[glyphct].attr.is_cluster_start) {
|
||||
*prevOffset=startCt+aGlyphData->log_clusters[glyphct];
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
--glyphct;
|
||||
}
|
||||
*prevOffset=startCt;
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (aPtr->isOther) {
|
||||
*prevOffset=aIndex-1;
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
PRInt32 j,beg,end,numPrev,numCur;
|
||||
|
||||
startCt=aStrCt;
|
||||
GetRawCtlData(aPtr->start, runLen, aGlyphData);
|
||||
|
||||
numPrev=numCur=beg=0;
|
||||
for (j=1; j<aGlyphData->num_glyphs; j++) {
|
||||
while ((!aGlyphData->glyphs[j].attr.is_cluster_start) &&
|
||||
j<aGlyphData->num_glyphs)
|
||||
j++;
|
||||
if (j>=aGlyphData->num_glyphs)
|
||||
end=runLen;
|
||||
else
|
||||
end=aGlyphData->log_clusters[j];
|
||||
numCur += end-beg;
|
||||
if (numCur+startCt >= aIndex)
|
||||
break;
|
||||
else {
|
||||
beg=end;
|
||||
numPrev=numCur;
|
||||
}
|
||||
}
|
||||
*prevOffset=startCt+numPrev;
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
aPtr=aPtr->next;
|
||||
}
|
||||
/* UNUSED */
|
||||
CLEAN_RUN
|
||||
}
|
||||
|
||||
// This routine returns the end-offset of the previous block
|
||||
// corresponding to string index 'aIndex'
|
||||
NS_IMETHODIMP
|
||||
nsULE::GetRangeOfCluster(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const PRInt32 aIndex,
|
||||
PRInt32 *aStart,
|
||||
PRInt32 *aEnd)
|
||||
{
|
||||
textRunList aRun;
|
||||
textRun *aPtr, *aTmpPtr;
|
||||
PRInt32 aStrCt=0, startCt=0,j;
|
||||
PangoGlyphString *aGlyphData=pango_glyph_string_new();
|
||||
|
||||
*aStart = *aEnd = 0;
|
||||
aRun.numRuns=0;
|
||||
SeparateScript(aString, aLength, &aRun);
|
||||
|
||||
// Get the index of current cluster
|
||||
aPtr=aRun.head;
|
||||
for (int i=0; i<aRun.numRuns; i++) {
|
||||
PRInt32 runLen=aPtr->length;
|
||||
|
||||
if ((aStrCt+runLen) < aIndex) /* Skip Run */
|
||||
aStrCt += runLen;
|
||||
else {
|
||||
if (aPtr->isOther) {
|
||||
*aStart = *aEnd = aIndex;
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
PRInt32 beg,end,numCur;
|
||||
|
||||
startCt=aStrCt;
|
||||
GetRawCtlData(aPtr->start, runLen, aGlyphData);
|
||||
|
||||
numCur=beg=0;
|
||||
for (j=1; j<aGlyphData->num_glyphs; j++) {
|
||||
while ((!aGlyphData->glyphs[j].attr.is_cluster_start) &&
|
||||
j<aGlyphData->num_glyphs)
|
||||
j++;
|
||||
if (j>=aGlyphData->num_glyphs)
|
||||
end=runLen;
|
||||
else
|
||||
end=aGlyphData->log_clusters[j];
|
||||
|
||||
numCur += end-beg;
|
||||
if (numCur+startCt >= aIndex)
|
||||
break;
|
||||
else
|
||||
beg=end;
|
||||
}
|
||||
|
||||
*aEnd = startCt+numCur;
|
||||
if (beg == 0)
|
||||
*aStart = beg;
|
||||
else {
|
||||
if ((end-beg) == 1) /* n=n Condition */
|
||||
*aStart = *aEnd;
|
||||
else
|
||||
*aStart = startCt+beg+1; /* Maintain Mozilla Convention */
|
||||
}
|
||||
CLEAN_RUN
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
aPtr=aPtr->next;
|
||||
}
|
||||
CLEAN_RUN
|
||||
/* UNUSED */
|
||||
}
|
||||
|
||||
@ -32,6 +32,22 @@
|
||||
#include "nsCtlCIID.h"
|
||||
#include "nsILE.h"
|
||||
|
||||
#include "pango-types.h"
|
||||
#include "pango-glyph.h"
|
||||
|
||||
struct textRun {
|
||||
PRInt32 length; /* Length of a chunk */
|
||||
PRBool isOther; /* Outside the range */
|
||||
const PRUnichar *start; /* Address of start offset */
|
||||
struct textRun *next;
|
||||
};
|
||||
|
||||
struct textRunList {
|
||||
struct textRun *head;
|
||||
struct textRun *cur;
|
||||
PRInt32 numRuns;
|
||||
};
|
||||
|
||||
/* Class nsULE : Declaration */
|
||||
class nsULE : public nsILE {
|
||||
public:
|
||||
@ -48,22 +64,29 @@ public:
|
||||
// A> API used to generate Presentation Forms based on supported fonts
|
||||
// B> API used by common text operations such as cursor positioning
|
||||
// and selection
|
||||
NS_IMETHOD GetPresentationForm(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
PangoAnalysis *aAnalysis,
|
||||
PangoGlyphString *aGlyphs);
|
||||
|
||||
NS_IMETHOD GetPresentationForm(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aLength,
|
||||
const char *fontCharset,
|
||||
char *aGlyphs,
|
||||
PRSize *aOutLength);
|
||||
|
||||
NS_IMETHOD GetPresentationForm(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const char *fontCharset,
|
||||
PRUint32 *aGlyphs,
|
||||
PRSize *aOutLength);
|
||||
NS_IMETHOD PrevCluster(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const PRInt32 aIndex,
|
||||
PRInt32 *prevOffset);
|
||||
|
||||
NS_IMETHOD NextCluster(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const PRInt32 aIndex,
|
||||
PRInt32 *nextOffset);
|
||||
|
||||
NS_IMETHOD GetRangeOfCluster(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
const PRInt32 aIndex,
|
||||
PRInt32 *aStart,
|
||||
PRInt32 *aEnd);
|
||||
|
||||
private:
|
||||
|
||||
// Housekeeping Members
|
||||
@ -71,5 +94,9 @@ public:
|
||||
void CleanUp(void);
|
||||
|
||||
PangoEngineShape* GetShaper(const PRUnichar *, PRUint32, const char *);
|
||||
|
||||
PRInt32 GetRawCtlData(const PRUnichar*, PRUint32, PangoGlyphString*);
|
||||
|
||||
PRInt32 SeparateScript(const PRUnichar*, PRInt32, textRunList*);
|
||||
};
|
||||
#endif /* nsULE_H */
|
||||
|
||||
@ -22,19 +22,24 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h> /* isspace */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsICharsetConverterManager2.h"
|
||||
#include "nsILanguageAtomService.h"
|
||||
#include "nsCtlCIID.h"
|
||||
#include "nsILE.h"
|
||||
#include "nsULE.h"
|
||||
#include "nsUnicodeToTIS620.h"
|
||||
|
||||
static NS_DEFINE_CID(kCharSetManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
|
||||
// XPCOM stuff
|
||||
NS_IMPL_ADDREF(nsUnicodeToTIS620);
|
||||
NS_IMPL_RELEASE(nsUnicodeToTIS620);
|
||||
|
||||
int
|
||||
PRInt32
|
||||
nsUnicodeToTIS620::Itemize(const PRUnichar* aSrcBuf, PRInt32 aSrcLen, textRunList *aRunList)
|
||||
{
|
||||
int ct = 0, start = 0;
|
||||
@ -78,14 +83,13 @@ nsUnicodeToTIS620::Itemize(const PRUnichar* aSrcBuf, PRInt32 aSrcLen, textRunLis
|
||||
|
||||
tmpChunk->length = ct - start;
|
||||
}
|
||||
return (int)aRunList->numRuns;
|
||||
return (PRInt32)aRunList->numRuns;
|
||||
}
|
||||
|
||||
nsresult nsUnicodeToTIS620::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
if (NULL == aInstancePtr)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
@ -123,11 +127,28 @@ NS_IMETHODIMP nsUnicodeToTIS620::SetOutputErrorBehavior(PRInt32 aBehavior,
|
||||
|
||||
nsUnicodeToTIS620::nsUnicodeToTIS620()
|
||||
{
|
||||
static NS_DEFINE_CID(kLECID, NS_ULE_CID);
|
||||
nsresult rv;
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mCtlObj = do_CreateInstance(kLECID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
#ifdef DEBUG_prabhat
|
||||
// No other error handling needed here since we
|
||||
// handle absence of mCtlObj in Convert
|
||||
printf("ERROR: Cannot create instance of component " NS_ULE_PROGID " [%x].\n",
|
||||
rv);
|
||||
#endif
|
||||
NS_WARNING("Thai Text Layout Will Not Be Supported\n");
|
||||
mCtlObj = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsUnicodeToTIS620::~nsUnicodeToTIS620()
|
||||
{
|
||||
// Maybe convert nsILE to a service
|
||||
// No NS_IF_RELEASE(mCtlObj) of nsCOMPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -135,44 +156,74 @@ nsUnicodeToTIS620::~nsUnicodeToTIS620()
|
||||
* Note: ConversionBufferFullException is not handled
|
||||
* since this class is only used for character display.
|
||||
*/
|
||||
NS_IMETHODIMP nsUnicodeToTIS620::Convert(const PRUnichar * input,
|
||||
PRInt32 * aSrcLength,
|
||||
char * output, PRInt32 * aDestLength)
|
||||
NS_IMETHODIMP nsUnicodeToTIS620::Convert(const PRUnichar* input,
|
||||
PRInt32* aSrcLength,
|
||||
char* output,
|
||||
PRInt32* aDestLength)
|
||||
{
|
||||
int i = 0;
|
||||
nsCOMPtr<nsILE> mCtlObj;
|
||||
static NS_DEFINE_CID(kLECID, NS_ULE_CID);
|
||||
nsresult rv;
|
||||
textRunList txtRuns;
|
||||
textRun *aPtr, *aTmpPtr;
|
||||
textRunList txtRuns;
|
||||
textRun *aPtr, *aTmpPtr;
|
||||
|
||||
#ifdef DEBUG_prabhath_no_shaper
|
||||
printf("Debug/Test Case of No thai pango shaper Object\n");
|
||||
// Comment out mCtlObj == nsnull for test purposes
|
||||
#endif
|
||||
|
||||
if (mCtlObj == nsnull) {
|
||||
nsICharsetConverterManager2* gCharSetManager = nsnull;
|
||||
nsIUnicodeEncoder* gDefaultTISConverter = nsnull;
|
||||
nsresult res;
|
||||
nsServiceManager::GetService(kCharSetManagerCID,
|
||||
NS_GET_IID(nsICharsetConverterManager2), (nsISupports**) &gCharSetManager);
|
||||
|
||||
// No question of starting the conversion from an offset
|
||||
charOff = byteOff = 0;
|
||||
#ifdef DEBUG_prabhath
|
||||
printf("ERROR: No CTL IMPLEMENTATION - Default Thai Conversion");
|
||||
// CP874 is the default converter for thai ;
|
||||
// In case mCtlObj is absent (no CTL support), use it to convert.
|
||||
#endif
|
||||
|
||||
mCtlObj = do_CreateInstance(kLECID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
printf("ERROR: Cannot create instance of component " NS_ULE_PROGID " [%x].\n",
|
||||
rv);
|
||||
printf("Thai Text Layout Will Not Be Supported\n");
|
||||
if (!gCharSetManager)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAtom> charset = getter_AddRefs(NS_NewAtom("TIS-620"));
|
||||
if (charset)
|
||||
res = gCharSetManager->GetUnicodeEncoder(charset, &gDefaultTISConverter);
|
||||
else {
|
||||
NS_IF_RELEASE(gCharSetManager);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!gDefaultTISConverter) {
|
||||
NS_WARNING("cannot get default converter for tis-620");
|
||||
NS_IF_RELEASE(gCharSetManager);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
gDefaultTISConverter->Convert(input, aSrcLength, output, aDestLength);
|
||||
NS_IF_RELEASE(gCharSetManager);
|
||||
NS_IF_RELEASE(gDefaultTISConverter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
txtRuns.numRuns = 0;
|
||||
// CTLized shaping conversion starts here
|
||||
// No question of starting the conversion from an offset
|
||||
mCharOff = mByteOff = 0;
|
||||
|
||||
txtRuns.numRuns = 0;
|
||||
Itemize(input, *aSrcLength, &txtRuns);
|
||||
|
||||
aPtr = txtRuns.head;
|
||||
for (i = 0; i < txtRuns.numRuns; i++) {
|
||||
// char *tmpDestBuf = output + byteOff;
|
||||
// PRInt32 tmpDestLen = *aDestLength - byteOff;
|
||||
for (int i = 0; i < txtRuns.numRuns; i++) {
|
||||
PRInt32 tmpSrcLen = aPtr->length;
|
||||
|
||||
if (aPtr->isOther) {
|
||||
// PangoThaiShaper does not handle ASCII + thai in same shaper
|
||||
for (i = 0; i < tmpSrcLen; i++)
|
||||
output[i + byteOff] = (char)(*(aPtr->start + i));
|
||||
byteOff += tmpSrcLen;
|
||||
for (int j = 0; j < tmpSrcLen; j++)
|
||||
output[j + mByteOff] = (char)(*(aPtr->start + j));
|
||||
mByteOff += tmpSrcLen;
|
||||
}
|
||||
else {
|
||||
PRSize outLen = *aDestLength;
|
||||
PRSize outLen = *aDestLength - mByteOff;
|
||||
// Charset tis620-0, tis620.2533-1, tis620.2529-1 & iso8859-11
|
||||
// are equivalent and have the same presentation forms
|
||||
|
||||
@ -180,24 +231,21 @@ NS_IMETHODIMP nsUnicodeToTIS620::Convert(const PRUnichar * input,
|
||||
// in Windows-Stye as it is the current defacto-standard for the
|
||||
// presentation of thai content
|
||||
mCtlObj->GetPresentationForm(aPtr->start, tmpSrcLen, "tis620-2",
|
||||
output, &outLen);
|
||||
byteOff += outLen;
|
||||
&output[mByteOff], &outLen);
|
||||
mByteOff += outLen;
|
||||
}
|
||||
aPtr = aPtr->next;
|
||||
}
|
||||
|
||||
// Check for free nsILE or convert nsILE to a service
|
||||
// NS_IF_RELEASE(mCtlObj);
|
||||
|
||||
// Cleanup Run Info;
|
||||
aPtr = txtRuns.head;
|
||||
for (i = 0; i < txtRuns.numRuns; i++) {
|
||||
for (int i = 0; i < txtRuns.numRuns; i++) {
|
||||
aTmpPtr = aPtr;
|
||||
aPtr = aPtr->next;
|
||||
delete aTmpPtr;
|
||||
}
|
||||
|
||||
*aDestLength = byteOff;
|
||||
*aDestLength = mByteOff;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -205,14 +253,14 @@ NS_IMETHODIMP nsUnicodeToTIS620::Finish(char * output, PRInt32 * aDestLength)
|
||||
{
|
||||
// Finish does'nt have to do much as Convert already flushes
|
||||
// to output buffer
|
||||
byteOff = charOff = 0;
|
||||
mByteOff = mCharOff = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
NS_IMETHODIMP nsUnicodeToTIS620::Reset()
|
||||
{
|
||||
byteOff = charOff = 0;
|
||||
mByteOff = mCharOff = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -35,18 +35,9 @@
|
||||
#include "nsIUnicodeEncoder.h"
|
||||
#include "nsICharRepresentable.h"
|
||||
|
||||
struct textRun {
|
||||
PRInt32 length; /* Length of a chunk */
|
||||
PRBool isOther; /* Outside the range */
|
||||
const PRUnichar *start; /* Address of start offset */
|
||||
struct textRun *next;
|
||||
};
|
||||
#include "nsILE.h"
|
||||
|
||||
typedef struct {
|
||||
struct textRun *head;
|
||||
struct textRun *cur;
|
||||
PRInt32 numRuns;
|
||||
} textRunList;
|
||||
struct textRunList;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Class nsUnicodeToTIS620 [declaration]
|
||||
@ -80,12 +71,14 @@ public:
|
||||
NS_IMETHOD FillInfo(PRUint32* aInfo);
|
||||
|
||||
private:
|
||||
PRUint8 state;
|
||||
PRInt32 byteOff;
|
||||
PRInt32 charOff;
|
||||
PRUint8 mState;
|
||||
PRInt32 mByteOff;
|
||||
PRInt32 mCharOff;
|
||||
|
||||
nsCOMPtr<nsILE> mCtlObj;
|
||||
|
||||
// beg and end denote ranges and may need to be expanded in the future to
|
||||
// handle discontinous ranges
|
||||
int Itemize(const PRUnichar* aSrcBuf, PRInt32 aSrcLen, textRunList *aRunList);
|
||||
PRInt32 Itemize(const PRUnichar* aSrcBuf, PRInt32 aSrcLen, textRunList *aRunList);
|
||||
};
|
||||
#endif /* nsUnicodeToTIS620_h___ */
|
||||
|
||||
@ -68,4 +68,6 @@ CXXFLAGS += $(GLIB_CFLAGS)
|
||||
CFLAGS += $(GLIB_CFLAGS)
|
||||
EXTRA_DSO_LDOPTS += $(GLIB_LIBS) -lgmodule
|
||||
|
||||
#DEFINES += -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
# Install pango.modules file for Shaping Modules.
|
||||
install::
|
||||
$(INSTALL) $(srcdir)/pango.modules $(DIST)/bin
|
||||
|
||||
@ -80,7 +80,7 @@ struct _PangoEngineShape
|
||||
{
|
||||
PangoEngine engine;
|
||||
void (*script_shape) (const char *fontCharset,
|
||||
const char *text,
|
||||
const gunichar2 *text,
|
||||
int length,
|
||||
PangoAnalysis *analysis,
|
||||
PangoGlyphString *glyphs);
|
||||
|
||||
@ -102,7 +102,7 @@ void pango_glyph_string_x_to_index(PangoGlyphString *glyphs,
|
||||
int *trailing);
|
||||
|
||||
/* Turn a string of characters into a string of glyphs */
|
||||
void pango_shape(const char *text,
|
||||
void pango_shape(const gunichar2 *text,
|
||||
gint length,
|
||||
PangoAnalysis *analysis,
|
||||
PangoGlyphString *glyphs);
|
||||
|
||||
5
mozilla/extensions/ctl/src/pangoLite/pango.modules
Executable file
5
mozilla/extensions/ctl/src/pangoLite/pango.modules
Executable file
@ -0,0 +1,5 @@
|
||||
|
||||
# Pango Modules file
|
||||
# Automatically generated file, do not edit
|
||||
#
|
||||
./libmozpango-thaix.so ThaiScriptEngineX PangoEngineShape PangoRenderX 3585-3675:*
|
||||
@ -47,7 +47,7 @@
|
||||
* convert the characters into glyphs. You may also pass
|
||||
* in only a substring of the item from pango_itemize().
|
||||
*/
|
||||
void pango_shape(const gchar *text,
|
||||
void pango_shape(const gunichar2 *text,
|
||||
gint length,
|
||||
PangoAnalysis *analysis,
|
||||
PangoGlyphString *glyphs)
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
#define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
||||
|
||||
#define ucs2tis(wc) (unsigned int)((unsigned int)(wc) - 0x0E00 + 0xA0)
|
||||
#define tis2uni(c) ((gunichar)(c) - 0xA0 + 0x0E00)
|
||||
#define tis2uni(c) ((gunichar2)(c) - 0xA0 + 0x0E00)
|
||||
|
||||
#define MAX_CLUSTER_CHRS 256
|
||||
#define MAX_GLYPHS 256
|
||||
@ -418,7 +418,7 @@ add_glyph(ThaiFontInfo *font_info,
|
||||
|
||||
static gint
|
||||
get_adjusted_glyphs_list(ThaiFontInfo *font_info,
|
||||
gunichar *cluster,
|
||||
gunichar2 *cluster,
|
||||
gint num_chrs,
|
||||
PangoGlyph *glyph_lists,
|
||||
const ThaiShapeTable *shaping_table)
|
||||
@ -582,7 +582,7 @@ get_adjusted_glyphs_list(ThaiFontInfo *font_info,
|
||||
|
||||
static gint
|
||||
get_glyphs_list(ThaiFontInfo *font_info,
|
||||
gunichar *cluster,
|
||||
gunichar2 *cluster,
|
||||
gint num_chrs,
|
||||
PangoGlyph *glyph_lists)
|
||||
{
|
||||
@ -647,7 +647,7 @@ static void
|
||||
add_cluster (ThaiFontInfo *font_info,
|
||||
PangoGlyphString *glyphs,
|
||||
gint cluster_start,
|
||||
gunichar *cluster,
|
||||
gunichar2 *cluster,
|
||||
gint num_chrs)
|
||||
|
||||
{
|
||||
@ -661,7 +661,7 @@ add_cluster (ThaiFontInfo *font_info,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_wtt_composible (gunichar cur_wc, gunichar nxt_wc)
|
||||
is_wtt_composible (gunichar2 cur_wc, gunichar2 nxt_wc)
|
||||
{
|
||||
switch (TAC_compose_and_input_check_type_table[char_class(ucs2tis(cur_wc))]
|
||||
[char_class(ucs2tis(nxt_wc))]) {
|
||||
@ -679,21 +679,21 @@ is_wtt_composible (gunichar cur_wc, gunichar nxt_wc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_next_cluster(const char *text,
|
||||
gint length,
|
||||
gunichar *cluster,
|
||||
gint *num_chrs)
|
||||
static const gunichar2 *
|
||||
get_next_cluster(const gunichar2 *text,
|
||||
gint length,
|
||||
gunichar2 *cluster,
|
||||
gint *num_chrs)
|
||||
{
|
||||
const char *p;
|
||||
gint n_chars = 0;
|
||||
const gunichar2 *p;
|
||||
gint n_chars = 0;
|
||||
|
||||
p = text;
|
||||
while (p < text + length && n_chars < 3) {
|
||||
gunichar current = g_utf8_get_char (p);
|
||||
gunichar2 current = *p;
|
||||
|
||||
if (n_chars == 0 ||
|
||||
is_wtt_composible ((gunichar)(cluster[n_chars - 1]), current) ||
|
||||
is_wtt_composible ((gunichar2)(cluster[n_chars - 1]), current) ||
|
||||
(n_chars == 1 &&
|
||||
is_char_type (cluster[0], Cons) &&
|
||||
is_char_type (current, SaraAm)) ||
|
||||
@ -702,7 +702,7 @@ get_next_cluster(const char *text,
|
||||
is_char_type (cluster[1], Tone) &&
|
||||
is_char_type (current, SaraAm))) {
|
||||
cluster[n_chars++] = current;
|
||||
p = g_utf8_next_char(p);
|
||||
p++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
@ -714,16 +714,16 @@ get_next_cluster(const char *text,
|
||||
|
||||
static void
|
||||
thai_engine_shape(const char *fontCharset,
|
||||
const char *text,
|
||||
const gunichar2 *text,
|
||||
gint length,
|
||||
PangoAnalysis *analysis,
|
||||
PangoGlyphString *glyphs)
|
||||
{
|
||||
ThaiFontInfo *font_info;
|
||||
const char *p;
|
||||
const char *log_cluster;
|
||||
gunichar cluster[MAX_CLUSTER_CHRS];
|
||||
gint num_chrs;
|
||||
ThaiFontInfo *font_info;
|
||||
const gunichar2 *p;
|
||||
const gunichar2 *log_cluster;
|
||||
gunichar2 cluster[MAX_CLUSTER_CHRS];
|
||||
gint num_chrs;
|
||||
|
||||
pango_glyph_string_set_size(glyphs, 0);
|
||||
|
||||
@ -745,7 +745,7 @@ thai_engine_get_coverage(const char *fontCharset,
|
||||
ThaiFontInfo *font_info = get_font_info(fontCharset);
|
||||
|
||||
if (font_info->type != THAI_FONT_NONE) {
|
||||
gunichar wc;
|
||||
gunichar2 wc;
|
||||
|
||||
for (wc = 0xe01; wc <= 0xe3a; wc++)
|
||||
pango_coverage_set(result, wc, PANGO_COVERAGE_EXACT);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user