Bug 1483566 - Update Graphite2 to version 1.3.12. r=jfkthame

Differential Revision: https://phabricator.services.mozilla.com/D3426

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ryan VanderMeulen 2018-08-21 13:58:42 +00:00
parent 203aa92dca
commit 9966e32859
80 changed files with 1034 additions and 2330 deletions

18
gfx/graphite2/ChangeLog Executable file → Normal file
View file

@ -1,3 +1,21 @@
1.3.12
. Graphite no longer does dumb rendering for fonts with no smarts
. Segment caching code removed. Anything attempting to use the segment cache gets given a regular face instead
. Add libfuzzer support
. Builds now require C++11
. Improvements to Windows 64 bit builds
. Support different versions of python including 32 bit and python 3
. Various minor bug fixes
1.3.11
. Fixes due to security review
. Minor collision avoidance fixes
. Fix LZ4 decompressor against high compression
1.3.10
. Address floating point build parameters to give consistent positioning results across platforms
. Various bug fixes
1.3.9
. Add Collision COLL_ISSPACE to allow for visible spaces in collision avoidance
. Add segment and pass direction information to tracing output

View file

@ -1,11 +1,10 @@
# Graphite engine
## Project CI status
Linux -- Intel 64bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt124/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt124&guest=1)
Intel 32bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt123/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt123&guest=1)
ARM 32bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Linux32bitArm/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Linux32bitArm&guest=1)
Windows -- Intel 64bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Windows64bitProduction/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Windows64bitProduction&guest=1)
| OS | Intel 64 bit | Intel 32 bit | Arm 32 bit |
|---------|:------------:|:------------:|:----------:|
| Linux | [![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt124/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt124&guest=1) | [![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt123/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt123&guest=1) | [![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Linux32bitArm/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Linux32bitArm&guest=1) |
| Windows | [![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Windows64bitProduction/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Windows64bitProduction&guest=1) | [![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt91/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt91&guest=1)| |
## What is Graphite?

View file

@ -1,7 +1,3 @@
This directory contains the Graphite2 library release 1.3.11 from
https://github.com/silnrsi/graphite/releases/download/1.3.11/graphite2-minimal-1.3.11.tgz
This directory contains the Graphite2 library release 1.3.12 from
https://github.com/silnrsi/graphite/releases/download/1.3.12/graphite2-minimal-1.3.12.tgz
See ./gfx/graphite2/moz-gr-update.sh for update procedure.
Note (2018-03-10):
Cherry-picked 6e24eb7edbd0872b46441d7397e8b87cccfede73 from upstream to fix memory leak
as noted in bug https://bugzilla.mozilla.org/show_bug.cgi?id=1443095.

View file

@ -30,7 +30,7 @@
#define GR2_VERSION_MAJOR 1
#define GR2_VERSION_MINOR 3
#define GR2_VERSION_BUGFIX 11
#define GR2_VERSION_BUGFIX 12
#ifdef __cplusplus
extern "C"
@ -56,7 +56,7 @@ GR2_API void gr_engine_version(int *nMajor, int *nMinor, int *nBugFix);
enum gr_face_options {
/** No preload, no cmap caching, fail if the graphite tables are invalid */
gr_face_default = 0,
/** Dumb rendering will be enabled if the graphite tables are invalid */
/** Dumb rendering will be enabled if the graphite tables are invalid. @deprecated Since 1.311 */
gr_face_dumbRendering = 1,
/** preload glyphs at construction time */
gr_face_preloadGlyphs = 2,
@ -130,8 +130,8 @@ typedef struct gr_face_ops gr_face_ops;
*/
GR2_API gr_face* gr_make_face_with_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *face_ops, unsigned int faceOptions);
/** Create a gr_face object given application information and a getTable function. This function is deprecated as of v1.2.0 in
* favour of gr_make_face_with_ops.
/** @deprecated Since v1.2.0 in favour of gr_make_face_with_ops.
* Create a gr_face object given application information and a getTable function.
*
* @return gr_face or NULL if the font fails to load for some reason.
* @param appFaceHandle This is application specific information that is passed
@ -140,22 +140,25 @@ GR2_API gr_face* gr_make_face_with_ops(const void* appFaceHandle/*non-NULL*/, co
* @param getTable Callback function to get table data.
* @param faceOptions Bitfield describing various options. See enum gr_face_options for details.
*/
GR2_API gr_face* gr_make_face(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn getTable, unsigned int faceOptions);
GR2_DEPRECATED_API gr_face* gr_make_face(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn getTable, unsigned int faceOptions);
//#ifndef GRAPHITE2_NSEGCACHE
/** Create a gr_face object given application information, with subsegmental caching support
/** @deprecated Since 1.3.7 this function is now an alias for gr_make_face_with_ops().
*
* Create a gr_face object given application information, with subsegmental caching support
*
* @return gr_face or NULL if the font fails to load.
* @param appFaceHandle is a pointer to application specific information that is passed to getTable.
* This may not be NULL and must stay alive as long as the gr_face is alive.
* @param face_ops Pointer to face specific callback structure for table management. Must stay
* alive for the duration of the call only.
* @param segCacheMaxSize How large the segment cache is.
* @param segCacheMaxSize Unused.
* @param faceOptions Bitfield of values from enum gr_face_options
*/
GR2_API gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle, const gr_face_ops *face_ops, unsigned int segCacheMaxSize, unsigned int faceOptions);
GR2_DEPRECATED_API gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle, const gr_face_ops *face_ops, unsigned int segCacheMaxSize, unsigned int faceOptions);
/** Create a gr_face object given application information, with subsegmental caching support.
/** @deprecated Since 1.3.7 this function is now an alias for gr_make_face().
*
* Create a gr_face object given application information, with subsegmental caching support.
* This function is deprecated as of v1.2.0 in favour of gr_make_face_with_seg_cache_and_ops.
*
* @return gr_face or NULL if the font fails to load.
@ -165,8 +168,7 @@ GR2_API gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle,
* @param segCacheMaxSize How large the segment cache is.
* @param faceOptions Bitfield of values from enum gr_face_options
*/
GR2_API gr_face* gr_make_face_with_seg_cache(const void* appFaceHandle, gr_get_table_fn getTable, unsigned int segCacheMaxSize, unsigned int faceOptions);
//#endif
GR2_DEPRECATED_API gr_face* gr_make_face_with_seg_cache(const void* appFaceHandle, gr_get_table_fn getTable, unsigned int segCacheMaxSize, unsigned int faceOptions);
/** Convert a tag in a string into a gr_uint32
*
@ -243,16 +245,16 @@ GR2_API int gr_face_is_char_supported(const gr_face *pFace, gr_uint32 usv, gr_ui
*/
GR2_API gr_face* gr_make_file_face(const char *filename, unsigned int faceOptions);
//#ifndef GRAPHITE2_NSEGCACHE
/** Create gr_face from a font file, with subsegment caching support.
/** @deprecated Since 1.3.7. This function is now an alias for gr_make_file_face().
*
* Create gr_face from a font file, with subsegment caching support.
*
* @return gr_face that accesses a font file directly. Returns NULL on failure.
* @param filename Full path and filename to font file
* @param segCacheMaxSize Specifies how big to make the cache in segments.
* @param faceOptions Bitfield from enum gr_face_options to control face options.
*/
GR2_API gr_face* gr_make_file_face_with_seg_cache(const char *filename, unsigned int segCacheMaxSize, unsigned int faceOptions);
//#endif
GR2_DEPRECATED_API gr_face* gr_make_file_face_with_seg_cache(const char *filename, unsigned int segCacheMaxSize, unsigned int faceOptions);
#endif // !GRAPHITE2_NFILEFACE
/** Create a font from a face
@ -385,4 +387,3 @@ GR2_API void gr_featureval_destroy(gr_feature_val *pfeatures);
#ifdef __cplusplus
}
#endif

View file

@ -40,33 +40,40 @@ enum gr_encform {
gr_utf8 = 1/*sizeof(uint8)*/, gr_utf16 = 2/*sizeof(uint16)*/, gr_utf32 = 4/*sizeof(uint32)*/
};
// Definitions for library publicly exported symbols
#if defined _WIN32 || defined __CYGWIN__
#if defined GRAPHITE2_STATIC
#define GR2_API
#elif defined GRAPHITE2_EXPORTING
#if defined __GNUC__
#define GR2_API __attribute__((dllexport))
#else
#define GR2_API __declspec(dllexport)
#endif
#else
#if defined __GNUC__
#define GR2_API __attribute__((dllimport))
#else
#define GR2_API __declspec(dllimport)
#endif
#endif
#define GR2_LOCAL
#elif __GNUC__ >= 4
#if defined GRAPHITE2_STATIC
#define GR2_API __attribute__ ((visibility("hidden")))
#else
#define GR2_API __attribute__ ((visibility("default")))
#endif
#define GR2_LOCAL __attribute__ ((visibility("hidden")))
#else
#define GR2_API
#define GR2_LOCAL
// Define API function declspec/attributes and how each supported compiler or OS
// allows us to specify them.
#if defined __GNUC__
#define _gr2_and ,
#define _gr2_tag_fn(a) __attribute__((a))
#define _gr2_deprecated_flag deprecated
#define _gr2_export_flag visibility("default")
#define _gr2_import_flag visibility("default")
#define _gr2_static_flag visibility("hidden")
#endif
#if defined _WIN32 || defined __CYGWIN__
#if defined __GNUC__ // These three will be redefined for Windows
#undef _gr2_export_flag
#undef _gr2_import_flag
#undef _gr2_static_flag
#else // How MSVC sepcifies function level attributes adn deprecation
#define _gr2_and
#define _gr2_tag_fn(a) __declspec(a)
#define _gr2_deprecated_flag deprecated
#endif
#define _gr2_export_flag dllexport
#define _gr2_import_flag dllimport
#define _gr2_static_flag
#endif
#if defined GRAPHITE2_STATIC
#define GR2_API _gr2_tag_fn(_gr2_static_flag)
#define GR2_DEPRECATED_API _gr2_tag_fn(_gr2_deprecated_flag _gr2_and _gr2_static_flag)
#elif defined GRAPHITE2_EXPORTING
#define GR2_API _gr2_tag_fn(_gr2_export_flag)
#define GR2_DEPRECATED_API _gr2_tag_fn(_gr2_deprecated_flag _gr2_and _gr2_export_flag)
#else
#define GR2_API _gr2_tag_fn(_gr2_import_flag)
#define GR2_DEPRECATED_API _gr2_tag_fn(_gr2_deprecated_flag _gr2_and _gr2_import_flag)
#endif

2
gfx/graphite2/moz-gr-update.sh Normal file → Executable file
View file

@ -22,7 +22,7 @@ fi
TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite2-minimal-$RELEASE.tgz"
foo=`basename $0`
TMPFILE=`mktemp -t ${foo}` || exit 1
TMPFILE=`mktemp -t ${foo}.XXX` || exit 1
curl -L "$TARBALL" -o "$TMPFILE"
tar -x -z -C gfx/graphite2/ --strip-components 1 -f "$TMPFILE" || exit 1

View file

@ -25,7 +25,7 @@ cmake_policy(SET CMP0012 NEW)
INCLUDE(CheckCXXSourceCompiles)
set(GRAPHITE_API_CURRENT 3)
set(GRAPHITE_API_REVISION 0)
set(GRAPHITE_API_REVISION 2)
set(GRAPHITE_API_AGE 1)
set(GRAPHITE_VERSION ${GRAPHITE_API_CURRENT}.${GRAPHITE_API_REVISION}.${GRAPHITE_API_AGE})
set(GRAPHITE_SO_VERSION ${GRAPHITE_API_CURRENT})
@ -34,12 +34,6 @@ include(TestBigEndian)
include_directories(${PROJECT_SOURCE_DIR})
set(SEGCACHE SegCache.cpp SegCacheEntry.cpp SegCacheStore.cpp)
if (GRAPHITE2_NSEGCACHE)
add_definitions(-DGRAPHITE2_NSEGCACHE)
set(SEGCACHE)
endif (GRAPHITE2_NSEGCACHE)
set(FILEFACE FileFace.cpp)
if (GRAPHITE2_NFILEFACE)
add_definitions(-DGRAPHITE2_NFILEFACE)
@ -78,7 +72,6 @@ add_library(graphite2
gr_logging.cpp
gr_segment.cpp
gr_slot.cpp
CachedFace.cpp
CmapCache.cpp
Code.cpp
Collider.cpp
@ -100,7 +93,6 @@ add_library(graphite2
TtfUtil.cpp
UtfCodec.cpp
${FILEFACE}
${SEGCACHE}
${TRACING})
set_target_properties(graphite2 PROPERTIES PUBLIC_HEADER "${GRAPHITE_HEADERS}"
@ -123,21 +115,21 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
endif (CMAKE_COMPILER_IS_GNUCXX)
message(STATUS "Compiler ID is: ${CMAKE_CXX_COMPILER_ID}")
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
add_definitions(-Wimplicit-fallthrough)
add_definitions(-Wimplicit-fallthrough -Wshorten-64-to-32)
endif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
if (${CMAKE_CXX_COMPILER} MATCHES ".*mingw.*")
target_link_libraries(graphite2 kernel32 msvcr90 mingw32 gcc user32)
else (${CMAKE_CXX_COMPILER} MATCHES ".*mingw.*")
if (GRAPHITE2_ASAN)
if (GRAPHITE2_SANITIZERS)
target_link_libraries(graphite2 c gcc_s)
else (GRAPHITE2_ASAN)
else ()
target_link_libraries(graphite2 c gcc)
endif (GRAPHITE2_ASAN)
endif ()
endif (${CMAKE_CXX_COMPILER} MATCHES ".*mingw.*")
include(Graphite)
if (BUILD_SHARED_LIBS)
nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
endif (BUILD_SHARED_LIBS)
endif (${CMAKE_CXX_COMPILER} MATCHES ".*mingw.*")
endif ()
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
CREATE_LIBTOOL_FILE(graphite2 "/lib${LIB_SUFFIX}")
endif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")

View file

@ -1,127 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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.
*/
#ifndef GRAPHITE2_NSEGCACHE
#include <graphite2/Segment.h>
#include "inc/CachedFace.h"
#include "inc/SegCacheStore.h"
using namespace graphite2;
CachedFace::CachedFace(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops)
: Face(appFaceHandle, ops), m_cacheStore(0)
{
}
CachedFace::~CachedFace()
{
delete m_cacheStore;
}
bool CachedFace::setupCache(unsigned int cacheSize)
{
m_cacheStore = new SegCacheStore(*this, m_numSilf, cacheSize);
return bool(m_cacheStore);
}
bool CachedFace::runGraphite(Segment *seg, const Silf *pSilf) const
{
assert(pSilf);
pSilf->runGraphite(seg, 0, pSilf->substitutionPass());
unsigned int silfIndex = 0;
for (; silfIndex < m_numSilf && &(m_silfs[silfIndex]) != pSilf; ++silfIndex);
if (silfIndex == m_numSilf) return false;
SegCache * const segCache = m_cacheStore->getOrCreate(silfIndex, seg->getFeatures(0));
if (!segCache)
return false;
assert(m_cacheStore);
// find where the segment can be broken
Slot * subSegStartSlot = seg->first();
Slot * subSegEndSlot = subSegStartSlot;
uint16 cmapGlyphs[eMaxSpliceSize];
int subSegStart = 0;
for (unsigned int i = 0; i < seg->charInfoCount() && subSegEndSlot; ++i)
{
const unsigned int length = i - subSegStart + 1;
if (length < eMaxSpliceSize && subSegEndSlot->gid() < m_cacheStore->maxCmapGid())
cmapGlyphs[length-1] = subSegEndSlot->gid();
else return false;
const bool spaceOnly = m_cacheStore->isSpaceGlyph(subSegEndSlot->gid());
// at this stage the character to slot mapping is still 1 to 1
const int breakWeight = seg->charinfo(i)->breakWeight(),
nextBreakWeight = (i + 1 < seg->charInfoCount())?
seg->charinfo(i+1)->breakWeight() : 0;
const uint8 f = seg->charinfo(i)->flags();
if (((spaceOnly
|| (breakWeight > 0 && breakWeight <= gr_breakWord)
|| i + 1 == seg->charInfoCount()
|| ((nextBreakWeight < 0 && nextBreakWeight >= gr_breakBeforeWord)
|| (subSegEndSlot->next() && m_cacheStore->isSpaceGlyph(subSegEndSlot->next()->gid()))))
&& f != 1)
|| f == 2)
{
// record the next slot before any splicing
Slot * nextSlot = subSegEndSlot->next();
// spaces should be left untouched by graphite rules in any sane font
if (!spaceOnly)
{
// found a break position, check for a cache of the sub sequence
const SegCacheEntry * entry = segCache->find(cmapGlyphs, length);
// TODO disable cache for words at start/end of line with contextuals
if (!entry)
{
SegmentScopeState scopeState = seg->setScope(subSegStartSlot, subSegEndSlot, length);
pSilf->runGraphite(seg, pSilf->substitutionPass(), pSilf->numPasses());
if (length < eMaxSpliceSize)
{
seg->associateChars(subSegStart, length);
segCache->cache(m_cacheStore, cmapGlyphs, length, seg, subSegStart);
}
seg->removeScope(scopeState);
}
else
seg->splice(subSegStart, length, subSegStartSlot, subSegEndSlot,
entry->first(), entry->glyphLength());
}
subSegStartSlot = subSegEndSlot = nextSlot;
subSegStart = i + 1;
}
else
{
subSegEndSlot = subSegEndSlot->next();
}
}
return true;
}
#endif

View file

@ -275,7 +275,7 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc)
// Do some basic sanity checks based on what we know about the opcode
if (!validate_opcode(opc, bc)) return MAX_OPCODE;
// And check it's arguments as far as possible
// And check its arguments as far as possible
switch (opcode(opc))
{
case NOP :
@ -509,7 +509,7 @@ void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8 * arg)
case NEXT :
case COPY_NEXT :
++_slotref;
_contexts[_slotref] = context(_code._instr_count+1);
_contexts[_slotref] = context(uint8(_code._instr_count+1));
// if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref;
break;
case INSERT :
@ -589,8 +589,8 @@ bool Machine::Code::decoder::emit_opcode(opcode opc, const byte * & bc)
if (load(bc, bc + instr_skip))
{
bc += instr_skip;
data_skip = instr_skip - (_code._instr_count - ctxt_start);
instr_skip = _code._instr_count - ctxt_start;
data_skip = instr_skip - byte(_code._instr_count - ctxt_start);
instr_skip = byte(_code._instr_count - ctxt_start);
_max.bytecode = curr_end;
_out_length = 1;
@ -750,4 +750,3 @@ int32 Machine::Code::run(Machine & m, slotref * & map) const
return m.run(_code, _data, map);
}

View file

@ -877,7 +877,7 @@ bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float
}
goto done;
}
numSlices = _edges.size();
numSlices = int(_edges.size());
#if !defined GRAPHITE2_NTRACING
// Debugging

View file

@ -121,6 +121,5 @@ int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
return -1;
dst = fast_copy(dst, literal, literal_len);
return dst - (u8*)out;
return int(dst - (u8*)out);
}

View file

@ -34,7 +34,6 @@ of the License or (at your option) any later version.
#include "inc/FileFace.h"
#include "inc/GlyphFace.h"
#include "inc/json.h"
#include "inc/SegCacheStore.h"
#include "inc/Segment.h"
#include "inc/NameTable.h"
#include "inc/Error.h"
@ -142,7 +141,7 @@ bool Face::readGraphite(const Table & silf)
{
error_context(EC_ASILF + (i << 8));
const uint32 offset = be::read<uint32>(p),
next = i == m_numSilf - 1 ? silf.size() : be::peek<uint32>(p);
next = i == m_numSilf - 1 ? uint32(silf.size()) : be::peek<uint32>(p);
if (e.test(next > silf.size() || offset >= next, E_BADSIZE))
return error(e);
@ -201,7 +200,7 @@ bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
<< "advance" << seg->advance()
<< "chars" << json::array;
for(size_t i = 0, n = seg->charInfoCount(); i != n; ++i)
*dbgout << json::flat << *seg->charinfo(i);
*dbgout << json::flat << *seg->charinfo(int(i));
*dbgout << json::close // Close up the chars array
<< json::close; // Close up the segment object
}
@ -276,15 +275,13 @@ uint16 Face::languageForLocale(const char * locale) const
Face::Table::Table(const Face & face, const Tag n, uint32 version) throw()
: _f(&face), _compressed(false)
: _f(&face), _sz(0), _compressed(false)
{
size_t sz = 0;
_p = static_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &sz));
_sz = uint32(sz);
_p = static_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &_sz));
if (!TtfUtil::CheckTable(n, _p, _sz))
{
releaseBuffers(); // Make sure we release the table buffer even if the table failed it's checks
release(); // Make sure we release the table buffer even if the table failed its checks
return;
}
@ -292,7 +289,7 @@ Face::Table::Table(const Face & face, const Tag n, uint32 version) throw()
decompress();
}
void Face::Table::releaseBuffers()
void Face::Table::release()
{
if (_compressed)
free(const_cast<byte *>(_p));
@ -301,12 +298,11 @@ void Face::Table::releaseBuffers()
_p = 0; _sz = 0;
}
Face::Table & Face::Table::operator = (const Table & rhs) throw()
Face::Table & Face::Table::operator = (const Table && rhs) throw()
{
if (_p == rhs._p) return *this;
this->~Table();
new (this) Table(rhs);
if (this == &rhs) return *this;
release();
new (this) Table(std::move(rhs));
return *this;
}
@ -353,7 +349,7 @@ Error Face::Table::decompress()
// Tell the provider to release the compressed form since were replacing
// it anyway.
releaseBuffers();
release();
if (e)
{

View file

@ -48,7 +48,7 @@ FileFace::FileFace(const char *filename)
// Get the header.
if (!TtfUtil::GetHeaderInfo(tbl_offset, tbl_len)) return;
if (fseek(_file, tbl_offset, SEEK_SET)) return;
if (fseek(_file, long(tbl_offset), SEEK_SET)) return;
_header_tbl = (TtfUtil::Sfnt::OffsetSubTable*)gralloc<char>(tbl_len);
if (_header_tbl)
{
@ -59,7 +59,7 @@ FileFace::FileFace(const char *filename)
// Get the table directory
if (!TtfUtil::GetTableDirInfo(_header_tbl, tbl_offset, tbl_len)) return;
_table_dir = (TtfUtil::Sfnt::OffsetSubTable::Entry*)gralloc<char>(tbl_len);
if (fseek(_file, tbl_offset, SEEK_SET)) return;
if (fseek(_file, long(tbl_offset), SEEK_SET)) return;
if (_table_dir && fread(_table_dir, 1, tbl_len, _file) != tbl_len)
{
free(_table_dir);
@ -88,7 +88,7 @@ const void *FileFace::get_table_fn(const void* appFaceHandle, unsigned int name,
return 0;
if (tbl_offset > file_face._file_len || tbl_len > file_face._file_len - tbl_offset
|| fseek(file_face._file, tbl_offset, SEEK_SET) != 0)
|| fseek(file_face._file, long(tbl_offset), SEEK_SET) != 0)
return 0;
tbl = malloc(tbl_len);

View file

@ -56,6 +56,3 @@ Font::Font(float ppm, const Face & f, const void * appFontHandle, const gr_font_
{
free(m_advances);
}

View file

@ -46,7 +46,7 @@ namespace
template<typename W>
class _glat_iterator : public std::iterator<std::input_iterator_tag, std::pair<sparse::key_type, sparse::mapped_type> >
{
unsigned short key() const { return be::peek<W>(_e) + _n; }
unsigned short key() const { return uint16(be::peek<W>(_e) + _n); }
unsigned int run() const { return be::peek<W>(_e+sizeof(W)); }
void advance_entry() { _n = 0; _e = _v; be::skip<W>(_v,2); }
public:
@ -84,7 +84,7 @@ const SlantBox SlantBox::empty = {0,0,0,0};
class GlyphCache::Loader
{
public:
Loader(const Face & face, const bool dumb_font); //return result indicates success. Do not use if failed.
Loader(const Face & face); //return result indicates success. Do not use if failed.
operator bool () const throw();
unsigned short int units_per_em() const throw();
@ -115,7 +115,7 @@ private:
GlyphCache::GlyphCache(const Face & face, const uint32 face_options)
: _glyph_loader(new Loader(face, bool(face_options & gr_face_dumbRendering))),
: _glyph_loader(new Loader(face)),
_glyphs(_glyph_loader && *_glyph_loader && _glyph_loader->num_glyphs()
? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0),
_boxes(_glyph_loader && _glyph_loader->has_boxes() && _glyph_loader->num_glyphs()
@ -239,7 +239,7 @@ const GlyphFace *GlyphCache::glyph(unsigned short glyphid) const //result m
GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
GlyphCache::Loader::Loader(const Face & face)
: _head(face, Tag::head),
_hhea(face, Tag::hhea),
_hmtx(face, Tag::hmtx),
@ -257,7 +257,7 @@ GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
const Face::Table maxp = Face::Table(face, Tag::maxp);
if (!maxp) { _head = Face::Table(); return; }
_num_glyphs_graphics = TtfUtil::GlyphCount(maxp);
_num_glyphs_graphics = static_cast<unsigned short>(TtfUtil::GlyphCount(maxp));
// This will fail if the number of glyphs is wildly out of range.
if (_glyf && TtfUtil::LocaLookup(_num_glyphs_graphics-1, _loca, _loca.size(), _head) == size_t(-2))
{
@ -265,8 +265,6 @@ GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
return;
}
if (!dumb_font)
{
if ((m_pGlat = Face::Table(face, Tag::Glat, 0x00030000)) == NULL
|| (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
|| m_pGloc.size() < 8)
@ -282,7 +280,7 @@ 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;
int tmpnumgattrs = (m_pGloc.size()
ptrdiff_t tmpnumgattrs = (m_pGloc.size()
- (p - m_pGloc)
- sizeof(uint16)*(flags & 0x2 ? _num_attrs : 0))
/ (_long_fmt ? sizeof(uint32) : sizeof(uint16)) - 1;
@ -311,7 +309,6 @@ GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
// delete this once the compiler is fixed
_has_boxes = true;
}
}
}
inline
@ -489,4 +486,3 @@ GlyphBox * GlyphCache::Loader::read_box(uint16 gid, GlyphBox *curr, const GlyphF
}
return (GlyphBox *)((char *)(curr) + sizeof(GlyphBox) + 2 * num * sizeof(Rect));
}

View file

@ -33,16 +33,16 @@ int32 GlyphFace::getMetric(uint8 metric) const
{
switch (metrics(metric))
{
case kgmetLsb : return m_bbox.bl.x;
case kgmetRsb : return m_advance.x - m_bbox.tr.x;
case kgmetBbTop : return m_bbox.tr.y;
case kgmetBbBottom : return m_bbox.bl.y;
case kgmetBbLeft : return m_bbox.bl.x;
case kgmetBbRight : return m_bbox.tr.x;
case kgmetBbHeight : return m_bbox.tr.y - m_bbox.bl.y;
case kgmetBbWidth : return m_bbox.tr.x - m_bbox.bl.x;
case kgmetAdvWidth : return m_advance.x;
case kgmetAdvHeight : return m_advance.y;
case kgmetLsb : return int32(m_bbox.bl.x);
case kgmetRsb : return int32(m_advance.x - m_bbox.tr.x);
case kgmetBbTop : return int32(m_bbox.tr.y);
case kgmetBbBottom : return int32(m_bbox.bl.y);
case kgmetBbLeft : return int32(m_bbox.bl.x);
case kgmetBbRight : return int32(m_bbox.tr.x);
case kgmetBbHeight : return int32(m_bbox.tr.y - m_bbox.bl.y);
case kgmetBbWidth : return int32(m_bbox.tr.x - m_bbox.bl.x);
case kgmetAdvWidth : return int32(m_advance.x);
case kgmetAdvHeight : return int32(m_advance.y);
default : return 0;
}
}

View file

@ -183,11 +183,11 @@ void Zones::remove(float x, float xm)
Zones::const_iterator Zones::find_exclusion_under(float x) const
{
int l = 0, h = _exclusions.size();
size_t l = 0, h = _exclusions.size();
while (l < h)
{
int const p = (l+h) >> 1;
size_t const p = (l+h) >> 1;
switch (_exclusions[p].outcode(x))
{
case 0 : return _exclusions.begin()+p;
@ -296,4 +296,3 @@ void Zones::jsonDbgOut(Segment *seg) const {
}
#endif

View file

@ -62,7 +62,7 @@ void JustifyTotal::accumulate(Slot *s, Segment *seg, int level)
float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags jflags, Slot *pFirst, Slot *pLast)
{
Slot *s, *end;
Slot *end = last();
float currWidth = 0.0;
const float scale = font ? font->scale() : 1.0f;
Position res;
@ -73,9 +73,7 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
{
reverseSlots();
s = pFirst;
pFirst = pLast;
pLast = s;
std::swap(pFirst, pLast);
}
if (!pFirst) pFirst = pSlot;
while (!pFirst->isBase()) pFirst = pFirst->attachedTo();
@ -85,22 +83,25 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
width = width / scale;
if ((jflags & gr_justEndInline) == 0)
{
do {
while (pLast != pFirst && pLast)
{
Rect bbox = theGlyphBBoxTemporary(pLast->glyph());
if (bbox.bl.x != 0.f || bbox.bl.y != 0.f || bbox.tr.x != 0.f || bbox.tr.y == 0.f)
break;
pLast = pLast->prev();
} while (pLast != pFirst);
}
}
if (pLast)
end = pLast->nextSibling();
if (pFirst)
pFirst = pFirst->nextSibling();
int icount = 0;
int numLevels = silf()->numJustLevels();
if (!numLevels)
{
for (s = pSlot; s && s != end; s = s->nextSibling())
for (Slot *s = pSlot; s && s != end; s = s->nextSibling())
{
CharInfo *c = charinfo(s->before());
if (isWhitespace(c->unicodeChar()))
@ -113,7 +114,7 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
}
if (!icount)
{
for (s = pSlot; s && s != end; s = s->nextSibling())
for (Slot *s = pSlot; s && s != end; s = s->nextSibling())
{
s->setJustify(this, 0, 3, 1);
s->setJustify(this, 0, 2, 1);
@ -124,7 +125,7 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
}
Vector<JustifyTotal> stats(numLevels);
for (s = pFirst; s && s != end; s = s->nextSibling())
for (Slot *s = pFirst; s && s != end; s = s->nextSibling())
{
float w = s->origin().x / scale + s->advance() - base;
if (w > currWidth) currWidth = w;
@ -146,7 +147,7 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
diff = width - currWidth;
diffpw = diff / tWeight;
tWeight = 0;
for (s = pFirst; s && s != end; s = s->nextSibling()) // don't include final glyph
for (Slot *s = pFirst; s && s != end; s = s->nextSibling()) // don't include final glyph
{
int w = s->getJustify(this, i, 3);
float pref = diffpw * w + error;
@ -224,7 +225,9 @@ float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUS
if (silf()->flags() & 1)
{
if (m_first)
delLineEnd(m_first);
if (m_last)
delLineEnd(m_last);
}
m_first = oldFirst;
@ -277,4 +280,3 @@ void Segment::delLineEnd(Slot *s)
s->prev()->next(NULL);
freeSlot(s);
}

View file

@ -51,7 +51,7 @@ NameTable::NameTable(const void* data, size_t length, uint16 platformId, uint16
{
m_nameData = reinterpret_cast<const uint8*>(pdata) + offset;
setPlatformEncoding(platformId, encodingID);
m_nameDataLength = length - offset;
m_nameDataLength = uint16(length - offset);
return;
}
}
@ -180,7 +180,7 @@ void* NameTable::getName(uint16& languageId, uint16 nameId, gr_encform enc, uint
utf8::iterator d = uniBuffer;
for (utf16::const_iterator s = utf16Name, e = utf16Name + utf16Length; s != e; ++s, ++d)
*d = *s;
length = d - uniBuffer;
length = uint32(d - uniBuffer);
uniBuffer[length] = 0;
free(utf16Name);
return uniBuffer;
@ -201,7 +201,7 @@ void* NameTable::getName(uint16& languageId, uint16 nameId, gr_encform enc, uint
utf32::iterator d = uniBuffer;
for (utf16::const_iterator s = utf16Name, e = utf16Name + utf16Length; s != e; ++s, ++d)
*d = *s;
length = d - uniBuffer;
length = uint32(d - uniBuffer);
uniBuffer[length] = 0;
free(utf16Name);
return uniBuffer;
@ -252,4 +252,3 @@ uint16 NameTable::getLanguageId(const char * bcp47Locale)
}
return localeId;
}

View file

@ -246,11 +246,11 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
Rule * r = m_rules + m_numRules - 1;
for (size_t n = m_numRules; r >= m_rules; --n, --r, ac_end = ac_begin, rc_end = rc_begin)
{
face.error_context((face.error_context() & 0xFFFF00) + EC_ARULE + ((n - 1) << 24));
face.error_context((face.error_context() & 0xFFFF00) + EC_ARULE + int((n - 1) << 24));
r->preContext = *--precontext;
r->sort = be::peek<uint16>(--sort_key);
#ifndef NDEBUG
r->rule_idx = n - 1;
r->rule_idx = uint16(n - 1);
#endif
if (r->sort > 63 || r->preContext >= r->sort || r->preContext > m_maxPreCtxt || r->preContext < m_minPreCtxt)
return false;
@ -291,7 +291,7 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
// Load the rule entries map
face.error_context((face.error_context() & 0xFFFF00) + EC_APASS);
//TODO: Coverty: 1315804: FORWARD_NULL
//TODO: Coverity: 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)
@ -330,7 +330,7 @@ bool Pass::readStates(const byte * starts, const byte *states, const byte * o_ru
*s = be::read<uint16>(starts);
if (e.test(*s >= m_numStates, E_BADSTATE))
{
face.error_context((face.error_context() & 0xFFFF00) + EC_ASTARTS + ((s - m_startStates) << 24));
face.error_context((face.error_context() & 0xFFFF00) + EC_ASTARTS + int((s - m_startStates) << 24));
return face.error(e); // true;
}
}
@ -342,7 +342,7 @@ bool Pass::readStates(const byte * starts, const byte *states, const byte * o_ru
*t = be::read<uint16>(states);
if (e.test(*t >= m_numStates, E_BADSTATE))
{
face.error_context((face.error_context() & 0xFFFF00) + EC_ATRANS + (((t - m_transitions) / m_numColumns) << 8));
face.error_context((face.error_context() & 0xFFFF00) + EC_ATRANS + int(((t - m_transitions) / m_numColumns) << 8));
return face.error(e);
}
}
@ -357,7 +357,7 @@ bool Pass::readStates(const byte * starts, const byte *states, const byte * o_ru
if (e.test(begin >= rule_map_end || end > rule_map_end || begin > end, E_BADRULEMAPPING))
{
face.error_context((face.error_context() & 0xFFFF00) + EC_ARULEMAP + (n << 24));
face.error_context((face.error_context() & 0xFFFF00) + EC_ARULEMAP + int(n << 24));
return face.error(e);
}
s->rules = begin;
@ -1105,4 +1105,3 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start
}
return 0.;
}

View file

@ -95,4 +95,3 @@ Position Rect::constrainedAvoid(Position &offset, Rect &box, Rect &sdbox, Positi
return res;
}
#endif

View file

@ -1,224 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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.
*/
#include "inc/Main.h"
#include "inc/TtfTypes.h"
#include "inc/TtfUtil.h"
#include "inc/SegCache.h"
#include "inc/SegCacheEntry.h"
#include "inc/SegCacheStore.h"
#include "inc/CmapCache.h"
using namespace graphite2;
#ifndef GRAPHITE2_NSEGCACHE
SegCache::SegCache(const SegCacheStore * store, const Features & feats)
: m_prefixLength(ePrefixLength),
// m_maxCachedSegLength(eMaxSpliceSize),
m_segmentCount(0),
m_features(feats),
m_totalAccessCount(0l), m_totalMisses(0l),
m_purgeFactor(1.0f / (ePurgeFactor * store->maxSegmentCount()))
{
m_prefixes.raw = grzeroalloc<void*>(store->maxCmapGid() + 2);
m_prefixes.range[SEG_CACHE_MIN_INDEX] = SEG_CACHE_UNSET_INDEX;
m_prefixes.range[SEG_CACHE_MAX_INDEX] = SEG_CACHE_UNSET_INDEX;
}
void SegCache::freeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level)
{
for (size_t i = 0; i < store->maxCmapGid(); i++)
{
if (prefixes.array[i].raw)
{
if (level + 1 < ePrefixLength)
freeLevel(store, prefixes.array[i], level + 1);
else
{
SegCachePrefixEntry * prefixEntry = prefixes.prefixEntries[i];
delete prefixEntry;
}
}
}
free(prefixes.raw);
}
void SegCache::clear(SegCacheStore * store)
{
freeLevel(store, m_prefixes, 0);
m_prefixes.raw = NULL;
}
SegCache::~SegCache()
{
assert(m_prefixes.raw == NULL);
}
SegCacheEntry* SegCache::cache(SegCacheStore * store, const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset)
{
uint16 pos = 0;
if (!length) return NULL;
// assert(length < m_maxCachedSegLength);
SegCachePrefixArray pArray = m_prefixes;
while (pos + 1 < m_prefixLength)
{
uint16 gid = (pos < length)? cmapGlyphs[pos] : 0;
if (!pArray.array[gid].raw)
{
pArray.array[gid].raw = grzeroalloc<void*>(store->maxCmapGid() + 2);
if (!pArray.array[gid].raw)
return NULL; // malloc failed
if (pArray.range[SEG_CACHE_MIN_INDEX] == SEG_CACHE_UNSET_INDEX)
{
pArray.range[SEG_CACHE_MIN_INDEX] = gid;
pArray.range[SEG_CACHE_MAX_INDEX] = gid;
}
else
{
if (gid < pArray.range[SEG_CACHE_MIN_INDEX])
pArray.range[SEG_CACHE_MIN_INDEX] = gid;
else if (gid > pArray.range[SEG_CACHE_MAX_INDEX])
pArray.range[SEG_CACHE_MAX_INDEX] = gid;
}
}
pArray = pArray.array[gid];
++pos;
}
uint16 gid = (pos < length)? cmapGlyphs[pos] : 0;
SegCachePrefixEntry * prefixEntry = pArray.prefixEntries[gid];
if (!prefixEntry)
{
prefixEntry = new SegCachePrefixEntry();
pArray.prefixEntries[gid] = prefixEntry;
if (pArray.range[SEG_CACHE_MIN_INDEX] == SEG_CACHE_UNSET_INDEX)
{
pArray.range[SEG_CACHE_MIN_INDEX] = gid;
pArray.range[SEG_CACHE_MAX_INDEX] = gid;
}
else
{
if (gid < pArray.range[SEG_CACHE_MIN_INDEX])
pArray.range[SEG_CACHE_MIN_INDEX] = gid;
else if (gid > pArray.range[SEG_CACHE_MAX_INDEX])
pArray.range[SEG_CACHE_MAX_INDEX] = gid;
}
}
if (!prefixEntry) return NULL;
// if the cache is full run a purge - this is slow, since it walks the tree
if (m_segmentCount + 1 > store->maxSegmentCount())
{
purge(store);
assert(m_segmentCount < store->maxSegmentCount());
}
SegCacheEntry * pEntry = prefixEntry->cache(cmapGlyphs, length, seg, charOffset, m_totalAccessCount);
if (pEntry) ++m_segmentCount;
return pEntry;
}
void SegCache::purge(SegCacheStore * store)
{
unsigned long long minAccessCount = static_cast<unsigned long long>(m_totalAccessCount * m_purgeFactor + 1);
if (minAccessCount < 2) minAccessCount = 2;
unsigned long long oldAccessTime = m_totalAccessCount - store->maxSegmentCount() / eAgeFactor;
purgeLevel(store, m_prefixes, 0, minAccessCount, oldAccessTime);
}
void SegCache::purgeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level,
unsigned long long minAccessCount, unsigned long long oldAccessTime)
{
if (prefixes.range[SEG_CACHE_MIN_INDEX] == SEG_CACHE_UNSET_INDEX) return;
size_t maxGlyphCached = prefixes.range[SEG_CACHE_MAX_INDEX];
for (size_t i = prefixes.range[SEG_CACHE_MIN_INDEX]; i <= maxGlyphCached; i++)
{
if (prefixes.array[i].raw)
{
if (level + 1 < ePrefixLength)
purgeLevel(store, prefixes.array[i], level + 1, minAccessCount, oldAccessTime);
else
{
SegCachePrefixEntry * prefixEntry = prefixes.prefixEntries[i];
m_segmentCount -= prefixEntry->purge(minAccessCount,
oldAccessTime, m_totalAccessCount);
}
}
}
}
uint32 SegCachePrefixEntry::purge(unsigned long long minAccessCount,
unsigned long long oldAccessTime,
unsigned long long currentTime)
{
// ignore the purge request if another has been done recently
//if (m_lastPurge > oldAccessTime)
// return 0;
uint32 totalPurged = 0;
// real length is length + 1 in this loop
for (uint16 length = 0; length < eMaxSpliceSize; length++)
{
if (m_entryCounts[length] == 0)
continue;
uint16 purgeCount = 0;
uint16 newIndex = 0;
for (uint16 j = 0; j < m_entryCounts[length]; j++)
{
SegCacheEntry & tempEntry = m_entries[length][j];
// purge entries with a low access count which haven't been
// accessed recently
if (tempEntry.accessCount() <= minAccessCount &&
tempEntry.lastAccess() <= oldAccessTime)
{
tempEntry.clear();
++purgeCount;
}
else
{
memcpy(m_entries[length] + newIndex++, m_entries[length] + j, sizeof(SegCacheEntry));
}
}
if (purgeCount == m_entryCounts[length])
{
assert(newIndex == 0);
m_entryCounts[length] = 0;
m_entryBSIndex[length] = 0;
free(m_entries[length]);
m_entries[length] = NULL;
}
else if (purgeCount > 0)
{
assert(m_entryCounts[length] == newIndex + purgeCount);
m_entryCounts[length] = newIndex;
}
totalPurged += purgeCount;
}
m_lastPurge = currentTime;
return totalPurged;
}
#endif

View file

@ -1,108 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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.
*/
#ifndef GRAPHITE2_NSEGCACHE
#include "inc/Main.h"
#include "inc/Slot.h"
#include "inc/Segment.h"
#include "inc/SegCache.h"
#include "inc/SegCacheEntry.h"
using namespace graphite2;
SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime)
: m_glyphLength(0), m_unicode(gralloc<uint16>(length)), m_glyph(NULL),
m_attr(NULL), m_justs(NULL),
m_accessCount(0), m_lastAccess(cacheTime)
{
if (m_unicode)
for (size_t i = 0; i < length; i++)
m_unicode[i] = cmapGlyphs[i];
const size_t glyphCount = seg->slotCount(),
sizeof_sjust = SlotJustify::size_of(seg->silf()->numJustLevels());
if (!glyphCount) return;
size_t num_justs = 0,
justs_pos = 0;
if (seg->hasJustification())
{
for (const Slot * s = seg->first(); s; s = s->next())
{
if (s->m_justs == 0) continue;
++num_justs;
}
m_justs = gralloc<byte>(sizeof_sjust * num_justs);
}
const Slot * slot = seg->first();
m_glyph = new Slot[glyphCount];
m_attr = gralloc<int16>(glyphCount * seg->numAttrs());
if (!m_glyph || (!m_attr && seg->numAttrs())) return;
m_glyphLength = glyphCount;
Slot * slotCopy = m_glyph;
m_glyph->prev(NULL);
uint16 pos = 0;
while (slot)
{
slotCopy->userAttrs(m_attr + pos * seg->numAttrs());
slotCopy->m_justs = m_justs ? reinterpret_cast<SlotJustify *>(m_justs + justs_pos++ * sizeof_sjust) : 0;
slotCopy->set(*slot, -static_cast<int32>(charOffset), seg->numAttrs(), seg->silf()->numJustLevels(), length);
slotCopy->index(pos);
if (slot->firstChild())
slotCopy->m_child = m_glyph + slot->firstChild()->index();
if (slot->attachedTo())
slotCopy->attachTo(m_glyph + slot->attachedTo()->index());
if (slot->nextSibling())
slotCopy->m_sibling = m_glyph + slot->nextSibling()->index();
slot = slot->next();
++slotCopy;
++pos;
if (slot)
{
slotCopy->prev(slotCopy-1);
(slotCopy-1)->next(slotCopy);
}
}
}
void SegCacheEntry::clear()
{
free(m_unicode);
free(m_attr);
free(m_justs);
delete [] m_glyph;
m_unicode = NULL;
m_glyph = NULL;
m_glyphLength = 0;
m_attr = NULL;
}
#endif

View file

@ -1,47 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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.
*/
#ifndef GRAPHITE2_NSEGCACHE
#include "inc/SegCacheStore.h"
#include "inc/Face.h"
using namespace graphite2;
SegCacheStore::SegCacheStore(const Face & face, unsigned int numSilf, size_t maxSegments)
: m_caches(new SilfSegCache[numSilf]),
m_numSilf(numSilf),
m_maxSegments(maxSegments),
m_maxCmapGid(face.glyphs().numGlyphs()),
m_spaceGid(face.cmap()[0x20]),
m_zwspGid(face.cmap()[0x200B])
{
}
#endif

View file

@ -42,7 +42,7 @@ of the License or (at your option) any later version.
using namespace graphite2;
Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir)
Segment::Segment(size_t numchars, const Face* face, uint32 script, int textDir)
: m_freeSlots(NULL),
m_freeJustifies(NULL),
m_charinfo(new CharInfo[numchars]),
@ -54,14 +54,12 @@ Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int tex
m_bufSize(numchars + 10),
m_numGlyphs(numchars),
m_numCharinfo(numchars),
m_passBits(m_silf->aPassBits() ? -1 : 0),
m_defaultOriginal(0),
m_dir(textDir),
m_flags(((m_silf->flags() & 0x20) != 0) << 1)
m_flags(((m_silf->flags() & 0x20) != 0) << 1),
m_passBits(m_silf->aPassBits() ? -1 : 0)
{
Slot *s = newSlot();
if (s)
freeSlot(s);
freeSlot(newSlot());
m_bufSize = log_binary(numchars)+1;
}
@ -77,71 +75,6 @@ Segment::~Segment()
free(m_collisions);
}
#ifndef GRAPHITE2_NSEGCACHE
SegmentScopeState Segment::setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength)
{
SegmentScopeState state;
state.numGlyphsOutsideScope = m_numGlyphs - subLength;
state.realFirstSlot = m_first;
state.slotBeforeScope = firstSlot->prev();
state.slotAfterScope = lastSlot->next();
state.realLastSlot = m_last;
firstSlot->prev(NULL);
lastSlot->next(NULL);
assert(m_defaultOriginal == 0);
m_defaultOriginal = firstSlot->original();
m_numGlyphs = subLength;
m_first = firstSlot;
m_last = lastSlot;
return state;
}
void Segment::removeScope(SegmentScopeState & state)
{
m_numGlyphs = state.numGlyphsOutsideScope + m_numGlyphs;
if (state.slotBeforeScope)
{
state.slotBeforeScope->next(m_first);
m_first->prev(state.slotBeforeScope);
m_first = state.realFirstSlot;
}
if (state.slotAfterScope)
{
state.slotAfterScope->prev(m_last);
m_last->next(state.slotAfterScope);
m_last = state.realLastSlot;
}
m_defaultOriginal = 0;
}
#if 0
void Segment::append(const Segment &other)
{
Rect bbox = other.m_bbox + m_advance;
m_slots.insert(m_slots.end(), other.m_slots.begin(), other.m_slots.end());
CharInfo* pNewCharInfo = new CharInfo[m_numCharinfo+other.m_numCharinfo]; //since CharInfo has no constructor, this doesn't do much
for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
pNewCharInfo[i] = m_charinfo[i];
m_last->next(other.m_first);
other.m_last->prev(m_last);
m_userAttrs.insert(m_userAttrs.end(), other.m_userAttrs.begin(), other.m_userAttrs.end());
delete[] m_charinfo;
m_charinfo = pNewCharInfo;
pNewCharInfo += m_numCharinfo ;
for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
pNewCharInfo[i] = other.m_charinfo[i];
m_numCharinfo += other.m_numCharinfo;
m_numGlyphs += other.m_numGlyphs;
m_advance = m_advance + other.m_advance;
m_bbox = m_bbox.widen(bbox);
m_passBits &= other.passBits();
}
#endif
#endif // GRAPHITE2_NSEGCACHE
void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
{
Slot *aSlot = newSlot();
@ -206,6 +139,7 @@ Slot *Segment::newSlot()
void Segment::freeSlot(Slot *aSlot)
{
if (aSlot == nullptr) return;
if (m_last == aSlot) m_last = aSlot->prev();
if (m_first == aSlot) m_first = aSlot->next();
if (aSlot->attachedTo())
@ -214,11 +148,11 @@ void Segment::freeSlot(Slot *aSlot)
{
if (aSlot->firstChild()->attachedTo() == aSlot)
{
aSlot->firstChild()->attachTo(NULL);
aSlot->firstChild()->attachTo(nullptr);
aSlot->removeChild(aSlot->firstChild());
}
else
aSlot->firstChild(NULL);
aSlot->firstChild(nullptr);
}
// reset the slot incase it is reused
::new (aSlot) Slot(aSlot->userAttrs());
@ -230,7 +164,7 @@ void Segment::freeSlot(Slot *aSlot)
#endif
// update next pointer
if (!m_freeSlots)
aSlot->next(NULL);
aSlot->next(nullptr);
else
aSlot->next(m_freeSlots);
m_freeSlots = aSlot;
@ -243,7 +177,7 @@ SlotJustify *Segment::newJustify()
const size_t justSize = SlotJustify::size_of(m_silf->numJustLevels());
byte *justs = grzeroalloc<byte>(justSize * m_bufSize);
if (!justs) return NULL;
for (int i = m_bufSize - 2; i >= 0; --i)
for (ptrdiff_t i = m_bufSize - 2; i >= 0; --i)
{
SlotJustify *p = reinterpret_cast<SlotJustify *>(justs + justSize * i);
SlotJustify *next = reinterpret_cast<SlotJustify *>(justs + justSize * (i + 1));
@ -267,64 +201,6 @@ void Segment::freeJustify(SlotJustify *aJustify)
m_freeJustifies = aJustify;
}
#ifndef GRAPHITE2_NSEGCACHE
void Segment::splice(size_t offset, size_t length, Slot * const startSlot,
Slot * endSlot, const Slot * srcSlot,
const size_t numGlyphs)
{
size_t numChars = length;
extendLength(numGlyphs - length);
// remove any extra
if (numGlyphs < length)
{
Slot * end = endSlot->next();
do
{
endSlot = endSlot->prev();
freeSlot(endSlot->next());
} while (numGlyphs < --length);
endSlot->next(end);
if (end)
end->prev(endSlot);
}
else
{
// insert extra slots if needed
while (numGlyphs > length)
{
Slot * extra = newSlot();
if (!extra) return;
extra->prev(endSlot);
extra->next(endSlot->next());
endSlot->next(extra);
if (extra->next())
extra->next()->prev(extra);
if (m_last == endSlot)
m_last = extra;
endSlot = extra;
++length;
}
}
endSlot = endSlot->next();
assert(numGlyphs == length);
assert(offset + numChars <= m_numCharinfo);
Slot * indexmap[eMaxSpliceSize*3];
assert(numGlyphs < sizeof indexmap/sizeof *indexmap);
Slot * slot = startSlot;
for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i)
indexmap[i] = slot;
for (slot = startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next())
{
slot->set(*srcSlot, offset, m_silf->numUser(), m_silf->numJustLevels(), numChars);
if (srcSlot->attachedTo()) slot->attachTo(indexmap[srcSlot->attachedTo()->index()]);
if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()];
if (srcSlot->firstChild()) slot->m_child = indexmap[srcSlot->firstChild()->index()];
}
}
#endif // GRAPHITE2_NSEGCACHE
// reverse the slots but keep diacritics in their same position after their bases
void Segment::reverseSlots()
{
@ -452,7 +328,7 @@ Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bo
}
void Segment::associateChars(int offset, int numChars)
void Segment::associateChars(int offset, size_t numChars)
{
int i = 0, j = 0;
CharInfo *c, *cend;
@ -476,7 +352,7 @@ void Segment::associateChars(int offset, int numChars)
for (Slot *s = m_first; s; s = s->next())
{
int a;
for (a = s->after() + 1; a < offset + numChars && charinfo(a)->after() < 0; ++a)
for (a = s->after() + 1; a < offset + int(numChars) && charinfo(a)->after() < 0; ++a)
{ charinfo(a)->after(s->index()); }
--a;
s->after(a);

View file

@ -199,7 +199,7 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face,
{
uint32 pass_start = be::read<uint32>(o_passes);
uint32 pass_end = be::peek<uint32>(o_passes);
face.error_context((face.error_context() & 0xFF00) + EC_ASILF + (i << 16));
face.error_context((face.error_context() & 0xFF00) + EC_ASILF + unsigned(i << 16));
if (e.test(pass_start > pass_end, E_BADPASSSTART)
|| e.test(pass_start < passes_start, E_BADPASSSTART)
|| e.test(pass_end > lSilf, E_BADPASSEND)) {
@ -233,7 +233,7 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face,
template<typename T> inline uint32 Silf::readClassOffsets(const byte *&p, size_t data_len, Error &e)
{
const T cls_off = 2*sizeof(uint16) + sizeof(T)*(m_nClass+1);
const size_t max_off = (be::peek<T>(p + sizeof(T)*m_nClass) - cls_off)/sizeof(uint16);
const uint32 max_off = (be::peek<T>(p + sizeof(T)*m_nClass) - cls_off)/sizeof(uint16);
// Check that the last+1 offset is less than or equal to the class map length.
if (e.test(be::peek<T>(p) != cls_off, E_MISALIGNEDCLASSES)
|| e.test(max_off > (data_len - cls_off)/sizeof(uint16), E_HIGHCLASSOFFSET))
@ -357,7 +357,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);
unsigned int maxSize = seg->slotCount() * MAX_SEG_GROWTH_FACTOR;
size_t maxSize = seg->slotCount() * MAX_SEG_GROWTH_FACTOR;
SlotMap map(*seg, m_dir, maxSize);
FiniteStateMachine fsm(map, seg->getFace()->logger());
vm::Machine m(map);

View file

@ -57,7 +57,7 @@ void Slot::set(const Slot & orig, int charOffset, size_t sizeAttr, size_t justLe
else
m_before = orig.m_before + charOffset;
if (charOffset <= 0 && orig.m_after + charOffset >= numChars)
m_after = numChars - 1;
m_after = int(numChars) - 1;
else
m_after = orig.m_after + charOffset;
m_parent = NULL;
@ -165,25 +165,25 @@ int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel, boo
switch (metrics(metric))
{
case kgmetLsb :
return bbox.bl.x;
return int32(bbox.bl.x);
case kgmetRsb :
return res.x - bbox.tr.x;
return int32(res.x - bbox.tr.x);
case kgmetBbTop :
return bbox.tr.y;
return int32(bbox.tr.y);
case kgmetBbBottom :
return bbox.bl.y;
return int32(bbox.bl.y);
case kgmetBbLeft :
return bbox.bl.x;
return int32(bbox.bl.x);
case kgmetBbRight :
return bbox.tr.x;
return int32(bbox.tr.x);
case kgmetBbWidth :
return bbox.tr.x - bbox.bl.x;
return int32(bbox.tr.x - bbox.bl.x);
case kgmetBbHeight :
return bbox.tr.y - bbox.bl.y;
return int32(bbox.tr.y - bbox.bl.y);
case kgmetAdvWidth :
return res.x;
return int32(res.x);
case kgmetAdvHeight :
return res.y;
return int32(res.y);
default :
return 0;
}
@ -193,14 +193,7 @@ int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel, boo
int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
{
if (ind == gr_slatUserDefnV1)
{
ind = gr_slatUserDefn;
subindex = 0;
if (seg->numAttrs() == 0)
return 0;
}
else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
{
int indx = ind - gr_slatJStretch;
return getJustify(seg, indx / 5, indx % 5);
@ -231,30 +224,32 @@ int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
case gr_slatMeasureSol: return -1; // err what's this?
case gr_slatMeasureEol: return -1;
case gr_slatJWidth: return int(m_just);
case gr_slatUserDefn : return m_userAttr[subindex];
case gr_slatUserDefnV1: subindex = 0; GR_FALLTHROUGH;
// no break
case gr_slatUserDefn : return subindex < seg->numAttrs() ? m_userAttr[subindex] : 0;
case gr_slatSegSplit : return seg->charinfo(m_original)->flags() & 3;
case gr_slatBidiLevel: return m_bidiLevel;
case gr_slatColFlags : { SlotCollision *c = seg->collisionInfo(this); return c ? c->flags() : 0; }
case gr_slatColLimitblx : SLOTGETCOLATTR(limit().bl.x)
case gr_slatColLimitbly : SLOTGETCOLATTR(limit().bl.y)
case gr_slatColLimittrx : SLOTGETCOLATTR(limit().tr.x)
case gr_slatColLimittry : SLOTGETCOLATTR(limit().tr.y)
case gr_slatColLimitblx:SLOTGETCOLATTR(limit().bl.x)
case gr_slatColLimitbly:SLOTGETCOLATTR(limit().bl.y)
case gr_slatColLimittrx:SLOTGETCOLATTR(limit().tr.x)
case gr_slatColLimittry:SLOTGETCOLATTR(limit().tr.y)
case gr_slatColShiftx : SLOTGETCOLATTR(offset().x)
case gr_slatColShifty : SLOTGETCOLATTR(offset().y)
case gr_slatColMargin : SLOTGETCOLATTR(margin())
case gr_slatColMarginWt : SLOTGETCOLATTR(marginWt())
case gr_slatColExclGlyph : SLOTGETCOLATTR(exclGlyph())
case gr_slatColExclOffx : SLOTGETCOLATTR(exclOffset().x)
case gr_slatColExclOffy : SLOTGETCOLATTR(exclOffset().y)
case gr_slatColMarginWt:SLOTGETCOLATTR(marginWt())
case gr_slatColExclGlyph:SLOTGETCOLATTR(exclGlyph())
case gr_slatColExclOffx:SLOTGETCOLATTR(exclOffset().x)
case gr_slatColExclOffy:SLOTGETCOLATTR(exclOffset().y)
case gr_slatSeqClass : SLOTGETCOLATTR(seqClass())
case gr_slatSeqProxClass : SLOTGETCOLATTR(seqProxClass())
case gr_slatSeqProxClass:SLOTGETCOLATTR(seqProxClass())
case gr_slatSeqOrder : SLOTGETCOLATTR(seqOrder())
case gr_slatSeqAboveXoff : SLOTGETCOLATTR(seqAboveXoff())
case gr_slatSeqAboveWt : SLOTGETCOLATTR(seqAboveWt())
case gr_slatSeqBelowXlim : SLOTGETCOLATTR(seqBelowXlim())
case gr_slatSeqBelowWt : SLOTGETCOLATTR(seqBelowWt())
case gr_slatSeqValignHt : SLOTGETCOLATTR(seqValignHt())
case gr_slatSeqValignWt : SLOTGETCOLATTR(seqValignWt())
case gr_slatSeqAboveXoff:SLOTGETCOLATTR(seqAboveXoff())
case gr_slatSeqAboveWt: SLOTGETCOLATTR(seqAboveWt())
case gr_slatSeqBelowXlim:SLOTGETCOLATTR(seqBelowXlim())
case gr_slatSeqBelowWt: SLOTGETCOLATTR(seqBelowWt())
case gr_slatSeqValignHt:SLOTGETCOLATTR(seqValignHt())
case gr_slatSeqValignWt:SLOTGETCOLATTR(seqValignWt())
default : return 0;
}
}
@ -480,7 +475,7 @@ void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
m_advance = Position(aGlyph->theAdvance().x, 0.);
if (seg->silf()->aPassBits())
{
seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]);
seg->mergePassBits(uint8(theGlyph->attrs()[seg->silf()->aPassBits()]));
if (seg->silf()->numPasses() > 16)
seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()+1] << 16);
}
@ -532,4 +527,3 @@ bool Slot::isChildOf(const Slot *base) const
return true;
return false;
}

View file

@ -1252,7 +1252,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 + pByte < pByte || nGlyfOffset >= nTableLen - sizeof(Sfnt::Glyph))
if (OVERFLOW_OFFSET_CHECK(pByte, nGlyfOffset) || nGlyfOffset >= nTableLen - sizeof(Sfnt::Glyph))
return NULL;
return const_cast<uint8 *>(pByte + nGlyfOffset);
}
@ -1670,7 +1670,7 @@ void * GlyfLookup(gid16 nGlyphId, const void * pGlyf, const void * pLoca,
}
}
long lGlyfOffset = LocaLookup(nGlyphId, pLoca, lLocaSize, pHead);
size_t lGlyfOffset = LocaLookup(nGlyphId, pLoca, lLocaSize, pHead);
void * pSimpleGlyf = GlyfLookup(pGlyf, lGlyfOffset, lGlyfSize); // invalid loca offset returns null
return pSimpleGlyf;
}

View file

@ -136,5 +136,3 @@ const opcode_t * Machine::getOpcodeTable() throw()
{
return opcode_table;
}

View file

@ -118,4 +118,3 @@ Machine::stack_t Machine::run(const instr * program,
check_final_stack(sp);
return ret;
}

View file

@ -63,9 +63,6 @@ $(_NS)_SOURCES = \
$($(_NS)_BASE)/src/NameTable.cpp \
$($(_NS)_BASE)/src/Pass.cpp \
$($(_NS)_BASE)/src/Position.cpp \
$($(_NS)_BASE)/src/SegCache.cpp \
$($(_NS)_BASE)/src/SegCacheEntry.cpp \
$($(_NS)_BASE)/src/SegCacheStore.cpp \
$($(_NS)_BASE)/src/Segment.cpp \
$($(_NS)_BASE)/src/Silf.cpp \
$($(_NS)_BASE)/src/Slot.cpp \
@ -104,9 +101,6 @@ $(_NS)_PRIVATE_HEADERS = \
$($(_NS)_BASE)/src/inc/Pass.h \
$($(_NS)_BASE)/src/inc/Position.h \
$($(_NS)_BASE)/src/inc/Rule.h \
$($(_NS)_BASE)/src/inc/SegCache.h \
$($(_NS)_BASE)/src/inc/SegCacheEntry.h \
$($(_NS)_BASE)/src/inc/SegCacheStore.h \
$($(_NS)_BASE)/src/inc/Segment.h \
$($(_NS)_BASE)/src/inc/Silf.h \
$($(_NS)_BASE)/src/inc/Slot.h \
@ -120,4 +114,3 @@ $(_NS)_PUBLIC_HEADERS = \
$($(_NS)_BASE)/include/graphite2/Log.h \
$($(_NS)_BASE)/include/graphite2/Segment.h \
$($(_NS)_BASE)/include/graphite2/Types.h

View file

@ -28,7 +28,6 @@ of the License or (at your option) any later version.
#include "inc/Face.h"
#include "inc/FileFace.h"
#include "inc/GlyphCache.h"
#include "inc/CachedFace.h"
#include "inc/CmapCache.h"
#include "inc/Silf.h"
#include "inc/json.h"
@ -47,8 +46,7 @@ namespace
telemetry::category _misc_cat(face.tele.misc);
#endif
Face::Table silf(face, Tag::Silf, 0x00050000);
if (silf) options &= ~gr_face_dumbRendering;
else if (!(options & gr_face_dumbRendering))
if (!silf)
return false;
if (!face.readGlyphs(options))
@ -74,7 +72,17 @@ namespace
return true;
}
else
return options & gr_face_dumbRendering;
return false;
}
inline
uint32 zeropad(const uint32 x)
{
if (x == 0x20202020) return 0;
if ((x & 0x00FFFFFF) == 0x00202020) return x & 0xFF000000;
if ((x & 0x0000FFFF) == 0x00002020) return x & 0xFFFF0000;
if ((x & 0x000000FF) == 0x00000020) return x & 0xFFFFFF00;
return x;
}
}
@ -99,56 +107,41 @@ gr_face* gr_make_face(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn tab
return gr_make_face_with_ops(appFaceHandle, &ops, faceOptions);
}
#ifndef GRAPHITE2_NSEGCACHE
gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int cacheSize, unsigned int faceOptions)
//the appFaceHandle must stay alive all the time when the GrFace is alive. When finished with the GrFace, call destroy_face
gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int , unsigned int faceOptions)
{
if (ops == 0) return 0;
CachedFace *res = new CachedFace(appFaceHandle, *ops);
if (res && load_face(*res, faceOptions)
&& res->setupCache(cacheSize))
return static_cast<gr_face *>(static_cast<Face *>(res));
delete res;
return 0;
return gr_make_face_with_ops(appFaceHandle, ops, faceOptions);
}
gr_face* gr_make_face_with_seg_cache(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn getTable, unsigned int cacheSize, unsigned int faceOptions)
gr_face* gr_make_face_with_seg_cache(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn tablefn, unsigned int, unsigned int faceOptions)
{
const gr_face_ops ops = {sizeof(gr_face_ops), getTable, NULL};
return gr_make_face_with_seg_cache_and_ops(appFaceHandle, &ops, cacheSize, faceOptions);
const gr_face_ops ops = {sizeof(gr_face_ops), tablefn, NULL};
return gr_make_face_with_ops(appFaceHandle, &ops, faceOptions);
}
#endif
gr_uint32 gr_str_to_tag(const char *str)
{
uint32 res = 0;
int i = strlen(str);
if (i > 4) i = 4;
while (--i >= 0)
res = (res >> 8) + (str[i] << 24);
switch(max(strlen(str),size_t(4)))
{
case 4: res |= str[3]; GR_FALLTHROUGH;
case 3: res |= str[2] << 8; GR_FALLTHROUGH;
case 2: res |= str[1] << 16; GR_FALLTHROUGH;
case 1: res |= str[0] << 24; GR_FALLTHROUGH;
default: break;
}
return res;
}
void gr_tag_to_str(gr_uint32 tag, char *str)
{
int i = 4;
while (--i >= 0)
{
str[i] = tag & 0xFF;
tag >>= 8;
}
}
if (!str) return;
inline
uint32 zeropad(const uint32 x)
{
if (x == 0x20202020) return 0;
if ((x & 0x00FFFFFF) == 0x00202020) return x & 0xFF000000;
if ((x & 0x0000FFFF) == 0x00002020) return x & 0xFFFF0000;
if ((x & 0x000000FF) == 0x00000020) return x & 0xFFFFFF00;
return x;
*str++ = char(tag >> 24);
*str++ = char(tag >> 16);
*str++ = char(tag >> 8);
*str++ = char(tag);
*str = '\0';
}
gr_feature_val* gr_face_featureval_for_lang(const gr_face* pFace, gr_uint32 langname/*0 means clone default*/) //clones the features. if none for language, clones the default
@ -253,30 +246,11 @@ gr_face* gr_make_file_face(const char *filename, unsigned int faceOptions)
return NULL;
}
#ifndef GRAPHITE2_NSEGCACHE
gr_face* gr_make_file_face_with_seg_cache(const char* filename, unsigned int segCacheMaxSize, unsigned int faceOptions) //returns NULL on failure. //TBD better error handling
gr_face* gr_make_file_face_with_seg_cache(const char* filename, unsigned int, unsigned int faceOptions) //returns NULL on failure. //TBD better error handling
//when finished with, call destroy_face
{
FileFace* pFileFace = new FileFace(filename);
if (*pFileFace)
{
gr_face * pRes = gr_make_face_with_seg_cache_and_ops(pFileFace, &FileFace::ops, segCacheMaxSize, faceOptions);
if (pRes)
{
pRes->takeFileFace(pFileFace); //takes ownership
return pRes;
}
}
//error when loading
delete pFileFace;
return NULL;
return gr_make_file_face(filename, faceOptions);
}
#endif
#endif //!GRAPHITE2_NFILEFACE
} // extern "C"

View file

@ -72,7 +72,3 @@ void gr_font_destroy(gr_font *font)
} // extern "C"

View file

@ -252,14 +252,14 @@ json & graphite2::operator << (json & j, const dslot & ds) throw()
graphite2::objectid::objectid(const dslot & ds) throw()
{
const Slot * const p = ds.second;
uint32 s = reinterpret_cast<size_t>(p);
uint32 s = uint32(reinterpret_cast<size_t>(p));
sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), uint16(p ? p->userAttrs()[ds.first->silf()->numUser()] : 0), uint16(s));
name[sizeof name-1] = 0;
}
graphite2::objectid::objectid(const Segment * const p) throw()
{
uint32 s = reinterpret_cast<size_t>(p);
uint32 s = uint32(reinterpret_cast<size_t>(p));
sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), 0, uint16(s));
name[sizeof name-1] = 0;
}

View file

@ -53,18 +53,19 @@ namespace
return static_cast<gr_segment*>(pRes);
}
}
template <typename utf_iter>
inline size_t count_unicode_chars(utf_iter first, const utf_iter last, const void **error)
{
template <typename utf_iter>
inline size_t count_unicode_chars(utf_iter first, const utf_iter last, const void **error)
{
size_t n_chars = 0;
uint32 usv = 0;
if (last)
{
if (!first.validate(last))
{
if (error) *error = last - 1;
return 0;
}
for (;first != last; ++first, ++n_chars)
if ((usv = *first) == 0 || first.error()) break;
}
@ -79,8 +80,10 @@ inline size_t count_unicode_chars(utf_iter first, const utf_iter last, const voi
if (error) *error = first.error() ? first : 0;
return n_chars;
}
}
extern "C" {
size_t gr_count_unicode_characters(gr_encform enc, const void* buffer_begin, const void* buffer_end/*don't go on or past end, If NULL then ignored*/, const void** pError) //Also stops on nul. Any nul is not in the count
@ -99,6 +102,8 @@ size_t gr_count_unicode_characters(gr_encform enc, const void* buffer_begin, con
gr_segment* gr_make_seg(const gr_font *font, const gr_face *face, gr_uint32 script, const gr_feature_val* pFeats, gr_encform enc, const void* pStart, size_t nChars, int dir)
{
if (!face) return nullptr;
const gr_feature_val * tmp_feats = 0;
if (pFeats == 0)
pFeats = tmp_feats = static_cast<const gr_feature_val*>(face->theSill().cloneFeatures(0));
@ -132,7 +137,7 @@ float gr_seg_advance_Y(const gr_segment* pSeg/*not NULL*/)
unsigned int gr_seg_n_cinfo(const gr_segment* pSeg/*not NULL*/)
{
assert(pSeg);
return pSeg->charInfoCount();
return static_cast<unsigned int>(pSeg->charInfoCount());
}
@ -145,7 +150,7 @@ const gr_char_info* gr_seg_cinfo(const gr_segment* pSeg/*not NULL*/, unsigned in
unsigned int gr_seg_n_slots(const gr_segment* pSeg/*not NULL*/)
{
assert(pSeg);
return pSeg->slotCount();
return static_cast<unsigned int>(pSeg->slotCount());
}
const gr_slot* gr_seg_first_slot(gr_segment* pSeg/*not NULL*/)

View file

@ -170,4 +170,3 @@ size_t id(const gr_slot* p/*not NULL*/)
} // extern "C"

View file

@ -1,56 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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
#ifndef GRAPHITE2_NSEGCACHE
#include "inc/Face.h"
namespace graphite2 {
class SegCacheStore;
class SegCache;
class CachedFace : public Face
{
CachedFace(const CachedFace &);
CachedFace & operator = (const CachedFace &);
public:
CachedFace(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops);
bool setupCache(unsigned int cacheSize);
virtual ~CachedFace();
virtual bool runGraphite(Segment *seg, const Silf *silf) const;
SegCacheStore * cacheStore() { return m_cacheStore; }
private:
SegCacheStore * m_cacheStore;
};
} // namespace graphite2
#endif

View file

@ -64,4 +64,3 @@ private:
} // namespace graphite2
struct gr_char_info : public graphite2::CharInfo {};

View file

@ -243,4 +243,3 @@ KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
};
}; // end of namespace graphite2

View file

@ -102,5 +102,3 @@ u8 * fast_copy(u8 * d, u8 const * s, size_t n) {
} // end of anonymous namespace

View file

@ -52,5 +52,3 @@ namespace lz4
int decompress(void const *in, size_t in_size, void *out, size_t out_size);
} // end of namespace shrinker

View file

@ -109,4 +109,3 @@ public:
template<>
inline unsigned long int le::_peek<1>(const unsigned char * p) { return *p; }

View file

@ -132,4 +132,3 @@ enum errors {
};
}

View file

@ -170,23 +170,23 @@ class Face::Table
{
const Face * _f;
mutable const byte * _p;
uint32 _sz;
size_t _sz;
bool _compressed;
Error decompress();
void releaseBuffers();
void release();
public:
Table() throw();
Table(const Face & face, const Tag n, uint32 version=0xffffffff) throw();
Table(const Table & rhs) throw();
~Table() throw();
Table(const Table && rhs) throw();
operator const byte * () const throw();
Table & operator = (const Table & rhs) throw();
size_t size() const throw();
Table & operator = (const Table && rhs) throw();
};
inline
@ -196,7 +196,7 @@ Face::Table::Table() throw()
}
inline
Face::Table::Table(const Table & rhs) throw()
Face::Table::Table(const Table && rhs) throw()
: _f(rhs._f), _p(rhs._p), _sz(rhs._sz), _compressed(rhs._compressed)
{
rhs._p = 0;
@ -205,7 +205,7 @@ Face::Table::Table(const Table & rhs) throw()
inline
Face::Table::~Table() throw()
{
releaseBuffers();
release();
}
inline

View file

@ -86,7 +86,7 @@ struct telemetry {};
#define HAVE_BUILTIN_OVERFLOW
#endif
#if defined(__has_include)
#if __has_include(<intsafe.h>)
#if __has_include(<intsafe.h>) && !defined(__CYGWIN__)
#define HAVE_INTSAFE_H
#endif
#elif defined(_WIN32)
@ -172,9 +172,14 @@ inline T max(const T a, const T b)
#define GR_MAYBE_UNUSED
#endif
#if defined(__clang__) && __cplusplus >= 201103L
/* clang's fallthrough annotations are only available starting in C++11. */
#define GR_FALLTHROUGH [[fallthrough]]
#ifndef __has_cpp_attribute
# define __has_cpp_attribute(x) 0
#endif
#if __has_cpp_attribute(clang::fallthrough)
# define GR_FALLTHROUGH [[clang::fallthrough]]
#elif __has_cpp_attribute(gnu::fallthrough)
# define GR_FALLTHROUGH [[gnu::fallthrough]]
#elif defined(_MSC_VER)
/*
* MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):

View file

@ -102,7 +102,7 @@ class SlotMap
{
public:
enum {MAX_SLOTS=64};
SlotMap(Segment & seg, uint8 direction, int maxSize);
SlotMap(Segment & seg, uint8 direction, size_t maxSize);
Slot * * begin();
Slot * * end();
@ -244,9 +244,9 @@ void FiniteStateMachine::Rules::accumulate_rules(const State &state)
}
inline
SlotMap::SlotMap(Segment & seg, uint8 direction, int maxSize)
SlotMap::SlotMap(Segment & seg, uint8 direction, size_t maxSize)
: segment(seg), m_size(0), m_precontext(0), m_highwater(0),
m_maxSize(maxSize), m_dir(direction), m_highpassed(false)
m_maxSize(int(maxSize)), m_dir(direction), m_highpassed(false)
{
m_slot_map[0] = 0;
}

View file

@ -1,316 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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
#ifndef GRAPHITE2_NSEGCACHE
#include <graphite2/Segment.h>
#include "inc/Main.h"
#include "inc/Slot.h"
#include "inc/FeatureVal.h"
#include "inc/SegCacheEntry.h"
#include "inc/Segment.h"
namespace graphite2 {
class SegCache;
class SegCacheEntry;
class SegCacheStore;
/**
* SegPrefixEntry stores lists of word/syllable segments
* with one list for each word length. The prefix size should be chosen so that
* these list sizes stay small since they will be searched iteratively.
*/
class SegCachePrefixEntry
{
SegCachePrefixEntry(const SegCachePrefixEntry &);
SegCachePrefixEntry & operator = (const SegCachePrefixEntry &);
public:
SegCachePrefixEntry() : m_lastPurge(0)
{
memset(m_entryCounts, 0, sizeof m_entryCounts);
memset(m_entryBSIndex, 0, sizeof m_entryBSIndex);
memset(m_entries, 0, sizeof m_entries);
}
~SegCachePrefixEntry()
{
for (size_t j = 0; j < eMaxSpliceSize; j++)
{
if (m_entryCounts[j])
{
assert(m_entries[j]);
for (size_t k = 0; k < m_entryCounts[j]; k++)
m_entries[j][k].clear();
free(m_entries[j]);
}
}
}
const SegCacheEntry * find(const uint16 * cmapGlyphs, size_t length) const
{
if (length <= ePrefixLength)
{
assert(m_entryCounts[length-1] <= 1);
if (m_entries[length-1])
return m_entries[length-1];
return NULL;
}
SegCacheEntry * entry = NULL;
findPosition(cmapGlyphs, length, &entry);
return entry;
}
SegCacheEntry * cache(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, unsigned long long totalAccessCount)
{
size_t listSize = m_entryBSIndex[length-1]? (m_entryBSIndex[length-1] << 1) - 1 : 0;
SegCacheEntry * newEntries = NULL;
if (m_entryCounts[length-1] + 1u > listSize)
{
if (m_entryCounts[length-1] == 0)
listSize = 1;
else
{
// the problem comes when you get incremental numeric ids in a large doc
if (listSize >= eMaxSuffixCount)
return NULL;
listSize = (m_entryBSIndex[length-1] << 2) - 1;
}
newEntries = gralloc<SegCacheEntry>(listSize);
if (!newEntries)
return NULL;
}
uint16 insertPos = 0;
if (m_entryCounts[length-1] > 0)
{
insertPos = findPosition(cmapGlyphs, length, NULL);
if (!newEntries)
{
// same buffer, shift entries up
memmove(m_entries[length-1] + insertPos + 1, m_entries[length-1] + insertPos,
sizeof(SegCacheEntry) * (m_entryCounts[length-1] - insertPos));
}
else
{
memcpy(newEntries, m_entries[length-1], sizeof(SegCacheEntry) * (insertPos));
memcpy(newEntries + insertPos + 1, m_entries[length-1] + insertPos,
sizeof(SegCacheEntry) * (m_entryCounts[length-1] - insertPos));
free(m_entries[length-1]);
m_entries[length-1] = newEntries;
assert (m_entryBSIndex[length-1]);
m_entryBSIndex[length-1] <<= 1;
}
}
else
{
m_entryBSIndex[length-1] = 1;
m_entries[length-1] = newEntries;
}
m_entryCounts[length-1] += 1;
new (m_entries[length-1] + insertPos)
SegCacheEntry(cmapGlyphs, length, seg, charOffset, totalAccessCount);
return m_entries[length-1] + insertPos;
}
uint32 purge(unsigned long long minAccessCount, unsigned long long oldAccessTime,
unsigned long long currentTime);
CLASS_NEW_DELETE
private:
uint16 findPosition(const uint16 * cmapGlyphs, uint16 length, SegCacheEntry ** entry) const
{
int dir = 0;
if (m_entryCounts[length-1] == 0)
{
if (entry) *entry = NULL;
return 0;
}
else if (m_entryCounts[length-1] == 1)
{
// optimize single entry case
for (int i = ePrefixLength; i < length; i++)
{
if (cmapGlyphs[i] > m_entries[length-1][0].m_unicode[i])
{
return 1;
}
else if (cmapGlyphs[i] < m_entries[length-1][0].m_unicode[i])
{
return 0;
}
}
if (entry)
*entry = m_entries[length-1];
return 0;
}
uint16 searchIndex = m_entryBSIndex[length-1] - 1;
uint16 stepSize = m_entryBSIndex[length-1] >> 1;
size_t prevIndex = searchIndex;
do
{
dir = 0;
if (searchIndex >= m_entryCounts[length-1])
{
dir = -1;
searchIndex -= stepSize;
stepSize >>= 1;
}
else
{
for (int i = ePrefixLength; i < length; i++)
{
if (cmapGlyphs[i] > m_entries[length-1][searchIndex].m_unicode[i])
{
dir = 1;
searchIndex += stepSize;
stepSize >>= 1;
break;
}
else if (cmapGlyphs[i] < m_entries[length-1][searchIndex].m_unicode[i])
{
dir = -1;
searchIndex -= stepSize;
stepSize >>= 1;
break;
}
}
}
if (prevIndex == searchIndex)
break;
prevIndex = searchIndex;
} while (dir != 0);
if (entry)
{
if (dir == 0)
*entry = m_entries[length-1] + searchIndex;
else
*entry = NULL;
}
else
{
// if entry is null, then this is for inserting a new value, which
// shouldn't already be in the cache
assert(dir != 0);
if (dir > 0)
++searchIndex;
}
return searchIndex;
}
/** m_entries is a null terminated list of entries */
uint16 m_entryCounts[eMaxSpliceSize];
uint16 m_entryBSIndex[eMaxSpliceSize];
SegCacheEntry * m_entries[eMaxSpliceSize];
unsigned long long m_lastPurge;
};
#define SEG_CACHE_MIN_INDEX (store->maxCmapGid())
#define SEG_CACHE_MAX_INDEX (store->maxCmapGid()+1u)
#define SEG_CACHE_UNSET_INDEX (store->maxCmapGid()+2u)
union SegCachePrefixArray
{
void ** raw;
SegCachePrefixArray * array;
SegCachePrefixEntry ** prefixEntries;
uintptr * range;
};
class SegCache
{
public:
SegCache(const SegCacheStore * store, const Features& features);
~SegCache();
const SegCacheEntry * find(const uint16 * cmapGlyphs, size_t length) const;
SegCacheEntry * cache(SegCacheStore * store, const uint16 * cmapGlyphs, size_t length, Segment * seg, size_t charOffset);
void purge(SegCacheStore * store);
long long totalAccessCount() const { return m_totalAccessCount; }
size_t segmentCount() const { return m_segmentCount; }
const Features & features() const { return m_features; }
void clear(SegCacheStore * store);
CLASS_NEW_DELETE
private:
void freeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level);
void purgeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level,
unsigned long long minAccessCount, unsigned long long oldAccessTime);
uint16 m_prefixLength;
// uint16 m_maxCachedSegLength;
size_t m_segmentCount;
SegCachePrefixArray m_prefixes;
Features m_features;
mutable unsigned long long m_totalAccessCount;
mutable unsigned long long m_totalMisses;
float m_purgeFactor;
};
inline const SegCacheEntry * SegCache::find(const uint16 * cmapGlyphs, size_t length) const
{
uint16 pos = 0;
if (!length || length > eMaxSpliceSize) return NULL;
SegCachePrefixArray pEntry = m_prefixes.array[cmapGlyphs[0]];
while (++pos < m_prefixLength - 1)
{
if (!pEntry.raw)
{
++m_totalMisses;
return NULL;
}
pEntry = pEntry.array[(pos < length)? cmapGlyphs[pos] : 0];
}
if (!pEntry.raw)
{
++m_totalMisses;
return NULL;
}
SegCachePrefixEntry * prefixEntry = pEntry.prefixEntries[(pos < length)? cmapGlyphs[pos] : 0];
if (!prefixEntry)
{
++m_totalMisses;
return NULL;
}
const SegCacheEntry * entry = prefixEntry->find(cmapGlyphs, length);
if (entry)
{
++m_totalAccessCount;
entry->accessed(m_totalAccessCount);
}
else
{
++m_totalMisses;
}
return entry;
}
} // namespace graphite2
#endif

View file

@ -1,121 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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
#ifndef GRAPHITE2_NSEGCACHE
#include "inc/Main.h"
#include "inc/Slot.h"
namespace graphite2 {
class Segment;
class Slot;
class SegCacheEntry;
class SegCachePrefixEntry;
enum SegCacheParameters {
/** number of characters used in initial prefix tree */
ePrefixLength = 2,
/** Segments more recent than maxSegmentCount() / eAgeFactor are kept */
eAgeFactor = 4,
/** Segments are purged according to the formular:
* accessCount < (totalAccesses)/(ePurgeFactor * maxSegments) */
ePurgeFactor = 5,
/** Maximum number of Segments to store which have the same
* prefix. Needed to prevent unique identifiers flooding the cache */
eMaxSuffixCount = 15
};
class SegCacheCharInfo
{
public:
uint16 m_unicode;
uint16 m_before;
uint16 m_after;
};
/**
* SegCacheEntry stores the result of running the engine for specific unicode
* code points in the typical mid-line situation.
*/
class SegCacheEntry
{
// Prevent any implict copying;
SegCacheEntry(const SegCacheEntry &);
SegCacheEntry & operator = (const SegCacheEntry &);
friend class SegCachePrefixEntry;
public:
SegCacheEntry() :
m_glyphLength(0), m_unicode(NULL), m_glyph(NULL), m_attr(NULL), m_justs(0),
m_accessCount(0), m_lastAccess(0)
{}
SegCacheEntry(const uint16 * cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime);
~SegCacheEntry() { clear(); };
void clear();
size_t glyphLength() const { return m_glyphLength; }
const Slot * first() const { return m_glyph; }
const Slot * last() const { return m_glyph + (m_glyphLength - 1); }
/** Total number of times this entry has been accessed since creation */
unsigned long long accessCount() const { return m_accessCount; }
/** "time" of last access where "time" is measured in accesses to the cache owning this entry */
void accessed(unsigned long long cacheTime) const
{
m_lastAccess = cacheTime; ++m_accessCount;
};
int compareRank(const SegCacheEntry & entry) const
{
if (m_accessCount > entry.m_accessCount) return 1;
else if (m_accessCount < entry.m_accessCount) return 1;
else if (m_lastAccess > entry.m_lastAccess) return 1;
else if (m_lastAccess < entry.m_lastAccess) return -1;
return 0;
}
unsigned long long lastAccess() const { return m_lastAccess; };
CLASS_NEW_DELETE;
private:
size_t m_glyphLength;
/** glyph ids resulting from cmap mapping from unicode to glyph before substitution
* the length of this array is determined by the position in the SegCachePrefixEntry */
uint16 * m_unicode;
/** slots after shapping and positioning */
Slot * m_glyph;
int16 * m_attr;
byte * m_justs;
mutable unsigned long long m_accessCount;
mutable unsigned long long m_lastAccess;
};
} // namespace graphite2
#endif

View file

@ -1,127 +0,0 @@
/* GRAPHITE2 LICENSING
Copyright 2010, 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
#ifndef GRAPHITE2_NSEGCACHE
#include "inc/Main.h"
#include "inc/CmapCache.h"
#include "inc/SegCache.h"
namespace graphite2 {
class SegCache;
class Face;
class SilfSegCache
{
SilfSegCache(const SilfSegCache &);
SilfSegCache & operator = (const SilfSegCache &);
public:
SilfSegCache() : m_caches(NULL), m_cacheCount(0) {};
~SilfSegCache()
{
assert(m_caches == NULL);
}
void clear(SegCacheStore * cacheStore)
{
for (size_t i = 0; i < m_cacheCount; i++)
{
m_caches[i]->clear(cacheStore);
delete m_caches[i];
}
free(m_caches);
m_caches = NULL;
m_cacheCount = 0;
}
SegCache * getOrCreate(SegCacheStore * cacheStore, const Features & features)
{
for (size_t i = 0; i < m_cacheCount; i++)
{
if (m_caches[i]->features() == features)
return m_caches[i];
}
SegCache ** newData = gralloc<SegCache*>(m_cacheCount+1);
if (newData)
{
if (m_cacheCount > 0)
{
memcpy(newData, m_caches, sizeof(SegCache*) * m_cacheCount);
free(m_caches);
}
m_caches = newData;
m_caches[m_cacheCount] = new SegCache(cacheStore, features);
m_cacheCount++;
return m_caches[m_cacheCount - 1];
}
return NULL;
}
CLASS_NEW_DELETE
private:
SegCache ** m_caches;
size_t m_cacheCount;
};
class SegCacheStore
{
SegCacheStore(const SegCacheStore &);
SegCacheStore & operator = (const SegCacheStore &);
public:
SegCacheStore(const Face & face, unsigned int numSilf, size_t maxSegments);
~SegCacheStore()
{
for (size_t i = 0; i < m_numSilf; i++)
{
m_caches[i].clear(this);
}
delete [] m_caches;
m_caches = NULL;
}
SegCache * getOrCreate(unsigned int i, const Features & features)
{
return m_caches[i].getOrCreate(this, features);
}
bool isSpaceGlyph(uint16 gid) const { return (gid == m_spaceGid) || (gid == m_zwspGid); }
uint16 maxCmapGid() const { return m_maxCmapGid; }
uint32 maxSegmentCount() const { return m_maxSegments; };
CLASS_NEW_DELETE
private:
SilfSegCache * m_caches;
uint8 m_numSilf;
uint32 m_maxSegments;
uint16 m_maxCmapGid;
uint16 m_spaceGid;
uint16 m_zwspGid;
};
} // namespace graphite2
#endif

View file

@ -49,9 +49,6 @@ typedef Vector<Slot *> SlotRope;
typedef Vector<int16 *> AttributeRope;
typedef Vector<SlotJustify *> JustifyRope;
#ifndef GRAPHITE2_NSEGCACHE
class SegmentScopeState;
#endif
class Font;
class Segment;
class Silf;
@ -91,26 +88,18 @@ public:
SEG_HASCOLLISIONS = 2
};
unsigned int slotCount() const { return m_numGlyphs; } //one slot per glyph
void extendLength(int num) { m_numGlyphs += num; }
size_t slotCount() const { return m_numGlyphs; } //one slot per glyph
void extendLength(ptrdiff_t num) { m_numGlyphs += num; }
Position advance() const { return m_advance; }
bool runGraphite() { if (m_silf) return m_face->runGraphite(this, m_silf); else return true;};
void chooseSilf(uint32 script) { m_silf = m_face->chooseSilf(script); }
const Silf *silf() const { return m_silf; }
unsigned int charInfoCount() const { return m_numCharinfo; }
size_t 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; }
Segment(unsigned int numchars, const Face* face, uint32 script, int dir);
Segment(size_t numchars, const Face* face, uint32 script, int dir);
~Segment();
#ifndef GRAPHITE2_NSEGCACHE
SegmentScopeState setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength);
void removeScope(SegmentScopeState & state);
void append(const Segment &other);
void splice(size_t offset, size_t length, Slot * const startSlot,
Slot * endSlot, const Slot * srcSlot,
const size_t numGlyphs);
#endif
uint8 flags() const { return m_flags; }
void flags(uint8 f) { m_flags = f; }
Slot *first() { return m_first; }
@ -123,11 +112,11 @@ public:
SlotJustify *newJustify();
void freeJustify(SlotJustify *aJustify);
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 associateChars(int offset, size_t num);
void linkClusters(Slot *first, Slot *last);
uint16 getClassGlyph(uint16 cid, uint16 offset) const { return m_silf->getClassGlyph(cid, offset); }
uint16 findClassIndex(uint16 cid, uint16 gid) const { return m_silf->findClassIndex(cid, gid); }
int addFeatures(const Features& feats) { m_feats.push_back(feats); return m_feats.size() - 1; }
int addFeatures(const Features& feats) { m_feats.push_back(feats); return int(m_feats.size()) - 1; }
uint32 getFeature(int index, uint8 findex) const { const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex); if (!pFR) return 0; else return pFR->getFeatureVal(m_feats[index]); }
void setFeature(int index, uint8 findex, uint32 val) {
const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex);
@ -139,8 +128,8 @@ public:
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; }
uint8 passBits() const { return m_passBits; }
void mergePassBits(const uint8 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, bool rtl) const;
float glyphAdvance(uint16 gid) const { return m_face->glyphs().glyph(gid)->theAdvance().x; }
@ -183,13 +172,13 @@ private:
const Silf * m_silf;
Slot * m_first; // first slot in segment
Slot * m_last; // last slot in segment
unsigned int m_bufSize, // how big a buffer to create when need more slots
size_t m_bufSize, // how big a buffer to create when need more slots
m_numGlyphs,
m_numCharinfo, // size of the array and number of input characters
m_passBits; // if bit set then skip pass
m_numCharinfo; // size of the array and number of input characters
int m_defaultOriginal; // number of whitespace chars in the string
int8 m_dir;
uint8 m_flags; // General purpose flags
uint8 m_flags, // General purpose flags
m_passBits; // if bit set then skip pass
};
inline
@ -245,4 +234,3 @@ bool Segment::isWhitespace(const int cid) const
} // namespace graphite2
struct gr_segment : public graphite2::Segment {};

View file

@ -37,7 +37,6 @@ namespace graphite2 {
typedef gr_attrCode attrCode;
class GlyphFace;
class SegCacheEntry;
class Segment;
struct SlotJustify
@ -163,7 +162,6 @@ private:
int16 *m_userAttr; // pointer to user attributes
SlotJustify *m_justs; // pointer to justification parameters
friend class SegCacheEntry;
friend class Segment;
};

View file

@ -138,7 +138,7 @@ sparse::sparse(I attr, const I last)
if (ci != ci_)
{
ci = ci_;
ci->offset = vi - m_array.values;
ci->offset = key_type(vi - m_array.values);
}
ci->mask |= 1UL << (SIZEOF_CHUNK - 1 - (v.first % SIZEOF_CHUNK));

View file

@ -79,9 +79,9 @@ enum
//**********************************************************************************************
namespace Sfnt
{
#pragma pack(1) // We need this or the structure members aren't alligned
#pragma pack(1) // We need this or the structure members aren't aligned
// correctly. Fortunately this form of pragma is supposed
// to be recongnised by VS C++ too (at least according to
// to be recognised by VS C++ too (at least according to
// MSDN).
struct OffsetSubTable

View file

@ -43,6 +43,8 @@ namespace graphite2
namespace TtfUtil
{
#define OVERFLOW_OFFSET_CHECK(p, o) (o + reinterpret_cast<size_t>(p) < reinterpret_cast<size_t>(p))
typedef long fontTableId32;
typedef unsigned short gid16;
@ -51,12 +53,12 @@ typedef unsigned short gid16;
// Enumeration used to specify a table in a TTF file
class Tag
{
unsigned long _v;
unsigned int _v;
public:
Tag(const char n[5]) throw() : _v(TTF_TAG(n[0],n[1],n[2],n[3])) {}
Tag(const unsigned long tag) throw() : _v(tag) {}
Tag(const unsigned int tag) throw() : _v(tag) {}
operator unsigned long () const throw () { return _v; }
operator unsigned int () const throw () { return _v; }
enum
{

View file

@ -40,7 +40,7 @@ struct _utf_codec
static void put(codeunit_t * cp, const uchar_t , int8 & len) throw();
static uchar_t get(const codeunit_t * cp, int8 & len) throw();
static bool validate(const codeunit_t * s, const codeunit_t * e) throw();
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw();
};
@ -66,9 +66,9 @@ public:
}
inline
static bool validate(codeunit_t * s, codeunit_t * e) throw()
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
{
return e > s;
return s <= e;
}
};
@ -101,18 +101,19 @@ public:
l = 1;
if (uh < 0xD800|| uh > 0xDFFF) { return uh; }
if (uh > 0xDBFF) { l = -1; return 0xFFFD; }
const uint32 ul = cp[1];
if (uh > 0xDBFF || ul < 0xDC00 || ul > 0xDFFF) { l = -1; return 0xFFFD; }
if (ul < 0xDC00 || ul > 0xDFFF) { l = -1; return 0xFFFD; }
++l;
return (uh<<10) + ul + surrogate_offset;
}
inline
static bool validate(codeunit_t * s, codeunit_t * e) throw()
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
{
const ptrdiff_t n = e-s;
if (n <= 0) return n == 0;
const uint32 u = *(s+(n-1)); // Get the last codepoint
const uint32 u = *(e-1); // Get the last codepoint
return (u < 0xD800 || u > 0xDBFF);
}
};
@ -166,7 +167,7 @@ public:
}
inline
static bool validate(codeunit_t * s, codeunit_t * e) throw()
static bool validate(const codeunit_t * s, const codeunit_t * const e) throw()
{
const ptrdiff_t n = e-s;
if (n <= 0) return n == 0;
@ -175,7 +176,7 @@ public:
if (*s >= 0xC0) return false;
if (n == 1) return true;
if (*--s < 0x80) return true;
if (*s >= 0xe0) return false;
if (*s >= 0xE0) return false;
if (n == 2 || *s >= 0xC0) return true;
if (*--s < 0x80) return true;
if (*s >= 0xF0) return false;
@ -225,6 +226,7 @@ public:
operator codeunit_type * () const throw() { return cp; }
bool error() const throw() { return sl < 1; }
bool validate(const _utf_iterator & e) { return codec::validate(cp, e.cp); }
};
template <typename C>

View file

@ -73,30 +73,34 @@ inline unsigned int bit_set_count(signed long long v)
{
return __builtin_popcountll(v);
}
#else
template<typename T>
inline unsigned int bit_set_count(T v)
{
v = v - ((v >> 1) & T(~(0UL)/3)); // temp
v = (v & T(~(0UL)/15*3)) + ((v >> 2) & T(~(0UL)/15*3)); // temp
v = (v + (v >> 4)) & T(~(0UL)/255*15); // temp
return (T)(v * T(~(0UL)/255)) >> (sizeof(T)-1)*8; // count
static size_t const ONES = ~0;
v = v - ((v >> 1) & T(ONES/3)); // temp
v = (v & T(ONES/15*3)) + ((v >> 2) & T(ONES/15*3)); // temp
v = (v + (v >> 4)) & T(ONES/255*15); // temp
return (T)(v * T(ONES/255)) >> (sizeof(T)-1)*8; // count
}
#endif
//TODO: Changed these to uintmax_t when we go to C++11
template<int S>
inline unsigned long _mask_over_val(unsigned long v)
inline size_t _mask_over_val(size_t v)
{
v = _mask_over_val<S/2>(v);
v |= v >> S*4;
return v;
}
//TODO: Changed these to uintmax_t when we go to C++11
template<>
inline unsigned long _mask_over_val<1>(unsigned long v)
inline size_t _mask_over_val<1>(size_t v)
{
v |= v >> 1;
v |= v >> 2;
@ -107,7 +111,7 @@ inline unsigned long _mask_over_val<1>(unsigned long v)
template<typename T>
inline T mask_over_val(T v)
{
return _mask_over_val<sizeof(T)>(v);
return T(_mask_over_val<sizeof(T)>(v));
}
template<typename T>

View file

@ -33,6 +33,7 @@ of the License or (at your option) any later version.
#include "inc/Main.h"
#include <cassert>
#include <cstdio>
#include <cstdint>
#include "inc/List.h"
namespace graphite2 {
@ -44,7 +45,6 @@ class json
json & operator = (const json &);
typedef void (*_context_t)(json &);
class _null_t {};
FILE * const _stream;
char _contexts[128], // context stack
@ -61,11 +61,12 @@ class json
public:
class closer;
typedef const char * string;
typedef double number;
typedef long signed int integer;
typedef bool boolean;
static const _null_t null;
using string = const char *;
using number = double;
enum class integer : std::intmax_t {};
enum class integer_u : std::uintmax_t {};
using boolean = bool;
static const std::nullptr_t null;
void setenv(unsigned int index, void *val) { _env.reserve(index + 1); if (index >= _env.size()) _env.insert(_env.end(), _env.size() - index + 1, 0); _env[index] = val; }
void *getenv(unsigned int index) const { return _env[index]; }
@ -85,9 +86,9 @@ public:
json & operator << (string) throw();
json & operator << (number) throw();
json & operator << (integer) throw();
json & operator << (long unsigned int d) throw();
json & operator << (integer_u) throw();
json & operator << (boolean) throw();
json & operator << (_null_t) throw();
json & operator << (std::nullptr_t) throw();
json & operator << (_context_t) throw();
operator bool() const throw();
@ -139,26 +140,31 @@ inline
json & operator << (json & j, signed char d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, short signed int d) throw() { return j << json::integer(d); }
json & operator << (json & j, unsigned char d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, signed int d) throw() { return j << json::integer(d); }
json & operator << (json & j, short int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned char d) throw() { return j << json::integer(d); }
json & operator << (json & j, unsigned short int d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, short unsigned int d) throw() { return j << json::integer(d); }
json & operator << (json & j, int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned int d) throw() { return j << json::integer(d); }
json & operator << (json & j, unsigned int d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, char c) throw ()
{
const char str[2] = {c,0};
return j << str;
}
json & operator << (json & j, long int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned long int d) throw() { return j << json::integer_u(d); }
inline
json & operator << (json & j, long long int d) throw() { return j << json::integer(d); }
inline
json & operator << (json & j, unsigned long long int d) throw() { return j << json::integer_u(d); }
inline
json::operator bool() const throw() { return good(); }

View file

@ -122,4 +122,3 @@ static const opcode_t opcode_table[] =
// private opcodes for internal use only, comes after all other on disk opcodes.
{{do_(temp_copy), NILOP}, 0, "TEMP_COPY"}
};

View file

@ -387,49 +387,49 @@ ENDOP
STARTOP(attr_set)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const int val = int(pop());
const int val = pop();
is->setAttr(&seg, slat, 0, val, smap);
ENDOP
STARTOP(attr_add)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const int val = int(pop());
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
int res = is->getAttr(&seg, slat, 0);
is->setAttr(&seg, slat, 0, val + res, smap);
uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
is->setAttr(&seg, slat, 0, int32_t(val + res), smap);
ENDOP
STARTOP(attr_sub)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const int val = int(pop());
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
int res = is->getAttr(&seg, slat, 0);
is->setAttr(&seg, slat, 0, res - val, smap);
uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
is->setAttr(&seg, slat, 0, int32_t(res - val), smap);
ENDOP
STARTOP(attr_set_slot)
declare_params(1);
const attrCode slat = attrCode(uint8(*param));
const int offset = (map - smap.begin())*int(slat == gr_slatAttTo);
const int val = int(pop()) + offset;
const int offset = int(map - smap.begin())*int(slat == gr_slatAttTo);
const int val = pop() + offset;
is->setAttr(&seg, slat, offset, val, smap);
ENDOP
STARTOP(iattr_set_slot)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const size_t idx = uint8(param[1]);
const int val = int(pop()) + (map - smap.begin())*int(slat == gr_slatAttTo);
const uint8 idx = uint8(param[1]);
const int val = int(pop() + (map - smap.begin())*int(slat == gr_slatAttTo));
is->setAttr(&seg, slat, idx, val, smap);
ENDOP
@ -548,37 +548,37 @@ ENDOP
STARTOP(iattr_set)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const size_t idx = uint8(param[1]);
const int val = int(pop());
const uint8 idx = uint8(param[1]);
const int val = pop();
is->setAttr(&seg, slat, idx, val, smap);
ENDOP
STARTOP(iattr_add)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const size_t idx = uint8(param[1]);
const int val = int(pop());
const uint8 idx = uint8(param[1]);
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
int res = is->getAttr(&seg, slat, idx);
is->setAttr(&seg, slat, idx, val + res, smap);
uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
is->setAttr(&seg, slat, idx, int32_t(val + res), smap);
ENDOP
STARTOP(iattr_sub)
declare_params(2);
const attrCode slat = attrCode(uint8(param[0]));
const size_t idx = uint8(param[1]);
const int val = int(pop());
const uint8 idx = uint8(param[1]);
const uint32_t val = pop();
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
{
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
flags |= POSITIONED;
}
int res = is->getAttr(&seg, slat, idx);
is->setAttr(&seg, slat, idx, res - val, smap);
uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
is->setAttr(&seg, slat, idx, int32_t(res - val), smap);
ENDOP
STARTOP(push_proc_state)
@ -689,4 +689,3 @@ STARTOP(set_feat)
seg.setFeature(fid, feat, pop());
}
ENDOP

View file

@ -33,6 +33,14 @@ of the License or (at your option) any later version.
#include <limits>
#include "inc/json.h"
#if defined(_MSC_VER)
#define FORMAT_INTMAX "%lli"
#define FORMAT_UINTMAX "%llu"
#else
#define FORMAT_INTMAX "%ji"
#define FORMAT_UINTMAX "%ju"
#endif
using namespace graphite2;
namespace
@ -45,7 +53,7 @@ namespace
};
}
const json::_null_t json::null = {};
const std::nullptr_t json::null = nullptr;
inline
void json::context(const char current) throw()
@ -131,10 +139,9 @@ json & json::operator << (json::number f) throw()
fprintf(_stream, "%g", f);
return *this;
}
json & json::operator << (json::integer d) throw() { context(seq); fprintf(_stream, "%ld", d); return *this; }
json & json::operator << (long unsigned d) throw() { context(seq); fprintf(_stream, "%ld", d); return *this; }
json & json::operator << (json::integer d) throw() { context(seq); fprintf(_stream, FORMAT_INTMAX, intmax_t(d)); return *this; }
json & json::operator << (json::integer_u d) throw() { context(seq); fprintf(_stream, FORMAT_UINTMAX, uintmax_t(d)); return *this; }
json & json::operator << (json::boolean b) throw() { context(seq); fputs(b ? "true" : "false", _stream); return *this; }
json & json::operator << (json::_null_t) throw() { context(seq); fputs("null",_stream); return *this; }
json & json::operator << (std::nullptr_t) throw() { context(seq); fputs("null",_stream); return *this; }
#endif

View file

@ -23,7 +23,6 @@ else:
# This should contain all of the _SOURCES from files.mk, except *_machine.cpp
UNIFIED_SOURCES += [
'CachedFace.cpp',
'CmapCache.cpp',
'Code.cpp',
'Collider.cpp',
@ -46,9 +45,6 @@ UNIFIED_SOURCES += [
'Justifier.cpp',
'Pass.cpp',
'Position.cpp',
'SegCache.cpp',
'SegCacheEntry.cpp',
'SegCacheStore.cpp',
'Segment.cpp',
'Silf.cpp',
'Slot.cpp',