/*
* 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-2005 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "LEFontInstance.h"
#include "OpenTypeTables.h"
#include "GlyphSubstitutionTables.h"
#include "ContextualSubstSubtables.h"
#include "GlyphIterator.h"
#include "LookupProcessor.h"
#include "CoverageTables.h"
#include "LESwaps.h"
/*
NOTE: This could be optimized somewhat by keeping track
of the previous sequenceIndex in the loop and doing next()
or prev() of the delta between that and the current
sequenceIndex instead of always resetting to the front.
*/
const LookupProcessor *lookupProcessor,
const LEFontInstance *fontInstance,
{
if (LE_FAILURE(success)) {
return;
}
}
}
le_bool ContextualSubstitutionBase::matchGlyphIDs(const TTGlyphID *glyphArray, le_uint16 glyphCount,
{
if (backtrack) {
direction = -1;
}
while (glyphCount > 0) {
if (! glyphIterator->next()) {
return FALSE;
}
return FALSE;
}
glyphCount -= 1;
}
return TRUE;
}
le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArray, le_uint16 glyphCount,
{
if (backtrack) {
direction = -1;
}
while (glyphCount > 0) {
if (! glyphIterator->next()) {
return FALSE;
}
if (glyphClass != matchClass) {
// Some fonts, e.g. Traditional Arabic, have classes
// in the class array which aren't in the class definition
// table. If we're looking for such a class, pretend that
// we found it.
return FALSE;
}
}
glyphCount -= 1;
}
return TRUE;
}
le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTableOffsetArray, le_uint16 glyphCount,
{
if (backtrack) {
direction = -1;
}
while (glyphCount > 0) {
if (! glyphIterator->next()) {
return FALSE;
}
return FALSE;
}
glyphCount -= 1;
}
return TRUE;
}
const LEFontInstance *fontInstance,
LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
return 0;
}
switch(SWAPW(subtableFormat))
{
case 0:
return 0;
case 1:
{
const ContextualSubstitutionFormat1Subtable *subtable = (const ContextualSubstitutionFormat1Subtable *) this;
}
case 2:
{
const ContextualSubstitutionFormat2Subtable *subtable = (const ContextualSubstitutionFormat2Subtable *) this;
}
case 3:
{
const ContextualSubstitutionFormat3Subtable *subtable = (const ContextualSubstitutionFormat3Subtable *) this;
}
default:
return 0;
}
}
const LEFontInstance *fontInstance,
LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
return 0;
}
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) {
if (coverageIndex < srSetCount) {
(const SubRuleSetTable *) ((char *) this + subRuleSetTableOffset);
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
return matchCount + 1;
}
}
}
// XXX If we get here, the table is mal-formed...
}
return 0;
}
const LEFontInstance *fontInstance,
LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
return 0;
}
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) {
(const SubClassSetTable *) ((char *) this + subClassSetTableOffset);
if (matchGlyphClasses(subClassRuleTable->classArray, matchCount, glyphIterator, classDefinitionTable)) {
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
return matchCount + 1;
}
}
}
// XXX If we get here, the table is mal-formed...
}
return 0;
}
const LEFontInstance *fontInstance,
LEErrorCode& success)const
{
if (LE_FAILURE(success)) {
return 0;
}
// Back up the glyph iterator so that we
// can call next() before the check, which
// will leave it pointing at the last glyph
// that matched when we're done.
glyphIterator->prev();
if (ContextualSubstitutionBase::matchGlyphCoverages(coverageTableOffsetArray, gCount, glyphIterator, (const char *) this)) {
ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, subCount, glyphIterator, fontInstance, position, success);
return gCount + 1;
}
return 0;
}
const LEFontInstance *fontInstance,
LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
return 0;
}
switch(SWAPW(subtableFormat))
{
case 0:
return 0;
case 1:
{
const ChainingContextualSubstitutionFormat1Subtable *subtable = (const ChainingContextualSubstitutionFormat1Subtable *) this;
}
case 2:
{
const ChainingContextualSubstitutionFormat2Subtable *subtable = (const ChainingContextualSubstitutionFormat2Subtable *) this;
}
case 3:
{
const ChainingContextualSubstitutionFormat3Subtable *subtable = (const ChainingContextualSubstitutionFormat3Subtable *) this;
}
default:
return 0;
}
}
// NOTE: This could be a #define, but that seems to confuse
// the Visual Studio .NET 2003 compiler on the calls to the
// GlyphIterator constructor. It somehow can't decide if
// emptyFeatureList matches an le_uint32 or an le_uint16...
le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor,
const LEFontInstance *fontInstance,
LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
return 0;
}
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) {
if (coverageIndex < srSetCount) {
(const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset);
le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
const TTGlyphID *inputGlyphArray = &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1];
continue;
}
tempIterator.prev();
if (! matchGlyphIDs(chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
continue;
}
continue;
}
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
return inputGlyphCount + 1;
}
}
}
// XXX If we get here, the table is mal-formed...
}
return 0;
}
le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor,
const LEFontInstance *fontInstance,
LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
return 0;
}
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) {
(const ChainSubClassSetTable *) ((char *) this + chainSubClassSetTableOffset);
le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
const le_uint16 *inputClassArray = &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1];
continue;
}
tempIterator.prev();
continue;
}
if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable)) {
continue;
}
if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable)) {
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
return inputGlyphCount + 1;
}
}
}
// XXX If we get here, the table is mal-formed...
}
return 0;
}
le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor,
const LEFontInstance *fontInstance,
LEErrorCode & success) const
{
if (LE_FAILURE(success)) {
return 0;
}
le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
const Offset *inputCoverageTableOffsetArray = &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1];
const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
const Offset *lookaheadCoverageTableOffsetArray = &inputCoverageTableOffsetArray[inputGlyphCount + 1];
return 0;
}
tempIterator.prev();
return 0;
}
lookaheadGlyphCount, &tempIterator, (const char *) this)) {
return 0;
}
// Back up the glyph iterator so that we
// can call next() before the check, which
// will leave it pointing at the last glyph
// that matched when we're done.
glyphIterator->prev();
inputGlyphCount, glyphIterator, (const char *) this)) {
ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
return inputGlyphCount;
}
return 0;
}