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