0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A *
0N/A */
0N/A
0N/A/*
0N/A *
0N/A * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
0N/A *
0N/A */
0N/A
0N/A#include "LETypes.h"
0N/A#include "LEFontInstance.h"
0N/A#include "OpenTypeTables.h"
0N/A#include "GlyphPositioningTables.h"
0N/A#include "PairPositioningSubtables.h"
0N/A#include "ValueRecords.h"
0N/A#include "GlyphIterator.h"
0N/A#include "OpenTypeUtilities.h"
0N/A#include "LESwaps.h"
0N/A
1693N/AU_NAMESPACE_BEGIN
1693N/A
5980N/Ale_uint32 PairPositioningSubtable::process(const LEReferenceTo<PairPositioningSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
0N/A{
0N/A switch(SWAPW(subtableFormat))
0N/A {
0N/A case 0:
0N/A return 0;
0N/A
0N/A case 1:
0N/A {
5980N/A const LEReferenceTo<PairPositioningFormat1Subtable> subtable(base, success, (const PairPositioningFormat1Subtable *) this);
0N/A
5980N/A if(LE_SUCCESS(success))
5980N/A return subtable->process(subtable, glyphIterator, fontInstance, success);
5980N/A else
5980N/A return 0;
0N/A }
0N/A
0N/A case 2:
0N/A {
5980N/A const LEReferenceTo<PairPositioningFormat2Subtable> subtable(base, success, (const PairPositioningFormat2Subtable *) this);
0N/A
5980N/A if(LE_SUCCESS(success))
5980N/A return subtable->process(subtable, glyphIterator, fontInstance, success);
5980N/A else
5980N/A return 0;
0N/A }
0N/A default:
5980N/A return 0;
0N/A }
0N/A}
0N/A
5980N/Ale_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
0N/A{
0N/A LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
5980N/A le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
6368N/A
6368N/A if (LE_FAILURE(success)) {
6368N/A return 0;
6368N/A }
0N/A GlyphIterator tempIterator(*glyphIterator);
0N/A
0N/A if (coverageIndex >= 0 && glyphIterator->next()) {
0N/A Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]);
6368N/A LEReferenceTo<PairSetTable> pairSetTable(base, success, ((char *) this + pairSetTableOffset));
6368N/A if (LE_FAILURE(success)) {
6368N/A return 0;
6368N/A }
0N/A le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount);
0N/A le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
0N/A le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
0N/A le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size;
0N/A LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
6368N/A LEReferenceTo<PairValueRecord> pairValueRecord;
0N/A
0N/A if (pairValueCount != 0) {
6368N/A pairValueRecord = findPairValueRecord(base, (TTGlyphID) LE_GET_GLYPH(secondGlyph), pairSetTable->pairValueRecordArray, pairValueCount, recordSize, success);
0N/A }
0N/A
6368N/A if (pairValueRecord.isEmpty()) {
0N/A return 0;
0N/A }
0N/A
0N/A if (valueFormat1 != 0) {
1693N/A pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance);
0N/A }
0N/A
0N/A if (valueFormat2 != 0) {
0N/A const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size);
0N/A
0N/A valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, *glyphIterator, fontInstance);
0N/A }
0N/A
3171N/A // back up glyphIterator so second glyph can be
3171N/A // first glyph in the next pair
3171N/A glyphIterator->prev();
3171N/A return 1;
0N/A }
0N/A
0N/A return 0;
0N/A}
0N/A
5980N/Ale_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
0N/A{
0N/A LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
5980N/A le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
6371N/A
6371N/A if (LE_FAILURE(success)) {
6371N/A return 0;
6371N/A }
6371N/A
0N/A GlyphIterator tempIterator(*glyphIterator);
0N/A
0N/A if (coverageIndex >= 0 && glyphIterator->next()) {
0N/A LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
0N/A const ClassDefinitionTable *classDef1 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef1Offset));
0N/A const ClassDefinitionTable *classDef2 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef2Offset));
0N/A le_int32 class1 = classDef1->getGlyphClass(firstGlyph);
0N/A le_int32 class2 = classDef2->getGlyphClass(secondGlyph);
0N/A le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
0N/A le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
0N/A le_int16 class2RecordSize = valueRecord1Size + valueRecord2Size;
0N/A le_int16 class1RecordSize = class2RecordSize * SWAPW(class2Count);
0N/A const Class1Record *class1Record = (const Class1Record *) ((char *) class1RecordArray + (class1RecordSize * class1));
0N/A const Class2Record *class2Record = (const Class2Record *) ((char *) class1Record->class2RecordArray + (class2RecordSize * class2));
0N/A
0N/A
0N/A if (valueFormat1 != 0) {
0N/A class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance);
0N/A }
0N/A
0N/A if (valueFormat2 != 0) {
0N/A const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &class2Record->valueRecord1 + valueRecord1Size);
0N/A
0N/A valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, *glyphIterator, fontInstance);
0N/A }
0N/A
3171N/A // back up glyphIterator so second glyph can be
3171N/A // first glyph in the next pair
3171N/A glyphIterator->prev();
3171N/A return 1;
0N/A }
0N/A
0N/A return 0;
0N/A}
0N/A
6368N/ALEReferenceTo<PairValueRecord> PairPositioningFormat1Subtable::findPairValueRecord(const LETableReference &base, TTGlyphID glyphID, const PairValueRecord *records, le_uint16 recordCount, le_uint16 recordSize, LEErrorCode &success) const
0N/A{
3171N/A#if 1
3171N/A // The OpenType spec. says that the ValueRecord table is
3171N/A // sorted by secondGlyph. Unfortunately, there are fonts
3171N/A // around that have an unsorted ValueRecord table.
6368N/A LEReferenceTo<PairValueRecord> record(base, success, records);
6368N/A record.verifyLength(0, recordSize, success);
3171N/A
3171N/A for(le_int32 r = 0; r < recordCount; r += 1) {
6368N/A if (LE_FAILURE(success)) return (const PairValueRecord*)NULL;
3171N/A if (SWAPW(record->secondGlyph) == glyphID) {
3171N/A return record;
3171N/A }
3171N/A
6368N/A record = LEReferenceTo<PairValueRecord>(base, success, ((const char*)record.getAlias())+ recordSize);
6368N/A record.verifyLength(0, recordSize, success);
3171N/A }
3171N/A#else
6368N/A #error dead code - not updated.
0N/A le_uint8 bit = OpenTypeUtilities::highBit(recordCount);
0N/A le_uint16 power = 1 << bit;
0N/A le_uint16 extra = (recordCount - power) * recordSize;
0N/A le_uint16 probe = power * recordSize;
0N/A const PairValueRecord *record = records;
0N/A const PairValueRecord *trial = (const PairValueRecord *) ((char *) record + extra);
0N/A
0N/A if (SWAPW(trial->secondGlyph) <= glyphID) {
0N/A record = trial;
0N/A }
0N/A
0N/A while (probe > recordSize) {
0N/A probe >>= 1;
0N/A trial = (const PairValueRecord *) ((char *) record + probe);
0N/A
0N/A if (SWAPW(trial->secondGlyph) <= glyphID) {
0N/A record = trial;
0N/A }
0N/A }
0N/A
0N/A if (SWAPW(record->secondGlyph) == glyphID) {
0N/A return record;
0N/A }
3171N/A#endif
0N/A
6368N/A return (const PairValueRecord*)NULL;
0N/A}
1693N/A
1693N/AU_NAMESPACE_END