Decoration.java
11.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
/*
* Decompiled with CFR 0_118.
*/
package com.adobe.xfa.text;
import com.adobe.xfa.font.FontInstance;
import com.adobe.xfa.gfx.GFXDecorationInfo;
import com.adobe.xfa.text.DispLineWrapped;
import com.adobe.xfa.text.DrawParm;
import com.adobe.xfa.text.LineHeight;
import com.adobe.xfa.text.TextAttr;
import com.adobe.xfa.text.TextBaselineShift;
import com.adobe.xfa.text.Units;
import com.adobe.xfa.ut.UnitSpan;
import java.util.Map;
abstract class Decoration {
static final int SPECIAL_HONOUR_SUPERSCRIPT = 0;
static final int SPECIAL_HONOUR_SUBSCRIPT = 1;
static final int SPECIAL_BREAK_ON_ALL_CHANGES = 2;
static final int DECORATION_SPACE = 1;
static final int DECORATION_SUPPRESS = 2;
static final int DECORATION_VERTICAL = 4;
private int mnType = 1;
private int mnCount = 0;
private int meSpecial;
private double mdWidth;
private double mdOffset;
private double mdOffset2;
private boolean mbUseDescent;
private UnitSpan moBaseline;
private float moStart;
private float moNonSpace;
private float moSpace;
private final LineHeight moHeight = new LineHeight();
static Decoration createUnderline(DispLineWrapped line, DrawParm parm) {
return new Underline(line, parm);
}
static Decoration createLineThrough(DispLineWrapped line, DrawParm parm) {
return new LineThrough(line, parm);
}
static Decoration createOverline(DispLineWrapped line, DrawParm parm) {
return new Overline(line, parm);
}
void update(DrawParm oParm, TextAttr poAttr, float oLeft, float oRight, int nFlags, Map<DecorationKey, DecorationValue> oDecorations) {
boolean bBreak = false;
int nCount = 0;
int nType = 1;
if (poAttr != null) {
GFXDecorationInfo info = GFXDecorationInfo.extractDecoration(this.getLineState(poAttr));
nCount = info.mCount;
nType = info.mType;
}
boolean bIsSpace = (nFlags & 1) != 0;
FontInstance poFontInstance = null;
if (poAttr != null) {
poFontInstance = poAttr.fontInstance();
}
if (nType == 3) {
nType = bIsSpace ? 1 : 2;
}
UnitSpan oNewShift = oParm.offsetText();
if (poAttr != null && poAttr.baselineShiftEnable() && !poAttr.baselineShift().isNeutral()) {
TextBaselineShift oShifter = poAttr.baselineShift();
oNewShift = oShifter.applyShift(oParm.offsetText(), oParm.offsetText());
switch (this.meSpecial) {
case 0: {
if (!oNewShift.gt(this.moBaseline)) break;
oNewShift = this.moBaseline;
break;
}
case 1: {
if (!oNewShift.lt(this.moBaseline)) break;
oNewShift = this.moBaseline;
}
}
}
if (this.meSpecial == 2 && oNewShift != this.moBaseline) {
bBreak = true;
}
if ((nFlags & 2) != 0) {
nType = 1;
nCount = 0;
}
if (nType != this.mnType || nCount != this.mnCount) {
bBreak = true;
} else if (this.meSpecial == 2 && poFontInstance != null && !poFontInstance.getAscent().equals(Units.toUnitSpan(this.moHeight.ascent()))) {
bBreak = true;
}
if (bBreak) {
this.flush(oParm, true, oDecorations);
this.mnType = nType;
this.mnCount = nCount;
this.onLineStateChange();
this.moStart = oLeft;
}
if (nType == 1) {
return;
}
this.moHeight.accumulate(poAttr, (nFlags & 4) != 0 ? 1 : 0, false);
this.moBaseline = oNewShift;
if (bIsSpace) {
this.moSpace = oRight;
} else {
this.moNonSpace = oRight;
}
}
void fontChange(DrawParm oParm, Map<DecorationKey, DecorationValue> oDecorations) {
if (this.meSpecial == 2) {
this.flush(oParm, true, oDecorations);
}
}
void complete(DrawParm oParm, Map<DecorationKey, DecorationValue> oDecorations, boolean bIncludeSpaces) {
this.flush(oParm, bIncludeSpaces, oDecorations);
}
static boolean hasDecoration(TextAttr poAttr) {
if (poAttr == null) {
return false;
}
return Decoration.hasDecoration(poAttr.underline()) || Decoration.hasDecoration(poAttr.overline()) || Decoration.hasDecoration(poAttr.strikeout());
}
static boolean hasDecoration(int nDecoration) {
return GFXDecorationInfo.extractDecoration(nDecoration) != GFXDecorationInfo.decorateNone;
}
Decoration(DispLineWrapped poLine, DrawParm oParm) {
this.moBaseline = oParm.offsetText();
this.moHeight.setLegacyLevel(poLine.getLegacyLevel());
}
void setSpecial(int eSpecial) {
this.meSpecial = eSpecial;
}
void setUseDescent(boolean bUseDescent) {
this.mbUseDescent = bUseDescent;
}
void setFactors(double dWidth, double dOffset, double dOffset2) {
this.mdWidth = dWidth;
if (this.mbUseDescent) {
this.mdOffset = dOffset;
this.mdOffset2 = dOffset2;
} else {
this.mdOffset = - dOffset;
this.mdOffset2 = - dOffset2;
}
}
void setFactors(double dWidth, double dOffset) {
this.setFactors(dWidth, dOffset, 0.0);
}
int getCount() {
return this.mnCount;
}
abstract int getLineState(TextAttr var1);
abstract void onLineStateChange();
private void flush(DrawParm oParm, boolean bIncludeSpaces, Map<DecorationKey, DecorationValue> oDecorations) {
if (this.mnType != 1) {
float oEnd = this.moNonSpace;
if (bIncludeSpaces && this.moSpace > this.moNonSpace) {
oEnd = this.moSpace;
}
if (oEnd > this.moStart) {
UnitSpan oScale = null;
if (this.mbUseDescent) {
oScale = Units.toUnitSpan(this.moHeight.descent());
if (oScale.value() == 0) {
oScale = new UnitSpan((double)this.moHeight.ascent() / 3.0, 19);
}
} else {
oScale = Units.toUnitSpan(this.moHeight.ascent());
}
DecorationKey oKey = new DecorationKey(this.moStart, oEnd);
UnitSpan width = oScale.multiply(this.mdWidth);
UnitSpan halfWidth = width.divide(2);
UnitSpan yOffset = this.calculateOffset(oScale, this.mdOffset, halfWidth);
oDecorations.put(oKey, new DecorationValue(yOffset, width));
if (this.mnCount == 2) {
UnitSpan yOffset2 = this.calculateOffset(oScale, this.mdOffset2, halfWidth);
oDecorations.put(oKey, new DecorationValue(yOffset2, width));
}
}
}
this.mnType = 1;
this.mnCount = 0;
this.moHeight.reset();
this.moBaseline = oParm.offsetText();
}
private UnitSpan calculateOffset(UnitSpan scale, double offset, UnitSpan halfWidth) {
UnitSpan scaledOffset = scale.multiply(offset);
UnitSpan quarterWidth = halfWidth.divide(2);
UnitSpan relativeOffset = scaledOffset.add(quarterWidth);
return this.moBaseline.add(relativeOffset);
}
private static class Overline
extends Decoration {
private static final double SINGLE_OFFSET = 1.1;
private static final double SINGLE_WIDTH = 0.04;
private static final double DOUBLE_OFFSET_1 = 1.1;
private static final double DOUBLE_OFFSET_2 = 1.18;
private static final double DOUBLE_WIDTH = 0.3;
Overline(DispLineWrapped poLine, DrawParm oParm) {
super(poLine, oParm);
this.setSpecial(0);
}
@Override
int getLineState(TextAttr poAttr) {
return poAttr == null ? 0 : poAttr.overline();
}
@Override
void onLineStateChange() {
switch (this.getCount()) {
case 1: {
this.setFactors(0.04, 1.1);
break;
}
case 2: {
this.setFactors(0.3, 1.1, 1.18);
}
}
}
}
private static class LineThrough
extends Decoration {
private static final double SINGLE_OFFSET = 0.4;
private static final double SINGLE_WIDTH = 0.04;
private static final double DOUBLE_OFFSET_1 = 0.36;
private static final double DOUBLE_OFFSET_2 = 0.44;
private static final double DOUBLE_WIDTH = 0.03;
LineThrough(DispLineWrapped poLine, DrawParm oParm) {
super(poLine, oParm);
this.setSpecial(2);
}
@Override
int getLineState(TextAttr poAttr) {
return poAttr == null ? 0 : poAttr.strikeout();
}
@Override
void onLineStateChange() {
switch (this.getCount()) {
case 1: {
this.setFactors(0.04, 0.4);
break;
}
case 2: {
this.setFactors(0.03, 0.36, 0.44);
}
}
}
}
private static class Underline
extends Decoration {
private static final double SINGLE_OFFSET = 0.4;
private static final double SINGLE_WIDTH = 0.16;
private static final double DOUBLE_OFFSET_1 = 0.4;
private static final double DOUBLE_OFFSET_2 = 0.9;
private static final double DOUBLE_WIDTH = 0.08;
Underline(DispLineWrapped poLine, DrawParm oParm) {
super(poLine, oParm);
this.setSpecial(1);
this.setUseDescent(true);
}
@Override
int getLineState(TextAttr poAttr) {
return poAttr == null ? 0 : poAttr.underline();
}
@Override
void onLineStateChange() {
switch (this.getCount()) {
case 1: {
this.setFactors(0.16, 0.4);
break;
}
case 2: {
this.setFactors(0.08, 0.4, 0.9);
}
}
}
}
static class DecorationValue {
final UnitSpan moYOffset;
final UnitSpan moWidth;
public DecorationValue(UnitSpan yOffset, UnitSpan width) {
this.moYOffset = yOffset;
this.moWidth = width;
}
}
static class DecorationKey
implements Comparable<DecorationKey> {
final float moXStart;
final float moXEnd;
public DecorationKey(float xStart, float xEnd) {
this.moXStart = xStart;
this.moXEnd = xEnd;
}
@Override
public int compareTo(DecorationKey compare) {
if (compare == null) {
throw new NullPointerException();
}
if (this.moXStart < compare.moXStart) {
return -1;
}
if (this.moXStart > compare.moXStart) {
return 1;
}
if (this.moXEnd < compare.moXEnd) {
return -1;
}
if (this.moXEnd > compare.moXEnd) {
return 1;
}
return 0;
}
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null) {
return false;
}
if (object.getClass() != this.getClass()) {
return false;
}
return this.compareTo((DecorationKey)object) == 0;
}
public int hashCode() {
int hash = 13;
hash = hash * 31 ^ Float.floatToIntBits(this.moXStart);
hash = hash * 31 ^ Float.floatToIntBits(this.moXEnd);
return hash;
}
}
}