blob: 525494dbab0d556b0706cc23394cb49b2583ac11 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 *
24 */
25
26/*
27 *
28 * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
29 *
30 */
31
32#include "LETypes.h"
33#include "OpenTypeTables.h"
34#include "GlyphDefinitionTables.h"
35#include "GlyphPositionAdjustments.h"
36#include "GlyphIterator.h"
37#include "LEGlyphStorage.h"
38#include "Lookups.h"
39#include "LESwaps.h"
40
41
42GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage,
43 GlyphPositionAdjustments *theGlyphPositionAdjustments,
44 le_bool rightToLeft, le_uint16 theLookupFlags, FeatureMask theFeatureMask,
45 const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
46 : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
47 glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
48 srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask),
49 glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
50
51{
52 le_int32 glyphCount = glyphStorage.getGlyphCount();
53
54 if (theGlyphDefinitionTableHeader != NULL) {
55 glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
56 markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
57 }
58
59 nextLimit = glyphCount;
60
61 if (rightToLeft) {
62 direction = -1;
63 position = glyphCount;
64 nextLimit = -1;
65 prevLimit = glyphCount;
66 }
67}
68
69GlyphIterator::GlyphIterator(GlyphIterator &that)
70 : glyphStorage(that.glyphStorage)
71{
72 direction = that.direction;
73 position = that.position;
74 nextLimit = that.nextLimit;
75 prevLimit = that.prevLimit;
76
77 glyphPositionAdjustments = that.glyphPositionAdjustments;
78 srcIndex = that.srcIndex;
79 destIndex = that.destIndex;
80 lookupFlags = that.lookupFlags;
81 featureMask = that.featureMask;
82 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
83 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
84}
85
86GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)
87 : glyphStorage(that.glyphStorage)
88{
89 direction = that.direction;
90 position = that.position;
91 nextLimit = that.nextLimit;
92 prevLimit = that.prevLimit;
93
94 glyphPositionAdjustments = that.glyphPositionAdjustments;
95 srcIndex = that.srcIndex;
96 destIndex = that.destIndex;
97 lookupFlags = that.lookupFlags;
98 featureMask = newFeatureMask;
99 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
100 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
101}
102
103GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
104 : glyphStorage(that.glyphStorage)
105{
106 direction = that.direction;
107 position = that.position;
108 nextLimit = that.nextLimit;
109 prevLimit = that.prevLimit;
110
111 glyphPositionAdjustments = that.glyphPositionAdjustments;
112 srcIndex = that.srcIndex;
113 destIndex = that.destIndex;
114 lookupFlags = newLookupFlags;
115 featureMask = that.featureMask;
116 glyphClassDefinitionTable = that.glyphClassDefinitionTable;
117 markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
118}
119
120GlyphIterator::~GlyphIterator()
121{
122 // nothing to do, right?
123}
124
125void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)
126{
127 position = prevLimit;
128 featureMask = newFeatureMask;
129 lookupFlags = newLookupFlags;
130}
131
132LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count)
133{
134 return glyphStorage.insertGlyphs(position, count);
135}
136
137le_int32 GlyphIterator::applyInsertions()
138{
139 le_int32 newGlyphCount = glyphStorage.applyInsertions();
140
141 if (direction < 0) {
142 prevLimit = newGlyphCount;
143 } else {
144 nextLimit = newGlyphCount;
145 }
146
147 return newGlyphCount;
148}
149
150le_int32 GlyphIterator::getCurrStreamPosition() const
151{
152 return position;
153}
154
155le_bool GlyphIterator::isRightToLeft() const
156{
157 return direction < 0;
158}
159
160le_bool GlyphIterator::ignoresMarks() const
161{
162 return (lookupFlags & lfIgnoreMarks) != 0;
163}
164
165le_bool GlyphIterator::baselineIsLogicalEnd() const
166{
167 return (lookupFlags & lfBaselineIsLogicalEnd) != 0;
168}
169
170LEGlyphID GlyphIterator::getCurrGlyphID() const
171{
172 if (direction < 0) {
173 if (position <= nextLimit || position >= prevLimit) {
174 return 0xFFFF;
175 }
176 } else {
177 if (position <= prevLimit || position >= nextLimit) {
178 return 0xFFFF;
179 }
180 }
181
182 return glyphStorage[position];
183}
184
185void GlyphIterator::getCursiveEntryPoint(LEPoint &entryPoint) const
186{
187 if (direction < 0) {
188 if (position <= nextLimit || position >= prevLimit) {
189 return;
190 }
191 } else {
192 if (position <= prevLimit || position >= nextLimit) {
193 return;
194 }
195 }
196
197 glyphPositionAdjustments->getEntryPoint(position, entryPoint);
198}
199
200void GlyphIterator::getCursiveExitPoint(LEPoint &exitPoint) const
201{
202 if (direction < 0) {
203 if (position <= nextLimit || position >= prevLimit) {
204 return;
205 }
206 } else {
207 if (position <= prevLimit || position >= nextLimit) {
208 return;
209 }
210 }
211
212 glyphPositionAdjustments->getExitPoint(position, exitPoint);
213}
214
215void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)
216{
217 LEGlyphID glyph = glyphStorage[position];
218
219 glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);
220}
221
222void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)
223{
224 if (direction < 0) {
225 if (newPosition >= prevLimit) {
226 position = prevLimit;
227 return;
228 }
229
230 if (newPosition <= nextLimit) {
231 position = nextLimit;
232 return;
233 }
234 } else {
235 if (newPosition <= prevLimit) {
236 position = prevLimit;
237 return;
238 }
239
240 if (newPosition >= nextLimit) {
241 position = nextLimit;
242 return;
243 }
244 }
245
246 position = newPosition - direction;
247 next();
248}
249
250void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)
251{
252 if (direction < 0) {
253 if (position <= nextLimit || position >= prevLimit) {
254 return;
255 }
256 } else {
257 if (position <= prevLimit || position >= nextLimit) {
258 return;
259 }
260 }
261
262 glyphPositionAdjustments->setBaseOffset(position, baseOffset);
263}
264
265void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust,
266 float yPlacementAdjust, float xAdvanceAdjust, float yAdvanceAdjust)
267{
268 if (direction < 0) {
269 if (position <= nextLimit || position >= prevLimit) {
270 return;
271 }
272 } else {
273 if (position <= prevLimit || position >= nextLimit) {
274 return;
275 }
276 }
277
278 glyphPositionAdjustments->adjustXPlacement(position, xPlacementAdjust);
279 glyphPositionAdjustments->adjustYPlacement(position, yPlacementAdjust);
280 glyphPositionAdjustments->adjustXAdvance(position, xAdvanceAdjust);
281 glyphPositionAdjustments->adjustYAdvance(position, yAdvanceAdjust);
282}
283
284void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust,
285 float yPlacementAdjust, float xAdvanceAdjust, float yAdvanceAdjust)
286{
287 if (direction < 0) {
288 if (position <= nextLimit || position >= prevLimit) {
289 return;
290 }
291 } else {
292 if (position <= prevLimit || position >= nextLimit) {
293 return;
294 }
295 }
296
297 glyphPositionAdjustments->setXPlacement(position, xPlacementAdjust);
298 glyphPositionAdjustments->setYPlacement(position, yPlacementAdjust);
299 glyphPositionAdjustments->setXAdvance(position, xAdvanceAdjust);
300 glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
301}
302
303void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
304{
305 if (direction < 0) {
306 if (position <= nextLimit || position >= prevLimit) {
307 return;
308 }
309 } else {
310 if (position <= prevLimit || position >= nextLimit) {
311 return;
312 }
313 }
314
315 glyphPositionAdjustments->setEntryPoint(position, entryPoint, baselineIsLogicalEnd());
316}
317
318void GlyphIterator::setCursiveExitPoint(LEPoint &exitPoint)
319{
320 if (direction < 0) {
321 if (position <= nextLimit || position >= prevLimit) {
322 return;
323 }
324 } else {
325 if (position <= prevLimit || position >= nextLimit) {
326 return;
327 }
328 }
329
330 glyphPositionAdjustments->setExitPoint(position, exitPoint, baselineIsLogicalEnd());
331}
332
333void GlyphIterator::setCursiveGlyph()
334{
335 if (direction < 0) {
336 if (position <= nextLimit || position >= prevLimit) {
337 return;
338 }
339 } else {
340 if (position <= prevLimit || position >= nextLimit) {
341 return;
342 }
343 }
344
345 glyphPositionAdjustments->setCursiveGlyph(position, baselineIsLogicalEnd());
346}
347
348le_bool GlyphIterator::filterGlyph(le_uint32 index) const
349{
350 LEGlyphID glyphID = glyphStorage[index];
351 le_int32 glyphClass = gcdNoGlyphClass;
352
353 if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
354 return TRUE;
355 }
356
357 if (glyphClassDefinitionTable != NULL) {
358 glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
359 }
360
361 switch (glyphClass)
362 {
363 case gcdNoGlyphClass:
364 return FALSE;
365
366 case gcdSimpleGlyph:
367 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
368
369 case gcdLigatureGlyph:
370 return (lookupFlags & lfIgnoreLigatures) != 0;
371
372 case gcdMarkGlyph:
373 {
374 if ((lookupFlags & lfIgnoreMarks) != 0) {
375 return TRUE;
376 }
377
378 le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
379
380 if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
381 return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
382 }
383
384 return FALSE;
385 }
386
387 case gcdComponentGlyph:
388 return (lookupFlags & lfIgnoreBaseGlyphs) != 0;
389
390 default:
391 return FALSE;
392 }
393}
394
395le_bool GlyphIterator::hasFeatureTag() const
396{
397 if (featureMask == 0) {
398 return TRUE;
399 }
400
401 LEErrorCode success = LE_NO_ERROR;
402 FeatureMask fm = glyphStorage.getAuxData(position, success);
403
404 return (fm & featureMask) != 0;
405}
406
407le_bool GlyphIterator::findFeatureTag()
408{
409 while (nextInternal()) {
410 if (hasFeatureTag()) {
411 prevInternal();
412 return TRUE;
413 }
414 }
415
416 return FALSE;
417}
418
419
420le_bool GlyphIterator::nextInternal(le_uint32 delta)
421{
422 le_int32 newPosition = position;
423
424 while (newPosition != nextLimit && delta > 0) {
425 do {
426 newPosition += direction;
427 } while (newPosition != nextLimit && filterGlyph(newPosition));
428
429 delta -= 1;
430 }
431
432 position = newPosition;
433
434 return position != nextLimit;
435}
436
437le_bool GlyphIterator::next(le_uint32 delta)
438{
439 return nextInternal(delta) && hasFeatureTag();
440}
441
442le_bool GlyphIterator::prevInternal(le_uint32 delta)
443{
444 le_int32 newPosition = position;
445
446 while (newPosition != prevLimit && delta > 0) {
447 do {
448 newPosition -= direction;
449 } while (newPosition != prevLimit && filterGlyph(newPosition));
450
451 delta -= 1;
452 }
453
454 position = newPosition;
455
456 return position != prevLimit;
457}
458
459le_bool GlyphIterator::prev(le_uint32 delta)
460{
461 return prevInternal(delta) && hasFeatureTag();
462}
463
464le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const
465{
466 le_int32 component = 0;
467 le_int32 posn;
468
469 for (posn = position; posn != markPosition; posn += direction) {
470 if (glyphStorage[posn] == 0xFFFE) {
471 component += 1;
472 }
473 }
474
475 return component;
476}
477
478// This is basically prevInternal except that it
479// doesn't take a delta argument, and it doesn't
480// filter out 0xFFFE glyphs.
481le_bool GlyphIterator::findMark2Glyph()
482{
483 le_int32 newPosition = position;
484
485 do {
486 newPosition -= direction;
487 } while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE &&
488 filterGlyph(newPosition));
489
490 position = newPosition;
491
492 return position != prevLimit;
493}