annotate src/share/native/sun/font/layout/LookupProcessor.cpp @ 9107:687fd7c7986d

Added tag jdk8-b132 for changeset 43cb25339b55
author katleman
date Tue, 04 Mar 2014 11:51:53 -0800
parents d931b672bfa9
children
rev   line source
duke@0 1 /*
duke@0 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 3 *
duke@0 4 * This code is free software; you can redistribute it and/or modify it
duke@0 5 * under the terms of the GNU General Public License version 2 only, as
ohair@2362 6 * published by the Free Software Foundation. Oracle designates this
duke@0 7 * particular file as subject to the "Classpath" exception as provided
ohair@2362 8 * by Oracle in the LICENSE file that accompanied this code.
duke@0 9 *
duke@0 10 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 13 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 14 * accompanied this code).
duke@0 15 *
duke@0 16 * You should have received a copy of the GNU General Public License version
duke@0 17 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 19 *
ohair@2362 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@2362 21 * or visit www.oracle.com if you need additional information or have any
ohair@2362 22 * questions.
duke@0 23 *
duke@0 24 */
duke@0 25
duke@0 26 /*
duke@0 27 *
prr@6934 28 * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
duke@0 29 *
duke@0 30 */
duke@0 31
duke@0 32 #include "LETypes.h"
duke@0 33 #include "OpenTypeUtilities.h"
duke@0 34 #include "LEFontInstance.h"
duke@0 35 #include "OpenTypeTables.h"
srl@3171 36 #include "ICUFeatures.h"
duke@0 37 #include "Lookups.h"
duke@0 38 #include "ScriptAndLanguage.h"
duke@0 39 #include "GlyphDefinitionTables.h"
duke@0 40 #include "GlyphIterator.h"
duke@0 41 #include "LookupProcessor.h"
duke@0 42 #include "LEGlyphStorage.h"
duke@0 43 #include "LESwaps.h"
duke@0 44
srl@1693 45 U_NAMESPACE_BEGIN
srl@1693 46
prr@6936 47 le_uint32 LookupProcessor::applyLookupTable(const LEReferenceTo<LookupTable> &lookupTable, GlyphIterator *glyphIterator,
srl@3171 48 const LEFontInstance *fontInstance, LEErrorCode& success) const
duke@0 49 {
srl@3171 50 if (LE_FAILURE(success)) {
srl@3171 51 return 0;
srl@3171 52 }
srl@3171 53
duke@0 54 le_uint16 lookupType = SWAPW(lookupTable->lookupType);
duke@0 55 le_uint16 subtableCount = SWAPW(lookupTable->subTableCount);
duke@0 56 le_int32 startPosition = glyphIterator->getCurrStreamPosition();
duke@0 57 le_uint32 delta;
duke@0 58
duke@0 59 for (le_uint16 subtable = 0; subtable < subtableCount; subtable += 1) {
prr@6936 60 LEReferenceTo<LookupSubtable> lookupSubtable = lookupTable->getLookupSubtable(lookupTable, subtable, success);
duke@0 61
srl@3171 62 delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance, success);
prr@9053 63 if (delta > 0 && LE_FAILURE(success)) {
prr@9053 64 #if LE_TRACE
prr@9053 65 _LETRACE("Posn #%d, type %X, applied subtable #%d/%d - %s\n", startPosition, lookupType, subtable, subtableCount, u_errorName((UErrorCode)success));
prr@9053 66 #endif
prr@9053 67 return 1;
duke@0 68 }
duke@0 69
duke@0 70 glyphIterator->setCurrStreamPosition(startPosition);
duke@0 71 }
duke@0 72
duke@0 73 return 1;
duke@0 74 }
duke@0 75
srl@1693 76 le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
prr@6936 77 le_bool rightToLeft, const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader,
srl@3171 78 const LEFontInstance *fontInstance, LEErrorCode& success) const
duke@0 79 {
srl@3171 80 if (LE_FAILURE(success)) {
srl@3171 81 return 0;
srl@3171 82 }
srl@3171 83
duke@0 84 le_int32 glyphCount = glyphStorage.getGlyphCount();
duke@0 85
duke@0 86 if (lookupSelectArray == NULL) {
duke@0 87 return glyphCount;
duke@0 88 }
duke@0 89
duke@0 90 GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments,
prr@9053 91 rightToLeft, 0, 0, glyphDefinitionTableHeader, success);
duke@0 92 le_int32 newGlyphCount = glyphCount;
duke@0 93
prr@6936 94 for (le_uint16 order = 0; order < lookupOrderCount && LE_SUCCESS(success); order += 1) {
duke@0 95 le_uint16 lookup = lookupOrderArray[order];
duke@0 96 FeatureMask selectMask = lookupSelectArray[lookup];
duke@0 97
duke@0 98 if (selectMask != 0) {
prr@9053 99 _LETRACE("Processing order#%d/%d", order, lookupOrderCount);
prr@6936 100 const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookup, success);
prr@6936 101 if (!lookupTable.isValid() ||LE_FAILURE(success) ) {
bae@5555 102 continue;
prr@6934 103 }
duke@0 104 le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
duke@0 105
duke@0 106 glyphIterator.reset(lookupFlags, selectMask);
duke@0 107
duke@0 108 while (glyphIterator.findFeatureTag()) {
prr@9053 109 applyLookupTable(lookupTable, &glyphIterator, fontInstance, success);
srl@3171 110 if (LE_FAILURE(success)) {
prr@9053 111 #if LE_TRACE
prr@9053 112 _LETRACE("Failure for lookup 0x%x - %s\n", lookup, u_errorName((UErrorCode)success));
prr@9053 113 #endif
srl@3171 114 return 0;
duke@0 115 }
duke@0 116 }
duke@0 117
duke@0 118 newGlyphCount = glyphIterator.applyInsertions();
duke@0 119 }
duke@0 120 }
duke@0 121
duke@0 122 return newGlyphCount;
duke@0 123 }
duke@0 124
duke@0 125 le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator,
srl@3171 126 const LEFontInstance *fontInstance, LEErrorCode& success) const
duke@0 127 {
srl@3171 128 if (LE_FAILURE(success)) {
srl@3171 129 return 0;
srl@3171 130 }
srl@3171 131
prr@6936 132 const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookupTableIndex, success);
prr@6936 133 if (!lookupTable.isValid()) {
jgodinez@6605 134 success = LE_INTERNAL_ERROR;
jgodinez@6605 135 return 0;
jgodinez@6605 136 }
duke@0 137 le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
duke@0 138 GlyphIterator tempIterator(*glyphIterator, lookupFlags);
srl@3171 139 le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success);
duke@0 140
duke@0 141 return delta;
duke@0 142 }
duke@0 143
prr@6936 144 le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success)
duke@0 145 {
prr@6936 146 le_uint16 lookupCount = featureTable.isValid()? SWAPW(featureTable->lookupCount) : 0;
prr@9037 147 le_uint32 store = (le_uint32)order;
duke@0 148
prr@6936 149 LEReferenceToArrayOf<le_uint16> lookupListIndexArray(featureTable, success, featureTable->lookupListIndexArray, lookupCount);
bae@5555 150
prr@6936 151 for (le_uint16 lookup = 0; LE_SUCCESS(success) && lookup < lookupCount; lookup += 1) {
prr@6936 152 le_uint16 lookupListIndex = SWAPW(lookupListIndexArray.getObject(lookup,success));
prr@6936 153 if (lookupListIndex >= lookupSelectCount) {
prr@6936 154 continue;
prr@6936 155 }
prr@9037 156 if (store >= lookupOrderCount) {
prr@9037 157 continue;
prr@9037 158 }
prr@6936 159
prr@6936 160 lookupSelectArray[lookupListIndex] |= featureMask;
prr@6936 161 lookupOrderArray[store++] = lookupListIndex;
duke@0 162 }
duke@0 163
duke@0 164 return store - order;
duke@0 165 }
duke@0 166
prr@6936 167 LookupProcessor::LookupProcessor(const LETableReference &baseAddress,
duke@0 168 Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset,
srl@3171 169 LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures,
srl@3171 170 LEErrorCode& success)
prr@6936 171 : lookupListTable(), featureListTable(), lookupSelectArray(NULL), lookupSelectCount(0),
prr@6936 172 lookupOrderArray(NULL), lookupOrderCount(0), fReference(baseAddress)
duke@0 173 {
prr@6936 174 LEReferenceTo<ScriptListTable> scriptListTable;
prr@6936 175 LEReferenceTo<LangSysTable> langSysTable;
duke@0 176 le_uint16 featureCount = 0;
duke@0 177 le_uint16 lookupListCount = 0;
duke@0 178 le_uint16 requiredFeatureIndex;
duke@0 179
srl@3171 180 if (LE_FAILURE(success)) {
srl@3171 181 return;
srl@3171 182 }
srl@3171 183
duke@0 184 if (scriptListOffset != 0) {
prr@6936 185 scriptListTable = LEReferenceTo<ScriptListTable>(baseAddress, success, scriptListOffset);
prr@6936 186 langSysTable = scriptListTable->findLanguage(scriptListTable, scriptTag, languageTag, success);
duke@0 187
prr@6936 188 if (langSysTable.isValid() && LE_SUCCESS(success)) {
prr@6936 189 featureCount = SWAPW(langSysTable->featureCount);
prr@6936 190 }
duke@0 191 }
duke@0 192
duke@0 193 if (featureListOffset != 0) {
prr@6936 194 featureListTable = LEReferenceTo<FeatureListTable>(baseAddress, success, featureListOffset);
duke@0 195 }
duke@0 196
duke@0 197 if (lookupListOffset != 0) {
prr@6936 198 lookupListTable = LEReferenceTo<LookupListTable>(baseAddress,success, lookupListOffset);
prr@6936 199 if(LE_SUCCESS(success) && lookupListTable.isValid()) {
duke@0 200 lookupListCount = SWAPW(lookupListTable->lookupCount);
prr@6936 201 }
duke@0 202 }
duke@0 203
prr@6936 204 if (langSysTable.isEmpty() || featureListTable.isEmpty() || lookupListTable.isEmpty() ||
duke@0 205 featureCount == 0 || lookupListCount == 0) {
duke@0 206 return;
duke@0 207 }
duke@0 208
prr@6936 209 if(langSysTable.isValid()) {
prr@6936 210 requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex);
prr@6936 211 }
duke@0 212
duke@0 213 lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount);
srl@3171 214 if (lookupSelectArray == NULL) {
srl@3171 215 success = LE_MEMORY_ALLOCATION_ERROR;
srl@3171 216 return;
srl@3171 217 }
duke@0 218
duke@0 219 for (int i = 0; i < lookupListCount; i += 1) {
duke@0 220 lookupSelectArray[i] = 0;
duke@0 221 }
duke@0 222
bae@5555 223 lookupSelectCount = lookupListCount;
bae@5555 224
duke@0 225 le_int32 count, order = 0;
prr@6935 226 le_uint32 featureReferences = 0;
prr@6936 227 LEReferenceTo<FeatureTable> featureTable;
duke@0 228 LETag featureTag;
duke@0 229
prr@6936 230 LEReferenceTo<FeatureTable> requiredFeatureTable;
duke@0 231 LETag requiredFeatureTag = 0x00000000U;
duke@0 232
duke@0 233 // Count the total number of lookups referenced by all features. This will
duke@0 234 // be the maximum number of entries in the lookupOrderArray. We can't use
duke@0 235 // lookupListCount because some lookups might be referenced by more than
duke@0 236 // one feature.
prr@6936 237 if(featureListTable.isValid() && LE_SUCCESS(success)) {
prr@6936 238 LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
duke@0 239
prr@6936 240 for (le_uint32 feature = 0; LE_SUCCESS(success)&&(feature < featureCount); feature += 1) {
prr@6936 241 le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature, success));
prr@6936 242
prr@6936 243 featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
prr@6936 244 if (!featureTable.isValid() || LE_FAILURE(success)) {
prr@6936 245 continue;
prr@6934 246 }
prr@6934 247 featureReferences += SWAPW(featureTable->lookupCount);
prr@6936 248 }
prr@6934 249 }
bae@5555 250
prr@6936 251 if (!featureTable.isValid() || LE_FAILURE(success)) {
prr@6934 252 success = LE_INTERNAL_ERROR;
prr@6934 253 return;
duke@0 254 }
duke@0 255
duke@0 256 if (requiredFeatureIndex != 0xFFFF) {
prr@6936 257 requiredFeatureTable = featureListTable->getFeatureTable(featureListTable, requiredFeatureIndex, &requiredFeatureTag, success);
prr@9037 258 featureReferences += SWAPW(requiredFeatureTable->lookupCount);
duke@0 259 }
duke@0 260
duke@0 261 lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences);
srl@3171 262 if (lookupOrderArray == NULL) {
srl@3171 263 success = LE_MEMORY_ALLOCATION_ERROR;
srl@3171 264 return;
srl@3171 265 }
prr@9037 266 lookupOrderCount = featureReferences;
duke@0 267
duke@0 268 for (le_int32 f = 0; f < featureMapCount; f += 1) {
duke@0 269 FeatureMap fm = featureMap[f];
duke@0 270 count = 0;
duke@0 271
duke@0 272 // If this is the required feature, add its lookups
duke@0 273 if (requiredFeatureTag == fm.tag) {
prr@6936 274 count += selectLookups(requiredFeatureTable, fm.mask, order, success);
duke@0 275 }
duke@0 276
duke@0 277 if (orderFeatures) {
duke@0 278 // If we added lookups from the required feature, sort them
duke@0 279 if (count > 1) {
duke@0 280 OpenTypeUtilities::sort(lookupOrderArray, order);
duke@0 281 }
duke@0 282
duke@0 283 for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
prr@6936 284 LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
prr@6936 285 le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
duke@0 286
duke@0 287 // don't add the required feature to the list more than once...
duke@0 288 // TODO: Do we need this check? (Spec. says required feature won't be in feature list...)
duke@0 289 if (featureIndex == requiredFeatureIndex) {
duke@0 290 continue;
duke@0 291 }
duke@0 292
prr@6936 293 featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
duke@0 294
duke@0 295 if (featureTag == fm.tag) {
prr@6936 296 count += selectLookups(featureTable, fm.mask, order + count, success);
duke@0 297 }
duke@0 298 }
duke@0 299
duke@0 300 if (count > 1) {
duke@0 301 OpenTypeUtilities::sort(&lookupOrderArray[order], count);
duke@0 302 }
duke@0 303
duke@0 304 order += count;
prr@6936 305 } else if(langSysTable.isValid()) {
prr@6936 306 LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
prr@6936 307 for (le_uint16 feature = 0; LE_SUCCESS(success)&& (feature < featureCount); feature += 1) {
prr@6936 308 le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
duke@0 309
duke@0 310 // don't add the required feature to the list more than once...
duke@0 311 // NOTE: This check is commented out because the spec. says that
duke@0 312 // the required feature won't be in the feature list, and because
duke@0 313 // any duplicate entries will be removed below.
duke@0 314 #if 0
duke@0 315 if (featureIndex == requiredFeatureIndex) {
duke@0 316 continue;
duke@0 317 }
duke@0 318 #endif
duke@0 319
prr@6936 320 featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
duke@0 321
duke@0 322 if (featureTag == fm.tag) {
prr@6936 323 order += selectLookups(featureTable, fm.mask, order, success);
duke@0 324 }
duke@0 325 }
duke@0 326 }
duke@0 327 }
duke@0 328
duke@0 329 if (!orderFeatures && (order > 1)) {
duke@0 330 OpenTypeUtilities::sort(lookupOrderArray, order);
duke@0 331
duke@0 332 // If there's no specified feature order,
duke@0 333 // we will apply the lookups in the order
duke@0 334 // that they're in the font. If a particular
duke@0 335 // lookup may be referenced by more than one feature,
duke@0 336 // it will apprear in the lookupOrderArray more than
duke@0 337 // once, so remove any duplicate entries in the sorted array.
duke@0 338 le_int32 out = 1;
duke@0 339
duke@0 340 for (le_int32 in = 1; in < order; in += 1) {
duke@0 341 if (lookupOrderArray[out - 1] != lookupOrderArray[in]) {
duke@0 342 if (out != in) {
duke@0 343 lookupOrderArray[out] = lookupOrderArray[in];
duke@0 344 }
duke@0 345
duke@0 346 out += 1;
duke@0 347 }
duke@0 348 }
duke@0 349
duke@0 350 order = out;
duke@0 351 }
duke@0 352
duke@0 353 lookupOrderCount = order;
duke@0 354 }
duke@0 355
duke@0 356 LookupProcessor::LookupProcessor()
duke@0 357 {
srl@3171 358 lookupOrderArray = NULL;
srl@3171 359 lookupSelectArray = NULL;
duke@0 360 }
duke@0 361
duke@0 362 LookupProcessor::~LookupProcessor()
duke@0 363 {
duke@0 364 LE_DELETE_ARRAY(lookupOrderArray);
duke@0 365 LE_DELETE_ARRAY(lookupSelectArray);
duke@0 366 }
srl@1693 367
srl@1693 368 U_NAMESPACE_END