1/* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26/* 27 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved 28 * 29 */ 30 31#include "LETypes.h" 32#include "LEFontInstance.h" 33#include "OpenTypeTables.h" 34#include "AnchorTables.h" 35#include "MarkArrays.h" 36#include "GlyphPositioningTables.h" 37#include "AttachmentPosnSubtables.h" 38#include "MarkToLigaturePosnSubtables.h" 39#include "GlyphIterator.h" 40#include "LESwaps.h" 41 42U_NAMESPACE_BEGIN 43 44LEGlyphID MarkToLigaturePositioningSubtable::findLigatureGlyph(GlyphIterator *glyphIterator) const 45{ 46 if (glyphIterator->prev()) { 47 return glyphIterator->getCurrGlyphID(); 48 } 49 50 return 0xFFFF; 51} 52 53le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const 54{ 55 LEGlyphID markGlyph = glyphIterator->getCurrGlyphID(); 56 le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success); 57 58 if (LE_FAILURE(success)) { 59 return 0; 60 } 61 62 if (markCoverage < 0) { 63 // markGlyph isn't a covered mark glyph 64 return 0; 65 } 66 67 LEPoint markAnchor; 68 LEReferenceTo<MarkArray> markArray(base, success, SWAPW(markArrayOffset)); 69 if( LE_FAILURE(success) ) { 70 return 0; 71 } 72 le_int32 markClass = markArray->getMarkClass(markArray, markGlyph, markCoverage, fontInstance, markAnchor, success); 73 le_uint16 mcCount = SWAPW(classCount); 74 75 if (markClass < 0 || markClass >= mcCount) { 76 // markGlyph isn't in the mark array or its 77 // mark class is too big. The table is mal-formed! 78 return 0; 79 } 80 81 // FIXME: we probably don't want to find a ligature before a previous base glyph... 82 GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/)); 83 LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator); 84 le_int32 ligatureCoverage = getBaseCoverage(base, (LEGlyphID) ligatureGlyph, success); 85 LEReferenceTo<LigatureArray> ligatureArray(base, success, SWAPW(baseArrayOffset)); 86 if (LE_FAILURE(success)) { return 0; } 87 le_uint16 ligatureCount = SWAPW(ligatureArray->ligatureCount); 88 89 if (ligatureCoverage < 0 || ligatureCoverage >= ligatureCount) { 90 // The ligature glyph isn't covered, or the coverage 91 // index is too big. The latter means that the 92 // table is mal-formed... 93 return 0; 94 } 95 96 le_int32 markPosition = glyphIterator->getCurrStreamPosition(); 97 Offset ligatureAttachOffset = SWAPW(ligatureArray->ligatureAttachTableOffsetArray[ligatureCoverage]); 98 LEReferenceTo<LigatureAttachTable> ligatureAttachTable(ligatureArray, success, ligatureAttachOffset); 99 if (LE_FAILURE(success)) { return 0; } 100 le_int32 componentCount = SWAPW(ligatureAttachTable->componentCount); 101 le_int32 component = ligatureIterator.getMarkComponent(markPosition); 102 103 if (component >= componentCount) { 104 // should really just bail at this point... 105 component = componentCount - 1; 106 } 107 108 LEReferenceTo<ComponentRecord> componentRecord(base, success, &ligatureAttachTable->componentRecordArray[component * mcCount]); 109 if (LE_FAILURE(success)) { return 0; } 110 LEReferenceToArrayOf<Offset> ligatureAnchorTableOffsetArray(base, success, &(componentRecord->ligatureAnchorTableOffsetArray[0]), mcCount); 111 if( LE_FAILURE(success) ) { return 0; } 112 Offset anchorTableOffset = SWAPW(componentRecord->ligatureAnchorTableOffsetArray[markClass]); 113 LEReferenceTo<AnchorTable> anchorTable(ligatureAttachTable, success, anchorTableOffset); 114 if (LE_FAILURE(success)) { return 0; } 115 LEPoint ligatureAnchor, markAdvance, pixels; 116 117 anchorTable->getAnchor(anchorTable, ligatureGlyph, fontInstance, ligatureAnchor, success); 118 119 fontInstance->getGlyphAdvance(markGlyph, pixels); 120 fontInstance->pixelsToUnits(pixels, markAdvance); 121 122 float anchorDiffX = ligatureAnchor.fX - markAnchor.fX; 123 float anchorDiffY = ligatureAnchor.fY - markAnchor.fY; 124 125 glyphIterator->setCurrGlyphBaseOffset(ligatureIterator.getCurrStreamPosition()); 126 127 if (glyphIterator->isRightToLeft()) { 128 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX, anchorDiffY, -markAdvance.fX, -markAdvance.fY); 129 } else { 130 LEPoint ligatureAdvance; 131 132 fontInstance->getGlyphAdvance(ligatureGlyph, pixels); 133 fontInstance->pixelsToUnits(pixels, ligatureAdvance); 134 135 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - ligatureAdvance.fX, anchorDiffY - ligatureAdvance.fY, -markAdvance.fX, -markAdvance.fY); 136 } 137 138 return 1; 139} 140 141U_NAMESPACE_END 142