|  | /* | 
|  | * | 
|  | * (C) Copyright IBM Corp. 1998-2008 - 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 assoicated 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; | 
|  | Locale **fLocalesCopy; | 
|  | }; | 
|  |  | 
|  | 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); | 
|  | } |