Merge inbound to mozilla-central. a=merge

This commit is contained in:
Noemi Erli 2018-08-10 00:31:09 +03:00
commit de9e45a850
337 changed files with 49959 additions and 3971 deletions

View File

@ -544,7 +544,8 @@
oncommand="openPreferences(undefined, {origin: 'menubar'});"/>
#endif
#ifdef MOZ_DEBUG
<menuitem label="&ldbCmd.label;"
<menuitem id="menu_layout_debugger"
label="&ldbCmd.label;"
accesskey="&ldbCmd.accesskey;"
oncommand="toOpenWindowByType('mozapp:layoutdebug',
'chrome://layoutdebug/content/');"/>

View File

@ -0,0 +1,11 @@
{
"manifest_version": 2,
"name": "Firefox Monitor",
"version": "2.0",
"applications": {
"gecko": {
"id": "fxmonitor@mozilla.org",
"strict_min_version": "62.0"
}
}
}

View File

@ -0,0 +1,12 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
with Files("**"):
BUG_COMPONENT = ("Firefox", "Firefox Monitor")
FINAL_TARGET_FILES.features['fxmonitor@mozilla.org'] += [
'manifest.json'
]

View File

@ -7,6 +7,7 @@
DIRS += [
'aushelper',
'formautofill',
'fxmonitor',
'onboarding',
'pdfjs',
'pocket',

View File

@ -514,6 +514,12 @@
; svg
@RESPATH@/res/svg.css
; [Layout Debugger]
#ifdef MOZ_DEBUG
@RESPATH@/chrome/layoutdebug@JAREXT@
@RESPATH@/chrome/layoutdebug.manifest
#endif
; [Personal Security Manager]
;
; NSS libraries are signed in the staging directory,

View File

@ -60,8 +60,13 @@ mozilla.pth:tools
mozilla.pth:testing/web-platform
mozilla.pth:testing/web-platform/tests/tools/third_party/html5lib
mozilla.pth:testing/web-platform/tests/tools/third_party/webencodings
mozilla.pth:testing/web-platform/tests/tools/wptrunner
mozilla.pth:testing/web-platform/tests/tools/third_party/enum
mozilla.pth:testing/web-platform/tests/tools/third_party/h2
mozilla.pth:testing/web-platform/tests/tools/third_party/hpack
mozilla.pth:testing/web-platform/tests/tools/third_party/hyperframe
mozilla.pth:testing/web-platform/tests/tools/third_party/certifi
mozilla.pth:testing/web-platform/tests/tools/wptserve
mozilla.pth:testing/web-platform/tests/tools/wptrunner
mozilla.pth:testing/web-platform/tests/tools/six
mozilla.pth:testing/xpcshell
mozilla.pth:third_party/python/mock-1.0.0

View File

@ -4,6 +4,8 @@
@import "chrome://global/skin/in-content/common.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/App.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/DebugTargetItem.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/DebugTargetList.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/ConnectPage.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/RuntimeInfo.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/Sidebar.css";
@ -24,4 +26,4 @@ ul {
list-style: none;
margin: 0;
padding: 0;
}
}

View File

@ -25,6 +25,8 @@ const { configureStore } = require("./src/create-store");
const App = createFactory(require("./src/components/App"));
const { PAGES } = require("./src/constants");
const AboutDebugging = {
init() {
if (!Services.prefs.getBoolPref("devtools.enabled", true)) {
@ -37,6 +39,8 @@ const AboutDebugging = {
this.actions = bindActionCreators(actions, this.store.dispatch);
render(Provider({ store: this.store }, App()), this.mount);
this.actions.selectPage(PAGES.THIS_FIREFOX);
},
destroy() {

View File

@ -4,6 +4,7 @@
"use strict";
const runtime = require("./runtime");
const ui = require("./ui");
Object.assign(exports, ui);
Object.assign(exports, ui, runtime);

View File

@ -4,5 +4,6 @@
DevToolsModules(
'index.js',
'runtime.js',
'ui.js',
)

View File

@ -0,0 +1,91 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
const { DebuggerServer } = require("devtools/server/main");
const {
CONNECT_RUNTIME_FAILURE,
CONNECT_RUNTIME_START,
CONNECT_RUNTIME_SUCCESS,
DEBUG_TARGETS,
DISCONNECT_RUNTIME_FAILURE,
DISCONNECT_RUNTIME_START,
DISCONNECT_RUNTIME_SUCCESS,
REQUEST_TABS_FAILURE,
REQUEST_TABS_START,
REQUEST_TABS_SUCCESS,
} = require("../constants");
function connectRuntime() {
return async (dispatch, getState) => {
dispatch({ type: CONNECT_RUNTIME_START });
DebuggerServer.init();
DebuggerServer.registerAllActors();
const client = new DebuggerClient(DebuggerServer.connectPipe());
try {
await client.connect();
dispatch({ type: CONNECT_RUNTIME_SUCCESS, client });
dispatch(requestTabs());
} catch (e) {
dispatch({ type: CONNECT_RUNTIME_FAILURE, error: e.message });
}
};
}
function disconnectRuntime() {
return async (dispatch, getState) => {
dispatch({ type: DISCONNECT_RUNTIME_START });
const client = getState().runtime.client;
try {
await client.close();
DebuggerServer.destroy();
dispatch({ type: DISCONNECT_RUNTIME_SUCCESS });
} catch (e) {
dispatch({ type: DISCONNECT_RUNTIME_FAILURE, error: e.message });
}
};
}
function inspectDebugTarget(type, id) {
if (type === DEBUG_TARGETS.TAB) {
window.open(`about:devtools-toolbox?type=tab&id=${ id }`);
} else {
console.error(`Failed to inspect the debug target of type: ${ type } id: ${ id }`);
}
// We cancel the redux flow here since the inspection does not need to update the state.
return () => {};
}
function requestTabs() {
return async (dispatch, getState) => {
dispatch({ type: REQUEST_TABS_START });
const client = getState().runtime.client;
try {
const { tabs } = await client.listTabs({ favicons: true });
dispatch({ type: REQUEST_TABS_SUCCESS, tabs });
} catch (e) {
dispatch({ type: REQUEST_TABS_FAILURE, error: e.message });
}
};
}
module.exports = {
connectRuntime,
disconnectRuntime,
inspectDebugTarget,
requestTabs,
};

View File

@ -6,12 +6,20 @@
const {
PAGE_SELECTED,
PAGES,
} = require("../constants");
const Actions = require("./index");
function selectPage(page) {
return {
type: PAGE_SELECTED,
page,
return async (dispatch, getState) => {
dispatch({ type: PAGE_SELECTED, page });
if (page === PAGES.THIS_FIREFOX) {
dispatch(Actions.connectRuntime());
} else {
dispatch(Actions.disconnectRuntime());
}
};
}

View File

@ -23,4 +23,6 @@
.page {
padding-block-start: 60px;
padding-inline-end: 40px;
overflow-y: auto;
}

View File

@ -27,9 +27,11 @@ class App extends PureComponent {
}
getSelectedPageComponent() {
switch (this.props.selectedPage) {
const { dispatch, selectedPage } = this.props;
switch (selectedPage) {
case PAGES.THIS_FIREFOX:
return RuntimePage();
return RuntimePage({ dispatch });
case PAGES.CONNECT:
return ConnectPage();
default:

View File

@ -0,0 +1,52 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
.ellipsis-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/*
* The current layout of debug target item is
*
* +--------+-----------------------------+----------------+
* | Icon | Information | Inspect button |
* | |+---------------------------+| |
* | || Name || |
* | |+---------------------------+| |
* | || Detail || |
* | |+---------------------------+| |
* +--------+-----------------------------+----------------+
*/
.debug-target-item {
display: grid;
grid-template-columns: 54px auto max-content;
grid-template-rows: auto auto;
grid-row-gap: 20px;
}
.debug-target-item__icon {
height: 36px;
width: 36px;
}
.debug-target-item__info {
/* so as to ellipsis */
min-width: 0;
}
.debug-target-item__info__name {
font-size: 20px;
margin-block-end: 2px;
}
.debug-target-item__inspect-button {
height: 36px;
margin-inline-start: 4px;
margin-inline-end: 4px;
min-width: 100px;
padding-inline-start: 20px;
padding-inline-end: 20px;
}

View File

@ -0,0 +1,83 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const Actions = require("../actions/index");
/**
* This component displays debug target.
*/
class DebugTargetItem extends PureComponent {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
icon: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
};
}
inspect() {
const { dispatch, type, id } = this.props;
dispatch(Actions.inspectDebugTarget(type, id));
}
renderIcon() {
return dom.img({
className: "debug-target-item__icon",
src: this.props.icon,
});
}
renderInfo() {
return dom.div(
{
className: "debug-target-item__info",
},
dom.div(
{
className: "debug-target-item__info__name ellipsis-text",
title: this.props.name,
},
this.props.name
),
dom.div(
{
className: "debug-target-item__info__url ellipsis-text",
},
this.props.url
),
);
}
renderInspectButton() {
return dom.button(
{
onClick: e => this.inspect(),
className: "debug-target-item__inspect-button",
},
"Inspect"
);
}
render() {
return dom.li(
{
className: "debug-target-item",
},
this.renderIcon(),
this.renderInfo(),
this.renderInspectButton(),
);
}
}
module.exports = DebugTargetItem;

View File

@ -2,4 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
pref("toolkit.defaultChromeURI", "chrome://layoutdebug/content/layoutdebug.xul");
.debug-target-list {
margin-inline-start: 60px;
}

View File

@ -0,0 +1,45 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const DebugTargetItem = createFactory(require("./DebugTargetItem"));
/**
* This component displays list of debug target.
*/
class DebugTargetList extends PureComponent {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
targets: PropTypes.arrayOf(PropTypes.Object).isRequired,
};
}
render() {
const { dispatch, targets } = this.props;
return dom.ul(
{
className: "debug-target-list",
},
targets.map(target =>
DebugTargetItem({
dispatch,
icon: target.icon,
id: target.id,
name: target.name,
type: target.type,
url: target.url,
})
),
);
}
}
module.exports = DebugTargetList;

View File

@ -0,0 +1,36 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const DebugTargetList = createFactory(require("./DebugTargetList"));
/**
* This component provides list for debug target and name area.
*/
class DebugTargetPane extends PureComponent {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
targets: PropTypes.arrayOf(PropTypes.Object).isRequired,
};
}
render() {
const { dispatch, name, targets } = this.props;
return dom.section(
{},
dom.h2({}, name),
DebugTargetList({ dispatch, targets }),
);
}
}
module.exports = DebugTargetPane;

View File

@ -5,6 +5,7 @@
.runtime-info {
align-items: center;
display: flex;
margin-block-end: 40px;
white-space: nowrap;
}

View File

@ -4,15 +4,27 @@
"use strict";
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const DebugTargetPane = createFactory(require("./DebugTargetPane"));
const RuntimeInfo = createFactory(require("./RuntimeInfo"));
const Services = require("Services");
class RuntimePage extends PureComponent {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
tabs: PropTypes.arrayOf(PropTypes.object).isRequired,
};
}
render() {
const { dispatch, tabs } = this.props;
return dom.article(
{
className: "page",
@ -22,8 +34,19 @@ class RuntimePage extends PureComponent {
name: Services.appinfo.name,
version: Services.appinfo.version,
}),
DebugTargetPane({
dispatch,
name: "Tabs",
targets: tabs
}),
);
}
}
module.exports = RuntimePage;
const mapStateToProps = state => {
return {
tabs: state.runtime.tabs,
};
};
module.exports = connect(mapStateToProps)(RuntimePage);

View File

@ -7,6 +7,11 @@ DevToolsModules(
'App.js',
'ConnectPage.css',
'ConnectPage.js',
'DebugTargetItem.css',
'DebugTargetItem.js',
'DebugTargetList.css',
'DebugTargetList.js',
'DebugTargetPane.js',
'RuntimeInfo.css',
'RuntimeInfo.js',
'RuntimePage.js',

View File

@ -5,13 +5,26 @@
"use strict";
const actionTypes = {
CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
CONNECT_RUNTIME_SUCCESS: "CONNECT_RUNTIME_SUCCESS",
DISCONNECT_RUNTIME_FAILURE: "DISCONNECT_RUNTIME_FAILURE",
DISCONNECT_RUNTIME_START: "DISCONNECT_RUNTIME_START",
DISCONNECT_RUNTIME_SUCCESS: "DISCONNECT_RUNTIME_SUCCESS",
REQUEST_TABS_FAILURE: "REQUEST_TABS_FAILURE",
REQUEST_TABS_START: "REQUEST_TABS_START",
REQUEST_TABS_SUCCESS: "REQUEST_TABS_SUCCESS",
PAGE_SELECTED: "PAGE_SELECTED",
};
const DEBUG_TARGETS = {
TAB: "TAB",
};
const PAGES = {
THIS_FIREFOX: "this-firefox",
CONNECT: "connect",
};
// flatten constants
module.exports = Object.assign({}, { PAGES }, actionTypes);
module.exports = Object.assign({}, { PAGES }, actionTypes, { DEBUG_TARGETS });

View File

@ -4,15 +4,21 @@
"use strict";
const { createStore } = require("devtools/client/shared/vendor/redux");
const { applyMiddleware, createStore } = require("devtools/client/shared/vendor/redux");
const { thunk } = require("devtools/client/shared/redux/middleware/thunk.js");
const rootReducer = require("./reducers/index");
const { RuntimeState } = require("./reducers/runtime-state");
const { UiState } = require("./reducers/ui-state");
const debugTargetListenerMiddleware = require("./middleware/debug-target-listener");
exports.configureStore = function() {
const initialState = {
runtime: new RuntimeState(),
ui: new UiState()
};
return createStore(rootReducer, initialState);
const middleware = applyMiddleware(thunk, debugTargetListenerMiddleware);
return createStore(rootReducer, initialState, middleware);
};

View File

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
CONNECT_RUNTIME_SUCCESS,
DISCONNECT_RUNTIME_START,
} = require("../constants");
const Actions = require("../actions/index");
function debugTargetListenerMiddleware(state) {
const onTabsUpdated = () => {
state.dispatch(Actions.requestTabs());
};
return next => action => {
switch (action.type) {
case CONNECT_RUNTIME_SUCCESS: {
action.client.addListener("tabListChanged", onTabsUpdated);
break;
}
case DISCONNECT_RUNTIME_START: {
state.getState().runtime.client.removeListener("tabListChanged", onTabsUpdated);
break;
}
}
return next(action);
};
}
module.exports = debugTargetListenerMiddleware;

View File

@ -0,0 +1,7 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'debug-target-listener.js',
)

View File

@ -5,6 +5,7 @@
DIRS += [
'actions',
'components',
'middleware',
'reducers',
]

View File

@ -5,8 +5,10 @@
"use strict";
const { combineReducers } = require("devtools/client/shared/vendor/redux");
const { runtimeReducer } = require("./runtime-state");
const { uiReducer } = require("./ui-state");
module.exports = combineReducers({
runtime: runtimeReducer,
ui: uiReducer
});

View File

@ -4,5 +4,6 @@
DevToolsModules(
'index.js',
'runtime-state.js',
'ui-state.js',
)

View File

@ -0,0 +1,56 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
CONNECT_RUNTIME_SUCCESS,
DEBUG_TARGETS,
DISCONNECT_RUNTIME_SUCCESS,
REQUEST_TABS_SUCCESS,
} = require("../constants");
function RuntimeState() {
return {
client: null,
tabs: [],
};
}
function runtimeReducer(state = RuntimeState(), action) {
switch (action.type) {
case CONNECT_RUNTIME_SUCCESS: {
const { client } = action;
return Object.assign({}, state, { client });
}
case DISCONNECT_RUNTIME_SUCCESS: {
return RuntimeState();
}
case REQUEST_TABS_SUCCESS: {
const { tabs } = action;
return Object.assign({}, state, { tabs: toTabComponentData(tabs) });
}
default:
return state;
}
}
function toTabComponentData(tabs) {
return tabs.map(tab => {
const type = DEBUG_TARGETS.TAB;
const id = tab.outerWindowID;
const icon = tab.favicon
? `data:image/png;base64,${ btoa(String.fromCharCode.apply(String, tab.favicon)) }`
: "chrome://devtools/skin/images/globe.svg";
const name = tab.title || tab.url;
const url = tab.url;
return { type, id, icon, name, url };
});
}
module.exports = {
RuntimeState,
runtimeReducer,
};

View File

@ -82,13 +82,12 @@ IntlUtils::GetDisplayNames(const Sequence<nsString>& aLocales,
return;
}
if (!retVal.isObject()) {
if (!retVal.isObject() || !JS_WrapValue(cx, &retVal)) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
// Return the result as DisplayNameResult.
JSAutoRealmAllowCCW ar(cx, &retVal.toObject());
if (!aResult.Init(cx, retVal)) {
aError.Throw(NS_ERROR_FAILURE);
}
@ -129,13 +128,12 @@ IntlUtils::GetLocaleInfo(const Sequence<nsString>& aLocales,
return;
}
if (!retVal.isObject()) {
if (!retVal.isObject() || !JS_WrapValue(cx, &retVal)) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
// Return the result as LocaleInfo.
JSAutoRealmAllowCCW ar(cx, &retVal.toObject());
if (!aResult.Init(cx, retVal)) {
aError.Throw(NS_ERROR_FAILURE);
}

View File

@ -45,9 +45,12 @@ WriteStructuredCloneImageData(JSContext* aCx, JSStructuredCloneWriter* aWriter,
{
uint32_t width = aImageData->Width();
uint32_t height = aImageData->Height();
JS::Rooted<JSObject*> dataArray(aCx, aImageData->GetDataObject());
JSAutoRealmAllowCCW ar(aCx, dataArray);
JS::Rooted<JSObject*> dataArray(aCx, aImageData->GetDataObject());
if (!JS_WrapObject(aCx, &dataArray)) {
return false;
}
JS::Rooted<JS::Value> arrayValue(aCx, JS::ObjectValue(*dataArray));
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEDATA, 0) &&
JS_WriteUint32Pair(aWriter, width, height) &&

View File

@ -590,7 +590,14 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JSAutoRealmAllowCCW ar(cx, aBuffer.Obj());
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(aBuffer.Obj()));
if (!obj) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
JSAutoRealm ar(cx, obj);
promise = Promise::Create(parentObject, aRv);
if (aRv.Failed()) {
@ -613,7 +620,6 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
// Detach the array buffer
size_t length = aBuffer.Length();
JS::RootedObject obj(cx, aBuffer.Obj());
uint8_t* data = static_cast<uint8_t*>(JS_StealArrayBufferContents(cx, obj));

View File

@ -858,12 +858,10 @@ TCPSocket::Send(JSContext* aCx,
return false;
}
} else {
JS::Rooted<JSObject*> obj(aCx, aData.Obj());
JSAutoRealmAllowCCW ar(aCx, obj);
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*obj));
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*aData.Obj()));
stream = do_CreateInstance("@mozilla.org/io/arraybuffer-input-stream;1");
nsresult rv = stream->SetData(value, aByteOffset, byteLength, aCx);
nsresult rv = stream->SetData(value, aByteOffset, byteLength);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return false;

View File

@ -1,3 +1,39 @@
Overview of changes leading to 1.8.7
Wednesday, August 8, 2018
====================================
- Fix assertion failure with GDEF-blacklisted fonts.
Overview of changes leading to 1.8.6
Tuesday, August 7, 2018
====================================
- Internal code shuffling.
- New API to speed up getting advance widths for implementations
that have heavy overhead in get_h_advance callback:
+hb_font_funcs_set_glyph_h_advances_func
+hb_font_funcs_set_glyph_v_advances_func
+hb_font_get_glyph_advances_for_direction
+hb_font_get_glyph_h_advances
+hb_font_get_glyph_h_advances_func_t
+hb_font_get_glyph_v_advances
+hb_font_get_glyph_v_advances_func_t
Overview of changes leading to 1.8.5
Wednesday, August 1, 2018
====================================
- Major Khmer shaper improvements to better match Microsoft.
- Indic bug fixes.
- Internal improvements to atomic operations.
Overview of changes leading to 1.8.4
Tuesday, July 17, 2018
====================================
- Fix build on non-C++11.
- Use C++-style GCC atomics and C++11 atomics.
Overview of changes leading to 1.8.3
Wednesday, July 11, 2018
====================================

View File

@ -1,7 +1,7 @@
This directory contains the HarfBuzz source from the upstream repo:
https://github.com/harfbuzz/harfbuzz
Current version: 1.8.3 [commit 2b76767bf572364d3d647cdd139f2044a7ad06b2]
Current version: 1.8.7 [commit b6fdcf4f8bd09e065c767939125861c9dc8ff18f]
UPDATING:

View File

@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
[1.8.3],
[1.8.7],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])

View File

@ -14,6 +14,7 @@ check_PROGRAMS =
# Convenience targets:
lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
lib_LTLIBRARIES = libharfbuzz.la
@ -373,15 +374,11 @@ dist_check_SCRIPTS += \
endif
check_PROGRAMS += \
dump-fon \
dump-indic-data \
dump-khmer-data \
dump-myanmar-data \
dump-use-data \
$(NULL)
dump_fon_SOURCES = dump-fon.cc
dump_fon_CPPFLAGS = $(HBCFLAGS)
dump_fon_LDADD = libharfbuzz.la $(HBLIBS)
dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
dump_indic_data_CPPFLAGS = $(HBCFLAGS)
dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)

View File

@ -14,9 +14,12 @@ HB_BASE_sources = \
hb-face.cc \
hb-font-private.hh \
hb-font.cc \
hb-iter-private.hh \
hb-map-private.hh \
hb-map.cc \
hb-machinery-private.hh \
hb-mutex-private.hh \
hb-null.hh \
hb-object-private.hh \
hb-open-file-private.hh \
hb-open-type-private.hh \
@ -50,6 +53,7 @@ HB_BASE_sources = \
hb-string-array.hh \
hb-unicode-private.hh \
hb-unicode.cc \
hb-vector-private.hh \
hb-utf-private.hh \
hb-warning.cc \
$(NULL)
@ -93,8 +97,6 @@ HB_OT_sources = \
hb-aat-layout-morx-table.hh \
hb-aat-layout-trak-table.hh \
hb-aat-layout-private.hh \
hb-aat-fmtx-table.hh \
hb-aat-gcid-table.hh \
hb-aat-ltag-table.hh \
hb-ot-font.cc \
hb-ot-layout.cc \

View File

@ -233,12 +233,10 @@ int main (int argc, char **argv)
svg.dump (svg_callback);
svg.fini ();
OT::Sanitizer<OT::COLR> sanitizerCOLR;
hb_blob_t* colr_blob = sanitizerCOLR.sanitize (face->reference_table (HB_OT_TAG_COLR));
hb_blob_t* colr_blob = hb_sanitize_context_t ().reference_table<OT::COLR> (face);
const OT::COLR *colr = colr_blob->as<OT::COLR> ();
OT::Sanitizer<OT::CPAL> sanitizerCPAL;
hb_blob_t* cpal_blob = sanitizerCPAL.sanitize (face->reference_table (HB_OT_TAG_CPAL));
hb_blob_t* cpal_blob = hb_sanitize_context_t ().reference_table<OT::CPAL> (face);
const OT::CPAL *cpal = cpal_blob->as<OT::CPAL> ();
cairo_font_face_t *cairo_face;

View File

@ -1,555 +0,0 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include "hb-static.cc"
#include <stdio.h>
#include <stdlib.h>
#include "hb-open-type-private.hh"
template <typename Type, int Bytes> struct LEInt;
template <typename Type>
struct LEInt<Type, 1>
{
public:
inline void set (Type V)
{
v = V;
}
inline operator Type (void) const
{
return v;
}
private: uint8_t v;
};
template <typename Type>
struct LEInt<Type, 2>
{
public:
inline void set (Type V)
{
v[1] = (V >> 8) & 0xFF;
v[0] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[1] << 8)
+ (v[0] );
}
private: uint8_t v[2];
};
template <typename Type>
struct LEInt<Type, 3>
{
public:
inline void set (Type V)
{
v[2] = (V >> 16) & 0xFF;
v[1] = (V >> 8) & 0xFF;
v[0] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[2] << 16)
+ (v[1] << 8)
+ (v[0] );
}
private: uint8_t v[3];
};
template <typename Type>
struct LEInt<Type, 4>
{
public:
inline void set (Type V)
{
v[3] = (V >> 24) & 0xFF;
v[2] = (V >> 16) & 0xFF;
v[1] = (V >> 8) & 0xFF;
v[0] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[3] << 24)
+ (v[2] << 16)
+ (v[1] << 8)
+ (v[0] );
}
private: uint8_t v[4];
};
template <typename Type, unsigned int Size>
struct LEIntType
{
inline void set (Type i) { v.set (i); }
inline operator Type(void) const { return v; }
inline bool sanitize (OT::hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this)));
}
protected:
LEInt<Type, Size> v;
public:
DEFINE_SIZE_STATIC (Size);
};
typedef LEIntType<uint8_t, 1> LEUINT8; /* 8-bit unsigned integer. */
typedef LEIntType<int8_t, 1> LEINT8; /* 8-bit signed integer. */
typedef LEIntType<uint16_t, 2> LEUINT16; /* 16-bit unsigned integer. */
typedef LEIntType<int16_t, 2> LEINT16; /* 16-bit signed integer. */
typedef LEIntType<uint32_t, 4> LEUINT32; /* 32-bit unsigned integer. */
typedef LEIntType<int32_t, 4> LEINT32; /* 32-bit signed integer. */
typedef LEIntType<uint32_t, 3> LEUINT24; /* 24-bit unsigned integer. */
struct LE_FONTINFO16
{
inline bool sanitize (OT::hb_sanitize_context_t *c, unsigned int length) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) && c->check_range (this, length)));
}
// https://msdn.microsoft.com/en-us/library/cc194829.aspx
enum charset_t
{
// dfCharSet possible values and the codepage they are indicating to
ANSI = 0x00, // 1252
DEFAULT = 0x01, //
SYMBOL = 0x02, //
SHIFTJIS = 0x80, // 932
HANGUL = 0x81, // 949
GB2312 = 0x86, // 936
CHINESEBIG5 = 0x88, // 950
GREEK = 0xA1, // 1253
TURKISH = 0xA2, // 1254
HEBREW = 0xB1, // 1255
ARABIC = 0xB2, // 1256
BALTIC = 0xBA, // 1257
RUSSIAN = 0xCC, // 1251
THAI = 0xDE, // 874
EE = 0xEE, // 1250
OEM = 0xFF //
};
inline const char* get_charset() const
{
switch (dfCharSet) {
case ANSI: return "ISO8859";
case DEFAULT: return "WinDefault";
case SYMBOL: return "Symbol";
case SHIFTJIS: return "JISX0208.1983";
case HANGUL: return "MSHangul";
case GB2312: return "GB2312.1980";
case CHINESEBIG5: return "Big5";
case GREEK: return "CP1253";
case TURKISH: return "CP1254";
case HEBREW: return "CP1255";
case ARABIC: return "CP1256";
case BALTIC: return "CP1257";
case RUSSIAN: return "CP1251";
case THAI: return "CP874";
case EE: return "CP1250";
case OEM: return "OEM";
default: return "Unknown";
}
}
inline unsigned int get_version () const
{
return dfVersion;
}
inline unsigned int get_weight () const
{
return dfWeight;
}
enum weight_t {
DONTCARE = 0,
THIN = 100,
EXTRALIGHT = 200,
ULTRALIGHT = 200,
LIGHT = 300,
NORMAL = 400,
REGULAR = 400,
MEDIUM = 500,
SEMIBOLD = 600,
DEMIBOLD = 600,
BOLD = 700,
EXTRABOLD = 800,
ULTRABOLD = 800,
HEAVY = 900,
BLACK = 900
};
inline void dump () const
{
// With https://github.com/juanitogan/mkwinfont/blob/master/python/dewinfont.py help
// Should be implemented differently eventually, but for now
unsigned int ctstart;
unsigned int ctsize;
if (dfVersion == 0x200)
{
ctstart = 0x76;
ctsize = 4;
}
else
{
return; // must of ".fon"s are version 2 and even dewinfont V1 implmentation doesn't seem correct
ctstart = 0x94;
ctsize = 6;
}
// unsigned int maxwidth = 0;
for (unsigned int i = dfFirstChar; i < dfLastChar; ++i)
{
unsigned int entry = ctstart + ctsize * (i-dfFirstChar);
unsigned int w = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry);
unsigned int off;
if (ctsize == 4)
off = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry+2);
else
off = (uint32_t) OT::StructAtOffset<LEUINT32> (this, entry+2);
unsigned int widthbytes = (w + 7) / 8;
for (unsigned int j = 0; j < dfPixHeight; ++j)
{
for (unsigned int k = 0; k < widthbytes; ++k)
{
unsigned int bytepos = off + k * dfPixHeight + j;
const uint8_t b = (uint8_t) OT::StructAtOffset<LEINT8> (this, bytepos);
for (unsigned int a = 128; a > 0; a >>= 1)
printf (b & a ? "x" : ".");
}
printf ("\n");
}
printf ("\n\n");
}
}
protected:
LEUINT16 dfVersion;
LEUINT32 dfSize;
LEUINT8 dfCopyright[60];
LEUINT16 dfType;
LEUINT16 dfPoints;
LEUINT16 dfVertRes;
LEUINT16 dfHorizRes;
LEUINT16 dfAscent;
LEUINT16 dfInternalLeading;
LEUINT16 dfExternalLeading;
LEUINT8 dfItalic;
LEUINT8 dfUnderline;
LEUINT8 dfStrikeOut;
LEUINT16 dfWeight; // see weight_t
LEUINT8 dfCharSet; // see charset_t
LEUINT16 dfPixWidth;
LEUINT16 dfPixHeight;
LEUINT8 dfPitchAndFamily;
LEUINT16 dfAvgWidth;
LEUINT16 dfMaxWidth;
LEUINT8 dfFirstChar;
LEUINT8 dfLastChar;
LEUINT8 dfDefaultChar;
LEUINT8 dfBreakChar;
LEUINT16 dfWidthBytes;
LEUINT32 dfDevice;
LEUINT32 dfFace;
LEUINT32 dfBitsPointer;
LEUINT32 dfBitsOffset;
LEUINT8 dfReserved;
// LEUINT32 dfFlags;
// LEUINT16 dfAspace;
// LEUINT16 dfBspace;
// LEUINT16 dfCspace;
// LEUINT32 dfColorPointer;
// LEUINT32 dfReserved1[4];
OT::UnsizedArrayOf<LEUINT8>
dataZ;
public:
DEFINE_SIZE_ARRAY (118, dataZ);
};
struct NE_NAMEINFO
{
friend struct NE_TYPEINFO;
inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
get_font (base, shift).sanitize (c, length << shift)));
}
inline const LE_FONTINFO16& get_font (const void *base, int shift) const
{
return OT::StructAtOffset<LE_FONTINFO16> (base, offset << shift);
}
enum resource_type_flag_t {
NONE = 0x0000,
MOVEABLE = 0x0010,
PURE = 0x0020,
PRELOAD = 0x0040
};
protected:
LEUINT16 offset; // Should be shifted with alignmentShiftCount before use
LEUINT16 length; // Should be shifted with alignmentShiftCount before use
LEUINT16 flags; // resource_type_flag_t
LEUINT16 id;
LEUINT16 handle;
LEUINT16 usage;
public:
DEFINE_SIZE_STATIC (12);
};
struct NE_TYPEINFO
{
inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && resources.sanitize (c, count, base, shift));
}
inline unsigned int get_size (void) const
{ return 8 + count * NE_NAMEINFO::static_size; }
inline const NE_TYPEINFO& next () const
{
const NE_TYPEINFO& next = OT::StructAfter<NE_TYPEINFO> (*this);
if (type_id == 0)
return Null(NE_TYPEINFO);
return next;
}
inline const LE_FONTINFO16& get_font (unsigned int idx, const void *base, int shift) const
{
if (idx < count)
return resources[idx].get_font (base, shift);
return Null(LE_FONTINFO16);
}
inline unsigned int get_count () const
{
return count;
}
inline unsigned int get_type_id () const
{
return type_id;
}
enum type_id_t {
CURSOR = 0x8001,
BITMAP = 0x8002,
ICON = 0x8003,
MENU = 0x8004,
DIALOG = 0x8005,
STRING = 0x8006,
FONT_DIRECTORY = 0x8007,
FONT = 0x8008,
ACCELERATOR_TABLE = 0x8009,
RESOURCE_DATA = 0x800a,
GROUP_CURSOR = 0x800c,
GROUP_ICON = 0x800e,
VERSION = 0x8010
};
protected:
LEUINT16 type_id; // see type_id_t
LEUINT16 count;
LEUINT32 resloader;
OT::UnsizedArrayOf<NE_NAMEINFO>
resources;
public:
DEFINE_SIZE_ARRAY (8, resources);
};
struct NE_RESOURCE_TABLE
{
inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
if (!c->check_struct (this))
return_trace (false);
const NE_TYPEINFO* n = &chain;
while (n != &Null(NE_TYPEINFO) && c->check_struct (n) && n->get_type_id () != 0)
{
if (n->get_type_id () == NE_TYPEINFO::FONT)
return_trace (n->sanitize (c, base, alignmentShiftCount));
n = &n->next();
}
return_trace (false);
}
inline unsigned int get_shift_value () const
{
return alignmentShiftCount;
}
inline const NE_TYPEINFO& get_fonts_entry () const
{
const NE_TYPEINFO* n = &chain;
while (n != &Null(NE_TYPEINFO) && n->get_type_id () != 0)
{
if (n->get_type_id () == NE_TYPEINFO::FONT)
return *n;
n = &n->next();
}
return Null(NE_TYPEINFO);
}
protected:
LEUINT16 alignmentShiftCount;
NE_TYPEINFO chain;
// It is followed by an array of OT::ArrayOf<LEUINT8, LEUINT8> chars;
public:
DEFINE_SIZE_MIN (2);
};
// https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L2467
struct LE_IMAGE_OS2_HEADER
{
inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) && (this+rsrctab).sanitize (c, base)));
}
inline const NE_RESOURCE_TABLE& get_resource_table () const
{
if (magic != 0x454E) // Only NE containers are support for now, NE == 0x454E
return Null(NE_RESOURCE_TABLE);
return this+rsrctab;
}
protected:
LEUINT16 magic; /* 00 NE signature 'NE' */
LEUINT8 ver; /* 02 Linker version number */
LEUINT8 rev; /* 03 Linker revision number */
LEUINT16 enttab; /* 04 Offset to entry table relative to NE */
LEUINT16 cbenttab; /* 06 Length of entry table in bytes */
LEUINT32 crc; /* 08 Checksum */
LEUINT16 flags; /* 0c Flags about segments in this file */
LEUINT16 autodata; /* 0e Automatic data segment number */
LEUINT16 heap; /* 10 Initial size of local heap */
LEUINT16 stack; /* 12 Initial size of stack */
LEUINT32 csip; /* 14 Initial CS:IP */
LEUINT32 sssp; /* 18 Initial SS:SP */
LEUINT16 cseg; /* 1c # of entries in segment table */
LEUINT16 cmod; /* 1e # of entries in module reference tab. */
LEUINT16 cbnrestab; /* 20 Length of nonresident-name table */
LEUINT16 segtab; /* 22 Offset to segment table */
OT::OffsetTo<NE_RESOURCE_TABLE, LEUINT16>
rsrctab; /* 24 Offset to resource table */
LEUINT16 restab; /* 26 Offset to resident-name table */
LEUINT16 modtab; /* 28 Offset to module reference table */
LEUINT16 imptab; /* 2a Offset to imported name table */
LEUINT32 nrestab; /* 2c Offset to nonresident-name table */
LEUINT16 cmovent; /* 30 # of movable entry points */
LEUINT16 align; /* 32 Logical sector alignment shift count */
LEUINT16 cres; /* 34 # of resource segments */
LEUINT8 exetyp; /* 36 Flags indicating target OS */
LEUINT8 flagsothers; /* 37 Additional information flags */
LEUINT16 pretthunks; /* 38 Offset to return thunks */
LEUINT16 psegrefbytes; /* 3a Offset to segment ref. bytes */
LEUINT16 swaparea; /* 3c Reserved by Microsoft */
LEUINT16 expver; /* 3e Expected Windows version number */
public:
DEFINE_SIZE_STATIC (64);
};
struct LE_IMAGE_DOS_HEADER {
inline bool sanitize (OT::hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
get_os2_header ().sanitize (c, this)));
}
inline const LE_IMAGE_OS2_HEADER& get_os2_header () const
{
return this+e_lfanew;
}
protected:
LEUINT16 e_magic; // Magic number
LEUINT16 e_cblp; // Bytes on last page of file
LEUINT16 e_cp; // Pages in file
LEUINT16 e_crlc; // Relocations
LEUINT16 e_cparhdr; // Size of header in paragraphs
LEUINT16 e_minalloc; // Minimum extra paragraphs needed
LEUINT16 e_maxalloc; // Maximum extra paragraphs needed
LEUINT16 e_ss; // Initial (relative) SS value
LEUINT16 e_sp; // Initial SP value
LEUINT16 e_csum; // Checksum
LEUINT16 e_ip; // Initial IP value
LEUINT16 e_cs; // Initial (relative) CS value
LEUINT16 e_lfarlc; // File address of relocation table
LEUINT16 e_ovno; // Overlay number
LEUINT16 e_res_0; // Reserved words
LEUINT16 e_res_1; // Reserved words
LEUINT16 e_res_2; // Reserved words
LEUINT16 e_res_3; // Reserved words
LEUINT16 e_oemid; // OEM identifier (for e_oeminfo)
LEUINT16 e_oeminfo; // OEM information; e_oemid specific
LEUINT16 e_res2_0; // Reserved words
LEUINT16 e_res2_1; // Reserved words
LEUINT16 e_res2_2; // Reserved words
LEUINT16 e_res2_3; // Reserved words
LEUINT16 e_res2_4; // Reserved words
LEUINT16 e_res2_5; // Reserved words
LEUINT16 e_res2_6; // Reserved words
LEUINT16 e_res2_7; // Reserved words
LEUINT16 e_res2_8; // Reserved words
LEUINT16 e_res2_9; // Reserved words
OT::OffsetTo<LE_IMAGE_OS2_HEADER, LEUINT32>
e_lfanew; // File address of new exe header
public:
DEFINE_SIZE_STATIC (64);
};
int main (int argc, char** argv) {
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
OT::Sanitizer<LE_IMAGE_DOS_HEADER> sanitizer;
hb_blob_t *font_blob = sanitizer.sanitize (blob);
const LE_IMAGE_DOS_HEADER* dos_header = font_blob->as<LE_IMAGE_DOS_HEADER> ();
const NE_RESOURCE_TABLE &rtable = dos_header->get_os2_header ().get_resource_table ();
int shift = rtable.get_shift_value ();
const NE_TYPEINFO& entry = rtable.get_fonts_entry ();
for (unsigned int i = 0; i < entry.get_count (); ++i)
{
const LE_FONTINFO16& font = entry.get_font (i, dos_header, shift);
printf ("version: %x, weight: %d, charset: %s\n", font.get_version (),
font.get_weight (), font.get_charset ());
// font.dump ();
}
return 0;
}

View File

@ -328,6 +328,9 @@ def map_to_use(data):
# TODO: https://github.com/harfbuzz/harfbuzz/pull/626
if U == 0xA8B4: UISC = Consonant_Medial
# TODO: https://github.com/harfbuzz/harfbuzz/issues/1105
if U == 0x11134: UISC = Gemination_Mark
values = [k for k,v in items if v(U,UISC,UGC)]
assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
USE = values[0]
@ -356,6 +359,13 @@ def map_to_use(data):
# https://github.com/roozbehp/unicode-data/issues/8
if U == 0x0A51: UIPC = Bottom
# TODO: https://github.com/harfbuzz/harfbuzz/pull/982
if UBlock == 'Chakma' and is_VOWEL (U, UISC, UGC):
if UIPC == Top:
UIPC = Bottom
elif UIPC == Bottom:
UIPC = Top
assert (UIPC in [Not_Applicable, Visual_Order_Left] or
USE in use_positions), "%s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC)

View File

@ -1,67 +0,0 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#ifndef HB_AAT_FMTX_TABLE_HH
#define HB_AAT_FMTX_TABLE_HH
#include "hb-aat-layout-common-private.hh"
/*
* fmtx -- Font Metrics
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fmtx.html
*/
#define HB_AAT_TAG_fmtx HB_TAG('f','m','t','x')
namespace AAT {
struct fmtx
{
static const hb_tag_t tableTag = HB_AAT_TAG_fmtx;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this)));
}
FixedVersion<>version; /* Version (set to 0x00020000). */
HBUINT32 glyphIndex; /* The glyph whose points represent the metrics. */
HBUINT8 horizontalBefore; /* Point number for the horizontal ascent. */
HBUINT8 horizontalAfter; /* Point number for the horizontal descent. */
HBUINT8 horizontalCaretHead; /* Point number for the horizontal caret head. */
HBUINT8 horizontalCaretBase; /* Point number for the horizontal caret base. */
HBUINT8 verticalBefore; /* Point number for the vertical ascent. */
HBUINT8 verticalAfter; /* Point number for the vertical descent. */
HBUINT8 verticalCaretHead; /* Point number for the vertical caret head. */
HBUINT8 verticalCaretBase; /* Point number for the vertical caret base. */
public:
DEFINE_SIZE_STATIC (16);
};
} /* namespace AAT */
#endif /* HB_AAT_FMTX_TABLE_HH */

View File

@ -1,73 +0,0 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#ifndef HB_AAT_GCID_TABLE_HH
#define HB_AAT_GCID_TABLE_HH
#include "hb-aat-layout-common-private.hh"
/*
* gcid -- Glyphs CIDs
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gcid.html
*/
#define HB_AAT_TAG_gcid HB_TAG('g','c','i','d')
namespace AAT {
struct gcid
{
static const hb_tag_t tableTag = HB_AAT_TAG_gcid;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) && CIDs.sanitize (c)));
}
protected:
HBUINT16 version; /* Version number (set to 0) */
HBUINT16 format; /* Data format (set to 0) */
HBUINT32 size; /* Size of the table, including header */
HBUINT16 registry; /* The registry ID */
HBUINT8 registryName[64];
/* The registry name in ASCII */
HBUINT16 order; /* The order ID */
HBUINT8 orderName[64]; /* The order name in ASCII */
HBUINT16 supplementVersion;
/* The supplement version */
ArrayOf<HBUINT16>
CIDs; /* The CIDs for the glyphs in the font,
* starting with glyph 0. If a glyph does not correspond
* to a CID in the identified collection, 0xFFFF is used.
* This should not exceed the number of glyphs in the font. */
public:
DEFINE_SIZE_ARRAY (144, CIDs);
};
} /* namespace AAT */
#endif /* HB_AAT_GCID_TABLE_HH */

View File

@ -161,7 +161,7 @@ struct LookupFormat0
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (arrayZ.sanitize (c, c->num_glyphs));
return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
}
protected:
@ -625,7 +625,7 @@ struct hb_aat_apply_context_t :
sanitizer (), lookup_index (0), debug_depth (0)
{
sanitizer.init (table);
sanitizer.num_glyphs = face->get_num_glyphs ();
sanitizer.set_num_glyphs (face->get_num_glyphs ());
sanitizer.start_processing ();
}

View File

@ -36,48 +36,12 @@
#include "hb-aat-layout-kerx-table.hh"
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-trak-table.hh"
#include "hb-aat-fmtx-table.hh" // Just so we compile it; unused otherwise.
#include "hb-aat-gcid-table.hh" // Just so we compile it; unused otherwise.
#include "hb-aat-ltag-table.hh" // Just so we compile it; unused otherwise.
/*
* morx/kerx/trak
* morx/kerx/trak/ankr
*/
#if 0
static inline const AAT::ankr&
_get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
{
if (blob)
*blob = hb_blob_get_empty ();
return Null(AAT::ankr);
}
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
const AAT::ankr& ankr = *(layout->ankr.get ());
if (blob)
*blob = layout->ankr.blob;
return ankr;
}
static inline const AAT::kerx&
_get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
{
if (blob)
*blob = hb_blob_get_empty ();
return Null(AAT::kerx);
}
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
/* XXX this doesn't call set_num_glyphs on sanitizer. */
const AAT::kerx& kerx = *(layout->kerx.get ());
if (blob)
*blob = layout->kerx.blob;
return kerx;
}
static inline const AAT::morx&
_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
{
@ -88,36 +52,16 @@ _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
return Null(AAT::morx);
}
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
/* XXX this doesn't call set_num_glyphs on sanitizer. */
const AAT::morx& morx = *(layout->morx.get ());
const AAT::morx& morx = *(layout->table.morx.get ());
if (blob)
*blob = layout->morx.blob;
*blob = layout->table.morx.get_blob ();
return morx;
}
static inline const AAT::trak&
_get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
{
if (blob)
*blob = hb_blob_get_empty ();
return Null(AAT::trak);
}
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
const AAT::trak& trak = *(layout->trak.get ());
if (blob)
*blob = layout->trak.blob;
return trak;
}
#endif
// static inline void
// _hb_aat_layout_create (hb_face_t *face)
// {
// OT::Sanitizer<AAT::morx> sanitizer;
// sanitizer.set_num_glyphs (face->get_num_glyphs ());
// hb_blob_t *morx_blob = sanitizer.sanitize (face->reference_table (HB_AAT_TAG_morx));
// hb_blob_t *morx_blob = hb_sanitize_context_t ().reference_table<AAT::morx> (face);
// morx_blob->as<AAT::morx> ();
// if (0)
@ -129,13 +73,11 @@ _get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
void
hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
{
#if 0
hb_blob_t *blob;
const AAT::morx& morx = _get_morx (font->face, &blob);
AAT::hb_aat_apply_context_t c (font, buffer, blob);
morx.apply (&c);
#endif
}
void

View File

@ -46,35 +46,74 @@
/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
#elif !defined(HB_NO_MT) && defined(__ATOMIC_CONSUME)
/* C++11-style GCC primitives. */
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) __atomic_fetch_add ((AI), (V), __ATOMIC_ACQ_REL)
#define hb_atomic_int_impl_set_relaxed(AI, V) __atomic_store_n ((AI), (V), __ATOMIC_RELAXED)
#define hb_atomic_int_impl_get_relaxed(AI) __atomic_load_n ((AI), __ATOMIC_RELAXED)
#define hb_atomic_ptr_impl_get(P) __atomic_load_n ((P), __ATOMIC_CONSUME)
static inline bool
_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
{
const void *O = O_; // Need lvalue
return __atomic_compare_exchange_n ((void **) P, (void **) &O, (void *) N, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
}
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
/* C++11 atomics. */
#include <atomic>
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_relaxed))
#define hb_atomic_ptr_impl_get(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_consume))
static inline bool
_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
{
const void *O = O_; // Need lvalue
return reinterpret_cast<std::atomic<const void*> *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed);
}
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
#include <windows.h>
/* MinGW has a convoluted history of supporting MemoryBarrier
* properly. As such, define a function to wrap the whole
* thing. */
static inline void _HBMemoryBarrier (void) {
static inline void _hb_memory_barrier (void)
{
#if !defined(MemoryBarrier)
/* MinGW has a convoluted history of supporting MemoryBarrier. */
long dummy = 0;
InterlockedExchange (&dummy, 1);
#else
MemoryBarrier ();
#endif
}
#define _hb_memory_barrier() _hb_memory_barrier ()
typedef LONG hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((AI), (V))
#define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V))
#define _hb_memory_barrier() __sync_synchronize ()
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
@ -83,11 +122,30 @@ typedef int hb_atomic_int_impl_t;
#include <atomic.h>
#include <mbarrier.h>
typedef unsigned int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
#define _hb_memory_r_barrier() __machine_r_barrier ()
#define _hb_memory_w_barrier() __machine_w_barrier ()
#define _hb_memory_barrier() __machine_rw_barrier ()
#define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
typedef unsigned int hb_atomic_int_impl_t;
static inline int _hb_fetch_and_add (hb_atomic_int_impl_t *AI, int V)
{
_hb_memory_w_barrier ();
int result = atomic_add_int_nv (AI, V);
_hb_memory_r_barrier ();
return result;
}
static inline bool _hb_compare_and_swap_ptr (const void **P, const void *O, const void *N)
{
_hb_memory_w_barrier ();
int result = atomic_cas_ptr ((void **) P, (void *) O, (void *) N) == (void *) O;
_hb_memory_r_barrier ();
return result;
}
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && defined(__APPLE__)
@ -99,11 +157,11 @@ typedef unsigned int hb_atomic_int_impl_t;
#include <Availability.h>
#endif
#define _hb_memory_barrier() OSMemoryBarrier ()
typedef int32_t hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V))
#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P))
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
#else
@ -119,63 +177,88 @@ typedef int32_t hb_atomic_int_impl_t;
#include <builtins.h>
static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
__lwsync();
int result = __fetch_and_add(AI, V);
__isync();
return result;
}
static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
__sync();
int result = __compare_and_swaplp (P, &O, N);
__sync();
return result;
}
#define _hb_memory_barrier() __lwsync ()
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V))
#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
static inline int _hb_fetch_and_add (hb_atomic_int_impl_t *AI, int V)
{
_hb_memory_barrier ();
int result = __fetch_and_add (AI, V);
_hb_memory_barrier ();
return result;
}
static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
{
_hb_memory_barrier ();
bool result = __compare_and_swaplp (P, &O, N);
_hb_memory_barrier ();
return result;
}
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
static_assert ((sizeof (long) == sizeof (void *)), "");
#elif !defined(HB_NO_MT)
#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
typedef volatile int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
#define _hb_memory_barrier()
typedef volatile int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
#else /* HB_NO_MT */
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
#define _hb_memory_barrier()
#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
#endif
#ifndef _hb_memory_r_barrier
#define _hb_memory_r_barrier() _hb_memory_barrier ()
#endif
#ifndef _hb_memory_w_barrier
#define _hb_memory_w_barrier() _hb_memory_barrier ()
#endif
#ifndef HB_ATOMIC_INT_INIT
#define HB_ATOMIC_INT_INIT(V) {V}
#endif
#ifndef hb_atomic_int_impl_set_relaxed
#define hb_atomic_int_impl_set_relaxed(AI, V) (*(AI) = (V))
#endif
#ifndef hb_atomic_int_impl_get_relaxed
#define hb_atomic_int_impl_get_relaxed(AI) (*(AI))
#endif
#ifndef hb_atomic_ptr_impl_get
inline void *hb_atomic_ptr_impl_get (void **P) { void *v = *P; _hb_memory_r_barrier (); return v; }
#endif
struct hb_atomic_int_t
{
hb_atomic_int_impl_t v;
mutable hb_atomic_int_impl_t v;
inline void set_unsafe (int v_) { v = v_; }
inline int get_unsafe (void) const { return v; }
inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), 1); }
inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
inline void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
inline int get_relaxed (void) const { return hb_atomic_int_impl_get_relaxed (&v); }
inline int inc (void) { return hb_atomic_int_impl_add (&v, 1); }
inline int dec (void) { return hb_atomic_int_impl_add (&v, -1); }
};
#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get((void **) P)
#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))

View File

@ -57,11 +57,6 @@ struct hb_blob_t
HB_INTERNAL bool try_make_writable_inplace (void);
HB_INTERNAL bool try_make_writable_inplace_unix (void);
inline void lock (void)
{
hb_blob_make_immutable (this);
}
template <typename Type>
inline const Type* as (void) const
{
@ -81,6 +76,7 @@ struct hb_blob_t
void *user_data;
hb_destroy_func_t destroy;
};
DECLARE_NULL_INSTANCE (hb_blob_t);
#endif /* HB_BLOB_PRIVATE_HH */

View File

@ -45,6 +45,20 @@
#include <stdlib.h>
DEFINE_NULL_INSTANCE (hb_blob_t) =
{
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
nullptr, /* data */
0, /* length */
HB_MEMORY_MODE_READONLY, /* mode */
nullptr, /* user_data */
nullptr /* destroy */
};
/**
* hb_blob_create: (skip)
* @data: Pointer to blob data.
@ -182,20 +196,7 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob)
hb_blob_t *
hb_blob_get_empty (void)
{
static const hb_blob_t _hb_blob_nil = {
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
nullptr, /* data */
0, /* length */
HB_MEMORY_MODE_READONLY, /* mode */
nullptr, /* user_data */
nullptr /* destroy */
};
return const_cast<hb_blob_t *> (&_hb_blob_nil);
return const_cast<hb_blob_t *> (&Null(hb_blob_t));
}
/**

View File

@ -83,7 +83,8 @@ HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
* hb_buffer_t
*/
struct hb_buffer_t {
struct hb_buffer_t
{
hb_object_header_t header;
ASSERT_POD ();
@ -352,6 +353,7 @@ struct hb_buffer_t {
info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
}
};
DECLARE_NULL_INSTANCE (hb_buffer_t);
/* Loop over clusters. Duplicated in foreach_syllable(). */

View File

@ -701,6 +701,28 @@ hb_buffer_t::guess_segment_properties (void)
/* Public API */
DEFINE_NULL_INSTANCE (hb_buffer_t) =
{
HB_OBJECT_HEADER_STATIC,
const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
HB_BUFFER_FLAG_DEFAULT,
HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
HB_BUFFER_MAX_LEN_DEFAULT,
HB_BUFFER_MAX_OPS_DEFAULT,
HB_BUFFER_CONTENT_TYPE_INVALID,
HB_SEGMENT_PROPERTIES_DEFAULT,
false, /* successful */
true, /* have_output */
true /* have_positions */
/* Zero is good enough for everything else. */
};
/**
* hb_buffer_create: (Xconstructor)
*
@ -743,27 +765,7 @@ hb_buffer_create (void)
hb_buffer_t *
hb_buffer_get_empty (void)
{
static const hb_buffer_t _hb_buffer_nil = {
HB_OBJECT_HEADER_STATIC,
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
HB_BUFFER_FLAG_DEFAULT,
HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
HB_BUFFER_MAX_LEN_DEFAULT,
HB_BUFFER_MAX_OPS_DEFAULT,
HB_BUFFER_CONTENT_TYPE_INVALID,
HB_SEGMENT_PROPERTIES_DEFAULT,
false, /* successful */
true, /* have_output */
true /* have_positions */
/* Zero is good enough for everything else. */
};
return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
}
/**

View File

@ -37,7 +37,7 @@
/* hb_options_t */
hb_options_union_t _hb_options;
hb_atomic_int_t _hb_options;
void
_hb_options_init (void)
@ -50,7 +50,7 @@ _hb_options_init (void)
u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
/* This is idempotent and threadsafe. */
_hb_options = u;
_hb_options.set_relaxed (u.i);
}
@ -1069,3 +1069,12 @@ hb_variation_to_string (hb_variation_t *variation,
memcpy (buf, s, len);
buf[len] = '\0';
}
/* If there is no visibility control, then hb-static.cc will NOT
* define anything. Instead, we get it to define one set in here
* only, so only libharfbuzz.so defines them, not other libs. */
#ifdef HB_NO_VISIBILITY
#undef HB_NO_VISIBILITY
#include "hb-static.cc"
#define HB_NO_VISIBILITY 1
#endif

View File

@ -269,7 +269,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
return ct_font;
}
hb_coretext_shaper_face_data_t *
hb_coretext_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
CGFontRef cg_font = create_cg_font (face);
@ -280,11 +280,11 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face)
return nullptr;
}
return (hb_coretext_shaper_face_data_t *) cg_font;
return (hb_coretext_face_data_t *) cg_font;
}
void
_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
_hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
{
CFRelease ((CGFontRef) data);
}
@ -306,7 +306,7 @@ hb_coretext_face_get_cg_font (hb_face_t *face)
}
hb_coretext_shaper_font_data_t *
hb_coretext_font_data_t *
_hb_coretext_shaper_font_data_create (hb_font_t *font)
{
hb_face_t *face = font->face;
@ -321,11 +321,11 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
return nullptr;
}
return (hb_coretext_shaper_font_data_t *) ct_font;
return (hb_coretext_font_data_t *) ct_font;
}
void
_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
_hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
{
CFRelease ((CTFontRef) data);
}
@ -348,7 +348,7 @@ hb_coretext_font_create (CTFontRef ct_font)
hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
/* Let there be dragons here... */
HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
HB_SHAPER_DATA_GET (font) = (hb_coretext_font_data_t *) CFRetain (ct_font);
return font;
}
@ -366,20 +366,20 @@ hb_coretext_font_get_ct_font (hb_font_t *font)
* shaper shape_plan data
*/
struct hb_coretext_shaper_shape_plan_data_t {};
struct hb_coretext_shape_plan_data_t {};
hb_coretext_shaper_shape_plan_data_t *
hb_coretext_shape_plan_data_t *
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_coretext_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shape_plan_data_t *data HB_UNUSED)
{
}
@ -1329,9 +1329,9 @@ HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
* shaper face data
*/
struct hb_coretext_aat_shaper_face_data_t {};
struct hb_coretext_aat_face_data_t {};
hb_coretext_aat_shaper_face_data_t *
hb_coretext_aat_face_data_t *
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
{
static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
@ -1342,7 +1342,7 @@ _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
if (hb_blob_get_length (blob))
{
hb_blob_destroy (blob);
return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
hb_blob_destroy (blob);
}
@ -1351,7 +1351,7 @@ _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
}
void
_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
{
}
@ -1360,16 +1360,16 @@ _hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *d
* shaper font data
*/
struct hb_coretext_aat_shaper_font_data_t {};
struct hb_coretext_aat_font_data_t {};
hb_coretext_aat_shaper_font_data_t *
hb_coretext_aat_font_data_t *
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
{
return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
void
_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
{
}
@ -1378,20 +1378,20 @@ _hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *d
* shaper shape_plan data
*/
struct hb_coretext_aat_shaper_shape_plan_data_t {};
struct hb_coretext_aat_shape_plan_data_t {};
hb_coretext_aat_shaper_shape_plan_data_t *
hb_coretext_aat_shape_plan_data_t *
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_coretext_aat_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shape_plan_data_t *data HB_UNUSED)
{
}

View File

@ -28,6 +28,7 @@
#define HB_DEBUG_HH
#include "hb-private.hh"
#include "hb-atomic-private.hh"
#include "hb-dsalgs.hh"
@ -35,6 +36,47 @@
#define HB_DEBUG 0
#endif
/*
* Global runtime options.
*/
struct hb_options_t
{
unsigned int unused : 1; /* In-case sign bit is here. */
unsigned int initialized : 1;
unsigned int uniscribe_bug_compatible : 1;
};
union hb_options_union_t {
int i;
hb_options_t opts;
};
static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
HB_INTERNAL void
_hb_options_init (void);
extern HB_INTERNAL hb_atomic_int_t _hb_options;
static inline hb_options_t
hb_options (void)
{
/* Make a local copy, so we can access bitfield threadsafely. */
hb_options_union_t u;
u.i = _hb_options.get_relaxed ();
if (unlikely (!u.i))
_hb_options_init ();
return u.opts;
}
/*
* Debug output (needs enabling at compile time.)
*/
static inline bool
_hb_debug (unsigned int level,
unsigned int max_level)

View File

@ -133,7 +133,7 @@ public:
* shaper face data
*/
struct hb_directwrite_shaper_face_data_t
struct hb_directwrite_face_data_t
{
IDWriteFactory *dwriteFactory;
IDWriteFontFile *fontFile;
@ -143,10 +143,10 @@ struct hb_directwrite_shaper_face_data_t
hb_blob_t *faceBlob;
};
hb_directwrite_shaper_face_data_t *
hb_directwrite_face_data_t *
_hb_directwrite_shaper_face_data_create (hb_face_t *face)
{
hb_directwrite_shaper_face_data_t *data = new hb_directwrite_shaper_face_data_t;
hb_directwrite_face_data_t *data = new hb_directwrite_face_data_t;
if (unlikely (!data))
return nullptr;
@ -206,7 +206,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
}
void
_hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *data)
_hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
{
if (data->fontFace)
data->fontFace->Release ();
@ -233,16 +233,16 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *dat
* shaper font data
*/
struct hb_directwrite_shaper_font_data_t
struct hb_directwrite_font_data_t
{
};
hb_directwrite_shaper_font_data_t *
hb_directwrite_font_data_t *
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
{
if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return nullptr;
hb_directwrite_shaper_font_data_t *data = new hb_directwrite_shaper_font_data_t;
hb_directwrite_font_data_t *data = new hb_directwrite_font_data_t;
if (unlikely (!data))
return nullptr;
@ -250,7 +250,7 @@ _hb_directwrite_shaper_font_data_create (hb_font_t *font)
}
void
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data)
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
{
delete data;
}
@ -260,20 +260,20 @@ _hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *dat
* shaper shape_plan data
*/
struct hb_directwrite_shaper_shape_plan_data_t {};
struct hb_directwrite_shape_plan_data_t {};
hb_directwrite_shaper_shape_plan_data_t *
hb_directwrite_shape_plan_data_t *
_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_directwrite_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shape_plan_data_t *data HB_UNUSED)
{
}
@ -555,8 +555,8 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
float lineWidth)
{
hb_face_t *face = font->face;
hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
hb_directwrite_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_directwrite_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
IDWriteFontFace *fontFace = face_data->fontFace;

View File

@ -232,6 +232,18 @@ hb_ctz (T v)
* Tiny stuff.
*/
/* ASCII tag/character handling */
static inline bool ISALPHA (unsigned char c)
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
static inline bool ISALNUM (unsigned char c)
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
static inline bool ISSPACE (unsigned char c)
{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
static inline unsigned char TOUPPER (unsigned char c)
{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
static inline unsigned char TOLOWER (unsigned char c)
{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
#undef MIN
template <typename Type>
static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
@ -262,6 +274,37 @@ hb_ceil_to_4 (unsigned int v)
return ((v - 1) | 3) + 1;
}
template <typename T> class hb_assert_unsigned_t;
template <> class hb_assert_unsigned_t<unsigned char> {};
template <> class hb_assert_unsigned_t<unsigned short> {};
template <> class hb_assert_unsigned_t<unsigned int> {};
template <> class hb_assert_unsigned_t<unsigned long> {};
template <typename T> static inline bool
hb_in_range (T u, T lo, T hi)
{
/* The sizeof() is here to force template instantiation.
* I'm sure there are better ways to do this but can't think of
* one right now. Declaring a variable won't work as HB_UNUSED
* is unusable on some platforms and unused types are less likely
* to generate a warning than unused variables. */
static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
/* The casts below are important as if T is smaller than int,
* the subtract results will become a signed int! */
return (T)(u - lo) <= (T)(hi - lo);
}
template <typename T> static inline bool
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
{
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
}
template <typename T> static inline bool
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
{
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
}
/*
* Sort and search.
@ -445,305 +488,6 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
}
#define HB_VECTOR_INIT {0, 0, false, nullptr}
template <typename Type, unsigned int StaticSize=8>
struct hb_vector_t
{
unsigned int len;
unsigned int allocated;
bool successful;
Type *arrayZ;
Type static_array[StaticSize];
void init (void)
{
len = 0;
allocated = ARRAY_LENGTH (static_array);
successful = true;
arrayZ = static_array;
}
inline Type& operator [] (unsigned int i)
{
if (unlikely (i >= len))
return Crap (Type);
return arrayZ[i];
}
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= len))
return Null(Type);
return arrayZ[i];
}
inline Type *push (void)
{
if (unlikely (!resize (len + 1)))
return &Crap(Type);
return &arrayZ[len - 1];
}
inline Type *push (const Type& v)
{
Type *p = push ();
*p = v;
return p;
}
/* Allocate for size but don't adjust len. */
inline bool alloc (unsigned int size)
{
if (unlikely (!successful))
return false;
if (likely (size <= allocated))
return true;
/* Reallocate */
unsigned int new_allocated = allocated;
while (size >= new_allocated)
new_allocated += (new_allocated >> 1) + 8;
Type *new_array = nullptr;
if (arrayZ == static_array)
{
new_array = (Type *) calloc (new_allocated, sizeof (Type));
if (new_array)
memcpy (new_array, arrayZ, len * sizeof (Type));
}
else
{
bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
if (likely (!overflows))
new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
}
if (unlikely (!new_array))
{
successful = false;
return false;
}
arrayZ = new_array;
allocated = new_allocated;
return true;
}
inline bool resize (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (!alloc (size))
return false;
if (size > len)
memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
len = size;
return true;
}
inline void pop (void)
{
if (!len) return;
len--;
}
inline void remove (unsigned int i)
{
if (unlikely (i >= len))
return;
memmove (static_cast<void *> (&arrayZ[i]),
static_cast<void *> (&arrayZ[i + 1]),
(len - i - 1) * sizeof (Type));
len--;
}
inline void shrink (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (size < len)
len = size;
}
template <typename T>
inline Type *find (T v) {
for (unsigned int i = 0; i < len; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
template <typename T>
inline const Type *find (T v) const {
for (unsigned int i = 0; i < len; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
inline void qsort (int (*cmp)(const void*, const void*))
{
::qsort (arrayZ, len, sizeof (Type), cmp);
}
inline void qsort (void)
{
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
}
inline void qsort (unsigned int start, unsigned int end)
{
::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
}
template <typename T>
inline Type *lsearch (const T &x)
{
for (unsigned int i = 0; i < len; i++)
if (0 == this->arrayZ[i].cmp (&x))
return &arrayZ[i];
return nullptr;
}
template <typename T>
inline Type *bsearch (const T &x)
{
unsigned int i;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline const Type *bsearch (const T &x) const
{
unsigned int i;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline bool bfind (const T &x, unsigned int *i) const
{
int min = 0, max = (int) this->len - 1;
while (min <= max)
{
int mid = (min + max) / 2;
int c = this->arrayZ[mid].cmp (&x);
if (c < 0)
max = mid - 1;
else if (c > 0)
min = mid + 1;
else
{
*i = mid;
return true;
}
}
if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
max++;
*i = max;
return false;
}
inline void fini (void)
{
if (arrayZ != static_array)
free (arrayZ);
arrayZ = nullptr;
allocated = len = 0;
}
};
#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
template <typename item_t, typename lock_t>
struct hb_lockable_set_t
{
hb_vector_t <item_t, 1> items;
inline void init (void) { items.init (); }
template <typename T>
inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
{
l.lock ();
item_t *item = items.find (v);
if (item) {
if (replace) {
item_t old = *item;
*item = v;
l.unlock ();
old.fini ();
}
else {
item = nullptr;
l.unlock ();
}
} else {
item = items.push (v);
l.unlock ();
}
return item;
}
template <typename T>
inline void remove (T v, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (item) {
item_t old = *item;
*item = items[items.len - 1];
items.pop ();
l.unlock ();
old.fini ();
} else {
l.unlock ();
}
}
template <typename T>
inline bool find (T v, item_t *i, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (item)
*i = *item;
l.unlock ();
return !!item;
}
template <typename T>
inline item_t *find_or_insert (T v, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (!item) {
item = items.push (v);
}
l.unlock ();
return item;
}
inline void fini (lock_t &l)
{
if (!items.len) {
/* No need for locking. */
items.fini ();
return;
}
l.lock ();
while (items.len) {
item_t old = items[items.len - 1];
items.pop ();
l.unlock ();
old.fini ();
l.lock ();
}
items.fini ();
l.unlock ();
}
};
template <typename Type>
struct hb_auto_t : Type
{
@ -854,8 +598,7 @@ struct hb_vector_size_t
union {
elt_t v[byte_size / sizeof (elt_t)];
#if HB_VECTOR_SIZE
typedef unsigned long vec_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
vec_t vec[byte_size / sizeof (vec_t)];
hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
#endif
} u;
};

View File

@ -39,7 +39,8 @@
* hb_face_t
*/
struct hb_face_t {
struct hb_face_t
{
hb_object_header_t header;
ASSERT_POD ();
@ -55,16 +56,13 @@ struct hb_face_t {
struct hb_shaper_data_t shaper_data; /* Various shaper data. */
/* Various non-shaping data. */
/* ... */
/* Cache */
struct plan_node_t {
struct plan_node_t
{
hb_shape_plan_t *shape_plan;
plan_node_t *next;
} *shape_plans;
inline hb_blob_t *reference_table (hb_tag_t tag) const
{
hb_blob_t *blob;
@ -97,8 +95,7 @@ struct hb_face_t {
HB_INTERNAL void load_upem (void) const;
HB_INTERNAL void load_num_glyphs (void) const;
};
extern HB_INTERNAL const hb_face_t _hb_face_nil;
DECLARE_NULL_INSTANCE (hb_face_t);
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);

View File

@ -31,9 +31,6 @@
#include "hb-face-private.hh"
#include "hb-blob-private.hh"
#include "hb-open-file-private.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
/**
@ -52,17 +49,22 @@ hb_face_count (hb_blob_t *blob)
if (unlikely (!blob))
return 0;
hb_blob_t *sanitized = OT::Sanitizer<OT::OpenTypeFontFile> ().sanitize (blob);
/* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
/* Make API signature const after. */
hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
unsigned int ret = ot.get_face_count ();
hb_blob_destroy (sanitized);
return ot.get_face_count ();
return ret;
}
/*
* hb_face_t
*/
const hb_face_t _hb_face_nil = {
DEFINE_NULL_INSTANCE (hb_face_t) =
{
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
@ -188,7 +190,7 @@ hb_face_create (hb_blob_t *blob,
if (unlikely (!blob))
blob = hb_blob_get_empty ();
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
if (unlikely (!closure))
return hb_face_get_empty ();
@ -214,7 +216,7 @@ hb_face_create (hb_blob_t *blob,
hb_face_t *
hb_face_get_empty (void)
{
return const_cast<hb_face_t *> (&_hb_face_nil);
return const_cast<hb_face_t *> (&Null(hb_face_t));
}
@ -301,7 +303,7 @@ hb_face_set_user_data (hb_face_t *face,
* Since: 0.9.2
**/
void *
hb_face_get_user_data (hb_face_t *face,
hb_face_get_user_data (const hb_face_t *face,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (face, key);
@ -335,7 +337,7 @@ hb_face_make_immutable (hb_face_t *face)
* Since: 0.9.2
**/
hb_bool_t
hb_face_is_immutable (hb_face_t *face)
hb_face_is_immutable (const hb_face_t *face)
{
return face->immutable;
}
@ -353,8 +355,8 @@ hb_face_is_immutable (hb_face_t *face)
* Since: 0.9.2
**/
hb_blob_t *
hb_face_reference_table (hb_face_t *face,
hb_tag_t tag)
hb_face_reference_table (const hb_face_t *face,
hb_tag_t tag)
{
return face->reference_table (tag);
}
@ -405,7 +407,7 @@ hb_face_set_index (hb_face_t *face,
* Since: 0.9.2
**/
unsigned int
hb_face_get_index (hb_face_t *face)
hb_face_get_index (const hb_face_t *face)
{
return face->index;
}
@ -440,20 +442,11 @@ hb_face_set_upem (hb_face_t *face,
* Since: 0.9.2
**/
unsigned int
hb_face_get_upem (hb_face_t *face)
hb_face_get_upem (const hb_face_t *face)
{
return face->get_upem ();
}
void
hb_face_t::load_upem (void) const
{
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
const OT::head *head_table = head_blob->as<OT::head> ();
upem = head_table->get_upem ();
hb_blob_destroy (head_blob);
}
/**
* hb_face_set_glyph_count:
* @face: a face.
@ -484,20 +477,11 @@ hb_face_set_glyph_count (hb_face_t *face,
* Since: 0.9.7
**/
unsigned int
hb_face_get_glyph_count (hb_face_t *face)
hb_face_get_glyph_count (const hb_face_t *face)
{
return face->get_num_glyphs ();
}
void
hb_face_t::load_num_glyphs (void) const
{
hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
num_glyphs = maxp_table->get_num_glyphs ();
hb_blob_destroy (maxp_blob);
}
/**
* hb_face_get_table_tags:
* @face: a face.
@ -509,7 +493,7 @@ hb_face_t::load_num_glyphs (void) const
* Since: 1.6.0
**/
unsigned int
hb_face_get_table_tags (hb_face_t *face,
hb_face_get_table_tags (const hb_face_t *face,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */)

View File

@ -76,19 +76,19 @@ hb_face_set_user_data (hb_face_t *face,
hb_bool_t replace);
HB_EXTERN void *
hb_face_get_user_data (hb_face_t *face,
hb_face_get_user_data (const hb_face_t *face,
hb_user_data_key_t *key);
HB_EXTERN void
hb_face_make_immutable (hb_face_t *face);
HB_EXTERN hb_bool_t
hb_face_is_immutable (hb_face_t *face);
hb_face_is_immutable (const hb_face_t *face);
HB_EXTERN hb_blob_t *
hb_face_reference_table (hb_face_t *face,
hb_tag_t tag);
hb_face_reference_table (const hb_face_t *face,
hb_tag_t tag);
HB_EXTERN hb_blob_t *
hb_face_reference_blob (hb_face_t *face);
@ -98,24 +98,24 @@ hb_face_set_index (hb_face_t *face,
unsigned int index);
HB_EXTERN unsigned int
hb_face_get_index (hb_face_t *face);
hb_face_get_index (const hb_face_t *face);
HB_EXTERN void
hb_face_set_upem (hb_face_t *face,
unsigned int upem);
HB_EXTERN unsigned int
hb_face_get_upem (hb_face_t *face);
hb_face_get_upem (const hb_face_t *face);
HB_EXTERN void
hb_face_set_glyph_count (hb_face_t *face,
unsigned int glyph_count);
HB_EXTERN unsigned int
hb_face_get_glyph_count (hb_face_t *face);
hb_face_get_glyph_count (const hb_face_t *face);
HB_EXTERN unsigned int
hb_face_get_table_tags (hb_face_t *face,
hb_face_get_table_tags (const hb_face_t *face,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */);

View File

@ -36,16 +36,16 @@ HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
* shaper face data
*/
struct hb_fallback_shaper_face_data_t {};
struct hb_fallback_face_data_t {};
hb_fallback_shaper_face_data_t *
hb_fallback_face_data_t *
_hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED)
{
return (hb_fallback_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_fallback_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED)
_hb_fallback_shaper_face_data_destroy (hb_fallback_face_data_t *data HB_UNUSED)
{
}
@ -54,16 +54,16 @@ _hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_U
* shaper font data
*/
struct hb_fallback_shaper_font_data_t {};
struct hb_fallback_font_data_t {};
hb_fallback_shaper_font_data_t *
hb_fallback_font_data_t *
_hb_fallback_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
return (hb_fallback_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_fallback_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_UNUSED)
_hb_fallback_shaper_font_data_destroy (hb_fallback_font_data_t *data HB_UNUSED)
{
}
@ -72,20 +72,20 @@ _hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_U
* shaper shape_plan data
*/
struct hb_fallback_shaper_shape_plan_data_t {};
struct hb_fallback_shape_plan_data_t {};
hb_fallback_shaper_shape_plan_data_t *
hb_fallback_shape_plan_data_t *
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_fallback_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shape_plan_data_t *data HB_UNUSED)
{
}

View File

@ -35,7 +35,6 @@
#include "hb-shaper-private.hh"
/*
* hb_font_funcs_t
*/
@ -47,6 +46,8 @@
HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
@ -57,7 +58,8 @@
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
/* ^--- Add new callbacks here */
struct hb_font_funcs_t {
struct hb_font_funcs_t
{
hb_object_header_t header;
ASSERT_POD ();
@ -89,14 +91,15 @@ struct hb_font_funcs_t {
]) (void);
} get;
};
DECLARE_NULL_INSTANCE (hb_font_funcs_t);
/*
* hb_font_t
*/
struct hb_font_t {
struct hb_font_t
{
hb_object_header_t header;
ASSERT_POD ();
@ -233,6 +236,32 @@ struct hb_font_t {
klass->user_data.glyph_v_advance);
}
inline void get_glyph_h_advances (unsigned int count,
hb_codepoint_t *first_glyph,
unsigned int glyph_stride,
hb_position_t *first_advance,
unsigned int advance_stride)
{
return klass->get.f.glyph_h_advances (this, user_data,
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
klass->user_data.glyph_h_advances);
}
inline void get_glyph_v_advances (unsigned int count,
hb_codepoint_t *first_glyph,
unsigned int glyph_stride,
hb_position_t *first_advance,
unsigned int advance_stride)
{
return klass->get.f.glyph_v_advances (this, user_data,
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
klass->user_data.glyph_v_advances);
}
inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y)
{
@ -341,13 +370,23 @@ struct hb_font_t {
hb_direction_t direction,
hb_position_t *x, hb_position_t *y)
{
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
*x = *y = 0;
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
*x = get_glyph_h_advance (glyph);
*y = 0;
} else {
*x = 0;
else
*y = get_glyph_v_advance (glyph);
}
}
inline void get_glyph_advances_for_direction (hb_direction_t direction,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride)
{
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
else
get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
}
inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
@ -553,6 +592,7 @@ struct hb_font_t {
return (float) v * scale / face->get_upem ();
}
};
DECLARE_NULL_INSTANCE (hb_font_t);
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);

View File

@ -29,6 +29,7 @@
#include "hb-private.hh"
#include "hb-font-private.hh"
#include "hb-machinery-private.hh"
/*
@ -45,10 +46,10 @@ hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_font_h_extents_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
hb_font_get_font_h_extents_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_font_h_extents (metrics);
if (ret) {
@ -69,10 +70,10 @@ hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_font_v_extents_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
hb_font_get_font_v_extents_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_font_v_extents (metrics);
if (ret) {
@ -94,11 +95,11 @@ hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_nominal_glyph_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
hb_font_get_nominal_glyph_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
return font->parent->get_nominal_glyph (unicode, glyph);
}
@ -115,12 +116,12 @@ hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_variation_glyph_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
hb_font_get_variation_glyph_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
}
@ -129,16 +130,16 @@ hb_font_get_variation_glyph_parent (hb_font_t *font,
static hb_position_t
hb_font_get_glyph_h_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_codepoint_t glyph HB_UNUSED,
void *user_data HB_UNUSED)
{
return font->x_scale;
}
static hb_position_t
hb_font_get_glyph_h_advance_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
hb_font_get_glyph_h_advance_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
{
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
}
@ -146,21 +147,85 @@ hb_font_get_glyph_h_advance_parent (hb_font_t *font,
static hb_position_t
hb_font_get_glyph_v_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_codepoint_t glyph HB_UNUSED,
void *user_data HB_UNUSED)
{
/* TODO use font_extents.ascender+descender */
return font->y_scale;
}
static hb_position_t
hb_font_get_glyph_v_advance_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
hb_font_get_glyph_v_advance_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
{
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
}
#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
static void
hb_font_get_glyph_h_advances_default (hb_font_t* font,
void* font_data HB_UNUSED,
unsigned int count,
hb_codepoint_t *first_glyph,
unsigned int glyph_stride,
hb_position_t *first_advance,
unsigned int advance_stride,
void *user_data HB_UNUSED)
{
if (font->has_glyph_h_advance_func ())
{
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->get_glyph_h_advance (*first_glyph);
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
return;
}
font->parent->get_glyph_h_advances (count,
first_glyph, glyph_stride,
first_advance, advance_stride);
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->parent_scale_x_distance (*first_advance);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
}
#define hb_font_get_glyph_v_advances_nil hb_font_get_glyph_v_advances_default
static void
hb_font_get_glyph_v_advances_default (hb_font_t* font,
void* font_data HB_UNUSED,
unsigned int count,
hb_codepoint_t *first_glyph,
unsigned int glyph_stride,
hb_position_t *first_advance,
unsigned int advance_stride,
void *user_data HB_UNUSED)
{
if (font->has_glyph_v_advance_func ())
{
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->get_glyph_v_advance (*first_glyph);
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
return;
}
font->parent->get_glyph_v_advances (count,
first_glyph, glyph_stride,
first_advance, advance_stride);
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->parent_scale_y_distance (*first_advance);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
}
static hb_bool_t
hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
@ -173,12 +238,12 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
return true;
}
static hb_bool_t
hb_font_get_glyph_h_origin_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
hb_font_get_glyph_h_origin_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
if (ret)
@ -198,12 +263,12 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_glyph_v_origin_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
hb_font_get_glyph_v_origin_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
if (ret)
@ -221,11 +286,11 @@ hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
return 0;
}
static hb_position_t
hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t left_glyph,
hb_codepoint_t right_glyph,
void *user_data HB_UNUSED)
hb_font_get_glyph_h_kerning_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t left_glyph,
hb_codepoint_t right_glyph,
void *user_data HB_UNUSED)
{
return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
}
@ -240,11 +305,11 @@ hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
return 0;
}
static hb_position_t
hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t top_glyph,
hb_codepoint_t bottom_glyph,
void *user_data HB_UNUSED)
hb_font_get_glyph_v_kerning_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t top_glyph,
hb_codepoint_t bottom_glyph,
void *user_data HB_UNUSED)
{
return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
}
@ -260,11 +325,11 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_glyph_extents_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
hb_font_get_glyph_extents_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
if (ret) {
@ -287,13 +352,13 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_glyph_contour_point_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
unsigned int point_index,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
hb_font_get_glyph_contour_point_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
unsigned int point_index,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
if (ret)
@ -312,11 +377,11 @@ hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_glyph_name_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
char *name, unsigned int size,
void *user_data HB_UNUSED)
hb_font_get_glyph_name_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
char *name, unsigned int size,
void *user_data HB_UNUSED)
{
return font->parent->get_glyph_name (glyph, name, size);
}
@ -332,16 +397,17 @@ hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
return false;
}
static hb_bool_t
hb_font_get_glyph_from_name_parent (hb_font_t *font,
void *font_data HB_UNUSED,
const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
hb_font_get_glyph_from_name_default (hb_font_t *font,
void *font_data HB_UNUSED,
const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
return font->parent->get_glyph_from_name (name, len, glyph);
}
static const hb_font_funcs_t _hb_font_funcs_nil = {
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
@ -364,7 +430,8 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
}
}
};
static const hb_font_funcs_t _hb_font_funcs_parent = {
static const hb_font_funcs_t _hb_font_funcs_default = {
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
@ -381,7 +448,7 @@ static const hb_font_funcs_t _hb_font_funcs_parent = {
},
{
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
}
@ -406,7 +473,7 @@ hb_font_funcs_create (void)
if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
return hb_font_funcs_get_empty ();
ffuncs->get = _hb_font_funcs_parent.get;
ffuncs->get = _hb_font_funcs_default.get;
return ffuncs;
}
@ -423,7 +490,7 @@ hb_font_funcs_create (void)
hb_font_funcs_t *
hb_font_funcs_get_empty (void)
{
return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_default);
}
/**
@ -562,9 +629,9 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
ffuncs->user_data.name = user_data; \
ffuncs->destroy.name = destroy; \
} else { \
ffuncs->get.f.name = hb_font_get_##name##_parent; \
ffuncs->user_data.name = nullptr; \
ffuncs->destroy.name = nullptr; \
ffuncs->get.f.name = hb_font_get_##name##_default; \
ffuncs->user_data.name = nullptr; \
ffuncs->destroy.name = nullptr; \
} \
}
@ -574,9 +641,8 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
bool
hb_font_t::has_func (unsigned int i)
{
if (parent && parent != hb_font_get_empty () && parent->has_func (i))
return true;
return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
return (this->klass->get.array[i] != _hb_font_funcs_default.get.array[i]) ||
(parent && parent != &_hb_Null_hb_font_t && parent->has_func (i));
}
/* Public getters */
@ -717,6 +783,43 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
return font->get_glyph_v_advance (glyph);
}
/**
* hb_font_get_glyph_h_advances:
* @font: a font.
*
*
*
* Since: 1.8.6
**/
void
hb_font_get_glyph_h_advances (hb_font_t* font,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride)
{
font->get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
}
/**
* hb_font_get_glyph_v_advances:
* @font: a font.
*
*
*
* Since: 1.8.6
**/
void
hb_font_get_glyph_v_advances (hb_font_t* font,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride)
{
font->get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
}
/**
* hb_font_get_glyph_h_origin:
* @font: a font.
@ -921,6 +1024,26 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
{
return font->get_glyph_advance_for_direction (glyph, direction, x, y);
}
/**
* hb_font_get_glyph_advances_for_direction:
* @font: a font.
* @direction:
*
*
*
* Since: 1.8.6
**/
HB_EXTERN void
hb_font_get_glyph_advances_for_direction (hb_font_t* font,
hb_direction_t direction,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride)
{
font->get_glyph_advances_for_direction (direction, count, first_glyph, glyph_stride, first_advance, advance_stride);
}
/**
* hb_font_get_glyph_origin_for_direction:
@ -1100,6 +1223,37 @@ hb_font_glyph_from_string (hb_font_t *font,
* hb_font_t
*/
DEFINE_NULL_INSTANCE (hb_font_t) =
{
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
nullptr, /* parent */
const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
1000, /* x_scale */
1000, /* y_scale */
0, /* x_ppem */
0, /* y_ppem */
0, /* ptem */
0, /* num_coords */
nullptr, /* coords */
const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t), /* klass */
nullptr, /* user_data */
nullptr, /* destroy */
{
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
}
};
/**
* hb_font_create: (Xconstructor)
* @face: a face.
@ -1187,36 +1341,7 @@ hb_font_create_sub_font (hb_font_t *parent)
hb_font_t *
hb_font_get_empty (void)
{
static const hb_font_t _hb_font_nil = {
HB_OBJECT_HEADER_STATIC,
true, /* immutable */
nullptr, /* parent */
const_cast<hb_face_t *> (&_hb_face_nil),
1000, /* x_scale */
1000, /* y_scale */
0, /* x_ppem */
0, /* y_ppem */
0, /* ptem */
0, /* num_coords */
nullptr, /* coords */
const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
nullptr, /* user_data */
nullptr, /* destroy */
{
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
}
};
return const_cast<hb_font_t *> (&_hb_font_nil);
return const_cast<hb_font_t *> (&Null(hb_font_t));
}
/**

View File

@ -132,6 +132,16 @@ typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride,
void *user_data);
typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t;
typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y,
@ -264,6 +274,38 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_v_advance_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_glyph_h_advances_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
* @destroy:
*
*
*
* Since: 1.8.6
**/
HB_EXTERN void
hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_h_advances_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_glyph_v_advances_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
* @destroy:
*
*
*
* Since: 1.8.6
**/
HB_EXTERN void
hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_v_advances_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_glyph_h_origin_func:
* @ffuncs: font functions.
@ -417,6 +459,21 @@ HB_EXTERN hb_position_t
hb_font_get_glyph_v_advance (hb_font_t *font,
hb_codepoint_t glyph);
HB_EXTERN void
hb_font_get_glyph_h_advances (hb_font_t* font,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride);
HB_EXTERN void
hb_font_get_glyph_v_advances (hb_font_t* font,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride);
HB_EXTERN hb_bool_t
hb_font_get_glyph_h_origin (hb_font_t *font,
hb_codepoint_t glyph,
@ -472,6 +529,14 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
HB_EXTERN void
hb_font_get_glyph_advances_for_direction (hb_font_t* font,
hb_direction_t direction,
unsigned count,
hb_codepoint_t *first_glyph,
unsigned glyph_stride,
hb_position_t *first_advance,
unsigned advance_stride);
HB_EXTERN void
hb_font_get_glyph_origin_for_direction (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,

View File

@ -497,7 +497,10 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
if (error)
{
free (buffer);
return nullptr;
}
return hb_blob_create ((const char *) buffer, length,
HB_MEMORY_MODE_WRITABLE,

View File

@ -71,6 +71,7 @@ HB_DEFINE_OBJECT_TYPE (face)
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)
HB_DEFINE_OBJECT_TYPE (set)
HB_DEFINE_OBJECT_TYPE (map)
HB_DEFINE_OBJECT_TYPE (shape_plan)
HB_DEFINE_OBJECT_TYPE (unicode_funcs)
HB_DEFINE_VALUE_TYPE (feature)

View File

@ -89,6 +89,10 @@ HB_EXTERN GType
hb_gobject_set_get_type (void);
#define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ())
HB_EXTERN GType
hb_gobject_map_get_type (void);
#define HB_GOBJECT_TYPE_MAP (hb_gobject_map_get_type ())
HB_EXTERN GType
hb_gobject_shape_plan_get_type (void);
#define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())

View File

@ -48,7 +48,7 @@ typedef struct hb_graphite2_tablelist_t {
unsigned int tag;
} hb_graphite2_tablelist_t;
struct hb_graphite2_shaper_face_data_t {
struct hb_graphite2_face_data_t {
hb_face_t *face;
gr_face *grface;
hb_graphite2_tablelist_t *tlist;
@ -56,7 +56,7 @@ struct hb_graphite2_shaper_face_data_t {
static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
{
hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
hb_graphite2_tablelist_t *tlist = face_data->tlist;
hb_blob_t *blob = nullptr;
@ -93,7 +93,7 @@ retry:
return d;
}
hb_graphite2_shaper_face_data_t *
hb_graphite2_face_data_t *
_hb_graphite2_shaper_face_data_create (hb_face_t *face)
{
hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
@ -106,7 +106,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
}
hb_blob_destroy (silf_blob);
hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) calloc (1, sizeof (hb_graphite2_face_data_t));
if (unlikely (!data))
return nullptr;
@ -122,7 +122,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
}
void
_hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
_hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
{
hb_graphite2_tablelist_t *tlist = data->tlist;
@ -154,16 +154,16 @@ hb_graphite2_face_get_gr_face (hb_face_t *face)
* shaper font data
*/
struct hb_graphite2_shaper_font_data_t {};
struct hb_graphite2_font_data_t {};
hb_graphite2_shaper_font_data_t *
hb_graphite2_font_data_t *
_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_graphite2_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED)
_hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED)
{
}
@ -181,20 +181,20 @@ hb_graphite2_font_get_gr_font (hb_font_t *font)
* shaper shape_plan data
*/
struct hb_graphite2_shaper_shape_plan_data_t {};
struct hb_graphite2_shape_plan_data_t {};
hb_graphite2_shaper_shape_plan_data_t *
hb_graphite2_shape_plan_data_t *
_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_graphite2_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shape_plan_data_t *data HB_UNUSED)
{
}

View File

@ -0,0 +1,149 @@
/*
* Copyright © 2018 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_ITER_PRIVATE_HH
#define HB_ITER_PRIVATE_HH
#include "hb-private.hh"
/* Unified iterator object.
*
* The goal of this template is to make the same iterator interface
* available to all types, and make it very easy and compact to use.
* Iterator objects are small, light-weight, objects that can be
* copied by value. If the collection / object being iterated on
* is writable, then the iterator points to lvalues, otherwise it
* returns rvalues.
*
* The way to declare, initialize, and use iterators, eg.:
*
* Iter<const int *> s (src);
* Iter<int *> t (dst);
* for (; s && t; s++, t++)
* *s = *t;
*/
template <typename T>
struct Iter;
#if 0
template <typename T>
struct Iter
{
explicit inline Iter (const T &c);
};
#endif
template <typename T>
struct Iter<T *>
{
/* Type of items. */
typedef T Value;
/* Constructors. */
inline Iter (T *array_, int length_) :
array (array_), length (MAX (length_, 0)) {}
template <unsigned int length_>
explicit inline Iter (T (&array_)[length_]) :
array (array_), length (length_) {}
/* Emptiness. */
explicit inline operator bool (void) const { return bool (length); }
/* Current item. */
inline T &operator * (void)
{
if (unlikely (!length)) return CrapOrNull(T);
return *array;
}
inline T &operator -> (void)
{
return (operator *);
}
/* Next. */
inline Iter<T *> & operator ++ (void)
{
if (unlikely (!length)) return *this;
array++;
length--;
return *this;
}
/* Might return void, or a copy of pre-increment iterator. */
inline void operator ++ (int)
{
if (unlikely (!length)) return;
array++;
length--;
}
/* Some iterators might implement len(). */
inline unsigned int len (void) const { return length; }
/* Some iterators might implement fast-forward.
* Only implement it if it's constant-time. */
inline void operator += (unsigned int n)
{
n = MIN (n, length);
array += n;
length -= n;
}
/* Some iterators might implement random-access.
* Only implement it if it's constant-time. */
inline Iter<T *> & operator [] (unsigned int i)
{
if (unlikely (i >= length)) return CrapOrNull(T);
return array[i];
}
private:
T *array;
unsigned int length;
};
/* XXX Remove
* Just to test these compile. */
static inline void
m (void)
{
const int src[10] = {};
int dst[20];
Iter<const int *> s (src);
Iter<const int *> s2 (src, 5);
Iter<int *> t (dst);
s2 = s;
for (; s && t; ++s, ++t)
{
*t = *s;
}
}
#endif /* HB_ITER_PRIVATE_HH */

View File

@ -0,0 +1,720 @@
/*
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
* Copyright © 2012,2018 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_MACHINERY_PRIVATE_HH
#define HB_MACHINERY_PRIVATE_HH
#include "hb-private.hh"
#include "hb-blob-private.hh"
#include "hb-iter-private.hh"
/*
* Casts
*/
/* Cast to struct T, reference to reference */
template<typename Type, typename TObject>
static inline const Type& CastR(const TObject &X)
{ return reinterpret_cast<const Type&> (X); }
template<typename Type, typename TObject>
static inline Type& CastR(TObject &X)
{ return reinterpret_cast<Type&> (X); }
/* Cast to struct T, pointer to pointer */
template<typename Type, typename TObject>
static inline const Type* CastP(const TObject *X)
{ return reinterpret_cast<const Type*> (X); }
template<typename Type, typename TObject>
static inline Type* CastP(TObject *X)
{ return reinterpret_cast<Type*> (X); }
/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
* location pointed to by P plus Ofs bytes. */
template<typename Type>
static inline const Type& StructAtOffset(const void *P, unsigned int offset)
{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
template<typename Type>
static inline Type& StructAtOffset(void *P, unsigned int offset)
{ return * reinterpret_cast<Type*> ((char *) P + offset); }
/* StructAfter<T>(X) returns the struct T& that is placed after X.
* Works with X of variable size also. X must implement get_size() */
template<typename Type, typename TObject>
static inline const Type& StructAfter(const TObject &X)
{ return StructAtOffset<Type>(&X, X.get_size()); }
template<typename Type, typename TObject>
static inline Type& StructAfter(TObject &X)
{ return StructAtOffset<Type>(&X, X.get_size()); }
/*
* Size checking
*/
/* Check _assertion in a method environment */
#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
inline void _instance_assertion_on_line_##_line (void) const \
{ \
static_assert ((_assertion), ""); \
ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
}
# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
/* Check that _code compiles in a method environment */
#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
inline void _compiles_assertion_on_line_##_line (void) const \
{ _code; }
# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
#define DEFINE_SIZE_STATIC(size) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
static const unsigned int static_size = (size); \
static const unsigned int min_size = (size); \
inline unsigned int get_size (void) const { return (size); }
#define DEFINE_SIZE_UNION(size, _member) \
DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_MIN(size) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_ARRAY(size, array) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
static const unsigned int min_size = (size)
/*
* Dispatch
*/
template <typename Context, typename Return, unsigned int MaxDebugDepth>
struct hb_dispatch_context_t
{
static const unsigned int max_debug_depth = MaxDebugDepth;
typedef Return return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
};
/*
* Sanitize
*/
/* This limits sanitizing time on really broken fonts. */
#ifndef HB_SANITIZE_MAX_EDITS
#define HB_SANITIZE_MAX_EDITS 32
#endif
#ifndef HB_SANITIZE_MAX_OPS_FACTOR
#define HB_SANITIZE_MAX_OPS_FACTOR 8
#endif
#ifndef HB_SANITIZE_MAX_OPS_MIN
#define HB_SANITIZE_MAX_OPS_MIN 16384
#endif
struct hb_sanitize_context_t :
hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
{
inline hb_sanitize_context_t (void) :
debug_depth (0),
start (nullptr), end (nullptr),
writable (false), edit_count (0), max_ops (0),
blob (nullptr),
num_glyphs (65536),
num_glyphs_set (false) {}
inline const char *get_name (void) { return "SANITIZE"; }
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format)
{ return format->sanitize (this); }
template <typename T>
inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
static return_t default_return_value (void) { return true; }
static return_t no_dispatch_return_value (void) { return false; }
bool stop_sublookup_iteration (const return_t r) const { return !r; }
inline void init (hb_blob_t *b)
{
this->blob = hb_blob_reference (b);
this->writable = false;
}
inline void set_num_glyphs (unsigned int num_glyphs_)
{
num_glyphs = num_glyphs_;
num_glyphs_set = true;
}
inline unsigned int get_num_glyphs (void) { return num_glyphs; }
inline void start_processing (void)
{
this->start = this->blob->data;
this->end = this->start + this->blob->length;
assert (this->start <= this->end); /* Must not overflow. */
this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
(unsigned) HB_SANITIZE_MAX_OPS_MIN);
this->edit_count = 0;
this->debug_depth = 0;
DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
"start [%p..%p] (%lu bytes)",
this->start, this->end,
(unsigned long) (this->end - this->start));
}
inline void end_processing (void)
{
DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
"end [%p..%p] %u edit requests",
this->start, this->end, this->edit_count);
hb_blob_destroy (this->blob);
this->blob = nullptr;
this->start = this->end = nullptr;
}
inline bool check_range (const void *base, unsigned int len) const
{
const char *p = (const char *) base;
bool ok = this->max_ops-- > 0 &&
this->start <= p &&
p <= this->end &&
(unsigned int) (this->end - p) >= len;
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
p, p + len, len,
this->start, this->end,
ok ? "OK" : "OUT-OF-RANGE");
return likely (ok);
}
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
{
const char *p = (const char *) base;
bool overflows = hb_unsigned_mul_overflows (len, record_size);
unsigned int array_size = record_size * len;
bool ok = !overflows && this->check_range (base, array_size);
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
p, p + (record_size * len), record_size, len, (unsigned int) array_size,
this->start, this->end,
overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
return likely (ok);
}
template <typename Type>
inline bool check_struct (const Type *obj) const
{
return likely (this->check_range (obj, obj->min_size));
}
inline bool may_edit (const void *base, unsigned int len)
{
if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
return false;
const char *p = (const char *) base;
this->edit_count++;
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
this->edit_count,
p, p + len, len,
this->start, this->end,
this->writable ? "GRANTED" : "DENIED");
return this->writable;
}
template <typename Type, typename ValueType>
inline bool try_set (const Type *obj, const ValueType &v) {
if (this->may_edit (obj, obj->static_size)) {
const_cast<Type *> (obj)->set (v);
return true;
}
return false;
}
template <typename Type>
inline hb_blob_t *sanitize_blob (hb_blob_t *blob)
{
bool sane;
init (blob);
retry:
DEBUG_MSG_FUNC (SANITIZE, start, "start");
start_processing ();
if (unlikely (!start))
{
end_processing ();
return blob;
}
Type *t = CastP<Type> (const_cast<char *> (start));
sane = t->sanitize (this);
if (sane)
{
if (edit_count)
{
DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
/* sanitize again to ensure no toe-stepping */
edit_count = 0;
sane = t->sanitize (this);
if (edit_count) {
DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
sane = false;
}
}
}
else
{
if (edit_count && !writable) {
start = hb_blob_get_data_writable (blob, nullptr);
end = start + blob->length;
if (start)
{
writable = true;
/* ok, we made it writable by relocating. try again */
DEBUG_MSG_FUNC (SANITIZE, start, "retry");
goto retry;
}
}
}
end_processing ();
DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
if (sane)
{
hb_blob_make_immutable (blob);
return blob;
}
else
{
hb_blob_destroy (blob);
return hb_blob_get_empty ();
}
}
template <typename Type>
inline hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
{
if (!num_glyphs_set)
set_num_glyphs (hb_face_get_glyph_count (face));
return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
}
mutable unsigned int debug_depth;
const char *start, *end;
private:
bool writable;
unsigned int edit_count;
mutable int max_ops;
hb_blob_t *blob;
unsigned int num_glyphs;
bool num_glyphs_set;
};
/*
* Serialize
*/
struct hb_serialize_context_t
{
inline hb_serialize_context_t (void *start_, unsigned int size)
{
this->start = (char *) start_;
this->end = this->start + size;
this->ran_out_of_room = false;
this->head = this->start;
this->debug_depth = 0;
}
template <typename Type>
inline Type *start_serialize (void)
{
DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
"start [%p..%p] (%lu bytes)",
this->start, this->end,
(unsigned long) (this->end - this->start));
return start_embed<Type> ();
}
inline void end_serialize (void)
{
DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
"end [%p..%p] serialized %d bytes; %s",
this->start, this->end,
(int) (this->head - this->start),
this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
}
template <typename Type>
inline Type *copy (void)
{
assert (!this->ran_out_of_room);
unsigned int len = this->head - this->start;
void *p = malloc (len);
if (p)
memcpy (p, this->start, len);
return reinterpret_cast<Type *> (p);
}
template <typename Type>
inline Type *allocate_size (unsigned int size)
{
if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
this->ran_out_of_room = true;
return nullptr;
}
memset (this->head, 0, size);
char *ret = this->head;
this->head += size;
return reinterpret_cast<Type *> (ret);
}
template <typename Type>
inline Type *allocate_min (void)
{
return this->allocate_size<Type> (Type::min_size);
}
template <typename Type>
inline Type *start_embed (void)
{
Type *ret = reinterpret_cast<Type *> (this->head);
return ret;
}
template <typename Type>
inline Type *embed (const Type &obj)
{
unsigned int size = obj.get_size ();
Type *ret = this->allocate_size<Type> (size);
if (unlikely (!ret)) return nullptr;
memcpy (ret, obj, size);
return ret;
}
template <typename Type>
inline Type *extend_min (Type &obj)
{
unsigned int size = obj.min_size;
assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
return reinterpret_cast<Type *> (&obj);
}
template <typename Type>
inline Type *extend (Type &obj)
{
unsigned int size = obj.get_size ();
assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
return reinterpret_cast<Type *> (&obj);
}
unsigned int debug_depth;
char *start, *end, *head;
bool ran_out_of_room;
};
/*
* Supplier
*/
template <typename Type>
struct Supplier
{
inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
{
head = array;
len = len_;
stride = stride_;
}
inline const Type operator [] (unsigned int i) const
{
if (unlikely (i >= len)) return Type ();
return * (const Type *) (const void *) ((const char *) head + stride * i);
}
inline Supplier<Type> & operator += (unsigned int count)
{
if (unlikely (count > len))
count = len;
len -= count;
head = (const Type *) (const void *) ((const char *) head + stride * count);
return *this;
}
private:
inline Supplier (const Supplier<Type> &); /* Disallow copy */
inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
unsigned int len;
unsigned int stride;
const Type *head;
};
/*
* Big-endian integers.
*/
template <typename Type, int Bytes> struct BEInt;
template <typename Type>
struct BEInt<Type, 1>
{
public:
inline void set (Type V)
{
v = V;
}
inline operator Type (void) const
{
return v;
}
private: uint8_t v;
};
template <typename Type>
struct BEInt<Type, 2>
{
public:
inline void set (Type V)
{
v[0] = (V >> 8) & 0xFF;
v[1] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[0] << 8)
+ (v[1] );
}
private: uint8_t v[2];
};
template <typename Type>
struct BEInt<Type, 3>
{
public:
inline void set (Type V)
{
v[0] = (V >> 16) & 0xFF;
v[1] = (V >> 8) & 0xFF;
v[2] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[0] << 16)
+ (v[1] << 8)
+ (v[2] );
}
private: uint8_t v[3];
};
template <typename Type>
struct BEInt<Type, 4>
{
public:
inline void set (Type V)
{
v[0] = (V >> 24) & 0xFF;
v[1] = (V >> 16) & 0xFF;
v[2] = (V >> 8) & 0xFF;
v[3] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[0] << 24)
+ (v[1] << 16)
+ (v[2] << 8)
+ (v[3] );
}
private: uint8_t v[4];
};
/*
* Lazy loaders.
*/
template <unsigned int WheresFace,
typename Subclass,
typename Returned,
typename Stored = Returned>
struct hb_lazy_loader_t
{
static_assert (WheresFace > 0, "");
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
inline Subclass* thiz (void) { return static_cast<Subclass *> (this); }
inline void init0 (void) {} /* Init, when memory is already set to 0. No-op for us. */
inline void init (void)
{
instance = nullptr;
}
inline void fini (void)
{
if (instance)
thiz ()->destroy (instance);
}
inline const Returned * operator -> (void) const { return thiz ()->get (); }
inline const Returned & operator * (void) const { return *thiz ()->get (); }
inline Stored * get_stored (void) const
{
retry:
Stored *p = (Stored *) hb_atomic_ptr_get (&this->instance);
if (unlikely (!p))
{
hb_face_t *face = *(((hb_face_t **) this) - WheresFace);
if (likely (!p))
p = thiz ()->create (face);
if (unlikely (!p))
p = thiz ()->create (nullptr); /* Produce nil object. */
assert (p);
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<Stored **>(&this->instance), nullptr, p)))
{
thiz ()->destroy (p);
goto retry;
}
}
return p;
}
inline void set_stored (Stored *instance_)
{
/* This *must* be called when there are no other threads accessing.
* However, to make TSan, etc, happy, we using cmpexch. */
retry:
Stored *p = (Stored *) hb_atomic_ptr_get (&this->instance);
if (p)
{
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<Stored **>(&this->instance), p, instance_)))
goto retry;
thiz ()->destroy (p);
}
}
inline const Returned * get (void) const
{
return thiz ()->convert (get_stored ());
}
static inline const Returned* convert (const Stored *p)
{
return p;
}
private:
/* Must only have one pointer. */
mutable Stored *instance;
};
/* Specializations. */
template <unsigned int WheresFace, typename T>
struct hb_object_lazy_loader_t : hb_lazy_loader_t<WheresFace, hb_object_lazy_loader_t<WheresFace, T>, T>
{
static inline T *create (hb_face_t *face)
{
if (unlikely (!face))
return const_cast<T *> (&Null(T));
T *p = (T *) calloc (1, sizeof (T));
if (unlikely (!p))
p = const_cast<T *> (&Null(T));
else
p->init (face);
return p;
}
static inline void destroy (T *p)
{
if (p != &Null(T))
{
p->fini();
free (p);
}
}
};
template <unsigned int WheresFace, typename T>
struct hb_table_lazy_loader_t : hb_lazy_loader_t<WheresFace, hb_table_lazy_loader_t<WheresFace, T>, T, hb_blob_t>
{
static inline hb_blob_t *create (hb_face_t *face)
{
if (unlikely (!face))
return hb_blob_get_empty ();
return hb_sanitize_context_t ().reference_table<T> (face);
}
static inline void destroy (hb_blob_t *p)
{
hb_blob_destroy (p);
}
static inline const T* convert (const hb_blob_t *blob)
{
return blob->as<T> ();
}
inline hb_blob_t* get_blob (void) const
{
return this->get_stored ();
}
};
#endif /* HB_MACHINERY_PRIVATE_HH */

View File

@ -157,8 +157,6 @@ hb_map_allocation_successful (const hb_map_t *map)
*
*
*
* Return value:
*
* Since: 1.7.7
**/
void
@ -188,7 +186,7 @@ hb_map_get (const hb_map_t *map,
/**
* hb_map_del:
* @map: a map.
* @codepoint:
* @key:
*
*
*
@ -204,7 +202,7 @@ hb_map_del (hb_map_t *map,
/**
* hb_map_has:
* @map: a map.
* @codepoint:
* @key:
*
*
*

106
gfx/harfbuzz/src/hb-null.hh Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright © 2018 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_NULL_HH
#define HB_NULL_HH
#include "hb-private.hh"
/*
* Static pools
*/
/* Global nul-content Null pool. Enlarge as necessary. */
#define HB_NULL_POOL_SIZE 264
extern HB_INTERNAL
hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
/* Generic nul-content Null objects. */
template <typename Type>
static inline Type const & Null (void) {
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
return *reinterpret_cast<Type const *> (_hb_NullPool);
}
#define Null(Type) Null<Type>()
/* Specializaitons for arbitrary-content Null objects expressed in bytes. */
#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
} /* Close namespace. */ \
extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
template <> \
/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
} \
namespace Namespace { \
static_assert (true, "Just so we take semicolon after.")
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
/* Specializaitons for arbitrary-content Null objects expressed as struct initializer. */
#define DECLARE_NULL_INSTANCE(Type) \
extern HB_INTERNAL const Type _hb_Null_##Type; \
template <> \
/*static*/ inline const Type& Null<Type> (void) { \
return _hb_Null_##Type; \
} \
static_assert (true, "Just so we take semicolon after.")
#define DEFINE_NULL_INSTANCE(Type) \
const Type _hb_Null_##Type
/* Global writable pool. Enlarge as necessary. */
/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
* for correct operation. It only exist to catch and divert program logic bugs instead of
* causing bad memory access. So, races there are not actually introducing incorrectness
* in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
extern HB_INTERNAL
/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
/* CRAP pool: Common Region for Access Protection. */
template <typename Type>
static inline Type& Crap (void) {
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
*obj = Null(Type);
return *obj;
}
#define Crap(Type) Crap<Type>()
template <typename Type>
struct CrapOrNull {
static inline Type & get (void) { return Crap(Type); }
};
template <typename Type>
struct CrapOrNull<const Type> {
static inline Type const & get (void) { return Null(Type); }
};
#define CrapOrNull(Type) CrapOrNull<Type>::get ()
#endif /* HB_NULL_HH */

View File

@ -35,9 +35,107 @@
#include "hb-private.hh"
#include "hb-atomic-private.hh"
#include "hb-mutex-private.hh"
#include "hb-vector-private.hh"
/* reference_count */
/*
* Lockable set
*/
template <typename item_t, typename lock_t>
struct hb_lockable_set_t
{
hb_vector_t <item_t, 1> items;
inline void init (void) { items.init (); }
template <typename T>
inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
{
l.lock ();
item_t *item = items.find (v);
if (item) {
if (replace) {
item_t old = *item;
*item = v;
l.unlock ();
old.fini ();
}
else {
item = nullptr;
l.unlock ();
}
} else {
item = items.push (v);
l.unlock ();
}
return item;
}
template <typename T>
inline void remove (T v, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (item) {
item_t old = *item;
*item = items[items.len - 1];
items.pop ();
l.unlock ();
old.fini ();
} else {
l.unlock ();
}
}
template <typename T>
inline bool find (T v, item_t *i, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (item)
*i = *item;
l.unlock ();
return !!item;
}
template <typename T>
inline item_t *find_or_insert (T v, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (!item) {
item = items.push (v);
}
l.unlock ();
return item;
}
inline void fini (lock_t &l)
{
if (!items.len) {
/* No need for locking. */
items.fini ();
return;
}
l.lock ();
while (items.len) {
item_t old = items[items.len - 1];
items.pop ();
l.unlock ();
old.fini ();
l.lock ();
}
items.fini ();
l.unlock ();
}
};
/*
* Reference-count.
*/
#define HB_REFERENCE_COUNT_INERT_VALUE 0
#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
@ -47,14 +145,14 @@ struct hb_reference_count_t
{
hb_atomic_int_t ref_count;
inline void init (int v) { ref_count.set_unsafe (v); }
inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
inline void init (int v) { ref_count.set_relaxed (v); }
inline int get_relaxed (void) const { return ref_count.get_relaxed (); }
inline int inc (void) { return ref_count.inc (); }
inline int dec (void) { return ref_count.dec (); }
inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
inline void fini (void) { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
inline bool is_inert (void) const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
inline bool is_valid (void) const { return ref_count.get_relaxed () > 0; }
};
@ -89,12 +187,14 @@ struct hb_user_data_array_t
};
/* object_header */
/*
* Object header
*/
struct hb_object_header_t
{
hb_reference_count_t ref_count;
hb_user_data_array_t *user_data;
mutable hb_user_data_array_t *user_data;
#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, nullptr}
@ -103,7 +203,9 @@ struct hb_object_header_t
};
/* object */
/*
* Object
*/
template <typename Type>
static inline void hb_object_trace (const Type *obj, const char *function)
@ -111,7 +213,7 @@ static inline void hb_object_trace (const Type *obj, const char *function)
DEBUG_MSG (OBJECT, (void *) obj,
"%s refcount=%d",
function,
obj ? obj->header.ref_count.get_unsafe () : 0);
obj ? obj->header.ref_count.get_relaxed () : 0);
}
template <typename Type>

View File

@ -484,8 +484,6 @@ struct ResourceForkHeader
struct OpenTypeFontFile
{
static const hb_tag_t tableTag = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
enum {
CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */

View File

@ -32,484 +32,12 @@
#include "hb-private.hh"
#include "hb-blob-private.hh"
#include "hb-face-private.hh"
#include "hb-machinery-private.hh"
namespace OT {
/*
* Casts
*/
/* Cast to struct T, reference to reference */
template<typename Type, typename TObject>
static inline const Type& CastR(const TObject &X)
{ return reinterpret_cast<const Type&> (X); }
template<typename Type, typename TObject>
static inline Type& CastR(TObject &X)
{ return reinterpret_cast<Type&> (X); }
/* Cast to struct T, pointer to pointer */
template<typename Type, typename TObject>
static inline const Type* CastP(const TObject *X)
{ return reinterpret_cast<const Type*> (X); }
template<typename Type, typename TObject>
static inline Type* CastP(TObject *X)
{ return reinterpret_cast<Type*> (X); }
/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
* location pointed to by P plus Ofs bytes. */
template<typename Type>
static inline const Type& StructAtOffset(const void *P, unsigned int offset)
{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
template<typename Type>
static inline Type& StructAtOffset(void *P, unsigned int offset)
{ return * reinterpret_cast<Type*> ((char *) P + offset); }
/* StructAfter<T>(X) returns the struct T& that is placed after X.
* Works with X of variable size also. X must implement get_size() */
template<typename Type, typename TObject>
static inline const Type& StructAfter(const TObject &X)
{ return StructAtOffset<Type>(&X, X.get_size()); }
template<typename Type, typename TObject>
static inline Type& StructAfter(TObject &X)
{ return StructAtOffset<Type>(&X, X.get_size()); }
/*
* Size checking
*/
/* Check _assertion in a method environment */
#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
inline void _instance_assertion_on_line_##_line (void) const \
{ \
static_assert ((_assertion), ""); \
ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
}
# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
/* Check that _code compiles in a method environment */
#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
inline void _compiles_assertion_on_line_##_line (void) const \
{ _code; }
# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
#define DEFINE_SIZE_STATIC(size) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
static const unsigned int static_size = (size); \
static const unsigned int min_size = (size); \
inline unsigned int get_size (void) const { return (size); }
#define DEFINE_SIZE_UNION(size, _member) \
DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_MIN(size) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_ARRAY(size, array) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
static const unsigned int min_size = (size)
/*
* Dispatch
*/
template <typename Context, typename Return, unsigned int MaxDebugDepth>
struct hb_dispatch_context_t
{
static const unsigned int max_debug_depth = MaxDebugDepth;
typedef Return return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
};
/*
* Sanitize
*/
/* This limits sanitizing time on really broken fonts. */
#ifndef HB_SANITIZE_MAX_EDITS
#define HB_SANITIZE_MAX_EDITS 32
#endif
#ifndef HB_SANITIZE_MAX_OPS_FACTOR
#define HB_SANITIZE_MAX_OPS_FACTOR 8
#endif
#ifndef HB_SANITIZE_MAX_OPS_MIN
#define HB_SANITIZE_MAX_OPS_MIN 16384
#endif
struct hb_sanitize_context_t :
hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
{
inline hb_sanitize_context_t (void) :
debug_depth (0),
start (nullptr), end (nullptr),
writable (false), edit_count (0), max_ops (0),
blob (nullptr),
num_glyphs (0) {}
inline const char *get_name (void) { return "SANITIZE"; }
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format)
{ return format->sanitize (this); }
template <typename T>
inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
static return_t default_return_value (void) { return true; }
static return_t no_dispatch_return_value (void) { return false; }
bool stop_sublookup_iteration (const return_t r) const { return !r; }
inline void init (hb_blob_t *b)
{
this->blob = hb_blob_reference (b);
this->writable = false;
}
inline void start_processing (void)
{
this->start = hb_blob_get_data (this->blob, nullptr);
this->end = this->start + this->blob->length;
assert (this->start <= this->end); /* Must not overflow. */
this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
(unsigned) HB_SANITIZE_MAX_OPS_MIN);
this->edit_count = 0;
this->debug_depth = 0;
DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
"start [%p..%p] (%lu bytes)",
this->start, this->end,
(unsigned long) (this->end - this->start));
}
inline void end_processing (void)
{
DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
"end [%p..%p] %u edit requests",
this->start, this->end, this->edit_count);
hb_blob_destroy (this->blob);
this->blob = nullptr;
this->start = this->end = nullptr;
}
inline bool check_range (const void *base, unsigned int len) const
{
const char *p = (const char *) base;
bool ok = this->max_ops-- > 0 &&
this->start <= p &&
p <= this->end &&
(unsigned int) (this->end - p) >= len;
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
p, p + len, len,
this->start, this->end,
ok ? "OK" : "OUT-OF-RANGE");
return likely (ok);
}
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
{
const char *p = (const char *) base;
bool overflows = hb_unsigned_mul_overflows (len, record_size);
unsigned int array_size = record_size * len;
bool ok = !overflows && this->check_range (base, array_size);
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
p, p + (record_size * len), record_size, len, (unsigned int) array_size,
this->start, this->end,
overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
return likely (ok);
}
template <typename Type>
inline bool check_struct (const Type *obj) const
{
return likely (this->check_range (obj, obj->min_size));
}
inline bool may_edit (const void *base, unsigned int len)
{
if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
return false;
const char *p = (const char *) base;
this->edit_count++;
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
this->edit_count,
p, p + len, len,
this->start, this->end,
this->writable ? "GRANTED" : "DENIED");
return this->writable;
}
template <typename Type, typename ValueType>
inline bool try_set (const Type *obj, const ValueType &v) {
if (this->may_edit (obj, obj->static_size)) {
const_cast<Type *> (obj)->set (v);
return true;
}
return false;
}
mutable unsigned int debug_depth;
const char *start, *end;
bool writable;
unsigned int edit_count;
mutable int max_ops;
hb_blob_t *blob;
unsigned int num_glyphs;
};
/* Template to sanitize an object. */
template <typename Type>
struct Sanitizer
{
inline Sanitizer (void) {}
inline hb_blob_t *sanitize (hb_blob_t *blob) {
bool sane;
/* TODO is_sane() stuff */
c->init (blob);
retry:
DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
c->start_processing ();
if (unlikely (!c->start)) {
c->end_processing ();
return blob;
}
Type *t = CastP<Type> (const_cast<char *> (c->start));
sane = t->sanitize (c);
if (sane) {
if (c->edit_count) {
DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
/* sanitize again to ensure no toe-stepping */
c->edit_count = 0;
sane = t->sanitize (c);
if (c->edit_count) {
DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
sane = false;
}
}
} else {
unsigned int edit_count = c->edit_count;
if (edit_count && !c->writable) {
c->start = hb_blob_get_data_writable (blob, nullptr);
c->end = c->start + blob->length;
if (c->start) {
c->writable = true;
/* ok, we made it writable by relocating. try again */
DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
goto retry;
}
}
}
c->end_processing ();
DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
if (sane)
{
blob->lock ();
return blob;
}
else
{
hb_blob_destroy (blob);
return hb_blob_get_empty ();
}
}
inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
private:
hb_sanitize_context_t c[1];
};
/*
* Serialize
*/
struct hb_serialize_context_t
{
inline hb_serialize_context_t (void *start_, unsigned int size)
{
this->start = (char *) start_;
this->end = this->start + size;
this->ran_out_of_room = false;
this->head = this->start;
this->debug_depth = 0;
}
template <typename Type>
inline Type *start_serialize (void)
{
DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
"start [%p..%p] (%lu bytes)",
this->start, this->end,
(unsigned long) (this->end - this->start));
return start_embed<Type> ();
}
inline void end_serialize (void)
{
DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
"end [%p..%p] serialized %d bytes; %s",
this->start, this->end,
(int) (this->head - this->start),
this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
}
template <typename Type>
inline Type *copy (void)
{
assert (!this->ran_out_of_room);
unsigned int len = this->head - this->start;
void *p = malloc (len);
if (p)
memcpy (p, this->start, len);
return reinterpret_cast<Type *> (p);
}
template <typename Type>
inline Type *allocate_size (unsigned int size)
{
if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
this->ran_out_of_room = true;
return nullptr;
}
memset (this->head, 0, size);
char *ret = this->head;
this->head += size;
return reinterpret_cast<Type *> (ret);
}
template <typename Type>
inline Type *allocate_min (void)
{
return this->allocate_size<Type> (Type::min_size);
}
template <typename Type>
inline Type *start_embed (void)
{
Type *ret = reinterpret_cast<Type *> (this->head);
return ret;
}
template <typename Type>
inline Type *embed (const Type &obj)
{
unsigned int size = obj.get_size ();
Type *ret = this->allocate_size<Type> (size);
if (unlikely (!ret)) return nullptr;
memcpy (ret, obj, size);
return ret;
}
template <typename Type>
inline Type *extend_min (Type &obj)
{
unsigned int size = obj.min_size;
assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
return reinterpret_cast<Type *> (&obj);
}
template <typename Type>
inline Type *extend (Type &obj)
{
unsigned int size = obj.get_size ();
assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
return reinterpret_cast<Type *> (&obj);
}
inline void truncate (void *new_head)
{
assert (this->start < new_head && new_head <= this->head);
this->head = (char *) new_head;
}
unsigned int debug_depth;
char *start, *end, *head;
bool ran_out_of_room;
};
template <typename Type>
struct Supplier
{
inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
{
head = array;
len = len_;
stride = stride_;
}
inline const Type operator [] (unsigned int i) const
{
if (unlikely (i >= len)) return Type ();
return * (const Type *) (const void *) ((const char *) head + stride * i);
}
inline Supplier<Type> & operator += (unsigned int count)
{
if (unlikely (count > len))
count = len;
len -= count;
head = (const Type *) (const void *) ((const char *) head + stride * count);
return *this;
}
private:
inline Supplier (const Supplier<Type> &); /* Disallow copy */
inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
unsigned int len;
unsigned int stride;
const Type *head;
};
/*
*
* The OpenType Font File: Data Types
@ -523,78 +51,6 @@ struct Supplier
* Int types
*/
template <typename Type, int Bytes> struct BEInt;
template <typename Type>
struct BEInt<Type, 1>
{
public:
inline void set (Type V)
{
v = V;
}
inline operator Type (void) const
{
return v;
}
private: uint8_t v;
};
template <typename Type>
struct BEInt<Type, 2>
{
public:
inline void set (Type V)
{
v[0] = (V >> 8) & 0xFF;
v[1] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[0] << 8)
+ (v[1] );
}
private: uint8_t v[2];
};
template <typename Type>
struct BEInt<Type, 3>
{
public:
inline void set (Type V)
{
v[0] = (V >> 16) & 0xFF;
v[1] = (V >> 8) & 0xFF;
v[2] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[0] << 16)
+ (v[1] << 8)
+ (v[2] );
}
private: uint8_t v[3];
};
template <typename Type>
struct BEInt<Type, 4>
{
public:
inline void set (Type V)
{
v[0] = (V >> 24) & 0xFF;
v[1] = (V >> 16) & 0xFF;
v[2] = (V >> 8) & 0xFF;
v[3] = (V ) & 0xFF;
}
inline operator Type (void) const
{
return (v[0] << 24)
+ (v[1] << 16)
+ (v[2] << 8)
+ (v[3] );
}
private: uint8_t v[4];
};
/* Integer types in big-endian order and no alignment requirement */
template <typename Type, unsigned int Size>
struct IntType
@ -684,7 +140,6 @@ struct Tag : HBUINT32
public:
DEFINE_SIZE_STATIC (4);
};
DEFINE_NULL_DATA (OT, Tag, " ");
/* Glyph index number, same as uint16 (length = 16 bits) */
typedef HBUINT16 GlyphID;
@ -696,7 +151,7 @@ typedef HBUINT16 NameID;
struct Index : HBUINT16 {
static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
};
DEFINE_NULL_DATA (OT, Index, "\xff\xff");
DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
/* Offset, Null offset = 0 */
template <typename Type>
@ -765,7 +220,6 @@ struct FixedVersion
};
/*
* Template subclasses of Offset that do the dereferencing.
* Use: (base+offset)
@ -831,7 +285,6 @@ static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset)
* Array Types
*/
/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
template <typename Type>
struct UnsizedArrayOf
@ -913,7 +366,6 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
}
};
/* An array with a number of elements. */
template <typename Type, typename LenType=HBUINT16>
struct ArrayOf
@ -1066,7 +518,6 @@ struct OffsetListOf : OffsetArrayOf<Type>
}
};
/* An array starting at second element. */
template <typename Type, typename LenType=HBUINT16>
struct HeadlessArrayOf
@ -1131,10 +582,7 @@ struct HeadlessArrayOf
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
/*
* An array with sorted elements. Supports binary searching.
*/
/* An array with sorted elements. Supports binary searching. */
template <typename Type, typename LenType=HBUINT16>
struct SortedArrayOf : ArrayOf<Type, LenType>
{
@ -1159,10 +607,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
}
};
/*
* Binary-search arrays
*/
/* Binary-search arrays */
struct BinSearchHeader
{
inline operator uint32_t (void) const { return len; }
@ -1198,101 +643,6 @@ template <typename Type>
struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
/* Lazy struct and blob loaders. */
/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
template <typename T>
struct hb_lazy_loader_t
{
inline void init (hb_face_t *face_)
{
face = face_;
instance = nullptr;
}
inline void fini (void)
{
if (instance && instance != &Null(T))
{
instance->fini();
free (instance);
}
}
inline const T* get (void) const
{
retry:
T *p = (T *) hb_atomic_ptr_get (&instance);
if (unlikely (!p))
{
p = (T *) calloc (1, sizeof (T));
if (unlikely (!p))
p = const_cast<T *> (&Null(T));
else
p->init (face);
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
{
if (p != &Null(T))
p->fini ();
goto retry;
}
}
return p;
}
inline const T* operator-> (void) const
{
return get ();
}
private:
hb_face_t *face;
T *instance;
};
/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
template <typename T>
struct hb_table_lazy_loader_t
{
inline void init (hb_face_t *face_)
{
face = face_;
blob = nullptr;
}
inline void fini (void)
{
hb_blob_destroy (blob);
}
inline const T* get (void) const
{
retry:
hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob);
if (unlikely (!blob_))
{
blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_))
{
hb_blob_destroy (blob_);
goto retry;
}
blob = blob_;
}
return blob_->as<T> ();
}
inline const T* operator-> (void) const
{
return get();
}
private:
hb_face_t *face;
mutable hb_blob_t *blob;
};
} /* namespace OT */

View File

@ -37,6 +37,9 @@
*/
#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
#ifndef HB_MAX_UNICODE_CODEPOINT_VALUE
#define HB_MAX_UNICODE_CODEPOINT_VALUE 0x10FFFF
#endif
namespace OT {
@ -437,8 +440,10 @@ struct CmapSubtableLongSegmented
{
for (unsigned int i = 0; i < this->groups.len; i++) {
hb_set_add_range (out,
this->groups[i].startCharCode,
this->groups[i].endCharCode);
MIN ((unsigned int) this->groups[i].startCharCode,
(unsigned int) HB_MAX_UNICODE_CODEPOINT_VALUE),
MIN ((unsigned int) this->groups[i].endCharCode,
(unsigned int) HB_MAX_UNICODE_CODEPOINT_VALUE));
}
}
@ -800,37 +805,37 @@ struct cmap
{
hb_serialize_context_t c (dest, dest_sz);
OT::cmap *cmap = c.start_serialize<OT::cmap> ();
if (unlikely (!c.extend_min (*cmap)))
cmap *table = c.start_serialize<cmap> ();
if (unlikely (!c.extend_min (*table)))
{
return false;
}
cmap->version.set (0);
table->version.set (0);
if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 3)))
if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3)))
return false;
// TODO(grieger): Convert the below to a for loop
// Format 4, Plat 0 Encoding Record
EncodingRecord &format4_plat0_rec = cmap->encodingRecord[0];
EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
format4_plat0_rec.platformID.set (0); // Unicode
format4_plat0_rec.encodingID.set (3);
// Format 4, Plat 3 Encoding Record
EncodingRecord &format4_plat3_rec = cmap->encodingRecord[1];
EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
format4_plat3_rec.platformID.set (3); // Windows
format4_plat3_rec.encodingID.set (1); // Unicode BMP
// Format 12 Encoding Record
EncodingRecord &format12_rec = cmap->encodingRecord[2];
EncodingRecord &format12_rec = table->encodingRecord[2];
format12_rec.platformID.set (3); // Windows
format12_rec.encodingID.set (10); // Unicode UCS-4
// Write out format 4 sub table
{
CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, cmap);
CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
format4_plat3_rec.subtable.set (format4_plat0_rec.subtable);
subtable.u.format.set (4);
@ -841,7 +846,7 @@ struct cmap
// Write out format 12 sub table.
{
CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap);
CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
subtable.u.format.set (12);
CmapSubtableFormat12 &format12 = subtable.u.format12;
@ -894,57 +899,57 @@ struct cmap
{
inline void init (hb_face_t *face)
{
this->blob = OT::Sanitizer<OT::cmap>().sanitize (face->reference_table (HB_OT_TAG_cmap));
const OT::cmap *cmap = this->blob->as<OT::cmap> ();
const OT::CmapSubtable *subtable = nullptr;
const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
this->blob = hb_sanitize_context_t().reference_table<cmap> (face);
const cmap *table = this->blob->as<cmap> ();
const CmapSubtable *subtable = nullptr;
const CmapSubtableFormat14 *subtable_uvs = nullptr;
bool symbol = false;
/* 32-bit subtables. */
if (!subtable) subtable = cmap->find_subtable (3, 10);
if (!subtable) subtable = cmap->find_subtable (0, 6);
if (!subtable) subtable = cmap->find_subtable (0, 4);
if (!subtable) subtable = table->find_subtable (3, 10);
if (!subtable) subtable = table->find_subtable (0, 6);
if (!subtable) subtable = table->find_subtable (0, 4);
/* 16-bit subtables. */
if (!subtable) subtable = cmap->find_subtable (3, 1);
if (!subtable) subtable = cmap->find_subtable (0, 3);
if (!subtable) subtable = cmap->find_subtable (0, 2);
if (!subtable) subtable = cmap->find_subtable (0, 1);
if (!subtable) subtable = cmap->find_subtable (0, 0);
if (!subtable) subtable = table->find_subtable (3, 1);
if (!subtable) subtable = table->find_subtable (0, 3);
if (!subtable) subtable = table->find_subtable (0, 2);
if (!subtable) subtable = table->find_subtable (0, 1);
if (!subtable) subtable = table->find_subtable (0, 0);
if (!subtable)
{
subtable = cmap->find_subtable (3, 0);
subtable = table->find_subtable (3, 0);
if (subtable) symbol = true;
}
/* Meh. */
if (!subtable) subtable = &Null(OT::CmapSubtable);
if (!subtable) subtable = &Null(CmapSubtable);
/* UVS subtable. */
if (!subtable_uvs)
{
const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
const CmapSubtable *st = table->find_subtable (0, 5);
if (st && st->u.format == 14)
subtable_uvs = &st->u.format14;
}
/* Meh. */
if (!subtable_uvs) subtable_uvs = &Null(OT::CmapSubtableFormat14);
if (!subtable_uvs) subtable_uvs = &Null(CmapSubtableFormat14);
this->uvs_table = subtable_uvs;
this->get_glyph_data = subtable;
if (unlikely (symbol))
{
this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
this->get_glyph_func = get_glyph_from_symbol<CmapSubtable>;
this->get_all_codepoints_func = null_get_all_codepoints_func;
} else {
switch (subtable->u.format) {
/* Accelerate format 4 and format 12. */
default:
this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
this->get_glyph_func = get_glyph_from<CmapSubtable>;
this->get_all_codepoints_func = null_get_all_codepoints_func;
break;
case 12:
this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
this->get_all_codepoints_func = get_all_codepoints_from<OT::CmapSubtableFormat12>;
this->get_glyph_func = get_glyph_from<CmapSubtableFormat12>;
this->get_all_codepoints_func = get_all_codepoints_from<CmapSubtableFormat12>;
break;
case 4:
{
@ -977,9 +982,9 @@ struct cmap
variation_selector,
glyph))
{
case OT::GLYPH_VARIANT_NOT_FOUND: return false;
case OT::GLYPH_VARIANT_FOUND: return true;
case OT::GLYPH_VARIANT_USE_DEFAULT: break;
case GLYPH_VARIANT_NOT_FOUND: return false;
case GLYPH_VARIANT_FOUND: return true;
case GLYPH_VARIANT_USE_DEFAULT: break;
}
return get_nominal_glyph (unicode, glyph);
@ -1046,9 +1051,9 @@ struct cmap
const void *get_glyph_data;
hb_cmap_get_all_codepoints_func_t get_all_codepoints_func;
OT::CmapSubtableFormat4::accelerator_t format4_accel;
CmapSubtableFormat4::accelerator_t format4_accel;
const OT::CmapSubtableFormat14 *uvs_table;
const CmapSubtableFormat14 *uvs_table;
hb_blob_t *blob;
};

View File

@ -394,8 +394,8 @@ struct CBDT
{
upem = hb_face_get_upem (face);
cblc_blob = Sanitizer<CBLC>().sanitize (face->reference_table (HB_OT_TAG_CBLC));
cbdt_blob = Sanitizer<CBDT>().sanitize (face->reference_table (HB_OT_TAG_CBDT));
cblc_blob = hb_sanitize_context_t().reference_table<CBLC> (face);
cbdt_blob = hb_sanitize_context_t().reference_table<CBDT> (face);
cbdt_len = hb_blob_get_length (cbdt_blob);
if (hb_blob_get_length (cblc_blob) == 0) {

View File

@ -68,7 +68,7 @@ struct SBIXStrike
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1));
imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
}
protected:
@ -96,14 +96,9 @@ struct sbix
{
inline void init (hb_face_t *face)
{
num_glyphs = hb_face_get_glyph_count (face);
OT::Sanitizer<OT::sbix> sanitizer;
sanitizer.set_num_glyphs (num_glyphs);
sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix));
sbix_blob = hb_sanitize_context_t().reference_table<sbix> (face);
sbix_len = hb_blob_get_length (sbix_blob);
sbix_table = sbix_blob->as<OT::sbix> ();
sbix_table = sbix_blob->as<sbix> ();
}
inline void fini (void)
@ -134,7 +129,6 @@ struct sbix
unsigned int sbix_len;
unsigned int num_glyphs;
};
protected:

View File

@ -96,11 +96,9 @@ struct SVG
{
inline void init (hb_face_t *face)
{
OT::Sanitizer<OT::SVG> sanitizer;
svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG));
svg_blob = hb_sanitize_context_t().reference_table<SVG> (face);
svg_len = hb_blob_get_length (svg_blob);
svg = svg_blob->as<OT::SVG> ();
svg = svg_blob->as<SVG> ();
}
inline void fini (void)

View File

@ -41,13 +41,39 @@
struct hb_ot_font_t
{
inline void init (hb_face_t *face)
{
cmap.init (face);
h_metrics.init (face);
v_metrics.init (face, h_metrics.ascender - h_metrics.descender); /* TODO Can we do this lazily? */
this->face = face;
glyf.init ();
cbdt.init ();
post.init ();
kern.init ();
}
inline void fini (void)
{
cmap.fini ();
h_metrics.fini ();
v_metrics.fini ();
glyf.fini ();
cbdt.fini ();
post.fini ();
kern.fini ();
}
OT::cmap::accelerator_t cmap;
OT::hmtx::accelerator_t h_metrics;
OT::vmtx::accelerator_t v_metrics;
OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
hb_object_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
hb_object_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
hb_object_lazy_loader_t<3, OT::post::accelerator_t> post;
hb_object_lazy_loader_t<4, OT::kern::accelerator_t> kern;
};
@ -59,13 +85,7 @@ _hb_ot_font_create (hb_face_t *face)
if (unlikely (!ot_font))
return nullptr;
ot_font->cmap.init (face);
ot_font->h_metrics.init (face);
ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
ot_font->glyf.init (face);
ot_font->cbdt.init (face);
ot_font->post.init (face);
ot_font->kern.init (face);
ot_font->init (face);
return ot_font;
}
@ -75,13 +95,7 @@ _hb_ot_font_destroy (void *data)
{
hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
ot_font->cmap.fini ();
ot_font->h_metrics.fini ();
ot_font->v_metrics.fini ();
ot_font->glyf.fini ();
ot_font->cbdt.fini ();
ot_font->post.fini ();
ot_font->kern.fini ();
ot_font->fini ();
free (ot_font);
}

View File

@ -103,14 +103,14 @@ struct glyf
static bool
_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
{
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
hb_blob_destroy (head_blob);
if (unlikely (!head_prime_blob))
return false;
OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
@ -236,20 +236,20 @@ struct glyf
{
memset (this, 0, sizeof (accelerator_t));
hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (face);
const head *head_table = head_blob->as<head> ();
if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
if (head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
{
/* head table is not present, or in an unknown format. Leave num_glyphs=0, that takes care of disabling us. */
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
hb_blob_destroy (head_blob);
return;
}
short_offset = 0 == head_table->indexToLocFormat;
hb_blob_destroy (head_blob);
loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
loca_blob = hb_sanitize_context_t().reference_table<loca> (face);
loca_table = loca_blob->as<loca> ();
glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
glyf_blob = hb_sanitize_context_t().reference_table<glyf> (face);
glyf_table = glyf_blob->as<glyf> ();
num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
@ -270,7 +270,7 @@ struct glyf
inline bool get_composite (hb_codepoint_t glyph,
CompositeGlyphHeader::Iterator *composite /* OUT */) const
{
if (this->glyf_table == &Null(glyf) || !num_glyphs)
if (unlikely (!num_glyphs))
return false;
unsigned int start_offset, end_offset;

View File

@ -141,8 +141,8 @@ struct head
* -1: Only strongly right to left;
* -2: Like -1 but also contains neutrals. */
public:
HBINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */
HBINT16 glyphDataFormat; /* 0 for current format. */
HBUINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */
HBUINT16 glyphDataFormat; /* 0 for current format. */
DEFINE_SIZE_STATIC (54);
};

View File

@ -69,7 +69,7 @@ struct hmtxvmtx
inline bool subset_update_header (hb_subset_plan_t *plan,
unsigned int num_hmetrics) const
{
hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
hb_blob_t *src_blob = hb_sanitize_context_t().reference_table<H> (plan->source, H::tableTag);
hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
hb_blob_destroy (src_blob);
@ -195,7 +195,7 @@ struct hmtxvmtx
bool got_font_extents = false;
if (T::os2Tag)
{
hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table<os2> (face);
const os2 *os2_table = os2_blob->as<os2> ();
#define USE_TYPO_METRICS (1u<<7)
if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
@ -208,7 +208,7 @@ struct hmtxvmtx
hb_blob_destroy (os2_blob);
}
hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
const H *_hea_table = _hea_blob->as<H> ();
num_advances = _hea_table->numberOfLongMetrics;
if (!got_font_extents)
@ -222,7 +222,7 @@ struct hmtxvmtx
has_font_extents = got_font_extents;
blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
blob = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
/* Cap num_metrics() and num_advances() based on table length. */
unsigned int len = hb_blob_get_length (blob);
@ -240,7 +240,7 @@ struct hmtxvmtx
}
table = blob->as<hmtxvmtx> ();
var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
var_blob = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
var_table = var_blob->as<HVARVVAR> ();
}

View File

@ -362,7 +362,7 @@ struct kern
{
inline void init (hb_face_t *face)
{
blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
blob = hb_sanitize_context_t().reference_table<kern> (face);
table = blob->as<kern> ();
table_length = blob->length;
}

View File

@ -33,13 +33,16 @@
namespace OT {
#define NOT_INDEXED ((unsigned int) -1)
/*
* BASE -- Baseline
* https://docs.microsoft.com/en-us/typography/opentype/spec/base
*/
/* XXX Review this. */
#define NOT_INDEXED ((unsigned int) -1)
struct BaseCoordFormat1
{
inline int get_coord (void) const { return coordinate; }
@ -52,7 +55,7 @@ struct BaseCoordFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
HBINT16 coordinate; /* X or Y value, in design units */
FWORD coordinate; /* X or Y value, in design units */
public:
DEFINE_SIZE_STATIC (4);
};
@ -73,7 +76,7 @@ struct BaseCoordFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
HBINT16 coordinate; /* X or Y value, in design units */
FWORD coordinate; /* X or Y value, in design units */
GlyphID referenceGlyph; /* Glyph ID of control glyph */
HBUINT16 coordPoint; /* Index of contour point on the
* reference glyph */
@ -97,7 +100,7 @@ struct BaseCoordFormat3
protected:
HBUINT16 format; /* Format identifier--format = 3 */
HBINT16 coordinate; /* X or Y value, in design units */
FWORD coordinate; /* X or Y value, in design units */
OffsetTo<Device> deviceTable; /* Offset to Device table for X or
* Y value, from beginning of
* BaseCoord table (may be NULL). */
@ -109,6 +112,7 @@ struct BaseCoord
{
inline int get_coord (void) const
{
/* XXX wire up direction and font. */
switch (u.format) {
case 1: return u.format1.get_coord ();
case 2: return u.format2.get_coord ();
@ -142,14 +146,10 @@ struct BaseCoord
struct FeatMinMaxRecord
{
inline int get_min_value (void) const
{ return (this+minCoord).get_coord(); }
inline int get_min_value (void) const { return (this+minCoord).get_coord(); }
inline int get_max_value (void) const { return (this+maxCoord).get_coord(); }
inline int get_max_value (void) const
{ return (this+maxCoord).get_coord(); }
inline const Tag &get_tag () const
{ return tag; }
inline const Tag& get_tag () const { return tag; }
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
@ -181,7 +181,7 @@ struct MinMax
unsigned int count = featMinMaxRecords.len;
for (unsigned int i = 0; i < count; i++)
{
Tag tag = featMinMaxRecords[i].get_tag();
Tag tag = featMinMaxRecords[i].get_tag ();
int cmp = tag.cmp(featureTableTag);
if (cmp == 0) return i;
if (cmp > 0) return NOT_INDEXED;
@ -233,13 +233,13 @@ struct BaseLangSysRecord
{ return baseLangSysTag; }
inline unsigned int get_feature_tag_index (Tag featureTableTag) const
{ return (this+minMax).get_feature_tag_index(featureTableTag); }
{ return (this+minMax).get_feature_tag_index( featureTableTag); }
inline int get_min_value (unsigned int featureTableTagIndex) const
{ return (this+minMax).get_min_value(featureTableTagIndex); }
{ return (this+minMax).get_min_value( featureTableTagIndex); }
inline int get_max_value (unsigned int featureTableTagIndex) const
{ return (this+minMax).get_max_value(featureTableTagIndex); }
{ return (this+minMax).get_max_value (featureTableTagIndex); }
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
@ -263,34 +263,34 @@ struct BaseValues
inline int get_base_coord (unsigned int baselineTagIndex) const
{
return (this+baseCoords[baselineTagIndex]).get_coord();
return (this+baseCoords[baselineTagIndex]).get_coord ();
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
defaultIndex <= baseCoordCount &&
baseCoords.sanitize (c, this));
baseCoords.sanitize (c, this));
}
protected:
Index defaultIndex;
HBUINT16 baseCoordCount;
OffsetArrayOf<BaseCoord> baseCoords;
public:
DEFINE_SIZE_ARRAY (6, baseCoords);
DEFINE_SIZE_ARRAY (4, baseCoords);
};
struct BaseScript {
inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
{
/* XXX bsearch */
Tag tag;
int cmp;
for (unsigned int i = 0; i < baseLangSysCount; i++) {
tag = baseLangSysRecords[i].get_tag();
unsigned int count = baseLangSysRecords.len;
for (unsigned int i = 0; i < count; i++)
{
tag = baseLangSysRecords[i].get_tag ();
// taking advantage of alphabetical order
cmp = tag.cmp(baseLangSysTag);
if (cmp == 0) return i;
@ -301,51 +301,50 @@ struct BaseScript {
inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
{
if (baseLangSysIndex == NOT_INDEXED) {
if (baseLangSysIndex == NOT_INDEXED)
{
if (unlikely(defaultMinMax)) return NOT_INDEXED;
return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
return (this+defaultMinMax).get_feature_tag_index (featureTableTag);
}
if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index (featureTableTag);
}
inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
if (baseLangSysIndex == NOT_INDEXED)
return (this+defaultMinMax).get_min_value(featureTableTagIndex);
return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
return (this+defaultMinMax).get_min_value (featureTableTagIndex);
return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
}
inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
if (baseLangSysIndex == NOT_INDEXED)
return (this+defaultMinMax).get_min_value(featureTableTagIndex);
return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
return (this+defaultMinMax).get_min_value (featureTableTagIndex);
return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
}
inline unsigned int get_default_base_tag_index (void) const
{ return (this+baseValues).get_default_base_tag_index(); }
{ return (this+baseValues).get_default_base_tag_index (); }
inline int get_base_coord (unsigned int baselineTagIndex) const
{ return (this+baseValues).get_base_coord(baselineTagIndex); }
{ return (this+baseValues).get_base_coord (baselineTagIndex); }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
baseValues.sanitize (c, this) &&
defaultMinMax.sanitize (c, this) &&
baseLangSysRecords.sanitize (c, this));
baseValues.sanitize (c, this) &&
defaultMinMax.sanitize (c, this) &&
baseLangSysRecords.sanitize (c, this));
}
protected:
OffsetTo<BaseValues> baseValues;
OffsetTo<MinMax> defaultMinMax;
HBUINT16 baseLangSysCount;
ArrayOf<BaseLangSysRecord> baseLangSysRecords;
OffsetTo<BaseValues> baseValues;
OffsetTo<MinMax> defaultMinMax;
ArrayOf<BaseLangSysRecord> baseLangSysRecords;
public:
DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
};
@ -355,29 +354,28 @@ struct BaseScriptRecord {
{ return baseScriptTag; }
inline unsigned int get_default_base_tag_index(void) const
{ return (this+baseScript).get_default_base_tag_index(); }
{ return (this+baseScript).get_default_base_tag_index (); }
inline int get_base_coord(unsigned int baselineTagIndex) const
{ return (this+baseScript).get_base_coord(baselineTagIndex); }
{ return (this+baseScript).get_base_coord (baselineTagIndex); }
inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
{ return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
{ return (this+baseScript).get_lang_tag_index (baseLangSysTag); }
inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
{ return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
{ return (this+baseScript).get_feature_tag_index (baseLangSysIndex, featureTableTag); }
inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{ return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
{ return (this+baseScript).get_max_value (baseLangSysIndex, featureTableTagIndex); }
inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{ return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
{ return (this+baseScript).get_min_value (baseLangSysIndex, featureTableTagIndex); }
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
baseScript != Null(OffsetTo<BaseScript>) &&
baseScript.sanitize (c, base));
baseScript.sanitize (c, base));
}
protected:
@ -392,7 +390,9 @@ struct BaseScriptList {
inline unsigned int get_base_script_index (Tag baseScriptTag) const
{
for (unsigned int i = 0; i < baseScriptCount; i++)
/* XXX bsearch? */
unsigned int count = baseScriptRecords.len;
for (unsigned int i = 0; i < count; i++)
if (baseScriptRecords[i].get_tag() == baseScriptTag)
return i;
return NOT_INDEXED;
@ -400,7 +400,6 @@ struct BaseScriptList {
inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
{
if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
}
@ -411,13 +410,11 @@ struct BaseScriptList {
inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
}
inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
}
@ -435,24 +432,23 @@ struct BaseScriptList {
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
baseScriptRecords.sanitize (c, this));
baseScriptRecords.sanitize (c, this));
}
protected:
HBUINT16 baseScriptCount;
ArrayOf<BaseScriptRecord> baseScriptRecords;
ArrayOf<BaseScriptRecord> baseScriptRecords;
public:
DEFINE_SIZE_ARRAY (4, baseScriptRecords);
DEFINE_SIZE_ARRAY (2, baseScriptRecords);
};
struct BaseTagList
{
inline unsigned int get_tag_index(Tag baselineTag) const
inline unsigned int get_tag_index (Tag baselineTag) const
{
for (unsigned int i = 0; i < baseTagCount; i++)
/* TODO bsearch? */
unsigned int count = baselineTags.len;
for (unsigned int i = 0; i < count; i++)
if (baselineTags[i] == baselineTag)
return i;
return NOT_INDEXED;
@ -465,42 +461,37 @@ struct BaseTagList
}
protected:
HBUINT16 baseTagCount;
SortedArrayOf<Tag> baselineTags;
public:
DEFINE_SIZE_ARRAY (4, baselineTags);
DEFINE_SIZE_ARRAY (2, baselineTags);
};
struct Axis
{
inline unsigned int get_base_tag_index(Tag baselineTag) const
inline unsigned int get_base_tag_index (Tag baselineTag) const
{
if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
return (this+baseTagList).get_tag_index(baselineTag);
}
inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
{
if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
}
inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
inline int get_base_coord (unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
{
return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
}
inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
}
inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
}
@ -518,13 +509,13 @@ struct Axis
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
baseTagList.sanitize (c, this) &&
baseScriptList.sanitize (c, this));
baseTagList.sanitize (c, this) &&
baseScriptList.sanitize (c, this));
}
protected:
OffsetTo<BaseTagList> baseTagList;
OffsetTo<BaseScriptList> baseScriptList;
OffsetTo<BaseTagList> baseTagList;
OffsetTo<BaseScriptList> baseScriptList;
public:
DEFINE_SIZE_STATIC (4);
@ -534,96 +525,78 @@ struct BASE
{
static const hb_tag_t tableTag = HB_OT_TAG_BASE;
inline bool has_vert_axis(void)
{ return vertAxis != Null(OffsetTo<Axis>); }
inline bool has_v_axis(void) { return vAxis != 0; }
inline bool has_horiz_axis(void)
{ return horizAxis != Null(OffsetTo<Axis>); }
inline bool has_h_axis(void) { return hAxis != 0; }
// horizontal axis base coords:
inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
inline unsigned int get_h_base_tag_index (Tag baselineTag) const
{
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+horizAxis).get_base_tag_index(baselineTag);
return (this+hAxis).get_base_tag_index(baselineTag);
}
inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
inline unsigned int get_h_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
{
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
return (this+hAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
}
inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
inline int get_h_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
{
return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
return (this+hAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
}
// vertical axis base coords:
inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
inline unsigned int get_v_base_tag_index(Tag baselineTag) const
{
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+vertAxis).get_base_tag_index(baselineTag);
return (this+vAxis).get_base_tag_index(baselineTag);
}
inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
inline unsigned int get_v_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
{
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
return (this+vAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
}
inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
inline int get_v_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
{
return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
return (this+vAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
}
// horizontal axis min/max coords:
inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
inline unsigned int get_h_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
return (this+hAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
}
inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
inline unsigned int get_h_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
return (this+hAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
}
inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
inline int get_h_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
return (this+hAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
inline int get_h_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
return (this+hAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
// vertical axis min/max coords:
inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
inline unsigned int get_v_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
{
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
return (this+vAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
}
inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
inline unsigned int get_v_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
{
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
return (this+vAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
}
inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
inline int get_v_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
return (this+vAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
inline int get_v_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
{
return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
return (this+vAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@ -631,15 +604,15 @@ struct BASE
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
likely (version.major == 1) &&
horizAxis.sanitize (c, this) &&
vertAxis.sanitize (c, this) &&
hAxis.sanitize (c, this) &&
vAxis.sanitize (c, this) &&
(version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
}
protected:
FixedVersion<> version;
OffsetTo<Axis> horizAxis;
OffsetTo<Axis> vertAxis;
OffsetTo<Axis> hAxis;
OffsetTo<Axis> vAxis;
LOffsetTo<VariationStore>
varStore; /* Offset to the table of Item Variation
* Store--from beginning of BASE

View File

@ -41,6 +41,15 @@
#ifndef HB_MAX_CONTEXT_LENGTH
#define HB_MAX_CONTEXT_LENGTH 64
#endif
#ifndef HB_CLOSURE_MAX_STAGES
/*
* The maximum number of times a lookup can be applied during shaping.
* Used to limit the number of iterations of the closure algorithm.
* This must be larger than the number of times add_pause() is
* called in a collect_features call of any shaper.
*/
#define HB_CLOSURE_MAX_STAGES 32
#endif
namespace OT {
@ -164,7 +173,7 @@ struct RangeRecord
public:
DEFINE_SIZE_STATIC (6);
};
DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
struct IndexArray : ArrayOf<Index>
@ -181,6 +190,11 @@ struct IndexArray : ArrayOf<Index>
}
return this->len;
}
inline void add_indexes_to (hb_set_t* output /* OUT */) const
{
output->add_array (arrayZ, len);
}
};
@ -199,6 +213,8 @@ struct LangSys
unsigned int *feature_count /* IN/OUT */,
unsigned int *feature_indexes /* OUT */) const
{ return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
inline void add_feature_indexes_to (hb_set_t *feature_indexes) const
{ featureIndex.add_indexes_to (feature_indexes); }
inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
inline unsigned int get_required_feature_index (void) const
@ -224,8 +240,7 @@ struct LangSys
public:
DEFINE_SIZE_ARRAY (6, featureIndex);
};
DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
struct Script
{
@ -540,9 +555,6 @@ struct Feature
c->try_set (&featureParams, new_offset) &&
!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
return_trace (false);
if (c->edit_count > 1)
c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
}
return_trace (true);
@ -597,6 +609,14 @@ struct Lookup
inline OffsetArrayOf<SubTableType>& get_subtables (void)
{ return CastR<OffsetArrayOf<SubTableType> > (subTable); }
inline unsigned int get_size (void) const
{
const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
return (const char *) &markFilteringSet - (const char *) this;
}
inline unsigned int get_type (void) const { return lookupType; }
/* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
@ -639,6 +659,7 @@ struct Lookup
if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
{
if (unlikely (!c->extend (*this))) return_trace (false);
HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
markFilteringSet.set (lookup_props >> 16);
}

View File

@ -349,6 +349,7 @@ struct GDEF
ComponentGlyph = 4
};
inline bool has_data (void) const { return version.to_int () != 0; }
inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
{ return (this+glyphClassDef).get_class (glyph); }

View File

@ -1628,14 +1628,14 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
template <typename context_t>
/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS);
const PosLookup &l = gpos.get_lookup (lookup_index);
return l.dispatch (c);
}
/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS);
const PosLookup &l = gpos.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
unsigned int saved_lookup_index = c->lookup_index;

View File

@ -47,7 +47,7 @@ struct SingleSubstFormat1
* https://github.com/harfbuzz/harfbuzz/issues/363 */
hb_codepoint_t glyph_id = iter.get_glyph ();
if (c->glyphs->has (glyph_id))
c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
}
}
@ -132,7 +132,7 @@ struct SingleSubstFormat2
if (unlikely (iter.get_coverage () >= count))
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
c->glyphs->add (substitute[iter.get_coverage ()]);
c->out->add (substitute[iter.get_coverage ()]);
}
}
@ -263,7 +263,7 @@ struct Sequence
TRACE_CLOSURE (this);
unsigned int count = substitute.len;
for (unsigned int i = 0; i < count; i++)
c->glyphs->add (substitute[i]);
c->out->add (substitute[i]);
}
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
@ -464,7 +464,7 @@ struct AlternateSubstFormat1
const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
unsigned int count = alt_set.len;
for (unsigned int i = 0; i < count; i++)
c->glyphs->add (alt_set[i]);
c->out->add (alt_set[i]);
}
}
}
@ -605,7 +605,7 @@ struct Ligature
for (unsigned int i = 1; i < count; i++)
if (!c->glyphs->has (component[i]))
return;
c->glyphs->add (ligGlyph);
c->out->add (ligGlyph);
}
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
@ -957,7 +957,7 @@ struct ReverseChainSingleSubstFormat1
if (unlikely (iter.get_coverage () >= count))
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
if (c->glyphs->has (iter.get_glyph ()))
c->glyphs->add (substitute[iter.get_coverage ()]);
c->out->add (substitute[iter.get_coverage ()]);
}
}
@ -1163,7 +1163,12 @@ struct SubstLookup : Lookup
return_trace (HB_VOID);
c->set_recurse_func (dispatch_closure_recurse_func);
return_trace (dispatch (c));
hb_closure_context_t::return_t ret = dispatch (c);
c->flush ();
return_trace (ret);
}
inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
@ -1265,7 +1270,12 @@ struct SubstLookup : Lookup
{
if (!c->should_visit_lookup (lookup_index))
return HB_VOID;
return dispatch_recurse_func (c, lookup_index);
hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
c->flush ();
return ret;
}
template <typename context_t>
@ -1325,7 +1335,7 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
{
_hb_buffer_assert_gsubgpos_vars (buffer);
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->table.GDEF;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
{
@ -1349,14 +1359,14 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
template <typename context_t>
/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB);
const SubstLookup &l = gsub.get_lookup (lookup_index);
return l.dispatch (c);
}
/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB);
const SubstLookup &l = gsub.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
unsigned int saved_lookup_index = c->lookup_index;

View File

@ -69,12 +69,13 @@ struct hb_closure_context_t :
bool is_lookup_done (unsigned int lookup_index)
{
// Have we visited this lookup with the current set of glyphs?
/* Have we visited this lookup with the current set of glyphs? */
return done_lookups->get (lookup_index) == glyphs->get_population ();
}
hb_face_t *face;
hb_set_t *glyphs;
hb_auto_t<hb_set_t> out[1];
recurse_func_t recurse_func;
unsigned int nesting_level_left;
unsigned int debug_depth;
@ -90,8 +91,19 @@ struct hb_closure_context_t :
debug_depth (0),
done_lookups (done_lookups_) {}
~hb_closure_context_t (void)
{
flush ();
}
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
void flush (void)
{
hb_set_union (glyphs, out);
hb_set_clear (out);
}
private:
hb_map_t *done_lookups;
};
@ -468,7 +480,7 @@ struct hb_ot_apply_context_t :
iter_input (), iter_context (),
font (font_), face (font->face), buffer (buffer_),
recurse_func (nullptr),
gdef (*hb_ot_layout_from_face (face)->gdef),
gdef (*hb_ot_layout_from_face (face)->table.GDEF),
var_store (gdef.get_var_store ()),
direction (buffer_->props.direction),
lookup_mask (1),
@ -2308,6 +2320,7 @@ struct Extension
struct GSUBGPOS
{
inline bool has_data (void) const { return version.to_int () != 0; }
inline unsigned int get_script_count (void) const
{ return (this+scriptList).len; }
inline const Tag& get_script_tag (unsigned int i) const

View File

@ -121,25 +121,6 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font,
* hb_ot_layout_t
*/
namespace OT {
struct BASE;
struct COLR;
struct CPAL;
struct GDEF;
struct GSUB;
struct GPOS;
struct MATH;
struct fvar;
struct avar;
}
namespace AAT {
struct ankr;
struct kerx;
struct morx;
struct trak;
}
struct hb_ot_layout_lookup_accelerator_t
{
template <typename TLookup>
@ -161,27 +142,73 @@ struct hb_ot_layout_lookup_accelerator_t
hb_set_digest_t digest;
};
/* Most of these tables are NOT needed for shaping. But we need to hook them *somewhere*.
* This is as good as any place. */
#define HB_OT_LAYOUT_TABLES \
/* OpenType shaping. */ \
HB_OT_LAYOUT_TABLE(OT, GDEF) \
HB_OT_LAYOUT_TABLE(OT, GSUB) \
HB_OT_LAYOUT_TABLE(OT, GPOS) \
HB_OT_LAYOUT_TABLE(OT, JSTF) \
HB_OT_LAYOUT_TABLE(OT, BASE) \
/* AAT shaping. */ \
HB_OT_LAYOUT_TABLE(AAT, morx) \
HB_OT_LAYOUT_TABLE(AAT, kerx) \
HB_OT_LAYOUT_TABLE(AAT, ankr) \
HB_OT_LAYOUT_TABLE(AAT, trak) \
/* OpenType variations. */ \
HB_OT_LAYOUT_TABLE(OT, fvar) \
HB_OT_LAYOUT_TABLE(OT, avar) \
HB_OT_LAYOUT_TABLE(OT, MVAR) \
/* OpenType color. */ \
HB_OT_LAYOUT_TABLE(OT, COLR) \
HB_OT_LAYOUT_TABLE(OT, CPAL) \
HB_OT_LAYOUT_TABLE(OT, CBDT) \
HB_OT_LAYOUT_TABLE(OT, CBLC) \
HB_OT_LAYOUT_TABLE(OT, sbix) \
HB_OT_LAYOUT_TABLE(OT, svg) \
/* OpenType math. */ \
HB_OT_LAYOUT_TABLE(OT, MATH) \
/* OpenType fundamentals. */ \
HB_OT_LAYOUT_TABLE(OT, post) \
/* */
/* Declare tables. */
#define HB_OT_LAYOUT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
HB_OT_LAYOUT_TABLES
#undef HB_OT_LAYOUT_TABLE
struct hb_ot_layout_t
{
hb_blob_t *gdef_blob;
hb_blob_t *gsub_blob;
hb_blob_t *gpos_blob;
const struct OT::GDEF *gdef;
const struct OT::GSUB *gsub;
const struct OT::GPOS *gpos;
/* TODO Move the following out of this struct. */
OT::hb_table_lazy_loader_t<struct OT::BASE> base;
OT::hb_table_lazy_loader_t<struct OT::MATH> math;
OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
OT::hb_table_lazy_loader_t<struct OT::avar> avar;
unsigned int gsub_lookup_count;
unsigned int gpos_lookup_count;
hb_ot_layout_lookup_accelerator_t *gsub_accels;
hb_ot_layout_lookup_accelerator_t *gpos_accels;
/* Various non-shaping tables. */
struct tables_t
{
HB_INTERNAL void init0 (hb_face_t *face);
HB_INTERNAL void fini (void);
#define HB_OT_LAYOUT_TABLE_ORDER(Namespace, Type) \
HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
enum order_t
{
ORDER_ZERO,
#define HB_OT_LAYOUT_TABLE(Namespace, Type) \
HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type),
HB_OT_LAYOUT_TABLES
#undef HB_OT_LAYOUT_TABLE
};
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
#define HB_OT_LAYOUT_TABLE(Namespace, Type) \
hb_table_lazy_loader_t<HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type), struct Namespace::Type> Type;
HB_OT_LAYOUT_TABLES
#undef HB_OT_LAYOUT_TABLE
} table;
};

View File

@ -31,6 +31,7 @@
#include "hb-open-type-private.hh"
#include "hb-ot-layout-private.hh"
#include "hb-ot-map-private.hh"
#include "hb-map-private.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
@ -44,9 +45,124 @@
#include "hb-ot-color-sbix-table.hh"
#include "hb-ot-color-svg-table.hh"
#include "hb-ot-name-table.hh"
#include "hb-map-private.hh"
static bool
_hb_ot_blacklist_gdef (unsigned int gdef_len,
unsigned int gsub_len,
unsigned int gpos_len)
{
/* The ugly business of blacklisting individual fonts' tables happen here!
* See this thread for why we finally had to bend in and do this:
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
*
* In certain versions of Times New Roman Italic and Bold Italic,
* ASCII double quotation mark U+0022 has wrong glyph class 3 (mark)
* in GDEF. Many versions of Tahoma have bad GDEF tables that
* incorrectly classify some spacing marks such as certain IPA
* symbols as glyph class 3. So do older versions of Microsoft
* Himalaya, and the version of Cantarell shipped by Ubuntu 16.04.
*
* Nuke the GDEF tables of to avoid unwanted width-zeroing.
*
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
*/
#define ENCODE(x,y,z) ((int64_t) (x) << 32 | (int64_t) (y) << 16 | (z))
switch ENCODE(gdef_len, gsub_len, gpos_len)
{
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
case ENCODE (442, 2874, 42038):
/* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
case ENCODE (430, 2874, 40662):
/* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
case ENCODE (442, 2874, 39116):
/* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
case ENCODE (430, 2874, 39374):
/* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
case ENCODE (490, 3046, 41638):
/* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
case ENCODE (478, 3046, 41902):
/* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
case ENCODE (898, 12554, 46470):
/* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */
case ENCODE (910, 12566, 47732):
/* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */
case ENCODE (928, 23298, 59332):
/* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
case ENCODE (940, 23310, 60732):
/* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
case ENCODE (964, 23836, 60072):
/* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
case ENCODE (976, 23832, 61456):
/* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
case ENCODE (994, 24474, 60336):
/* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
case ENCODE (1006, 24470, 61740):
/* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
case ENCODE (1006, 24576, 61346):
/* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
case ENCODE (1018, 24572, 62828):
/* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */
case ENCODE (1006, 24576, 61352):
/* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */
case ENCODE (1018, 24572, 62834):
/* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */
case ENCODE (832, 7324, 47162):
/* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */
case ENCODE (844, 7302, 45474):
/* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */
case ENCODE (180, 13054, 7254):
/* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */
case ENCODE (192, 12638, 7254):
/* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */
case ENCODE (192, 12690, 7254):
/* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
/* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
case ENCODE (188, 248, 3852):
/* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
/* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
case ENCODE (188, 264, 3426):
/* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
case ENCODE (1058, 47032, 11818):
/* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
case ENCODE (1046, 47030, 12600):
/* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
case ENCODE (1058, 71796, 16770):
/* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
case ENCODE (1046, 71790, 17862):
/* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
case ENCODE (1046, 71788, 17112):
/* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
case ENCODE (1058, 71794, 17514):
/* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
case ENCODE (1330, 109904, 57938):
/* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
case ENCODE (1330, 109904, 58972):
/* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf
* "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
case ENCODE (1004, 59092, 14836):
return true;
#undef ENCODE
}
return false;
}
void hb_ot_layout_t::tables_t::init0 (hb_face_t *face)
{
this->face = face;
#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.init0 ();
HB_OT_LAYOUT_TABLES
#undef HB_OT_LAYOUT_TABLE
}
void hb_ot_layout_t::tables_t::fini (void)
{
#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.fini ();
HB_OT_LAYOUT_TABLES
#undef HB_OT_LAYOUT_TABLE
}
hb_ot_layout_t *
_hb_ot_layout_create (hb_face_t *face)
{
@ -54,143 +170,33 @@ _hb_ot_layout_create (hb_face_t *face)
if (unlikely (!layout))
return nullptr;
layout->gdef_blob = OT::Sanitizer<OT::GDEF>().sanitize (face->reference_table (HB_OT_TAG_GDEF));
layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
layout->table.init0 (face);
layout->gsub_blob = OT::Sanitizer<OT::GSUB>().sanitize (face->reference_table (HB_OT_TAG_GSUB));
layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
const OT::GSUB &gsub = *layout->table.GSUB;
const OT::GPOS &gpos = *layout->table.GPOS;
layout->gpos_blob = OT::Sanitizer<OT::GPOS>().sanitize (face->reference_table (HB_OT_TAG_GPOS));
layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
if (unlikely (_hb_ot_blacklist_gdef (layout->table.GDEF.get_blob ()->length,
layout->table.GSUB.get_blob ()->length,
layout->table.GPOS.get_blob ()->length)))
layout->table.GDEF.set_stored (hb_blob_get_empty ());
layout->math.init (face);
layout->fvar.init (face);
layout->avar.init (face);
unsigned int gsub_lookup_count = layout->gsub_lookup_count = gsub.get_lookup_count ();
unsigned int gpos_lookup_count = layout->gpos_lookup_count = gpos.get_lookup_count ();
{
/*
* The ugly business of blacklisting individual fonts' tables happen here!
* See this thread for why we finally had to bend in and do this:
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
*/
unsigned int gdef_len = layout->gdef_blob->length;
unsigned int gsub_len = layout->gsub_blob->length;
unsigned int gpos_len = layout->gpos_blob->length;
if (0
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
|| (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
/* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
|| (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
/* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
|| (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
/* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
|| (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
/* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
|| (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
/* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
|| (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
)
{
/* In certain versions of Times New Roman Italic and Bold Italic,
* ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
* glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width
* double-quote. See:
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
*/
if (3 == layout->gdef->get_glyph_class (5))
layout->gdef = &Null(OT::GDEF);
}
else if (0
/* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
|| (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
/* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */
|| (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
/* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */
|| (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
/* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
|| (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
/* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|| (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
/* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|| (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
/* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
|| (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
/* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
|| (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
/* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|| (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
/* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|| (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
/* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */
|| (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
/* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */
|| (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len)
/* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */
|| (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
/* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */
|| (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
/* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */
|| (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len)
/* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */
|| (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
/* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */
|| (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
/* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
/* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
|| (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
/* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
/* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
|| (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
/* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
|| (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
/* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
|| (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
/* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
|| (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
/* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
|| (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
/* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
|| (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
/* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
|| (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
/* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
|| (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
/* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
|| (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
/* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf
* "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
|| (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
)
{
/* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
* such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
* and the version of Cantarell shipped by Ubuntu 16.04.
* Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
*/
layout->gdef = &Null(OT::GDEF);
}
}
layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gsub_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gpos_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
(layout->gpos_lookup_count && !layout->gpos_accels)))
if (unlikely ((gsub_lookup_count && !layout->gsub_accels) ||
(gpos_lookup_count && !layout->gpos_accels)))
{
_hb_ot_layout_destroy (layout);
return nullptr;
}
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
for (unsigned int i = 0; i < gsub_lookup_count; i++)
layout->gsub_accels[i].init (gsub.get_lookup (i));
for (unsigned int i = 0; i < gpos_lookup_count; i++)
layout->gpos_accels[i].init (gpos.get_lookup (i));
return layout;
}
@ -208,13 +214,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
free (layout->gsub_accels);
free (layout->gpos_accels);
hb_blob_destroy (layout->gdef_blob);
hb_blob_destroy (layout->gsub_blob);
hb_blob_destroy (layout->gpos_blob);
layout->math.fini ();
layout->fvar.fini ();
layout->avar.fini ();
layout->table.fini ();
free (layout);
}
@ -231,19 +231,19 @@ static inline const OT::GDEF&
_get_gdef (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
return *hb_ot_layout_from_face (face)->gdef;
return *hb_ot_layout_from_face (face)->table.GDEF;
}
static inline const OT::GSUB&
_get_gsub (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB);
return *hb_ot_layout_from_face (face)->gsub;
return *hb_ot_layout_from_face (face)->table.GSUB;
}
static inline const OT::GPOS&
_get_gpos (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS);
return *hb_ot_layout_from_face (face)->gpos;
return *hb_ot_layout_from_face (face)->table.GPOS;
}
/*
@ -518,6 +518,19 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
return l.has_required_feature ();
}
static void
_hb_ot_layout_language_add_feature_indexes_to (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
hb_set_t *feature_indexes /* OUT */)
{
const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
l.add_feature_indexes_to (feature_indexes);
}
unsigned int
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
hb_tag_t table_tag,
@ -656,12 +669,12 @@ _hb_ot_layout_collect_lookups_lookups (hb_face_t *face,
}
static void
_hb_ot_layout_collect_lookups_features (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
const hb_tag_t *features,
hb_set_t *lookup_indexes /* OUT */)
_hb_ot_layout_collect_features_features (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
const hb_tag_t *features,
hb_set_t *feature_indexes /* OUT */)
{
if (!features)
{
@ -672,33 +685,14 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face,
language_index,
&required_feature_index,
nullptr))
_hb_ot_layout_collect_lookups_lookups (face,
table_tag,
required_feature_index,
lookup_indexes);
feature_indexes->add (required_feature_index);
/* All features */
unsigned int feature_indices[32];
unsigned int offset, len;
offset = 0;
do {
len = ARRAY_LENGTH (feature_indices);
hb_ot_layout_language_get_feature_indexes (face,
table_tag,
script_index,
language_index,
offset, &len,
feature_indices);
for (unsigned int i = 0; i < len; i++)
_hb_ot_layout_collect_lookups_lookups (face,
table_tag,
feature_indices[i],
lookup_indexes);
offset += len;
} while (len == ARRAY_LENGTH (feature_indices));
_hb_ot_layout_language_add_feature_indexes_to (face,
table_tag,
script_index,
language_index,
feature_indexes);
}
else
{
@ -711,28 +705,25 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face,
language_index,
*features,
&feature_index))
_hb_ot_layout_collect_lookups_lookups (face,
table_tag,
feature_index,
lookup_indexes);
feature_indexes->add (feature_index);
}
}
}
static void
_hb_ot_layout_collect_lookups_languages (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
const hb_tag_t *languages,
const hb_tag_t *features,
hb_set_t *lookup_indexes /* OUT */)
_hb_ot_layout_collect_features_languages (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
const hb_tag_t *languages,
const hb_tag_t *features,
hb_set_t *feature_indexes /* OUT */)
{
_hb_ot_layout_collect_lookups_features (face,
table_tag,
script_index,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
features,
lookup_indexes);
_hb_ot_layout_collect_features_features (face,
table_tag,
script_index,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
features,
feature_indexes);
if (!languages)
{
@ -742,12 +733,12 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face,
script_index,
0, nullptr, nullptr);
for (unsigned int language_index = 0; language_index < count; language_index++)
_hb_ot_layout_collect_lookups_features (face,
table_tag,
script_index,
language_index,
features,
lookup_indexes);
_hb_ot_layout_collect_features_features (face,
table_tag,
script_index,
language_index,
features,
feature_indexes);
}
else
{
@ -759,12 +750,58 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face,
script_index,
*languages,
&language_index))
_hb_ot_layout_collect_lookups_features (face,
table_tag,
script_index,
language_index,
features,
lookup_indexes);
_hb_ot_layout_collect_features_features (face,
table_tag,
script_index,
language_index,
features,
feature_indexes);
}
}
}
/**
* hb_ot_layout_collect_features:
*
* Since: 1.8.5
**/
void
hb_ot_layout_collect_features (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *scripts,
const hb_tag_t *languages,
const hb_tag_t *features,
hb_set_t *feature_indexes /* OUT */)
{
if (!scripts)
{
/* All scripts */
unsigned int count = hb_ot_layout_table_get_script_tags (face,
table_tag,
0, nullptr, nullptr);
for (unsigned int script_index = 0; script_index < count; script_index++)
_hb_ot_layout_collect_features_languages (face,
table_tag,
script_index,
languages,
features,
feature_indexes);
}
else
{
for (; *scripts; scripts++)
{
unsigned int script_index;
if (hb_ot_layout_table_find_script (face,
table_tag,
*scripts,
&script_index))
_hb_ot_layout_collect_features_languages (face,
table_tag,
script_index,
languages,
features,
feature_indexes);
}
}
}
@ -782,37 +819,10 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
const hb_tag_t *features,
hb_set_t *lookup_indexes /* OUT */)
{
if (!scripts)
{
/* All scripts */
unsigned int count = hb_ot_layout_table_get_script_tags (face,
table_tag,
0, nullptr, nullptr);
for (unsigned int script_index = 0; script_index < count; script_index++)
_hb_ot_layout_collect_lookups_languages (face,
table_tag,
script_index,
languages,
features,
lookup_indexes);
}
else
{
for (; *scripts; scripts++)
{
unsigned int script_index;
if (hb_ot_layout_table_find_script (face,
table_tag,
*scripts,
&script_index))
_hb_ot_layout_collect_lookups_languages (face,
table_tag,
script_index,
languages,
features,
lookup_indexes);
}
}
hb_auto_t<hb_set_t> feature_indexes;
hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID; hb_set_next (&feature_indexes, &feature_index);)
_hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes);
}
/**
@ -841,13 +851,13 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
{
case HB_OT_TAG_GSUB:
{
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index);
l.collect_glyphs (&c);
return;
}
case HB_OT_TAG_GPOS:
{
const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
const OT::PosLookup& l = hb_ot_layout_from_face (face)->table.GPOS->get_lookup (lookup_index);
l.collect_glyphs (&c);
return;
}
@ -894,7 +904,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
hb_bool_t
hb_ot_layout_has_substitution (hb_face_t *face)
{
return &_get_gsub (face) != &Null(OT::GSUB);
return _get_gsub (face).has_data ();
}
/**
@ -923,7 +933,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index);
return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
}
@ -969,6 +979,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
OT::hb_closure_context_t c (face, glyphs, &done_lookups);
const OT::GSUB& gsub = _get_gsub (face);
unsigned int iteration_count = 0;
unsigned int glyphs_length;
do
{
@ -983,7 +994,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
for (unsigned int i = 0; i < gsub.get_lookup_count (); i++)
gsub.get_lookup (i).closure (&c, i);
}
} while (glyphs_length != glyphs->get_population ());
iteration_count++;
} while (iteration_count <= HB_CLOSURE_MAX_STAGES
&& glyphs_length != glyphs->get_population ());
}
/*
@ -993,7 +1006,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face)
{
return &_get_gpos (face) != &Null(OT::GPOS);
return _get_gpos (face).has_data ();
}
void
@ -1078,7 +1091,7 @@ struct GSUBProxy
typedef OT::SubstLookup Lookup;
GSUBProxy (hb_face_t *face) :
table (*hb_ot_layout_from_face (face)->gsub),
table (*hb_ot_layout_from_face (face)->table.GSUB),
accels (hb_ot_layout_from_face (face)->gsub_accels) {}
const OT::GSUB &table;
@ -1092,7 +1105,7 @@ struct GPOSProxy
typedef OT::PosLookup Lookup;
GPOSProxy (hb_face_t *face) :
table (*hb_ot_layout_from_face (face)->gpos),
table (*hb_ot_layout_from_face (face)->table.GPOS),
accels (hb_ot_layout_from_face (face)->gpos_accels) {}
const OT::GPOS &table;
@ -1101,7 +1114,7 @@ struct GPOSProxy
struct hb_get_subtables_context_t :
OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
@ -1328,5 +1341,5 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
// hb_bool_t
// hb_ot_base_has_data (hb_face_t *face)
// {
// return &_get_base (face) != &Null(OT::BASE);
// return _get_base (face).has_data ();
// }

View File

@ -194,6 +194,13 @@ HB_EXTERN unsigned int
hb_ot_layout_table_get_lookup_count (hb_face_t *face,
hb_tag_t table_tag);
HB_EXTERN void
hb_ot_layout_collect_features (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *scripts,
const hb_tag_t *languages,
const hb_tag_t *features,
hb_set_t *feature_indexes /* OUT */);
HB_EXTERN void
hb_ot_layout_collect_lookups (hb_face_t *face,

View File

@ -686,6 +686,8 @@ struct MATH
{
static const hb_tag_t tableTag = HB_OT_TAG_MATH;
inline bool has_data (void) const { return version.to_int () != 0; }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -34,7 +34,7 @@ _get_math (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::MATH);
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
return *(layout->math.get ());
return *(layout->table.MATH.get ());
}
/*
@ -55,7 +55,7 @@ _get_math (hb_face_t *face)
hb_bool_t
hb_ot_math_has_data (hb_face_t *face)
{
return &_get_math (face) != &Null(OT::MATH);
return _get_math (face).has_data ();
}
/**

View File

@ -100,14 +100,14 @@ struct maxp
inline bool subset (hb_subset_plan_t *plan) const
{
hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_maxp));
hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
hb_blob_destroy (maxp_blob);
if (unlikely (!maxp_prime_blob)) {
return false;
}
OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
maxp_prime->set_num_glyphs (plan->glyphs.len);
if (plan->drop_hints)
@ -118,7 +118,7 @@ struct maxp
return result;
}
static inline void drop_hint_fields (hb_subset_plan_t *plan, OT::maxp *maxp_prime)
static inline void drop_hint_fields (hb_subset_plan_t *plan, maxp *maxp_prime)
{
if (maxp_prime->version.major == 1)
{

View File

@ -51,12 +51,12 @@ struct os2
inline bool subset (hb_subset_plan_t *plan) const
{
hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_os2));
hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table<os2> (plan->source);
hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
// TODO(grieger): move to hb_blob_copy_writable_or_fail
hb_blob_destroy (os2_blob);
OT::os2 *os2_prime = (OT::os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
os2 *os2_prime = (os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
if (unlikely (!os2_prime)) {
hb_blob_destroy (os2_prime_blob);
return false;

View File

@ -85,7 +85,7 @@ struct post
inline bool subset (hb_subset_plan_t *plan) const
{
unsigned int post_prime_length;
hb_blob_t *post_blob = OT::Sanitizer<post>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post));
hb_blob_t *post_blob = hb_sanitize_context_t().reference_table<post>(plan->source);
hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_size);
post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
hb_blob_destroy (post_blob);
@ -110,7 +110,7 @@ struct post
{
index_to_offset.init ();
blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post));
blob = hb_sanitize_context_t().reference_table<post> (face);
const post *table = blob->as<post> ();
unsigned int table_length = blob->length;

View File

@ -79,12 +79,12 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
OT::Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs);
OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs);
Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
/* Each glyph takes four bytes max, and there's some overhead. */
char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
OT::hb_serialize_context_t c (buf, sizeof (buf));
hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_single (&c,
OT::LookupFlag::IgnoreMarks,
@ -155,15 +155,15 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
if (!num_ligatures)
return nullptr;
OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
OT::Supplier<unsigned int > component_count_supplier (component_count_list, num_ligatures);
OT::Supplier<OT::GlyphID> component_supplier (component_list, num_ligatures);
Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
Supplier<unsigned int > component_count_supplier (component_count_list, num_ligatures);
Supplier<OT::GlyphID> component_supplier (component_list, num_ligatures);
/* 16 bytes per ligature ought to be enough... */
char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
OT::hb_serialize_context_t c (buf, sizeof (buf));
hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_ligature (&c,
OT::LookupFlag::IgnoreMarks,
@ -205,8 +205,6 @@ struct arabic_fallback_plan_t
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
};
static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
#define HB_WITH_WIN1256
#endif
@ -215,7 +213,8 @@ static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
#include "hb-ot-shape-complex-arabic-win1256.hh"
#endif
struct ManifestLookup {
struct ManifestLookup
{
OT::Tag tag;
OT::OffsetTo<OT::SubstLookup> lookupOffset;
};
@ -299,7 +298,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
{
arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
if (unlikely (!fallback_plan))
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
fallback_plan->num_lookups = 0;
fallback_plan->free_lookups = false;
@ -314,14 +313,15 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
return fallback_plan;
assert (fallback_plan->num_lookups == 0);
free (fallback_plan);
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
}
static void
arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
{
if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
if (!fallback_plan || fallback_plan->num_lookups == 0)
return;
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)

View File

@ -250,7 +250,7 @@ struct arabic_shape_plan_t
* mask_array[NONE] == 0. */
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
arabic_fallback_plan_t *fallback_plan;
mutable arabic_fallback_plan_t *fallback_plan;
unsigned int do_fallback : 1;
unsigned int has_stch : 1;

View File

@ -300,7 +300,9 @@ static const hb_codepoint_t ra_chars[] = {
0x0CB0u, /* Kannada */
0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
0x179Au, /* Khmer */
};
static inline bool

Some files were not shown because too many files have changed in this diff Show More