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
18U_NAMESPACE_USE
19
20U_CAPI pl_fontRuns * U_EXPORT2
21pl_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
28U_CAPI pl_fontRuns * U_EXPORT2
29pl_openEmptyFontRuns(le_int32 initialCapacity)
30{
31    return (pl_fontRuns *) new FontRuns(initialCapacity);
32}
33
34U_CAPI void U_EXPORT2
35pl_closeFontRuns(pl_fontRuns *fontRuns)
36{
37    FontRuns *fr = (FontRuns *) fontRuns;
38
39    delete fr;
40}
41
42U_CAPI le_int32 U_EXPORT2
43pl_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
54U_CAPI void U_EXPORT2
55pl_resetFontRuns(pl_fontRuns *fontRuns)
56{
57    FontRuns *fr = (FontRuns *) fontRuns;
58
59    if (fr != NULL) {
60        fr->reset();
61    }
62}
63
64U_CAPI le_int32 U_EXPORT2
65pl_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
76U_CAPI le_int32 U_EXPORT2
77pl_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
89U_CAPI const le_font * U_EXPORT2
90pl_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
102U_CAPI le_int32 U_EXPORT2
103pl_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
116U_CAPI pl_valueRuns * U_EXPORT2
117pl_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
124U_CAPI pl_valueRuns * U_EXPORT2
125pl_openEmptyValueRuns(le_int32 initialCapacity)
126{
127    return (pl_valueRuns *) new ValueRuns(initialCapacity);
128}
129
130U_CAPI void U_EXPORT2
131pl_closeValueRuns(pl_valueRuns *valueRuns)
132{
133    ValueRuns *vr = (ValueRuns *) valueRuns;
134
135    delete vr;
136}
137
138U_CAPI le_int32 U_EXPORT2
139pl_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
150U_CAPI void U_EXPORT2
151pl_resetValueRuns(pl_valueRuns *valueRuns)
152{
153    ValueRuns *vr = (ValueRuns *) valueRuns;
154
155    if (vr != NULL) {
156        vr->reset();
157    }
158}
159
160U_CAPI le_int32 U_EXPORT2
161pl_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
172U_CAPI le_int32 U_EXPORT2
173pl_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
185U_CAPI le_int32 U_EXPORT2
186pl_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
198U_CAPI le_int32 U_EXPORT2
199pl_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
212U_NAMESPACE_BEGIN
213class ULocRuns : public LocaleRuns
214{
215public:
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
306protected:
307    virtual void init(le_int32 capacity);
308    virtual void grow(le_int32 capacity);
309
310private:
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
318inline ULocRuns::ULocRuns()
319    : LocaleRuns(0), fLocaleNames(NULL)
320{
321    // nothing else to do...
322}
323
324inline ULocRuns::ULocRuns(const ULocRuns & /*other*/)
325    : LocaleRuns(0), fLocaleNames(NULL)
326{
327    // nothing else to do...
328}
329
330static 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
341ULocRuns::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
347ULocRuns::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
355ULocRuns::~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
372void ULocRuns::init(le_int32 capacity)
373{
374    LocaleRuns::init(capacity);
375    fLocaleNames = LE_NEW_ARRAY(const char *, capacity);
376}
377
378void ULocRuns::grow(le_int32 capacity)
379{
380    LocaleRuns::grow(capacity);
381    fLocaleNames = (const char **) LE_GROW_ARRAY(fLocaleNames, capacity);
382}
383
384le_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
398const char *ULocRuns::getLocaleName(le_int32 run) const
399{
400    if (run < 0 || run >= getCount()) {
401        return NULL;
402    }
403
404    return fLocaleNames[run];
405}
406UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ULocRuns)
407U_NAMESPACE_END
408
409U_CAPI pl_localeRuns * U_EXPORT2
410pl_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
417U_CAPI pl_localeRuns * U_EXPORT2
418pl_openEmptyLocaleRuns(le_int32 initialCapacity)
419{
420    return (pl_localeRuns *) new ULocRuns(initialCapacity);
421}
422
423U_CAPI void U_EXPORT2
424pl_closeLocaleRuns(pl_localeRuns *localeRuns)
425{
426    ULocRuns *lr = (ULocRuns *) localeRuns;
427
428    delete lr;
429}
430
431U_CAPI le_int32 U_EXPORT2
432pl_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
443U_CAPI void U_EXPORT2
444pl_resetLocaleRuns(pl_localeRuns *localeRuns)
445{
446    ULocRuns *lr = (ULocRuns *) localeRuns;
447
448    if (lr != NULL) {
449        lr->reset();
450    }
451}
452
453U_CAPI le_int32 U_EXPORT2
454pl_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
465U_CAPI le_int32 U_EXPORT2
466pl_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
478U_CAPI const char * U_EXPORT2
479pl_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
491U_CAPI le_int32 U_EXPORT2
492pl_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