/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
*
* (C) Copyright IBM Corp. 1998-2009 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "OpenTypeTables.h"
#include "OpenTypeUtilities.h"
#include "IndicReordering.h"
#include "LEGlyphStorage.h"
#include "MPreFixups.h"
// Syllable structure bits
#define basicShapingFormsMask ( loclFeatureMask | nuktFeatureMask | akhnFeatureMask | rkrfFeatureMask | blwfFeatureMask | halfFeatureMask | vatuFeatureMask | cjctFeatureMask )
#define positioningFormsMask ( kernFeatureMask | distFeatureMask | abvmFeatureMask | blwmFeatureMask )
#define presentationFormsMask ( presFeatureMask | abvsFeatureMask | blwsFeatureMask | pstsFeatureMask | halnFeatureMask | caltFeatureMask )
// Some level of debate as to the proper value for MAX_CONSONANTS_PER_SYLLABLE. Ticket 5588 states that 4
// is the magic number according to ISCII, but 5 seems to be the more consistent with XP.
private:
{
// FIXME: check if already set, or if not a matra...
fLengthMark = matra;
} else {
switch (matraClass & CF_POS_MASK) {
case CF_POS_BEFORE:
break;
case CF_POS_BELOW:
break;
case CF_POS_ABOVE:
break;
case CF_POS_AFTER:
break;
default:
// can't get here...
break;
}
}
}
public:
{
// nothing else to do...
}
{
// nothing to do here...
}
void reset()
{
fSyllableCount += 1;
fMPreOutIndex = -1;
fPreBaseConsonant = fPreBaseVirama = 0;
}
{
fGlyphStorage.setAuxData(fOutIndex, charFeatures | (fSyllableCount & LE_GLYPH_GROUP_MASK), success);
fOutIndex += 1;
}
{
}
{
}
void decomposeReorderMatras ( const IndicClassTable *classTable, le_int32 beginSyllable, le_int32 nextSyllable, le_int32 inv_count ) {
le_int32 i;
for ( i = beginSyllable ; i < nextSyllable ; i++ ) {
int j;
for (j = 0 ; j < SM_MAX_PIECES && *(splitMatra)[j] != 0 ; j++) {
if ( j == 0 ) {
} else {
nextSyllable++;
}
}
}
}
}
}
}
if ( fromPosition > toPosition ) {
for ( i = fromPosition ; i > toPosition ; i-- ) {
}
} else {
for ( i = fromPosition ; i < toPosition ; i++ ) {
}
}
}
le_int32 i;
fOutIndex += 1;
for ( i = fOutIndex ; i > toPosition ; i--) {
}
}
le_int32 i;
fOutIndex -= 1;
for ( i = fromPosition ; i < fOutIndex ; i--) {
}
}
le_bool noteMatra(const IndicClassTable *classTable, LEUnicode matra, le_uint32 matraIndex, FeatureMask matraFeatures, le_bool wordStart)
{
if (wordStart) {
}
int i;
}
} else {
}
return TRUE;
}
return FALSE;
}
void noteVowelModifier(const IndicClassTable *classTable, LEUnicode vowelModifier, le_uint32 vowelModifierIndex, FeatureMask vowelModifierFeatures)
{
switch (vmClass & CF_POS_MASK) {
case CF_POS_ABOVE:
break;
case CF_POS_AFTER:
break;
default:
// FIXME: this is an error...
break;
}
}
}
void noteStressMark(const IndicClassTable *classTable, LEUnicode stressMark, le_uint32 stressMarkIndex, FeatureMask stressMarkFeatures)
{
switch (smClass & CF_POS_MASK) {
case CF_POS_ABOVE:
break;
case CF_POS_BELOW:
break;
default:
// FIXME: this is an error...
break;
}
}
}
void notePreBaseConsonant(le_uint32 index,LEUnicode PBConsonant, LEUnicode PBVirama, FeatureMask features)
{
}
void noteBaseConsonant()
{
}
}
// Handles Al-Lakuna in Sinhala split vowels.
void writeAlLakuna()
{
if (fAlLakuna != 0) {
}
}
void writeMpre()
{
if (fMpre != 0) {
}
}
void writeMbelow()
{
if (fMbelow != 0) {
}
}
void writeMabove()
{
if (fMabove != 0) {
}
}
void writeMpost()
{
if (fMpost != 0) {
}
}
void writeLengthMark()
{
if (fLengthMark != 0) {
}
}
void writeVMabove()
{
if (fVMabove != 0) {
}
}
void writeVMpost()
{
if (fVMpost != 0) {
}
}
void writeSMabove()
{
if (fSMabove != 0) {
}
}
void writeSMbelow()
{
if (fSMbelow != 0) {
}
}
void writePreBaseConsonant()
{
// The TDIL spec says that consonant + virama + RRA should produce a rakar in Malayalam. However,
// it seems that almost none of the fonts for Malayalam are set up to handle this.
// So, we're going to force the issue here by using the rakar as defined with RA in most fonts.
}
if (fPreBaseConsonant != 0) {
}
}
{
return fOutIndex;
}
};
// TODO: Find better names for these!
#define tagArray4 (loclFeatureMask | nuktFeatureMask | akhnFeatureMask | vatuFeatureMask | presFeatureMask | blwsFeatureMask | abvsFeatureMask | pstsFeatureMask | halnFeatureMask | blwmFeatureMask | abvmFeatureMask | distFeatureMask)
};
};
{
// xx vm sm iv i2 i3 ct cn nu dv s1 s2 s3 vr zw al
{ 1, 6, 1, 5, 8, 11, 3, 2, 1, 5, 9, 5, 5, 1, 1, 1}, // 0 - ground state
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 1 - exit state
{-1, 6, 1, -1, -1, -1, -1, -1, -1, 5, 9, 5, 5, 4, 12, -1}, // 2 - consonant with nukta
{-1, 6, 1, -1, -1, -1, -1, -1, 2, 5, 9, 5, 5, 4, 12, 13}, // 3 - consonant
{-1, -1, -1, -1, -1, -1, 3, 2, -1, -1, -1, -1, -1, -1, 7, -1}, // 4 - consonant virama
{-1, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 5 - dependent vowels
{-1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 6 - vowel mark
{-1, -1, -1, -1, -1, -1, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1}, // 7 - consonant virama ZWJ, consonant ZWJ virama
{-1, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1}, // 8 - independent vowels that can take a virama
{-1, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 5, -1, -1, -1}, // 9 - first part of split vowel
{-1, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1}, // 10 - second part of split vowel
{-1, 6, 1, -1, -1, -1, -1, -1, -1, 5, 9, 5, 5, 4, -1, -1}, // 11 - independent vowels that can take an iv
{-1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, 7}, // 12 - consonant ZWJ (TODO: Take everything else that can be after a consonant?)
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1} // 13 - consonant al-lakuna ZWJ consonant
};
{
return featureMap;
}
{
return v2FeatureMap;
}
le_int32 IndicReordering::findSyllable(const IndicClassTable *classTable, const LEUnicode *chars, le_int32 prev, le_int32 charCount)
{
if ( consonant_count > MAX_CONSONANTS_PER_SYLLABLE ) {
break;
}
}
if (state < 0) {
break;
}
cursor += 1;
}
return cursor;
}
{
if (LE_FAILURE(success)) {
return 0;
}
if(classTable==NULL) {
return 0;
}
if (mpreFixups == NULL) {
return 0;
}
}
markStart -= 1;
}
markStart -= 1;
}
while (output.noteMatra(classTable, chars[matra], matra, tagArray1, !lastInWord) && matra != prev) {
matra -= 1;
}
lastInWord = TRUE;
case CC_RESERVED:
lastInWord = FALSE;
/* fall through */
case CC_INDEPENDENT_VOWEL:
case CC_ZERO_WIDTH_MARK:
}
break;
case CC_AL_LAKUNA:
case CC_NUKTA:
break;
case CC_VIRAMA:
// A lone virama is illegal unless it follows a
// MALAYALAM_VOWEL_SIGN_U. Such a usage is called
// "samvruthokaram".
}
break;
case CC_DEPENDENT_VOWEL:
case CC_SPLIT_VOWEL_PIECE_1:
case CC_SPLIT_VOWEL_PIECE_2:
case CC_SPLIT_VOWEL_PIECE_3:
case CC_VOWEL_MODIFIER:
case CC_STRESS_MARK:
output.writeMpost();
}
}
output.writeMpost();
}
}
break;
case CC_INDEPENDENT_VOWEL_2:
case CC_INDEPENDENT_VOWEL_3:
case CC_CONSONANT:
case CC_CONSONANT_WITH_NUKTA:
{
// Check for REPH at front of syllable
if (length > 2 && classTable->isReph(chars[prev]) && classTable->isVirama(chars[prev + 1]) && chars[prev + 2] != C_SIGN_ZWNJ) {
baseLimit += 2;
// Check for eyelash RA, if the script supports it
if (length > 3) {
baseLimit += 1;
} else {
baseLimit -= 2;
}
}
}
lastConsonant -= 1;
}
postBase += 1;
}
while (baseConsonant > baseLimit) {
if (postBaseLimit == 0 || seenVattu ||
break;
}
// Note any pre-base consonants
}
// consonants with nuktas are never vattus
// consonants with nuktas never have below- or post-base forms
if (hasPostBaseForm) {
if (seenBelowBaseForm) {
break;
}
} else if (hasBelowBaseForm) {
}
postBaseLimit -= 1;
}
baseConsonant -= 1;
}
// Write Mpre
// Write eyelash RA
// NOTE: baseLimit == prev + 3 iff eyelash RA present...
}
// write any pre-base consonants
// Don't put 'pstf' or 'blwf' on anything before the base consonant.
}
{
}
}
bcSpan += 1;
}
bcSpan += 1;
bcSpan += 1;
}
}
// note the base consonant for post-GSUB fixups
// write base consonant
}
output.writeMpost();
}
// write below-base consonants
}
if (postBase > lastConsonant) {
// write halant that was after base consonant
}
}
// write Mbelow, SMbelow, Mabove
}
}
}
// write post-base consonants
// FIXME: does this put the right tags on post-base consonants?
if (postBase <= lastConsonant) {
}
// write halant that was after base consonant
}
// write the training halant, if there is one
}
}
// write Mpost
output.writeMpost();
}
// write reph
}
}
break;
}
default:
break;
}
}
return output.getOutputIndex();
}
void IndicReordering::adjustMPres(MPreFixups *mpreFixups, LEGlyphStorage &glyphStorage, LEErrorCode& success)
{
if (mpreFixups != NULL) {
delete mpreFixups;
}
}
{
// This sets us up for 2nd pass of glyph substitution as well as setting the feature masks for the
// GPOS table lookups
}
}
{
// Reposition REPH as appropriate
if ( ( tmpGlyph != NO_GLYPH ) && (tmpAuxData & rephConsonantMask) && !(tmpAuxData & repositionedGlyphMask)) {
while (!targetPositionFound) {
if ( tmpAuxData & baseConsonantMask ) {
targetPositionFound = true;
} else {
}
}
// Make sure we are not putting the reph into an empty hole
while (!targetPositionHasGlyph) {
targetPositionHasGlyph = true;
} else {
}
}
// Make sure that REPH is positioned after any above base or post base matras
//
while ( !checkMatraDone ) {
checkMatraDone = true;
continue;
}
if ( (tmpAuxData & matraMask) &&
}
}
}
}
}
le_int32 IndicReordering::v2process(const LEUnicode *chars, le_int32 charCount, le_int32 scriptCode,
{
//le_bool lastInWord = FALSE;
while (beginSyllable < charCount) {
// Find the First Consonant
break;
}
}
// Find the base consonant
// TODO: Use Dynamic Properties for hasBelowBaseForm and hasPostBaseForm()
while ( baseConsonant > firstConsonant ) {
break;
}
else {
}
}
}
// If the syllable starts with Ra + Halant ( in a script that has Reph ) and has more than one
// consonant, Ra is excluced from candidates for base consonants
}
// Populate the output
for ( i = beginSyllable ; i < nextSyllable ; i++ ) {
// Handle invalid combinartions
inv_count++;
}
}
// Adjust features and set syllable structure bits
for ( i = beginSyllable ; i < nextSyllable ; i++ ) {
// Since reph can only validly occur at the beginning of a syllable
// We only apply it to the first 2 characters in the syllable, to keep it from
// conflicting with other features ( i.e. rkrf )
// TODO : Use the dynamic property for determining isREPH
}
if ( i == baseConsonant ) {
}
}
}
// Don't apply half form to virama that stands alone at the end of a syllable
// to prevent half forms from forming when syllable ends with virama
tmp ^= halfFeatureMask;
}
}
}
}
}
return output.getOutputIndex();
}
void IndicReordering::getDynamicProperties( DynamicProperties *, const IndicClassTable *classTable ) {
//le_int32 offset = 0;
#if 0
// TODO: Should this section of code have actually been doing something?
// First find the relevant virama for the script we are dealing with
break;
}
}
#endif
workOutput.reset();
}
}
}