| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /* |
| * |
| * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved |
| * |
| */ |
| |
| #include "layout/LETypes.h" |
| #include "layout/loengine.h" |
| #include "layout/plruns.h" |
| |
| #include "unicode/locid.h" |
| |
| #include "layout/LayoutEngine.h" |
| #include "layout/RunArrays.h" |
| |
| U_NAMESPACE_USE |
| |
| U_CAPI pl_fontRuns * U_EXPORT2 |
| pl_openFontRuns(const le_font **fonts, |
| const le_int32 *limits, |
| le_int32 count) |
| { |
| return (pl_fontRuns *) new FontRuns((const LEFontInstance **) fonts, limits, count); |
| } |
| |
| U_CAPI pl_fontRuns * U_EXPORT2 |
| pl_openEmptyFontRuns(le_int32 initialCapacity) |
| { |
| return (pl_fontRuns *) new FontRuns(initialCapacity); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| pl_closeFontRuns(pl_fontRuns *fontRuns) |
| { |
| FontRuns *fr = (FontRuns *) fontRuns; |
| |
| delete fr; |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getFontRunCount(const pl_fontRuns *fontRuns) |
| { |
| const FontRuns *fr = (const FontRuns *) fontRuns; |
| |
| if (fr == NULL) { |
| return -1; |
| } |
| |
| return fr->getCount(); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| pl_resetFontRuns(pl_fontRuns *fontRuns) |
| { |
| FontRuns *fr = (FontRuns *) fontRuns; |
| |
| if (fr != NULL) { |
| fr->reset(); |
| } |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getFontRunLastLimit(const pl_fontRuns *fontRuns) |
| { |
| const FontRuns *fr = (const FontRuns *) fontRuns; |
| |
| if (fr == NULL) { |
| return -1; |
| } |
| |
| return fr->getLimit(); |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getFontRunLimit(const pl_fontRuns *fontRuns, |
| le_int32 run) |
| { |
| const FontRuns *fr = (const FontRuns *) fontRuns; |
| |
| if (fr == NULL) { |
| return -1; |
| } |
| |
| return fr->getLimit(run); |
| } |
| |
| U_CAPI const le_font * U_EXPORT2 |
| pl_getFontRunFont(const pl_fontRuns *fontRuns, |
| le_int32 run) |
| { |
| const FontRuns *fr = (const FontRuns *) fontRuns; |
| |
| if (fr == NULL) { |
| return NULL; |
| } |
| |
| return (const le_font *) fr->getFont(run); |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_addFontRun(pl_fontRuns *fontRuns, |
| const le_font *font, |
| le_int32 limit) |
| { |
| FontRuns *fr = (FontRuns *) fontRuns; |
| |
| if (fr == NULL) { |
| return -1; |
| } |
| |
| return fr->add((const LEFontInstance *) font, limit); |
| } |
| |
| U_CAPI pl_valueRuns * U_EXPORT2 |
| pl_openValueRuns(const le_int32 *values, |
| const le_int32 *limits, |
| le_int32 count) |
| { |
| return (pl_valueRuns *) new ValueRuns(values, limits, count); |
| } |
| |
| U_CAPI pl_valueRuns * U_EXPORT2 |
| pl_openEmptyValueRuns(le_int32 initialCapacity) |
| { |
| return (pl_valueRuns *) new ValueRuns(initialCapacity); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| pl_closeValueRuns(pl_valueRuns *valueRuns) |
| { |
| ValueRuns *vr = (ValueRuns *) valueRuns; |
| |
| delete vr; |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getValueRunCount(const pl_valueRuns *valueRuns) |
| { |
| const ValueRuns *vr = (const ValueRuns *) valueRuns; |
| |
| if (vr == NULL) { |
| return -1; |
| } |
| |
| return vr->getCount(); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| pl_resetValueRuns(pl_valueRuns *valueRuns) |
| { |
| ValueRuns *vr = (ValueRuns *) valueRuns; |
| |
| if (vr != NULL) { |
| vr->reset(); |
| } |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getValueRunLastLimit(const pl_valueRuns *valueRuns) |
| { |
| const ValueRuns *vr = (const ValueRuns *) valueRuns; |
| |
| if (vr == NULL) { |
| return -1; |
| } |
| |
| return vr->getLimit(); |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getValueRunLimit(const pl_valueRuns *valueRuns, |
| le_int32 run) |
| { |
| const ValueRuns *vr = (const ValueRuns *) valueRuns; |
| |
| if (vr == NULL) { |
| return -1; |
| } |
| |
| return vr->getLimit(run); |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getValueRunValue(const pl_valueRuns *valueRuns, |
| le_int32 run) |
| { |
| const ValueRuns *vr = (const ValueRuns *) valueRuns; |
| |
| if (vr == NULL) { |
| return -1; |
| } |
| |
| return vr->getValue(run); |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_addValueRun(pl_valueRuns *valueRuns, |
| le_int32 value, |
| le_int32 limit) |
| { |
| ValueRuns *vr = (ValueRuns *) valueRuns; |
| |
| if (vr == NULL) { |
| return -1; |
| } |
| |
| return vr->add(value, limit); |
| } |
| |
| U_NAMESPACE_BEGIN |
| class ULocRuns : public LocaleRuns |
| { |
| public: |
| /** |
| * Construct a <code>LocaleRuns</code> object from pre-existing arrays of locales |
| * and limit indices. |
| * |
| * @param locales is the address of an array of locale name strings. This array, |
| * and the <code>Locale</code> objects to which it points, must remain valid until |
| * the <code>LocaleRuns</code> object is destroyed. |
| * |
| * @param limits is the address of an array of limit indices. This array must remain valid until the |
| * <code>LocaleRuns</code> object is destroyed. |
| * |
| * @param count is the number of entries in the two arrays. |
| * |
| * @draft ICU 3.8 |
| */ |
| ULocRuns(const char **locales, const le_int32 *limits, le_int32 count); |
| |
| /** |
| * Construct an empty <code>LoIDRuns</code> object. Clients can add locale and limit |
| * indices arrays using the <code>add</code> method. |
| * |
| * @param initialCapacity is the initial size of the locale and limit indices arrays. If |
| * this value is zero, no arrays will be allocated. |
| * |
| * @see add |
| * |
| * @draft ICU 3.8 |
| */ |
| ULocRuns(le_int32 initialCapacity); |
| |
| /** |
| * The destructor; virtual so that subclass destructors are invoked as well. |
| * |
| * @draft ICU 3.8 |
| */ |
| virtual ~ULocRuns(); |
| |
| /** |
| * Get the name of the locale associated with the given run |
| * of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding |
| * limit index. |
| * |
| * @param run is the index into the font and limit indices arrays. |
| * |
| * @return the locale name associated with the given text run. |
| * |
| * @see RunArray::getLimit |
| * |
| * @draft ICU 3.8 |
| */ |
| const char *getLocaleName(le_int32 run) const; |
| |
| /** |
| * Add a <code>Locale</code> and limit index pair to the data arrays and return |
| * the run index where the data was stored. This method calls |
| * <code>RunArray::add(limit)</code> which will create or grow the arrays as needed. |
| * |
| * If the <code>ULocRuns</code> object was created with a client-supplied |
| * locale and limit indices arrays, this method will return a run index of -1. |
| * |
| * Subclasses should not override this method. Rather they should provide a new <code>add</code> |
| * method which takes a locale name and a limit index along with whatever other data they implement. |
| * The new <code>add</code> method should first call this method to grow the font and limit indices |
| * arrays, and use the returned run index to store data their own arrays. |
| * |
| * @param locale is the name of the locale to add. This object must remain valid |
| * until the <code>ULocRuns</code> object is destroyed. |
| * |
| * @param limit is the limit index to add |
| * |
| * @return the run index where the locale and limit index were stored, or -1 if the data cannot be stored. |
| * |
| * @draft ICU 3.8 |
| */ |
| le_int32 add(const char *locale, le_int32 limit); |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for this class. |
| * |
| * @draft ICU 3.8 |
| */ |
| static inline UClassID getStaticClassID(); |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for the actual class. |
| * |
| * @draft ICU 3.8 |
| */ |
| virtual inline UClassID getDynamicClassID() const; |
| |
| protected: |
| virtual void init(le_int32 capacity); |
| virtual void grow(le_int32 capacity); |
| |
| private: |
| |
| inline ULocRuns(); |
| inline ULocRuns(const ULocRuns &other); |
| inline ULocRuns &operator=(const ULocRuns & /*other*/) { return *this; }; |
| const char **fLocaleNames; |
| }; |
| |
| inline ULocRuns::ULocRuns() |
| : LocaleRuns(0), fLocaleNames(NULL) |
| { |
| // nothing else to do... |
| } |
| |
| inline ULocRuns::ULocRuns(const ULocRuns & /*other*/) |
| : LocaleRuns(0), fLocaleNames(NULL) |
| { |
| // nothing else to do... |
| } |
| |
| static const Locale **getLocales(const char **localeNames, le_int32 count) |
| { |
| Locale **locales = LE_NEW_ARRAY(Locale *, count); |
| |
| for (int i = 0; i < count; i += 1) { |
| locales[i] = new Locale(Locale::createFromName(localeNames[i])); |
| } |
| |
| return (const Locale **) locales; |
| } |
| |
| ULocRuns::ULocRuns(const char **locales, const le_int32 *limits, le_int32 count) |
| : LocaleRuns(getLocales(locales, count), limits, count), fLocaleNames(locales) |
| { |
| // nothing else to do... |
| } |
| |
| ULocRuns::ULocRuns(le_int32 initialCapacity) |
| : LocaleRuns(initialCapacity), fLocaleNames(NULL) |
| { |
| if(initialCapacity > 0) { |
| fLocaleNames = LE_NEW_ARRAY(const char *, initialCapacity); |
| } |
| } |
| |
| ULocRuns::~ULocRuns() |
| { |
| le_int32 count = getCount(); |
| |
| for(int i = 0; i < count; i += 1) { |
| delete fLocales[i]; |
| } |
| |
| if (fClientArrays) { |
| LE_DELETE_ARRAY(fLocales); |
| fLocales = NULL; |
| } else { |
| LE_DELETE_ARRAY(fLocaleNames); |
| fLocaleNames = NULL; |
| } |
| } |
| |
| void ULocRuns::init(le_int32 capacity) |
| { |
| LocaleRuns::init(capacity); |
| fLocaleNames = LE_NEW_ARRAY(const char *, capacity); |
| } |
| |
| void ULocRuns::grow(le_int32 capacity) |
| { |
| LocaleRuns::grow(capacity); |
| fLocaleNames = (const char **) LE_GROW_ARRAY(fLocaleNames, capacity); |
| } |
| |
| le_int32 ULocRuns::add(const char *locale, le_int32 limit) |
| { |
| Locale *loc = new Locale(Locale::createFromName(locale)); |
| le_int32 index = LocaleRuns::add(loc, limit); |
| |
| if (index >= 0) { |
| char **localeNames = (char **) fLocaleNames; |
| |
| localeNames[index] = (char *) locale; |
| } |
| |
| return index; |
| } |
| |
| const char *ULocRuns::getLocaleName(le_int32 run) const |
| { |
| if (run < 0 || run >= getCount()) { |
| return NULL; |
| } |
| |
| return fLocaleNames[run]; |
| } |
| UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ULocRuns) |
| U_NAMESPACE_END |
| |
| U_CAPI pl_localeRuns * U_EXPORT2 |
| pl_openLocaleRuns(const char **locales, |
| const le_int32 *limits, |
| le_int32 count) |
| { |
| return (pl_localeRuns *) new ULocRuns(locales, limits, count); |
| } |
| |
| U_CAPI pl_localeRuns * U_EXPORT2 |
| pl_openEmptyLocaleRuns(le_int32 initialCapacity) |
| { |
| return (pl_localeRuns *) new ULocRuns(initialCapacity); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| pl_closeLocaleRuns(pl_localeRuns *localeRuns) |
| { |
| ULocRuns *lr = (ULocRuns *) localeRuns; |
| |
| delete lr; |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getLocaleRunCount(const pl_localeRuns *localeRuns) |
| { |
| const ULocRuns *lr = (const ULocRuns *) localeRuns; |
| |
| if (lr == NULL) { |
| return -1; |
| } |
| |
| return lr->getCount(); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| pl_resetLocaleRuns(pl_localeRuns *localeRuns) |
| { |
| ULocRuns *lr = (ULocRuns *) localeRuns; |
| |
| if (lr != NULL) { |
| lr->reset(); |
| } |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getLocaleRunLastLimit(const pl_localeRuns *localeRuns) |
| { |
| const ULocRuns *lr = (const ULocRuns *) localeRuns; |
| |
| if (lr == NULL) { |
| return -1; |
| } |
| |
| return lr->getLimit(); |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_getLocaleRunLimit(const pl_localeRuns *localeRuns, |
| le_int32 run) |
| { |
| const ULocRuns *lr = (const ULocRuns *) localeRuns; |
| |
| if (lr == NULL) { |
| return -1; |
| } |
| |
| return lr->getLimit(run); |
| } |
| |
| U_CAPI const char * U_EXPORT2 |
| pl_getLocaleRunLocale(const pl_localeRuns *localeRuns, |
| le_int32 run) |
| { |
| const ULocRuns *lr = (const ULocRuns *) localeRuns; |
| |
| if (lr == NULL) { |
| return NULL; |
| } |
| |
| return lr->getLocaleName(run); |
| } |
| |
| U_CAPI le_int32 U_EXPORT2 |
| pl_addLocaleRun(pl_localeRuns *localeRuns, |
| const char *locale, |
| le_int32 limit) |
| { |
| ULocRuns *lr = (ULocRuns *) localeRuns; |
| |
| if (lr == NULL) { |
| return -1; |
| } |
| |
| return lr->add(locale, limit); |
| } |