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