Home | History | Annotate | Download | only in layout
      1 /*
      2  * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
      3  *
      4  */
      5 
      6 #include "LETypes.h"
      7 #include "LEFontInstance.h"
      8 #include "OpenTypeTables.h"
      9 #include "AnchorTables.h"
     10 #include "MarkArrays.h"
     11 #include "GlyphPositioningTables.h"
     12 #include "AttachmentPosnSubtables.h"
     13 #include "MarkToLigaturePosnSubtables.h"
     14 #include "GlyphIterator.h"
     15 #include "LESwaps.h"
     16 
     17 U_NAMESPACE_BEGIN
     18 
     19 LEGlyphID MarkToLigaturePositioningSubtable::findLigatureGlyph(GlyphIterator *glyphIterator) const
     20 {
     21     if (glyphIterator->prev()) {
     22         return glyphIterator->getCurrGlyphID();
     23     }
     24 
     25     return 0xFFFF;
     26 }
     27 
     28 le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
     29 {
     30     LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
     31     le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
     32 
     33     if (markCoverage < 0) {
     34         // markGlyph isn't a covered mark glyph
     35         return 0;
     36     }
     37 
     38     LEPoint markAnchor;
     39     const MarkArray *markArray = (const MarkArray *) ((char *) this + SWAPW(markArrayOffset));
     40     le_int32 markClass = markArray->getMarkClass(markGlyph, markCoverage, fontInstance, markAnchor);
     41     le_uint16 mcCount = SWAPW(classCount);
     42 
     43     if (markClass < 0 || markClass >= mcCount) {
     44         // markGlyph isn't in the mark array or its
     45         // mark class is too big. The table is mal-formed!
     46         return 0;
     47     }
     48 
     49     // FIXME: we probably don't want to find a ligature before a previous base glyph...
     50     GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/));
     51     LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator);
     52     le_int32 ligatureCoverage = getBaseCoverage(base, (LEGlyphID) ligatureGlyph, success);
     53     const LigatureArray *ligatureArray = (const LigatureArray *) ((char *) this + SWAPW(baseArrayOffset));
     54     le_uint16 ligatureCount = SWAPW(ligatureArray->ligatureCount);
     55 
     56     if (ligatureCoverage < 0 || ligatureCoverage >= ligatureCount) {
     57         // The ligature glyph isn't covered, or the coverage
     58         // index is too big. The latter means that the
     59         // table is mal-formed...
     60         return 0;
     61     }
     62 
     63     le_int32 markPosition = glyphIterator->getCurrStreamPosition();
     64     Offset ligatureAttachOffset = SWAPW(ligatureArray->ligatureAttachTableOffsetArray[ligatureCoverage]);
     65     const LigatureAttachTable *ligatureAttachTable = (const LigatureAttachTable *) ((char *) ligatureArray + ligatureAttachOffset);
     66     le_int32 componentCount = SWAPW(ligatureAttachTable->componentCount);
     67     le_int32 component = ligatureIterator.getMarkComponent(markPosition);
     68 
     69     if (component >= componentCount) {
     70         // should really just bail at this point...
     71         component = componentCount - 1;
     72     }
     73 
     74     const ComponentRecord *componentRecord = &ligatureAttachTable->componentRecordArray[component * mcCount];
     75     Offset anchorTableOffset = SWAPW(componentRecord->ligatureAnchorTableOffsetArray[markClass]);
     76     const AnchorTable *anchorTable = (const AnchorTable *) ((char *) ligatureAttachTable + anchorTableOffset);
     77     LEPoint ligatureAnchor, markAdvance, pixels;
     78 
     79     anchorTable->getAnchor(ligatureGlyph, fontInstance, ligatureAnchor);
     80 
     81     fontInstance->getGlyphAdvance(markGlyph, pixels);
     82     fontInstance->pixelsToUnits(pixels, markAdvance);
     83 
     84     float anchorDiffX = ligatureAnchor.fX - markAnchor.fX;
     85     float anchorDiffY = ligatureAnchor.fY - markAnchor.fY;
     86 
     87     glyphIterator->setCurrGlyphBaseOffset(ligatureIterator.getCurrStreamPosition());
     88 
     89     if (glyphIterator->isRightToLeft()) {
     90         glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX, anchorDiffY, -markAdvance.fX, -markAdvance.fY);
     91     } else {
     92         LEPoint ligatureAdvance;
     93 
     94         fontInstance->getGlyphAdvance(ligatureGlyph, pixels);
     95         fontInstance->pixelsToUnits(pixels, ligatureAdvance);
     96 
     97         glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - ligatureAdvance.fX, anchorDiffY - ligatureAdvance.fY, -markAdvance.fX, -markAdvance.fY);
     98     }
     99 
    100     return 1;
    101 }
    102 
    103 U_NAMESPACE_END
    104