зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1200098 - Update graphite2 library to release 1.3.2 from upstream. r=jdaggett
This commit is contained in:
Родитель
35f8a79f6f
Коммит
065c095a00
|
@ -1,6 +1,6 @@
|
|||
This directory contains the Graphite2 library from http://hg.palaso.org/graphitedev
|
||||
|
||||
Current version derived from upstream changeset e6539b6769cf
|
||||
Current version derived from upstream changeset 0f9edca71849
|
||||
|
||||
See gfx/graphite2/moz-gr-update.sh for update procedure.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#define GR2_VERSION_MAJOR 1
|
||||
#define GR2_VERSION_MINOR 3
|
||||
#define GR2_VERSION_BUGFIX 0
|
||||
#define GR2_VERSION_BUGFIX 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
|
|
@ -170,7 +170,8 @@ enum gr_bidirtl {
|
|||
/// Underlying paragraph direction is RTL
|
||||
gr_rtl = 1,
|
||||
/// Set this to not run the bidi pass internally, even if the font asks for it.
|
||||
/// This presumes that the segment is in a single direction.
|
||||
/// This presumes that the segment is in a single direction. Most of the time
|
||||
/// this bit should be set unless you know you are passing full paragraphs of text.
|
||||
gr_nobidi = 2,
|
||||
/// Disable auto mirroring for rtl text
|
||||
gr_nomirror = 4
|
||||
|
|
|
@ -747,7 +747,7 @@ void resolveWhitespace(int baseLevel, Slot *s)
|
|||
for ( ; s; s = s->prev())
|
||||
{
|
||||
int8 cls = s->getBidiClass();
|
||||
if (cls == WS || cls & WSflag)
|
||||
if (cls == WS || (cls & WSflag))
|
||||
s->setBidiLevel(baseLevel);
|
||||
else if (cls != BN)
|
||||
break;
|
||||
|
|
|
@ -74,7 +74,6 @@ add_library(graphite2 SHARED
|
|||
gr_logging.cpp
|
||||
gr_segment.cpp
|
||||
gr_slot.cpp
|
||||
Bidi.cpp
|
||||
CachedFace.cpp
|
||||
CmapCache.cpp
|
||||
Code.cpp
|
||||
|
@ -107,17 +106,14 @@ set_target_properties(graphite2 PROPERTIES PUBLIC_HEADER "${GRAPHITE_HEADERS}"
|
|||
LT_VERSION_REVISION ${GRAPHITE_API_REVISION}
|
||||
LT_VERSION_AGE ${GRAPHITE_API_AGE})
|
||||
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL "ClangASN")
|
||||
set(GRAPHITE_LINK_FLAGS "-fsanitize=address")
|
||||
else (${CMAKE_BUILD_TYPE} STREQUAL "ClangASN")
|
||||
set(GRAPHITE_LINK_FLAGS "")
|
||||
endif (${CMAKE_BUILD_TYPE} STREQUAL "ClangASN")
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set_target_properties(graphite2 PROPERTIES
|
||||
COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wctor-dtor-privacy -Wnon-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector -Wdouble-promotion"
|
||||
COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wctor-dtor-privacy -Wnon-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector"
|
||||
LINK_FLAGS "-nodefaultlibs ${GRAPHITE_LINK_FLAGS}"
|
||||
LINKER_LANGUAGE C)
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
add_definitions(-Wdouble-promotion)
|
||||
endif (CMAKE_COMPILER_IS_GNUCXX)
|
||||
if (${CMAKE_CXX_COMPILER} MATCHES ".*mingw.*")
|
||||
target_link_libraries(graphite2 kernel32 msvcr90 mingw32 gcc user32)
|
||||
else (${CMAKE_CXX_COMPILER} MATCHES ".*mingw.*")
|
||||
|
|
|
@ -38,11 +38,11 @@ const void * bmp_subtable(const Face::Table & cmap)
|
|||
{
|
||||
const void * stbl;
|
||||
if (!cmap.size()) return 0;
|
||||
if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size())))
|
||||
if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap.size())
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap.size())
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap.size())
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap.size())
|
||||
|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap.size()))
|
||||
return stbl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -51,8 +51,8 @@ const void * smp_subtable(const Face::Table & cmap)
|
|||
{
|
||||
const void * stbl;
|
||||
if (!cmap.size()) return 0;
|
||||
if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()))
|
||||
|| TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size())))
|
||||
if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap.size())
|
||||
|| TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap.size()))
|
||||
return stbl;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,6 @@ struct context
|
|||
|
||||
} // end namespace
|
||||
|
||||
byte * Machine::Code::local_memory = 0;
|
||||
|
||||
class Machine::Code::decoder
|
||||
{
|
||||
|
@ -90,7 +89,8 @@ public:
|
|||
byte max_ref;
|
||||
|
||||
analysis() : slotref(0), max_ref(0) {};
|
||||
void set_ref(int index) throw();
|
||||
void set_ref(int index, bool incinsert=false) throw();
|
||||
void set_noref(int index) throw();
|
||||
void set_changed(int index) throw();
|
||||
|
||||
};
|
||||
|
@ -146,7 +146,7 @@ inline Machine::Code::decoder::decoder(limits & lims, Code &code, enum passtype
|
|||
|
||||
Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
|
||||
uint8 pre_context, uint16 rule_length, const Silf & silf, const Face & face,
|
||||
enum passtype pt, byte * & _out)
|
||||
enum passtype pt, byte * * const _out)
|
||||
: _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0), _status(loaded),
|
||||
_constraint(is_constraint), _modify(false), _delete(false), _own(_out==0)
|
||||
{
|
||||
|
@ -162,11 +162,10 @@ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte
|
|||
assert(bytecode_end > bytecode_begin);
|
||||
const opcode_t * op_to_fn = Machine::getOpcodeTable();
|
||||
|
||||
// Allocate code and dat target buffers, these sizes are a worst case
|
||||
// Allocate code and data target buffers, these sizes are a worst case
|
||||
// estimate. Once we know their real sizes the we'll shrink them.
|
||||
if (_out) _code = reinterpret_cast<instr *>(_out);
|
||||
else _code = static_cast<instr *>(malloc((bytecode_end - bytecode_begin)
|
||||
* (sizeof(instr)+sizeof(byte))));
|
||||
if (_out) _code = reinterpret_cast<instr *>(*_out);
|
||||
else _code = static_cast<instr *>(malloc(estimateCodeDataOut(bytecode_end-bytecode_begin)));
|
||||
_data = reinterpret_cast<byte *>(_code + (bytecode_end - bytecode_begin));
|
||||
|
||||
if (!_code || !_data) {
|
||||
|
@ -220,7 +219,7 @@ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte
|
|||
memmove(_code + (_instr_count+1), _data, _data_size*sizeof(byte));
|
||||
size_t const total_sz = ((_instr_count+1) + (_data_size + sizeof(instr)-1)/sizeof(instr))*sizeof(instr);
|
||||
if (_out)
|
||||
_out += total_sz;
|
||||
*_out += total_sz;
|
||||
else
|
||||
_code = static_cast<instr *>(realloc(_code, total_sz));
|
||||
_data = reinterpret_cast<byte *>(_code + (_instr_count+1));
|
||||
|
@ -418,9 +417,11 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc)
|
|||
break;
|
||||
case PUSH_IGLYPH_ATTR :// not implemented
|
||||
++_stack_depth;
|
||||
break;
|
||||
case POP_RET :
|
||||
if (--_stack_depth < 0)
|
||||
failure(underfull_stack);
|
||||
// no break
|
||||
case RET_ZERO :
|
||||
case RET_TRUE :
|
||||
break;
|
||||
|
@ -477,14 +478,23 @@ void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8 * arg)
|
|||
case PUT_GLYPH_8BIT_OBS :
|
||||
case PUT_GLYPH :
|
||||
_code._modify = true;
|
||||
_analysis.set_changed(_analysis.slotref);
|
||||
_analysis.set_changed(0);
|
||||
break;
|
||||
case ATTR_SET :
|
||||
case ATTR_ADD :
|
||||
case ATTR_SET_SLOT :
|
||||
case IATTR_SET_SLOT :
|
||||
case IATTR_SET :
|
||||
case IATTR_ADD :
|
||||
case IATTR_SUB :
|
||||
_analysis.set_noref(0);
|
||||
break;
|
||||
case NEXT :
|
||||
case COPY_NEXT :
|
||||
if (!_analysis.contexts[_analysis.slotref].flags.inserted)
|
||||
++_analysis.slotref;
|
||||
_analysis.contexts[_analysis.slotref] = context(_code._instr_count+1);
|
||||
if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref;
|
||||
// if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref;
|
||||
break;
|
||||
case INSERT :
|
||||
_analysis.contexts[_analysis.slotref].flags.inserted = true;
|
||||
|
@ -493,14 +503,15 @@ void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8 * arg)
|
|||
case PUT_SUBS_8BIT_OBS : // slotref on 1st parameter
|
||||
case PUT_SUBS :
|
||||
_code._modify = true;
|
||||
_analysis.set_changed(_analysis.slotref);
|
||||
_analysis.set_changed(0);
|
||||
// no break
|
||||
case PUT_COPY :
|
||||
{
|
||||
if (arg[0] != 0) { _analysis.set_changed(_analysis.slotref); _code._modify = true; }
|
||||
if (arg[0] != 0) { _analysis.set_changed(0); _code._modify = true; }
|
||||
if (arg[0] <= 0 && -arg[0] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
|
||||
_analysis.set_ref(_analysis.slotref + arg[0] - _analysis.contexts[_analysis.slotref].flags.inserted);
|
||||
else if (_analysis.slotref + arg[0] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[0];
|
||||
_analysis.set_ref(arg[0], true);
|
||||
else if (arg[0] > 0)
|
||||
_analysis.set_ref(arg[0], true);
|
||||
break;
|
||||
}
|
||||
case PUSH_ATT_TO_GATTR_OBS : // slotref on 2nd parameter
|
||||
|
@ -513,16 +524,18 @@ void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8 * arg)
|
|||
case PUSH_ISLOT_ATTR :
|
||||
case PUSH_FEAT :
|
||||
if (arg[1] <= 0 && -arg[1] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
|
||||
_analysis.set_ref(_analysis.slotref + arg[1] - _analysis.contexts[_analysis.slotref].flags.inserted);
|
||||
else if (_analysis.slotref + arg[1] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[1];
|
||||
_analysis.set_ref(arg[1], true);
|
||||
else if (arg[1] > 0)
|
||||
_analysis.set_ref(arg[1], true);
|
||||
break;
|
||||
case PUSH_ATT_TO_GLYPH_ATTR :
|
||||
if (_code._constraint) return;
|
||||
// no break
|
||||
case PUSH_GLYPH_ATTR :
|
||||
if (arg[2] <= 0 && -arg[2] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
|
||||
_analysis.set_ref(_analysis.slotref + arg[2] - _analysis.contexts[_analysis.slotref].flags.inserted);
|
||||
else if (_analysis.slotref + arg[2] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[2];
|
||||
_analysis.set_ref(arg[2], true);
|
||||
else if (arg[2] > 0)
|
||||
_analysis.set_ref(arg[2], true);
|
||||
break;
|
||||
case ASSOC : // slotrefs in varargs
|
||||
break;
|
||||
|
@ -604,6 +617,7 @@ void Machine::Code::decoder::apply_analysis(instr * const code, instr * code_end
|
|||
*tip = temp_copy;
|
||||
++code_end;
|
||||
++tempcount;
|
||||
_code._delete = true;
|
||||
}
|
||||
|
||||
_code._instr_count = code_end - code;
|
||||
|
@ -619,8 +633,13 @@ bool Machine::Code::decoder::validate_opcode(const opcode opc, const byte * cons
|
|||
return false;
|
||||
}
|
||||
const opcode_t & op = Machine::getOpcodeTable()[opc];
|
||||
if (op.param_sz == VARARGS && bc >= _max.bytecode)
|
||||
{
|
||||
failure(arguments_exhausted);
|
||||
return false;
|
||||
}
|
||||
const size_t param_sz = op.param_sz == VARARGS ? bc[0] + 1 : op.param_sz;
|
||||
if (bc - 1 + param_sz > _max.bytecode)
|
||||
if (bc - 1 + param_sz >= _max.bytecode)
|
||||
{
|
||||
failure(arguments_exhausted);
|
||||
return false;
|
||||
|
@ -654,16 +673,28 @@ void Machine::Code::failure(const status_t s) throw() {
|
|||
|
||||
|
||||
inline
|
||||
void Machine::Code::decoder::analysis::set_ref(const int index) throw() {
|
||||
contexts[index].flags.referenced = true;
|
||||
if (index > max_ref) max_ref = index;
|
||||
void Machine::Code::decoder::analysis::set_ref(int index, bool incinsert) throw() {
|
||||
if (incinsert && contexts[slotref].flags.inserted) --index;
|
||||
if (index + slotref < 0) return;
|
||||
contexts[index + slotref].flags.referenced = true;
|
||||
if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void Machine::Code::decoder::analysis::set_changed(const int index) throw() {
|
||||
contexts[index].flags.changed = true;
|
||||
if (index > max_ref) max_ref = index;
|
||||
void Machine::Code::decoder::analysis::set_noref(int index) throw() {
|
||||
if (contexts[slotref].flags.inserted) --index;
|
||||
if (index + slotref < 0) return;
|
||||
if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void Machine::Code::decoder::analysis::set_changed(int index) throw() {
|
||||
if (contexts[slotref].flags.inserted) --index;
|
||||
if (index + slotref < 0) return;
|
||||
contexts[index + slotref].flags.changed = true;
|
||||
if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
|
||||
}
|
||||
|
||||
|
||||
|
@ -682,10 +713,12 @@ int32 Machine::Code::run(Machine & m, slotref * & map) const
|
|||
// assert(_own);
|
||||
assert(*this); // Check we are actually runnable
|
||||
|
||||
if (m.slotMap().size() <= size_t(_max_ref + m.slotMap().context()))
|
||||
if (m.slotMap().size() <= size_t(_max_ref + m.slotMap().context())
|
||||
|| m.slotMap()[_max_ref + m.slotMap().context()] == 0)
|
||||
{
|
||||
m._status = Machine::slot_offset_out_bounds;
|
||||
return 1;
|
||||
// return m.run(_code, _data, map);
|
||||
}
|
||||
|
||||
return m.run(_code, _data, map);
|
||||
|
|
|
@ -39,7 +39,7 @@ of the License or (at your option) any later version.
|
|||
|
||||
// Possible rounding error for subbox boundaries: 0.016 = 1/64 = 1/256 * 4
|
||||
// (values in font range from 0..256)
|
||||
#define SUBBOX_RND_ERR 0.016
|
||||
// #define SUBBOX_RND_ERR 0.016
|
||||
|
||||
using namespace graphite2;
|
||||
|
||||
|
@ -543,7 +543,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif
|
|||
}
|
||||
}
|
||||
bool res = true;
|
||||
if (cslot && cslot->exclGlyph() > 0 && gc.check(cslot->exclGlyph()) && !isExclusion)
|
||||
if (cslot->exclGlyph() > 0 && gc.check(cslot->exclGlyph()) && !isExclusion)
|
||||
{
|
||||
// Set up the bogus slot representing the exclusion glyph.
|
||||
Slot *exclSlot = seg->newSlot();
|
||||
|
@ -925,6 +925,8 @@ bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float
|
|||
bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, GR_MAYBE_UNUSED json * const dbgout)
|
||||
{
|
||||
int rtl = (dir & 1) * 2 - 1;
|
||||
if (!seg->getFace()->glyphs().check(slot->gid()))
|
||||
return false;
|
||||
const Rect &bb = seg->theGlyphBBoxTemporary(slot->gid());
|
||||
const float sx = slot->origin().x + currShift.x;
|
||||
float x = sx + (rtl > 0 ? bb.tr.x : bb.bl.x);
|
||||
|
@ -971,7 +973,6 @@ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift
|
|||
|
||||
|
||||
// Return the amount to kern by.
|
||||
// TODO: do we need to make use of marginMin here? Probably not.
|
||||
Position KernCollider::resolve(GR_MAYBE_UNUSED Segment *seg, GR_MAYBE_UNUSED Slot *slot,
|
||||
int dir, float margin, GR_MAYBE_UNUSED json * const dbgout)
|
||||
{
|
||||
|
|
|
@ -1,75 +1,75 @@
|
|||
/* Copyright (c) 2012, Siyuan Fu <fusiyuan2010@gmail.com>
|
||||
Copyright (c) 2015, SIL International
|
||||
/* GRAPHITE2 LICENSING
|
||||
|
||||
Copyright 2015, SIL International
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should also have received a copy of the GNU Lesser General Public
|
||||
License along with this library in the file named "LICENSE".
|
||||
If not, write to the Free Software Foundation, 51 Franklin Street,
|
||||
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
|
||||
internet at http://www.fsf.org/licenses/lgpl.html.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
|
||||
License, as published by the Free Software Foundation, either version 2
|
||||
of the License or (at your option) any later version.
|
||||
*/
|
||||
#include <cassert>
|
||||
|
||||
#include "inc/Decompressor.h"
|
||||
#include "inc/Shrinker.h"
|
||||
#include "inc/Compression.h"
|
||||
|
||||
using namespace shrinker;
|
||||
using namespace lz4;
|
||||
|
||||
namespace {
|
||||
|
||||
u8 const LONG_DIST = 0x10;
|
||||
u8 const MATCH_LEN = 0x0f;
|
||||
|
||||
template <int M>
|
||||
inline
|
||||
u32 read_literal(u8 const * &s, u8 const * const e, u32 l) {
|
||||
if (unlikely(l == M))
|
||||
if (unlikely(l == 15) && likely(s != e))
|
||||
{
|
||||
u8 b = 0;
|
||||
u8 b = 0;
|
||||
do { l += b = *s++; } while(b==0xff && s != e);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
bool read_directive(u8 const * &src, u8 const * const end, u32 & literal_len, u32 & match_len, u32 & match_dist)
|
||||
bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
|
||||
{
|
||||
u8 const flag = *src++;
|
||||
u8 const token = *src++;
|
||||
|
||||
literal_len = read_literal<7>(src, end, flag >> 5);
|
||||
match_len = read_literal<15>(src, end, flag & MATCH_LEN);
|
||||
literal_len = read_literal(src, end, token >> 4);
|
||||
literal = src;
|
||||
src += literal_len;
|
||||
|
||||
match_dist = *src++;
|
||||
if (flag & LONG_DIST)
|
||||
match_dist |= ((*src++) << 8);
|
||||
if (unlikely(src > end - 2))
|
||||
return false;
|
||||
|
||||
return match_dist != 0xffff;
|
||||
match_dist = *src++;
|
||||
match_dist |= *src++ << 8;
|
||||
match_len = read_literal(src, end, token & 0xf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int shrinker::decompress(void const *in, size_t in_size, void *out, size_t out_size)
|
||||
int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
|
||||
{
|
||||
if (out_size <= in_size)
|
||||
return -1;
|
||||
|
||||
u8 const * src = static_cast<u8 const *>(in),
|
||||
* literal = 0,
|
||||
* const src_end = src + in_size;
|
||||
|
||||
u8 * dst = static_cast<u8*>(out),
|
||||
|
@ -78,24 +78,29 @@ int shrinker::decompress(void const *in, size_t in_size, void *out, size_t out_s
|
|||
u32 literal_len = 0,
|
||||
match_len = 0,
|
||||
match_dist = 0;
|
||||
|
||||
while (read_directive(src, src_end, literal_len, match_len, match_dist))
|
||||
|
||||
while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
|
||||
{
|
||||
// Copy in literal
|
||||
if (unlikely(dst + literal_len + sizeof(unsigned long) > dst_end)) return -1;
|
||||
dst = memcpy_nooverlap(dst, src, literal_len);
|
||||
src += literal_len;
|
||||
|
||||
// Copy in literal. At this point the last full sequence must be at
|
||||
// least MINMATCH + 5 from the end of the output buffer.
|
||||
if (unlikely(literal + align(literal_len) > src_end
|
||||
|| dst + align(literal_len) > dst_end - MINMATCH+5))
|
||||
return -1;
|
||||
dst = overrun_copy(dst, literal, literal_len);
|
||||
|
||||
// Copy, possibly repeating, match from earlier in the
|
||||
// decoded output.
|
||||
u8 const * const pcpy = dst - match_dist - 1;
|
||||
if (unlikely(pcpy < static_cast<u8*>(out)
|
||||
|| dst + match_len + MINMATCH + sizeof(unsigned long) > dst_end)) return -1;
|
||||
dst = memcpy_(dst, pcpy, match_len + MINMATCH);
|
||||
u8 const * const pcpy = dst - match_dist;
|
||||
if (unlikely(pcpy < static_cast<u8*>(out)
|
||||
|| dst + align(match_len + MINMATCH) > dst_end))
|
||||
return -1;
|
||||
dst = copy(dst, pcpy, match_len + MINMATCH);
|
||||
}
|
||||
|
||||
if (unlikely(dst + literal_len > dst_end)) return -1;
|
||||
dst = memcpy_nooverlap_surpass(dst, src, literal_len);
|
||||
if (unlikely(literal + literal_len > src_end
|
||||
|| dst + literal_len > dst_end))
|
||||
return -1;
|
||||
dst = fast_copy(dst, literal, literal_len);
|
||||
|
||||
return dst - (u8*)out;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace
|
|||
enum compression
|
||||
{
|
||||
NONE,
|
||||
SHRINKER
|
||||
LZ4
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ bool Face::readGraphite(const Table & silf)
|
|||
Error e;
|
||||
error_context(EC_READSILF);
|
||||
const byte * p = silf;
|
||||
if (e.test(!p, E_NOSILF)) return error(e);
|
||||
if (e.test(!p, E_NOSILF) || e.test(silf.size() < 20, E_BADSIZE)) return error(e);
|
||||
|
||||
const uint32 version = be::read<uint32>(p);
|
||||
if (e.test(version < 0x00020000, E_TOOOLD)) return error(e);
|
||||
|
@ -173,6 +173,10 @@ bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
|
|||
}
|
||||
#endif
|
||||
|
||||
// if ((seg->dir() & 1) != aSilf->dir())
|
||||
// seg->reverseSlots();
|
||||
if ((seg->dir() & 3) == 3 && aSilf->bidiPass() == 0xFF)
|
||||
seg->doMirror(aSilf->aMirror());
|
||||
bool res = aSilf->runGraphite(seg, 0, aSilf->positionPass(), true);
|
||||
if (res)
|
||||
{
|
||||
|
@ -185,6 +189,7 @@ bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
|
|||
#if !defined GRAPHITE2_NTRACING
|
||||
if (dbgout)
|
||||
{
|
||||
seg->positionSlots(0, 0, 0, aSilf->dir());
|
||||
*dbgout << json::item
|
||||
<< json::close // Close up the passes array
|
||||
<< "output" << json::array;
|
||||
|
@ -233,7 +238,9 @@ uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const
|
|||
{
|
||||
case kgmetAscent : return m_ascent;
|
||||
case kgmetDescent : return m_descent;
|
||||
default: return glyphs().glyph(gid)->getMetric(metric);
|
||||
default:
|
||||
if (gid > glyphs().numGlyphs()) return 0;
|
||||
return glyphs().glyph(gid)->getMetric(metric);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,7 +284,6 @@ Face::Table::Table(const Face & face, const Tag n, uint32 version) throw()
|
|||
if (!TtfUtil::CheckTable(n, _p, _sz))
|
||||
{
|
||||
this->~Table(); // Make sure we release the table buffer even if the table filed it's checks
|
||||
_p = 0; _sz = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -285,6 +291,15 @@ Face::Table::Table(const Face & face, const Tag n, uint32 version) throw()
|
|||
decompress();
|
||||
}
|
||||
|
||||
void Face::Table::releaseBuffers()
|
||||
{
|
||||
if (_compressed)
|
||||
free(const_cast<byte *>(_p));
|
||||
else if (_p && _f->m_ops.release_table)
|
||||
(*_f->m_ops.release_table)(_f->m_appFaceHandle, _p);
|
||||
_p = 0; _sz = 0;
|
||||
}
|
||||
|
||||
Face::Table & Face::Table::operator = (const Table & rhs) throw()
|
||||
{
|
||||
if (_p == rhs._p) return *this;
|
||||
|
@ -297,6 +312,8 @@ Face::Table & Face::Table::operator = (const Table & rhs) throw()
|
|||
Error Face::Table::decompress()
|
||||
{
|
||||
Error e;
|
||||
if (e.test(_sz < 2 * sizeof(uint32) + 3, E_BADSIZE))
|
||||
return e;
|
||||
byte * uncompressed_table = 0;
|
||||
size_t uncompressed_size = 0;
|
||||
|
||||
|
@ -308,25 +325,30 @@ Error Face::Table::decompress()
|
|||
switch(compression(hdr >> 27))
|
||||
{
|
||||
case NONE: return e;
|
||||
case SHRINKER:
|
||||
|
||||
case LZ4:
|
||||
{
|
||||
uncompressed_size = hdr & 0x07ffffff;
|
||||
uncompressed_table = gralloc<byte>(uncompressed_size);
|
||||
//TODO: Coverty: 1315803: FORWARD_NULL
|
||||
if (!e.test(!uncompressed_table, E_OUTOFMEM))
|
||||
e.test(shrinker::decompress(p, _sz - 2*sizeof(uint32), uncompressed_table, uncompressed_size) != signed(uncompressed_size), E_SHRINKERFAILED);
|
||||
//TODO: Coverty: 1315800: CHECKED_RETURN
|
||||
e.test(lz4::decompress(p, _sz - 2*sizeof(uint32), uncompressed_table, uncompressed_size) != signed(uncompressed_size), E_SHRINKERFAILED);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
e.error(E_BADSCHEME);
|
||||
};
|
||||
|
||||
// Check the uncompressed version number against the original.
|
||||
if (!e)
|
||||
//TODO: Coverty: 1315800: CHECKED_RETURN
|
||||
e.test(be::peek<uint32>(uncompressed_table) != version, E_SHRINKERFAILED);
|
||||
|
||||
// Tell the provider to release the compressed form since were replacing
|
||||
// it anyway.
|
||||
this->~Table();
|
||||
releaseBuffers();
|
||||
|
||||
if (e)
|
||||
{
|
||||
|
|
|
@ -131,11 +131,12 @@ bool FeatureMap::readFeats(const Face & face)
|
|||
const uint16 num_settings = be::read<uint16>(p);
|
||||
if (version >= 0x00020000)
|
||||
be::skip<uint16>(p);
|
||||
const byte * const feat_setts = feat_start + be::read<uint32>(p);
|
||||
const uint32 settings_offset = be::read<uint32>(p);
|
||||
const uint16 flags = be::read<uint16>(p),
|
||||
uiName = be::read<uint16>(p);
|
||||
|
||||
if (feat_setts + num_settings * FEATURE_SETTING_SIZE > feat_end)
|
||||
if (settings_offset > size_t(feat_end - feat_start)
|
||||
|| settings_offset + num_settings * FEATURE_SETTING_SIZE > size_t(feat_end - feat_start))
|
||||
{
|
||||
free(defVals);
|
||||
return false;
|
||||
|
@ -151,7 +152,7 @@ bool FeatureMap::readFeats(const Face & face)
|
|||
free(defVals);
|
||||
return false;
|
||||
}
|
||||
maxVal = readFeatureSettings(feat_setts, uiSet, num_settings);
|
||||
maxVal = readFeatureSettings(feat_start + settings_offset, uiSet, num_settings);
|
||||
defVals[i] = uiSet[0].value();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -83,7 +83,7 @@ const void *FileFace::get_table_fn(const void* appFaceHandle, unsigned int name,
|
|||
if (!TtfUtil::GetTableInfo(name, file_face._header_tbl, file_face._table_dir, tbl_offset, tbl_len))
|
||||
return 0;
|
||||
|
||||
if (tbl_offset + tbl_len > file_face._file_len
|
||||
if (tbl_offset > file_face._file_len || tbl_len > file_face._file_len - tbl_offset
|
||||
|| fseek(file_face._file, tbl_offset, SEEK_SET) != 0)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace
|
|||
// This is strictly a >= operator. A true == operator could be
|
||||
// implemented that test for overlap but it would be more expensive a
|
||||
// test.
|
||||
bool operator == (const _glat_iterator<W> & rhs) { return _v >= rhs._e; }
|
||||
bool operator == (const _glat_iterator<W> & rhs) { return _v >= rhs._e - 1; }
|
||||
bool operator != (const _glat_iterator<W> & rhs) { return !operator==(rhs); }
|
||||
|
||||
value_type operator * () const {
|
||||
|
@ -78,7 +78,8 @@ namespace
|
|||
typedef _glat_iterator<uint16> glat2_iterator;
|
||||
}
|
||||
|
||||
const Rect GlyphCache::nullRect = Rect();
|
||||
const SlantBox SlantBox::empty = {0,0,0,0};
|
||||
|
||||
|
||||
class GlyphCache::Loader
|
||||
{
|
||||
|
@ -145,7 +146,7 @@ GlyphCache::GlyphCache(const Face & face, const uint32 face_options)
|
|||
}
|
||||
else if (numsubs > 0)
|
||||
{
|
||||
GlyphBox * boxes = (GlyphBox *)gralloc<char>(_num_glyphs * sizeof(GlyphBox) + (numsubs-1) * 8 * sizeof(float));
|
||||
GlyphBox * boxes = (GlyphBox *)gralloc<char>(_num_glyphs * sizeof(GlyphBox) + numsubs * 8 * sizeof(float));
|
||||
GlyphBox * currbox = boxes;
|
||||
|
||||
for (uint16 gid = 0; currbox && gid != _num_glyphs; ++gid)
|
||||
|
@ -277,19 +278,20 @@ GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
|
|||
// subtracting the length of the attribids array (numAttribs long if present)
|
||||
// and dividing by either 2 or 4 depending on shor or lonf format
|
||||
_long_fmt = flags & 1;
|
||||
_num_glyphs_attributes = (m_pGloc.size()
|
||||
int tmpnumgattrs = (m_pGloc.size()
|
||||
- (p - m_pGloc)
|
||||
- sizeof(uint16)*(flags & 0x2 ? _num_attrs : 0))
|
||||
/ (_long_fmt ? sizeof(uint32) : sizeof(uint16)) - 1;
|
||||
|
||||
if (version >= 0x00020000
|
||||
if (version >= 0x00020000 || tmpnumgattrs < 0 || tmpnumgattrs > 65535
|
||||
|| _num_attrs == 0 || _num_attrs > 0x3000 // is this hard limit appropriate?
|
||||
|| _num_glyphs_graphics > _num_glyphs_attributes)
|
||||
|| _num_glyphs_graphics > tmpnumgattrs)
|
||||
{
|
||||
_head = Face::Table();
|
||||
return;
|
||||
}
|
||||
|
||||
_num_glyphs_attributes = static_cast<unsigned short>(tmpnumgattrs);
|
||||
p = m_pGlat;
|
||||
version = be::read<uint32>(p);
|
||||
if (version >= 0x00040000) // reject Glat tables that are too new
|
||||
|
@ -347,8 +349,12 @@ const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFa
|
|||
void *pGlyph = TtfUtil::GlyfLookup(_glyf, locidx, _glyf.size());
|
||||
|
||||
if (pGlyph && TtfUtil::GlyfBox(pGlyph, xMin, yMin, xMax, yMax))
|
||||
{
|
||||
if ((xMin > xMax) || (yMin > yMax))
|
||||
return 0;
|
||||
bbox = Rect(Position(static_cast<float>(xMin), static_cast<float>(yMin)),
|
||||
Position(static_cast<float>(xMax), static_cast<float>(yMax)));
|
||||
}
|
||||
}
|
||||
if (TtfUtil::HorMetrics(glyphid, _hmtx, _hmtx.size(), _hhea, nLsb, nAdvWid))
|
||||
advance = Position(static_cast<float>(nAdvWid), 0);
|
||||
|
@ -398,7 +404,8 @@ const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFa
|
|||
else
|
||||
{
|
||||
if (gloce - glocs < 3*sizeof(uint16) // can a glyph have no attributes? why not?
|
||||
|| gloce - glocs > _num_attrs*3*sizeof(uint16))
|
||||
|| gloce - glocs > _num_attrs*3*sizeof(uint16)
|
||||
|| glocs > m_pGlat.size() - 2*sizeof(uint16))
|
||||
return 0;
|
||||
new (&glyph) GlyphFace(bbox, advance, glat2_iterator(m_pGlat + glocs), glat2_iterator(m_pGlat + gloce));
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ of the License or (at your option) any later version.
|
|||
#include "inc/CharInfo.h"
|
||||
#include "inc/Slot.h"
|
||||
#include "inc/Main.h"
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
|
||||
using namespace graphite2;
|
||||
|
||||
|
@ -70,6 +70,13 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
|
|||
if (width < 0 && !(silf()->flags()))
|
||||
return width;
|
||||
|
||||
if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
|
||||
{
|
||||
reverseSlots();
|
||||
s = pFirst;
|
||||
pFirst = pLast;
|
||||
pLast = s;
|
||||
}
|
||||
if (!pFirst) pFirst = pSlot;
|
||||
while (!pFirst->isBase()) pFirst = pFirst->attachedTo();
|
||||
if (!pLast) pLast = last();
|
||||
|
@ -170,7 +177,7 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
|
|||
}
|
||||
}
|
||||
currWidth += diff - error;
|
||||
} while (i == 0 && int(abs(error)) > 0 && tWeight);
|
||||
} while (i == 0 && int(std::abs(error)) > 0 && tWeight);
|
||||
}
|
||||
|
||||
Slot *oldFirst = m_first;
|
||||
|
@ -203,7 +210,7 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
|
|||
if (dbgout)
|
||||
{
|
||||
*dbgout << json::item << json::close; // Close up the passes array
|
||||
positionSlots(NULL, pSlot, pLast);
|
||||
positionSlots(NULL, pSlot, pLast, m_dir);
|
||||
Slot *lEnd = pLast->nextSibling();
|
||||
*dbgout << "output" << json::array;
|
||||
for(Slot * t = pSlot; t != lEnd; t = t->next())
|
||||
|
@ -212,7 +219,7 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
|
|||
}
|
||||
#endif
|
||||
|
||||
res = positionSlots(font, pSlot, pLast);
|
||||
res = positionSlots(font, pSlot, pLast, m_dir);
|
||||
|
||||
if (silf()->flags() & 1)
|
||||
{
|
||||
|
@ -221,6 +228,9 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
|
|||
}
|
||||
m_first = oldFirst;
|
||||
m_last = oldLast;
|
||||
|
||||
if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
|
||||
reverseSlots();
|
||||
return res.x;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,13 @@ using namespace graphite2;
|
|||
using vm::Machine;
|
||||
typedef Machine::Code Code;
|
||||
|
||||
enum KernCollison
|
||||
{
|
||||
None = 0,
|
||||
CrossSpace = 1,
|
||||
InWord = 2,
|
||||
reserved = 3
|
||||
};
|
||||
|
||||
Pass::Pass()
|
||||
: m_silf(0),
|
||||
|
@ -53,16 +60,20 @@ Pass::Pass()
|
|||
m_states(0),
|
||||
m_codes(0),
|
||||
m_progs(0),
|
||||
m_flags(0),
|
||||
m_numCollRuns(0),
|
||||
m_kernColls(0),
|
||||
m_iMaxLoop(0),
|
||||
m_numGlyphs(0),
|
||||
m_numRules(0),
|
||||
m_numStates(0),
|
||||
m_numTransition(0),
|
||||
m_numSuccess(0),
|
||||
m_successStart(0),
|
||||
m_numColumns(0),
|
||||
m_minPreCtxt(0),
|
||||
m_maxPreCtxt(0)
|
||||
m_maxPreCtxt(0),
|
||||
m_colThreshold(0),
|
||||
m_isReverseDir(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -88,13 +99,17 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
|
|||
|
||||
if (e.test(pass_length < 40, E_BADPASSLENGTH)) return face.error(e);
|
||||
// Read in basic values
|
||||
m_flags = be::read<byte>(p);
|
||||
if (e.test((m_flags & 15) && pt < PASS_TYPE_POSITIONING, E_BADCOLLISIONPASS))
|
||||
const byte flags = be::read<byte>(p);
|
||||
if (e.test((flags & 0x1f) && pt < PASS_TYPE_POSITIONING, E_BADCOLLISIONPASS))
|
||||
return face.error(e);
|
||||
m_numCollRuns = flags & 0x7;
|
||||
m_kernColls = (flags >> 3) & 0x3;
|
||||
m_isReverseDir = (flags >> 5) & 0x1;
|
||||
m_iMaxLoop = be::read<byte>(p);
|
||||
if (m_iMaxLoop < 1) m_iMaxLoop = 1;
|
||||
be::skip<byte>(p,2); // skip maxContext & maxBackup
|
||||
m_numRules = be::read<uint16>(p);
|
||||
if (e.test(!m_numRules && !(m_flags & 7), E_BADEMPTYPASS)) return face.error(e);
|
||||
if (e.test(!m_numRules && m_numCollRuns == 0, E_BADEMPTYPASS)) return face.error(e);
|
||||
be::skip<uint16>(p); // fsmOffset - not sure why we would want this
|
||||
const byte * const pcCode = pass_start + be::read<uint32>(p) - subtable_base,
|
||||
* const rcCode = pass_start + be::read<uint32>(p) - subtable_base,
|
||||
|
@ -152,7 +167,7 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
|
|||
const uint16 * const o_actions = reinterpret_cast<const uint16 *>(p);
|
||||
be::skip<uint16>(p, m_numRules + 1);
|
||||
const byte * const states = p;
|
||||
if (e.test(p + 2 * m_numTransition*m_numColumns >= pass_end, E_BADPASSLENGTH)) return face.error(e);
|
||||
if (e.test(p + 2u*m_numTransition*m_numColumns >= pass_end, E_BADPASSLENGTH)) return face.error(e);
|
||||
be::skip<int16>(p, m_numTransition*m_numColumns);
|
||||
be::skip<uint8>(p);
|
||||
if (e.test(p != pcCode, E_BADPASSCCODEPTR)) return face.error(e);
|
||||
|
@ -212,9 +227,10 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
|
|||
// Allocate pools
|
||||
m_rules = new Rule [m_numRules];
|
||||
m_codes = new Code [m_numRules*2];
|
||||
m_progs = static_cast<byte *>(malloc((ac_end - ac_data + rc_end - rc_data)
|
||||
*(sizeof(vm::instr)+sizeof(byte))));
|
||||
byte * prog_pool_free = m_progs;
|
||||
const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data);
|
||||
m_progs = gralloc<byte>(prog_pool_sz);
|
||||
byte * prog_pool_free = m_progs,
|
||||
* prog_pool_end = m_progs + prog_pool_sz;
|
||||
if (e.test(!(m_rules && m_codes && m_progs), E_OUTOFMEM)) return face.error(e);
|
||||
|
||||
Rule * r = m_rules + m_numRules - 1;
|
||||
|
@ -233,10 +249,11 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
|
|||
rc_begin = be::peek<uint16>(o_constraint) ? rc_data + be::peek<uint16>(o_constraint) : rc_end;
|
||||
|
||||
if (ac_begin > ac_end || ac_begin > ac_data_end || ac_end > ac_data_end
|
||||
|| rc_begin > rc_end || rc_begin > rc_data_end || rc_end > rc_data_end)
|
||||
|| rc_begin > rc_end || rc_begin > rc_data_end || rc_end > rc_data_end
|
||||
|| vm::Machine::Code::estimateCodeDataOut(ac_end - ac_begin + rc_end - rc_begin) > size_t(prog_pool_end - prog_pool_free))
|
||||
return false;
|
||||
r->action = new (m_codes+n*2-2) vm::Machine::Code(false, ac_begin, ac_end, r->preContext, r->sort, *m_silf, face, pt, prog_pool_free);
|
||||
r->constraint = new (m_codes+n*2-1) vm::Machine::Code(true, rc_begin, rc_end, r->preContext, r->sort, *m_silf, face, pt, prog_pool_free);
|
||||
r->action = new (m_codes+n*2-2) vm::Machine::Code(false, ac_begin, ac_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free);
|
||||
r->constraint = new (m_codes+n*2-1) vm::Machine::Code(true, rc_begin, rc_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free);
|
||||
|
||||
if (e.test(!r->action || !r->constraint, E_OUTOFMEM)
|
||||
|| e.test(r->action->status() != Code::loaded, r->action->status() + E_CODEFAILURE)
|
||||
|
@ -245,19 +262,21 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
|
|||
return face.error(e);
|
||||
}
|
||||
|
||||
// Shrink the program pool
|
||||
ptrdiff_t const delta = static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs)) - m_progs;
|
||||
if (delta)
|
||||
byte * moved_progs = static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs));
|
||||
if (e.test(!moved_progs, E_OUTOFMEM)) return face.error(e);
|
||||
|
||||
if (moved_progs != m_progs)
|
||||
{
|
||||
m_progs += delta;
|
||||
for (Code * c = m_codes, * const ce = c + m_numRules*2; c != ce; ++c)
|
||||
{
|
||||
c->externalProgramMoved(delta);
|
||||
c->externalProgramMoved(moved_progs - m_progs);
|
||||
}
|
||||
m_progs = moved_progs;
|
||||
}
|
||||
|
||||
// Load the rule entries map
|
||||
face.error_context((face.error_context() & 0xFFFF00) + EC_APASS);
|
||||
//TODO: Coverty: 1315804: FORWARD_NULL
|
||||
RuleEntry * re = m_ruleMap = gralloc<RuleEntry>(num_entries);
|
||||
if (e.test(!re, E_OUTOFMEM)) return face.error(e);
|
||||
for (size_t n = num_entries; n; --n, ++re)
|
||||
|
@ -360,10 +379,11 @@ bool Pass::readRanges(const byte * ranges, size_t num_ranges, Error &e)
|
|||
}
|
||||
|
||||
|
||||
bool Pass::runGraphite(vm::Machine & m, FiniteStateMachine & fsm) const
|
||||
bool Pass::runGraphite(vm::Machine & m, FiniteStateMachine & fsm, bool reverse) const
|
||||
{
|
||||
Slot *s = m.slotMap().segment.first();
|
||||
if (!s || !testPassConstraint(m)) return true;
|
||||
if (reverse) m.slotMap().segment.reverseSlots();
|
||||
if (m_numRules)
|
||||
{
|
||||
Slot *currHigh = s->next();
|
||||
|
@ -387,23 +407,25 @@ bool Pass::runGraphite(vm::Machine & m, FiniteStateMachine & fsm) const
|
|||
}
|
||||
} while (s);
|
||||
}
|
||||
//TODO: Use enums for flags
|
||||
const bool collisions = m_numCollRuns || m_kernColls;
|
||||
|
||||
if (!(m_flags & 15) || !m.slotMap().segment.hasCollisionInfo())
|
||||
if (!collisions || !m.slotMap().segment.hasCollisionInfo())
|
||||
return true;
|
||||
|
||||
if (m_flags & 7)
|
||||
if (m_numCollRuns)
|
||||
{
|
||||
if (!(m.slotMap().segment.flags() & Segment::SEG_INITCOLLISIONS))
|
||||
{
|
||||
m.slotMap().segment.positionSlots(0, 0, 0, true);
|
||||
m.slotMap().segment.positionSlots(0, 0, 0, m.slotMap().dir(), true);
|
||||
// m.slotMap().segment.flags(m.slotMap().segment.flags() | Segment::SEG_INITCOLLISIONS);
|
||||
}
|
||||
if (!collisionShift(&m.slotMap().segment, m.slotMap().segment.dir(), fsm.dbgout))
|
||||
if (!collisionShift(&m.slotMap().segment, m.slotMap().dir(), fsm.dbgout))
|
||||
return false;
|
||||
}
|
||||
if ((m_flags & 24) && !collisionKern(&m.slotMap().segment, m.slotMap().segment.dir(), fsm.dbgout))
|
||||
if ((m_kernColls) && !collisionKern(&m.slotMap().segment, m.slotMap().dir(), fsm.dbgout))
|
||||
return false;
|
||||
if ((m_flags & 15) && !collisionFinish(&m.slotMap().segment, fsm.dbgout))
|
||||
if (collisions && !collisionFinish(&m.slotMap().segment, fsm.dbgout))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -478,8 +500,8 @@ void Pass::findNDoRule(Slot * & slot, Machine &m, FiniteStateMachine & fsm) cons
|
|||
if (r != re)
|
||||
{
|
||||
const int adv = doAction(r->rule->action, slot, m);
|
||||
dumpRuleEventOutput(fsm, *r->rule, slot);
|
||||
if (r->rule->action->deletes()) fsm.slots.collectGarbage();
|
||||
dumpRuleEventOutput(fsm, m, *r->rule, slot);
|
||||
if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot);
|
||||
adjustSlot(adv, slot, fsm.slots);
|
||||
*fsm.dbgout << "cursor" << objectid(dslot(&fsm.slots.segment, slot))
|
||||
<< json::close; // Close RuelEvent object
|
||||
|
@ -501,7 +523,7 @@ void Pass::findNDoRule(Slot * & slot, Machine &m, FiniteStateMachine & fsm) cons
|
|||
if (r != re)
|
||||
{
|
||||
const int adv = doAction(r->rule->action, slot, m);
|
||||
if (r->rule->action->deletes()) fsm.slots.collectGarbage();
|
||||
if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot);
|
||||
adjustSlot(adv, slot, fsm.slots);
|
||||
return;
|
||||
}
|
||||
|
@ -533,7 +555,7 @@ void Pass::dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEnt
|
|||
}
|
||||
|
||||
|
||||
void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * const last_slot) const
|
||||
void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, Machine & m, const Rule & r, Slot * const last_slot) const
|
||||
{
|
||||
*fsm.dbgout << json::item << json::flat << json::object
|
||||
<< "id" << &r - m_rules
|
||||
|
@ -551,7 +573,7 @@ void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, S
|
|||
<< json::close // close "input"
|
||||
<< "slots" << json::array;
|
||||
const Position rsb_prepos = last_slot ? last_slot->origin() : fsm.slots.segment.advance();
|
||||
fsm.slots.segment.positionSlots(0);
|
||||
fsm.slots.segment.positionSlots(0, 0, 0, m.slotMap().dir());
|
||||
|
||||
for(Slot * slot = output_slot(fsm.slots, 0); slot != last_slot; slot = slot->next())
|
||||
*fsm.dbgout << dslot(&fsm.slots.segment, slot);
|
||||
|
@ -607,12 +629,16 @@ bool Pass::testConstraint(const Rule & r, Machine & m) const
|
|||
}
|
||||
|
||||
|
||||
void SlotMap::collectGarbage()
|
||||
void SlotMap::collectGarbage(Slot * &aSlot)
|
||||
{
|
||||
for(Slot **s = begin(), *const *const se = end() - 1; s != se; ++s) {
|
||||
Slot *& slot = *s;
|
||||
if(slot->isDeleted() || slot->isCopied())
|
||||
{
|
||||
if (slot == aSlot)
|
||||
aSlot = slot->prev() ? slot->prev() : slot->next();
|
||||
segment.freeSlot(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -681,7 +707,6 @@ bool Pass::collisionShift(Segment *seg, int dir, json * const dbgout) const
|
|||
{
|
||||
ShiftCollider shiftcoll(dbgout);
|
||||
// bool isfirst = true;
|
||||
const uint8 numLoops = m_flags & 7; // number of loops permitted to fix collisions; does not include kerning
|
||||
bool hasCollisions = false;
|
||||
Slot *start = seg->first(); // turn on collision fixing for the first slot
|
||||
Slot *end = NULL;
|
||||
|
@ -690,7 +715,7 @@ bool Pass::collisionShift(Segment *seg, int dir, json * const dbgout) const
|
|||
#if !defined GRAPHITE2_NTRACING
|
||||
if (dbgout)
|
||||
*dbgout << "collisions" << json::array
|
||||
<< json::flat << json::object << "num-loops" << numLoops << json::close;
|
||||
<< json::flat << json::object << "num-loops" << m_numCollRuns << json::close;
|
||||
#endif
|
||||
|
||||
while (start)
|
||||
|
@ -707,7 +732,7 @@ bool Pass::collisionShift(Segment *seg, int dir, json * const dbgout) const
|
|||
if (start && (c->flags() & (SlotCollision::COLL_FIX | SlotCollision::COLL_KERN)) == SlotCollision::COLL_FIX
|
||||
&& !resolveCollisions(seg, s, start, shiftcoll, false, dir, moved, hasCollisions, dbgout))
|
||||
return false;
|
||||
if (s != start && c->flags() & SlotCollision::COLL_END)
|
||||
if (s != start && (c->flags() & SlotCollision::COLL_END))
|
||||
{
|
||||
end = s->next();
|
||||
break;
|
||||
|
@ -720,7 +745,7 @@ bool Pass::collisionShift(Segment *seg, int dir, json * const dbgout) const
|
|||
#endif
|
||||
|
||||
// phase 2 : loop until happy.
|
||||
for (int i = 0; i < numLoops - 1; ++i)
|
||||
for (int i = 0; i < m_numCollRuns - 1; ++i)
|
||||
{
|
||||
if (hasCollisions || moved)
|
||||
{
|
||||
|
@ -918,7 +943,7 @@ bool Pass::resolveCollisions(Segment *seg, Slot *slotFix, Slot *start,
|
|||
|| (rtl ^ ignoreForKern)) // or it comes before(ltr) or after(rtl)
|
||||
&& (!isRev // if processing forwards then good to merge otherwise only:
|
||||
|| !(cNbor->flags() & SlotCollision::COLL_FIX) // merge in immovable stuff
|
||||
|| (cNbor->flags() & SlotCollision::COLL_KERN && !sameCluster) // ignore other kernable clusters
|
||||
|| ((cNbor->flags() & SlotCollision::COLL_KERN) && !sameCluster) // ignore other kernable clusters
|
||||
|| (cNbor->flags() & SlotCollision::COLL_ISCOL)) // test against other collided glyphs
|
||||
&& !coll.mergeSlot(seg, nbor, cNbor->shift(), !ignoreForKern, sameCluster, collides, false, dbgout))
|
||||
return false;
|
||||
|
@ -944,7 +969,7 @@ bool Pass::resolveCollisions(Segment *seg, Slot *slotFix, Slot *start,
|
|||
Rect bbox;
|
||||
Position here = slotFix->origin() + shift;
|
||||
float clusterMin = here.x;
|
||||
slotFix->firstChild()->finalise(seg, NULL, here, bbox, 0, clusterMin, false);
|
||||
slotFix->firstChild()->finalise(seg, NULL, here, bbox, 0, clusterMin, rtl, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1002,7 +1027,7 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start
|
|||
SlotCollision *cNbor = seg->collisionInfo(nbor);
|
||||
if (bb.bl.y == 0.f && bb.tr.y == 0.f)
|
||||
{
|
||||
if ((m_flags & 24) == 16)
|
||||
if (m_kernColls == InWord)
|
||||
break;
|
||||
// Add space for a space glyph.
|
||||
currSpace += nbor->advance();
|
||||
|
|
|
@ -40,7 +40,7 @@ using namespace graphite2;
|
|||
|
||||
SegCache::SegCache(const SegCacheStore * store, const Features & feats)
|
||||
: m_prefixLength(ePrefixLength),
|
||||
m_maxCachedSegLength(eMaxSpliceSize),
|
||||
// m_maxCachedSegLength(eMaxSpliceSize),
|
||||
m_segmentCount(0),
|
||||
m_features(feats),
|
||||
m_totalAccessCount(0l), m_totalMisses(0l),
|
||||
|
@ -84,7 +84,7 @@ SegCacheEntry* SegCache::cache(SegCacheStore * store, const uint16* cmapGlyphs,
|
|||
{
|
||||
uint16 pos = 0;
|
||||
if (!length) return NULL;
|
||||
assert(length < m_maxCachedSegLength);
|
||||
// assert(length < m_maxCachedSegLength);
|
||||
SegCachePrefixArray pArray = m_prefixes;
|
||||
while (pos + 1 < m_prefixLength)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@ of the License or (at your option) any later version.
|
|||
#include "inc/Slot.h"
|
||||
#include "inc/Main.h"
|
||||
#include "inc/CmapCache.h"
|
||||
#include "inc/Bidi.h"
|
||||
//#include "inc/Bidi.h"
|
||||
#include "inc/Collider.h"
|
||||
#include "graphite2/Segment.h"
|
||||
|
||||
|
@ -68,8 +68,10 @@ Segment::~Segment()
|
|||
{
|
||||
for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
|
||||
free(*i);
|
||||
for (AttributeRope::iterator j = m_userAttrs.begin(); j != m_userAttrs.end(); ++j)
|
||||
free(*j);
|
||||
for (AttributeRope::iterator i = m_userAttrs.begin(); i != m_userAttrs.end(); ++i)
|
||||
free(*i);
|
||||
for (JustifyRope::iterator i = m_justifies.begin(); i != m_justifies.end(); ++i)
|
||||
free(*i);
|
||||
delete[] m_charinfo;
|
||||
}
|
||||
|
||||
|
@ -154,6 +156,12 @@ void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
|
|||
aSlot->originate(id);
|
||||
aSlot->before(id);
|
||||
aSlot->after(id);
|
||||
// uint8 aBidi = m_silf->aBidi();
|
||||
// if (aBidi != 0xFF)
|
||||
// {
|
||||
// unsigned int bAttr = glyphAttr(gid, aBidi);
|
||||
// aSlot->setBidiClass((bAttr <= 22) * bAttr);
|
||||
// }
|
||||
if (m_last) m_last->next(aSlot);
|
||||
aSlot->prev(m_last);
|
||||
m_last = aSlot;
|
||||
|
@ -167,6 +175,9 @@ Slot *Segment::newSlot()
|
|||
{
|
||||
if (!m_freeSlots)
|
||||
{
|
||||
// check that the segment doesn't grow indefinintely
|
||||
if (m_numGlyphs > m_numCharinfo * MAX_SEG_GROWTH_FACTOR)
|
||||
return NULL;
|
||||
int numUser = m_silf->numUser();
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
if (m_face->logger()) ++numUser;
|
||||
|
@ -176,9 +187,8 @@ Slot *Segment::newSlot()
|
|||
if (!newSlots || !newAttrs) return NULL;
|
||||
for (size_t i = 0; i < m_bufSize; i++)
|
||||
{
|
||||
::new (newSlots + i) Slot(newAttrs + i * numUser);
|
||||
newSlots[i].next(newSlots + i + 1);
|
||||
newSlots[i].userAttrs(newAttrs + i * numUser);
|
||||
newSlots[i].setBidiClass(-1);
|
||||
}
|
||||
newSlots[m_bufSize - 1].next(NULL);
|
||||
newSlots[0].next(NULL);
|
||||
|
@ -205,7 +215,7 @@ void Segment::freeSlot(Slot *aSlot)
|
|||
aSlot->removeChild(aSlot->firstChild());
|
||||
}
|
||||
// reset the slot incase it is reused
|
||||
::new (aSlot) Slot;
|
||||
::new (aSlot) Slot(aSlot->userAttrs());
|
||||
memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
|
||||
// Update generation counter for debug
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
|
@ -309,6 +319,61 @@ void Segment::splice(size_t offset, size_t length, Slot * const startSlot,
|
|||
}
|
||||
#endif // GRAPHITE2_NSEGCACHE
|
||||
|
||||
// reverse the slots but keep diacritics in their same position after their bases
|
||||
void Segment::reverseSlots()
|
||||
{
|
||||
m_dir = m_dir ^ 64; // invert the reverse flag
|
||||
if (m_first == m_last) return; // skip 0 or 1 glyph runs
|
||||
|
||||
Slot *t = 0;
|
||||
Slot *curr = m_first;
|
||||
Slot *tlast;
|
||||
Slot *tfirst;
|
||||
Slot *out = 0;
|
||||
|
||||
while (curr && getSlotBidiClass(curr) == 16)
|
||||
curr = curr->next();
|
||||
if (!curr) return;
|
||||
tfirst = curr->prev();
|
||||
tlast = curr;
|
||||
|
||||
while (curr)
|
||||
{
|
||||
if (getSlotBidiClass(curr) == 16)
|
||||
{
|
||||
Slot *d = curr->next();
|
||||
while (d && getSlotBidiClass(d) == 16)
|
||||
d = d->next();
|
||||
|
||||
d = d ? d->prev() : m_last;
|
||||
Slot *p = out->next(); // one after the diacritics. out can't be null
|
||||
if (p)
|
||||
p->prev(d);
|
||||
else
|
||||
tlast = d;
|
||||
t = d->next();
|
||||
d->next(p);
|
||||
curr->prev(out);
|
||||
out->next(curr);
|
||||
}
|
||||
else // will always fire first time round the loop
|
||||
{
|
||||
if (out)
|
||||
out->prev(curr);
|
||||
t = curr->next();
|
||||
curr->next(out);
|
||||
out = curr;
|
||||
}
|
||||
curr = t;
|
||||
}
|
||||
out->prev(tfirst);
|
||||
if (tfirst)
|
||||
tfirst->next(out);
|
||||
else
|
||||
m_first = out;
|
||||
m_last = tlast;
|
||||
}
|
||||
|
||||
void Segment::linkClusters(Slot *s, Slot * end)
|
||||
{
|
||||
end = end->next();
|
||||
|
@ -338,7 +403,7 @@ void Segment::linkClusters(Slot *s, Slot * end)
|
|||
}
|
||||
}
|
||||
|
||||
Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bool isFinal)
|
||||
Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bool isRtl, bool isFinal)
|
||||
{
|
||||
Position currpos(0., 0.);
|
||||
float clusterMin = 0.;
|
||||
|
@ -347,12 +412,12 @@ Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bo
|
|||
if (!iStart) iStart = m_first;
|
||||
if (!iEnd) iEnd = m_last;
|
||||
|
||||
if (m_dir & 1)
|
||||
if (isRtl)
|
||||
{
|
||||
for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
|
||||
{
|
||||
if (s->isBase())
|
||||
currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isFinal);
|
||||
currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -360,7 +425,7 @@ Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bo
|
|||
for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
|
||||
{
|
||||
if (s->isBase())
|
||||
currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isFinal);
|
||||
currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
|
||||
}
|
||||
}
|
||||
return currpos;
|
||||
|
@ -437,12 +502,13 @@ bool Segment::read_text(const Face *face, const Features* pFeats/*must not be NU
|
|||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Slot *process_bidi(Slot *start, int level, int prelevel, int &nextLevel, int dirover, int isol, int &cisol, int &isolerr, int &embederr, int init, Segment *seg, uint8 aMirror, BracketPairStack &stack);
|
||||
void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror);
|
||||
void resolveWhitespace(int baseLevel, Slot *s);
|
||||
Slot *resolveOrder(Slot * & s, const bool reordered, const int level = 0);
|
||||
|
||||
void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
|
||||
void Segment::bidiPass(int paradir, uint8 aMirror)
|
||||
{
|
||||
if (slotCount() == 0)
|
||||
return;
|
||||
|
@ -453,11 +519,8 @@ void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
|
|||
unsigned int ssize = 0;
|
||||
for (s = first(); s; s = s->next())
|
||||
{
|
||||
if (s->getBidiClass() == -1)
|
||||
{
|
||||
unsigned int bAttr = glyphAttr(s->gid(), aBidi);
|
||||
s->setBidiClass((bAttr <= 22) * bAttr);
|
||||
}
|
||||
if (getSlotBidiClass(s) < 0)
|
||||
s->setBidiClass(0);
|
||||
bmask |= (1 << s->getBidiClass());
|
||||
s->setBidiLevel(baseLevel);
|
||||
if (s->getBidiClass() == 21)
|
||||
|
@ -489,6 +552,18 @@ void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Segment::doMirror(uint16 aMirror)
|
||||
{
|
||||
Slot * s;
|
||||
for (s = m_first; s; s = s->next())
|
||||
{
|
||||
unsigned short g = glyphAttr(s->gid(), aMirror);
|
||||
if (g && (!(dir() & 4) || !glyphAttr(s->gid(), aMirror + 1)))
|
||||
s->setGlyph(this, g);
|
||||
}
|
||||
}
|
||||
|
||||
bool Segment::initCollisions()
|
||||
{
|
||||
|
|
|
@ -51,6 +51,7 @@ Silf::Silf() throw()
|
|||
m_jPass(0),
|
||||
m_bPass(0),
|
||||
m_flags(0),
|
||||
m_dir(0),
|
||||
m_aPseudo(0),
|
||||
m_aBreak(0),
|
||||
m_aUser(0),
|
||||
|
@ -58,6 +59,7 @@ Silf::Silf() throw()
|
|||
m_aMirror(0),
|
||||
m_aPassBits(0),
|
||||
m_iMaxComp(0),
|
||||
m_aCollision(0),
|
||||
m_aLig(0),
|
||||
m_numPseudo(0),
|
||||
m_nClass(0),
|
||||
|
@ -141,10 +143,10 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face,
|
|||
}
|
||||
|
||||
if (e.test(p + sizeof(uint16) + sizeof(uint8)*8 >= silf_end, E_BADENDJUSTS)) { releaseBuffers(); return face.error(e); }
|
||||
m_aLig = be::read<uint16>(p);
|
||||
m_aUser = be::read<uint8>(p);
|
||||
m_iMaxComp = be::read<uint8>(p);
|
||||
be::skip<byte>(p); // direction
|
||||
m_aLig = be::read<uint16>(p);
|
||||
m_aUser = be::read<uint8>(p);
|
||||
m_iMaxComp = be::read<uint8>(p);
|
||||
m_dir = be::read<uint8>(p) - 1;
|
||||
m_aCollision = be::read<uint8>(p);
|
||||
be::skip<byte>(p,3);
|
||||
be::skip<uint16>(p, be::read<uint8>(p)); // don't need critical features yet
|
||||
|
@ -198,7 +200,9 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face,
|
|||
const byte * const pass_start = silf_start + be::read<uint32>(o_passes),
|
||||
* const pass_end = silf_start + be::peek<uint32>(o_passes);
|
||||
face.error_context((face.error_context() & 0xFF00) + EC_ASILF + (i << 16));
|
||||
if (e.test(pass_start > pass_end, E_BADPASSSTART) || e.test(pass_end > silf_end, E_BADPASSEND)) {
|
||||
if (e.test(pass_start > pass_end, E_BADPASSSTART)
|
||||
|| e.test(pass_start < passes_start, E_BADPASSSTART)
|
||||
|| e.test(pass_end > silf_end, E_BADPASSEND)) {
|
||||
releaseBuffers(); return face.error(e);
|
||||
}
|
||||
|
||||
|
@ -268,6 +272,9 @@ size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version, Error
|
|||
|
||||
if (max_off == ERROROFFSET) return ERROROFFSET;
|
||||
|
||||
if (e.test((int)max_off < m_nLinear + (m_nClass - m_nLinear) * 6, E_CLASSESTOOBIG))
|
||||
return ERROROFFSET;
|
||||
|
||||
// Check the linear offsets are sane, these must be monotonically increasing.
|
||||
for (const uint32 *o = m_classOffsets, * const o_end = o + m_nLinear; o != o_end; ++o)
|
||||
if (e.test(o[0] > o[1], E_BADCLASSOFFSET))
|
||||
|
@ -283,10 +290,10 @@ size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version, Error
|
|||
for (const uint32 *o = m_classOffsets + m_nLinear, * const o_end = m_classOffsets + m_nClass; o != o_end; ++o)
|
||||
{
|
||||
const uint16 * lookup = m_classData + *o;
|
||||
if (e.test(*o > max_off - 4, E_HIGHCLASSOFFSET) // LookupClass doesn't stretch over max_off
|
||||
if (e.test(*o + 4 > max_off, E_HIGHCLASSOFFSET) // LookupClass doesn't stretch over max_off
|
||||
|| e.test(lookup[0] == 0 // A LookupClass with no looks is a suspicious thing ...
|
||||
|| lookup[0] > (max_off - *o - 4)/2 // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off]
|
||||
|| lookup[3] != lookup[0] - lookup[1], E_BADCLASSLOOKUPINFO)) // rangeShift: numIDs - searchRange
|
||||
|| lookup[0] * 2 + *o + 4 > max_off // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off]
|
||||
|| lookup[3] + lookup[1] != lookup[0], E_BADCLASSLOOKUPINFO)) // rangeShift: numIDs - searchRange
|
||||
return ERROROFFSET;
|
||||
}
|
||||
|
||||
|
@ -307,7 +314,7 @@ uint16 Silf::findClassIndex(uint16 cid, uint16 gid) const
|
|||
const uint16 * cls = m_classData + m_classOffsets[cid];
|
||||
if (cid < m_nLinear) // output class being used for input, shouldn't happen
|
||||
{
|
||||
for (unsigned int i = 0, n = m_classOffsets[cid + 1]; i < n; ++i, ++cls)
|
||||
for (unsigned int i = 0, n = m_classOffsets[cid + 1] - m_classOffsets[cid]; i < n; ++i, ++cls)
|
||||
if (*cls == gid) return i;
|
||||
return -1;
|
||||
}
|
||||
|
@ -348,7 +355,7 @@ uint16 Silf::getClassGlyph(uint16 cid, unsigned int index) const
|
|||
bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi) const
|
||||
{
|
||||
assert(seg != 0);
|
||||
SlotMap map(*seg);
|
||||
SlotMap map(*seg, m_dir);
|
||||
FiniteStateMachine fsm(map, seg->getFace()->logger());
|
||||
vm::Machine m(map);
|
||||
unsigned int initSize = seg->slotCount();
|
||||
|
@ -363,7 +370,7 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi
|
|||
return true;
|
||||
lastPass = m_numPasses;
|
||||
}
|
||||
if (firstPass <= lbidi && lastPass >= lbidi && dobidi)
|
||||
if ((firstPass < lbidi || (dobidi && firstPass == lbidi)) && (lastPass >= lbidi || (dobidi && lastPass + 1 == lbidi)))
|
||||
lastPass++;
|
||||
else
|
||||
lbidi = 0xFF;
|
||||
|
@ -379,7 +386,7 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi
|
|||
*dbgout << json::item << json::object
|
||||
<< "id" << -1
|
||||
<< "slots" << json::array;
|
||||
seg->positionSlots(0);
|
||||
seg->positionSlots(0, 0, 0, m_dir);
|
||||
for(Slot * s = seg->first(); s; s = s->next())
|
||||
*dbgout << dslot(seg, s);
|
||||
*dbgout << json::close
|
||||
|
@ -387,22 +394,13 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi
|
|||
<< json::close;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(seg->dir() & 2))
|
||||
seg->bidiPass(m_aBidi, seg->dir() & 1, m_aMirror);
|
||||
else if (m_aMirror && (seg->dir() & 1))
|
||||
{
|
||||
Slot * s;
|
||||
for (s = seg->first(); s; s = s->next())
|
||||
{
|
||||
unsigned short g = seg->glyphAttr(s->gid(), m_aMirror);
|
||||
if (g && (!(seg->dir() & 4) || !seg->glyphAttr(s->gid(), m_aMirror + 1)))
|
||||
s->setGlyph(seg, g);
|
||||
}
|
||||
}
|
||||
if (seg->currdir() != m_dir)
|
||||
seg->reverseSlots();
|
||||
if (m_aMirror && (seg->dir() & 3) == 3)
|
||||
seg->doMirror(m_aMirror);
|
||||
--i;
|
||||
lbidi = lastPass;
|
||||
--lastPass;
|
||||
lbidi = 0xFF;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -412,7 +410,7 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi
|
|||
*dbgout << json::item << json::object
|
||||
<< "id" << i+1
|
||||
<< "slots" << json::array;
|
||||
seg->positionSlots(0);
|
||||
seg->positionSlots(0, 0, 0, m_dir);
|
||||
for(Slot * s = seg->first(); s; s = s->next())
|
||||
*dbgout << dslot(seg, s);
|
||||
*dbgout << json::close;
|
||||
|
@ -420,13 +418,13 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi
|
|||
#endif
|
||||
|
||||
// test whether to reorder, prepare for positioning
|
||||
if ((i >= 32 || (seg->passBits() & (1 << i)) == 0 || (m_passes[i].flags() & 7))
|
||||
&& !m_passes[i].runGraphite(m, fsm))
|
||||
bool reverse = (lbidi == 0xFF) && (seg->currdir() != ((m_dir & 1) ^ m_passes[i].reverseDir()));
|
||||
if ((i >= 32 || (seg->passBits() & (1 << i)) == 0 || m_passes[i].collisionLoops())
|
||||
&& !m_passes[i].runGraphite(m, fsm, reverse))
|
||||
return false;
|
||||
// only subsitution passes can change segment length, cached subsegments are short for their text
|
||||
if (m.status() != vm::Machine::finished
|
||||
|| (i < m_pPass && (seg->slotCount() > initSize * MAX_SEG_GROWTH_FACTOR
|
||||
|| (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize))))
|
||||
|| (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -34,15 +34,14 @@ of the License or (at your option) any later version.
|
|||
|
||||
using namespace graphite2;
|
||||
|
||||
Slot::Slot() :
|
||||
Slot::Slot(int16 *user_attrs) :
|
||||
m_next(NULL), m_prev(NULL),
|
||||
m_glyphid(0), m_realglyphid(0), m_original(0), m_before(0), m_after(0),
|
||||
m_index(0), m_parent(NULL), m_child(NULL), m_sibling(NULL),
|
||||
m_position(0, 0), m_shift(0, 0), m_advance(0, 0),
|
||||
m_attach(0, 0), m_with(0, 0), m_just(0.),
|
||||
m_flags(0), m_attLevel(0), m_bidiCls(-1), m_bidiLevel(0), m_justs(NULL)
|
||||
// Do not set m_userAttr since it is set *before* new is called since this
|
||||
// is used as a positional new to reset the GrSlot
|
||||
m_flags(0), m_attLevel(0), m_bidiCls(-1), m_bidiLevel(0),
|
||||
m_userAttr(user_attrs), m_justs(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -86,17 +85,17 @@ void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos)
|
|||
m_position = m_position + relpos;
|
||||
}
|
||||
|
||||
Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool isFinal)
|
||||
Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal)
|
||||
{
|
||||
SlotCollision *coll = NULL;
|
||||
if (attrLevel && m_attLevel > attrLevel) return Position(0, 0);
|
||||
float scale = font ? font->scale() : 1.0f;
|
||||
Position shift(m_shift.x * ((seg->dir() & 1) * -2 + 1) + m_just, m_shift.y);
|
||||
Position shift(m_shift.x * (rtl * -2 + 1) + m_just, m_shift.y);
|
||||
float tAdvance = m_advance.x + m_just;
|
||||
if (isFinal && (coll = seg->collisionInfo(this)))
|
||||
{
|
||||
const Position &collshift = coll->offset();
|
||||
if (!(coll->flags() & SlotCollision::COLL_KERN) || (seg->dir() & 1))
|
||||
if (!(coll->flags() & SlotCollision::COLL_KERN) || rtl)
|
||||
shift = shift + collshift;
|
||||
}
|
||||
const GlyphFace * glyphFace = seg->getFace()->glyphs().glyphSafe(glyph());
|
||||
|
@ -134,13 +133,13 @@ Position Slot::finalise(const Segment *seg, const Font *font, Position & base, R
|
|||
|
||||
if (m_child && m_child != this && m_child->attachedTo() == this)
|
||||
{
|
||||
Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin, isFinal);
|
||||
Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin, rtl, isFinal);
|
||||
if ((!m_parent || m_advance.x >= 0.5f) && tRes.x > res.x) res = tRes;
|
||||
}
|
||||
|
||||
if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent)
|
||||
{
|
||||
Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin, isFinal);
|
||||
Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin, rtl, isFinal);
|
||||
if (tRes.x > res.x) res = tRes;
|
||||
}
|
||||
|
||||
|
@ -154,12 +153,14 @@ Position Slot::finalise(const Segment *seg, const Font *font, Position & base, R
|
|||
return res;
|
||||
}
|
||||
|
||||
int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
|
||||
int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel, bool rtl)
|
||||
{
|
||||
Position base;
|
||||
if (glyph() >= seg->getFace()->glyphs().numGlyphs())
|
||||
return 0;
|
||||
Rect bbox = seg->theGlyphBBoxTemporary(glyph());
|
||||
float clusterMin = 0.;
|
||||
Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin, false);
|
||||
Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin, rtl, false);
|
||||
|
||||
switch (metrics(metric))
|
||||
{
|
||||
|
@ -192,7 +193,6 @@ int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
|
|||
|
||||
int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
|
||||
{
|
||||
if (!this) return 0;
|
||||
if (ind == gr_slatUserDefnV1)
|
||||
{
|
||||
ind = gr_slatUserDefn;
|
||||
|
@ -220,9 +220,7 @@ int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
|
|||
case gr_slatAttLevel : return m_attLevel;
|
||||
case gr_slatBreak : return seg->charinfo(m_original)->breakWeight();
|
||||
case gr_slatCompRef : return 0;
|
||||
case gr_slatDir : if (m_bidiCls == -1)
|
||||
const_cast<Slot *>(this)->setBidiClass(int8(seg->glyphAttr(gid(), seg->silf()->aBidi())));
|
||||
return m_bidiCls;
|
||||
case gr_slatDir : return seg->dir() & 1;
|
||||
case gr_slatInsert : return isInsertBefore();
|
||||
case gr_slatPosX : return int(m_position.x); // but need to calculate it
|
||||
case gr_slatPosY : return int(m_position.y);
|
||||
|
@ -272,7 +270,6 @@ int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
|
|||
|
||||
void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
|
||||
{
|
||||
if (!this) return;
|
||||
if (ind == gr_slatUserDefnV1)
|
||||
{
|
||||
ind = gr_slatUserDefn;
|
||||
|
@ -299,7 +296,7 @@ void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, cons
|
|||
if (!other->isChildOf(this) && other->child(this))
|
||||
{
|
||||
attachTo(other);
|
||||
if (((seg->dir() & 1) != 0) ^ (idx > subindex))
|
||||
if ((map.dir() != 0) ^ (idx > subindex))
|
||||
m_with = Position(advance(), 0);
|
||||
else // normal match to previous root
|
||||
m_attach = Position(other->advance(), 0);
|
||||
|
@ -322,7 +319,7 @@ void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, cons
|
|||
seg->charinfo(m_original)->breakWeight(value);
|
||||
break;
|
||||
case gr_slatCompRef : break; // not sure what to do here
|
||||
case gr_slatDir : m_bidiCls = int8(value); break;
|
||||
case gr_slatDir : break;
|
||||
case gr_slatInsert :
|
||||
markInsertBefore(value? true : false);
|
||||
break;
|
||||
|
@ -450,6 +447,7 @@ bool Slot::removeSibling(Slot *ap)
|
|||
void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
|
||||
{
|
||||
m_glyphid = glyphid;
|
||||
m_bidiCls = -1;
|
||||
if (!theGlyph)
|
||||
{
|
||||
theGlyph = seg->getFace()->glyphs().glyphSafe(glyphid);
|
||||
|
@ -461,6 +459,8 @@ void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
|
|||
}
|
||||
}
|
||||
m_realglyphid = theGlyph->attrs()[seg->silf()->aPseudo()];
|
||||
if (m_realglyphid > seg->getFace()->glyphs().numGlyphs())
|
||||
m_realglyphid = 0;
|
||||
const GlyphFace *aGlyph = theGlyph;
|
||||
if (m_realglyphid)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@ of the License or (at your option) any later version.
|
|||
|
||||
using namespace graphite2;
|
||||
|
||||
sparse::chunk sparse::empty_chunk = {0,0};
|
||||
const sparse::chunk sparse::empty_chunk = {0,0};
|
||||
|
||||
sparse::~sparse() throw()
|
||||
{
|
||||
|
|
|
@ -62,8 +62,10 @@ Description
|
|||
***********************************************************************************************/
|
||||
namespace
|
||||
{
|
||||
#ifdef ALL_TTFUTILS
|
||||
// max number of components allowed in composite glyphs
|
||||
const int kMaxGlyphComponents = 8;
|
||||
#endif
|
||||
|
||||
template <int R, typename T>
|
||||
inline float fixed_to_float(const T f) {
|
||||
|
@ -227,7 +229,7 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
|
|||
{
|
||||
using namespace Sfnt;
|
||||
|
||||
if (pTable == 0) return false;
|
||||
if (pTable == 0 || lTableSize < 4) return false;
|
||||
|
||||
switch(TableId)
|
||||
{
|
||||
|
@ -235,6 +237,8 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
|
|||
{
|
||||
const Sfnt::CharacterCodeMap * const pCmap
|
||||
= reinterpret_cast<const Sfnt::CharacterCodeMap *>(pTable);
|
||||
if (lTableSize < sizeof(Sfnt::CharacterCodeMap))
|
||||
return false;
|
||||
return be::swap(pCmap->version) == 0;
|
||||
}
|
||||
|
||||
|
@ -242,6 +246,8 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
|
|||
{
|
||||
const Sfnt::FontHeader * const pHead
|
||||
= reinterpret_cast<const Sfnt::FontHeader *>(pTable);
|
||||
if (lTableSize < sizeof(Sfnt::FontHeader))
|
||||
return false;
|
||||
bool r = be::swap(pHead->version) == OneFix
|
||||
&& be::swap(pHead->magic_number) == FontHeader::MagicNumber
|
||||
&& be::swap(pHead->glyph_data_format)
|
||||
|
@ -258,6 +264,8 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
|
|||
{
|
||||
const Sfnt::PostScriptGlyphName * const pPost
|
||||
= reinterpret_cast<const Sfnt::PostScriptGlyphName *>(pTable);
|
||||
if (lTableSize < sizeof(Sfnt::PostScriptGlyphName))
|
||||
return false;
|
||||
const fixed format = be::swap(pPost->format);
|
||||
bool r = format == PostScriptGlyphName::Format1
|
||||
|| format == PostScriptGlyphName::Format2
|
||||
|
@ -270,6 +278,8 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
|
|||
{
|
||||
const Sfnt::HorizontalHeader * pHhea =
|
||||
reinterpret_cast<const Sfnt::HorizontalHeader *>(pTable);
|
||||
if (lTableSize < sizeof(Sfnt::HorizontalHeader))
|
||||
return false;
|
||||
bool r = be::swap(pHhea->version) == OneFix
|
||||
&& be::swap(pHhea->metric_data_format) == 0
|
||||
&& sizeof (Sfnt::HorizontalHeader) <= lTableSize;
|
||||
|
@ -280,6 +290,8 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
|
|||
{
|
||||
const Sfnt::MaximumProfile * pMaxp =
|
||||
reinterpret_cast<const Sfnt::MaximumProfile *>(pTable);
|
||||
if (lTableSize < sizeof(Sfnt::MaximumProfile))
|
||||
return false;
|
||||
bool r = be::swap(pMaxp->version) == OneFix
|
||||
&& sizeof(Sfnt::MaximumProfile) <= lTableSize;
|
||||
return r;
|
||||
|
@ -324,6 +336,8 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
|
|||
{
|
||||
const Sfnt::FontNames * pName
|
||||
= reinterpret_cast<const Sfnt::FontNames *>(pTable);
|
||||
if (lTableSize < sizeof(Sfnt::FontNames))
|
||||
return false;
|
||||
return be::swap(pName->format) == 0;
|
||||
}
|
||||
|
||||
|
@ -796,7 +810,7 @@ bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, const void
|
|||
size_t cLongHorMetrics = be::swap(phhea->num_long_hor_metrics);
|
||||
if (nGlyphId < cLongHorMetrics)
|
||||
{ // glyph id is acceptable
|
||||
if (nGlyphId * sizeof(Sfnt::HorizontalMetric) >= lHmtxSize) return false;
|
||||
if ((nGlyphId + 1) * sizeof(Sfnt::HorizontalMetric) > lHmtxSize) return false;
|
||||
nAdvWid = be::swap(phmtx[nGlyphId].advance_width);
|
||||
nLsb = be::swap(phmtx[nGlyphId].left_side_bearing);
|
||||
}
|
||||
|
@ -806,7 +820,7 @@ bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, const void
|
|||
size_t lLsbOffset = sizeof(Sfnt::HorizontalMetric) * cLongHorMetrics +
|
||||
sizeof(int16) * (nGlyphId - cLongHorMetrics); // offset in bytes
|
||||
// We test like this as LsbOffset is an offset not a length.
|
||||
if (lLsbOffset > lHmtxSize - sizeof(int16))
|
||||
if (lLsbOffset >= lHmtxSize - sizeof(int16) || cLongHorMetrics == 0)
|
||||
{
|
||||
nLsb = 0;
|
||||
return false;
|
||||
|
@ -873,7 +887,7 @@ const void * FindCmapSubtable(const void * pCmap, int nPlatformId, /* =3 */ int
|
|||
/*----------------------------------------------------------------------------------------------
|
||||
Check the Microsoft Unicode subtable for expected values
|
||||
----------------------------------------------------------------------------------------------*/
|
||||
bool CheckCmapSubtable4(const void * pCmapSubtable4 /*, unsigned int maxgid*/)
|
||||
bool CheckCmapSubtable4(const void * pCmapSubtable4, size_t table_len /*, unsigned int maxgid*/)
|
||||
{
|
||||
if (!pCmapSubtable4) return false;
|
||||
const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable4);
|
||||
|
@ -882,6 +896,8 @@ bool CheckCmapSubtable4(const void * pCmapSubtable4 /*, unsigned int maxgid*/)
|
|||
if (be::swap(pTable->format) != 4) return false;
|
||||
const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtable4);
|
||||
uint16 length = be::swap(pTable4->length);
|
||||
if (length > table_len)
|
||||
return false;
|
||||
if (length < sizeof(Sfnt::CmapSubTableFormat4))
|
||||
return false;
|
||||
uint16 nRanges = be::swap(pTable4->seg_count_x2) >> 1;
|
||||
|
@ -919,7 +935,7 @@ bool CheckCmapSubtable4(const void * pCmapSubtable4 /*, unsigned int maxgid*/)
|
|||
lastend = end;
|
||||
}
|
||||
#endif
|
||||
return true;;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------------------------
|
||||
|
@ -1062,7 +1078,7 @@ unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnico
|
|||
/*----------------------------------------------------------------------------------------------
|
||||
Check the Microsoft UCS-4 subtable for expected values.
|
||||
----------------------------------------------------------------------------------------------*/
|
||||
bool CheckCmapSubtable12(const void *pCmapSubtable12 /*, unsigned int maxgid*/)
|
||||
bool CheckCmapSubtable12(const void *pCmapSubtable12, size_t table_len /*, unsigned int maxgid*/)
|
||||
{
|
||||
if (!pCmapSubtable12) return false;
|
||||
const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable12);
|
||||
|
@ -1070,6 +1086,8 @@ bool CheckCmapSubtable12(const void *pCmapSubtable12 /*, unsigned int maxgid*/)
|
|||
return false;
|
||||
const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmapSubtable12);
|
||||
uint32 length = be::swap(pTable12->length);
|
||||
if (length > table_len)
|
||||
return false;
|
||||
if (length < sizeof(Sfnt::CmapSubTableFormat12))
|
||||
return false;
|
||||
uint32 num_groups = be::swap(pTable12->num_groups);
|
||||
|
@ -1221,7 +1239,7 @@ size_t LocaLookup(gid16 nGlyphId,
|
|||
void * GlyfLookup(const void * pGlyf, size_t nGlyfOffset, size_t nTableLen)
|
||||
{
|
||||
const uint8 * pByte = reinterpret_cast<const uint8 *>(pGlyf);
|
||||
if (nGlyfOffset == size_t(-1) || nGlyfOffset == size_t(-2) || nGlyfOffset >= nTableLen)
|
||||
if (nGlyfOffset + pByte < pByte || nGlyfOffset + sizeof(Sfnt::Glyph) >= nTableLen)
|
||||
return NULL;
|
||||
return const_cast<uint8 *>(pByte + nGlyfOffset);
|
||||
}
|
||||
|
@ -1833,7 +1851,6 @@ bool GlyfContourEndPoints(gid16 nGlyphId, const void * pGlyf, const void * pLoca
|
|||
This range is parallel to the prgnX & prgnY
|
||||
Return true if successful, false otherwise. On false, all points may be INT_MIN
|
||||
False may indicate a white space glyph, a multi-level composite, or a corrupt font
|
||||
// TODO: doesn't support composite glyphs whose components are themselves components
|
||||
It's not clear from the TTF spec when the transforms should be applied. Should the
|
||||
transform be done before or after attachment point calcs? (current code - before)
|
||||
Should the transform be applied to other offsets? (currently - no; however commented
|
||||
|
|
|
@ -70,6 +70,7 @@ struct regbank {
|
|||
SlotMap & smap;
|
||||
slotref * const map_base;
|
||||
const instr * & ip;
|
||||
uint8 direction;
|
||||
int8 flags;
|
||||
};
|
||||
|
||||
|
@ -86,6 +87,7 @@ namespace {
|
|||
#define map reg.map
|
||||
#define mapb reg.map_base
|
||||
#define flags reg.flags
|
||||
#define dir reg.direction
|
||||
|
||||
#include "inc/opcodes.h"
|
||||
|
||||
|
@ -96,6 +98,7 @@ namespace {
|
|||
#undef map
|
||||
#undef mapb
|
||||
#undef flags
|
||||
#undef dir
|
||||
}
|
||||
|
||||
Machine::stack_t Machine::run(const instr * program,
|
||||
|
@ -110,7 +113,7 @@ Machine::stack_t Machine::run(const instr * program,
|
|||
const byte * dp = data;
|
||||
stack_t * sp = _stack + Machine::STACK_GUARD,
|
||||
* const sb = sp;
|
||||
regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, 0};
|
||||
regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0};
|
||||
|
||||
// Run the program
|
||||
while ((reinterpret_cast<ip_t>(*++ip))(dp, sp, sb, reg)) {}
|
||||
|
|
|
@ -61,6 +61,7 @@ const void * direct_run(const bool get_table_mode,
|
|||
const byte * data,
|
||||
Machine::stack_t * stack,
|
||||
slotref * & __map,
|
||||
uint8 _dir,
|
||||
SlotMap * __smap=0)
|
||||
{
|
||||
// We need to define and return to opcode table from within this function
|
||||
|
@ -79,6 +80,7 @@ const void * direct_run(const bool get_table_mode,
|
|||
slotref is = *__map,
|
||||
* map = __map,
|
||||
* const mapb = smap.begin()+smap.context();
|
||||
uint8 dir = _dir;
|
||||
int8 flags = 0;
|
||||
|
||||
// start the program
|
||||
|
@ -109,7 +111,7 @@ Machine::stack_t Machine::run(const instr * program,
|
|||
assert(program != 0);
|
||||
|
||||
const stack_t *sp = static_cast<const stack_t *>(
|
||||
direct_run(false, program, data, _stack, is, &_map));
|
||||
direct_run(false, program, data, _stack, is, _map.dir(), &_map));
|
||||
const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
|
||||
check_final_stack(sp);
|
||||
return ret;
|
||||
|
|
|
@ -47,7 +47,6 @@ $(_NS)_SOURCES = \
|
|||
$($(_NS)_BASE)/src/gr_segment.cpp \
|
||||
$($(_NS)_BASE)/src/gr_slot.cpp \
|
||||
$($(_NS)_BASE)/src/json.cpp \
|
||||
$($(_NS)_BASE)/src/Bidi.cpp \
|
||||
$($(_NS)_BASE)/src/CachedFace.cpp \
|
||||
$($(_NS)_BASE)/src/CmapCache.cpp \
|
||||
$($(_NS)_BASE)/src/Code.cpp \
|
||||
|
@ -78,13 +77,12 @@ $(_NS)_PRIVATE_HEADERS = \
|
|||
$($(_NS)_BASE)/src/inc/bits.h \
|
||||
$($(_NS)_BASE)/src/inc/debug.h \
|
||||
$($(_NS)_BASE)/src/inc/json.h \
|
||||
$($(_NS)_BASE)/src/inc/locale2lcid.h \
|
||||
$($(_NS)_BASE)/src/inc/Bidi.h \
|
||||
$($(_NS)_BASE)/src/inc/CachedFace.h \
|
||||
$($(_NS)_BASE)/src/inc/CharInfo.h \
|
||||
$($(_NS)_BASE)/src/inc/CmapCache.h \
|
||||
$($(_NS)_BASE)/src/inc/Code.h \
|
||||
$($(_NS)_BASE)/src/inc/Collider.h \
|
||||
$($(_NS)_BASE)/src/inc/Compression.h \
|
||||
$($(_NS)_BASE)/src/inc/Decompressor.h \
|
||||
$($(_NS)_BASE)/src/inc/Endian.h \
|
||||
$($(_NS)_BASE)/src/inc/Error.h \
|
||||
|
@ -110,7 +108,6 @@ $(_NS)_PRIVATE_HEADERS = \
|
|||
$($(_NS)_BASE)/src/inc/SegCacheEntry.h \
|
||||
$($(_NS)_BASE)/src/inc/SegCacheStore.h \
|
||||
$($(_NS)_BASE)/src/inc/Segment.h \
|
||||
$($(_NS)_BASE)/src/inc/Shrinker.h \
|
||||
$($(_NS)_BASE)/src/inc/Silf.h \
|
||||
$($(_NS)_BASE)/src/inc/Slot.h \
|
||||
$($(_NS)_BASE)/src/inc/Sparse.h \
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace
|
|||
delete pRes;
|
||||
return NULL;
|
||||
}
|
||||
pRes->finalise(font);
|
||||
pRes->finalise(font, true);
|
||||
|
||||
return static_cast<gr_segment*>(pRes);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
static byte * local_memory;
|
||||
class decoder;
|
||||
|
||||
instr * _code;
|
||||
|
@ -87,22 +86,24 @@ private:
|
|||
void failure(const status_t) throw();
|
||||
|
||||
public:
|
||||
static size_t estimateCodeDataOut(size_t num_bytecodes);
|
||||
|
||||
Code() throw();
|
||||
Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
|
||||
uint8 pre_context, uint16 rule_length, const Silf &, const Face &,
|
||||
enum passtype pt, byte * & _out = local_memory);
|
||||
enum passtype pt, byte * * const _out = 0);
|
||||
Code(const Machine::Code &) throw();
|
||||
~Code() throw();
|
||||
|
||||
Code & operator=(const Code &rhs) throw();
|
||||
operator bool () const throw();
|
||||
status_t status() const throw();
|
||||
bool constraint() const throw();
|
||||
size_t dataSize() const throw();
|
||||
size_t instructionCount() const throw();
|
||||
bool immutable() const throw();
|
||||
bool deletes() const throw();
|
||||
size_t maxRef() const throw();
|
||||
operator bool () const throw() { return _code && status() == loaded; }
|
||||
status_t status() const throw() { return _status; }
|
||||
bool constraint() const throw() { return _constraint; }
|
||||
size_t dataSize() const throw() { return _data_size; }
|
||||
size_t instructionCount() const throw() { return _instr_count; }
|
||||
bool immutable() const throw() { return !(_delete || _modify); }
|
||||
bool deletes() const throw() { return _delete; }
|
||||
size_t maxRef() const throw() { return _max_ref; }
|
||||
void externalProgramMoved(ptrdiff_t) throw();
|
||||
|
||||
int32 run(Machine &m, slotref * & map) const;
|
||||
|
@ -110,10 +111,16 @@ public:
|
|||
CLASS_NEW_DELETE;
|
||||
};
|
||||
|
||||
inline
|
||||
size_t Machine::Code::estimateCodeDataOut(size_t n_bc)
|
||||
{
|
||||
return n_bc * (sizeof(instr)+sizeof(byte));
|
||||
}
|
||||
|
||||
|
||||
inline Machine::Code::Code() throw()
|
||||
: _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
|
||||
_status(loaded), _constraint(false), _modify(false),_delete(false),
|
||||
_status(loaded), _constraint(false), _modify(false), _delete(false),
|
||||
_own(false)
|
||||
{
|
||||
}
|
||||
|
@ -149,41 +156,6 @@ inline Machine::Code & Machine::Code::operator=(const Machine::Code &rhs) throw(
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline Machine::Code::operator bool () const throw () {
|
||||
return _code && status() == loaded;
|
||||
}
|
||||
|
||||
inline Machine::Code::status_t Machine::Code::status() const throw() {
|
||||
return _status;
|
||||
}
|
||||
|
||||
inline bool Machine::Code::constraint() const throw() {
|
||||
return _constraint;
|
||||
}
|
||||
|
||||
inline size_t Machine::Code::dataSize() const throw() {
|
||||
return _data_size;
|
||||
}
|
||||
|
||||
inline size_t Machine::Code::instructionCount() const throw() {
|
||||
return _instr_count;
|
||||
}
|
||||
|
||||
inline bool Machine::Code::immutable() const throw()
|
||||
{
|
||||
return !(_delete || _modify);
|
||||
}
|
||||
|
||||
inline bool Machine::Code::deletes() const throw()
|
||||
{
|
||||
return _delete;
|
||||
}
|
||||
|
||||
inline size_t Machine::Code::maxRef() const throw()
|
||||
{
|
||||
return _max_ref;
|
||||
}
|
||||
|
||||
inline void Machine::Code::externalProgramMoved(ptrdiff_t dist) throw()
|
||||
{
|
||||
if (_code && !_own)
|
||||
|
|
|
@ -28,7 +28,7 @@ of the License or (at your option) any later version.
|
|||
|
||||
#include <utility>
|
||||
#include "inc/List.h"
|
||||
#include "inc/Slot.h"
|
||||
//#include "inc/Slot.h"
|
||||
#include "inc/Position.h"
|
||||
#include "inc/Intervals.h"
|
||||
#include "inc/debug.h"
|
||||
|
@ -118,8 +118,8 @@ private:
|
|||
|
||||
}; // end of class SlotColllision
|
||||
|
||||
class BBox;
|
||||
class SlantBox;
|
||||
struct BBox;
|
||||
struct SlantBox;
|
||||
|
||||
class ShiftCollider
|
||||
{
|
||||
|
@ -128,13 +128,7 @@ public:
|
|||
typedef Vector<fpair> vfpairs;
|
||||
typedef vfpairs::iterator ivfpairs;
|
||||
|
||||
ShiftCollider(GR_MAYBE_UNUSED json *dbgout)
|
||||
{
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_ranges[i].setdebug(dbgout);
|
||||
#endif
|
||||
}
|
||||
ShiftCollider(json *dbgout);
|
||||
~ShiftCollider() throw() { };
|
||||
|
||||
bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint,
|
||||
|
@ -176,10 +170,25 @@ protected:
|
|||
|
||||
}; // end of class ShiftCollider
|
||||
|
||||
inline
|
||||
ShiftCollider::ShiftCollider(GR_MAYBE_UNUSED json *dbgout)
|
||||
: _target(0),
|
||||
_margin(0.0),
|
||||
_marginWt(0.0),
|
||||
_seqClass(0),
|
||||
_seqProxClass(0),
|
||||
_seqOrder(0)
|
||||
{
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_ranges[i].setdebug(dbgout);
|
||||
#endif
|
||||
}
|
||||
|
||||
class KernCollider
|
||||
{
|
||||
public:
|
||||
KernCollider(GR_MAYBE_UNUSED json *dbg) : _miny(-1e38f), _maxy(1e38f) { };
|
||||
KernCollider(json *dbg);
|
||||
~KernCollider() throw() { };
|
||||
bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint, float margin,
|
||||
const Position &currShift, const Position &offsetPrev, int dir,
|
||||
|
@ -213,8 +222,24 @@ private:
|
|||
|
||||
|
||||
inline
|
||||
float sqr(float x) { return x * x; }
|
||||
float sqr(float x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
inline
|
||||
KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
|
||||
: _target(0),
|
||||
_margin(0.0f),
|
||||
_miny(-1e38f),
|
||||
_maxy(1e38f),
|
||||
_sliceWidth(0.0f),
|
||||
_mingap(0.0f),
|
||||
_xbound(0.0)
|
||||
{
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
_seg = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
}; // end of namespace graphite2
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* GRAPHITE2 LICENSING
|
||||
|
||||
Copyright 2015, SIL International
|
||||
All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should also have received a copy of the GNU Lesser General Public
|
||||
License along with this library in the file named "LICENSE".
|
||||
If not, write to the Free Software Foundation, 51 Franklin Street,
|
||||
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
|
||||
internet at http://www.fsf.org/licenses/lgpl.html.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
|
||||
License, as published by the Free Software Foundation, either version 2
|
||||
of the License or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#if ((defined GCC_VERSION && GCC_VERSION >= 302) || (defined __INTEL_COMPILER && __INTEL_COMPILER >= 800) || defined(__clang__))
|
||||
#define expect(expr,value) (__builtin_expect ((expr),(value)) )
|
||||
#else
|
||||
#define expect(expr,value) (expr)
|
||||
#endif
|
||||
|
||||
#define likely(expr) expect((expr) != 0, 1)
|
||||
#define unlikely(expr) expect((expr) != 0, 0)
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned __int8 u8;
|
||||
typedef unsigned __int16 u16;
|
||||
typedef unsigned __int32 u32;
|
||||
typedef unsigned __int64 u64;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
#endif
|
||||
|
||||
ptrdiff_t const MINMATCH = 4;
|
||||
|
||||
template<int S>
|
||||
inline
|
||||
void unaligned_copy(void * d, void const * s) {
|
||||
::memcpy(d, s, S);
|
||||
}
|
||||
|
||||
inline
|
||||
size_t align(size_t p) {
|
||||
return (p + sizeof(unsigned long)-1) & ~(sizeof(unsigned long)-1);
|
||||
}
|
||||
|
||||
inline
|
||||
u8 * overrun_copy(u8 * d, u8 const * s, size_t n) {
|
||||
size_t const WS = sizeof(unsigned long);
|
||||
u8 const * e = s + n;
|
||||
do
|
||||
{
|
||||
unaligned_copy<WS>(d, s);
|
||||
d += WS;
|
||||
s += WS;
|
||||
}
|
||||
while (s < e);
|
||||
d-=(s-e);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
u8 * fast_copy(u8 * d, u8 const * s, size_t n) {
|
||||
size_t const WS = sizeof(unsigned long);
|
||||
size_t wn = n/WS;
|
||||
while (wn--)
|
||||
{
|
||||
unaligned_copy<WS>(d, s);
|
||||
d += WS;
|
||||
s += WS;
|
||||
}
|
||||
n &= WS-1;
|
||||
while (n--) {*d++ = *s++; }
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
u8 * copy(u8 * d, u8 const * s, size_t n) {
|
||||
if (likely(d>s+sizeof(unsigned long)))
|
||||
return overrun_copy(d,s,n);
|
||||
else
|
||||
while (n--) *d++ = *s++;
|
||||
return d;
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
|
|
@ -1,51 +1,39 @@
|
|||
/* Copyright (c) 2012, Siyuan Fu <fusiyuan2010@gmail.com>
|
||||
Copyright (c) 2015, SIL International
|
||||
/* GRAPHITE2 LICENSING
|
||||
|
||||
Copyright 2015, SIL International
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should also have received a copy of the GNU Lesser General Public
|
||||
License along with this library in the file named "LICENSE".
|
||||
If not, write to the Free Software Foundation, 51 Franklin Street,
|
||||
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
|
||||
internet at http://www.fsf.org/licenses/lgpl.html.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
|
||||
License, as published by the Free Software Foundation, either version 2
|
||||
of the License or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace shrinker
|
||||
namespace lz4
|
||||
{
|
||||
|
||||
// return value is either decompressed size of -1
|
||||
int decompress(void const *in, size_t in_size, void *out, size_t out_size);
|
||||
/*
|
||||
in: inbuf --- compressed data
|
||||
out: outbuf --- decompressed data to place in
|
||||
size: decompressed(original) data size should be
|
||||
|
||||
return value:
|
||||
positive integer means decompress success and it's the sizeof decompressed data,
|
||||
which should be equal to size.
|
||||
or -1 means decompress failed
|
||||
*/
|
||||
|
||||
} // end of namespace shrinker
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ class FileFace;
|
|||
class GlyphCache;
|
||||
class NameTable;
|
||||
class json;
|
||||
class Font;
|
||||
|
||||
|
||||
using TtfUtil::Tag;
|
||||
|
@ -174,6 +175,8 @@ class Face::Table
|
|||
|
||||
Error decompress();
|
||||
|
||||
void releaseBuffers();
|
||||
|
||||
public:
|
||||
Table() throw();
|
||||
Table(const Face & face, const Tag n, uint32 version=0xffffffff) throw();
|
||||
|
@ -202,10 +205,7 @@ Face::Table::Table(const Table & rhs) throw()
|
|||
inline
|
||||
Face::Table::~Table() throw()
|
||||
{
|
||||
if (_compressed)
|
||||
free(const_cast<byte *>(_p));
|
||||
else if (_p && _f->m_ops.release_table)
|
||||
(*_f->m_ops.release_table)(_f->m_appFaceHandle, _p);
|
||||
releaseBuffers();
|
||||
}
|
||||
|
||||
inline
|
||||
|
|
|
@ -56,7 +56,7 @@ class FeatureRef
|
|||
static const uint8 SIZEOF_CHUNK = sizeof(chunk_t)*8;
|
||||
|
||||
public:
|
||||
FeatureRef() : m_nameValues(0) {}
|
||||
FeatureRef();
|
||||
FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val,
|
||||
uint32 name, uint16 uiName, uint16 flags,
|
||||
FeatureSetting *settings, uint16 num_set) throw();
|
||||
|
@ -99,6 +99,16 @@ private: //unimplemented
|
|||
};
|
||||
|
||||
|
||||
inline
|
||||
FeatureRef::FeatureRef()
|
||||
: m_pFace(0), m_nameValues(0),
|
||||
m_mask(0), m_max(0), m_id(0),
|
||||
m_nameid(0), m_flags(0), m_numSet(0),
|
||||
m_bits(0), m_index(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
class NameAndFeatureRef
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -39,10 +39,11 @@ class FeatureVal;
|
|||
class Segment;
|
||||
|
||||
|
||||
class SlantBox
|
||||
struct SlantBox
|
||||
{
|
||||
public:
|
||||
SlantBox(float psi = 0., float pdi = 0., float psa = 0., float pda = 0.) : si(psi), di(pdi), sa(psa), da(pda) {};
|
||||
static const SlantBox empty;
|
||||
|
||||
// SlantBox(float psi = 0., float pdi = 0., float psa = 0., float pda = 0.) : si(psi), di(pdi), sa(psa), da(pda) {};
|
||||
float width() const { return sa - si; }
|
||||
float height() const { return da - di; }
|
||||
float si; // min
|
||||
|
@ -51,11 +52,9 @@ public:
|
|||
float da; // max
|
||||
};
|
||||
|
||||
static SlantBox nullSlant(0, 0, 0, 0);
|
||||
|
||||
class BBox
|
||||
struct BBox
|
||||
{
|
||||
public:
|
||||
BBox(float pxi = 0, float pyi = 0., float pxa = 0., float pya = 0.) : xi(pxi), yi(pyi), xa(pxa), ya(pya) {};
|
||||
float width() const { return xa - xi; }
|
||||
float height() const { return ya - yi; }
|
||||
|
@ -65,7 +64,6 @@ public:
|
|||
float ya; // max
|
||||
};
|
||||
|
||||
static BBox nullBBox(0, 0, 0, 0);
|
||||
|
||||
class GlyphBox
|
||||
{
|
||||
|
@ -95,8 +93,6 @@ class GlyphCache
|
|||
GlyphCache(const GlyphCache&);
|
||||
GlyphCache& operator=(const GlyphCache&);
|
||||
|
||||
static const Rect nullRect;
|
||||
|
||||
public:
|
||||
GlyphCache(const Face & face, const uint32 face_options);
|
||||
~GlyphCache();
|
||||
|
@ -110,7 +106,7 @@ public:
|
|||
float getBoundingMetric(unsigned short glyphid, uint8 metric) const;
|
||||
uint8 numSubBounds(unsigned short glyphid) const;
|
||||
float getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const;
|
||||
const Rect & slant(unsigned short glyphid) const { return _boxes[glyphid] ? _boxes[glyphid]->slant() : nullRect; }
|
||||
const Rect & slant(unsigned short glyphid) const { return _boxes[glyphid] ? _boxes[glyphid]->slant() : _empty_slant_box; }
|
||||
const SlantBox & getBoundingSlantBox(unsigned short glyphid) const;
|
||||
const BBox & getBoundingBBox(unsigned short glyphid) const;
|
||||
const SlantBox & getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const;
|
||||
|
@ -120,6 +116,7 @@ public:
|
|||
CLASS_NEW_DELETE;
|
||||
|
||||
private:
|
||||
const Rect _empty_slant_box;
|
||||
const Loader * _glyph_loader;
|
||||
const GlyphFace * * _glyphs;
|
||||
GlyphBox * * _boxes;
|
||||
|
@ -149,7 +146,7 @@ unsigned short GlyphCache::unitsPerEm() const throw()
|
|||
inline
|
||||
bool GlyphCache::check(unsigned short glyphid) const
|
||||
{
|
||||
return glyphid < _num_glyphs;
|
||||
return _boxes && glyphid < _num_glyphs;
|
||||
}
|
||||
|
||||
inline
|
||||
|
@ -177,7 +174,7 @@ float GlyphCache::getBoundingMetric(unsigned short glyphid, uint8 metric) const
|
|||
|
||||
inline const SlantBox &GlyphCache::getBoundingSlantBox(unsigned short glyphid) const
|
||||
{
|
||||
return _boxes[glyphid] ? *(SlantBox *)(&(_boxes[glyphid]->slant())) : nullSlant;
|
||||
return _boxes[glyphid] ? *(SlantBox *)(&(_boxes[glyphid]->slant())) : SlantBox::empty;
|
||||
}
|
||||
|
||||
inline const BBox &GlyphCache::getBoundingBBox(unsigned short glyphid) const
|
||||
|
@ -207,14 +204,12 @@ float GlyphCache::getSubBoundingMetric(unsigned short glyphid, uint8 subindex, u
|
|||
inline const SlantBox &GlyphCache::getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const
|
||||
{
|
||||
GlyphBox *b = _boxes[glyphid];
|
||||
// if (b == NULL || subindex >= b->num()) return nullSlant;
|
||||
return *(SlantBox *)(b->subs() + 2 * subindex + 1);
|
||||
}
|
||||
|
||||
inline const BBox &GlyphCache::getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const
|
||||
{
|
||||
GlyphBox *b = _boxes[glyphid];
|
||||
// if (b == NULL || subindex >= b->num()) return nullBBox;
|
||||
return *(BBox *)(b->subs() + 2 * subindex);
|
||||
}
|
||||
|
||||
|
|
|
@ -144,6 +144,9 @@ inline
|
|||
Zones::Zones()
|
||||
: _margin_len(0), _margin_weight(0), _pos(0), _posm(0)
|
||||
{
|
||||
#if !defined GRAPHITE2_NTRACING
|
||||
_dbg = 0;
|
||||
#endif
|
||||
_exclusions.reserve(8);
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ void Vector<T>::reserve(size_t n)
|
|||
{
|
||||
const ptrdiff_t sz = size();
|
||||
m_first = static_cast<T*>(realloc(m_first, n*sizeof(T)));
|
||||
if (!m_first) std::abort();
|
||||
m_last = m_first + sz;
|
||||
m_end = m_first + n;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ template <typename T> T * gralloc(size_t n)
|
|||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::count_bytes(sizeof(T) * n);
|
||||
#endif
|
||||
return reinterpret_cast<T*>(malloc(sizeof(T) * n));
|
||||
return static_cast<T*>(malloc(sizeof(T) * n));
|
||||
}
|
||||
|
||||
template <typename T> T * grzeroalloc(size_t n)
|
||||
|
@ -93,7 +93,7 @@ template <typename T> T * grzeroalloc(size_t n)
|
|||
#ifdef GRAPHITE2_TELEMETRY
|
||||
telemetry::count_bytes(sizeof(T) * n);
|
||||
#endif
|
||||
return reinterpret_cast<T*>(calloc(n, sizeof(T)));
|
||||
return static_cast<T*>(calloc(n, sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -128,5 +128,5 @@ inline T max(const T a, const T b)
|
|||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4800)
|
||||
#pragma warning(once: 4355)
|
||||
#pragma warning(disable: 4355)
|
||||
#endif
|
||||
|
|
|
@ -53,9 +53,10 @@ public:
|
|||
|
||||
bool readPass(const byte * pPass, size_t pass_length, size_t subtable_base, Face & face,
|
||||
enum passtype pt, uint32 version, Error &e);
|
||||
bool runGraphite(vm::Machine & m, FiniteStateMachine & fsm) const;
|
||||
bool runGraphite(vm::Machine & m, FiniteStateMachine & fsm, bool reverse) const;
|
||||
void init(Silf *silf) { m_silf = silf; }
|
||||
byte flags() const { return m_flags; }
|
||||
byte collisionLoops() const { return m_numCollRuns; }
|
||||
bool reverseDir() const { return m_isReverseDir; }
|
||||
|
||||
CLASS_NEW_DELETE
|
||||
private:
|
||||
|
@ -73,7 +74,7 @@ private:
|
|||
uint16 glyphToCol(const uint16 gid) const;
|
||||
bool runFSM(FiniteStateMachine & fsm, Slot * slot) const;
|
||||
void dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEntry & re) const;
|
||||
void dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * os) const;
|
||||
void dumpRuleEventOutput(const FiniteStateMachine & fsm, vm::Machine & m, const Rule & r, Slot * os) const;
|
||||
void adjustSlot(int delta, Slot * & slot_out, SlotMap &) const;
|
||||
bool collisionShift(Segment *seg, int dir, json * const dbgout) const;
|
||||
bool collisionKern(Segment *seg, int dir, json * const dbgout) const;
|
||||
|
@ -93,7 +94,8 @@ private:
|
|||
vm::Machine::Code * m_codes;
|
||||
byte * m_progs;
|
||||
|
||||
byte m_flags;
|
||||
byte m_numCollRuns;
|
||||
byte m_kernColls;
|
||||
byte m_iMaxLoop;
|
||||
uint16 m_numGlyphs;
|
||||
uint16 m_numRules;
|
||||
|
@ -105,6 +107,7 @@ private:
|
|||
byte m_minPreCtxt;
|
||||
byte m_maxPreCtxt;
|
||||
byte m_colThreshold;
|
||||
bool m_isReverseDir;
|
||||
vm::Machine::Code m_cPConstraint;
|
||||
|
||||
private: //defensive
|
||||
|
|
|
@ -41,8 +41,8 @@ struct Rule {
|
|||
uint16 rule_idx;
|
||||
#endif
|
||||
|
||||
Rule() : constraint(0), action(0), sort(0), preContext(0) {}
|
||||
~Rule();
|
||||
Rule();
|
||||
~Rule() {}
|
||||
|
||||
CLASS_NEW_DELETE;
|
||||
|
||||
|
@ -51,8 +51,16 @@ private:
|
|||
Rule & operator = (const Rule &);
|
||||
};
|
||||
|
||||
inline Rule::~Rule()
|
||||
inline
|
||||
Rule::Rule()
|
||||
: constraint(0),
|
||||
action(0),
|
||||
sort(0),
|
||||
preContext(0)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
rule_idx = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,7 +102,7 @@ class SlotMap
|
|||
{
|
||||
public:
|
||||
enum {MAX_SLOTS=64};
|
||||
SlotMap(Segment & seg);
|
||||
SlotMap(Segment & seg, uint8 direction);
|
||||
|
||||
Slot * * begin();
|
||||
Slot * * end();
|
||||
|
@ -105,19 +113,22 @@ public:
|
|||
Slot * const & operator[](int n) const;
|
||||
Slot * & operator [] (int);
|
||||
void pushSlot(Slot * const slot);
|
||||
void collectGarbage();
|
||||
void collectGarbage(Slot *& aSlot);
|
||||
|
||||
Slot * highwater() { return m_highwater; }
|
||||
void highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
|
||||
bool highpassed() const { return m_highpassed; }
|
||||
void highpassed(bool v) { m_highpassed = v; }
|
||||
|
||||
uint8 dir() const { return m_dir; }
|
||||
|
||||
Segment & segment;
|
||||
private:
|
||||
Slot * m_slot_map[MAX_SLOTS+1];
|
||||
unsigned short m_size;
|
||||
unsigned short m_precontext;
|
||||
Slot * m_highwater;
|
||||
uint8 m_dir;
|
||||
bool m_highpassed;
|
||||
};
|
||||
|
||||
|
@ -231,8 +242,8 @@ void FiniteStateMachine::Rules::accumulate_rules(const State &state)
|
|||
}
|
||||
|
||||
inline
|
||||
SlotMap::SlotMap(Segment & seg)
|
||||
: segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_highpassed(false)
|
||||
SlotMap::SlotMap(Segment & seg, uint8 direction)
|
||||
: segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_dir(direction), m_highpassed(false)
|
||||
{
|
||||
m_slot_map[0] = 0;
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ private:
|
|||
unsigned long long minAccessCount, unsigned long long oldAccessTime);
|
||||
|
||||
uint16 m_prefixLength;
|
||||
uint16 m_maxCachedSegLength;
|
||||
// uint16 m_maxCachedSegLength;
|
||||
size_t m_segmentCount;
|
||||
SegCachePrefixArray m_prefixes;
|
||||
Features m_features;
|
||||
|
|
|
@ -39,7 +39,7 @@ of the License or (at your option) any later version.
|
|||
#include "inc/Slot.h"
|
||||
#include "inc/Position.h"
|
||||
#include "inc/List.h"
|
||||
#include "inc/Bidi.h"
|
||||
//#include "inc/Bidi.h"
|
||||
#include "inc/Collider.h"
|
||||
|
||||
#define MAX_SEG_GROWTH_FACTOR 256
|
||||
|
@ -48,7 +48,7 @@ namespace graphite2 {
|
|||
|
||||
typedef Vector<Features> FeatureList;
|
||||
typedef Vector<Slot *> SlotRope;
|
||||
typedef Vector<int16 *> AttributeRope;
|
||||
typedef Vector<int16 *> AttributeRope;
|
||||
typedef Vector<SlotJustify *> JustifyRope;
|
||||
|
||||
#ifndef GRAPHITE2_NSEGCACHE
|
||||
|
@ -101,7 +101,6 @@ public:
|
|||
unsigned int charInfoCount() const { return m_numCharinfo; }
|
||||
const CharInfo *charinfo(unsigned int index) const { return index < m_numCharinfo ? m_charinfo + index : NULL; }
|
||||
CharInfo *charinfo(unsigned int index) { return index < m_numCharinfo ? m_charinfo + index : NULL; }
|
||||
int8 dir() const { return m_dir; }
|
||||
|
||||
Segment(unsigned int numchars, const Face* face, uint32 script, int dir);
|
||||
~Segment();
|
||||
|
@ -124,7 +123,7 @@ public:
|
|||
void freeSlot(Slot *);
|
||||
SlotJustify *newJustify();
|
||||
void freeJustify(SlotJustify *aJustify);
|
||||
Position positionSlots(const Font *font=0, Slot *first=0, Slot *last=0, bool isFinal = true);
|
||||
Position positionSlots(const Font *font=0, Slot *first=0, Slot *last=0, bool isRtl = false, bool isFinal = true);
|
||||
void associateChars(int offset, int num);
|
||||
void linkClusters(Slot *first, Slot *last);
|
||||
uint16 getClassGlyph(uint16 cid, uint16 offset) const { return m_silf->getClassGlyph(cid, offset); }
|
||||
|
@ -138,11 +137,13 @@ public:
|
|||
if (val > pFR->maxVal()) val = pFR->maxVal();
|
||||
pFR->applyValToFeature(val, m_feats[index]);
|
||||
} }
|
||||
int8 dir() const { return m_dir; }
|
||||
void dir(int8 val) { m_dir = val; }
|
||||
bool currdir() const { return ((m_dir >> 6) ^ m_dir) & 1; }
|
||||
unsigned int passBits() const { return m_passBits; }
|
||||
void mergePassBits(const unsigned int val) { m_passBits &= val; }
|
||||
int16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; }
|
||||
int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const;
|
||||
int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const;
|
||||
float glyphAdvance(uint16 gid) const { return m_face->glyphs().glyph(gid)->theAdvance().x; }
|
||||
const Rect &theGlyphBBoxTemporary(uint16 gid) const { return m_face->glyphs().glyph(gid)->theBBox(); } //warning value may become invalid when another glyph is accessed
|
||||
Slot *findRoot(Slot *is) const { return is->attachedTo() ? findRoot(is->attachedTo()) : is; }
|
||||
|
@ -150,10 +151,13 @@ public:
|
|||
int defaultOriginal() const { return m_defaultOriginal; }
|
||||
const Face * getFace() const { return m_face; }
|
||||
const Features & getFeatures(unsigned int /*charIndex*/) { assert(m_feats.size() == 1); return m_feats[0]; }
|
||||
void bidiPass(uint8 aBidi, int paradir, uint8 aMirror);
|
||||
void bidiPass(int paradir, uint8 aMirror);
|
||||
int8 getSlotBidiClass(Slot *s) const;
|
||||
void doMirror(uint16 aMirror);
|
||||
Slot *addLineEnd(Slot *nSlot);
|
||||
void delLineEnd(Slot *s);
|
||||
bool hasJustification() const { return m_justifies.size() != 0; }
|
||||
void reverseSlots();
|
||||
|
||||
bool isWhitespace(const int cid) const;
|
||||
bool hasCollisionInfo() const { return m_collisions != 0; }
|
||||
|
@ -163,7 +167,7 @@ public:
|
|||
|
||||
public: //only used by: GrSegment* makeAndInitialize(const GrFont *font, const GrFace *face, uint32 script, const FeaturesHandle& pFeats/*must not be IsNull*/, encform enc, const void* pStart, size_t nChars, int dir);
|
||||
bool read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void*pStart, size_t nChars);
|
||||
void finalise(const Font *font);
|
||||
void finalise(const Font *font, bool reverse=false);
|
||||
float justify(Slot *pSlot, const Font *font, float width, enum justFlags flags, Slot *pFirst, Slot *pLast);
|
||||
bool initCollisions();
|
||||
|
||||
|
@ -190,24 +194,34 @@ private:
|
|||
uint8 m_flags; // General purpose flags
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
int8 Segment::getSlotBidiClass(Slot *s) const
|
||||
{
|
||||
int8 res = s->getBidiClass();
|
||||
if (res != -1) return res;
|
||||
res = glyphAttr(s->gid(), m_silf->aBidi());
|
||||
s->setBidiClass(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline
|
||||
void Segment::finalise(const Font *font)
|
||||
void Segment::finalise(const Font *font, bool reverse)
|
||||
{
|
||||
if (!m_first) return;
|
||||
|
||||
m_advance = positionSlots(font);
|
||||
m_advance = positionSlots(font, m_first, m_last, m_silf->dir(), true);
|
||||
//associateChars(0, m_numCharinfo);
|
||||
if (reverse && currdir() != (m_dir & 1))
|
||||
reverseSlots();
|
||||
linkClusters(m_first, m_last);
|
||||
}
|
||||
|
||||
inline
|
||||
int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const {
|
||||
int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const {
|
||||
if (attrLevel > 0)
|
||||
{
|
||||
Slot *is = findRoot(iSlot);
|
||||
return is->clusterMetric(this, metric, attrLevel);
|
||||
return is->clusterMetric(this, metric, attrLevel, rtl);
|
||||
}
|
||||
else
|
||||
return m_face->getGlyphMetric(iSlot->gid(), metric);
|
||||
|
|
|
@ -94,6 +94,7 @@ public:
|
|||
uint8 maxCompPerLig() const { return m_iMaxComp; }
|
||||
uint16 numClasses() const { return m_nClass; }
|
||||
byte flags() const { return m_flags; }
|
||||
byte dir() const { return m_dir; }
|
||||
uint8 numJustLevels() const { return m_numJusts; }
|
||||
Justinfo *justAttrs() const { return m_justs; }
|
||||
uint16 endLineGlyphid() const { return m_gEndLine; }
|
||||
|
@ -113,7 +114,7 @@ private:
|
|||
uint8 m_numPasses;
|
||||
uint8 m_numJusts;
|
||||
uint8 m_sPass, m_pPass, m_jPass, m_bPass,
|
||||
m_flags;
|
||||
m_flags, m_dir;
|
||||
|
||||
uint8 m_aPseudo, m_aBreak, m_aUser, m_aBidi, m_aMirror, m_aPassBits,
|
||||
m_iMaxComp, m_aCollision;
|
||||
|
|
|
@ -32,15 +32,13 @@ of the License or (at your option) any later version.
|
|||
#include "inc/Font.h"
|
||||
#include "inc/Position.h"
|
||||
|
||||
|
||||
|
||||
namespace graphite2 {
|
||||
|
||||
typedef gr_attrCode attrCode;
|
||||
|
||||
class GlyphFace;
|
||||
class Segment;
|
||||
class SegCacheEntry;
|
||||
class Segment;
|
||||
|
||||
struct SlotJustify
|
||||
{
|
||||
|
@ -82,7 +80,7 @@ public:
|
|||
uint32 index() const { return m_index; }
|
||||
void index(uint32 val) { m_index = val; }
|
||||
|
||||
Slot();
|
||||
Slot(int16 *m_userAttr = NULL);
|
||||
void set(const Slot & slot, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars);
|
||||
Slot *next() const { return m_next; }
|
||||
void next(Slot *s) { m_next = s; }
|
||||
|
@ -99,7 +97,7 @@ public:
|
|||
void after(int ind) { m_after = ind; }
|
||||
bool isBase() const { return (!m_parent); }
|
||||
void update(int numSlots, int numCharInfo, Position &relpos);
|
||||
Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool isFinal);
|
||||
Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal);
|
||||
bool isDeleted() const { return (m_flags & DELETED) ? true : false; }
|
||||
void markDeleted(bool state) { if (state) m_flags |= DELETED; else m_flags &= ~DELETED; }
|
||||
bool isCopied() const { return (m_flags & COPIED) ? true : false; }
|
||||
|
@ -109,6 +107,7 @@ public:
|
|||
bool isInsertBefore() const { return !(m_flags & INSERTED); }
|
||||
uint8 getBidiLevel() const { return m_bidiLevel; }
|
||||
void setBidiLevel(uint8 level) { m_bidiLevel = level; }
|
||||
int8 getBidiClass(const Segment *seg);
|
||||
int8 getBidiClass() const { return m_bidiCls; }
|
||||
void setBidiClass(int8 cls) { m_bidiCls = cls; }
|
||||
int16 *userAttrs() const { return m_userAttr; }
|
||||
|
@ -130,7 +129,7 @@ public:
|
|||
bool sibling(Slot *ap);
|
||||
bool removeChild(Slot *ap);
|
||||
bool removeSibling(Slot *ap);
|
||||
int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel);
|
||||
int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel, bool rtl);
|
||||
void positionShift(Position a) { m_position += a; }
|
||||
void floodShift(Position adj);
|
||||
float just() const { return m_just; }
|
||||
|
|
|
@ -56,7 +56,7 @@ private:
|
|||
key_type offset;
|
||||
};
|
||||
|
||||
static chunk empty_chunk;
|
||||
static const chunk empty_chunk;
|
||||
sparse(const sparse &);
|
||||
sparse & operator = (const sparse &);
|
||||
|
||||
|
@ -88,7 +88,7 @@ private:
|
|||
inline
|
||||
sparse::sparse() throw() : m_nchunks(0)
|
||||
{
|
||||
m_array.map = &empty_chunk;
|
||||
m_array.map = const_cast<graphite2::sparse::chunk *>(&empty_chunk);
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,7 +113,7 @@ sparse::sparse(I attr, const I last)
|
|||
}
|
||||
if (m_nchunks == 0)
|
||||
{
|
||||
m_array.map=&empty_chunk;
|
||||
m_array.map=const_cast<graphite2::sparse::chunk *>(&empty_chunk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,11 +137,11 @@ public:
|
|||
////////////////////////////////// cmap lookup tools
|
||||
const void * FindCmapSubtable(const void * pCmap, int nPlatformId = 3,
|
||||
int nEncodingId = 1, size_t length = 0);
|
||||
bool CheckCmapSubtable4(const void * pCmap31 /*, unsigned int maxgid*/);
|
||||
bool CheckCmapSubtable4(const void * pCmap31, size_t table_len /*, unsigned int maxgid*/);
|
||||
gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey = 0);
|
||||
unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId,
|
||||
int * pRangeKey = 0);
|
||||
bool CheckCmapSubtable12(const void *pCmap310 /*, unsigned int maxgid*/);
|
||||
bool CheckCmapSubtable12(const void *pCmap310, size_t table_len /*, unsigned int maxgid*/);
|
||||
gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey = 0);
|
||||
unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId,
|
||||
int * pRangeKey = 0);
|
||||
|
|
|
@ -61,6 +61,7 @@ of the License or (at your option) any later version.
|
|||
// isl = The last positioned slot
|
||||
// ip = The current instruction pointer
|
||||
// endPos = Position of advance of last cluster
|
||||
// dir = writing system directionality of the font
|
||||
|
||||
|
||||
// #define NOT_IMPLEMENTED assert(false)
|
||||
|
@ -313,6 +314,8 @@ STARTOP(insert)
|
|||
{
|
||||
newSlot->originate(seg.defaultOriginal());
|
||||
}
|
||||
if (is == smap.highwater())
|
||||
smap.highpassed(false);
|
||||
is = newSlot;
|
||||
seg.extendLength(1);
|
||||
if (map != &smap[-1])
|
||||
|
@ -389,7 +392,7 @@ STARTOP(attr_add)
|
|||
const int val = int(pop());
|
||||
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
|
||||
{
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
|
||||
flags |= POSITIONED;
|
||||
}
|
||||
int res = is->getAttr(&seg, slat, 0);
|
||||
|
@ -402,7 +405,7 @@ STARTOP(attr_sub)
|
|||
const int val = int(pop());
|
||||
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
|
||||
{
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
|
||||
flags |= POSITIONED;
|
||||
}
|
||||
int res = is->getAttr(&seg, slat, 0);
|
||||
|
@ -431,7 +434,7 @@ STARTOP(push_slot_attr)
|
|||
const int slot_ref = int8(param[1]);
|
||||
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
|
||||
{
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
|
||||
flags |= POSITIONED;
|
||||
}
|
||||
slotref slot = slotat(slot_ref);
|
||||
|
@ -458,7 +461,7 @@ STARTOP(push_glyph_metric)
|
|||
const signed int attr_level = uint8(param[2]);
|
||||
slotref slot = slotat(slot_ref);
|
||||
if (slot)
|
||||
push(seg.getGlyphMetric(slot, glyph_attr, attr_level));
|
||||
push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));
|
||||
ENDOP
|
||||
|
||||
STARTOP(push_feat)
|
||||
|
@ -496,7 +499,7 @@ STARTOP(push_att_to_glyph_metric)
|
|||
{
|
||||
slotref att = slot->attachedTo();
|
||||
if (att) slot = att;
|
||||
push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level)));
|
||||
push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));
|
||||
}
|
||||
ENDOP
|
||||
|
||||
|
@ -507,7 +510,7 @@ STARTOP(push_islot_attr)
|
|||
idx = uint8(param[2]);
|
||||
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
|
||||
{
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
|
||||
flags |= POSITIONED;
|
||||
}
|
||||
slotref slot = slotat(slot_ref);
|
||||
|
@ -552,7 +555,7 @@ STARTOP(iattr_add)
|
|||
const int val = int(pop());
|
||||
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
|
||||
{
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
|
||||
flags |= POSITIONED;
|
||||
}
|
||||
int res = is->getAttr(&seg, slat, idx);
|
||||
|
@ -566,7 +569,7 @@ STARTOP(iattr_sub)
|
|||
const int val = int(pop());
|
||||
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
|
||||
{
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
|
||||
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
|
||||
flags |= POSITIONED;
|
||||
}
|
||||
int res = is->getAttr(&seg, slat, idx);
|
||||
|
|
Загрузка…
Ссылка в новой задаче