Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/font/layout/GlyphIterator.cpp
38918 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425/*26*27* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved28*29*/3031#include "LETypes.h"32#include "OpenTypeTables.h"33#include "GlyphDefinitionTables.h"34#include "GlyphPositionAdjustments.h"35#include "GlyphIterator.h"36#include "LEGlyphStorage.h"37#include "Lookups.h"38#include "LESwaps.h"3940U_NAMESPACE_BEGIN4142GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,43FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader, LEErrorCode &success)44: direction(1), position(-1), nextLimit(-1), prevLimit(-1),45glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),46srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),47glyphClassDefinitionTable(), markAttachClassDefinitionTable()4849{50le_int32 glyphCount = glyphStorage.getGlyphCount();5152if (theGlyphDefinitionTableHeader.isValid()) {53glyphClassDefinitionTable = theGlyphDefinitionTableHeader54-> getGlyphClassDefinitionTable(theGlyphDefinitionTableHeader, success);55markAttachClassDefinitionTable = theGlyphDefinitionTableHeader56->getMarkAttachClassDefinitionTable(theGlyphDefinitionTableHeader, success);57}5859nextLimit = glyphCount;6061if (rightToLeft) {62direction = -1;63position = glyphCount;64nextLimit = -1;65prevLimit = glyphCount;66}67filterResetCache();68}6970GlyphIterator::GlyphIterator(GlyphIterator &that)71: glyphStorage(that.glyphStorage)72{73direction = that.direction;74position = that.position;75nextLimit = that.nextLimit;76prevLimit = that.prevLimit;7778glyphPositionAdjustments = that.glyphPositionAdjustments;79srcIndex = that.srcIndex;80destIndex = that.destIndex;81lookupFlags = that.lookupFlags;82featureMask = that.featureMask;83glyphGroup = that.glyphGroup;84glyphClassDefinitionTable = that.glyphClassDefinitionTable;85markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;86filterResetCache();87}8889GlyphIterator::GlyphIterator(GlyphIterator &that, FeatureMask newFeatureMask)90: glyphStorage(that.glyphStorage)91{92direction = that.direction;93position = that.position;94nextLimit = that.nextLimit;95prevLimit = that.prevLimit;9697glyphPositionAdjustments = that.glyphPositionAdjustments;98srcIndex = that.srcIndex;99destIndex = that.destIndex;100lookupFlags = that.lookupFlags;101featureMask = newFeatureMask;102glyphGroup = 0;103glyphClassDefinitionTable = that.glyphClassDefinitionTable;104markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;105filterResetCache();106}107108GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)109: glyphStorage(that.glyphStorage)110{111direction = that.direction;112position = that.position;113nextLimit = that.nextLimit;114prevLimit = that.prevLimit;115116glyphPositionAdjustments = that.glyphPositionAdjustments;117srcIndex = that.srcIndex;118destIndex = that.destIndex;119lookupFlags = newLookupFlags;120featureMask = that.featureMask;121glyphGroup = that.glyphGroup;122glyphClassDefinitionTable = that.glyphClassDefinitionTable;123markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;124filterResetCache();125}126127GlyphIterator::~GlyphIterator()128{129// nothing to do, right?130}131132void GlyphIterator::reset(le_uint16 newLookupFlags, FeatureMask newFeatureMask)133{134position = prevLimit;135featureMask = newFeatureMask;136glyphGroup = 0;137lookupFlags = newLookupFlags;138filterResetCache();139}140141LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count, LEErrorCode& success)142{143return glyphStorage.insertGlyphs(position, count, success);144}145146le_int32 GlyphIterator::applyInsertions()147{148le_int32 newGlyphCount = glyphStorage.applyInsertions();149150if (direction < 0) {151prevLimit = newGlyphCount;152} else {153nextLimit = newGlyphCount;154}155156return newGlyphCount;157}158159le_int32 GlyphIterator::getCurrStreamPosition() const160{161return position;162}163164le_bool GlyphIterator::isRightToLeft() const165{166return direction < 0;167}168169le_bool GlyphIterator::ignoresMarks() const170{171return (lookupFlags & lfIgnoreMarks) != 0;172}173174le_bool GlyphIterator::baselineIsLogicalEnd() const175{176return (lookupFlags & lfBaselineIsLogicalEnd) != 0;177}178179LEGlyphID GlyphIterator::getCurrGlyphID() const180{181if (direction < 0) {182if (position <= nextLimit || position >= prevLimit) {183return 0xFFFF;184}185} else {186if (position <= prevLimit || position >= nextLimit) {187return 0xFFFF;188}189}190191return glyphStorage[position];192}193194void GlyphIterator::getCursiveEntryPoint(LEPoint &entryPoint) const195{196if (direction < 0) {197if (position <= nextLimit || position >= prevLimit) {198return;199}200} else {201if (position <= prevLimit || position >= nextLimit) {202return;203}204}205206glyphPositionAdjustments->getEntryPoint(position, entryPoint);207}208209void GlyphIterator::getCursiveExitPoint(LEPoint &exitPoint) const210{211if (direction < 0) {212if (position <= nextLimit || position >= prevLimit) {213return;214}215} else {216if (position <= prevLimit || position >= nextLimit) {217return;218}219}220221glyphPositionAdjustments->getExitPoint(position, exitPoint);222}223224void GlyphIterator::setCurrGlyphID(TTGlyphID glyphID)225{226if (direction < 0) {227if (position <= nextLimit || position >= prevLimit) {228return;229}230} else {231if (position <= prevLimit || position >= nextLimit) {232return;233}234}235236LEGlyphID glyph = glyphStorage[position];237238glyphStorage[position] = LE_SET_GLYPH(glyph, glyphID);239}240241void GlyphIterator::setCurrStreamPosition(le_int32 newPosition)242{243if (direction < 0) {244if (newPosition >= prevLimit) {245position = prevLimit;246return;247}248249if (newPosition <= nextLimit) {250position = nextLimit;251return;252}253} else {254if (newPosition <= prevLimit) {255position = prevLimit;256return;257}258259if (newPosition >= nextLimit) {260position = nextLimit;261return;262}263}264265position = newPosition - direction;266next();267}268269void GlyphIterator::setCurrGlyphBaseOffset(le_int32 baseOffset)270{271if (direction < 0) {272if (position <= nextLimit || position >= prevLimit) {273return;274}275} else {276if (position <= prevLimit || position >= nextLimit) {277return;278}279}280281glyphPositionAdjustments->setBaseOffset(position, baseOffset);282}283284void GlyphIterator::adjustCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,285float xAdvanceAdjust, float yAdvanceAdjust)286{287if (direction < 0) {288if (position <= nextLimit || position >= prevLimit) {289return;290}291} else {292if (position <= prevLimit || position >= nextLimit) {293return;294}295}296297glyphPositionAdjustments->adjustXPlacement(position, xPlacementAdjust);298glyphPositionAdjustments->adjustYPlacement(position, yPlacementAdjust);299glyphPositionAdjustments->adjustXAdvance(position, xAdvanceAdjust);300glyphPositionAdjustments->adjustYAdvance(position, yAdvanceAdjust);301}302303void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,304float xAdvanceAdjust, float yAdvanceAdjust)305{306if (direction < 0) {307if (position <= nextLimit || position >= prevLimit) {308return;309}310} else {311if (position <= prevLimit || position >= nextLimit) {312return;313}314}315316glyphPositionAdjustments->setXPlacement(position, xPlacementAdjust);317glyphPositionAdjustments->setYPlacement(position, yPlacementAdjust);318glyphPositionAdjustments->setXAdvance(position, xAdvanceAdjust);319glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);320}321322void GlyphIterator::clearCursiveEntryPoint()323{324if (direction < 0) {325if (position <= nextLimit || position >= prevLimit) {326return;327}328} else {329if (position <= prevLimit || position >= nextLimit) {330return;331}332}333334glyphPositionAdjustments->clearEntryPoint(position);335}336337void GlyphIterator::clearCursiveExitPoint()338{339if (direction < 0) {340if (position <= nextLimit || position >= prevLimit) {341return;342}343} else {344if (position <= prevLimit || position >= nextLimit) {345return;346}347}348349glyphPositionAdjustments->clearExitPoint(position);350}351352void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)353{354if (direction < 0) {355if (position <= nextLimit || position >= prevLimit) {356return;357}358} else {359if (position <= prevLimit || position >= nextLimit) {360return;361}362}363364glyphPositionAdjustments->setEntryPoint(position, entryPoint, baselineIsLogicalEnd());365}366367void GlyphIterator::setCursiveExitPoint(LEPoint &exitPoint)368{369if (direction < 0) {370if (position <= nextLimit || position >= prevLimit) {371return;372}373} else {374if (position <= prevLimit || position >= nextLimit) {375return;376}377}378379glyphPositionAdjustments->setExitPoint(position, exitPoint, baselineIsLogicalEnd());380}381382void GlyphIterator::setCursiveGlyph()383{384if (direction < 0) {385if (position <= nextLimit || position >= prevLimit) {386return;387}388} else {389if (position <= prevLimit || position >= nextLimit) {390return;391}392}393394glyphPositionAdjustments->setCursiveGlyph(position, baselineIsLogicalEnd());395}396397void GlyphIterator::filterResetCache(void) {398filterCacheValid = FALSE;399}400401le_bool GlyphIterator::filterGlyph(le_uint32 index)402{403LEGlyphID glyphID = glyphStorage[index];404405if (!filterCacheValid || filterCache.id != glyphID) {406filterCache.id = glyphID;407408le_bool &filterResult = filterCache.result; // NB: Making this a reference to accept the updated value, in case409// we want more fancy cacheing in the future.410if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {411filterResult = TRUE;412} else {413LEErrorCode success = LE_NO_ERROR;414le_int32 glyphClass = gcdNoGlyphClass;415if (glyphClassDefinitionTable.isValid()) {416glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success);417}418switch (glyphClass) {419case gcdNoGlyphClass:420filterResult = FALSE;421break;422423case gcdSimpleGlyph:424filterResult = (lookupFlags & lfIgnoreBaseGlyphs) != 0;425break;426427case gcdLigatureGlyph:428filterResult = (lookupFlags & lfIgnoreLigatures) != 0;429break;430431case gcdMarkGlyph:432if ((lookupFlags & lfIgnoreMarks) != 0) {433filterResult = TRUE;434} else {435le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;436437if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) {438filterResult = (markAttachClassDefinitionTable439-> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType);440} else {441filterResult = FALSE;442}443}444break;445446case gcdComponentGlyph:447filterResult = ((lookupFlags & lfIgnoreBaseGlyphs) != 0);448break;449450default:451filterResult = FALSE;452break;453}454}455filterCacheValid = TRUE;456}457458return filterCache.result;459}460461le_bool GlyphIterator::hasFeatureTag(le_bool matchGroup) const462{463if (featureMask == 0) {464return TRUE;465}466467LEErrorCode success = LE_NO_ERROR;468FeatureMask fm = glyphStorage.getAuxData(position, success);469470return ((fm & featureMask) == featureMask) && (!matchGroup || (le_int32)(fm & LE_GLYPH_GROUP_MASK) == glyphGroup);471}472473le_bool GlyphIterator::findFeatureTag()474{475//glyphGroup = 0;476477while (nextInternal()) {478if (hasFeatureTag(FALSE)) {479LEErrorCode success = LE_NO_ERROR;480481glyphGroup = (glyphStorage.getAuxData(position, success) & LE_GLYPH_GROUP_MASK);482return TRUE;483}484}485486return FALSE;487}488489490le_bool GlyphIterator::nextInternal(le_uint32 delta)491{492le_int32 newPosition = position;493494while (newPosition != nextLimit && delta > 0) {495do {496newPosition += direction;497//fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);498} while (newPosition != nextLimit && filterGlyph(newPosition));499500delta -= 1;501}502503position = newPosition;504505//fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);506return position != nextLimit;507}508509le_bool GlyphIterator::next(le_uint32 delta)510{511return nextInternal(delta) && hasFeatureTag(TRUE);512}513514le_bool GlyphIterator::prevInternal(le_uint32 delta)515{516le_int32 newPosition = position;517518while (newPosition != prevLimit && delta > 0) {519do {520newPosition -= direction;521//fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);522} while (newPosition != prevLimit && filterGlyph(newPosition));523524delta -= 1;525}526527position = newPosition;528529//fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);530return position != prevLimit;531}532533le_bool GlyphIterator::prev(le_uint32 delta)534{535return prevInternal(delta) && hasFeatureTag(TRUE);536}537538le_int32 GlyphIterator::getMarkComponent(le_int32 markPosition) const539{540le_int32 component = 0;541le_int32 posn;542543for (posn = position; posn != markPosition; posn += direction) {544if (glyphStorage[posn] == 0xFFFE) {545component += 1;546}547}548549return component;550}551552// This is basically prevInternal except that it553// doesn't take a delta argument, and it doesn't554// filter out 0xFFFE glyphs.555le_bool GlyphIterator::findMark2Glyph()556{557le_int32 newPosition = position;558559do {560newPosition -= direction;561} while (newPosition != prevLimit && glyphStorage[newPosition] != 0xFFFE && filterGlyph(newPosition));562563position = newPosition;564565return position != prevLimit;566}567568U_NAMESPACE_END569570571