Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* GRAPHITE2 LICENSING |
michael@0 | 2 | |
michael@0 | 3 | Copyright 2010, SIL International |
michael@0 | 4 | All rights reserved. |
michael@0 | 5 | |
michael@0 | 6 | This library is free software; you can redistribute it and/or modify |
michael@0 | 7 | it under the terms of the GNU Lesser General Public License as published |
michael@0 | 8 | by the Free Software Foundation; either version 2.1 of License, or |
michael@0 | 9 | (at your option) any later version. |
michael@0 | 10 | |
michael@0 | 11 | This program is distributed in the hope that it will be useful, |
michael@0 | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
michael@0 | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
michael@0 | 14 | Lesser General Public License for more details. |
michael@0 | 15 | |
michael@0 | 16 | You should also have received a copy of the GNU Lesser General Public |
michael@0 | 17 | License along with this library in the file named "LICENSE". |
michael@0 | 18 | If not, write to the Free Software Foundation, 51 Franklin Street, |
michael@0 | 19 | Suite 500, Boston, MA 02110-1335, USA or visit their web page on the |
michael@0 | 20 | internet at http://www.fsf.org/licenses/lgpl.html. |
michael@0 | 21 | |
michael@0 | 22 | Alternatively, the contents of this file may be used under the terms of the |
michael@0 | 23 | Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public |
michael@0 | 24 | License, as published by the Free Software Foundation, either version 2 |
michael@0 | 25 | of the License or (at your option) any later version. |
michael@0 | 26 | */ |
michael@0 | 27 | #include "graphite2/Segment.h" |
michael@0 | 28 | #include "inc/UtfCodec.h" |
michael@0 | 29 | #include "inc/Segment.h" |
michael@0 | 30 | |
michael@0 | 31 | using namespace graphite2; |
michael@0 | 32 | |
michael@0 | 33 | namespace |
michael@0 | 34 | { |
michael@0 | 35 | |
michael@0 | 36 | gr_segment* makeAndInitialize(const Font *font, const Face *face, uint32 script, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void* pStart, size_t nChars, int dir) |
michael@0 | 37 | { |
michael@0 | 38 | if (script == 0x20202020) script = 0; |
michael@0 | 39 | else if ((script & 0x00FFFFFF) == 0x00202020) script = script & 0xFF000000; |
michael@0 | 40 | else if ((script & 0x0000FFFF) == 0x00002020) script = script & 0xFFFF0000; |
michael@0 | 41 | else if ((script & 0x000000FF) == 0x00000020) script = script & 0xFFFFFF00; |
michael@0 | 42 | // if (!font) return NULL; |
michael@0 | 43 | Segment* pRes=new Segment(nChars, face, script, dir); |
michael@0 | 44 | |
michael@0 | 45 | |
michael@0 | 46 | if (!pRes->read_text(face, pFeats, enc, pStart, nChars) || !pRes->runGraphite()) |
michael@0 | 47 | { |
michael@0 | 48 | delete pRes; |
michael@0 | 49 | return NULL; |
michael@0 | 50 | } |
michael@0 | 51 | // run the line break passes |
michael@0 | 52 | // run the substitution passes |
michael@0 | 53 | pRes->prepare_pos(font); |
michael@0 | 54 | // run the positioning passes |
michael@0 | 55 | pRes->finalise(font); |
michael@0 | 56 | |
michael@0 | 57 | return static_cast<gr_segment*>(pRes); |
michael@0 | 58 | } |
michael@0 | 59 | |
michael@0 | 60 | |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | |
michael@0 | 64 | template <typename utf_iter> |
michael@0 | 65 | inline size_t count_unicode_chars(utf_iter first, const utf_iter last, const void **error) |
michael@0 | 66 | { |
michael@0 | 67 | size_t n_chars = 0; |
michael@0 | 68 | uint32 usv = 0; |
michael@0 | 69 | |
michael@0 | 70 | if (last) |
michael@0 | 71 | { |
michael@0 | 72 | for (;first != last; ++first, ++n_chars) |
michael@0 | 73 | if ((usv = *first) == 0 || first.error()) break; |
michael@0 | 74 | } |
michael@0 | 75 | else |
michael@0 | 76 | { |
michael@0 | 77 | while ((usv = *first) != 0 && !first.error()) |
michael@0 | 78 | { |
michael@0 | 79 | ++first; |
michael@0 | 80 | ++n_chars; |
michael@0 | 81 | } |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | if (error) *error = first.error() ? first : 0; |
michael@0 | 85 | return n_chars; |
michael@0 | 86 | } |
michael@0 | 87 | |
michael@0 | 88 | extern "C" { |
michael@0 | 89 | |
michael@0 | 90 | size_t gr_count_unicode_characters(gr_encform enc, const void* buffer_begin, const void* buffer_end/*don't go on or past end, If NULL then ignored*/, const void** pError) //Also stops on nul. Any nul is not in the count |
michael@0 | 91 | { |
michael@0 | 92 | assert(buffer_begin); |
michael@0 | 93 | |
michael@0 | 94 | switch (enc) |
michael@0 | 95 | { |
michael@0 | 96 | case gr_utf8: return count_unicode_chars<utf8::const_iterator>(buffer_begin, buffer_end, pError); break; |
michael@0 | 97 | case gr_utf16: return count_unicode_chars<utf16::const_iterator>(buffer_begin, buffer_end, pError); break; |
michael@0 | 98 | case gr_utf32: return count_unicode_chars<utf32::const_iterator>(buffer_begin, buffer_end, pError); break; |
michael@0 | 99 | default: return 0; |
michael@0 | 100 | } |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | |
michael@0 | 104 | gr_segment* gr_make_seg(const gr_font *font, const gr_face *face, gr_uint32 script, const gr_feature_val* pFeats, gr_encform enc, const void* pStart, size_t nChars, int dir) |
michael@0 | 105 | { |
michael@0 | 106 | const gr_feature_val * tmp_feats = 0; |
michael@0 | 107 | if (pFeats == 0) |
michael@0 | 108 | pFeats = tmp_feats = static_cast<const gr_feature_val*>(face->theSill().cloneFeatures(0)); |
michael@0 | 109 | gr_segment * seg = makeAndInitialize(font, face, script, pFeats, enc, pStart, nChars, dir); |
michael@0 | 110 | delete tmp_feats; |
michael@0 | 111 | |
michael@0 | 112 | return seg; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | |
michael@0 | 116 | void gr_seg_destroy(gr_segment* p) |
michael@0 | 117 | { |
michael@0 | 118 | delete p; |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | |
michael@0 | 122 | float gr_seg_advance_X(const gr_segment* pSeg/*not NULL*/) |
michael@0 | 123 | { |
michael@0 | 124 | assert(pSeg); |
michael@0 | 125 | return pSeg->advance().x; |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | |
michael@0 | 129 | float gr_seg_advance_Y(const gr_segment* pSeg/*not NULL*/) |
michael@0 | 130 | { |
michael@0 | 131 | assert(pSeg); |
michael@0 | 132 | return pSeg->advance().y; |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | |
michael@0 | 136 | unsigned int gr_seg_n_cinfo(const gr_segment* pSeg/*not NULL*/) |
michael@0 | 137 | { |
michael@0 | 138 | assert(pSeg); |
michael@0 | 139 | return pSeg->charInfoCount(); |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | |
michael@0 | 143 | const gr_char_info* gr_seg_cinfo(const gr_segment* pSeg/*not NULL*/, unsigned int index/*must be <number_of_CharInfo*/) |
michael@0 | 144 | { |
michael@0 | 145 | assert(pSeg); |
michael@0 | 146 | return static_cast<const gr_char_info*>(pSeg->charinfo(index)); |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | unsigned int gr_seg_n_slots(const gr_segment* pSeg/*not NULL*/) |
michael@0 | 150 | { |
michael@0 | 151 | assert(pSeg); |
michael@0 | 152 | return pSeg->slotCount(); |
michael@0 | 153 | } |
michael@0 | 154 | |
michael@0 | 155 | const gr_slot* gr_seg_first_slot(gr_segment* pSeg/*not NULL*/) |
michael@0 | 156 | { |
michael@0 | 157 | assert(pSeg); |
michael@0 | 158 | return static_cast<const gr_slot*>(pSeg->first()); |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | const gr_slot* gr_seg_last_slot(gr_segment* pSeg/*not NULL*/) |
michael@0 | 162 | { |
michael@0 | 163 | assert(pSeg); |
michael@0 | 164 | return static_cast<const gr_slot*>(pSeg->last()); |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | float gr_seg_justify(gr_segment* pSeg/*not NULL*/, const gr_slot* pSlot/*not NULL*/, const gr_font *pFont, double width, enum gr_justFlags flags, const gr_slot *pFirst, const gr_slot *pLast) |
michael@0 | 168 | { |
michael@0 | 169 | assert(pSeg); |
michael@0 | 170 | assert(pSlot); |
michael@0 | 171 | return pSeg->justify(const_cast<gr_slot *>(pSlot), pFont, float(width), justFlags(flags), const_cast<gr_slot *>(pFirst), const_cast<gr_slot *>(pLast)); |
michael@0 | 172 | } |
michael@0 | 173 | |
michael@0 | 174 | } // extern "C" |