ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

breaking.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of line breaking algorithm for the Uniscribe Script Processor
00003  *
00004  * Copyright 2011 CodeWeavers, Aric Stewart
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  */
00021 #include "config.h"
00022 #include <stdarg.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "wingdi.h"
00030 #include "winnls.h"
00031 #include "usp10.h"
00032 #include "winternl.h"
00033 
00034 #include "wine/debug.h"
00035 #include "usp10_internal.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
00038 
00039 extern const unsigned short wine_linebreak_table[];
00040 
00041 enum breaking_types { b_BK=1, b_CR, b_LF, b_CM, b_SG, b_GL, b_CB, b_SP, b_ZW, b_NL, b_WJ, b_JL, b_JV, b_JT, b_H2, b_H3, b_XX, b_OP, b_CL, b_CP, b_QU, b_NS, b_EX, b_SY, b_IS, b_PR, b_PO, b_NU, b_AL, b_ID, b_IN, b_HY, b_BB, b_BA, b_SA, b_AI, b_B2};
00042 
00043 enum breaking_class {b_r=1, b_s, b_x};
00044 
00045 static void debug_output_breaks(const short* breaks, int count)
00046 {
00047     if (TRACE_ON(uniscribe))
00048     {
00049         int i;
00050         TRACE("[");
00051         for (i = 0; i < count && i < 200; i++)
00052         {
00053             switch (breaks[i])
00054             {
00055                 case b_x: TRACE("x"); break;
00056                 case b_r: TRACE("!"); break;
00057                 case b_s: TRACE("+"); break;
00058                 default: TRACE("*");
00059             }
00060         }
00061         if (i == 200)
00062             TRACE("...");
00063         TRACE("]\n");
00064     }
00065 }
00066 
00067 static inline void else_break(short* before, short class)
00068 {
00069     if (*before == 0)  *before = class;
00070 }
00071 
00072 void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
00073 {
00074     int i,j;
00075     short *break_class;
00076     short *break_before;
00077 
00078     TRACE("In      %s\n",debugstr_wn(chars,count));
00079 
00080     break_class = HeapAlloc(GetProcessHeap(),0, count * sizeof(short));
00081     break_before = HeapAlloc(GetProcessHeap(),0, count * sizeof(short));
00082 
00083     for (i = 0; i < count; i++)
00084     {
00085         break_class[i] = get_table_entry( wine_linebreak_table, chars[i] );
00086         break_before[i] = 0;
00087 
00088         memset(&la[i],0,sizeof(SCRIPT_LOGATTR));
00089 
00090         la[i].fCharStop = TRUE;
00091         switch (break_class[i])
00092         {
00093             case b_BK:
00094             case b_ZW:
00095             case b_SP:
00096                 la[i].fWhiteSpace = TRUE;
00097                 break;
00098             case b_CM:
00099                 la[i].fCharStop = FALSE;
00100         }
00101     }
00102 
00103     /* LB1 */
00104     /* TODO: Have outside algorithms for these scripts */
00105     for (i = 0; i < count; i++)
00106     {
00107         switch(break_class[i])
00108         {
00109             case b_AI:
00110             case b_SA:
00111             case b_SG:
00112             case b_XX:
00113                 break_class[i] = b_AL;
00114         }
00115     }
00116 
00117     /* LB2 - LB3 */
00118     break_before[0] = b_x;
00119     for (i = 0; i < count; i++)
00120     {
00121         switch(break_class[i])
00122         {
00123             /* LB4 - LB6 */
00124             case b_CR:
00125                 if (i < count-1 && break_class[i+1] == b_LF)
00126                 {
00127                     else_break(&break_before[i],b_x);
00128                     else_break(&break_before[i+1],b_x);
00129                     break;
00130                 }
00131             case b_LF:
00132             case b_NL:
00133             case b_BK:
00134                 if (i < count-1) else_break(&break_before[i+1],b_r);
00135                     else_break(&break_before[i],b_x);
00136                 break;
00137             /* LB7 */
00138             case b_SP:
00139                 else_break(&break_before[i],b_x);
00140                 break;
00141             case b_ZW:
00142                 else_break(&break_before[i],b_x);
00143             /* LB8 */
00144                 while (i < count-1 && break_class[i+1] == b_SP)
00145                     i++;
00146                 else_break(&break_before[i],b_s);
00147                 break;
00148         }
00149     }
00150 
00151     debug_output_breaks(break_before,count);
00152 
00153     /* LB9 - LB10 */
00154     for (i = 0; i < count; i++)
00155     {
00156         if (break_class[i] == b_CM)
00157         {
00158             if (i > 0)
00159             {
00160                 switch (break_class[i-1])
00161                 {
00162                     case b_SP:
00163                     case b_BK:
00164                     case b_CR:
00165                     case b_LF:
00166                     case b_NL:
00167                     case b_ZW:
00168                         break_class[i] = b_AL;
00169                         break;
00170                     default:
00171                         break_class[i] = break_class[i-1];
00172                 }
00173             }
00174             else break_class[i] = b_AL;
00175         }
00176     }
00177 
00178     for (i = 0; i < count; i++)
00179     {
00180         switch(break_class[i])
00181         {
00182             /* LB11 */
00183             case b_WJ:
00184                 else_break(&break_before[i],b_x);
00185                 if (i < count-1)
00186                     else_break(&break_before[i+1],b_x);
00187                 break;
00188             /* LB12 */
00189             case b_GL:
00190                 if (i < count-1)
00191                     else_break(&break_before[i+1],b_x);
00192             /* LB12a */
00193                 if (i > 0)
00194                 {
00195                     if (break_class[i-1] != b_SP &&
00196                         break_class[i-1] != b_BA &&
00197                         break_class[i-1] != b_HY)
00198                         else_break(&break_before[i],b_x);
00199                 }
00200                 break;
00201             /* LB13 */
00202             case b_CL:
00203             case b_CP:
00204             case b_EX:
00205             case b_IS:
00206             case b_SY:
00207                 else_break(&break_before[i],b_x);
00208                 break;
00209             /* LB14 */
00210             case b_OP:
00211                 while (i < count-1 && break_class[i+1] == b_SP)
00212                 {
00213                     else_break(&break_before[i+1],b_x);
00214                     i++;
00215                 }
00216                 else_break(&break_before[i+1],b_x);
00217                 break;
00218             /* LB15 */
00219             case b_QU:
00220                 j = i+1;
00221                 while (j < count-1 && break_class[j] == b_SP)
00222                     j++;
00223                 if (break_class[j] == b_OP)
00224                 {
00225                     for (; j > i; j--)
00226                         else_break(&break_before[j],b_x);
00227                 }
00228                 break;
00229             /* LB16 */
00230             case b_NS:
00231                 j = i-1;
00232                 while(j > 0 && break_class[j] == b_SP)
00233                     j--;
00234                 if (break_class[j] == b_CL || break_class[j] == b_CP)
00235                 {
00236                     for (j++; j <= i; j++)
00237                         else_break(&break_before[j],b_x);
00238                 }
00239                 break;
00240             /* LB17 */
00241             case b_B2:
00242                 j = i+1;
00243                 while (j < count && break_class[j] == b_SP)
00244                     j++;
00245                 if (break_class[j] == b_B2)
00246                 {
00247                     for (; j > i; j--)
00248                         else_break(&break_before[j],b_x);
00249                 }
00250                 break;
00251         }
00252     }
00253 
00254     debug_output_breaks(break_before,count);
00255 
00256     for (i = 0; i < count; i++)
00257     {
00258         switch(break_class[i])
00259         {
00260             /* LB18 */
00261             case b_SP:
00262                 if (i < count-1)
00263                     else_break(&break_before[i+1],b_s);
00264                 break;
00265             /* LB19 */
00266             case b_QU:
00267                 else_break(&break_before[i],b_x);
00268                 if (i < count-1)
00269                     else_break(&break_before[i+1],b_x);
00270                 break;
00271             /* LB20 */
00272             case b_CB:
00273                 else_break(&break_before[i],b_s);
00274                 if (i < count-1)
00275                     else_break(&break_before[i+1],b_s);
00276             /* LB21 */
00277             case b_BA:
00278             case b_HY:
00279             case b_NS:
00280                 else_break(&break_before[i],b_x);
00281                 break;
00282             case b_BB:
00283                 if (i < count-1)
00284                     else_break(&break_before[i+1],b_x);
00285                 break;
00286             /* LB22 */
00287             case b_IN:
00288                 if (i > 0)
00289                 {
00290                     switch (break_class[i-1])
00291                     {
00292                         case b_AL:
00293                         case b_ID:
00294                         case b_IN:
00295                         case b_NU:
00296                             else_break(&break_before[i], b_x);
00297                     }
00298                 }
00299                 break;
00300         }
00301 
00302         if (i < count-1)
00303         {
00304             /* LB23 */
00305             if ((break_class[i] == b_ID && break_class[i+1] == b_PO) ||
00306                 (break_class[i] == b_AL && break_class[i+1] == b_NU) ||
00307                 (break_class[i] == b_NU && break_class[i+1] == b_AL))
00308                     else_break(&break_before[i+1],b_x);
00309             /* LB24 */
00310             if ((break_class[i] == b_PR && break_class[i+1] == b_ID) ||
00311                 (break_class[i] == b_PR && break_class[i+1] == b_AL) ||
00312                 (break_class[i] == b_PO && break_class[i+1] == b_AL))
00313                     else_break(&break_before[i+1],b_x);
00314 
00315             /* LB25 */
00316             if ((break_class[i] == b_CL && break_class[i+1] == b_PO) ||
00317                 (break_class[i] == b_CP && break_class[i+1] == b_PO) ||
00318                 (break_class[i] == b_CL && break_class[i+1] == b_PR) ||
00319                 (break_class[i] == b_CP && break_class[i+1] == b_PR) ||
00320                 (break_class[i] == b_NU && break_class[i+1] == b_PO) ||
00321                 (break_class[i] == b_NU && break_class[i+1] == b_PR) ||
00322                 (break_class[i] == b_PO && break_class[i+1] == b_OP) ||
00323                 (break_class[i] == b_PO && break_class[i+1] == b_NU) ||
00324                 (break_class[i] == b_PR && break_class[i+1] == b_OP) ||
00325                 (break_class[i] == b_PR && break_class[i+1] == b_NU) ||
00326                 (break_class[i] == b_HY && break_class[i+1] == b_NU) ||
00327                 (break_class[i] == b_IS && break_class[i+1] == b_NU) ||
00328                 (break_class[i] == b_NU && break_class[i+1] == b_NU) ||
00329                 (break_class[i] == b_SY && break_class[i+1] == b_NU))
00330                     else_break(&break_before[i+1],b_x);
00331 
00332             /* LB26 */
00333             if (break_class[i] == b_JL)
00334             {
00335                 switch (break_class[i+1])
00336                 {
00337                     case b_JL:
00338                     case b_JV:
00339                     case b_H2:
00340                     case b_H3:
00341                         else_break(&break_before[i+1],b_x);
00342                 }
00343             }
00344             if ((break_class[i] == b_JV || break_class[i] == b_H2) &&
00345                 (break_class[i+1] == b_JV || break_class[i+1] == b_JT))
00346                     else_break(&break_before[i+1],b_x);
00347             if ((break_class[i] == b_JT || break_class[i] == b_H3) &&
00348                  break_class[i+1] == b_JT)
00349                     else_break(&break_before[i+1],b_x);
00350 
00351             /* LB27 */
00352             switch (break_class[i])
00353             {
00354                 case b_JL:
00355                 case b_JV:
00356                 case b_JT:
00357                 case b_H2:
00358                 case b_H3:
00359                     if (break_class[i+1] == b_IN || break_class[i+1] == b_PO)
00360                         else_break(&break_before[i+1],b_x);
00361             }
00362             if (break_class[i] == b_PO)
00363             {
00364                 switch (break_class[i+1])
00365                 {
00366                     case b_JL:
00367                     case b_JV:
00368                     case b_JT:
00369                     case b_H2:
00370                     case b_H3:
00371                         else_break(&break_before[i+1],b_x);
00372                 }
00373             }
00374 
00375             /* LB28 */
00376             if (break_class[i] == b_AL && break_class[i+1] == b_AL)
00377                 else_break(&break_before[i+1],b_x);
00378 
00379             /* LB29 */
00380             if (break_class[i] == b_IS && break_class[i+1] == b_AL)
00381                 else_break(&break_before[i+1],b_x);
00382 
00383             /* LB30 */
00384             if ((break_class[i] == b_AL || break_class[i] == b_NU) &&
00385                  break_class[i+1] == b_OP)
00386                 else_break(&break_before[i+1],b_x);
00387             if (break_class[i] == b_CP &&
00388                 (break_class[i+1] == b_AL || break_class[i] == b_NU))
00389                 else_break(&break_before[i+1],b_x);
00390         }
00391     }
00392     debug_output_breaks(break_before,count);
00393 
00394     /* LB31 */
00395     for (i = 0; i < count-1; i++)
00396         else_break(&break_before[i+1],b_s);
00397 
00398     debug_output_breaks(break_before,count);
00399     for (i = 0; i < count; i++)
00400     {
00401         if (break_before[i] != b_x)
00402         {
00403             la[i].fSoftBreak = TRUE;
00404             la[i].fWordStop = TRUE;
00405         }
00406     }
00407 
00408     HeapFree(GetProcessHeap(), 0, break_before);
00409     HeapFree(GetProcessHeap(), 0, break_class);
00410 }

Generated on Sun May 27 2012 04:26:43 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.