1 // Copyright (C) 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 * 5 * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved 6 * 7 */ 8 9 #include "layout/LETypes.h" 10 #include "layout/loengine.h" 11 #include "layout/plruns.h" 12 13 #include "unicode/locid.h" 14 15 #include "layout/LayoutEngine.h" 16 #include "layout/RunArrays.h" 17 18 U_NAMESPACE_USE 19 20 U_CAPI pl_fontRuns * U_EXPORT2 21 pl_openFontRuns(const le_font **fonts, 22 const le_int32 *limits, 23 le_int32 count) 24 { 25 return (pl_fontRuns *) new FontRuns((const LEFontInstance **) fonts, limits, count); 26 } 27 28 U_CAPI pl_fontRuns * U_EXPORT2 29 pl_openEmptyFontRuns(le_int32 initialCapacity) 30 { 31 return (pl_fontRuns *) new FontRuns(initialCapacity); 32 } 33 34 U_CAPI void U_EXPORT2 35 pl_closeFontRuns(pl_fontRuns *fontRuns) 36 { 37 FontRuns *fr = (FontRuns *) fontRuns; 38 39 delete fr; 40 } 41 42 U_CAPI le_int32 U_EXPORT2 43 pl_getFontRunCount(const pl_fontRuns *fontRuns) 44 { 45 const FontRuns *fr = (const FontRuns *) fontRuns; 46 47 if (fr == NULL) { 48 return -1; 49 } 50 51 return fr->getCount(); 52 } 53 54 U_CAPI void U_EXPORT2 55 pl_resetFontRuns(pl_fontRuns *fontRuns) 56 { 57 FontRuns *fr = (FontRuns *) fontRuns; 58 59 if (fr != NULL) { 60 fr->reset(); 61 } 62 } 63 64 U_CAPI le_int32 U_EXPORT2 65 pl_getFontRunLastLimit(const pl_fontRuns *fontRuns) 66 { 67 const FontRuns *fr = (const FontRuns *) fontRuns; 68 69 if (fr == NULL) { 70 return -1; 71 } 72 73 return fr->getLimit(); 74 } 75 76 U_CAPI le_int32 U_EXPORT2 77 pl_getFontRunLimit(const pl_fontRuns *fontRuns, 78 le_int32 run) 79 { 80 const FontRuns *fr = (const FontRuns *) fontRuns; 81 82 if (fr == NULL) { 83 return -1; 84 } 85 86 return fr->getLimit(run); 87 } 88 89 U_CAPI const le_font * U_EXPORT2 90 pl_getFontRunFont(const pl_fontRuns *fontRuns, 91 le_int32 run) 92 { 93 const FontRuns *fr = (const FontRuns *) fontRuns; 94 95 if (fr == NULL) { 96 return NULL; 97 } 98 99 return (const le_font *) fr->getFont(run); 100 } 101 102 U_CAPI le_int32 U_EXPORT2 103 pl_addFontRun(pl_fontRuns *fontRuns, 104 const le_font *font, 105 le_int32 limit) 106 { 107 FontRuns *fr = (FontRuns *) fontRuns; 108 109 if (fr == NULL) { 110 return -1; 111 } 112 113 return fr->add((const LEFontInstance *) font, limit); 114 } 115 116 U_CAPI pl_valueRuns * U_EXPORT2 117 pl_openValueRuns(const le_int32 *values, 118 const le_int32 *limits, 119 le_int32 count) 120 { 121 return (pl_valueRuns *) new ValueRuns(values, limits, count); 122 } 123 124 U_CAPI pl_valueRuns * U_EXPORT2 125 pl_openEmptyValueRuns(le_int32 initialCapacity) 126 { 127 return (pl_valueRuns *) new ValueRuns(initialCapacity); 128 } 129 130 U_CAPI void U_EXPORT2 131 pl_closeValueRuns(pl_valueRuns *valueRuns) 132 { 133 ValueRuns *vr = (ValueRuns *) valueRuns; 134 135 delete vr; 136 } 137 138 U_CAPI le_int32 U_EXPORT2 139 pl_getValueRunCount(const pl_valueRuns *valueRuns) 140 { 141 const ValueRuns *vr = (const ValueRuns *) valueRuns; 142 143 if (vr == NULL) { 144 return -1; 145 } 146 147 return vr->getCount(); 148 } 149 150 U_CAPI void U_EXPORT2 151 pl_resetValueRuns(pl_valueRuns *valueRuns) 152 { 153 ValueRuns *vr = (ValueRuns *) valueRuns; 154 155 if (vr != NULL) { 156 vr->reset(); 157 } 158 } 159 160 U_CAPI le_int32 U_EXPORT2 161 pl_getValueRunLastLimit(const pl_valueRuns *valueRuns) 162 { 163 const ValueRuns *vr = (const ValueRuns *) valueRuns; 164 165 if (vr == NULL) { 166 return -1; 167 } 168 169 return vr->getLimit(); 170 } 171 172 U_CAPI le_int32 U_EXPORT2 173 pl_getValueRunLimit(const pl_valueRuns *valueRuns, 174 le_int32 run) 175 { 176 const ValueRuns *vr = (const ValueRuns *) valueRuns; 177 178 if (vr == NULL) { 179 return -1; 180 } 181 182 return vr->getLimit(run); 183 } 184 185 U_CAPI le_int32 U_EXPORT2 186 pl_getValueRunValue(const pl_valueRuns *valueRuns, 187 le_int32 run) 188 { 189 const ValueRuns *vr = (const ValueRuns *) valueRuns; 190 191 if (vr == NULL) { 192 return -1; 193 } 194 195 return vr->getValue(run); 196 } 197 198 U_CAPI le_int32 U_EXPORT2 199 pl_addValueRun(pl_valueRuns *valueRuns, 200 le_int32 value, 201 le_int32 limit) 202 { 203 ValueRuns *vr = (ValueRuns *) valueRuns; 204 205 if (vr == NULL) { 206 return -1; 207 } 208 209 return vr->add(value, limit); 210 } 211 212 U_NAMESPACE_BEGIN 213 class ULocRuns : public LocaleRuns 214 { 215 public: 216 /** 217 * Construct a <code>LocaleRuns</code> object from pre-existing arrays of locales 218 * and limit indices. 219 * 220 * @param locales is the address of an array of locale name strings. This array, 221 * and the <code>Locale</code> objects to which it points, must remain valid until 222 * the <code>LocaleRuns</code> object is destroyed. 223 * 224 * @param limits is the address of an array of limit indices. This array must remain valid until the 225 * <code>LocaleRuns</code> object is destroyed. 226 * 227 * @param count is the number of entries in the two arrays. 228 * 229 * @draft ICU 3.8 230 */ 231 ULocRuns(const char **locales, const le_int32 *limits, le_int32 count); 232 233 /** 234 * Construct an empty <code>LoIDRuns</code> object. Clients can add locale and limit 235 * indices arrays using the <code>add</code> method. 236 * 237 * @param initialCapacity is the initial size of the locale and limit indices arrays. If 238 * this value is zero, no arrays will be allocated. 239 * 240 * @see add 241 * 242 * @draft ICU 3.8 243 */ 244 ULocRuns(le_int32 initialCapacity); 245 246 /** 247 * The destructor; virtual so that subclass destructors are invoked as well. 248 * 249 * @draft ICU 3.8 250 */ 251 virtual ~ULocRuns(); 252 253 /** 254 * Get the name of the locale assoicated with the given run 255 * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding 256 * limit index. 257 * 258 * @param run is the index into the font and limit indices arrays. 259 * 260 * @return the locale name associated with the given text run. 261 * 262 * @see RunArray::getLimit 263 * 264 * @draft ICU 3.8 265 */ 266 const char *getLocaleName(le_int32 run) const; 267 268 /** 269 * Add a <code>Locale</code> and limit index pair to the data arrays and return 270 * the run index where the data was stored. This method calls 271 * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed. 272 * 273 * If the <code>ULocRuns</code> object was created with a client-supplied 274 * locale and limit indices arrays, this method will return a run index of -1. 275 * 276 * Subclasses should not override this method. Rather they should provide a new <code>add</code> 277 * method which takes a locale name and a limit index along with whatever other data they implement. 278 * The new <code>add</code> method should first call this method to grow the font and limit indices 279 * arrays, and use the returned run index to store data their own arrays. 280 * 281 * @param locale is the name of the locale to add. This object must remain valid 282 * until the <code>ULocRuns</code> object is destroyed. 283 * 284 * @param limit is the limit index to add 285 * 286 * @return the run index where the locale and limit index were stored, or -1 if the data cannot be stored. 287 * 288 * @draft ICU 3.8 289 */ 290 le_int32 add(const char *locale, le_int32 limit); 291 292 /** 293 * ICU "poor man's RTTI", returns a UClassID for this class. 294 * 295 * @draft ICU 3.8 296 */ 297 static inline UClassID getStaticClassID(); 298 299 /** 300 * ICU "poor man's RTTI", returns a UClassID for the actual class. 301 * 302 * @draft ICU 3.8 303 */ 304 virtual inline UClassID getDynamicClassID() const; 305 306 protected: 307 virtual void init(le_int32 capacity); 308 virtual void grow(le_int32 capacity); 309 310 private: 311 312 inline ULocRuns(); 313 inline ULocRuns(const ULocRuns &other); 314 inline ULocRuns &operator=(const ULocRuns & /*other*/) { return *this; }; 315 const char **fLocaleNames; 316 }; 317 318 inline ULocRuns::ULocRuns() 319 : LocaleRuns(0), fLocaleNames(NULL) 320 { 321 // nothing else to do... 322 } 323 324 inline ULocRuns::ULocRuns(const ULocRuns & /*other*/) 325 : LocaleRuns(0), fLocaleNames(NULL) 326 { 327 // nothing else to do... 328 } 329 330 static const Locale **getLocales(const char **localeNames, le_int32 count) 331 { 332 Locale **locales = LE_NEW_ARRAY(Locale *, count); 333 334 for (int i = 0; i < count; i += 1) { 335 locales[i] = new Locale(Locale::createFromName(localeNames[i])); 336 } 337 338 return (const Locale **) locales; 339 } 340 341 ULocRuns::ULocRuns(const char **locales, const le_int32 *limits, le_int32 count) 342 : LocaleRuns(getLocales(locales, count), limits, count), fLocaleNames(locales) 343 { 344 // nothing else to do... 345 } 346 347 ULocRuns::ULocRuns(le_int32 initialCapacity) 348 : LocaleRuns(initialCapacity), fLocaleNames(NULL) 349 { 350 if(initialCapacity > 0) { 351 fLocaleNames = LE_NEW_ARRAY(const char *, initialCapacity); 352 } 353 } 354 355 ULocRuns::~ULocRuns() 356 { 357 le_int32 count = getCount(); 358 359 for(int i = 0; i < count; i += 1) { 360 delete fLocales[i]; 361 } 362 363 if (fClientArrays) { 364 LE_DELETE_ARRAY(fLocales); 365 fLocales = NULL; 366 } else { 367 LE_DELETE_ARRAY(fLocaleNames); 368 fLocaleNames = NULL; 369 } 370 } 371 372 void ULocRuns::init(le_int32 capacity) 373 { 374 LocaleRuns::init(capacity); 375 fLocaleNames = LE_NEW_ARRAY(const char *, capacity); 376 } 377 378 void ULocRuns::grow(le_int32 capacity) 379 { 380 LocaleRuns::grow(capacity); 381 fLocaleNames = (const char **) LE_GROW_ARRAY(fLocaleNames, capacity); 382 } 383 384 le_int32 ULocRuns::add(const char *locale, le_int32 limit) 385 { 386 Locale *loc = new Locale(Locale::createFromName(locale)); 387 le_int32 index = LocaleRuns::add(loc, limit); 388 389 if (index >= 0) { 390 char **localeNames = (char **) fLocaleNames; 391 392 localeNames[index] = (char *) locale; 393 } 394 395 return index; 396 } 397 398 const char *ULocRuns::getLocaleName(le_int32 run) const 399 { 400 if (run < 0 || run >= getCount()) { 401 return NULL; 402 } 403 404 return fLocaleNames[run]; 405 } 406 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ULocRuns) 407 U_NAMESPACE_END 408 409 U_CAPI pl_localeRuns * U_EXPORT2 410 pl_openLocaleRuns(const char **locales, 411 const le_int32 *limits, 412 le_int32 count) 413 { 414 return (pl_localeRuns *) new ULocRuns(locales, limits, count); 415 } 416 417 U_CAPI pl_localeRuns * U_EXPORT2 418 pl_openEmptyLocaleRuns(le_int32 initialCapacity) 419 { 420 return (pl_localeRuns *) new ULocRuns(initialCapacity); 421 } 422 423 U_CAPI void U_EXPORT2 424 pl_closeLocaleRuns(pl_localeRuns *localeRuns) 425 { 426 ULocRuns *lr = (ULocRuns *) localeRuns; 427 428 delete lr; 429 } 430 431 U_CAPI le_int32 U_EXPORT2 432 pl_getLocaleRunCount(const pl_localeRuns *localeRuns) 433 { 434 const ULocRuns *lr = (const ULocRuns *) localeRuns; 435 436 if (lr == NULL) { 437 return -1; 438 } 439 440 return lr->getCount(); 441 } 442 443 U_CAPI void U_EXPORT2 444 pl_resetLocaleRuns(pl_localeRuns *localeRuns) 445 { 446 ULocRuns *lr = (ULocRuns *) localeRuns; 447 448 if (lr != NULL) { 449 lr->reset(); 450 } 451 } 452 453 U_CAPI le_int32 U_EXPORT2 454 pl_getLocaleRunLastLimit(const pl_localeRuns *localeRuns) 455 { 456 const ULocRuns *lr = (const ULocRuns *) localeRuns; 457 458 if (lr == NULL) { 459 return -1; 460 } 461 462 return lr->getLimit(); 463 } 464 465 U_CAPI le_int32 U_EXPORT2 466 pl_getLocaleRunLimit(const pl_localeRuns *localeRuns, 467 le_int32 run) 468 { 469 const ULocRuns *lr = (const ULocRuns *) localeRuns; 470 471 if (lr == NULL) { 472 return -1; 473 } 474 475 return lr->getLimit(run); 476 } 477 478 U_CAPI const char * U_EXPORT2 479 pl_getLocaleRunLocale(const pl_localeRuns *localeRuns, 480 le_int32 run) 481 { 482 const ULocRuns *lr = (const ULocRuns *) localeRuns; 483 484 if (lr == NULL) { 485 return NULL; 486 } 487 488 return lr->getLocaleName(run); 489 } 490 491 U_CAPI le_int32 U_EXPORT2 492 pl_addLocaleRun(pl_localeRuns *localeRuns, 493 const char *locale, 494 le_int32 limit) 495 { 496 ULocRuns *lr = (ULocRuns *) localeRuns; 497 498 if (lr == NULL) { 499 return -1; 500 } 501 502 return lr->add(locale, limit); 503 } 504