Home | History | Annotate | Download | only in layout
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /**
      4  *******************************************************************************
      5  * Copyright (C) 2002-2010, International Business Machines Corporation and    *
      6  * others. All Rights Reserved.                                                *
      7  *******************************************************************************
      8  */
      9 
     10 package com.ibm.icu.dev.tool.layout;
     11 
     12 import java.util.Vector;
     13 
     14 import com.ibm.icu.text.UTF16;
     15 
     16 /**
     17  * @author Owner
     18  *
     19  * To change the template for this generated type comment go to
     20  * Window>Preferences>Java>Code Generation>Code and Comments
     21  */
     22 public class DecompTable implements LookupSubtable
     23 {
     24     static class DecompEntry
     25     {
     26         private int composed;
     27         private int[] decomp;
     28 
     29         DecompEntry(int composedChar, String decomposition)
     30         {
     31             int decompCount = UTF16.countCodePoint(decomposition);
     32 
     33             composed = composedChar;
     34             decomp = new int[decompCount];
     35 
     36             int out = 0, cp;
     37 
     38             for (int in = 0; in < decomposition.length(); in += UTF16.getCharCount(cp)) {
     39                 cp = UTF16.charAt(decomposition, in);
     40                 decomp[out++] = cp;
     41             }
     42         }
     43 
     44         public int getComposedCharacter()
     45         {
     46             return composed;
     47         }
     48 
     49         public int[] getDecomposition()
     50         {
     51             return decomp;
     52         }
     53 
     54         public int getDecompositionCount()
     55         {
     56             return decomp.length;
     57         }
     58 
     59         public int getDecomposedCharacter(int i)
     60         {
     61             if (i >= 0 && i < decomp.length) {
     62                 return decomp[i];
     63             }
     64 
     65             return -1;
     66         }
     67 
     68         public int compareTo(DecompEntry that)
     69         {
     70             return this.composed - that.composed;
     71         }
     72 
     73         //
     74         // Straight insertion sort from Knuth vol. III, pg. 81
     75         //
     76         public static void sort(DecompEntry[] table, Vector decompVector)
     77         {
     78             for (int j = 0; j < table.length; j += 1) {
     79                 int i;
     80                 DecompEntry v = (DecompEntry) decompVector.elementAt(j);
     81 
     82                 for (i = j - 1; i >= 0; i -= 1) {
     83                     if (v.compareTo(table[i]) >= 0) {
     84                       break;
     85                     }
     86 
     87                     table[i + 1] = table[i];
     88                 }
     89 
     90                 table[i + 1] = v;
     91             }
     92         }
     93     }
     94 
     95     private Vector decompVector;
     96     private DecompEntry[] decompEntries;
     97     private int snapshotSize;
     98 
     99     public DecompTable()
    100     {
    101         decompVector = new Vector();
    102         decompEntries = null;
    103         snapshotSize = -1;
    104     }
    105 
    106     public void add(int composed, String decomposition)
    107     {
    108         DecompEntry entry = new DecompEntry(composed, decomposition);
    109 
    110         decompVector.addElement(entry);
    111     }
    112 
    113     public int getComposedCharacter(int i)
    114     {
    115         if (i < 0 || i > decompEntries.length) {
    116             return -1;
    117         }
    118 
    119         return decompEntries[i].getComposedCharacter();
    120     }
    121 
    122     public int getDecompositionCount(int i)
    123     {
    124         if (i < 0 || i > decompEntries.length) {
    125             return -1;
    126         }
    127 
    128         return decompEntries[i].getDecompositionCount();
    129     }
    130 
    131     public boolean hasEntries()
    132     {
    133         return decompVector.size() > 0;
    134     }
    135 
    136     private void snapshot()
    137     {
    138         if (snapshotSize != decompVector.size()) {
    139             snapshotSize = decompVector.size();
    140             decompEntries = new DecompEntry[snapshotSize];
    141             DecompEntry.sort(decompEntries, decompVector);
    142         }
    143     }
    144 
    145     public void writeLookupSubtable(OpenTypeTableWriter writer)
    146     {
    147         snapshot();
    148 
    149         int multipleSubstitutionsBase = writer.getOutputIndex();
    150         int coverageTableIndex, sequenceOffsetIndex;
    151         int sequenceCount = decompEntries.length;
    152 
    153         writer.writeData(1); // format = 1
    154 
    155         coverageTableIndex = writer.getOutputIndex();
    156         writer.writeData(0); // coverage table offset (fixed later)
    157 
    158         writer.writeData(sequenceCount);
    159 
    160         sequenceOffsetIndex = writer.getOutputIndex();
    161         for (int s = 0; s < sequenceCount; s += 1) {
    162             writer.writeData(0); // offset to sequence table (fixed later);
    163         }
    164 
    165         for (int s = 0; s < sequenceCount; s += 1) {
    166             DecompEntry entry = decompEntries[s];
    167             int decompCount = entry.getDecompositionCount();
    168 
    169             writer.fixOffset(sequenceOffsetIndex++, multipleSubstitutionsBase);
    170 
    171             writer.writeData(decompCount); // glyphCount
    172 
    173             for (int g = 0; g < decompCount; g += 1) {
    174                 writer.writeData(entry.getDecomposedCharacter(g));
    175             }
    176         }
    177 
    178         // write a format 1 coverage table
    179         writer.fixOffset(coverageTableIndex, multipleSubstitutionsBase);
    180         writer.writeData(1); // format = 1
    181         writer.writeData(sequenceCount);  // glyphCount
    182 
    183         for (int i = 0; i < sequenceCount; i += 1) {
    184             writer.writeData(decompEntries[i].getComposedCharacter());
    185         }
    186     }
    187 }
    188