1 /*
2 * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
75 import java.awt.geom.AffineTransform;
76 import java.awt.geom.NoninvertibleTransformException;
77 import java.awt.geom.Point2D;
78 import java.util.ArrayList;
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 _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;
440 int limit = _scriptRuns.getScriptLimit();
441 int script = _scriptRuns.getScriptCode();
442 nextEngineRecord(start, limit, script, lang, font2D, 0);
443 start = limit;
444 }
445 }
446
447 int ix = 0;
448 int stop = _ercount;
449 int dir = 1;
450
451 if (_typo_flags < 0) { // RTL
452 ix = stop - 1;
453 stop = -1;
454 dir = -1;
455 }
456
457 // _sd.init(dtx, gtx, font.getStyle(), frc.isAntiAliased(), frc.usesFractionalMetrics());
458 _sd = txinfo.sd;
459 for (;ix != stop; ix += dir) {
460 EngineRecord er = (EngineRecord)_erecords.get(ix);
461 for (;;) {
462 try {
463 er.layout();
464 break;
465 }
466 catch (IndexOutOfBoundsException e) {
467 if (_gvdata._count >=0) {
468 _gvdata.grow();
469 }
470 }
471 }
472 // Break out of the outer for loop if layout fails.
473 if (_gvdata._count < 0) {
474 break;
475 }
476 }
477
478 // if (txinfo.invdtx != null) {
479 // _gvdata.adjustPositions(txinfo.invdtx);
480 // }
488 if (FontUtilities.debugFonts()) {
489 FontUtilities.getLogger().warning("OpenType layout failed on font: " +
490 font);
491 }
492 } else {
493 gv = _gvdata.createGlyphVector(font, frc, result);
494 }
495 // System.err.println("Layout returns: " + gv);
496 return gv;
497 }
498
499 //
500 // private methods
501 //
502
503 private GlyphLayout() {
504 this._gvdata = new GVData();
505 this._textRecord = new TextRecord();
506 this._scriptRuns = new ScriptRun();
507 this._fontRuns = new FontRunIterator();
508 this._erecords = new ArrayList(10);
509 this._pt = new Point2D.Float();
510 this._sd = new FontStrikeDesc();
511 this._mat = new float[4];
512 }
513
514 private void init(int capacity) {
515 this._typo_flags = 0;
516 this._ercount = 0;
517 this._gvdata.init(capacity);
518 }
519
520 private void nextEngineRecord(int start, int limit, int script, int lang, Font2D font, int gmask) {
521 EngineRecord er = null;
522 if (_ercount == _erecords.size()) {
523 er = new EngineRecord();
524 _erecords.add(er);
525 } else {
526 er = (EngineRecord)_erecords.get(_ercount);
527 }
528 er.init(start, limit, font, script, lang, gmask);
529 ++_ercount;
530 }
531
532 /**
533 * Storage for layout to build glyph vector data, then generate a real GlyphVector
534 */
535 public static final class GVData {
536 public int _count; // number of glyphs, >= number of chars
537 public int _flags;
538 public int[] _glyphs;
539 public float[] _positions;
540 public int[] _indices;
541
542 private static final int UNINITIALIZED_FLAGS = -1;
543
544 public void init(int size) {
545 _count = 0;
546 _flags = UNINITIALIZED_FLAGS;
|
1 /*
2 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
75 import java.awt.geom.AffineTransform;
76 import java.awt.geom.NoninvertibleTransformException;
77 import java.awt.geom.Point2D;
78 import java.util.ArrayList;
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;
440 int limit = _scriptRuns.getScriptLimit();
441 int script = _scriptRuns.getScriptCode();
442 nextEngineRecord(start, limit, script, lang, font2D, 0);
443 start = limit;
444 }
445 }
446
447 int ix = 0;
448 int stop = _ercount;
449 int dir = 1;
450
451 if (_typo_flags < 0) { // RTL
452 ix = stop - 1;
453 stop = -1;
454 dir = -1;
455 }
456
457 // _sd.init(dtx, gtx, font.getStyle(), frc.isAntiAliased(), frc.usesFractionalMetrics());
458 _sd = txinfo.sd;
459 for (;ix != stop; ix += dir) {
460 EngineRecord er = _erecords.get(ix);
461 for (;;) {
462 try {
463 er.layout();
464 break;
465 }
466 catch (IndexOutOfBoundsException e) {
467 if (_gvdata._count >=0) {
468 _gvdata.grow();
469 }
470 }
471 }
472 // Break out of the outer for loop if layout fails.
473 if (_gvdata._count < 0) {
474 break;
475 }
476 }
477
478 // if (txinfo.invdtx != null) {
479 // _gvdata.adjustPositions(txinfo.invdtx);
480 // }
488 if (FontUtilities.debugFonts()) {
489 FontUtilities.getLogger().warning("OpenType layout failed on font: " +
490 font);
491 }
492 } else {
493 gv = _gvdata.createGlyphVector(font, frc, result);
494 }
495 // System.err.println("Layout returns: " + gv);
496 return gv;
497 }
498
499 //
500 // private methods
501 //
502
503 private GlyphLayout() {
504 this._gvdata = new GVData();
505 this._textRecord = new TextRecord();
506 this._scriptRuns = new ScriptRun();
507 this._fontRuns = new FontRunIterator();
508 this._erecords = new ArrayList<>(10);
509 this._pt = new Point2D.Float();
510 this._sd = new FontStrikeDesc();
511 this._mat = new float[4];
512 }
513
514 private void init(int capacity) {
515 this._typo_flags = 0;
516 this._ercount = 0;
517 this._gvdata.init(capacity);
518 }
519
520 private void nextEngineRecord(int start, int limit, int script, int lang, Font2D font, int gmask) {
521 EngineRecord er = null;
522 if (_ercount == _erecords.size()) {
523 er = new EngineRecord();
524 _erecords.add(er);
525 } else {
526 er = _erecords.get(_ercount);
527 }
528 er.init(start, limit, font, script, lang, gmask);
529 ++_ercount;
530 }
531
532 /**
533 * Storage for layout to build glyph vector data, then generate a real GlyphVector
534 */
535 public static final class GVData {
536 public int _count; // number of glyphs, >= number of chars
537 public int _flags;
538 public int[] _glyphs;
539 public float[] _positions;
540 public int[] _indices;
541
542 private static final int UNINITIALIZED_FLAGS = -1;
543
544 public void init(int size) {
545 _count = 0;
546 _flags = UNINITIALIZED_FLAGS;
|