1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* $Id$ */ 19 20 package org.apache.fop.complexscripts.fonts; 21 22 import org.apache.fop.complexscripts.util.GlyphSequence; 23 import org.apache.fop.complexscripts.util.ScriptContextTester; 24 25 // CSOFF: LineLengthCheck 26 27 /** 28 * <p>The <code>GlyphPositioningSubtable</code> implements an abstract base of a glyph subtable, 29 * providing a default implementation of the <code>GlyphPositioning</code> interface.</p> 30 * 31 * <p>This work was originally authored by Glenn Adams (gadams@apache.org).</p> 32 */ 33 public abstract class GlyphPositioningSubtable extends GlyphSubtable implements GlyphPositioning { 34 35 private static final GlyphPositioningState STATE = new GlyphPositioningState(); 36 37 /** 38 * Instantiate a <code>GlyphPositioningSubtable</code>. 39 * @param id subtable identifier 40 * @param sequence subtable sequence 41 * @param flags subtable flags 42 * @param format subtable format 43 * @param coverage subtable coverage table 44 */ GlyphPositioningSubtable(String id, int sequence, int flags, int format, GlyphCoverageTable coverage)45 protected GlyphPositioningSubtable(String id, int sequence, int flags, int format, GlyphCoverageTable coverage) { 46 super(id, sequence, flags, format, coverage); 47 } 48 49 /** {@inheritDoc} */ getTableType()50 public int getTableType() { 51 return GlyphTable.GLYPH_TABLE_TYPE_POSITIONING; 52 } 53 54 /** {@inheritDoc} */ getTypeName()55 public String getTypeName() { 56 return GlyphPositioningTable.getLookupTypeName(getType()); 57 } 58 59 /** {@inheritDoc} */ isCompatible(GlyphSubtable subtable)60 public boolean isCompatible(GlyphSubtable subtable) { 61 return subtable instanceof GlyphPositioningSubtable; 62 } 63 64 /** {@inheritDoc} */ usesReverseScan()65 public boolean usesReverseScan() { 66 return false; 67 } 68 69 /** {@inheritDoc} */ position(GlyphPositioningState ps)70 public boolean position(GlyphPositioningState ps) { 71 return false; 72 } 73 74 /** 75 * Apply positioning using specified state and subtable array. For each position in input sequence, 76 * apply subtables in order until some subtable applies or none remain. If no subtable applied or no 77 * input was consumed for a given position, then apply default action (no adjustments and advance). 78 * If <code>sequenceIndex</code> is non-negative, then apply subtables only when current position 79 * matches <code>sequenceIndex</code> in relation to the starting position. Furthermore, upon 80 * successful application at <code>sequenceIndex</code>, then discontinue processing the remaining 81 * @param ps positioning state 82 * @param sta array of subtables to apply 83 * @param sequenceIndex if non negative, then apply subtables only at specified sequence index 84 * @return true if a non-zero adjustment occurred 85 */ position(GlyphPositioningState ps, GlyphPositioningSubtable[] sta, int sequenceIndex)86 public static final boolean position(GlyphPositioningState ps, GlyphPositioningSubtable[] sta, int sequenceIndex) { 87 int sequenceStart = ps.getPosition(); 88 boolean appliedOneShot = false; 89 while (ps.hasNext()) { 90 boolean applied = false; 91 if (!appliedOneShot && ps.maybeApplicable()) { 92 for (int i = 0, n = sta.length; !applied && (i < n); i++) { 93 if (sequenceIndex < 0) { 94 applied = ps.apply(sta [ i ]); 95 } else if (ps.getPosition() == (sequenceStart + sequenceIndex)) { 96 applied = ps.apply(sta [ i ]); 97 if (applied) { 98 appliedOneShot = true; 99 } 100 } 101 } 102 } 103 if (!applied || !ps.didConsume()) { 104 ps.applyDefault(); 105 } 106 ps.next(); 107 } 108 return ps.getAdjusted(); 109 } 110 111 /** 112 * Apply positioning. 113 * @param gs input glyph sequence 114 * @param script tag 115 * @param language tag 116 * @param feature tag 117 * @param fontSize the font size 118 * @param sta subtable array 119 * @param widths array 120 * @param adjustments array (receives output adjustments) 121 * @param sct script context tester 122 * @return true if a non-zero adjustment occurred 123 */ position(GlyphSequence gs, String script, String language, String feature, int fontSize, GlyphPositioningSubtable[] sta, int[] widths, int[][] adjustments, ScriptContextTester sct)124 public static final boolean position(GlyphSequence gs, String script, String language, String feature, int fontSize, GlyphPositioningSubtable[] sta, int[] widths, int[][] adjustments, ScriptContextTester sct) { 125 synchronized (STATE) { 126 return position(STATE.reset(gs, script, language, feature, fontSize, widths, adjustments, sct), sta, -1); 127 } 128 } 129 130 } 131