1 /*
2  * Copyright (c) 1998, 2015, 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
23  * questions.
24  */
25 /*
26  *
27  * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
28  */
29 
30 package sun.font;
31 
32 import java.awt.Font;
33 import java.awt.font.FontRenderContext;
34 import java.awt.font.LineMetrics;
35 
36 final class StandardTextSource extends TextSource {
37 
38     private final char[] chars;
39     private final int start;
40     private final int len;
41     private final int cstart;
42     private final int clen;
43     private final int level; // assumed all uniform
44     private final int flags; // see GlyphVector.java
45     private final Font font;
46     private final FontRenderContext frc;
47     private final CoreMetrics cm;
48 
49     /**
50      * Create a simple implementation of a TextSource.
51      *
52      * Chars is an array containing clen chars in the context, in
53      * logical order, contiguously starting at cstart.  Start and len
54      * represent that portion of the context representing the true
55      * source; start, like cstart, is relative to the start of the
56      * character array.
57      *
58      * Level is the bidi level (0-63 for the entire context. Flags is
59      * the layout flags. Font is the font, frc is the render context,
60      * and lm is the line metrics for the entire source text, but not
61      * necessarily the context.
62      */
StandardTextSource(char[] chars, int start, int len, int cstart, int clen, int level, int flags, Font font, FontRenderContext frc, CoreMetrics cm)63     StandardTextSource(char[] chars,
64                        int start,
65                        int len,
66                        int cstart,
67                        int clen,
68                        int level,
69                        int flags,
70                        Font font,
71                        FontRenderContext frc,
72                        CoreMetrics cm) {
73     if (chars == null) {
74       throw new IllegalArgumentException("bad chars: null");
75     }
76     if (cstart < 0) {
77       throw new IllegalArgumentException("bad cstart: " + cstart);
78     }
79     if (start < cstart) {
80       throw new IllegalArgumentException("bad start: " + start + " for cstart: " + cstart);
81     }
82     if (clen < 0) {
83       throw new IllegalArgumentException("bad clen: " + clen);
84     }
85     if (cstart + clen > chars.length) {
86       throw new IllegalArgumentException("bad clen: " + clen + " cstart: " + cstart + " for array len: " + chars.length);
87     }
88     if (len < 0) {
89       throw new IllegalArgumentException("bad len: " + len);
90     }
91     if ((start + len) > (cstart + clen)) {
92       throw new IllegalArgumentException("bad len: " + len + " start: " + start + " for cstart: " + cstart + " clen: " + clen);
93     }
94     if (font == null) {
95       throw new IllegalArgumentException("bad font: null");
96     }
97     if (frc == null) {
98       throw new IllegalArgumentException("bad frc: null");
99     }
100 
101     this.chars = chars;
102     this.start = start;
103     this.len = len;
104     this.cstart = cstart;
105     this.clen = clen;
106     this.level = level;
107     this.flags = flags;
108     this.font = font;
109     this.frc = frc;
110 
111     if (cm != null) {
112         this.cm = cm;
113     } else {
114         LineMetrics metrics = font.getLineMetrics(chars, cstart, clen, frc);
115         this.cm = ((FontLineMetrics)metrics).cm;
116     }
117   }
118 
119   // TextSource API
120 
getChars()121   public char[] getChars() {
122     return chars;
123   }
124 
getStart()125   public int getStart() {
126     return start;
127   }
128 
getLength()129   public int getLength() {
130     return len;
131   }
132 
getContextStart()133   public int getContextStart() {
134     return cstart;
135   }
136 
getContextLength()137   public int getContextLength() {
138     return clen;
139   }
140 
getLayoutFlags()141   public int getLayoutFlags() {
142     return flags;
143   }
144 
getBidiLevel()145   public int getBidiLevel() {
146     return level;
147   }
148 
getFont()149   public Font getFont() {
150     return font;
151   }
152 
getFRC()153   public FontRenderContext getFRC() {
154     return frc;
155   }
156 
getCoreMetrics()157   public CoreMetrics getCoreMetrics() {
158     return cm;
159   }
160 
getSubSource(int start, int length, int dir)161   public TextSource getSubSource(int start, int length, int dir) {
162     if (start < 0 || length < 0 || (start + length) > len) {
163       throw new IllegalArgumentException("bad start (" + start + ") or length (" + length + ")");
164     }
165 
166     int level = this.level;
167     if (dir != TextLineComponent.UNCHANGED) {
168         boolean ltr = (flags & 0x8) == 0;
169         if (!(dir == TextLineComponent.LEFT_TO_RIGHT && ltr) &&
170                 !(dir == TextLineComponent.RIGHT_TO_LEFT && !ltr)) {
171             throw new IllegalArgumentException("direction flag is invalid");
172         }
173         level = ltr? 0 : 1;
174     }
175 
176     return new StandardTextSource(chars, this.start + start, length, cstart, clen, level, flags, font, frc, cm);
177   }
178 
toString()179   public String toString() {
180     return toString(WITH_CONTEXT);
181   }
182 
toString(boolean withContext)183   public String toString(boolean withContext) {
184     StringBuilder sb = new StringBuilder(super.toString());
185     sb.append("[start:");
186     sb.append(start);
187     sb.append(", len:" );
188     sb.append(len);
189     sb.append(", cstart:");
190     sb.append(cstart);
191     sb.append(", clen:" );
192     sb.append(clen);
193     sb.append(", chars:\"");
194     int chStart, chLimit;
195     if (withContext == WITH_CONTEXT) {
196         chStart = cstart;
197         chLimit = cstart + clen;
198     }
199     else {
200         chStart = start;
201         chLimit = start + len;
202     }
203     for (int i = chStart; i < chLimit; ++i) {
204       if (i > chStart) {
205         sb.append(" ");
206       }
207       sb.append(Integer.toHexString(chars[i]));
208     }
209     sb.append("\"");
210     sb.append(", level:");
211     sb.append(level);
212     sb.append(", flags:");
213     sb.append(flags);
214     sb.append(", font:");
215     sb.append(font);
216     sb.append(", frc:");
217     sb.append(frc);
218     sb.append(", cm:");
219     sb.append(cm);
220     sb.append("]");
221 
222     return sb.toString();
223   }
224 }
225