| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.fop.svg.text; |
| |
| import java.text.AttributedCharacterIterator; |
| import java.text.AttributedString; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; |
| |
| import org.apache.fop.complexscripts.bidi.UnicodeBidiAlgorithm; |
| import org.apache.fop.traits.Direction; |
| |
| public class BidiAttributedCharacterIterator implements AttributedCharacterIterator { |
| |
| private AttributedCharacterIterator aci; |
| |
| protected BidiAttributedCharacterIterator(AttributedCharacterIterator aci) { |
| this.aci = aci; |
| } |
| |
| public BidiAttributedCharacterIterator(AttributedCharacterIterator aci, int defaultBidiLevel) { |
| this(annotateBidiLevels(aci, defaultBidiLevel)); |
| } |
| |
| private static AttributedCharacterIterator |
| annotateBidiLevels(AttributedCharacterIterator aci, int defaultBidiLevel) { |
| int start = aci.getBeginIndex(); |
| int end = aci.getEndIndex(); |
| int numChars = end - start; |
| StringBuffer sb = new StringBuffer(numChars); |
| for (int i = 0; i < numChars; ++i) { |
| char ch = aci.setIndex(i); |
| assert ch != AttributedCharacterIterator.DONE; |
| sb.append(ch); |
| } |
| int[] levels = |
| UnicodeBidiAlgorithm.resolveLevels(sb, (defaultBidiLevel & 1) == 1 ? Direction.RL : Direction.LR); |
| if (levels != null) { |
| assert levels.length == numChars; |
| AttributedString as = new AttributedString(aci, start, end); |
| int runStart = 0; |
| int runEnd = runStart; |
| int nextRunLevel = -1; |
| int currRunLevel = -1; |
| for (int i = 0, n = levels.length; i < n; ++i) { |
| nextRunLevel = levels[i]; |
| if (currRunLevel < 0) { |
| currRunLevel = nextRunLevel; |
| } else if (nextRunLevel != currRunLevel) { |
| as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.BIDI_LEVEL, |
| currRunLevel, runStart, i); |
| runStart = i; |
| runEnd = runStart; |
| currRunLevel = nextRunLevel; |
| } |
| } |
| if ((currRunLevel >= 0) && (end > runStart)) { |
| as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.BIDI_LEVEL, |
| currRunLevel, runStart, end); |
| } |
| return as.getIterator(); |
| } else { |
| return aci; |
| } |
| } |
| |
| // CharacterIterator |
| |
| public char first() { |
| return aci.first(); |
| } |
| |
| public char last() { |
| return aci.last(); |
| } |
| |
| public char current() { |
| return aci.current(); |
| } |
| |
| public char next() { |
| return aci.next(); |
| } |
| |
| public char previous() { |
| return aci.previous(); |
| } |
| |
| public char setIndex(int position) { |
| return aci.setIndex(position); |
| } |
| |
| public int getBeginIndex() { |
| return aci.getBeginIndex(); |
| } |
| |
| public int getEndIndex() { |
| return aci.getEndIndex(); |
| } |
| |
| public int getIndex() { |
| return aci.getIndex(); |
| } |
| |
| // @SuppressFBWarnings("CN_IDIOM_NO_SUPER_CALL") |
| public Object clone() { |
| return new BidiAttributedCharacterIterator((AttributedCharacterIterator)aci.clone()); |
| } |
| |
| // AttributedCharacterIterator |
| |
| public int getRunStart() { |
| return aci.getRunStart(); |
| } |
| |
| public int getRunStart(AttributedCharacterIterator.Attribute attribute) { |
| return aci.getRunStart(attribute); |
| } |
| |
| public int getRunStart(Set<? extends AttributedCharacterIterator.Attribute> attributes) { |
| return aci.getRunStart(attributes); |
| } |
| |
| public int getRunLimit() { |
| return aci.getRunLimit(); |
| } |
| |
| public int getRunLimit(AttributedCharacterIterator.Attribute attribute) { |
| return aci.getRunLimit(attribute); |
| } |
| |
| public int getRunLimit(Set<? extends AttributedCharacterIterator.Attribute> attributes) { |
| return aci.getRunLimit(attributes); |
| } |
| |
| public Map<AttributedCharacterIterator.Attribute, Object> getAttributes() { |
| return aci.getAttributes(); |
| } |
| |
| public Object getAttribute(AttributedCharacterIterator.Attribute attribute) { |
| return aci.getAttribute(attribute); |
| } |
| |
| public Set<AttributedCharacterIterator.Attribute> getAllAttributeKeys() { |
| return aci.getAllAttributeKeys(); |
| } |
| |
| } |