79 import java.util.concurrent.ConcurrentHashMap;
80
81 import static java.lang.Character.*;
82
83 public final class GlyphLayout {
84 // data for glyph vector
85 private GVData _gvdata;
86
87 // cached glyph layout data for reuse
88 private static volatile GlyphLayout cache; // reusable
89
90 private LayoutEngineFactory _lef; // set when get is called, unset when done is called
91 private TextRecord _textRecord; // the text we're working on, used by iterators
92 private ScriptRun _scriptRuns; // iterator over script runs
93 private FontRunIterator _fontRuns; // iterator over physical fonts in a composite
94 private int _ercount;
95 private ArrayList<EngineRecord> _erecords;
96 private Point2D.Float _pt;
97 private FontStrikeDesc _sd;
98 private float[] _mat;
99 private int _typo_flags;
100 private int _offset;
101
102 public static final class LayoutEngineKey {
103 private Font2D font;
104 private int script;
105 private int lang;
106
107 LayoutEngineKey() {
108 }
109
110 LayoutEngineKey(Font2D font, int script, int lang) {
111 init(font, script, lang);
112 }
113
114 void init(Font2D font, int script, int lang) {
115 this.font = font;
116 this.script = script;
117 this.lang = lang;
118 }
155 public static interface LayoutEngineFactory {
156 /**
157 * Given a font, script, and language, determine a layout engine to use.
158 */
159 public LayoutEngine getEngine(Font2D font, int script, int lang);
160
161 /**
162 * Given a key, determine a layout engine to use.
163 */
164 public LayoutEngine getEngine(LayoutEngineKey key);
165 }
166
167 public static interface LayoutEngine {
168 /**
169 * Given a strike descriptor, text, rtl flag, and starting point, append information about
170 * glyphs, positions, and character indices to the glyphvector data, and advance the point.
171 *
172 * If the GVData does not have room for the glyphs, throws an IndexOutOfBoundsException and
173 * leave pt and the gvdata unchanged.
174 */
175 public void layout(FontStrikeDesc sd, float[] mat, int gmask,
176 int baseIndex, TextRecord text, int typo_flags, Point2D.Float pt, GVData data);
177 }
178
179 /**
180 * Return a new instance of GlyphLayout, using the provided layout engine factory.
181 * If null, the system layout engine factory will be used.
182 */
183 public static GlyphLayout get(LayoutEngineFactory lef) {
184 if (lef == null) {
185 lef = SunLayoutEngine.instance();
186 }
187 GlyphLayout result = null;
188 synchronized(GlyphLayout.class) {
189 if (cache != null) {
190 result = cache;
191 cache = null;
192 }
193 }
194 if (result == null) {
195 result = new GlyphLayout();
369 init(count);
370
371 // need to set after init
372 // go through the back door for this
373 if (font.hasLayoutAttributes()) {
374 AttributeValues values = ((AttributeMap)font.getAttributes()).getValues();
375 if (values.getKerning() != 0) _typo_flags |= 0x1;
376 if (values.getLigatures() != 0) _typo_flags |= 0x2;
377 }
378
379 _offset = offset;
380
381 // use cache now - can we use the strike cache for this?
382
383 SDCache txinfo = SDCache.get(font, frc);
384 _mat[0] = (float)txinfo.gtx.getScaleX();
385 _mat[1] = (float)txinfo.gtx.getShearY();
386 _mat[2] = (float)txinfo.gtx.getShearX();
387 _mat[3] = (float)txinfo.gtx.getScaleY();
388 _pt.setLocation(txinfo.delta);
389
390 int lim = offset + count;
391
392 int min = 0;
393 int max = text.length;
394 if (flags != 0) {
395 if ((flags & Font.LAYOUT_RIGHT_TO_LEFT) != 0) {
396 _typo_flags |= 0x80000000; // RTL
397 }
398
399 if ((flags & Font.LAYOUT_NO_START_CONTEXT) != 0) {
400 min = offset;
401 }
402
403 if ((flags & Font.LAYOUT_NO_LIMIT_CONTEXT) != 0) {
404 max = lim;
405 }
406 }
407
408 int lang = -1; // default for now
665 isLowSurrogate(_textRecord.text[i+1])) {
666 // rare case
667 ch = toCodePoint((char)ch,_textRecord.text[++i]); // inc
668 }
669 int gc = getType(ch);
670 if (gc == NON_SPACING_MARK ||
671 gc == ENCLOSING_MARK ||
672 gc == COMBINING_SPACING_MARK) { // could do range test also
673
674 this.eflags = 0x4;
675 break;
676 }
677 }
678
679 this.engine = _lef.getEngine(key); // flags?
680 }
681
682 void layout() {
683 _textRecord.start = start;
684 _textRecord.limit = limit;
685 engine.layout(_sd, _mat, gmask, start - _offset, _textRecord,
686 _typo_flags | eflags, _pt, _gvdata);
687 }
688 }
689 }
|
79 import java.util.concurrent.ConcurrentHashMap;
80
81 import static java.lang.Character.*;
82
83 public final class GlyphLayout {
84 // data for glyph vector
85 private GVData _gvdata;
86
87 // cached glyph layout data for reuse
88 private static volatile GlyphLayout cache; // reusable
89
90 private LayoutEngineFactory _lef; // set when get is called, unset when done is called
91 private TextRecord _textRecord; // the text we're working on, used by iterators
92 private ScriptRun _scriptRuns; // iterator over script runs
93 private FontRunIterator _fontRuns; // iterator over physical fonts in a composite
94 private int _ercount;
95 private ArrayList<EngineRecord> _erecords;
96 private Point2D.Float _pt;
97 private FontStrikeDesc _sd;
98 private float[] _mat;
99 private float ptSize;
100 private int _typo_flags;
101 private int _offset;
102
103 public static final class LayoutEngineKey {
104 private Font2D font;
105 private int script;
106 private int lang;
107
108 LayoutEngineKey() {
109 }
110
111 LayoutEngineKey(Font2D font, int script, int lang) {
112 init(font, script, lang);
113 }
114
115 void init(Font2D font, int script, int lang) {
116 this.font = font;
117 this.script = script;
118 this.lang = lang;
119 }
156 public static interface LayoutEngineFactory {
157 /**
158 * Given a font, script, and language, determine a layout engine to use.
159 */
160 public LayoutEngine getEngine(Font2D font, int script, int lang);
161
162 /**
163 * Given a key, determine a layout engine to use.
164 */
165 public LayoutEngine getEngine(LayoutEngineKey key);
166 }
167
168 public static interface LayoutEngine {
169 /**
170 * Given a strike descriptor, text, rtl flag, and starting point, append information about
171 * glyphs, positions, and character indices to the glyphvector data, and advance the point.
172 *
173 * If the GVData does not have room for the glyphs, throws an IndexOutOfBoundsException and
174 * leave pt and the gvdata unchanged.
175 */
176 public void layout(FontStrikeDesc sd, float[] mat, float ptSize, int gmask,
177 int baseIndex, TextRecord text, int typo_flags, Point2D.Float pt, GVData data);
178 }
179
180 /**
181 * Return a new instance of GlyphLayout, using the provided layout engine factory.
182 * If null, the system layout engine factory will be used.
183 */
184 public static GlyphLayout get(LayoutEngineFactory lef) {
185 if (lef == null) {
186 lef = SunLayoutEngine.instance();
187 }
188 GlyphLayout result = null;
189 synchronized(GlyphLayout.class) {
190 if (cache != null) {
191 result = cache;
192 cache = null;
193 }
194 }
195 if (result == null) {
196 result = new GlyphLayout();
370 init(count);
371
372 // need to set after init
373 // go through the back door for this
374 if (font.hasLayoutAttributes()) {
375 AttributeValues values = ((AttributeMap)font.getAttributes()).getValues();
376 if (values.getKerning() != 0) _typo_flags |= 0x1;
377 if (values.getLigatures() != 0) _typo_flags |= 0x2;
378 }
379
380 _offset = offset;
381
382 // use cache now - can we use the strike cache for this?
383
384 SDCache txinfo = SDCache.get(font, frc);
385 _mat[0] = (float)txinfo.gtx.getScaleX();
386 _mat[1] = (float)txinfo.gtx.getShearY();
387 _mat[2] = (float)txinfo.gtx.getShearX();
388 _mat[3] = (float)txinfo.gtx.getScaleY();
389 _pt.setLocation(txinfo.delta);
390 ptSize = font.getSize2D();
391
392 int lim = offset + count;
393
394 int min = 0;
395 int max = text.length;
396 if (flags != 0) {
397 if ((flags & Font.LAYOUT_RIGHT_TO_LEFT) != 0) {
398 _typo_flags |= 0x80000000; // RTL
399 }
400
401 if ((flags & Font.LAYOUT_NO_START_CONTEXT) != 0) {
402 min = offset;
403 }
404
405 if ((flags & Font.LAYOUT_NO_LIMIT_CONTEXT) != 0) {
406 max = lim;
407 }
408 }
409
410 int lang = -1; // default for now
667 isLowSurrogate(_textRecord.text[i+1])) {
668 // rare case
669 ch = toCodePoint((char)ch,_textRecord.text[++i]); // inc
670 }
671 int gc = getType(ch);
672 if (gc == NON_SPACING_MARK ||
673 gc == ENCLOSING_MARK ||
674 gc == COMBINING_SPACING_MARK) { // could do range test also
675
676 this.eflags = 0x4;
677 break;
678 }
679 }
680
681 this.engine = _lef.getEngine(key); // flags?
682 }
683
684 void layout() {
685 _textRecord.start = start;
686 _textRecord.limit = limit;
687 engine.layout(_sd, _mat, ptSize, gmask, start - _offset, _textRecord,
688 _typo_flags | eflags, _pt, _gvdata);
689 }
690 }
691 }
|