LCOV - code coverage report
Current view: top level - vcl/generic/glyphs - scrptrun.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 66 78 84.6 %
Date: 2014-11-03 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *******************************************************************************
       3             :  *
       4             :  *   Copyright (c) 1995-2013 International Business Machines Corporation and others
       5             :  *
       6             :  *   All rights reserved.
       7             :  *
       8             :  *   Permission is hereby granted, free of charge, to any person obtaining a copy of
       9             :  *   this software and associated documentation files (the "Software"), to deal in
      10             :  *   the Software without restriction, including without limitation the rights to
      11             :  *   use, copy, modify, merge, publish, distribute, and/or sell copies of the
      12             :  *   Software, and to permit persons to whom the Software is furnished to do so,
      13             :  *   provided that the above copyright notice(s) and this permission notice appear
      14             :  *   in all copies of the Software and that both the above copyright notice(s) and
      15             :  *   this permission notice appear in supporting documentation.
      16             :  *
      17             :  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      18             :  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      19             :  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
      20             :  *   NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE
      21             :  *   LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
      22             :  *   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      23             :  *   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
      24             :  *   CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      25             :  *
      26             :  *   Except as contained in this notice, the name of a copyright holder shall not be
      27             :  *   used in advertising or otherwise to promote the sale, use or other dealings in
      28             :  *   this Software without prior written authorization of the copyright holder.
      29             :  *
      30             :  *******************************************************************************
      31             :  *   file name:  scrptrun.cpp
      32             :  *
      33             :  *   created on: 10/17/2001
      34             :  *   created by: Eric R. Mader
      35             :  */
      36             : 
      37             : #include "unicode/utypes.h"
      38             : #include "unicode/uscript.h"
      39             : 
      40             : #include "scrptrun.h"
      41             : 
      42             : #define ARRAY_SIZE(array) (sizeof array  / sizeof array[0])
      43             : 
      44             : namespace vcl {
      45             : 
      46             : const char ScriptRun::fgClassID=0;
      47             : 
      48             : UChar32 ScriptRun::pairedChars[] = {
      49             :     0x0028, 0x0029, // ascii paired punctuation
      50             :     0x003c, 0x003e,
      51             :     0x005b, 0x005d,
      52             :     0x007b, 0x007d,
      53             :     0x00ab, 0x00bb, // guillemets
      54             :     0x2018, 0x2019, // general punctuation
      55             :     0x201c, 0x201d,
      56             :     0x2039, 0x203a,
      57             :     0x3008, 0x3009, // chinese paired punctuation
      58             :     0x300a, 0x300b,
      59             :     0x300c, 0x300d,
      60             :     0x300e, 0x300f,
      61             :     0x3010, 0x3011,
      62             :     0x3014, 0x3015,
      63             :     0x3016, 0x3017,
      64             :     0x3018, 0x3019,
      65             :     0x301a, 0x301b
      66             : };
      67             : 
      68             : const int32_t ScriptRun::pairedCharCount = ARRAY_SIZE(pairedChars);
      69         411 : const int32_t ScriptRun::pairedCharPower = 1 << highBit(pairedCharCount);
      70         411 : const int32_t ScriptRun::pairedCharExtra = pairedCharCount - pairedCharPower;
      71             : 
      72         411 : int8_t ScriptRun::highBit(int32_t value)
      73             : {
      74         411 :     if (value <= 0) {
      75           0 :         return -32;
      76             :     }
      77             : 
      78         411 :     int8_t bit = 0;
      79             : 
      80         411 :     if (value >= 1 << 16) {
      81           0 :         value >>= 16;
      82           0 :         bit += 16;
      83             :     }
      84             : 
      85         411 :     if (value >= 1 << 8) {
      86           0 :         value >>= 8;
      87           0 :         bit += 8;
      88             :     }
      89             : 
      90         411 :     if (value >= 1 << 4) {
      91         411 :         value >>= 4;
      92         411 :         bit += 4;
      93             :     }
      94             : 
      95         411 :     if (value >= 1 << 2) {
      96           0 :         value >>= 2;
      97           0 :         bit += 2;
      98             :     }
      99             : 
     100         411 :     if (value >= 1 << 1) {
     101         411 :         value >>= 1;
     102         411 :         bit += 1;
     103             :     }
     104             : 
     105         411 :     return bit;
     106             : }
     107             : 
     108   490772574 : int32_t ScriptRun::getPairIndex(UChar32 ch)
     109             : {
     110   490772574 :     int32_t probe = pairedCharPower;
     111   490772574 :     int32_t index = 0;
     112             : 
     113   490772574 :     if (ch >= pairedChars[pairedCharExtra]) {
     114   124556668 :         index = pairedCharExtra;
     115             :     }
     116             : 
     117  3435408018 :     while (probe > (1 << 0)) {
     118  2453862870 :         probe >>= 1;
     119             : 
     120  2453862870 :         if (ch >= pairedChars[index + probe]) {
     121   573201105 :             index += probe;
     122             :         }
     123             :     }
     124             : 
     125   490772574 :     if (pairedChars[index] != ch) {
     126   490547504 :         index = -1;
     127             :     }
     128             : 
     129   490772574 :     return index;
     130             : }
     131             : 
     132   490772574 : UBool ScriptRun::sameScript(int32_t scriptOne, int32_t scriptTwo)
     133             : {
     134   490772574 :     return scriptOne <= USCRIPT_INHERITED || scriptTwo <= USCRIPT_INHERITED || scriptOne == scriptTwo;
     135             : }
     136             : 
     137     4280578 : UBool ScriptRun::next()
     138             : {
     139     4280578 :     int32_t startSP  = parenSP;  // used to find the first new open character
     140     4280578 :     UErrorCode error = U_ZERO_ERROR;
     141             : 
     142             :     // if we've fallen off the end of the text, we're done
     143     4280578 :     if (scriptEnd >= charLimit) {
     144     2138064 :         return false;
     145             :     }
     146             : 
     147     2142514 :     scriptCode = USCRIPT_COMMON;
     148             : 
     149   492911208 :     for (scriptStart = scriptEnd; scriptEnd < charLimit; scriptEnd += 1) {
     150   490772574 :         UChar   high = charArray[scriptEnd];
     151   490772574 :         UChar32 ch   = high;
     152             : 
     153             :         // if the character is a high surrogate and it's not the last one
     154             :         // in the text, see if it's followed by a low surrogate
     155   490772574 :         if (high >= 0xD800 && high <= 0xDBFF && scriptEnd < charLimit - 1)
     156             :         {
     157           0 :             UChar low = charArray[scriptEnd + 1];
     158             : 
     159             :             // if it is followed by a low surrogate,
     160             :             // consume it and form the full character
     161           0 :             if (low >= 0xDC00 && low <= 0xDFFF) {
     162           0 :                 ch = (high - 0xD800) * 0x0400 + low - 0xDC00 + 0x10000;
     163           0 :                 scriptEnd += 1;
     164             :             }
     165             :         }
     166             : 
     167   490772574 :         UScriptCode sc = uscript_getScript(ch, &error);
     168   490772574 :         int32_t pairIndex = getPairIndex(ch);
     169             : 
     170             :         // Paired character handling:
     171             : 
     172             :         // if it's an open character, push it onto the stack.
     173             :         // if it's a close character, find the matching open on the
     174             :         // stack, and use that script code. Any non-matching open
     175             :         // characters above it on the stack will be poped.
     176   490772574 :         if (pairIndex >= 0) {
     177      225070 :             if ((pairIndex & 1) == 0) {
     178       98794 :                 parenStack[++parenSP].pairIndex = pairIndex;
     179       98794 :                 parenStack[parenSP].scriptCode  = scriptCode;
     180      126276 :             } else if (parenSP >= 0) {
     181       90798 :                 int32_t pi = pairIndex & ~1;
     182             : 
     183      183764 :                 while (parenSP >= 0 && parenStack[parenSP].pairIndex != pi) {
     184        2168 :                     parenSP -= 1;
     185             :                 }
     186             : 
     187       90798 :                 if (parenSP < startSP) {
     188         144 :                     startSP = parenSP;
     189             :                 }
     190             : 
     191       90798 :                 if (parenSP >= 0) {
     192       88792 :                     sc = parenStack[parenSP].scriptCode;
     193             :                 }
     194             :             }
     195             :         }
     196             : 
     197   490772574 :         if (sameScript(scriptCode, sc)) {
     198   490768694 :             if (scriptCode <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) {
     199     1298761 :                 scriptCode = sc;
     200             : 
     201             :                 // now that we have a final script code, fix any open
     202             :                 // characters we pushed before we knew the script code.
     203     2606352 :                 while (startSP < parenSP) {
     204        8830 :                     parenStack[++startSP].scriptCode = scriptCode;
     205             :                 }
     206             :             }
     207             : 
     208             :             // if this character is a close paired character,
     209             :             // pop it from the stack
     210   490768694 :             if (pairIndex >= 0 && (pairIndex & 1) != 0 && parenSP >= 0) {
     211       88786 :                 parenSP -= 1;
     212             :                 /* decrement startSP only if it is >= 0,
     213             :                    decrementing it unnecessarily will lead to memory corruption
     214             :                    while processing the above while block.
     215             :                    e.g. startSP = -4 , parenSP = -1
     216             :                 */
     217       88786 :                 if (startSP >= 0) {
     218        8686 :                     startSP -= 1;
     219             :                 }
     220             :             }
     221             :         } else {
     222             :             // if the run broke on a surrogate pair,
     223             :             // end it before the high surrogate
     224        3880 :             if (ch >= 0x10000) {
     225           0 :                 scriptEnd -= 1;
     226             :             }
     227             : 
     228        3880 :             break;
     229             :         }
     230             :     }
     231             : 
     232     2142514 :     return true;
     233             : }
     234             : 
     235        1233 : }

Generated by: LCOV version 1.10