1 /*
2  *
3  * (C) Copyright IBM Corp. 1998-2013 - 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 
16 U_NAMESPACE_USE
17 
18 U_CAPI pl_fontRuns * U_EXPORT2
pl_openFontRuns(const le_font ** fonts,const le_int32 * limits,le_int32 count)19 pl_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 
26 U_CAPI pl_fontRuns * U_EXPORT2
pl_openEmptyFontRuns(le_int32 initialCapacity)27 pl_openEmptyFontRuns(le_int32 initialCapacity)
28 {
29     return (pl_fontRuns *) new FontRuns(initialCapacity);
30 }
31 
32 U_CAPI void U_EXPORT2
pl_closeFontRuns(pl_fontRuns * fontRuns)33 pl_closeFontRuns(pl_fontRuns *fontRuns)
34 {
35     FontRuns *fr = (FontRuns *) fontRuns;
36 
37     delete fr;
38 }
39 
40 U_CAPI le_int32 U_EXPORT2
pl_getFontRunCount(const pl_fontRuns * fontRuns)41 pl_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 
52 U_CAPI void U_EXPORT2
pl_resetFontRuns(pl_fontRuns * fontRuns)53 pl_resetFontRuns(pl_fontRuns *fontRuns)
54 {
55     FontRuns *fr = (FontRuns *) fontRuns;
56 
57     if (fr != NULL) {
58         fr->reset();
59     }
60 }
61 
62 U_CAPI le_int32 U_EXPORT2
pl_getFontRunLastLimit(const pl_fontRuns * fontRuns)63 pl_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 
74 U_CAPI le_int32 U_EXPORT2
pl_getFontRunLimit(const pl_fontRuns * fontRuns,le_int32 run)75 pl_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 
87 U_CAPI const le_font * U_EXPORT2
pl_getFontRunFont(const pl_fontRuns * fontRuns,le_int32 run)88 pl_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 
100 U_CAPI le_int32 U_EXPORT2
pl_addFontRun(pl_fontRuns * fontRuns,const le_font * font,le_int32 limit)101 pl_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 
114 U_CAPI pl_valueRuns * U_EXPORT2
pl_openValueRuns(const le_int32 * values,const le_int32 * limits,le_int32 count)115 pl_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 
122 U_CAPI pl_valueRuns * U_EXPORT2
pl_openEmptyValueRuns(le_int32 initialCapacity)123 pl_openEmptyValueRuns(le_int32 initialCapacity)
124 {
125     return (pl_valueRuns *) new ValueRuns(initialCapacity);
126 }
127 
128 U_CAPI void U_EXPORT2
pl_closeValueRuns(pl_valueRuns * valueRuns)129 pl_closeValueRuns(pl_valueRuns *valueRuns)
130 {
131     ValueRuns *vr = (ValueRuns *) valueRuns;
132 
133     delete vr;
134 }
135 
136 U_CAPI le_int32 U_EXPORT2
pl_getValueRunCount(const pl_valueRuns * valueRuns)137 pl_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 
148 U_CAPI void U_EXPORT2
pl_resetValueRuns(pl_valueRuns * valueRuns)149 pl_resetValueRuns(pl_valueRuns *valueRuns)
150 {
151     ValueRuns *vr = (ValueRuns *) valueRuns;
152 
153     if (vr != NULL) {
154         vr->reset();
155     }
156 }
157 
158 U_CAPI le_int32 U_EXPORT2
pl_getValueRunLastLimit(const pl_valueRuns * valueRuns)159 pl_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 
170 U_CAPI le_int32 U_EXPORT2
pl_getValueRunLimit(const pl_valueRuns * valueRuns,le_int32 run)171 pl_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 
183 U_CAPI le_int32 U_EXPORT2
pl_getValueRunValue(const pl_valueRuns * valueRuns,le_int32 run)184 pl_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 
196 U_CAPI le_int32 U_EXPORT2
pl_addValueRun(pl_valueRuns * valueRuns,le_int32 value,le_int32 limit)197 pl_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 
210 U_NAMESPACE_BEGIN
211 class ULocRuns : public LocaleRuns
212 {
213 public:
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 
304 protected:
305     virtual void init(le_int32 capacity);
306     virtual void grow(le_int32 capacity);
307 
308 private:
309 
310     inline ULocRuns();
311     inline ULocRuns(const ULocRuns &other);
operator =(const ULocRuns &)312     inline ULocRuns &operator=(const ULocRuns & /*other*/) { return *this; };
313     const char **fLocaleNames;
314 };
315 
ULocRuns()316 inline ULocRuns::ULocRuns()
317     : LocaleRuns(0), fLocaleNames(NULL)
318 {
319     // nothing else to do...
320 }
321 
ULocRuns(const ULocRuns &)322 inline ULocRuns::ULocRuns(const ULocRuns & /*other*/)
323     : LocaleRuns(0), fLocaleNames(NULL)
324 {
325     // nothing else to do...
326 }
327 
getLocales(const char ** localeNames,le_int32 count)328 static const Locale **getLocales(const char **localeNames, le_int32 count)
329 {
330     Locale **locales = LE_NEW_ARRAY(Locale *, count);
331 
332     for (int i = 0; i < count; i += 1) {
333         locales[i] = new Locale(Locale::createFromName(localeNames[i]));
334     }
335 
336     return (const Locale **) locales;
337 }
338 
ULocRuns(const char ** locales,const le_int32 * limits,le_int32 count)339 ULocRuns::ULocRuns(const char **locales, const le_int32 *limits, le_int32 count)
340     : LocaleRuns(getLocales(locales, count), limits, count), fLocaleNames(locales)
341 {
342     // nothing else to do...
343 }
344 
ULocRuns(le_int32 initialCapacity)345 ULocRuns::ULocRuns(le_int32 initialCapacity)
346     : LocaleRuns(initialCapacity), fLocaleNames(NULL)
347 {
348     if(initialCapacity > 0) {
349         fLocaleNames = LE_NEW_ARRAY(const char *, initialCapacity);
350     }
351 }
352 
~ULocRuns()353 ULocRuns::~ULocRuns()
354 {
355     le_int32 count = getCount();
356 
357     for(int i = 0; i < count; i += 1) {
358         delete fLocales[i];
359     }
360 
361     if (fClientArrays) {
362         LE_DELETE_ARRAY(fLocales);
363         fLocales = NULL;
364     } else {
365         LE_DELETE_ARRAY(fLocaleNames);
366         fLocaleNames = NULL;
367     }
368 }
369 
init(le_int32 capacity)370 void ULocRuns::init(le_int32 capacity)
371 {
372     LocaleRuns::init(capacity);
373     fLocaleNames = LE_NEW_ARRAY(const char *, capacity);
374 }
375 
grow(le_int32 capacity)376 void ULocRuns::grow(le_int32 capacity)
377 {
378     LocaleRuns::grow(capacity);
379     fLocaleNames = (const char **) LE_GROW_ARRAY(fLocaleNames, capacity);
380 }
381 
add(const char * locale,le_int32 limit)382 le_int32 ULocRuns::add(const char *locale, le_int32 limit)
383 {
384     Locale *loc = new Locale(Locale::createFromName(locale));
385     le_int32 index = LocaleRuns::add(loc, limit);
386 
387     if (index >= 0) {
388         char **localeNames = (char **) fLocaleNames;
389 
390         localeNames[index] = (char *) locale;
391     }
392 
393     return index;
394 }
395 
getLocaleName(le_int32 run) const396 const char *ULocRuns::getLocaleName(le_int32 run) const
397 {
398     if (run < 0 || run >= getCount()) {
399         return NULL;
400     }
401 
402     return fLocaleNames[run];
403 }
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ULocRuns)404 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ULocRuns)
405 U_NAMESPACE_END
406 
407 U_CAPI pl_localeRuns * U_EXPORT2
408 pl_openLocaleRuns(const char **locales,
409                   const le_int32 *limits,
410                   le_int32 count)
411 {
412     return (pl_localeRuns *) new ULocRuns(locales, limits, count);
413 }
414 
415 U_CAPI pl_localeRuns * U_EXPORT2
pl_openEmptyLocaleRuns(le_int32 initialCapacity)416 pl_openEmptyLocaleRuns(le_int32 initialCapacity)
417 {
418     return (pl_localeRuns *) new ULocRuns(initialCapacity);
419 }
420 
421 U_CAPI void U_EXPORT2
pl_closeLocaleRuns(pl_localeRuns * localeRuns)422 pl_closeLocaleRuns(pl_localeRuns *localeRuns)
423 {
424     ULocRuns *lr = (ULocRuns *) localeRuns;
425 
426     delete lr;
427 }
428 
429 U_CAPI le_int32 U_EXPORT2
pl_getLocaleRunCount(const pl_localeRuns * localeRuns)430 pl_getLocaleRunCount(const pl_localeRuns *localeRuns)
431 {
432     const ULocRuns *lr = (const ULocRuns *) localeRuns;
433 
434     if (lr == NULL) {
435         return -1;
436     }
437 
438     return lr->getCount();
439 }
440 
441 U_CAPI void U_EXPORT2
pl_resetLocaleRuns(pl_localeRuns * localeRuns)442 pl_resetLocaleRuns(pl_localeRuns *localeRuns)
443 {
444     ULocRuns *lr = (ULocRuns *) localeRuns;
445 
446     if (lr != NULL) {
447         lr->reset();
448     }
449 }
450 
451 U_CAPI le_int32 U_EXPORT2
pl_getLocaleRunLastLimit(const pl_localeRuns * localeRuns)452 pl_getLocaleRunLastLimit(const pl_localeRuns *localeRuns)
453 {
454     const ULocRuns *lr = (const ULocRuns *) localeRuns;
455 
456     if (lr == NULL) {
457         return -1;
458     }
459 
460     return lr->getLimit();
461 }
462 
463 U_CAPI le_int32 U_EXPORT2
pl_getLocaleRunLimit(const pl_localeRuns * localeRuns,le_int32 run)464 pl_getLocaleRunLimit(const pl_localeRuns *localeRuns,
465                      le_int32 run)
466 {
467     const ULocRuns *lr = (const ULocRuns *) localeRuns;
468 
469     if (lr == NULL) {
470         return -1;
471     }
472 
473     return lr->getLimit(run);
474 }
475 
476 U_CAPI const char * U_EXPORT2
pl_getLocaleRunLocale(const pl_localeRuns * localeRuns,le_int32 run)477 pl_getLocaleRunLocale(const pl_localeRuns *localeRuns,
478                       le_int32 run)
479 {
480     const ULocRuns *lr = (const ULocRuns *) localeRuns;
481 
482     if (lr == NULL) {
483         return NULL;
484     }
485 
486     return lr->getLocaleName(run);
487 }
488 
489 U_CAPI le_int32 U_EXPORT2
pl_addLocaleRun(pl_localeRuns * localeRuns,const char * locale,le_int32 limit)490 pl_addLocaleRun(pl_localeRuns *localeRuns,
491                 const char *locale,
492                 le_int32 limit)
493 {
494     ULocRuns *lr = (ULocRuns *) localeRuns;
495 
496     if (lr == NULL) {
497         return -1;
498     }
499 
500     return lr->add(locale, limit);
501 }
502