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 16U_NAMESPACE_BEGIN 17 18GlyphIterator::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 47GlyphIterator::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 66GlyphIterator::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 85GlyphIterator::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 104GlyphIterator::~GlyphIterator() 105{ 106 // nothing to do, right? 107} 108 109void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask) 110{ 111 position = prevLimit; 112 featureMask = newFeatureMask; 113 glyphGroup = 0; 114 lookupFlags = newLookupFlags; 115 filterResetCache(); 116} 117 118LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success) 119{ 120 return glyphStorage.insertGlyphs(position, count, success); 121} 122 123le_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 136le_int32 GlyphIterator::getCurrStreamPosition() const 137{ 138 return position; 139} 140 141le_bool GlyphIterator::isRightToLeft() const 142{ 143 return direction < 0; 144} 145 146le_bool GlyphIterator::ignoresMarks() const 147{ 148 return (lookupFlags & lfIgnoreMarks) != 0; 149} 150 151le_bool GlyphIterator::baselineIsLogicalEnd() const 152{ 153 return (lookupFlags & lfBaselineIsLogicalEnd) != 0; 154} 155 156LEGlyphID 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 171void 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 186void 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 201void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID) 202{ 203 LEGlyphID glyph = glyphStorage[position]; 204 205 glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID); 206} 207 208void 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 236void 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 251void 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 270void 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 289void 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 304void 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 319void 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 334void 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 349void 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 364void GlyphIterator::filterResetCache(void) { 365 filterCacheValid = FALSE; 366} 367 368le_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 428le_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 440le_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 457le_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 476le_bool GlyphIterator::next(le_uint32 delta) 477{ 478 return nextInternal(delta) && hasFeatureTag(TRUE); 479} 480 481le_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 500le_bool GlyphIterator::prev(le_uint32 delta) 501{ 502 return prevInternal(delta) && hasFeatureTag(TRUE); 503} 504 505le_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. 522le_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 535U_NAMESPACE_END 536