]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
374ca955 | 3 | * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved |
b75a7d8f A |
4 | * |
5 | */ | |
6 | ||
7 | #include "LETypes.h" | |
8 | #include "OpenTypeTables.h" | |
9 | #include "GlyphDefinitionTables.h" | |
10 | #include "GlyphPositionAdjustments.h" | |
11 | #include "GlyphIterator.h" | |
374ca955 | 12 | #include "LEGlyphStorage.h" |
b75a7d8f A |
13 | #include "Lookups.h" |
14 | #include "LESwaps.h" | |
15 | ||
16 | U_NAMESPACE_BEGIN | |
17 | ||
374ca955 | 18 | GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag, |
b75a7d8f | 19 | const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader) |
374ca955 | 20 | : direction(1), position(-1), nextLimit(-1), prevLimit(-1), |
b75a7d8f | 21 | cursiveFirstPosition(-1), cursiveLastPosition(-1), cursiveBaselineAdjustment(0), |
374ca955 A |
22 | glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments), |
23 | srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureTag(theFeatureTag), | |
24 | glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL) | |
b75a7d8f A |
25 | |
26 | { | |
374ca955 A |
27 | le_int32 glyphCount = glyphStorage.getGlyphCount(); |
28 | ||
b75a7d8f A |
29 | if (theGlyphDefinitionTableHeader != NULL) { |
30 | glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable(); | |
31 | markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable(); | |
32 | } | |
33 | ||
374ca955 A |
34 | nextLimit = glyphCount; |
35 | ||
b75a7d8f A |
36 | if (rightToLeft) { |
37 | direction = -1; | |
374ca955 | 38 | position = glyphCount; |
b75a7d8f | 39 | nextLimit = -1; |
374ca955 | 40 | prevLimit = glyphCount; |
b75a7d8f A |
41 | } |
42 | } | |
43 | ||
44 | GlyphIterator::GlyphIterator(GlyphIterator &that) | |
374ca955 | 45 | : glyphStorage(that.glyphStorage) |
b75a7d8f A |
46 | { |
47 | direction = that.direction; | |
48 | position = that.position; | |
49 | nextLimit = that.nextLimit; | |
50 | prevLimit = that.prevLimit; | |
51 | ||
52 | cursiveFirstPosition = that.cursiveFirstPosition; | |
53 | cursiveLastPosition = that.cursiveLastPosition; | |
54 | ||
b75a7d8f | 55 | glyphPositionAdjustments = that.glyphPositionAdjustments; |
374ca955 A |
56 | srcIndex = that.srcIndex; |
57 | destIndex = that.destIndex; | |
b75a7d8f A |
58 | lookupFlags = that.lookupFlags; |
59 | featureTag = that.featureTag; | |
b75a7d8f A |
60 | glyphClassDefinitionTable = that.glyphClassDefinitionTable; |
61 | markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; | |
62 | } | |
63 | ||
64 | GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag) | |
374ca955 | 65 | : glyphStorage(that.glyphStorage) |
b75a7d8f A |
66 | { |
67 | direction = that.direction; | |
68 | position = that.position; | |
69 | nextLimit = that.nextLimit; | |
70 | prevLimit = that.prevLimit; | |
71 | ||
72 | cursiveFirstPosition = that.cursiveFirstPosition; | |
73 | cursiveLastPosition = that.cursiveLastPosition; | |
74 | ||
b75a7d8f | 75 | glyphPositionAdjustments = that.glyphPositionAdjustments; |
374ca955 A |
76 | srcIndex = that.srcIndex; |
77 | destIndex = that.destIndex; | |
b75a7d8f A |
78 | lookupFlags = that.lookupFlags; |
79 | featureTag = newFeatureTag; | |
b75a7d8f A |
80 | glyphClassDefinitionTable = that.glyphClassDefinitionTable; |
81 | markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; | |
82 | } | |
83 | ||
84 | GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags) | |
374ca955 | 85 | : glyphStorage(that.glyphStorage) |
b75a7d8f A |
86 | { |
87 | direction = that.direction; | |
88 | position = that.position; | |
89 | nextLimit = that.nextLimit; | |
90 | prevLimit = that.prevLimit; | |
91 | ||
92 | ||
93 | cursiveFirstPosition = that.cursiveFirstPosition; | |
94 | cursiveLastPosition = that.cursiveLastPosition; | |
95 | ||
b75a7d8f | 96 | glyphPositionAdjustments = that.glyphPositionAdjustments; |
374ca955 A |
97 | srcIndex = that.srcIndex; |
98 | destIndex = that.destIndex; | |
b75a7d8f A |
99 | lookupFlags = newLookupFlags; |
100 | featureTag = that.featureTag; | |
b75a7d8f A |
101 | glyphClassDefinitionTable = that.glyphClassDefinitionTable; |
102 | markAttachClassDefinitionTable = that.markAttachClassDefinitionTable; | |
103 | } | |
104 | ||
374ca955 | 105 | GlyphIterator::~GlyphIterator() |
b75a7d8f | 106 | { |
374ca955 A |
107 | // nothing to do, right? |
108 | } | |
b75a7d8f | 109 | |
374ca955 A |
110 | void GlyphIterator::reset(le_uint16 newLookupFlags, LETag newFeatureTag) |
111 | { | |
112 | position = prevLimit; | |
113 | featureTag = newFeatureTag; | |
114 | lookupFlags = newLookupFlags; | |
115 | } | |
116 | ||
117 | LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count) | |
118 | { | |
119 | return glyphStorage.insertGlyphs(position, count); | |
120 | } | |
121 | ||
122 | le_int32 GlyphIterator::applyInsertions() | |
b75a7d8f | 123 | { |
374ca955 A |
124 | le_int32 newGlyphCount = glyphStorage.applyInsertions(); |
125 | ||
126 | if (direction < 0) { | |
127 | prevLimit = newGlyphCount; | |
128 | } else { | |
129 | nextLimit = newGlyphCount; | |
130 | } | |
131 | ||
132 | return newGlyphCount; | |
b75a7d8f A |
133 | } |
134 | ||
135 | le_int32 GlyphIterator::getCurrStreamPosition() const | |
136 | { | |
137 | return position; | |
138 | } | |
139 | ||
140 | le_bool GlyphIterator::isRightToLeft() const | |
141 | { | |
142 | return direction < 0; | |
143 | } | |
144 | ||
145 | le_bool GlyphIterator::ignoresMarks() const | |
146 | { | |
147 | return (lookupFlags & lfIgnoreMarks) != 0; | |
148 | } | |
149 | ||
150 | le_bool GlyphIterator::baselineIsLogicalEnd() const | |
151 | { | |
152 | return (lookupFlags & lfBaselineIsLogicalEnd) != 0; | |
153 | } | |
154 | ||
155 | le_bool GlyphIterator::hasCursiveFirstExitPoint() const | |
156 | { | |
157 | return cursiveFirstPosition >= 0; | |
158 | } | |
159 | ||
160 | le_bool GlyphIterator::hasCursiveLastExitPoint() const | |
161 | { | |
162 | return cursiveLastPosition >= 0; | |
163 | } | |
164 | ||
165 | LEGlyphID GlyphIterator::getCurrGlyphID() const | |
166 | { | |
167 | if (direction < 0) { | |
168 | if (position <= nextLimit || position >= prevLimit) { | |
169 | return 0xFFFF; | |
170 | } | |
171 | } else { | |
172 | if (position <= prevLimit || position >= nextLimit) { | |
173 | return 0xFFFF; | |
174 | } | |
175 | } | |
176 | ||
374ca955 | 177 | return glyphStorage[position]; |
b75a7d8f A |
178 | } |
179 | ||
180 | LEGlyphID GlyphIterator::getCursiveLastGlyphID() const | |
181 | { | |
182 | if (direction < 0) { | |
183 | if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) { | |
184 | return 0xFFFF; | |
185 | } | |
186 | } else { | |
187 | if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) { | |
188 | return 0xFFFF; | |
189 | } | |
190 | } | |
191 | ||
374ca955 | 192 | return glyphStorage[cursiveLastPosition]; |
b75a7d8f A |
193 | } |
194 | ||
195 | void GlyphIterator::getCursiveLastExitPoint(LEPoint &exitPoint) const | |
196 | { | |
197 | if (cursiveLastPosition >= 0) { | |
198 | exitPoint = cursiveLastExitPoint; | |
199 | } | |
200 | } | |
201 | ||
202 | float GlyphIterator::getCursiveBaselineAdjustment() const | |
203 | { | |
204 | return cursiveBaselineAdjustment; | |
205 | } | |
206 | ||
207 | void GlyphIterator::getCurrGlyphPositionAdjustment(GlyphPositionAdjustment &adjustment) const | |
208 | { | |
209 | if (direction < 0) | |
210 | { | |
211 | if (position <= nextLimit || position >= prevLimit) | |
212 | { | |
213 | return; | |
214 | } | |
215 | } else { | |
216 | if (position <= prevLimit || position >= nextLimit) { | |
217 | return; | |
218 | } | |
219 | } | |
220 | ||
221 | adjustment = glyphPositionAdjustments[position]; | |
222 | } | |
223 | ||
224 | void GlyphIterator::getCursiveLastPositionAdjustment(GlyphPositionAdjustment &adjustment) const | |
225 | { | |
226 | if (direction < 0) | |
227 | { | |
228 | if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) | |
229 | { | |
230 | return; | |
231 | } | |
232 | } else { | |
233 | if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) { | |
234 | return; | |
235 | } | |
236 | } | |
237 | ||
238 | adjustment = glyphPositionAdjustments[cursiveLastPosition]; | |
239 | } | |
240 | ||
241 | void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID) | |
242 | { | |
374ca955 A |
243 | LEGlyphID glyph = glyphStorage[position]; |
244 | ||
245 | glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID); | |
b75a7d8f A |
246 | } |
247 | ||
248 | void GlyphIterator::setCurrStreamPosition(le_int32 newPosition) | |
249 | { | |
250 | cursiveFirstPosition = -1; | |
251 | cursiveLastPosition = -1; | |
252 | cursiveBaselineAdjustment = 0; | |
253 | ||
254 | if (direction < 0) { | |
255 | if (newPosition >= prevLimit) { | |
256 | position = prevLimit; | |
257 | return; | |
258 | } | |
259 | ||
260 | if (newPosition <= nextLimit) { | |
261 | position = nextLimit; | |
262 | return; | |
263 | } | |
264 | } else { | |
265 | if (newPosition <= prevLimit) { | |
266 | position = prevLimit; | |
267 | return; | |
268 | } | |
269 | ||
270 | if (newPosition >= nextLimit) { | |
271 | position = nextLimit; | |
272 | return; | |
273 | } | |
274 | } | |
275 | ||
276 | position = newPosition - direction; | |
277 | next(); | |
278 | } | |
279 | ||
280 | void GlyphIterator::setCurrGlyphPositionAdjustment(const GlyphPositionAdjustment *adjustment) | |
281 | { | |
282 | if (direction < 0) { | |
283 | if (position <= nextLimit || position >= prevLimit) { | |
284 | return; | |
285 | } | |
286 | } else { | |
287 | if (position <= prevLimit || position >= nextLimit) { | |
288 | return; | |
289 | } | |
290 | } | |
291 | ||
292 | glyphPositionAdjustments[position] = *adjustment; | |
293 | } | |
294 | ||
295 | void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset) | |
296 | { | |
297 | if (direction < 0) { | |
298 | if (position <= nextLimit || position >= prevLimit) { | |
299 | return; | |
300 | } | |
301 | } else { | |
302 | if (position <= prevLimit || position >= nextLimit) { | |
303 | return; | |
304 | } | |
305 | } | |
306 | ||
307 | glyphPositionAdjustments[position].setBaseOffset(baseOffset); | |
308 | } | |
309 | ||
310 | void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust, | |
311 | float xAdvanceAdjust, float yAdvanceAdjust) | |
312 | { | |
313 | if (direction < 0) { | |
314 | if (position <= nextLimit || position >= prevLimit) { | |
315 | return; | |
316 | } | |
317 | } else { | |
318 | if (position <= prevLimit || position >= nextLimit) { | |
319 | return; | |
320 | } | |
321 | } | |
322 | ||
323 | glyphPositionAdjustments[position].adjustXPlacement(xPlacementAdjust); | |
324 | glyphPositionAdjustments[position].adjustYPlacement(yPlacementAdjust); | |
325 | glyphPositionAdjustments[position].adjustXAdvance(xAdvanceAdjust); | |
326 | glyphPositionAdjustments[position].adjustYAdvance(yAdvanceAdjust); | |
327 | } | |
328 | ||
374ca955 A |
329 | void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust, |
330 | float xAdvanceAdjust, float yAdvanceAdjust) | |
331 | { | |
332 | if (direction < 0) { | |
333 | if (position <= nextLimit || position >= prevLimit) { | |
334 | return; | |
335 | } | |
336 | } else { | |
337 | if (position <= prevLimit || position >= nextLimit) { | |
338 | return; | |
339 | } | |
340 | } | |
341 | ||
342 | glyphPositionAdjustments[position].setXPlacement(xPlacementAdjust); | |
343 | glyphPositionAdjustments[position].setYPlacement(yPlacementAdjust); | |
344 | glyphPositionAdjustments[position].setXAdvance(xAdvanceAdjust); | |
345 | glyphPositionAdjustments[position].setYAdvance(yAdvanceAdjust); | |
346 | } | |
347 | ||
b75a7d8f A |
348 | void GlyphIterator::setCursiveFirstExitPoint() |
349 | { | |
350 | if (direction < 0) { | |
351 | if (position <= nextLimit || position >= prevLimit) { | |
352 | return; | |
353 | } | |
354 | } else { | |
355 | if (position <= prevLimit || position >= nextLimit) { | |
356 | return; | |
357 | } | |
358 | } | |
359 | ||
360 | cursiveFirstPosition = position; | |
361 | } | |
362 | ||
363 | void GlyphIterator::resetCursiveLastExitPoint() | |
364 | { | |
365 | if ((lookupFlags & lfBaselineIsLogicalEnd) != 0 && cursiveFirstPosition >= 0 && cursiveLastPosition >= 0) { | |
366 | le_int32 savePosition = position, saveLimit = nextLimit; | |
367 | ||
368 | position = cursiveFirstPosition - direction; | |
369 | nextLimit = cursiveLastPosition + direction; | |
370 | ||
371 | while (nextInternal()) { | |
372 | glyphPositionAdjustments[position].adjustYPlacement(-cursiveBaselineAdjustment); | |
373 | } | |
374 | ||
375 | position = savePosition; | |
376 | nextLimit = saveLimit; | |
377 | } | |
378 | ||
379 | cursiveLastPosition = -1; | |
380 | cursiveFirstPosition = -1; | |
381 | cursiveBaselineAdjustment = 0; | |
382 | } | |
383 | ||
384 | void GlyphIterator::setCursiveLastExitPoint(LEPoint &exitPoint) | |
385 | { | |
386 | if (direction < 0) { | |
387 | if (position <= nextLimit || position >= prevLimit) { | |
388 | return; | |
389 | } | |
390 | } else { | |
391 | if (position <= prevLimit || position >= nextLimit) { | |
392 | return; | |
393 | } | |
394 | } | |
395 | ||
396 | cursiveLastPosition = position; | |
397 | cursiveLastExitPoint = exitPoint; | |
398 | ||
399 | } | |
400 | ||
401 | void GlyphIterator::setCursiveBaselineAdjustment(float adjustment) | |
402 | { | |
403 | cursiveBaselineAdjustment = adjustment; | |
404 | } | |
405 | ||
406 | void GlyphIterator::adjustCursiveLastGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust, | |
407 | float xAdvanceAdjust, float yAdvanceAdjust) | |
408 | { | |
409 | if (direction < 0) { | |
410 | if (cursiveLastPosition <= nextLimit || cursiveLastPosition >= prevLimit) { | |
411 | return; | |
412 | } | |
413 | } else { | |
414 | if (cursiveLastPosition <= prevLimit || cursiveLastPosition >= nextLimit) { | |
415 | return; | |
416 | } | |
417 | } | |
418 | ||
419 | glyphPositionAdjustments[cursiveLastPosition].adjustXPlacement(xPlacementAdjust); | |
420 | glyphPositionAdjustments[cursiveLastPosition].adjustYPlacement(yPlacementAdjust); | |
421 | glyphPositionAdjustments[cursiveLastPosition].adjustXAdvance(xAdvanceAdjust); | |
422 | glyphPositionAdjustments[cursiveLastPosition].adjustYAdvance(yAdvanceAdjust); | |
423 | } | |
424 | ||
425 | le_bool GlyphIterator::filterGlyph(le_uint32 index) const | |
426 | { | |
374ca955 | 427 | LEGlyphID glyphID = glyphStorage[index]; |
b75a7d8f A |
428 | le_int32 glyphClass = gcdNoGlyphClass; |
429 | ||
430 | if (LE_GET_GLYPH(glyphID) >= 0xFFFE) { | |
374ca955 | 431 | return TRUE; |
b75a7d8f A |
432 | } |
433 | ||
434 | if (glyphClassDefinitionTable != NULL) { | |
435 | glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID); | |
436 | } | |
437 | ||
438 | switch (glyphClass) | |
439 | { | |
440 | case gcdNoGlyphClass: | |
374ca955 | 441 | return FALSE; |
b75a7d8f A |
442 | |
443 | case gcdSimpleGlyph: | |
444 | return (lookupFlags & lfIgnoreBaseGlyphs) != 0; | |
445 | ||
446 | case gcdLigatureGlyph: | |
447 | return (lookupFlags & lfIgnoreLigatures) != 0; | |
448 | ||
449 | case gcdMarkGlyph: | |
450 | { | |
451 | if ((lookupFlags & lfIgnoreMarks) != 0) { | |
374ca955 | 452 | return TRUE; |
b75a7d8f A |
453 | } |
454 | ||
455 | le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift; | |
456 | ||
457 | if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) { | |
458 | return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType; | |
459 | } | |
460 | ||
374ca955 | 461 | return FALSE; |
b75a7d8f A |
462 | } |
463 | ||
464 | case gcdComponentGlyph: | |
465 | return (lookupFlags & lfIgnoreBaseGlyphs) != 0; | |
466 | ||
467 | default: | |
374ca955 | 468 | return FALSE; |
b75a7d8f A |
469 | } |
470 | } | |
471 | ||
374ca955 A |
472 | static const LETag emptyTag = 0; |
473 | static const LETag defaultTag = 0xFFFFFFFF; | |
b75a7d8f A |
474 | |
475 | le_bool GlyphIterator::hasFeatureTag() const | |
476 | { | |
477 | if (featureTag == defaultTag || featureTag == emptyTag) { | |
374ca955 | 478 | return TRUE; |
b75a7d8f A |
479 | } |
480 | ||
374ca955 A |
481 | LEErrorCode success = LE_NO_ERROR; |
482 | const LETag *tagList = (const LETag *) glyphStorage.getAuxData(position, success); | |
b75a7d8f | 483 | |
374ca955 | 484 | if (tagList != NULL) { |
b75a7d8f A |
485 | for (le_int32 tag = 0; tagList[tag] != emptyTag; tag += 1) { |
486 | if (tagList[tag] == featureTag) { | |
374ca955 | 487 | return TRUE; |
b75a7d8f A |
488 | } |
489 | } | |
490 | } | |
491 | ||
374ca955 | 492 | return FALSE; |
b75a7d8f A |
493 | } |
494 | ||
495 | le_bool GlyphIterator::findFeatureTag() | |
496 | { | |
497 | while (nextInternal()) { | |
498 | if (hasFeatureTag()) { | |
499 | prevInternal(); | |
374ca955 | 500 | return TRUE; |
b75a7d8f A |
501 | } |
502 | } | |
503 | ||
374ca955 | 504 | return FALSE; |
b75a7d8f A |
505 | } |
506 | ||
507 | ||
508 | le_bool GlyphIterator::nextInternal(le_uint32 delta) | |
509 | { | |
510 | le_int32 newPosition = position; | |
511 | ||
512 | while (newPosition != nextLimit && delta > 0) { | |
513 | do { | |
514 | newPosition += direction; | |
515 | } while (newPosition != nextLimit && filterGlyph(newPosition)); | |
516 | ||
517 | delta -= 1; | |
518 | } | |
519 | ||
520 | position = newPosition; | |
521 | ||
522 | return position != nextLimit; | |
523 | } | |
524 | ||
525 | le_bool GlyphIterator::next(le_uint32 delta) | |
526 | { | |
527 | return nextInternal(delta) && hasFeatureTag(); | |
528 | } | |
529 | ||
530 | le_bool GlyphIterator::prevInternal(le_uint32 delta) | |
531 | { | |
532 | le_int32 newPosition = position; | |
533 | ||
534 | while (newPosition != prevLimit && delta > 0) { | |
535 | do { | |
536 | newPosition -= direction; | |
537 | } while (newPosition != prevLimit && filterGlyph(newPosition)); | |
538 | ||
539 | delta -= 1; | |
540 | } | |
541 | ||
542 | position = newPosition; | |
543 | ||
544 | return position != prevLimit; | |
545 | } | |
546 | ||
547 | le_bool GlyphIterator::prev(le_uint32 delta) | |
548 | { | |
549 | return prevInternal(delta) && hasFeatureTag(); | |
550 | } | |
551 | ||
552 | le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const | |
553 | { | |
554 | le_int32 component = 0; | |
555 | le_int32 posn; | |
556 | ||
557 | for (posn = position; posn != markPosition; posn += direction) { | |
374ca955 | 558 | if (glyphStorage[posn] == 0xFFFE) { |
b75a7d8f A |
559 | component += 1; |
560 | } | |
561 | } | |
562 | ||
563 | return component; | |
564 | } | |
565 | ||
566 | // This is basically prevInternal except that it | |
567 | // doesn't take a delta argument, and it doesn't | |
568 | // filter out 0xFFFE glyphs. | |
569 | le_bool GlyphIterator::findMark2Glyph() | |
570 | { | |
571 | le_int32 newPosition = position; | |
572 | ||
573 | do { | |
574 | newPosition -= direction; | |
374ca955 | 575 | } while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE && filterGlyph(newPosition)); |
b75a7d8f A |
576 | |
577 | position = newPosition; | |
578 | ||
579 | return position != prevLimit; | |
580 | } | |
581 | ||
582 | U_NAMESPACE_END |