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 * 28 * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved 29 * 30 */ 31 32#include "LETypes.h" 33#include "LEFontInstance.h" 34#include "OpenTypeTables.h" 35#include "AnchorTables.h" 36#include "MarkArrays.h" 37#include "GlyphPositioningTables.h" 38#include "AttachmentPosnSubtables.h" 39#include "MarkToMarkPosnSubtables.h" 40#include "GlyphIterator.h" 41#include "LESwaps.h" 42 43U_NAMESPACE_BEGIN 44 45LEGlyphID MarkToMarkPositioningSubtable::findMark2Glyph(GlyphIterator *glyphIterator) const 46{ 47 if (glyphIterator->findMark2Glyph()) { 48 return glyphIterator->getCurrGlyphID(); 49 } 50 51 return 0xFFFF; 52} 53 54le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const 55{ 56 LEGlyphID markGlyph = glyphIterator->getCurrGlyphID(); 57 le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success); 58 59 if (LE_FAILURE(success)) { 60 return 0; 61 } 62 63 if (markCoverage < 0) { 64 // markGlyph isn't a covered mark glyph 65 return 0; 66 } 67 68 LEPoint markAnchor; 69 LEReferenceTo<MarkArray> markArray(base, success, SWAPW(markArrayOffset)); 70 if(LE_FAILURE(success)) { 71 return 0; 72 } 73 le_int32 markClass = markArray->getMarkClass(markArray, markGlyph, markCoverage, fontInstance, markAnchor, success); 74 le_uint16 mcCount = SWAPW(classCount); 75 76 if (markClass < 0 || markClass >= mcCount) { 77 // markGlyph isn't in the mark array or its 78 // mark class is too big. The table is mal-formed! 79 return 0; 80 } 81 82 GlyphIterator mark2Iterator(*glyphIterator); 83 LEGlyphID mark2Glyph = findMark2Glyph(&mark2Iterator); 84 le_int32 mark2Coverage = getBaseCoverage(base, (LEGlyphID) mark2Glyph, success); 85 LEReferenceTo<Mark2Array> mark2Array(base, success, (const Mark2Array *) ((char *) this + SWAPW(baseArrayOffset))); 86 if(LE_FAILURE(success)) return 0; 87 le_uint16 mark2Count = SWAPW(mark2Array->mark2RecordCount); 88 89 if (mark2Coverage < 0 || mark2Coverage >= mark2Count) { 90 // The mark2 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 LEReferenceTo<Mark2Record> mark2Record(base, success, &mark2Array->mark2RecordArray[mark2Coverage * mcCount]); 97 if(LE_FAILURE(success)) return 0; 98 Offset anchorTableOffset = SWAPW(mark2Record->mark2AnchorTableOffsetArray[markClass]); 99 LEReferenceTo<AnchorTable> anchorTable(mark2Array, success, anchorTableOffset); 100 if(LE_FAILURE(success)) return 0; 101 LEPoint mark2Anchor, markAdvance, pixels; 102 103 if (anchorTableOffset == 0) { 104 // this seems to mean that the marks don't attach... 105 return 0; 106 } 107 108 anchorTable->getAnchor(anchorTable, mark2Glyph, fontInstance, mark2Anchor, success); 109 110 fontInstance->getGlyphAdvance(markGlyph, pixels); 111 fontInstance->pixelsToUnits(pixels, markAdvance); 112 113 float anchorDiffX = mark2Anchor.fX - markAnchor.fX; 114 float anchorDiffY = mark2Anchor.fY - markAnchor.fY; 115 116 _LETRACE("Offset: (%.2f, %.2f) glyph 0x%X mark2 0x%X", anchorDiffX, anchorDiffY, markGlyph, mark2Glyph); 117 118 glyphIterator->setCurrGlyphBaseOffset(mark2Iterator.getCurrStreamPosition()); 119 120 if (glyphIterator->isRightToLeft()) { 121 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX, anchorDiffY, -markAdvance.fX, -markAdvance.fY); 122 } else { 123 LEPoint mark2Advance; 124 125 fontInstance->getGlyphAdvance(mark2Glyph, pixels); 126 fontInstance->pixelsToUnits(pixels, mark2Advance); 127 128 glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - mark2Advance.fX, anchorDiffY - mark2Advance.fY, -markAdvance.fX, -markAdvance.fY); 129 } 130 131 return 1; 132} 133 134U_NAMESPACE_END 135