Back to index

lightning-sunbird  0.9+nobinonly
nsULE.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  * XPCTL : nsULE.cpp
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is mozilla.org code. The Initial Developer of the Original Code is Sun Microsystems, Inc.  Portions created by SUN are Copyright (C) 2000 SUN Microsystems, Inc. All Rights Reserved.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Sun Microsystems, Inc.
00021  * Portions created by the Initial Developer are Copyright (C) 2000
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Prabhat Hegde (prabhat.hegde@sun.com)
00026  *   Jungshik Shin (jshin@mailmaps.org)
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either of the GNU General Public License Version 2 or later (the "GPL"),
00030  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the MPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the MPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 #include "nsULE.h"
00043 #include "nsString.h"
00044 
00045 #include "pango-types.h"
00046 #include "pango-glyph.h"
00047 #include "pango-modules.h"
00048 #include "pango-utils.h"
00049 
00050 #define GLYPH_COMBINING 256
00051 
00052 /* 
00053  * To Do:(prabhat-04/01/03) Cache GlyphString
00054 */
00055 
00056 nsULE::nsULE() {
00057 }
00058 
00059 nsULE::~nsULE() {
00060 }
00061 
00062 NS_IMPL_THREADSAFE_ISUPPORTS1(nsULE, nsILE)
00063 
00064 // Default font encoding by code-range
00065 // At the moment pangoLite only supports 2 shapers/scripts
00066 const char*
00067 nsULE::GetDefaultFont(const PRUnichar aString)
00068 {
00069   if ((aString >= 0x0e01) && (aString <= 0x0e5b))
00070     return "tis620-2";
00071   if ((aString >= 0x0901) && (aString <= 0x0970))
00072     return "sun.unicode.india-0";
00073   return "iso8859-1";
00074 }
00075 
00076 PRInt32
00077 nsULE::GetGlyphInfo(const PRUnichar      *aSrcBuf,
00078                     PRInt32              aSrcLen,
00079                     PangoliteGlyphString *aGlyphData,
00080                     const char           *aFontCharset)
00081 {
00082   int                  ct=0, start=0, i, index, startgid, lastCluster=0;
00083   PRBool               sameCtlRun=PR_FALSE;
00084   PangoliteEngineShape *curShaper=NULL, *prevShaper=NULL;
00085   PangoliteMap         *pngMap=NULL;
00086   PangoliteAnalysis    pngAnalysis;
00087   guint                enginetypeId=0, rendertypeId=0;
00088 
00089   pngAnalysis.aDir = PANGO_DIRECTION_LTR;
00090  
00091   // Maybe find a better way to handle font encodings
00092   if (aFontCharset == NULL)
00093     pngAnalysis.fontCharset = strdup(GetDefaultFont(aSrcBuf[0]));
00094   else
00095     pngAnalysis.fontCharset = strdup(aFontCharset);
00096 
00097   enginetypeId = g_quark_from_static_string(PANGO_ENGINE_TYPE_SHAPE);
00098   rendertypeId = g_quark_from_static_string(PANGO_RENDER_TYPE_X);
00099   pngMap = pangolite_find_map("en_US", enginetypeId, rendertypeId);
00100 
00101   for (ct=0; ct < aSrcLen;) {
00102     start = ct;
00103     curShaper = (PangoliteEngineShape*)
00104       pangolite_map_get_engine(pngMap, (PRUint32)aSrcBuf[ct++]);
00105     sameCtlRun = (curShaper != NULL);
00106     prevShaper = curShaper;
00107 
00108     if (sameCtlRun) {
00109       while (sameCtlRun && ct < aSrcLen) {
00110         curShaper = (PangoliteEngineShape*)
00111           pangolite_map_get_engine(pngMap, (PRUint32)aSrcBuf[ct]);
00112         sameCtlRun = ((curShaper != NULL) && (curShaper == prevShaper));
00113         if (sameCtlRun)
00114           ct++;
00115       }
00116       startgid = aGlyphData->num_glyphs;
00117       pngAnalysis.shape_engine = curShaper;
00118       prevShaper->script_shape(pngAnalysis.fontCharset,
00119                                &aSrcBuf[start], (ct-start),
00120                                &pngAnalysis, aGlyphData);
00121       if (lastCluster > 0) {
00122          for (i=startgid; i < aGlyphData->num_glyphs; i++)
00123            aGlyphData->log_clusters[i] += lastCluster;
00124       }
00125     }
00126     else {
00127       while (!sameCtlRun && ct < aSrcLen) {
00128         curShaper = (PangoliteEngineShape*)
00129           pangolite_map_get_engine(pngMap, (PRUint32)aSrcBuf[ct]);
00130         sameCtlRun = (curShaper != NULL);
00131         if (!sameCtlRun)
00132           ct++;
00133       }
00134       index = aGlyphData->num_glyphs;
00135       for (i=0; i < (ct-start); i++) {
00136         pangolite_glyph_string_set_size(aGlyphData, index+1);
00137         aGlyphData->glyphs[index].glyph = aSrcBuf[start+i];
00138         aGlyphData->glyphs[index].is_cluster_start = (gint)1;
00139         aGlyphData->log_clusters[index] = i+lastCluster;
00140         index++;
00141       }
00142     }
00143     lastCluster = aGlyphData->log_clusters[aGlyphData->num_glyphs-1];
00144   }
00145   nsMemory::Free(pngAnalysis.fontCharset);
00146   return aGlyphData->num_glyphs;
00147 }
00148 
00149 NS_IMETHODIMP
00150 nsULE::NeedsCTLFix(const PRUnichar *aString,
00151                    const PRInt32   aBeg,
00152                    const PRInt32   aEnd,
00153                    PRBool          *aCTLNeeded)
00154 {
00155   PangoliteEngineShape *BegShaper=NULL, *EndShaper=NULL;
00156   PangoliteMap         *pngMap=NULL;
00157   guint                enginetypeId=0, rendertypeId=0;
00158 
00159   enginetypeId = g_quark_from_static_string(PANGO_ENGINE_TYPE_SHAPE);
00160   rendertypeId = g_quark_from_static_string(PANGO_RENDER_TYPE_X);
00161   pngMap = pangolite_find_map("en_US", enginetypeId, rendertypeId);
00162 
00163   *aCTLNeeded = PR_FALSE;
00164   if (aBeg >= 0)
00165     BegShaper = (PangoliteEngineShape*)
00166       pangolite_map_get_engine(pngMap, (PRUint32)aString[aBeg]);
00167 
00168   if (!BegShaper) {
00169 
00170     if ((aEnd < 0) && ((aBeg+aEnd) >= 0)) {
00171       EndShaper = (PangoliteEngineShape*)
00172         pangolite_map_get_engine(pngMap, (PRUint32)aString[aBeg+aEnd]);
00173     }
00174     else {
00175       EndShaper = (PangoliteEngineShape*)
00176         pangolite_map_get_engine(pngMap, (PRUint32)aString[aEnd]);
00177     }
00178   }
00179 
00180   if (BegShaper || EndShaper)
00181     *aCTLNeeded = PR_TRUE;
00182   return NS_OK;
00183 }
00184 
00185 NS_IMETHODIMP
00186 nsULE::GetPresentationForm(const PRUnichar *aString,
00187                            PRUint32        aLength,
00188                            const char      *aFontCharset,
00189                            char            *aGlyphs,
00190                            PRSize          *aOutLength,
00191                            PRBool          aIsWide)
00192 {
00193   PangoliteGlyphString *tmpGlyphs=pangolite_glyph_string_new();
00194 
00195   GetGlyphInfo(aString, aLength, tmpGlyphs, aFontCharset);
00196 
00197   if (tmpGlyphs->num_glyphs > 0) {
00198     gint i=0, glyphCt=0;
00199     for (i=0; i < tmpGlyphs->num_glyphs; i++, glyphCt++) {
00200       if (aIsWide)
00201          aGlyphs[glyphCt++]=(unsigned char)
00202                             ((tmpGlyphs->glyphs[i].glyph & 0xFF00) >> 8);
00203       aGlyphs[glyphCt]=(unsigned char)(tmpGlyphs->glyphs[i].glyph & 0x00FF);
00204     }
00205     *aOutLength = (PRSize)glyphCt;
00206   }
00207   pangolite_glyph_string_free(tmpGlyphs);
00208   return NS_OK;
00209 }
00210 
00211 // This routine returns the string index of the next cluster
00212 // corresponding to the cluster at string index 'aIndex'
00213 NS_IMETHODIMP
00214 nsULE::NextCluster(const PRUnichar *aString,
00215                    PRUint32        aLength,
00216                    const PRInt32   aIndex,
00217                    PRInt32         *aNextOffset)
00218 {
00219   int mStart, mEnd;
00220 
00221   if (aIndex < 0) {
00222     *aNextOffset = 0;
00223     return NS_OK;
00224   }
00225 
00226   if (PRUint32(aIndex) >= aLength) {
00227     *aNextOffset = aLength;
00228     return NS_OK;
00229   }
00230   this->GetRangeOfCluster(aString, aLength, aIndex, &mStart, &mEnd);
00231   *aNextOffset = mEnd;
00232   return NS_OK;
00233 }
00234 
00235 // This routine returns the end-offset of the previous block
00236 // corresponding to string index 'aIndex'
00237 NS_IMETHODIMP
00238 nsULE::PrevCluster(const PRUnichar *aString,
00239                    PRUint32        aLength,
00240                    const PRInt32   aIndex,
00241                    PRInt32         *aPrevOffset)
00242 {
00243   int                  gCt, pCluster, cCluster;
00244   PangoliteGlyphString *GlyphInfo=pangolite_glyph_string_new();
00245 
00246   if (aIndex <= 1) {
00247     *aPrevOffset = 0;
00248     return NS_OK;
00249   }
00250   pCluster=cCluster=0;
00251   GetGlyphInfo(aString, aLength, GlyphInfo, NULL);
00252   for (gCt=0; gCt < GlyphInfo->num_glyphs; gCt++) {
00253 
00254     if (GlyphInfo->glyphs[gCt].is_cluster_start != GLYPH_COMBINING)
00255        cCluster += GlyphInfo->glyphs[gCt].is_cluster_start;
00256 
00257     if (cCluster >= aIndex) {
00258        *aPrevOffset = pCluster;
00259        pangolite_glyph_string_free(GlyphInfo);
00260        return NS_OK;
00261     }
00262     pCluster = cCluster;
00263   }
00264   *aPrevOffset = pCluster;
00265   pangolite_glyph_string_free(GlyphInfo);
00266   return NS_OK;
00267 }
00268 
00269 // This routine gets the bounds of a cluster given a index
00270 NS_IMETHODIMP
00271 nsULE::GetRangeOfCluster(const PRUnichar *aString,
00272                          PRUint32        aLength,
00273                          const PRInt32   aIndex,
00274                          PRInt32         *aStart,
00275                          PRInt32         *aEnd)
00276 {
00277   PangoliteGlyphString *GlyphInfo=pangolite_glyph_string_new();
00278   int                  gCt=0;
00279 
00280   GetGlyphInfo(aString, aLength, GlyphInfo, NULL);
00281 
00282   *aStart=*aEnd=0;
00283   for (gCt=0; gCt < GlyphInfo->num_glyphs; gCt++) {
00284 
00285     if (GlyphInfo->glyphs[gCt].is_cluster_start != GLYPH_COMBINING)
00286        *aEnd += GlyphInfo->glyphs[gCt].is_cluster_start;
00287 
00288     if (*aEnd >= aIndex+1) {
00289       pangolite_glyph_string_free(GlyphInfo);
00290       return NS_OK;
00291     }
00292     *aStart = *aEnd;
00293   }
00294   *aEnd = aLength;
00295   pangolite_glyph_string_free(GlyphInfo);
00296   return NS_OK;
00297 }