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