122 #define DEFINE_SIZE_ARRAY2(size, array1, array2) \ |
123 #define DEFINE_SIZE_ARRAY2(size, array1, array2) \ |
123 DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ |
124 DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ |
124 DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ |
125 DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ |
125 static const unsigned int min_size = (size) |
126 static const unsigned int min_size = (size) |
126 |
127 |
127 |
|
128 |
|
129 /* |
|
130 * Null objects |
|
131 */ |
|
132 |
|
133 /* Global nul-content Null pool. Enlarge as necessary. */ |
|
134 |
|
135 #define HB_NULL_POOL_SIZE 264 |
|
136 static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); |
|
137 |
|
138 #ifdef HB_NO_VISIBILITY |
|
139 static |
|
140 #else |
|
141 extern HB_INTERNAL |
|
142 #endif |
|
143 const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] |
|
144 #ifdef HB_NO_VISIBILITY |
|
145 = {} |
|
146 #endif |
|
147 ; |
|
148 |
|
149 /* Generic nul-content Null objects. */ |
|
150 template <typename Type> |
|
151 static inline const Type& Null (void) { |
|
152 static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); |
|
153 return *CastP<Type> (_hb_NullPool); |
|
154 } |
|
155 |
|
156 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ |
|
157 #define DEFINE_NULL_DATA(Type, data) \ |
|
158 static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \ |
|
159 template <> \ |
|
160 /*static*/ inline const Type& Null<Type> (void) { \ |
|
161 return *CastP<Type> (_Null##Type); \ |
|
162 } /* The following line really exists such that we end in a place needing semicolon */ \ |
|
163 static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") |
|
164 |
|
165 /* Accessor macro. */ |
|
166 #define Null(Type) Null<Type>() |
|
167 |
128 |
168 |
129 |
169 /* |
130 /* |
170 * Dispatch |
131 * Dispatch |
171 */ |
132 */ |
223 } |
184 } |
224 |
185 |
225 inline void start_processing (void) |
186 inline void start_processing (void) |
226 { |
187 { |
227 this->start = hb_blob_get_data (this->blob, nullptr); |
188 this->start = hb_blob_get_data (this->blob, nullptr); |
228 this->end = this->start + hb_blob_get_length (this->blob); |
189 this->end = this->start + this->blob->length; |
229 assert (this->start <= this->end); /* Must not overflow. */ |
190 assert (this->start <= this->end); /* Must not overflow. */ |
230 this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR, |
191 this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR, |
231 (unsigned) HB_SANITIZE_MAX_OPS_MIN); |
192 (unsigned) HB_SANITIZE_MAX_OPS_MIN); |
232 this->edit_count = 0; |
193 this->edit_count = 0; |
233 this->debug_depth = 0; |
194 this->debug_depth = 0; |
670 typedef IntType<int8_t, 1> HBINT8; /* 8-bit signed integer. */ |
629 typedef IntType<int8_t, 1> HBINT8; /* 8-bit signed integer. */ |
671 typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */ |
630 typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */ |
672 typedef IntType<int16_t, 2> HBINT16; /* 16-bit signed integer. */ |
631 typedef IntType<int16_t, 2> HBINT16; /* 16-bit signed integer. */ |
673 typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */ |
632 typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */ |
674 typedef IntType<int32_t, 4> HBINT32; /* 32-bit signed integer. */ |
633 typedef IntType<int32_t, 4> HBINT32; /* 32-bit signed integer. */ |
675 typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ |
634 typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */ |
676 |
635 |
677 /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */ |
636 /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */ |
678 typedef HBINT16 FWORD; |
637 typedef HBINT16 FWORD; |
679 |
638 |
680 /* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */ |
639 /* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */ |
681 typedef HBUINT16 UFWORD; |
640 typedef HBUINT16 UFWORD; |
682 |
641 |
683 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ |
642 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ |
684 struct F2DOT14 : HBINT16 |
643 struct F2DOT14 : HBINT16 |
685 { |
644 { |
686 //inline float to_float (void) const { return ???; } |
645 // 16384 means 1<<14 |
687 //inline void set_float (float f) { v.set (f * ???); } |
646 inline float to_float (void) const { return ((int32_t) v) / 16384.f; } |
|
647 inline void set_float (float f) { v.set (round (f * 16384.f)); } |
688 public: |
648 public: |
689 DEFINE_SIZE_STATIC (2); |
649 DEFINE_SIZE_STATIC (2); |
690 }; |
650 }; |
691 |
651 |
692 /* 32-bit signed fixed-point number (16.16). */ |
652 /* 32-bit signed fixed-point number (16.16). */ |
693 struct Fixed: HBINT32 |
653 struct Fixed : HBINT32 |
694 { |
654 { |
695 inline float to_float (void) const { return ((int32_t) v) / 65536.0; } |
655 // 65536 means 1<<16 |
696 inline void set_float (float f) { v.set (round (f * 65536.0)); } |
656 inline float to_float (void) const { return ((int32_t) v) / 65536.f; } |
|
657 inline void set_float (float f) { v.set (round (f * 65536.f)); } |
697 public: |
658 public: |
698 DEFINE_SIZE_STATIC (4); |
659 DEFINE_SIZE_STATIC (4); |
699 }; |
660 }; |
700 |
661 |
701 /* Date represented in number of seconds since 12:00 midnight, January 1, |
662 /* Date represented in number of seconds since 12:00 midnight, January 1, |
722 inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } |
683 inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } |
723 inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } |
684 inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } |
724 public: |
685 public: |
725 DEFINE_SIZE_STATIC (4); |
686 DEFINE_SIZE_STATIC (4); |
726 }; |
687 }; |
727 DEFINE_NULL_DATA (Tag, " "); |
688 DEFINE_NULL_DATA (OT, Tag, " "); |
728 |
689 |
729 /* Glyph index number, same as uint16 (length = 16 bits) */ |
690 /* Glyph index number, same as uint16 (length = 16 bits) */ |
730 typedef HBUINT16 GlyphID; |
691 typedef HBUINT16 GlyphID; |
|
692 |
|
693 /* Name-table index, same as uint16 (length = 16 bits) */ |
|
694 typedef HBUINT16 NameID; |
731 |
695 |
732 /* Script/language-system/feature index */ |
696 /* Script/language-system/feature index */ |
733 struct Index : HBUINT16 { |
697 struct Index : HBUINT16 { |
734 static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; |
698 static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; |
735 }; |
699 }; |
736 DEFINE_NULL_DATA (Index, "\xff\xff"); |
700 DEFINE_NULL_DATA (OT, Index, "\xff\xff"); |
737 |
701 |
738 /* Offset, Null offset = 0 */ |
702 /* Offset, Null offset = 0 */ |
739 template <typename Type> |
703 template <typename Type> |
740 struct Offset : Type |
704 struct Offset : Type |
741 { |
705 { |
813 { |
777 { |
814 inline const Type& operator () (const void *base) const |
778 inline const Type& operator () (const void *base) const |
815 { |
779 { |
816 unsigned int offset = *this; |
780 unsigned int offset = *this; |
817 if (unlikely (!offset)) return Null(Type); |
781 if (unlikely (!offset)) return Null(Type); |
|
782 return StructAtOffset<const Type> (base, offset); |
|
783 } |
|
784 inline Type& operator () (void *base) const |
|
785 { |
|
786 unsigned int offset = *this; |
|
787 if (unlikely (!offset)) return Crap(Type); |
818 return StructAtOffset<Type> (base, offset); |
788 return StructAtOffset<Type> (base, offset); |
819 } |
789 } |
820 |
790 |
821 inline Type& serialize (hb_serialize_context_t *c, const void *base) |
791 inline Type& serialize (hb_serialize_context_t *c, const void *base) |
822 { |
792 { |
859 |
829 |
860 |
830 |
861 /* |
831 /* |
862 * Array Types |
832 * Array Types |
863 */ |
833 */ |
|
834 |
|
835 |
|
836 /* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */ |
|
837 template <typename Type> |
|
838 struct UnsizedArrayOf |
|
839 { |
|
840 inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } |
|
841 inline Type& operator [] (unsigned int i) { return arrayZ[i]; } |
|
842 |
|
843 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const |
|
844 { |
|
845 TRACE_SANITIZE (this); |
|
846 if (unlikely (!sanitize_shallow (c, count))) return_trace (false); |
|
847 |
|
848 /* Note: for structs that do not reference other structs, |
|
849 * we do not need to call their sanitize() as we already did |
|
850 * a bound check on the aggregate array size. We just include |
|
851 * a small unreachable expression to make sure the structs |
|
852 * pointed to do have a simple sanitize(), ie. they do not |
|
853 * reference other structs via offsets. |
|
854 */ |
|
855 (void) (false && arrayZ[0].sanitize (c)); |
|
856 |
|
857 return_trace (true); |
|
858 } |
|
859 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const |
|
860 { |
|
861 TRACE_SANITIZE (this); |
|
862 if (unlikely (!sanitize_shallow (c, count))) return_trace (false); |
|
863 for (unsigned int i = 0; i < count; i++) |
|
864 if (unlikely (!arrayZ[i].sanitize (c, base))) |
|
865 return_trace (false); |
|
866 return_trace (true); |
|
867 } |
|
868 template <typename T> |
|
869 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const |
|
870 { |
|
871 TRACE_SANITIZE (this); |
|
872 if (unlikely (!sanitize_shallow (c, count))) return_trace (false); |
|
873 for (unsigned int i = 0; i < count; i++) |
|
874 if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) |
|
875 return_trace (false); |
|
876 return_trace (true); |
|
877 } |
|
878 |
|
879 inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const |
|
880 { |
|
881 TRACE_SANITIZE (this); |
|
882 return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count)); |
|
883 } |
|
884 |
|
885 public: |
|
886 Type arrayZ[VAR]; |
|
887 public: |
|
888 DEFINE_SIZE_ARRAY (0, arrayZ); |
|
889 }; |
|
890 |
|
891 /* Unsized array of offset's */ |
|
892 template <typename Type, typename OffsetType> |
|
893 struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {}; |
|
894 |
|
895 /* Unsized array of offsets relative to the beginning of the array itself. */ |
|
896 template <typename Type, typename OffsetType> |
|
897 struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType> |
|
898 { |
|
899 inline const Type& operator [] (unsigned int i) const |
|
900 { |
|
901 return this+this->arrayZ[i]; |
|
902 } |
|
903 |
|
904 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const |
|
905 { |
|
906 TRACE_SANITIZE (this); |
|
907 return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this))); |
|
908 } |
|
909 template <typename T> |
|
910 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const |
|
911 { |
|
912 TRACE_SANITIZE (this); |
|
913 return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data))); |
|
914 } |
|
915 }; |
|
916 |
864 |
917 |
865 /* An array with a number of elements. */ |
918 /* An array with a number of elements. */ |
866 template <typename Type, typename LenType=HBUINT16> |
919 template <typename Type, typename LenType=HBUINT16> |
867 struct ArrayOf |
920 struct ArrayOf |
868 { |
921 { |
873 count = 0; |
926 count = 0; |
874 else |
927 else |
875 count -= start_offset; |
928 count -= start_offset; |
876 count = MIN (count, *pcount); |
929 count = MIN (count, *pcount); |
877 *pcount = count; |
930 *pcount = count; |
878 return array + start_offset; |
931 return arrayZ + start_offset; |
879 } |
932 } |
880 |
933 |
881 inline const Type& operator [] (unsigned int i) const |
934 inline const Type& operator [] (unsigned int i) const |
882 { |
935 { |
883 if (unlikely (i >= len)) return Null(Type); |
936 if (unlikely (i >= len)) return Null(Type); |
884 return array[i]; |
937 return arrayZ[i]; |
885 } |
938 } |
886 inline Type& operator [] (unsigned int i) |
939 inline Type& operator [] (unsigned int i) |
887 { |
940 { |
888 return array[i]; |
941 if (unlikely (i >= len)) return Crap(Type); |
|
942 return arrayZ[i]; |
889 } |
943 } |
890 inline unsigned int get_size (void) const |
944 inline unsigned int get_size (void) const |
891 { return len.static_size + len * Type::static_size; } |
945 { return len.static_size + len * Type::static_size; } |
892 |
946 |
893 inline bool serialize (hb_serialize_context_t *c, |
947 inline bool serialize (hb_serialize_context_t *c, |
922 * a bound check on the aggregate array size. We just include |
976 * a bound check on the aggregate array size. We just include |
923 * a small unreachable expression to make sure the structs |
977 * a small unreachable expression to make sure the structs |
924 * pointed to do have a simple sanitize(), ie. they do not |
978 * pointed to do have a simple sanitize(), ie. they do not |
925 * reference other structs via offsets. |
979 * reference other structs via offsets. |
926 */ |
980 */ |
927 (void) (false && array[0].sanitize (c)); |
981 (void) (false && arrayZ[0].sanitize (c)); |
928 |
982 |
929 return_trace (true); |
983 return_trace (true); |
930 } |
984 } |
931 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
985 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
932 { |
986 { |
933 TRACE_SANITIZE (this); |
987 TRACE_SANITIZE (this); |
934 if (unlikely (!sanitize_shallow (c))) return_trace (false); |
988 if (unlikely (!sanitize_shallow (c))) return_trace (false); |
935 unsigned int count = len; |
989 unsigned int count = len; |
936 for (unsigned int i = 0; i < count; i++) |
990 for (unsigned int i = 0; i < count; i++) |
937 if (unlikely (!array[i].sanitize (c, base))) |
991 if (unlikely (!arrayZ[i].sanitize (c, base))) |
938 return_trace (false); |
992 return_trace (false); |
939 return_trace (true); |
993 return_trace (true); |
940 } |
994 } |
941 template <typename T> |
995 template <typename T> |
942 inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const |
996 inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const |
943 { |
997 { |
944 TRACE_SANITIZE (this); |
998 TRACE_SANITIZE (this); |
945 if (unlikely (!sanitize_shallow (c))) return_trace (false); |
999 if (unlikely (!sanitize_shallow (c))) return_trace (false); |
946 unsigned int count = len; |
1000 unsigned int count = len; |
947 for (unsigned int i = 0; i < count; i++) |
1001 for (unsigned int i = 0; i < count; i++) |
948 if (unlikely (!array[i].sanitize (c, base, user_data))) |
1002 if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) |
949 return_trace (false); |
1003 return_trace (false); |
950 return_trace (true); |
1004 return_trace (true); |
951 } |
1005 } |
952 |
1006 |
953 template <typename SearchType> |
1007 template <typename SearchType> |
954 inline int lsearch (const SearchType &x) const |
1008 inline int lsearch (const SearchType &x) const |
955 { |
1009 { |
956 unsigned int count = len; |
1010 unsigned int count = len; |
957 for (unsigned int i = 0; i < count; i++) |
1011 for (unsigned int i = 0; i < count; i++) |
958 if (!this->array[i].cmp (x)) |
1012 if (!this->arrayZ[i].cmp (x)) |
959 return i; |
1013 return i; |
960 return -1; |
1014 return -1; |
961 } |
1015 } |
962 |
1016 |
963 inline void qsort (void) |
1017 inline void qsort (void) |
964 { |
1018 { |
965 ::qsort (array, len, sizeof (Type), Type::cmp); |
1019 ::qsort (arrayZ, len, sizeof (Type), Type::cmp); |
966 } |
1020 } |
967 |
1021 |
968 private: |
1022 private: |
969 inline bool sanitize_shallow (hb_sanitize_context_t *c) const |
1023 inline bool sanitize_shallow (hb_sanitize_context_t *c) const |
970 { |
1024 { |
971 TRACE_SANITIZE (this); |
1025 TRACE_SANITIZE (this); |
972 return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len)); |
1026 return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len)); |
973 } |
1027 } |
974 |
1028 |
975 public: |
1029 public: |
976 LenType len; |
1030 LenType len; |
977 Type array[VAR]; |
1031 Type arrayZ[VAR]; |
978 public: |
1032 public: |
979 DEFINE_SIZE_ARRAY (sizeof (LenType), array); |
1033 DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); |
980 }; |
1034 }; |
981 template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {}; |
1035 template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {}; |
982 |
1036 |
983 /* Array of Offset's */ |
1037 /* Array of Offset's */ |
984 template <typename Type, typename OffsetType=HBUINT16> |
1038 template <typename Type, typename OffsetType=HBUINT16> |
1028 if (unlikely (!c->extend_min (*this))) return_trace (false); |
1092 if (unlikely (!c->extend_min (*this))) return_trace (false); |
1029 len.set (items_len); /* TODO(serialize) Overflow? */ |
1093 len.set (items_len); /* TODO(serialize) Overflow? */ |
1030 if (unlikely (!items_len)) return_trace (true); |
1094 if (unlikely (!items_len)) return_trace (true); |
1031 if (unlikely (!c->extend (*this))) return_trace (false); |
1095 if (unlikely (!c->extend (*this))) return_trace (false); |
1032 for (unsigned int i = 0; i < items_len - 1; i++) |
1096 for (unsigned int i = 0; i < items_len - 1; i++) |
1033 array[i] = items[i]; |
1097 arrayZ[i] = items[i]; |
1034 items += items_len - 1; |
1098 items += items_len - 1; |
1035 return_trace (true); |
1099 return_trace (true); |
1036 } |
1100 } |
1037 |
1101 |
1038 inline bool sanitize (hb_sanitize_context_t *c) const |
1102 inline bool sanitize (hb_sanitize_context_t *c) const |
1045 * a bound check on the aggregate array size. We just include |
1109 * a bound check on the aggregate array size. We just include |
1046 * a small unreachable expression to make sure the structs |
1110 * a small unreachable expression to make sure the structs |
1047 * pointed to do have a simple sanitize(), ie. they do not |
1111 * pointed to do have a simple sanitize(), ie. they do not |
1048 * reference other structs via offsets. |
1112 * reference other structs via offsets. |
1049 */ |
1113 */ |
1050 (void) (false && array[0].sanitize (c)); |
1114 (void) (false && arrayZ[0].sanitize (c)); |
1051 |
1115 |
1052 return_trace (true); |
1116 return_trace (true); |
1053 } |
1117 } |
1054 |
1118 |
1055 private: |
1119 private: |
1056 inline bool sanitize_shallow (hb_sanitize_context_t *c) const |
1120 inline bool sanitize_shallow (hb_sanitize_context_t *c) const |
1057 { |
1121 { |
1058 TRACE_SANITIZE (this); |
1122 TRACE_SANITIZE (this); |
1059 return_trace (len.sanitize (c) && |
1123 return_trace (len.sanitize (c) && |
1060 (!len || c->check_array (array, Type::static_size, len - 1))); |
1124 (!len || c->check_array (arrayZ, Type::static_size, len - 1))); |
1061 } |
1125 } |
1062 |
1126 |
1063 public: |
1127 public: |
1064 LenType len; |
1128 LenType len; |
1065 Type array[VAR]; |
1129 Type arrayZ[VAR]; |
1066 public: |
1130 public: |
1067 DEFINE_SIZE_ARRAY (sizeof (LenType), array); |
1131 DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); |
1068 }; |
1132 }; |
1069 |
1133 |
1070 |
1134 |
1071 /* |
1135 /* |
1072 * An array with sorted elements. Supports binary searching. |
1136 * An array with sorted elements. Supports binary searching. |
1111 |
1175 |
1112 inline void set (unsigned int v) |
1176 inline void set (unsigned int v) |
1113 { |
1177 { |
1114 len.set (v); |
1178 len.set (v); |
1115 assert (len == v); |
1179 assert (len == v); |
1116 entrySelectorZ.set (MAX (1u, _hb_bit_storage (v)) - 1); |
1180 entrySelector.set (MAX (1u, _hb_bit_storage (v)) - 1); |
1117 searchRangeZ.set (16 * (1u << entrySelectorZ)); |
1181 searchRange.set (16 * (1u << entrySelector)); |
1118 rangeShiftZ.set (v * 16 > searchRangeZ |
1182 rangeShift.set (v * 16 > searchRange |
1119 ? 16 * v - searchRangeZ |
1183 ? 16 * v - searchRange |
1120 : 0); |
1184 : 0); |
1121 } |
1185 } |
1122 |
1186 |
1123 protected: |
1187 protected: |
1124 HBUINT16 len; |
1188 HBUINT16 len; |
1125 HBUINT16 searchRangeZ; |
1189 HBUINT16 searchRange; |
1126 HBUINT16 entrySelectorZ; |
1190 HBUINT16 entrySelector; |
1127 HBUINT16 rangeShiftZ; |
1191 HBUINT16 rangeShift; |
1128 |
1192 |
1129 public: |
1193 public: |
1130 DEFINE_SIZE_STATIC (8); |
1194 DEFINE_SIZE_STATIC (8); |
1131 }; |
1195 }; |
1132 |
1196 |
1184 private: |
1248 private: |
1185 hb_face_t *face; |
1249 hb_face_t *face; |
1186 T *instance; |
1250 T *instance; |
1187 }; |
1251 }; |
1188 |
1252 |
1189 /* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ |
1253 /* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */ |
1190 template <typename T> |
1254 template <typename T> |
1191 struct hb_lazy_table_loader_t |
1255 struct hb_table_lazy_loader_t |
1192 { |
1256 { |
1193 inline void init (hb_face_t *face_) |
1257 inline void init (hb_face_t *face_) |
1194 { |
1258 { |
1195 face = face_; |
1259 face = face_; |
1196 blob = nullptr; |
1260 blob = nullptr; |
1197 instance = nullptr; |
|
1198 } |
1261 } |
1199 |
1262 |
1200 inline void fini (void) |
1263 inline void fini (void) |
1201 { |
1264 { |
1202 hb_blob_destroy (blob); |
1265 hb_blob_destroy (blob); |
1203 } |
1266 } |
1204 |
1267 |
1205 inline const T* get (void) const |
1268 inline const T* get (void) const |
1206 { |
1269 { |
1207 retry: |
1270 retry: |
1208 T *p = (T *) hb_atomic_ptr_get (&instance); |
1271 hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob); |
1209 if (unlikely (!p)) |
1272 if (unlikely (!blob_)) |
1210 { |
1273 { |
1211 hb_blob_t *blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag)); |
1274 blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag)); |
1212 p = const_cast<T *>(OT::Sanitizer<T>::lock_instance (blob_)); |
1275 if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_)) |
1213 if (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)) |
|
1214 { |
1276 { |
1215 hb_blob_destroy (blob_); |
1277 hb_blob_destroy (blob_); |
1216 goto retry; |
1278 goto retry; |
1217 } |
1279 } |
1218 blob = blob_; |
1280 blob = blob_; |
1219 } |
1281 } |
1220 return p; |
1282 return blob_->as<T> (); |
1221 } |
1283 } |
1222 |
1284 |
1223 inline const T* operator-> (void) const |
1285 inline const T* operator-> (void) const |
1224 { |
1286 { |
1225 return get(); |
1287 return get(); |
1226 } |
1288 } |
1227 |
1289 |
|
1290 private: |
1228 hb_face_t *face; |
1291 hb_face_t *face; |
1229 mutable hb_blob_t *blob; |
1292 mutable hb_blob_t *blob; |
1230 private: |
|
1231 mutable T *instance; |
|
1232 }; |
1293 }; |
1233 |
1294 |
1234 |
1295 |
1235 } /* namespace OT */ |
1296 } /* namespace OT */ |
1236 |
1297 |