1/*
2 * Copyright © 2007,2008,2009 Red Hat, Inc.
3 * Copyright © 2010,2012 Google, Inc.
4 *
5 * This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod, Garret Rieger
27 */
28
29#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
30#define OT_LAYOUT_COMMON_RANGERECORD_HH
31
32namespace OT {
33namespace Layout {
34namespace Common {
35
36template <typename Types>
37struct RangeRecord
38{
39 typename Types::HBGlyphID first; /* First GlyphID in the range */
40 typename Types::HBGlyphID last; /* Last GlyphID in the range */
41 HBUINT16 value; /* Value */
42
43 DEFINE_SIZE_STATIC (2 + 2 * Types::size);
44
45 bool sanitize (hb_sanitize_context_t *c) const
46 {
47 TRACE_SANITIZE (this);
48 return_trace (c->check_struct (this));
49 }
50
51 int cmp (hb_codepoint_t g) const
52 { return g < first ? -1 : g <= last ? 0 : +1; }
53
54 HB_INTERNAL static int cmp_range (const void *pa, const void *pb) {
55 const RangeRecord *a = (const RangeRecord *) pa;
56 const RangeRecord *b = (const RangeRecord *) pb;
57 if (a->first < b->first) return -1;
58 if (a->first > b->first) return +1;
59 if (a->last < b->last) return -1;
60 if (a->last > b->last) return +1;
61 if (a->value < b->value) return -1;
62 if (a->value > b->value) return +1;
63 return 0;
64 }
65
66 unsigned get_population () const
67 {
68 if (unlikely (last < first)) return 0;
69 return (last - first + 1);
70 }
71
72 bool intersects (const hb_set_t &glyphs) const
73 { return glyphs.intersects (first, last); }
74
75 template <typename set_t>
76 bool collect_coverage (set_t *glyphs) const
77 { return glyphs->add_range (first, last); }
78};
79
80}
81}
82}
83
84// TODO(garretrieger): This was previously implemented using
85// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
86// but that only works when there is only a single namespace level.
87// The macro should probably be fixed so it can work in this situation.
88extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
89template <typename Spec>
90struct Null<OT::Layout::Common::RangeRecord<Spec>> {
91 static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
92 return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
93 }
94};
95
96
97#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
98