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