(empty log message)
@@ -0,0 +1,29 @@ | ||
1 | +package jp.cssj.sakae.util; | |
2 | + | |
3 | +public class ArrayIntMapIterator implements IntMapIterator { | |
4 | + private final int[] array; | |
5 | + private int i = 0; | |
6 | + | |
7 | + public ArrayIntMapIterator(int[] array) { | |
8 | + this.array = array; | |
9 | + } | |
10 | + | |
11 | + public boolean next() { | |
12 | + if (this.i >= this.array.length) { | |
13 | + return false; | |
14 | + } | |
15 | + this.i++; | |
16 | + return true; | |
17 | + } | |
18 | + | |
19 | + @Override | |
20 | + public int key() { | |
21 | + return this.i - 1; | |
22 | + } | |
23 | + | |
24 | + @Override | |
25 | + public int value() { | |
26 | + return this.array[this.i - 1]; | |
27 | + } | |
28 | + | |
29 | +} |
@@ -0,0 +1,29 @@ | ||
1 | +package jp.cssj.sakae.util; | |
2 | + | |
3 | +public class ArrayShortMapIterator implements ShortMapIterator { | |
4 | + private final short[] array; | |
5 | + private int i = 0; | |
6 | + | |
7 | + public ArrayShortMapIterator(short[] array) { | |
8 | + this.array = array; | |
9 | + } | |
10 | + | |
11 | + public boolean next() { | |
12 | + if (this.i >= this.array.length) { | |
13 | + return false; | |
14 | + } | |
15 | + this.i++; | |
16 | + return true; | |
17 | + } | |
18 | + | |
19 | + @Override | |
20 | + public int key() { | |
21 | + return this.i - 1; | |
22 | + } | |
23 | + | |
24 | + @Override | |
25 | + public short value() { | |
26 | + return this.array[this.i - 1]; | |
27 | + } | |
28 | + | |
29 | +} |
@@ -8,7 +8,7 @@ | ||
8 | 8 | * @author MIYABE Tatsuhiko |
9 | 9 | * @version $Id$ |
10 | 10 | */ |
11 | -public class IntList implements Serializable { | |
11 | +public class IntList implements Serializable, IntMap { | |
12 | 12 | private static final long serialVersionUID = 0; |
13 | 13 | |
14 | 14 | private static final int[] ZERO = new int[0]; |
@@ -57,7 +57,12 @@ | ||
57 | 57 | } |
58 | 58 | return this.array[i]; |
59 | 59 | } |
60 | + | |
61 | + public boolean contains(int key) { | |
62 | + return this.get(key) != this.defaultValue; | |
63 | + } | |
60 | 64 | |
65 | + | |
61 | 66 | public int size() { |
62 | 67 | return this.length; |
63 | 68 | } |
@@ -73,4 +78,9 @@ | ||
73 | 78 | public boolean isEmpty() { |
74 | 79 | return this.length == 0; |
75 | 80 | } |
81 | + | |
82 | + public IntMapIterator getIterator() { | |
83 | + this.pack(); | |
84 | + return new ArrayIntMapIterator(this.array); | |
85 | + } | |
76 | 86 | } |
@@ -0,0 +1,8 @@ | ||
1 | +package jp.cssj.sakae.util; | |
2 | + | |
3 | +public interface IntMap { | |
4 | + public void set(int key, int value); | |
5 | + public int get(int key); | |
6 | + public boolean contains(int key); | |
7 | + public IntMapIterator getIterator(); | |
8 | +} |
@@ -0,0 +1,7 @@ | ||
1 | +package jp.cssj.sakae.util; | |
2 | + | |
3 | +public interface IntMapIterator { | |
4 | + public boolean next(); | |
5 | + public int key(); | |
6 | + public int value(); | |
7 | +} |
@@ -0,0 +1,47 @@ | ||
1 | +package jp.cssj.sakae.util; | |
2 | + | |
3 | +import java.util.Iterator; | |
4 | +import java.util.Map; | |
5 | +import java.util.Map.Entry; | |
6 | +import java.util.TreeMap; | |
7 | + | |
8 | +public class MapIntMap implements IntMap { | |
9 | + protected Map<Integer, Integer> map = new TreeMap<Integer, Integer>(); | |
10 | + | |
11 | + public void set(int key, int value) { | |
12 | + this.map.put(key, value); | |
13 | + } | |
14 | + | |
15 | + public int get(int key) { | |
16 | + return this.map.get(key); | |
17 | + } | |
18 | + | |
19 | + public boolean contains(int key) { | |
20 | + return this.map.containsKey(key); | |
21 | + } | |
22 | + | |
23 | + public IntMapIterator getIterator() { | |
24 | + final Iterator<Entry<Integer, Integer>> i = this.map.entrySet().iterator(); | |
25 | + return new IntMapIterator() { | |
26 | + private Entry<Integer, Integer> e; | |
27 | + @Override | |
28 | + public boolean next() { | |
29 | + if (!i.hasNext()) { | |
30 | + return false; | |
31 | + } | |
32 | + this.e = i.next(); | |
33 | + return true; | |
34 | + } | |
35 | + | |
36 | + @Override | |
37 | + public int key() { | |
38 | + return e.getKey(); | |
39 | + } | |
40 | + | |
41 | + @Override | |
42 | + public int value() { | |
43 | + return e.getValue(); | |
44 | + } | |
45 | + }; | |
46 | + } | |
47 | +} |
@@ -0,0 +1,7 @@ | ||
1 | +package jp.cssj.sakae.util; | |
2 | + | |
3 | +public interface ShortMapIterator { | |
4 | + public boolean next(); | |
5 | + public int key(); | |
6 | + public short value(); | |
7 | +} |
@@ -27,11 +27,11 @@ | ||
27 | 27 | return this.name; |
28 | 28 | } |
29 | 29 | |
30 | - public short getKerning(int gid, int cid) { | |
30 | + public short getKerning(int gid, int c) { | |
31 | 31 | return 0; |
32 | 32 | } |
33 | 33 | |
34 | - public int getLigature(int gid, int cid) { | |
34 | + public int getLigature(int gid, int c) { | |
35 | 35 | return -1; |
36 | 36 | } |
37 | 37 |
@@ -11,6 +11,9 @@ | ||
11 | 11 | |
12 | 12 | import jp.cssj.resolver.Source; |
13 | 13 | import jp.cssj.sakae.util.IntList; |
14 | +import jp.cssj.sakae.util.IntMap; | |
15 | +import jp.cssj.sakae.util.IntMapIterator; | |
16 | +import jp.cssj.sakae.util.MapIntMap; | |
14 | 17 | |
15 | 18 | /** |
16 | 19 | * CIDフォントのキャラクタマッピング情報です。 |
@@ -29,7 +32,7 @@ | ||
29 | 32 | |
30 | 33 | protected final String javaEncoding; |
31 | 34 | |
32 | - transient protected WeakReference<int[]> toCID = null; | |
35 | + transient protected WeakReference<IntMap> toCID = null; | |
33 | 36 | |
34 | 37 | transient protected int missingCID = 0; |
35 | 38 |
@@ -40,10 +43,10 @@ | ||
40 | 43 | this.javaEncoding = javaEncoding; |
41 | 44 | } |
42 | 45 | |
43 | - private int[] getToCid() { | |
44 | - int[] toCid = null; | |
46 | + private IntMap getToCid() { | |
47 | + IntMap toCid = null; | |
45 | 48 | if (this.toCID != null) { |
46 | - toCid = (int[]) this.toCID.get(); | |
49 | + toCid = this.toCID.get(); | |
47 | 50 | if (toCid != null) { |
48 | 51 | return toCid; |
49 | 52 | } |
@@ -54,32 +57,38 @@ | ||
54 | 57 | |
55 | 58 | CIDTableParser parser = new CIDTableParser(); |
56 | 59 | try { |
57 | - toCid = parser.parse(this.cmapSource); | |
58 | 60 | Charset charset = this.getCharset(); |
59 | 61 | // UTF-16BEの場合は、Javaの内部コードと一致する |
60 | - if (!charset.name().equalsIgnoreCase("UTF-16BE")) { | |
62 | + if (charset.name().equalsIgnoreCase("UTF-16BE")) { | |
63 | + toCid = new MapIntMap(); | |
64 | + parser.parse(this.cmapSource, toCid); | |
65 | + } else { | |
66 | + toCid = new IntList(); | |
67 | + parser.parse(this.cmapSource, toCid); | |
61 | 68 | IntList intList = new IntList(); |
62 | 69 | CharsetDecoder decoder = charset.newDecoder(); |
63 | 70 | ByteBuffer in = ByteBuffer.allocate(4); |
64 | 71 | CharBuffer out = CharBuffer.allocate(1); |
65 | - for (int i = 0; i < toCid.length; ++i) { | |
66 | - int cid = toCid[i]; | |
72 | + IntMapIterator i = toCid.getIterator(); | |
73 | + while (i.next()) { | |
74 | + int cid = i.value(); | |
75 | + int c = i.key(); | |
67 | 76 | if (cid != 0) { |
68 | 77 | in.clear(); |
69 | - if (i < 0xFF) { | |
70 | - in.put((byte) (i & 0xFF)); | |
71 | - } else if (i <= 0xFFFF) { | |
72 | - in.put((byte) ((i >> 8) & 0xFF)); | |
73 | - in.put((byte) (i & 0xFF)); | |
74 | - } else if (i <= 0xFFFFFF) { | |
75 | - in.put((byte) ((i >> 16) & 0xFF)); | |
76 | - in.put((byte) ((i >> 8) & 0xFF)); | |
77 | - in.put((byte) (i & 0xFF)); | |
78 | + if (c < 0xFF) { | |
79 | + in.put((byte) (c & 0xFF)); | |
80 | + } else if (c <= 0xFFFF) { | |
81 | + in.put((byte) ((c >> 8) & 0xFF)); | |
82 | + in.put((byte) (c & 0xFF)); | |
83 | + } else if (c <= 0xFFFFFF) { | |
84 | + in.put((byte) ((c >> 16) & 0xFF)); | |
85 | + in.put((byte) ((c >> 8) & 0xFF)); | |
86 | + in.put((byte) (c & 0xFF)); | |
78 | 87 | } else { |
79 | - in.put((byte) ((i >> 24) & 0xFF)); | |
80 | - in.put((byte) ((i >> 16) & 0xFF)); | |
81 | - in.put((byte) ((i >> 8) & 0xFF)); | |
82 | - in.put((byte) (i & 0xFF)); | |
88 | + in.put((byte) ((c >> 24) & 0xFF)); | |
89 | + in.put((byte) ((c >> 16) & 0xFF)); | |
90 | + in.put((byte) ((c >> 8) & 0xFF)); | |
91 | + in.put((byte) (c & 0xFF)); | |
83 | 92 | } |
84 | 93 | in.flip(); |
85 | 94 | out.clear(); |
@@ -89,17 +98,15 @@ | ||
89 | 98 | intList.set(out.get(0), cid); |
90 | 99 | } |
91 | 100 | } |
92 | - toCid = intList.toArray(); | |
101 | + toCid = intList; | |
93 | 102 | } |
94 | - for (int i = 0; i < toCid.length; ++i) { | |
95 | - if (toCid[i] == 0) { | |
96 | - toCid[i] = -1; | |
97 | - } | |
103 | + if (!toCid.contains(MISSING_CHAR)) { | |
104 | + System.err.println("missing missing char"); | |
98 | 105 | } |
99 | 106 | } catch (Exception e) { |
100 | 107 | throw new RuntimeException(e); |
101 | 108 | } |
102 | - this.toCID = new WeakReference<int[]>(toCid); | |
109 | + this.toCID = new WeakReference<IntMap>(toCid); | |
103 | 110 | return toCid; |
104 | 111 | } |
105 | 112 |
@@ -130,20 +137,15 @@ | ||
130 | 137 | /** |
131 | 138 | * 文字をCIDに変換します。 |
132 | 139 | * |
133 | - * @param c | |
134 | - * 文字 | |
140 | + * @param c 文字 | |
135 | 141 | * @return cid |
136 | 142 | */ |
137 | 143 | public int toCID(int c) { |
138 | - int[] toCid = this.getToCid(); | |
139 | - if (c < 0 || c >= toCid.length) { | |
144 | + IntMap toCid = this.getToCid(); | |
145 | + if (!toCid.contains(c)) { | |
140 | 146 | return this.getMissingCID(); |
141 | 147 | } |
142 | - int cid = toCid[c]; | |
143 | - if (cid == -1) { | |
144 | - return this.getMissingCID(); | |
145 | - } | |
146 | - return cid; | |
148 | + return toCid.get(c); | |
147 | 149 | } |
148 | 150 | |
149 | 151 | /** |
@@ -153,19 +155,12 @@ | ||
153 | 155 | * @return |
154 | 156 | */ |
155 | 157 | public boolean containsChar(int c) { |
156 | - int[] toCid = this.getToCid(); | |
157 | - if (c < 0 || c >= toCid.length) { | |
158 | - return false; | |
159 | - } | |
160 | - int cid = toCid[c]; | |
161 | - if (cid == -1) { | |
162 | - return false; | |
163 | - } | |
164 | - return true; | |
158 | + IntMap toCid = this.getToCid(); | |
159 | + return toCid.contains(c); | |
165 | 160 | } |
166 | 161 | |
167 | - public int getLength() { | |
168 | - int[] toCid = this.getToCid(); | |
169 | - return toCid.length; | |
162 | + public IntMapIterator getIterator() { | |
163 | + IntMap toCid = this.getToCid(); | |
164 | + return toCid.getIterator(); | |
170 | 165 | } |
171 | 166 | } |
\ No newline at end of file |
@@ -12,7 +12,7 @@ | ||
12 | 12 | import jp.cssj.resolver.composite.CompositeSourceResolver; |
13 | 13 | import jp.cssj.resolver.helpers.URIHelper; |
14 | 14 | import jp.cssj.sakae.pdf.util.PdfUtils; |
15 | -import jp.cssj.sakae.util.IntList; | |
15 | +import jp.cssj.sakae.util.IntMap; | |
16 | 16 | |
17 | 17 | /** |
18 | 18 | * CMapファイルのCIDテーブルを解析します。 |
@@ -28,13 +28,7 @@ | ||
28 | 28 | |
29 | 29 | private SourceResolver resolver; |
30 | 30 | |
31 | - public int[] parse(Source source) throws IOException, CMapException { | |
32 | - IntList toCID = new IntList(); | |
33 | - this.parse(source, toCID); | |
34 | - return toCID.toArray(); | |
35 | - } | |
36 | - | |
37 | - private void parse(Source source, IntList toCID) throws IOException, CMapException { | |
31 | + public void parse(Source source, IntMap toCID) throws IOException, CMapException { | |
38 | 32 | this.in = new InputStreamReader(new BufferedInputStream(source.getInputStream()), "ISO-8859-1"); |
39 | 33 | try { |
40 | 34 | try { |
@@ -73,8 +67,22 @@ | ||
73 | 67 | this.in.close(); |
74 | 68 | } |
75 | 69 | } |
70 | + | |
71 | + private static int parseCode(String a) { | |
72 | + int code; | |
73 | + if (a.length() <= 4) { | |
74 | + code = Integer.parseInt(a, 16); | |
75 | + } | |
76 | + else { | |
77 | + // サロゲートペア | |
78 | + int h = Integer.parseInt(a.substring(0, 4), 16); | |
79 | + int l = Integer.parseInt(a.substring(4, 8), 16); | |
80 | + code = 0x10000 + (h - 0xD800) * 0x400 + (l - 0xDC00); | |
81 | + } | |
82 | + return code; | |
83 | + } | |
76 | 84 | |
77 | - private void parseCidChars(IntList toCID) throws IOException, CMapException { | |
85 | + private void parseCidChars(IntMap toCID) throws IOException, CMapException { | |
78 | 86 | for (;;) { |
79 | 87 | String a = this.nextToken(); |
80 | 88 | if (a.equals("endcidchar")) { |
@@ -83,7 +91,7 @@ | ||
83 | 91 | String b = this.nextToken(); |
84 | 92 | a = a.substring(1, a.length() - 1).trim(); |
85 | 93 | try { |
86 | - int code = Integer.parseInt(a, 16); | |
94 | + int code = parseCode(a); | |
87 | 95 | int offset = Integer.parseInt(b); |
88 | 96 | toCID.set(code, offset); |
89 | 97 | } catch (NumberFormatException e) { |
@@ -92,7 +100,7 @@ | ||
92 | 100 | } |
93 | 101 | } |
94 | 102 | |
95 | - private void parseCidRanges(IntList toCID) throws IOException, CMapException { | |
103 | + private void parseCidRanges(IntMap toCID) throws IOException, CMapException { | |
96 | 104 | for (;;) { |
97 | 105 | String a = this.nextToken(); |
98 | 106 | if (a.equals("endcidrange")) { |
@@ -104,8 +112,8 @@ | ||
104 | 112 | a = a.substring(1, a.length() - 1).trim(); |
105 | 113 | b = b.substring(1, b.length() - 1).trim(); |
106 | 114 | try { |
107 | - int start = Integer.parseInt(a, 16); | |
108 | - int end = Integer.parseInt(b, 16); | |
115 | + int start = parseCode(a); | |
116 | + int end = parseCode(b); | |
109 | 117 | if (a.length() != b.length() || a.length() % 2 != 0) { |
110 | 118 | throw new CMapException("開始位置と終了位置のキャラクターコードのバイト数が一致しないか、偶数桁の116進数になっていません"); |
111 | 119 | } |
@@ -12,6 +12,7 @@ | ||
12 | 12 | import jp.cssj.sakae.pdf.font.PdfEmbeddedFont; |
13 | 13 | import jp.cssj.sakae.pdf.font.cid.ToUnicode.Unicode; |
14 | 14 | import jp.cssj.sakae.pdf.font.type2.CffGenerator; |
15 | +import jp.cssj.sakae.util.ArrayShortMapIterator; | |
15 | 16 | |
16 | 17 | public final class CIDUtils { |
17 | 18 | public static final String ENCODING_H = "Identity-H"; |
@@ -279,11 +280,11 @@ | ||
279 | 280 | |
280 | 281 | // WArray |
281 | 282 | { |
282 | - WArray warray = WArray.buildFromWidths(w); | |
283 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(w)); | |
283 | 284 | CIDUtils.writeWArray(out, warray); |
284 | 285 | } |
285 | 286 | if (w2 != null && w2.length > 0) { |
286 | - WArray warray = WArray.buildFromWidths(w2); | |
287 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(w2)); | |
287 | 288 | CIDUtils.writeWArray2(out, warray); |
288 | 289 | } |
289 | 290 |
@@ -444,8 +445,7 @@ | ||
444 | 445 | * @param fontRef |
445 | 446 | * @param w |
446 | 447 | * @param w2 |
447 | - * @param unicodeArray | |
448 | - * CIDからユニコードへのマッピング | |
448 | + * @param unicodeArray CIDからユニコードへのマッピング | |
449 | 449 | * @throws IOException |
450 | 450 | */ |
451 | 451 | public static void writeEmbeddedFont(PdfFragmentOutput out, XRef xref, CIDFontSource source, PdfEmbeddedFont font, |
@@ -525,11 +525,11 @@ | ||
525 | 525 | |
526 | 526 | // WArray |
527 | 527 | { |
528 | - WArray warray = WArray.buildFromWidths(w); | |
528 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(w)); | |
529 | 529 | CIDUtils.writeWArray(out, warray); |
530 | 530 | } |
531 | 531 | if (w2 != null && w2.length > 0) { |
532 | - WArray warray = WArray.buildFromWidths(w2); | |
532 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(w2)); | |
533 | 533 | CIDUtils.writeWArray2(out, warray); |
534 | 534 | } |
535 | 535 |
@@ -610,7 +610,7 @@ | ||
610 | 610 | out.writeName("CIDFontType0C"); |
611 | 611 | out.lineBreak(); |
612 | 612 | |
613 | - try (OutputStream cout = out.startStreamFromHash(PdfFragmentOutput.STREAM_BINARY)) { | |
613 | + try (OutputStream cout = out.startStreamFromHash(PdfFragmentOutput.STREAM_BINARY)) { | |
614 | 614 | // InputStream in = new InflaterInputStream(new FileInputStream("/home/miyabe/workspaces/copper/CopperPDF.dev/files/misc/fontfile.bin")); |
615 | 615 | // IOUtils.copy(in, cout); |
616 | 616 | CffGenerator cff = new CffGenerator(); |
@@ -5,6 +5,7 @@ | ||
5 | 5 | import java.util.List; |
6 | 6 | |
7 | 7 | import jp.cssj.sakae.util.IntList; |
8 | +import jp.cssj.sakae.util.ShortMapIterator; | |
8 | 9 | |
9 | 10 | /** |
10 | 11 | * フォントのDW,W属性です。 |
@@ -77,7 +78,7 @@ | ||
77 | 78 | * @param widths |
78 | 79 | * @return |
79 | 80 | */ |
80 | - public static WArray buildFromWidths(short[] widths) { | |
81 | + public static WArray buildFromWidths(ShortMapIterator widths) { | |
81 | 82 | final List<Width> list = new ArrayList<Width>(); |
82 | 83 | final IntList widthCounts = new IntList();// 最も多い幅をデフォルトとする |
83 | 84 | final short[] runWidths = new short[255]; |
@@ -85,8 +86,9 @@ | ||
85 | 86 | int position = 0; |
86 | 87 | int startCid = -1; |
87 | 88 | boolean run = false; |
88 | - for (int cid = 0; cid < widths.length; ++cid) { | |
89 | - short advance = widths[cid]; | |
89 | + int cid = widths.key(); | |
90 | + while (widths.next()) { | |
91 | + short advance = widths.value(); | |
90 | 92 | // Short.MIN_VALUEはデフォルトの幅とする |
91 | 93 | if (advance == Short.MIN_VALUE) { |
92 | 94 | if (position == 0) { |
@@ -127,7 +129,7 @@ | ||
127 | 129 | if (startCid != -1) { |
128 | 130 | short[] temp = new short[position]; |
129 | 131 | System.arraycopy(runWidths, 0, temp, 0, position); |
130 | - list.add(new Width(startCid, widths.length - 1, temp)); | |
132 | + list.add(new Width(startCid, cid, temp)); | |
131 | 133 | } |
132 | 134 | short defaultWidth = 0; |
133 | 135 | if (!widthCounts.isEmpty()) { |
@@ -15,7 +15,6 @@ | ||
15 | 15 | import jp.cssj.sakae.pdf.PdfGraphicsOutput; |
16 | 16 | import jp.cssj.sakae.pdf.XRef; |
17 | 17 | import jp.cssj.sakae.pdf.font.cid.CIDFont; |
18 | -import jp.cssj.sakae.pdf.font.cid.CIDTable; | |
19 | 18 | import jp.cssj.sakae.pdf.font.cid.CIDUtils; |
20 | 19 | import jp.cssj.sakae.pdf.font.cid.CMap; |
21 | 20 | import jp.cssj.sakae.pdf.font.cid.WArray; |
@@ -104,10 +103,6 @@ | ||
104 | 103 | char c = ch[i + off]; |
105 | 104 | // \A0は空白に変換 |
106 | 105 | c = (c == '\u00A0') ? '\u0020' : c; |
107 | - // 不明な文字 | |
108 | - if (!this.cmap.getCIDTable().containsChar(c)) { | |
109 | - c = CIDTable.MISSING_CHAR; | |
110 | - } | |
111 | 106 | this.cbuff.put(c); |
112 | 107 | } |
113 | 108 | len -= llen; |
@@ -8,6 +8,8 @@ | ||
8 | 8 | import jp.cssj.sakae.pdf.font.cid.CMap; |
9 | 9 | import jp.cssj.sakae.pdf.font.cid.WArray; |
10 | 10 | import jp.cssj.sakae.pdf.font.cid.identity.OpenTypeCIDIdentityFontSource; |
11 | +import jp.cssj.sakae.util.ArrayShortMapIterator; | |
12 | +import jp.cssj.sakae.util.IntMapIterator; | |
11 | 13 | import jp.cssj.sakae.util.ShortList; |
12 | 14 | import net.zamasoft.font.OpenTypeFont; |
13 | 15 | import net.zamasoft.font.table.Table; |
@@ -65,12 +67,10 @@ | ||
65 | 67 | |
66 | 68 | ShortList cidToAdvance = new ShortList(Short.MIN_VALUE); |
67 | 69 | CIDTable ct = cmap.getCIDTable(); |
68 | - for (int i = 0; i < ct.getLength(); ++i) { | |
69 | - if (!ct.containsChar(i)) { | |
70 | - continue; | |
71 | - } | |
72 | - int cid = ct.toCID(i); | |
73 | - int gid = fs.getCmapFormat().mapCharCode(i); | |
70 | + IntMapIterator i = ct.getIterator(); | |
71 | + while (i.next()) { | |
72 | + int cid = i.value(); | |
73 | + int gid = fs.getCmapFormat().mapCharCode(i.key()); | |
74 | 74 | short advance = (short) (hmtx.getAdvanceWidth(gid) * FontSource.DEFAULT_UNITS_PER_EM / upm); |
75 | 75 | // CIDは重複することがあるので、広い方の幅を採用する |
76 | 76 | if (advance > cidToAdvance.get(cid)) { |
@@ -77,7 +77,8 @@ | ||
77 | 77 | cidToAdvance.set(cid, advance); |
78 | 78 | } |
79 | 79 | } |
80 | - WArray warray = WArray.buildFromWidths(cidToAdvance.toArray()); | |
80 | + short[] widths = cidToAdvance.toArray(); | |
81 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(widths)); | |
81 | 82 | return warray; |
82 | 83 | } |
83 | 84 | } |
@@ -6,6 +6,8 @@ | ||
6 | 6 | import jp.cssj.sakae.pdf.font.cid.CMap; |
7 | 7 | import jp.cssj.sakae.pdf.font.cid.WArray; |
8 | 8 | import jp.cssj.sakae.pdf.font.cid.identity.SystemCIDIdentityFontSource; |
9 | +import jp.cssj.sakae.util.ArrayShortMapIterator; | |
10 | +import jp.cssj.sakae.util.IntMapIterator; | |
9 | 11 | import jp.cssj.sakae.util.ShortList; |
10 | 12 | |
11 | 13 | /** |
@@ -49,16 +51,15 @@ | ||
49 | 51 | private static WArray systemWArray(SystemCIDIdentityFontSource fs, CMap cmap) { |
50 | 52 | ShortList cidToAdvance = new ShortList(Short.MIN_VALUE); |
51 | 53 | CIDTable ct = cmap.getCIDTable(); |
52 | - for (int i = 0; i < ct.getLength(); ++i) { | |
53 | - if (!ct.containsChar(i)) { | |
54 | - continue; | |
55 | - } | |
56 | - int cid = ct.toCID(i); | |
57 | - int gid = fs.toGID(i); | |
54 | + IntMapIterator i = ct.getIterator(); | |
55 | + while (i.next()) { | |
56 | + int cid = i.value(); | |
57 | + int gid = fs.toGID(i.key()); | |
58 | 58 | short advance = (short) fs.getWidth(gid); |
59 | 59 | cidToAdvance.set(cid, advance); |
60 | 60 | } |
61 | - WArray warray = WArray.buildFromWidths(cidToAdvance.toArray()); | |
61 | + short[] widths = cidToAdvance.toArray(); | |
62 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(widths)); | |
62 | 63 | return warray; |
63 | 64 | } |
64 | 65 | } |
@@ -11,6 +11,8 @@ | ||
11 | 11 | import jp.cssj.sakae.pdf.font.cid.WArray; |
12 | 12 | import jp.cssj.sakae.pdf.font.cid.identity.OpenTypeCIDIdentityFontSource; |
13 | 13 | import jp.cssj.sakae.pdf.font.cid.identity.SystemCIDIdentityFontSource; |
14 | +import jp.cssj.sakae.util.ArrayShortMapIterator; | |
15 | +import jp.cssj.sakae.util.IntMapIterator; | |
14 | 16 | import jp.cssj.sakae.util.ShortList; |
15 | 17 | import net.zamasoft.font.OpenTypeFont; |
16 | 18 | import net.zamasoft.font.table.Os2Table; |
@@ -84,19 +86,17 @@ | ||
84 | 86 | |
85 | 87 | ShortList cidToAdvance = new ShortList(Short.MIN_VALUE); |
86 | 88 | CIDTable ct = cmap.getCIDTable(); |
87 | - for (int i = 0; i < ct.getLength(); ++i) { | |
88 | - if (!ct.containsChar(i)) { | |
89 | - continue; | |
90 | - } | |
91 | - int gid = fs.getCmapFormat().mapCharCode(i); | |
89 | + IntMapIterator i = ct.getIterator(); | |
90 | + while (i.next()) { | |
91 | + int gid = fs.getCmapFormat().mapCharCode(i.key()); | |
92 | 92 | if (gid != 0) { |
93 | - int cid = ct.toCID(i); | |
93 | + int cid = i.value(); | |
94 | 94 | short advance = (short) (hmtx.getAdvanceWidth(gid) * FontSource.DEFAULT_UNITS_PER_EM / upm); |
95 | 95 | cidToAdvance.set(cid, advance); |
96 | 96 | } |
97 | 97 | } |
98 | 98 | short[] widths = cidToAdvance.toArray(); |
99 | - WArray warray = WArray.buildFromWidths(widths); | |
99 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(widths)); | |
100 | 100 | return warray; |
101 | 101 | } |
102 | 102 |
@@ -103,17 +103,15 @@ | ||
103 | 103 | private static WArray systemWArray(SystemCIDIdentityFontSource fs, CMap cmap) { |
104 | 104 | ShortList cidToAdvance = new ShortList(Short.MIN_VALUE); |
105 | 105 | CIDTable ct = cmap.getCIDTable(); |
106 | - for (int i = 0; i < ct.getLength(); ++i) { | |
107 | - if (!ct.containsChar(i)) { | |
108 | - continue; | |
109 | - } | |
110 | - int cid = ct.toCID(i); | |
111 | - int gid = fs.toGID(i); | |
106 | + IntMapIterator i = ct.getIterator(); | |
107 | + while (i.next()) { | |
108 | + int cid = i.value(); | |
109 | + int gid = fs.toGID(i.key()); | |
112 | 110 | short advance = (short) fs.getWidth(gid); |
113 | 111 | cidToAdvance.set(cid, advance); |
114 | 112 | } |
115 | 113 | short[] widths = cidToAdvance.toArray(); |
116 | - WArray warray = WArray.buildFromWidths(widths); | |
114 | + WArray warray = WArray.buildFromWidths(new ArrayShortMapIterator(widths)); | |
117 | 115 | return warray; |
118 | 116 | } |
119 | 117 | } |
@@ -81,16 +81,16 @@ | ||
81 | 81 | <cid-fonts> |
82 | 82 | <!-- CID-Keydフォント name: フォント名 italic: 斜体ならtrue weight: 太さ(100-900) panose: |
83 | 83 | PANOSEコード cmap: 横書きcmapエンコーディング名 vcmap: 縦書きcmapエンコーディング名 warray: フォントメトリックス --> |
84 | - <!-- Adobe Japan 1 4 --> | |
85 | - <cid-keyed-font name="AJ14UniJIS-Mincho" panose="1 5 2 2 6 9 4 2 5 8 3 4" | |
86 | - cmap="UniJIS-UCS2-HW-H" vcmap="UniJIS-UCS2-HW-V" warray="warrays/monospace_jis.txt"> | |
84 | + <!-- Adobe Japan 1 7 --> | |
85 | + <cid-keyed-font name="AJ17UniJIS-Mincho" panose="1 5 2 2 6 9 4 2 5 8 3 4" | |
86 | + cmap="UniJIS-UTF16-H" vcmap="UniJIS-UTF16-V" warray="warrays/monospace_jis.txt"> | |
87 | 87 | <alias name="Mincho" /> |
88 | 88 | <alias name="小塚明朝 Pr6N R" /> |
89 | 89 | <alias name="KozMinPr6N" /> |
90 | 90 | <alias name="Serif" /> |
91 | 91 | </cid-keyed-font> |
92 | - <cid-keyed-font name="AJ14UniJIS-Gothic" panose="8 1 2 11 6 9 7 2 5 8 2 4" | |
93 | - cmap="UniJIS-UCS2-HW-H" vcmap="UniJIS-UCS2-HW-V" warray="warrays/monospace_jis.txt"> | |
92 | + <cid-keyed-font name="AJ17UniJIS-Gothic" panose="8 1 2 11 6 9 7 2 5 8 2 4" | |
93 | + cmap="UniJIS-UTF16-H" vcmap="UniJIS-UTF16-V" warray="warrays/monospace_jis.txt"> | |
94 | 94 | <alias name="Gothic" /> |
95 | 95 | <alias name="小塚ゴシック Pr6N M" /> |
96 | 96 | <alias name="KozGoPr6N" /> |
@@ -112,11 +112,11 @@ | ||
112 | 112 | <cid-keyed-font name="EUC-Gothic" panose="8 1 2 11 6 9 7 2 5 8 2 4" |
113 | 113 | cmap="EUC-H" vcmap="EUC-V" warray="warrays/monospace_jis.txt" /> |
114 | 114 | |
115 | - <!-- Adobe Japan 1 7 --> | |
116 | - <cid-keyed-font name="AJ17UniJIS-Mincho" panose="1 5 2 2 6 9 4 2 5 8 3 4" | |
117 | - cmap="UniJIS-UTF16-H" vcmap="UniJIS-UTF16-V" warray="warrays/monospace_jis.txt" /> | |
118 | - <cid-keyed-font name="AJ17UniJIS-Gothic" panose="8 1 2 11 6 9 7 2 5 8 2 4" | |
119 | - cmap="UniJIS-UTF16-H" vcmap="UniJIS-UTF16-V" warray="warrays/monospace_jis.txt" /> | |
115 | + <!-- Adobe Japan 1 4 --> | |
116 | + <cid-keyed-font name="AJ14UniJIS-Mincho" panose="1 5 2 2 6 9 4 2 5 8 3 4" | |
117 | + cmap="UniJIS-UCS2-HW-H" vcmap="UniJIS-UCS2-HW-V" warray="warrays/monospace_jis.txt" /> | |
118 | + <cid-keyed-font name="AJ14UniJIS-Gothic" panose="8 1 2 11 6 9 7 2 5 8 2 4" | |
119 | + cmap="UniJIS-UCS2-HW-H" vcmap="UniJIS-UCS2-HW-V" warray="warrays/monospace_jis.txt" /> | |
120 | 120 | |
121 | 121 | <!-- JIS 2004 --> |
122 | 122 | <cid-keyed-font name="UniJIS2004-Mincho" panose="1 5 2 2 6 9 4 2 5 8 3 4" |