Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/font/layout/ArabicShaping.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 "ArabicShaping.h"34#include "LEGlyphStorage.h"35#include "ClassDefinitionTables.h"3637U_NAMESPACE_BEGIN3839// This table maps Unicode joining types to40// ShapeTypes.41const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =42{43ArabicShaping::ST_NOSHAPE_NONE, // [U]44ArabicShaping::ST_NOSHAPE_DUAL, // [C]45ArabicShaping::ST_DUAL, // [D]46ArabicShaping::ST_LEFT, // [L]47ArabicShaping::ST_RIGHT, // [R]48ArabicShaping::ST_TRANSPARENT // [T]49};5051/*52shaping array holds types for Arabic chars between 0610 and 070053other values are either unshaped, or transparent if a mark or format54code, except for format codes 200c (zero-width non-joiner) and 200d55(dual-width joiner) which are both unshaped and non_joining or56dual-joining, respectively.57*/58ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)59{60LEErrorCode success = LE_NO_ERROR;61const LEReferenceTo<ClassDefinitionTable> joiningTypes(LETableReference::kStaticData,62(const ClassDefinitionTable *) ArabicShaping::shapingTypeTable,63ArabicShaping::shapingTypeTableLen);64le_int32 joiningType = joiningTypes->getGlyphClass(joiningTypes, c, success);6566if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT && LE_SUCCESS(success)) {67return ArabicShaping::shapeTypes[joiningType];68}6970return ArabicShaping::ST_NOSHAPE_NONE;71}7273#define isolFeatureTag LE_ISOL_FEATURE_TAG74#define initFeatureTag LE_INIT_FEATURE_TAG75#define mediFeatureTag LE_MEDI_FEATURE_TAG76#define finaFeatureTag LE_FINA_FEATURE_TAG77#define ligaFeatureTag LE_LIGA_FEATURE_TAG78#define msetFeatureTag LE_MSET_FEATURE_TAG79#define markFeatureTag LE_MARK_FEATURE_TAG80#define ccmpFeatureTag LE_CCMP_FEATURE_TAG81#define rligFeatureTag LE_RLIG_FEATURE_TAG82#define caltFeatureTag LE_CALT_FEATURE_TAG83#define dligFeatureTag LE_DLIG_FEATURE_TAG84#define cswhFeatureTag LE_CSWH_FEATURE_TAG85#define cursFeatureTag LE_CURS_FEATURE_TAG86#define kernFeatureTag LE_KERN_FEATURE_TAG87#define mkmkFeatureTag LE_MKMK_FEATURE_TAG8889// NOTE:90// The isol, fina, init and medi features must be91// defined in the above order, and have masks that92// are all in the same nibble.93#define isolFeatureMask 0x80000000UL94#define finaFeatureMask 0x40000000UL95#define initFeatureMask 0x20000000UL96#define mediFeatureMask 0x10000000UL97#define ccmpFeatureMask 0x08000000UL98#define rligFeatureMask 0x04000000UL99#define caltFeatureMask 0x02000000UL100#define ligaFeatureMask 0x01000000UL101#define dligFeatureMask 0x00800000UL102#define cswhFeatureMask 0x00400000UL103#define msetFeatureMask 0x00200000UL104#define cursFeatureMask 0x00100000UL105#define kernFeatureMask 0x00080000UL106#define markFeatureMask 0x00040000UL107#define mkmkFeatureMask 0x00020000UL108109#define NO_FEATURES 0110#define ISOL_FEATURES (isolFeatureMask | ligaFeatureMask | msetFeatureMask | markFeatureMask | ccmpFeatureMask | rligFeatureMask | caltFeatureMask | dligFeatureMask | cswhFeatureMask | cursFeatureMask | kernFeatureMask | mkmkFeatureMask)111112#define SHAPE_MASK 0xF0000000UL113114static const FeatureMap featureMap[] = {115{ccmpFeatureTag, ccmpFeatureMask},116{isolFeatureTag, isolFeatureMask},117{finaFeatureTag, finaFeatureMask},118{mediFeatureTag, mediFeatureMask},119{initFeatureTag, initFeatureMask},120{rligFeatureTag, rligFeatureMask},121{caltFeatureTag, caltFeatureMask},122{ligaFeatureTag, ligaFeatureMask},123{dligFeatureTag, dligFeatureMask},124{cswhFeatureTag, cswhFeatureMask},125{msetFeatureTag, msetFeatureMask},126{cursFeatureTag, cursFeatureMask},127{kernFeatureTag, kernFeatureMask},128{markFeatureTag, markFeatureMask},129{mkmkFeatureTag, mkmkFeatureMask}130};131132const FeatureMap *ArabicShaping::getFeatureMap(le_int32 &count)133{134count = LE_ARRAY_SIZE(featureMap);135136return featureMap;137}138139void ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage)140{141LEErrorCode success = LE_NO_ERROR;142FeatureMask featureMask = (FeatureMask) glyphStorage.getAuxData(outIndex, success);143FeatureMask shape = featureMask & SHAPE_MASK;144145shape >>= shapeOffset;146147glyphStorage.setAuxData(outIndex, ((featureMask & ~SHAPE_MASK) | shape), success);148}149150void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax,151le_bool rightToLeft, LEGlyphStorage &glyphStorage)152{153// iterate in logical order, store tags in visible order154//155// the effective right char is the most recently encountered156// non-transparent char157//158// four boolean states:159// the effective right char shapes160// the effective right char causes left shaping161// the current char shapes162// the current char causes right shaping163//164// if both cause shaping, then165// shaper.shape(errout, 2) (isolate to initial, or final to medial)166// shaper.shape(out, 1) (isolate to final)167168ShapeType rightType = ST_NOSHAPE_NONE, leftType = ST_NOSHAPE_NONE;169LEErrorCode success = LE_NO_ERROR;170le_int32 i;171172for (i = offset - 1; i >= 0; i -= 1) {173rightType = getShapeType(chars[i]);174175if (rightType != ST_TRANSPARENT) {176break;177}178}179180for (i = offset + charCount; i < charMax; i += 1) {181leftType = getShapeType(chars[i]);182183if (leftType != ST_TRANSPARENT) {184break;185}186}187188// erout is effective right logical index189le_int32 erout = -1;190le_bool rightShapes = FALSE;191le_bool rightCauses = (rightType & MASK_SHAPE_LEFT) != 0;192le_int32 in, e, out = 0, dir = 1;193194if (rightToLeft) {195out = charCount - 1;196erout = charCount;197dir = -1;198}199200for (in = offset, e = offset + charCount; in < e; in += 1, out += dir) {201LEUnicode c = chars[in];202ShapeType t = getShapeType(c);203204if (t == ST_NOSHAPE_NONE) {205glyphStorage.setAuxData(out, NO_FEATURES, success);206} else {207glyphStorage.setAuxData(out, ISOL_FEATURES, success);208}209210if ((t & MASK_TRANSPARENT) != 0) {211continue;212}213214le_bool curShapes = (t & MASK_NOSHAPE) == 0;215le_bool curCauses = (t & MASK_SHAPE_RIGHT) != 0;216217if (rightCauses && curCauses) {218if (rightShapes) {219adjustTags(erout, 2, glyphStorage);220}221222if (curShapes) {223adjustTags(out, 1, glyphStorage);224}225}226227rightShapes = curShapes;228rightCauses = (t & MASK_SHAPE_LEFT) != 0;229erout = out;230}231232if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) {233adjustTags(erout, 2, glyphStorage);234}235}236237U_NAMESPACE_END238239240