Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-08-03 15:02:19 -04:00
commit 56f294a5ec
221 changed files with 6660 additions and 2548 deletions

View File

@ -1016,7 +1016,6 @@ pref("media.webspeech.synth.enabled", true);
// Enable Web Speech recognition API
pref("media.webspeech.recognition.enable", true);
pref("media.webspeech.service.default", "pocketsphinx");
// Downloads API
pref("dom.mozDownloads.enabled", true);

View File

@ -7213,7 +7213,7 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
filterBundle->GetStringFromName(MOZ_UTF16("videoFilter"),
getter_Copies(extensionListStr));
} else if (token.First() == '.') {
if (token.FindChar(';') >= 0 || token.FindChar('*') >= 0) {
if (token.Contains(';') || token.Contains('*')) {
// Ignore this filter as it contains reserved characters
continue;
}

View File

@ -54,13 +54,16 @@ public:
SpeechRecognitionResultList* resultList =
new SpeechRecognitionResultList(mRecognition);
SpeechRecognitionResult* result = new SpeechRecognitionResult(mRecognition);
SpeechRecognitionAlternative* alternative =
new SpeechRecognitionAlternative(mRecognition);
ErrorResult rv;
if (0 < mRecognition->GetMaxAlternatives(rv)) { // GetMaxAlternatives can't fail
SpeechRecognitionAlternative* alternative =
new SpeechRecognitionAlternative(mRecognition);
alternative->mTranscript = mResult;
alternative->mConfidence = 100;
alternative->mTranscript = mResult;
alternative->mConfidence = 100;
result->mItems.AppendElement(alternative);
result->mItems.AppendElement(alternative);
}
resultList->mItems.AppendElement(result);
event->mRecognitionResultList = resultList;
@ -330,13 +333,16 @@ PocketSphinxSpeechRecognitionService::BuildMockResultList()
SpeechRecognitionResultList* resultList =
new SpeechRecognitionResultList(mRecognition);
SpeechRecognitionResult* result = new SpeechRecognitionResult(mRecognition);
SpeechRecognitionAlternative* alternative =
new SpeechRecognitionAlternative(mRecognition);
ErrorResult rv;
if (0 < mRecognition->GetMaxAlternatives(rv)) { // GetMaxAlternatives can't fail
SpeechRecognitionAlternative* alternative =
new SpeechRecognitionAlternative(mRecognition);
alternative->mTranscript = NS_LITERAL_STRING("Mock final result");
alternative->mConfidence = 0.0f;
alternative->mTranscript = NS_LITERAL_STRING("Mock final result");
alternative->mConfidence = 0.0f;
result->mItems.AppendElement(alternative);
result->mItems.AppendElement(alternative);
}
resultList->mItems.AppendElement(result);
return resultList;

View File

@ -23,10 +23,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechGrammarList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
SpeechGrammarList::SpeechGrammarList(nsISupports* aParent, nsISpeechRecognitionService* aRecognitionService)
SpeechGrammarList::SpeechGrammarList(nsISupports* aParent)
: mParent(aParent)
{
this->mRecognitionService = aRecognitionService;
}
SpeechGrammarList::~SpeechGrammarList()
@ -37,16 +36,9 @@ already_AddRefed<SpeechGrammarList>
SpeechGrammarList::Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv)
{
nsCOMPtr<nsISpeechRecognitionService> recognitionService;
recognitionService = GetSpeechRecognitionService();
if (!recognitionService) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
} else {
nsRefPtr<SpeechGrammarList> speechGrammarList =
new SpeechGrammarList(aGlobal.GetAsSupports(), recognitionService);
return speechGrammarList.forget();
}
nsRefPtr<SpeechGrammarList> speechGrammarList =
new SpeechGrammarList(aGlobal.GetAsSupports());
return speechGrammarList.forget();
}
JSObject*
@ -91,7 +83,6 @@ SpeechGrammarList::AddFromString(const nsAString& aString,
SpeechGrammar* speechGrammar = new SpeechGrammar(mParent);
speechGrammar->SetSrc(aString, aRv);
mItems.AppendElement(speechGrammar);
mRecognitionService->ValidateAndSetGrammarList(speechGrammar, nullptr);
return;
}

View File

@ -11,7 +11,6 @@
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsISpeechRecognitionService.h"
struct JSContext;
@ -29,7 +28,7 @@ class SpeechGrammarList final : public nsISupports,
public nsWrapperCache
{
public:
explicit SpeechGrammarList(nsISupports* aParent, nsISpeechRecognitionService* aRecognitionService);
explicit SpeechGrammarList(nsISupports* aParent);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(SpeechGrammarList)
@ -50,8 +49,6 @@ public:
already_AddRefed<SpeechGrammar> IndexedGetter(uint32_t aIndex, bool& aPresent, ErrorResult& aRv);
nsCOMPtr<nsISpeechRecognitionService> mRecognitionService;
private:
~SpeechGrammarList();

View File

@ -10,6 +10,7 @@
#include "nsCycleCollectionParticipant.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/SpeechRecognitionBinding.h"
#include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/MediaStreamError.h"
@ -20,7 +21,9 @@
#include "endpointer.h"
#include "mozilla/dom/SpeechRecognitionEvent.h"
#include "nsIDocument.h"
#include "nsIObserverService.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h"
#include "nsQueryObject.h"
@ -35,7 +38,8 @@ namespace mozilla {
namespace dom {
#define PREFERENCE_DEFAULT_RECOGNITION_SERVICE "media.webspeech.service.default"
#define DEFAULT_RECOGNITION_SERVICE "pocketsphinx"
#define DEFAULT_RECOGNITION_SERVICE_PREFIX "pocketsphinx-"
#define DEFAULT_RECOGNITION_SERVICE "pocketsphinx-en-US"
#define PREFERENCE_ENDPOINTER_SILENCE_LENGTH "media.webspeech.silence_length"
#define PREFERENCE_ENDPOINTER_LONG_SILENCE_LENGTH "media.webspeech.long_silence_length"
@ -62,7 +66,7 @@ GetSpeechRecognitionLog()
#define SR_LOG(...) MOZ_LOG(GetSpeechRecognitionLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
already_AddRefed<nsISpeechRecognitionService>
GetSpeechRecognitionService()
GetSpeechRecognitionService(const nsAString& aLang)
{
nsAutoCString speechRecognitionServiceCID;
@ -70,19 +74,23 @@ GetSpeechRecognitionService()
Preferences::GetCString(PREFERENCE_DEFAULT_RECOGNITION_SERVICE);
nsAutoCString speechRecognitionService;
if (!prefValue.get() || prefValue.IsEmpty()) {
speechRecognitionService = DEFAULT_RECOGNITION_SERVICE;
} else {
if (!aLang.IsEmpty()) {
speechRecognitionService =
NS_LITERAL_CSTRING(DEFAULT_RECOGNITION_SERVICE_PREFIX) +
NS_ConvertUTF16toUTF8(aLang);
} else if (!prefValue.IsEmpty()) {
speechRecognitionService = prefValue;
} else {
speechRecognitionService = DEFAULT_RECOGNITION_SERVICE;
}
if (!SpeechRecognition::mTestConfig.mFakeRecognitionService){
if (SpeechRecognition::mTestConfig.mFakeRecognitionService) {
speechRecognitionServiceCID =
NS_SPEECH_RECOGNITION_SERVICE_CONTRACTID_PREFIX "fake";
} else {
speechRecognitionServiceCID =
NS_LITERAL_CSTRING(NS_SPEECH_RECOGNITION_SERVICE_CONTRACTID_PREFIX) +
speechRecognitionService;
} else {
speechRecognitionServiceCID =
NS_SPEECH_RECOGNITION_SERVICE_CONTRACTID_PREFIX "fake";
}
nsresult rv;
@ -91,7 +99,9 @@ GetSpeechRecognitionService()
return recognitionService.forget();
}
NS_INTERFACE_MAP_BEGIN(SpeechRecognition)
NS_IMPL_CYCLE_COLLECTION_INHERITED(SpeechRecognition, DOMEventTargetHelper, mDOMStream, mSpeechGrammarList)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SpeechRecognition)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
@ -105,6 +115,9 @@ SpeechRecognition::SpeechRecognition(nsPIDOMWindow* aOwnerWindow)
, mEndpointer(kSAMPLE_RATE)
, mAudioSamplesPerChunk(mEndpointer.FrameSize())
, mSpeechDetectionTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
, mSpeechGrammarList(new SpeechGrammarList(GetParentObject()))
, mInterimResults(false)
, mMaxAlternatives(1)
{
SR_LOG("created SpeechRecognition");
@ -619,31 +632,28 @@ SpeechRecognition::ProcessTestEventRequest(nsISupports* aSubject, const nsAStrin
}
already_AddRefed<SpeechGrammarList>
SpeechRecognition::GetGrammars(ErrorResult& aRv) const
SpeechRecognition::Grammars() const
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
nsRefPtr<SpeechGrammarList> speechGrammarList = mSpeechGrammarList;
return speechGrammarList.forget();
}
void
SpeechRecognition::SetGrammars(SpeechGrammarList& aArg, ErrorResult& aRv)
SpeechRecognition::SetGrammars(SpeechGrammarList& aArg)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return;
mSpeechGrammarList = &aArg;
}
void
SpeechRecognition::GetLang(nsString& aRetVal, ErrorResult& aRv) const
SpeechRecognition::GetLang(nsString& aRetVal) const
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return;
aRetVal = mLang;
}
void
SpeechRecognition::SetLang(const nsAString& aArg, ErrorResult& aRv)
SpeechRecognition::SetLang(const nsAString& aArg)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return;
mLang = aArg;
}
bool
@ -661,30 +671,28 @@ SpeechRecognition::SetContinuous(bool aArg, ErrorResult& aRv)
}
bool
SpeechRecognition::GetInterimResults(ErrorResult& aRv) const
SpeechRecognition::InterimResults() const
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return false;
return mInterimResults;
}
void
SpeechRecognition::SetInterimResults(bool aArg, ErrorResult& aRv)
SpeechRecognition::SetInterimResults(bool aArg)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
mInterimResults = aArg;
return;
}
uint32_t
SpeechRecognition::GetMaxAlternatives(ErrorResult& aRv) const
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return 0;
return mMaxAlternatives;
}
void
SpeechRecognition::SetMaxAlternatives(uint32_t aArg, ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
mMaxAlternatives = aArg;
return;
}
@ -710,8 +718,11 @@ SpeechRecognition::Start(const Optional<NonNull<DOMMediaStream>>& aStream, Error
return;
}
mRecognitionService = GetSpeechRecognitionService();
if (NS_WARN_IF(!mRecognitionService)) {
if (!SetRecognitionService(aRv)) {
return;
}
if (!ValidateAndSetGrammarList(aRv)) {
return;
}
@ -739,6 +750,77 @@ SpeechRecognition::Start(const Optional<NonNull<DOMMediaStream>>& aStream, Error
NS_DispatchToMainThread(event);
}
bool
SpeechRecognition::SetRecognitionService(ErrorResult& aRv)
{
// See: https://dvcs.w3.org/hg/speech-api/raw-file/tip/webspeechapi.html#dfn-lang
if (!mLang.IsEmpty()) {
mRecognitionService = GetSpeechRecognitionService(mLang);
if (!mRecognitionService) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
return true;
}
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
if(!window) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
nsCOMPtr<nsIDocument> document = window->GetExtantDoc();
if(!document) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
nsCOMPtr<Element> element = document->GetRootElement();
if(!element) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
nsAutoString lang;
element->GetLang(lang);
mRecognitionService = GetSpeechRecognitionService(lang);
if (!mRecognitionService) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
return true;
}
bool
SpeechRecognition::ValidateAndSetGrammarList(ErrorResult& aRv)
{
if (!mSpeechGrammarList) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
uint32_t grammarListLength = mSpeechGrammarList->Length();
if (0 == grammarListLength) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
for (uint32_t count = 0; count < grammarListLength; ++count) {
nsRefPtr<SpeechGrammar> speechGrammar = mSpeechGrammarList->Item(count, aRv);
if (aRv.Failed()) {
return false;
}
if (NS_FAILED(mRecognitionService->ValidateAndSetGrammarList(speechGrammar.get(), nullptr))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return false;
}
}
return true;
}
void
SpeechRecognition::Stop()
{

View File

@ -49,8 +49,6 @@ class SpeechEvent;
PRLogModuleInfo* GetSpeechRecognitionLog();
#define SR_LOG(...) MOZ_LOG(GetSpeechRecognitionLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
already_AddRefed<nsISpeechRecognitionService> GetSpeechRecognitionService();
class SpeechRecognition final : public DOMEventTargetHelper,
public nsIObserver,
public SupportsWeakPtr<SpeechRecognition>
@ -60,6 +58,7 @@ public:
explicit SpeechRecognition(nsPIDOMWindow* aOwnerWindow);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SpeechRecognition, DOMEventTargetHelper)
NS_DECL_NSIOBSERVER
@ -72,21 +71,21 @@ public:
static already_AddRefed<SpeechRecognition>
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
already_AddRefed<SpeechGrammarList> GetGrammars(ErrorResult& aRv) const;
already_AddRefed<SpeechGrammarList> Grammars() const;
void SetGrammars(mozilla::dom::SpeechGrammarList& aArg, ErrorResult& aRv);
void SetGrammars(mozilla::dom::SpeechGrammarList& aArg);
void GetLang(nsString& aRetVal, ErrorResult& aRv) const;
void GetLang(nsString& aRetVal) const;
void SetLang(const nsAString& aArg, ErrorResult& aRv);
void SetLang(const nsAString& aArg);
bool GetContinuous(ErrorResult& aRv) const;
void SetContinuous(bool aArg, ErrorResult& aRv);
bool GetInterimResults(ErrorResult& aRv) const;
bool InterimResults() const;
void SetInterimResults(bool aArg, ErrorResult& aRv);
void SetInterimResults(bool aArg);
uint32_t GetMaxAlternatives(ErrorResult& aRv) const;
@ -176,6 +175,9 @@ private:
void SetState(FSMState state);
bool StateBetween(FSMState begin, FSMState end);
bool SetRecognitionService(ErrorResult& aRv);
bool ValidateAndSetGrammarList(ErrorResult& aRv);
class GetUserMediaSuccessCallback : public nsIDOMGetUserMediaSuccessCallback
{
public:
@ -249,6 +251,32 @@ private:
nsCOMPtr<nsITimer> mSpeechDetectionTimer;
bool mAborted;
nsString mLang;
nsRefPtr<SpeechGrammarList> mSpeechGrammarList;
// WebSpeechAPI (http://bit.ly/1gIl7DC) states:
//
// 1. Default value MUST be false
// 2. If true, interim results SHOULD be returned
// 3. If false, interim results MUST NOT be returned
//
// Pocketsphinx does not return interm results; so, defaulting
// mInterimResults to false, then ignoring its subsequent value
// is a conforming implementation.
bool mInterimResults;
// WebSpeechAPI (http://bit.ly/1JAiqeo) states:
//
// 1. Default value is 1
// 2. Subsequent value is the "maximum number of SpeechRecognitionAlternatives per result"
//
// Pocketsphinx can only return at maximum a single SpeechRecognitionAlternative
// per SpeechRecognitionResult. So defaulting mMaxAlternatives to 1, for all non
// zero values ignoring mMaxAlternatives while for a 0 value returning no
// SpeechRecognitionAlternative per result is a conforming implementation.
uint32_t mMaxAlternatives;
void ProcessTestEventRequest(nsISupports* aSubject, const nsAString& aEventName);
const char* GetName(FSMState aId);

View File

@ -102,12 +102,15 @@ FakeSpeechRecognitionService::BuildMockResultList()
{
SpeechRecognitionResultList* resultList = new SpeechRecognitionResultList(mRecognition);
SpeechRecognitionResult* result = new SpeechRecognitionResult(mRecognition);
SpeechRecognitionAlternative* alternative = new SpeechRecognitionAlternative(mRecognition);
ErrorResult rv;
if (0 < mRecognition->GetMaxAlternatives(rv)) { // GetMaxAlternatives can't fail
SpeechRecognitionAlternative* alternative = new SpeechRecognitionAlternative(mRecognition);
alternative->mTranscript = NS_LITERAL_STRING("Mock final result");
alternative->mConfidence = 0.0f;
alternative->mTranscript = NS_LITERAL_STRING("Mock final result");
alternative->mConfidence = 0.0f;
result->mItems.AppendElement(alternative);
result->mItems.AppendElement(alternative);
}
resultList->mItems.AppendElement(result);
return resultList;

View File

@ -44,6 +44,11 @@ function EventManager(sr) {
var isDone = false;
// set up grammar
var sgl = new SpeechGrammarList();
sgl.addFromString("#JSGF V1.0; grammar test; public <simple> = hello ;", 1);
sr.grammars = sgl;
// AUDIO_DATA events are asynchronous,
// so we queue events requested while they are being
// issued to make them seem synchronous

View File

@ -23,11 +23,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=650295
performTest({
eventsToRequest: ['EVENT_AUDIO_ERROR'],
expectedEvents: {
'start': null,
'audiostart': null,
'speechstart': null,
'speechend': null,
'audioend': null,
'error': buildErrorCallback(errorCodes.AUDIO_CAPTURE),
'end': null
},
doneFunc: SimpleTest.finish,
prefs: [["media.webspeech.test.fake_fsm_events", true]]
prefs: [["media.webspeech.test.fake_fsm_events", true], ["media.webspeech.test.fake_recognition_service", true]]
});
</script>
</pre>

View File

@ -464,13 +464,9 @@ public:
nsRefPtr<PromiseWorkerProxy> proxy = mProxy.forget();
nsRefPtr<Promise> promise = proxy->GetWorkerPromise();
if (NS_SUCCEEDED(mStatus)) {
if (mEndpoint.IsEmpty()) {
promise->MaybeResolve(JS::NullHandleValue);
} else {
nsRefPtr<WorkerPushSubscription> sub =
new WorkerPushSubscription(mEndpoint, mScope);
promise->MaybeResolve(sub);
}
nsRefPtr<WorkerPushSubscription> sub =
new WorkerPushSubscription(mEndpoint, mScope);
promise->MaybeResolve(sub);
} else {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}

View File

@ -21,5 +21,3 @@ skip-if = os == "android" || toolkit == "gonk"
skip-if = os == "android" || toolkit == "gonk"
[test_try_registering_offline_disabled.html]
skip-if = os == "android" || toolkit == "gonk"
[test_push_manager_worker.html]
skip-if = os == "android" || toolkit == "gonk"

View File

@ -1,101 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
Bug 1184574: Expose PushManager to workers.
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<head>
<title>Test for Bug 1184574</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1184574">Mozilla Bug 1184574</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="text/javascript">
var registration;
function start() {
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: "."})
.then(swr => { registration = swr; return swr; });
}
function unregisterSW() {
return registration.unregister().then(function(result) {
ok(result, "Unregister should return true.");
}, function(e) {
dump("Unregistering the SW failed with " + e + "\n");
});
}
function setupPushNotification(swr) {
return swr.pushManager.subscribe().then(
pushSubscription => {
ok(true, "successful registered for push notification");
return pushSubscription;
}, error => {
ok(false, "could not register for push notification");
});
}
function getNewEndpointFromWorker(pushSubscription) {
return new Promise((resolve, reject) => {
var channel = new MessageChannel();
channel.port1.onmessage = e => {
(e.data.error ? reject : resolve)(e.data);
};
registration.active.postMessage({
endpoint: pushSubscription.endpoint,
}, [channel.port2]);
}).then(data => {
return registration.pushManager.getSubscription().then(
pushSubscription => {
is(data.endpoint, pushSubscription.endpoint,
"Wrong push endpoint in parent");
return pushSubscription;
});
});
}
function unregisterPushNotification(pushSubscription) {
return pushSubscription.unsubscribe().then(
result => {
ok(result, "unsubscribe() on existing subscription should return true.");
return pushSubscription;
}, error => {
ok(false, "unsubscribe() should never fail.");
});
}
function runTest() {
start()
.then(setupPushNotification)
.then(getNewEndpointFromWorker)
.then(unregisterPushNotification)
.then(unregisterSW)
.catch(function(e) {
ok(false, "Some test failed with error " + e);
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>

View File

@ -1,14 +1,7 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
// This worker is used for two types of tests. `handlePush` sends messages to
// `frame.html`, which verifies that the worker can receive push messages.
// `handleMessage` receives a message from `test_push_manager_worker.html`, and
// verifies that `PushManager` can be used from the worker.
this.onpush = handlePush;
this.onmessage = handleMessage;
function handlePush(event) {
@ -26,26 +19,3 @@ function handlePush(event) {
result[0].postMessage({type: "finished", okay: "no"});
});
}
function handleMessage(event) {
self.registration.pushManager.getSubscription().then(subscription => {
if (subscription.endpoint != event.data.endpoint) {
throw new Error("Wrong push endpoint in worker");
}
return subscription.unsubscribe();
}).then(result => {
if (!result) {
throw new Error("Error dropping subscription in worker");
}
return self.registration.pushManager.getSubscription();
}).then(subscription => {
if (subscription) {
throw new Error("Subscription not dropped in worker");
}
return self.registration.pushManager.subscribe();
}).then(subscription => {
event.ports[0].postMessage({endpoint: subscription.endpoint});
}).catch(error => {
event.ports[0].postMessage({error: error});
});
}

View File

@ -39,6 +39,8 @@ class Matrix;
} // namespace gfx
} // namespace mozilla
#define SVG_ZERO_LENGTH_PATH_FIX_FACTOR 512
inline bool
IsSVGWhitespace(char aChar)
{

View File

@ -37,6 +37,23 @@ SVGLineElement::SVGLineElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeIn
{
}
void
SVGLineElement::MaybeAdjustForZeroLength(float aX1, float aY1,
float& aX2, float aY2)
{
if (aX1 == aX2 && aY1 == aY2) {
SVGContentUtils::AutoStrokeOptions strokeOptions;
SVGContentUtils::GetStrokeOptions(&strokeOptions, this, nullptr, nullptr,
SVGContentUtils::eIgnoreStrokeDashing);
if (strokeOptions.mLineCap != CapStyle::BUTT) {
float tinyLength =
strokeOptions.mLineWidth / SVG_ZERO_LENGTH_PATH_FIX_FACTOR;
aX2 += tinyLength;
}
}
}
//----------------------------------------------------------------------
// nsIDOMNode methods
@ -112,6 +129,8 @@ SVGLineElement::GetAsSimplePath(SimplePath* aSimplePath)
{
float x1, y1, x2, y2;
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
MaybeAdjustForZeroLength(x1, y1, x2, y2);
aSimplePath->SetLine(x1, y1, x2, y2);
}
@ -121,6 +140,7 @@ SVGLineElement::BuildPath(PathBuilder* aBuilder)
float x1, y1, x2, y2;
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
MaybeAdjustForZeroLength(x1, y1, x2, y2);
aBuilder->MoveTo(Point(x1, y1));
aBuilder->LineTo(Point(x2, y2));

View File

@ -25,6 +25,10 @@ protected:
virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
friend nsresult (::NS_NewSVGLineElement(nsIContent **aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
// If the input line has length zero and linecaps aren't butt, adjust |aX2| by
// a tiny amount to a barely-nonzero-length line that all of our draw targets
// will render
void MaybeAdjustForZeroLength(float aX1, float aY1, float& aX2, float aY2);
public:
// nsIContent interface

View File

@ -255,7 +255,7 @@ ApproximateZeroLengthSubpathSquareCaps(PathBuilder* aPB,
// line is rather arbitrary, other than being chosen to meet the requirements
// described in the comment above.
Float tinyLength = aStrokeWidth / 512;
Float tinyLength = aStrokeWidth / SVG_ZERO_LENGTH_PATH_FIX_FACTOR;
aPB->LineTo(aPoint + Point(tinyLength, 0));
aPB->MoveTo(aPoint);

View File

@ -15,13 +15,10 @@
Func="SpeechRecognition::IsAuthorized"]
interface SpeechRecognition : EventTarget {
// recognition parameters
[Throws]
attribute SpeechGrammarList grammars;
[Throws]
attribute DOMString lang;
[Throws]
attribute boolean continuous;
[Throws]
attribute boolean interimResults;
[Throws]
attribute unsigned long maxAlternatives;

View File

@ -1686,7 +1686,7 @@ static void
DrawPaintedLayer(PaintedLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aDirtyRegion,
const nsIntRegion* aDirtyRegion,
DrawRegionClip aClip,
const nsIntRegion& aRegionToInvalidate,
void* aCallbackData)

View File

@ -69,6 +69,10 @@ struct BasePoint {
return Sub(-x, -y);
}
T DotProduct(const Sub& aPoint) const {
return x * aPoint.x + y * aPoint.y;
}
T Length() const {
return hypot(x, y);
}

View File

@ -30,6 +30,10 @@ struct BaseSize {
return width == 0 || height == 0;
}
bool IsSquare() const {
return width == height;
}
// Note that '=' isn't defined so we'll get the
// compiler generated default assignment operator

View File

@ -13,6 +13,80 @@
namespace mozilla {
namespace gfx {
// Kappa constant for 90-degree angle
const Float kKappaFactor = 0.55191497064665766025f;
// Calculate kappa constant for partial curve. The sign of angle in the
// tangent will actually ensure this is negative for a counter clockwise
// sweep, so changing signs later isn't needed.
inline Float ComputeKappaFactor(Float aAngle)
{
return (4.0f / 3.0f) * tanf(aAngle / 4.0f);
}
/**
* Draws a partial arc <= 90 degrees given exact start and end points.
* Assumes that it is continuing from an already specified start point.
*/
template <typename T>
inline void PartialArcToBezier(T* aSink,
const Size& aRadius,
const Point& aStartPoint, const Point& aEndPoint,
const Point& aStartOffset, const Point& aEndOffset,
Float aKappaFactor = kKappaFactor)
{
Float kappaX = aKappaFactor * aRadius.width;
Float kappaY = aKappaFactor * aRadius.height;
Point cp1 =
aStartPoint + Point(-aStartOffset.y * kappaX, aStartOffset.x * kappaY);
Point cp2 =
aEndPoint + Point(aEndOffset.y * kappaX, -aEndOffset.x * kappaY);
aSink->BezierTo(cp1, cp2, aEndPoint);
}
/**
* Draws an acute arc (<= 90 degrees) given exact start and end points.
* Specialized version avoiding kappa calculation.
*/
template <typename T>
inline void AcuteArcToBezier(T* aSink,
const Point& aOrigin, const Size& aRadius,
const Point& aStartPoint, const Point& aEndPoint,
Float aKappaFactor = kKappaFactor)
{
aSink->LineTo(aStartPoint);
if (!aRadius.IsEmpty()) {
Point startOffset = aStartPoint - aOrigin;
startOffset.x /= aRadius.width;
startOffset.y /= aRadius.height;
Point endOffset = aEndPoint - aOrigin;
endOffset.x /= aRadius.width;
endOffset.y /= aRadius.height;
PartialArcToBezier(aSink, aRadius,
aStartPoint, aEndPoint,
startOffset, endOffset,
aKappaFactor);
} else if (aEndPoint != aStartPoint) {
aSink->LineTo(aEndPoint);
}
}
/**
* Draws an acute arc (<= 90 degrees) given exact start and end points.
*/
template <typename T>
inline void AcuteArcToBezier(T* aSink,
const Point& aOrigin, const Size& aRadius,
const Point& aStartPoint, const Point& aEndPoint,
Float aStartAngle, Float aEndAngle)
{
AcuteArcToBezier(aSink, aOrigin, aRadius, aStartPoint, aEndPoint,
ComputeKappaFactor(aEndAngle - aStartAngle));
}
template <typename T>
void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
float aStartAngle, float aEndAngle, bool aAntiClockwise)
@ -35,39 +109,30 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
}
Float currentStartAngle = aStartAngle;
Point currentStartPoint(aOrigin.x + cosf(aStartAngle) * aRadius.width,
aOrigin.y + sinf(aStartAngle) * aRadius.height);
Point currentStartOffset(cosf(aStartAngle), sinf(aStartAngle));
Point currentStartPoint(aOrigin.x + currentStartOffset.x * aRadius.width,
aOrigin.y + currentStartOffset.y * aRadius.height);
aSink->LineTo(currentStartPoint);
while (arcSweepLeft > 0) {
// We guarantee here the current point is the start point of the next
// curve segment.
Float currentEndAngle =
currentStartAngle + std::min(arcSweepLeft, Float(M_PI / 2.0f)) * sweepDirection;
Point currentEndPoint(aOrigin.x + cosf(currentEndAngle) * aRadius.width,
aOrigin.y + sinf(currentEndAngle) * aRadius.height);
Point currentEndOffset(cosf(currentEndAngle), sinf(currentEndAngle));
Point currentEndPoint(aOrigin.x + currentEndOffset.x * aRadius.width,
aOrigin.y + currentEndOffset.y * aRadius.height);
// Calculate kappa constant for partial curve. The sign of angle in the
// tangent will actually ensure this is negative for a counter clockwise
// sweep, so changing signs later isn't needed.
Float kappaFactor = (4.0f / 3.0f) * tanf((currentEndAngle - currentStartAngle) / 4.0f);
Float kappaX = kappaFactor * aRadius.width;
Float kappaY = kappaFactor * aRadius.height;
Point tangentStart(-sinf(currentStartAngle), cosf(currentStartAngle));
Point cp1 = currentStartPoint;
cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY);
Point revTangentEnd(sinf(currentEndAngle), -cosf(currentEndAngle));
Point cp2 = currentEndPoint;
cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY);
aSink->BezierTo(cp1, cp2, currentEndPoint);
PartialArcToBezier(aSink, aRadius,
currentStartPoint, currentEndPoint,
currentStartOffset, currentEndOffset,
ComputeKappaFactor(currentEndAngle - currentStartAngle));
// We guarantee here the current point is the start point of the next
// curve segment.
arcSweepLeft -= Float(M_PI / 2.0f);
currentStartAngle = currentEndAngle;
currentStartOffset = currentEndOffset;
currentStartPoint = currentEndPoint;
}
}
@ -78,42 +143,26 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
template <typename T>
void EllipseToBezier(T* aSink, const Point &aOrigin, const Size &aRadius)
{
Point startPoint(aOrigin.x + aRadius.width,
aOrigin.y);
Point currentStartOffset(1, 0);
Point currentStartPoint(aOrigin.x + aRadius.width, aOrigin.y);
aSink->LineTo(startPoint);
aSink->LineTo(currentStartPoint);
// Calculate kappa constant for partial curve. The sign of angle in the
// tangent will actually ensure this is negative for a counter clockwise
// sweep, so changing signs later isn't needed.
Float kappaFactor = (4.0f / 3.0f) * tan((M_PI/2.0f) / 4.0f);
Float kappaX = kappaFactor * aRadius.width;
Float kappaY = kappaFactor * aRadius.height;
Float cosStartAngle = 1;
Float sinStartAngle = 0;
for (int i = 0; i < 4; i++) {
// We guarantee here the current point is the start point of the next
// curve segment.
Point currentStartPoint(aOrigin.x + cosStartAngle * aRadius.width,
aOrigin.y + sinStartAngle * aRadius.height);
Point currentEndPoint(aOrigin.x + -sinStartAngle * aRadius.width,
aOrigin.y + cosStartAngle * aRadius.height);
Point tangentStart(-sinStartAngle, cosStartAngle);
Point cp1 = currentStartPoint;
cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY);
Point revTangentEnd(cosStartAngle, sinStartAngle);
Point cp2 = currentEndPoint;
cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY);
aSink->BezierTo(cp1, cp2, currentEndPoint);
// cos(x+pi/2) == -sin(x)
// sin(x+pi/2) == cos(x)
Float tmp = cosStartAngle;
cosStartAngle = -sinStartAngle;
sinStartAngle = tmp;
Point currentEndOffset(-currentStartOffset.y, currentStartOffset.x);
Point currentEndPoint(aOrigin.x + currentEndOffset.x * aRadius.width,
aOrigin.y + currentEndOffset.y * aRadius.height);
PartialArcToBezier(aSink, aRadius,
currentStartPoint, currentEndPoint,
currentStartOffset, currentEndOffset);
// We guarantee here the current point is the start point of the next
// curve segment.
currentStartOffset = currentEndOffset;
currentStartPoint = currentEndPoint;
}
}

View File

@ -266,6 +266,14 @@ public:
uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
}
bool operator==(const Color& aColor) const {
return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a;
}
bool operator!=(const Color& aColor) const {
return !(*this == aColor);
}
Float r, g, b, a;
};

View File

@ -14,7 +14,7 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
#AM_CXXFLAGS =
# Convenience targets:
lib: libharfbuzz.la
lib: $(BUILT_SOURCES) libharfbuzz.la
lib_LTLIBRARIES = libharfbuzz.la
@ -104,10 +104,12 @@ HBSOURCES += \
hb-ot-shape-complex-indic-table.cc \
hb-ot-shape-complex-myanmar.cc \
hb-ot-shape-complex-myanmar-machine.hh \
hb-ot-shape-complex-sea.cc \
hb-ot-shape-complex-sea-machine.hh \
hb-ot-shape-complex-thai.cc \
hb-ot-shape-complex-tibetan.cc \
hb-ot-shape-complex-use.cc \
hb-ot-shape-complex-use-machine.hh \
hb-ot-shape-complex-use-private.hh \
hb-ot-shape-complex-use-table.cc \
hb-ot-shape-complex-private.hh \
hb-ot-shape-normalize-private.hh \
hb-ot-shape-normalize.cc \
@ -276,29 +278,34 @@ harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
GENERATORS = \
gen-arabic-table.py \
gen-indic-table.py \
gen-use-table.py \
$(NULL)
EXTRA_DIST += $(GENERATORS)
unicode-tables: arabic-table indic-table
indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc \
|| ($(RM) hb-ot-shape-complex-indic-table.cc; false)
unicode-tables: arabic-table indic-table use-table
arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-arabic-table.hh \
|| ($(RM) hb-ot-shape-complex-arabic-table.hh; false)
indic-table: gen-indic-table.py IndicSyllabicCategory-7.0.0.txt IndicMatraCategory-7.0.0.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc \
|| ($(RM) hb-ot-shape-complex-indic-table.cc; false)
use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-use-table.cc \
|| ($(RM) hb-ot-shape-complex-use-table.cc; false)
built-sources: $(BUILT_SOURCES)
.PHONY: unicode-tables arabic-table indic-table built-sources
.PHONY: unicode-tables arabic-table indic-table use-table built-sources
RAGEL_GENERATED = \
$(srcdir)/hb-buffer-deserialize-json.hh \
$(srcdir)/hb-buffer-deserialize-text.hh \
$(srcdir)/hb-ot-shape-complex-indic-machine.hh \
$(srcdir)/hb-ot-shape-complex-myanmar-machine.hh \
$(srcdir)/hb-ot-shape-complex-sea-machine.hh \
$(srcdir)/hb-ot-shape-complex-use-machine.hh \
$(NULL)
BUILT_SOURCES += $(RAGEL_GENERATED)
EXTRA_DIST += \
@ -306,7 +313,7 @@ EXTRA_DIST += \
hb-buffer-deserialize-text.rl \
hb-ot-shape-complex-indic-machine.rl \
hb-ot-shape-complex-myanmar-machine.rl \
hb-ot-shape-complex-sea-machine.rl \
hb-ot-shape-complex-use-machine.rl \
$(NULL)
MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
$(srcdir)/%.hh: $(srcdir)/%.rl

476
gfx/harfbuzz/src/gen-use-table.py Executable file
View File

@ -0,0 +1,476 @@
#!/usr/bin/python
import sys
if len (sys.argv) != 5:
print >>sys.stderr, "usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt"
sys.exit (1)
BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"]
files = [file (x) for x in sys.argv[1:]]
headers = [[f.readline () for i in range (2)] for j,f in enumerate(files) if j != 2]
headers.append (["UnicodeData.txt does not have a header."])
data = [{} for f in files]
values = [{} for f in files]
for i, f in enumerate (files):
for line in f:
j = line.find ('#')
if j >= 0:
line = line[:j]
fields = [x.strip () for x in line.split (';')]
if len (fields) == 1:
continue
uu = fields[0].split ('..')
start = int (uu[0], 16)
if len (uu) == 1:
end = start
else:
end = int (uu[1], 16)
t = fields[1 if i != 2 else 2]
for u in range (start, end + 1):
data[i][u] = t
values[i][t] = values[i].get (t, 0) + end - start + 1
defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block')
# TODO Characters that are not in Unicode Indic files, but used in USE
data[0][0x034F] = defaults[0]
data[0][0x2060] = defaults[0]
for u in range (0xFE00, 0xFE0F + 1):
data[0][u] = defaults[0]
# Merge data into one dict:
for i,v in enumerate (defaults):
values[i][v] = values[i].get (v, 0) + 1
combined = {}
for i,d in enumerate (data):
for u,v in d.items ():
if i >= 2 and not u in combined:
continue
if not u in combined:
combined[u] = list (defaults)
combined[u][i] = v
combined = {k:v for k,v in combined.items() if v[3] not in BLACKLISTED_BLOCKS}
data = combined
del combined
num = len (data)
property_names = [
# General_Category
'Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', 'Mc',
'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', 'Pi', 'Po',
'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',
# Indic_Syllabic_Category
'Other',
'Bindu',
'Visarga',
'Avagraha',
'Nukta',
'Virama',
'Pure_Killer',
'Invisible_Stacker',
'Vowel_Independent',
'Vowel_Dependent',
'Vowel',
'Consonant_Placeholder',
'Consonant',
'Consonant_Dead',
'Consonant_With_Stacker',
'Consonant_Prefixed',
'Consonant_Preceding_Repha',
'Consonant_Succeeding_Repha',
'Consonant_Subjoined',
'Consonant_Medial',
'Consonant_Final',
'Consonant_Head_Letter',
'Modifying_Letter',
'Tone_Letter',
'Tone_Mark',
'Gemination_Mark',
'Cantillation_Mark',
'Register_Shifter',
'Syllable_Modifier',
'Consonant_Killer',
'Non_Joiner',
'Joiner',
'Number_Joiner',
'Number',
'Brahmi_Joining_Number',
# Indic_Positional_Category
'Not_Applicable',
'Right',
'Left',
'Visual_Order_Left',
'Left_And_Right',
'Top',
'Bottom',
'Top_And_Bottom',
'Top_And_Right',
'Top_And_Left',
'Top_And_Left_And_Right',
'Bottom_And_Right',
'Top_And_Bottom_And_Right',
'Overstruck',
]
class PropertyValue(object):
def __init__(self, name_):
self.name = name_
def __str__(self):
return self.name
def __eq__(self, other):
return self.name == (other if isinstance(other, basestring) else other.name)
def __ne__(self, other):
return not (self == other)
property_values = {}
for name in property_names:
value = PropertyValue(name)
assert value not in property_values
assert value not in globals()
property_values[name] = value
globals().update(property_values)
def is_BASE(U, UISC, UGC):
return (UISC in [Number, Consonant, Consonant_Head_Letter,
#SPEC-OUTDATED Consonant_Placeholder,
Tone_Letter] or
(UGC == Lo and UISC in [Avagraha, Bindu, Consonant_Final, Consonant_Medial,
Consonant_Subjoined, Vowel, Vowel_Dependent]))
def is_BASE_VOWEL(U, UISC, UGC):
return UISC == Vowel_Independent
def is_BASE_IND(U, UISC, UGC):
#SPEC-BROKEN return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
return (UISC in [Consonant_Dead, Modifying_Letter] or
(UGC == Po and not is_BASE_OTHER(U, UISC, UGC))) # for 104E
def is_BASE_NUM(U, UISC, UGC):
return UISC == Brahmi_Joining_Number
def is_BASE_OTHER(U, UISC, UGC):
if UISC == Consonant_Placeholder: return True #SPEC-OUTDATED
return U in [0x00A0, 0x00D7, 0x2015, 0x2022, 0x25CC,
0x25FB, 0x25FC, 0x25FD, 0x25FE]
def is_CGJ(U, UISC, UGC):
return U == 0x034F
def is_CONS_FINAL(U, UISC, UGC):
return ((UISC == Consonant_Final and UGC != Lo) or
UISC == Consonant_Succeeding_Repha)
def is_CONS_FINAL_MOD(U, UISC, UGC):
#SPEC-OUTDATED return UISC in [Consonant_Final_Modifier, Syllable_Modifier]
return UISC == Syllable_Modifier
def is_CONS_MED(U, UISC, UGC):
return UISC == Consonant_Medial and UGC != Lo
def is_CONS_MOD(U, UISC, UGC):
return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
def is_CONS_SUB(U, UISC, UGC):
#SPEC-OUTDATED return UISC == Consonant_Subjoined
return UISC == Consonant_Subjoined and UGC != Lo
def is_HALANT(U, UISC, UGC):
return UISC in [Virama, Invisible_Stacker]
def is_HALANT_NUM(U, UISC, UGC):
return UISC == Number_Joiner
def is_ZWNJ(U, UISC, UGC):
return UISC == Non_Joiner
def is_ZWJ(U, UISC, UGC):
return UISC == Joiner
def is_Word_Joiner(U, UISC, UGC):
return U == 0x2060
def is_OTHER(U, UISC, UGC):
#SPEC-OUTDATED return UGC == Zs # or any other SCRIPT_COMMON characters
return (UISC == Other
and not is_SYM_MOD(U, UISC, UGC)
and not is_CGJ(U, UISC, UGC)
and not is_Word_Joiner(U, UISC, UGC)
and not is_VARIATION_SELECTOR(U, UISC, UGC)
)
def is_Reserved(U, UISC, UGC):
return UGC == 'Cn'
def is_REPHA(U, UISC, UGC):
#return UISC == Consonant_Preceding_Repha
#SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed
return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed]
def is_SYM(U, UISC, UGC):
if U == 0x25CC: return False #SPEC-OUTDATED
#SPEC-OUTDATED return UGC in [So, Sc] or UISC == Symbol_Letter
return UGC in [So, Sc]
def is_SYM_MOD(U, UISC, UGC):
return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
def is_VARIATION_SELECTOR(U, UISC, UGC):
return 0xFE00 <= U <= 0xFE0F
def is_VOWEL(U, UISC, UGC):
return (UISC == Pure_Killer or
(UGC != Lo and UISC in [Vowel, Vowel_Dependent]))
def is_VOWEL_MOD(U, UISC, UGC):
return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
(UGC != Lo and UISC == Bindu))
use_mapping = {
'B': is_BASE,
'IV': is_BASE_VOWEL,
'IND': is_BASE_IND,
'N': is_BASE_NUM,
'GB': is_BASE_OTHER,
'CGJ': is_CGJ,
'F': is_CONS_FINAL,
'FM': is_CONS_FINAL_MOD,
'M': is_CONS_MED,
'CM': is_CONS_MOD,
'SUB': is_CONS_SUB,
'H': is_HALANT,
'HN': is_HALANT_NUM,
'ZWNJ': is_ZWNJ,
'ZWJ': is_ZWJ,
'WJ': is_Word_Joiner,
'O': is_OTHER,
'Rsv': is_Reserved,
'R': is_REPHA,
'S': is_SYM,
'SM': is_SYM_MOD,
'VS': is_VARIATION_SELECTOR,
'V': is_VOWEL,
'VM': is_VOWEL_MOD,
}
use_positions = {
'F': {
'Abv': [Top],
'Blw': [Bottom],
'Pst': [Right],
},
'M': {
'Abv': [Top],
'Blw': [Bottom],
'Pst': [Right],
'Pre': [Left],
},
'CM': {
'Abv': [Top],
'Blw': [Bottom],
},
'V': {
'Abv': [Top, Top_And_Bottom, Top_And_Bottom_And_Right, Top_And_Right],
'Blw': [Bottom, Overstruck, Bottom_And_Right],
'Pst': [Right],
'Pre': [Left, Top_And_Left, Top_And_Left_And_Right, Left_And_Right],
},
'VM': {
'Abv': [Top],
'Blw': [Bottom, Overstruck],
'Pst': [Right],
'Pre': [Left],
},
'SM': {
'Abv': [Top],
'Blw': [Bottom],
},
'H': None,
'B': None,
'FM': None,
'SUB': None,
}
def map_to_use(data):
out = {}
items = use_mapping.items()
for U,(UISC,UIPC,UGC,UBlock) in data.items():
# Resolve Indic_Syllabic_Category
# TODO: These don't have UISC assigned in Unicode 8.0, but
# have UIPC
if U == 0x17DD: UISC = Vowel_Dependent
if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
# TODO: U+1CED should only be allowed after some of
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
if U == 0x1CED: UISC = Tone_Mark
evals = [(k, v(U,UISC,UGC)) for k,v in items]
values = [k for k,v in evals if v]
assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
USE = values[0]
# Resolve Indic_Positional_Category
# TODO: Not in Unicode 8.0 yet, but in spec.
if U == 0x1B6C: UIPC = Bottom
# TODO: These should die, but have UIPC in Unicode 8.0
if U in [0x953, 0x954]: UIPC = Not_Applicable
# TODO: In USE's override list but not in Unicode 8.0
if U == 0x103C: UIPC = Left
# TODO: These are not in USE's override list that we have, nor are they in Unicode 8.0
if 0xA926 <= U <= 0xA92A: UIPC = Top
if U == 0x111CA: UIPC = Bottom
if U == 0x11300: UIPC = Top
if U == 0x1133C: UIPC = Bottom
if U == 0x1171E: UIPC = Left # Correct?!
if 0x1CF2 <= U <= 0x1CF3: UIPC = Right
if 0x1CF8 <= U <= 0x1CF9: 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)
pos_mapping = use_positions.get(USE, None)
if pos_mapping:
values = [k for k,v in pos_mapping.items() if v and UIPC in v]
assert len(values) == 1, "%s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC, values)
USE = USE + values[0]
out[U] = (USE, UBlock)
return out
defaults = ('O', 'No_Block')
data = map_to_use(data)
# Remove the outliers
singles = {}
for u in [0x034F, 0x25CC, 0x1107F]:
singles[u] = data[u]
del data[u]
print "/* == Start of generated table == */"
print "/*"
print " * The following table is generated by running:"
print " *"
print " * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt"
print " *"
print " * on files with these headers:"
print " *"
for h in headers:
for l in h:
print " * %s" % (l.strip())
print " */"
print
print '#include "hb-ot-shape-complex-use-private.hh"'
print
total = 0
used = 0
last_block = None
def print_block (block, start, end, data):
global total, used, last_block
if block and block != last_block:
print
print
print " /* %s */" % block
if start % 16:
print ' ' * (20 + (start % 16 * 6)),
num = 0
assert start % 8 == 0
assert (end+1) % 8 == 0
for u in range (start, end+1):
if u % 16 == 0:
print
print " /* %04X */" % u,
if u in data:
num += 1
d = data.get (u, defaults)
sys.stdout.write ("%6s," % d[0])
total += end - start + 1
used += num
if block:
last_block = block
uu = data.keys ()
uu.sort ()
last = -100000
num = 0
offset = 0
starts = []
ends = []
for k,v in sorted(use_mapping.items()):
if k in use_positions and use_positions[k]: continue
print "#define %s USE_%s /* %s */" % (k, k, v.__name__[3:])
for k,v in sorted(use_positions.items()):
if not v: continue
for suf in v.keys():
tag = k + suf
print "#define %s USE_%s" % (tag, tag)
print ""
print "static const USE_TABLE_ELEMENT_TYPE use_table[] = {"
for u in uu:
if u <= last:
continue
block = data[u][1]
start = u//8*8
end = start+1
while end in uu and block == data[end][1]:
end += 1
end = (end-1)//8*8 + 7
if start != last + 1:
if start - last <= 1+16*3:
print_block (None, last+1, start-1, data)
last = start-1
else:
if last >= 0:
ends.append (last + 1)
offset += ends[-1] - starts[-1]
print
print
print "#define use_offset_0x%04xu %d" % (start, offset)
starts.append (start)
print_block (block, start, end, data)
last = end
ends.append (last + 1)
offset += ends[-1] - starts[-1]
print
print
occupancy = used * 100. / total
page_bits = 12
print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
print
print "USE_TABLE_ELEMENT_TYPE"
print "hb_use_get_categories (hb_codepoint_t u)"
print "{"
print " switch (u >> %d)" % page_bits
print " {"
pages = set([u>>page_bits for u in starts+ends+singles.keys()])
for p in sorted(pages):
print " case 0x%0Xu:" % p
for (start,end) in zip (starts, ends):
if p not in [start>>page_bits, end>>page_bits]: continue
offset = "use_offset_0x%04xu" % start
print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
for u,d in singles.items ():
if p != u>>page_bits: continue
print " if (unlikely (u == 0x%04Xu)) return %s;" % (u, d[0])
print " break;"
print ""
print " default:"
print " break;"
print " }"
print " return USE_O;"
print "}"
print
for k in sorted(use_mapping.keys()):
if k in use_positions and use_positions[k]: continue
print "#undef %s" % k
for k,v in sorted(use_positions.items()):
if not v: continue
for suf in v.keys():
tag = k + suf
print "#undef %s" % tag
print
print "/* == End of generated table == */"
# Maintain at least 50% occupancy in the table */
if occupancy < 50:
raise Exception ("Table too sparse, please investigate: ", occupancy)

View File

@ -0,0 +1,13 @@
prefix=/usr/local
exec_prefix=/usr/local
libdir=/usr/local/lib
includedir=/usr/local/include
Name: harfbuzz
Description: HarfBuzz text shaping library ICU integration
Version: 1.0.1
Requires: harfbuzz
Requires.private: icu-uc
Libs: -L${libdir} -lharfbuzz-icu
Cflags: -I${includedir}/harfbuzz

View File

@ -0,0 +1,11 @@
prefix=/usr/local
exec_prefix=/usr/local
libdir=/usr/local/lib
includedir=/usr/local/include
Name: harfbuzz
Description: HarfBuzz text shaping library
Version: 1.0.1
Libs: -L${libdir} -lharfbuzz
Cflags: -I${includedir}/harfbuzz

View File

@ -50,6 +50,7 @@ struct hb_buffer_t {
/* Information about how the text in the buffer should be treated */
hb_unicode_funcs_t *unicode; /* Unicode functions */
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
hb_buffer_cluster_level_t cluster_level;
hb_codepoint_t replacement; /* U+FFFD or something else. */
/* Buffer contents */
@ -171,9 +172,18 @@ struct hb_buffer_t {
unsigned int cluster_end);
HB_INTERNAL void merge_clusters (unsigned int start,
unsigned int end);
unsigned int end)
{
if (end - start < 2)
return;
merge_clusters_impl (start, end);
}
HB_INTERNAL void merge_clusters_impl (unsigned int start,
unsigned int end);
HB_INTERNAL void merge_out_clusters (unsigned int start,
unsigned int end);
/* Merge clusters for deleting current glyph, and skip it. */
HB_INTERNAL void delete_glyph (void);
/* Internal methods */
HB_INTERNAL bool enlarge (unsigned int size);

View File

@ -36,6 +36,9 @@
#endif
/**
* Since: 0.9.7
**/
hb_bool_t
hb_segment_properties_equal (const hb_segment_properties_t *a,
const hb_segment_properties_t *b)
@ -48,6 +51,9 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
}
/**
* Since: 0.9.7
**/
unsigned int
hb_segment_properties_hash (const hb_segment_properties_t *p)
{
@ -498,14 +504,10 @@ hb_buffer_t::reverse_clusters (void)
}
void
hb_buffer_t::merge_clusters (unsigned int start,
unsigned int end)
hb_buffer_t::merge_clusters_impl (unsigned int start,
unsigned int end)
{
#ifdef HB_NO_MERGE_CLUSTERS
return;
#endif
if (unlikely (end - start < 2))
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
return;
unsigned int cluster = info[start].cluster;
@ -523,7 +525,7 @@ hb_buffer_t::merge_clusters (unsigned int start,
/* If we hit the start of buffer, continue in out-buffer. */
if (idx == start)
for (unsigned i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
out_info[i - 1].cluster = cluster;
for (unsigned int i = start; i < end; i++)
@ -533,9 +535,8 @@ void
hb_buffer_t::merge_out_clusters (unsigned int start,
unsigned int end)
{
#ifdef HB_NO_MERGE_CLUSTERS
return;
#endif
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
return;
if (unlikely (end - start < 2))
return;
@ -555,12 +556,44 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
/* If we hit the end of out-buffer, continue in buffer. */
if (end == out_len)
for (unsigned i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
info[i].cluster = cluster;
for (unsigned int i = start; i < end; i++)
out_info[i].cluster = cluster;
}
void
hb_buffer_t::delete_glyph ()
{
unsigned int cluster = info[idx].cluster;
if (idx + 1 < len && cluster == info[idx + 1].cluster)
{
/* Cluster survives; do nothing. */
goto done;
}
if (out_len)
{
/* Merge cluster backward. */
if (cluster < out_info[out_len - 1].cluster)
{
unsigned int old_cluster = out_info[out_len - 1].cluster;
for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
out_info[i - 1].cluster = cluster;
}
goto done;
}
if (idx + 1 < len)
{
/* Merge cluster forward. */
merge_clusters (idx, idx + 2);
goto done;
}
done:
skip_glyph ();
}
void
hb_buffer_t::guess_segment_properties (void)
@ -703,6 +736,7 @@ hb_buffer_get_empty (void)
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_CONTENT_TYPE_INVALID,
@ -804,7 +838,7 @@ hb_buffer_get_user_data (hb_buffer_t *buffer,
*
*
*
* Since: 1.0
* Since: 0.9.5
**/
void
hb_buffer_set_content_type (hb_buffer_t *buffer,
@ -821,7 +855,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.5
**/
hb_buffer_content_type_t
hb_buffer_get_content_type (hb_buffer_t *buffer)
@ -984,7 +1018,7 @@ hb_buffer_get_language (hb_buffer_t *buffer)
*
*
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_buffer_set_segment_properties (hb_buffer_t *buffer,
@ -1003,7 +1037,7 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer,
*
*
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_buffer_get_segment_properties (hb_buffer_t *buffer,
@ -1020,7 +1054,7 @@ hb_buffer_get_segment_properties (hb_buffer_t *buffer,
*
*
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_buffer_set_flags (hb_buffer_t *buffer,
@ -1040,7 +1074,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.7
**/
hb_buffer_flags_t
hb_buffer_get_flags (hb_buffer_t *buffer)
@ -1048,6 +1082,41 @@ hb_buffer_get_flags (hb_buffer_t *buffer)
return buffer->flags;
}
/**
* hb_buffer_set_cluster_level:
* @buffer: a buffer.
* @cluster_level:
*
*
*
* Since: 0.9.42
**/
void
hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level)
{
if (unlikely (hb_object_is_inert (buffer)))
return;
buffer->cluster_level = cluster_level;
}
/**
* hb_buffer_get_cluster_level:
* @buffer: a buffer.
*
*
*
* Return value:
*
* Since: 0.9.42
**/
hb_buffer_cluster_level_t
hb_buffer_get_cluster_level (hb_buffer_t *buffer)
{
return buffer->cluster_level;
}
/**
* hb_buffer_set_replacement_codepoint:
@ -1056,7 +1125,7 @@ hb_buffer_get_flags (hb_buffer_t *buffer)
*
*
*
* Since: 1.0
* Since: 0.9.31
**/
void
hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
@ -1076,7 +1145,7 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.31
**/
hb_codepoint_t
hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
@ -1105,7 +1174,7 @@ hb_buffer_reset (hb_buffer_t *buffer)
*
*
*
* Since: 1.0
* Since: 0.9.11
**/
void
hb_buffer_clear_contents (hb_buffer_t *buffer)
@ -1282,6 +1351,23 @@ hb_buffer_reverse (hb_buffer_t *buffer)
buffer->reverse ();
}
/**
* hb_buffer_reverse_range:
* @buffer: a buffer.
* @start: start index.
* @end: end index.
*
* Reverses buffer contents between start to end.
*
* Since: 1.0
**/
void
hb_buffer_reverse_range (hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
buffer->reverse_range (start, end);
}
/**
* hb_buffer_reverse_clusters:
* @buffer: a buffer.
@ -1320,7 +1406,7 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
* hb_language_get_default(). This may change in the future by
* taking buffer script into consideration when choosing a language.
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
@ -1473,7 +1559,7 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
*
*
*
* Since: 1.0
* Since: 0.9.39
**/
void
hb_buffer_add_latin1 (hb_buffer_t *buffer,
@ -1495,7 +1581,7 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer,
*
*
*
* Since: 1.0
* Since: 0.9.31
**/
void
hb_buffer_add_codepoints (hb_buffer_t *buffer,
@ -1569,7 +1655,7 @@ normalize_glyphs_cluster (hb_buffer_t *buffer,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_buffer_normalize_glyphs (hb_buffer_t *buffer)

View File

@ -185,7 +185,19 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t
hb_buffer_get_flags (hb_buffer_t *buffer);
typedef enum {
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0,
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1,
HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2,
HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
} hb_buffer_cluster_level_t;
void
hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level);
hb_buffer_cluster_level_t
hb_buffer_get_cluster_level (hb_buffer_t *buffer);
#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
@ -221,6 +233,10 @@ hb_buffer_allocation_successful (hb_buffer_t *buffer);
void
hb_buffer_reverse (hb_buffer_t *buffer);
void
hb_buffer_reverse_range (hb_buffer_t *buffer,
unsigned int start, unsigned int end);
void
hb_buffer_reverse_clusters (hb_buffer_t *buffer);

View File

@ -92,7 +92,7 @@ hb_tag_from_string (const char *str, int len)
*
*
*
* Since: 1.0
* Since: 0.9.5
**/
void
hb_tag_to_string (hb_tag_t tag, char *buf)
@ -334,7 +334,7 @@ hb_language_to_string (hb_language_t language)
*
*
*
* Return value:
* Return value: (transfer none):
*
* Since: 1.0
**/
@ -493,6 +493,9 @@ hb_script_get_horizontal_direction (hb_script_t script)
case HB_SCRIPT_PALMYRENE:
case HB_SCRIPT_PSALTER_PAHLAVI:
/* Unicode-8.0 additions */
case HB_SCRIPT_OLD_HUNGARIAN:
return HB_DIRECTION_RTL;
}
@ -579,7 +582,7 @@ hb_version_string (void)
*
* Return value:
*
* Since: 1.0
* Since: 0.9.30
**/
hb_bool_t
hb_version_atleast (unsigned int major,

View File

@ -296,12 +296,12 @@ typedef enum
/*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'),
/*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'),
/*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'),
/*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'),
/*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'),
/*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'),
/*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'),
/*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'),
/*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'),
/*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'),
/*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'),
/*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'),
/*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'),
/*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'),
/* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE,

View File

@ -347,7 +347,7 @@ hb_face_reference_table (hb_face_t *face,
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.2
**/
hb_blob_t *
hb_face_reference_blob (hb_face_t *face)
@ -362,7 +362,7 @@ hb_face_reference_blob (hb_face_t *face)
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_face_set_index (hb_face_t *face,
@ -382,7 +382,7 @@ hb_face_set_index (hb_face_t *face,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
unsigned int
hb_face_get_index (hb_face_t *face)
@ -397,7 +397,7 @@ hb_face_get_index (hb_face_t *face)
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_face_set_upem (hb_face_t *face,
@ -441,7 +441,7 @@ hb_face_t::load_upem (void) const
*
*
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_face_set_glyph_count (hb_face_t *face,
@ -461,7 +461,7 @@ hb_face_set_glyph_count (hb_face_t *face,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.7
**/
unsigned int
hb_face_get_glyph_count (hb_face_t *face)

View File

@ -604,7 +604,7 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_font_get_glyph_name (hb_font_t *font,
@ -625,7 +625,7 @@ hb_font_get_glyph_name (hb_font_t *font,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_font_get_glyph_from_name (hb_font_t *font,
@ -800,7 +800,7 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_font_glyph_to_string (hb_font_t *font,
@ -822,7 +822,7 @@ hb_font_glyph_to_string (hb_font_t *font,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_font_glyph_from_string (hb_font_t *font,
@ -1078,7 +1078,7 @@ hb_font_get_parent (hb_font_t *font)
*
* Return value: (transfer none):
*
* Since: 1.0
* Since: 0.9.2
**/
hb_face_t *
hb_font_get_face (hb_font_t *font)
@ -1096,7 +1096,7 @@ hb_font_get_face (hb_font_t *font)
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_font_set_funcs (hb_font_t *font,
@ -1131,7 +1131,7 @@ hb_font_set_funcs (hb_font_t *font,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_font_set_funcs_data (hb_font_t *font,

View File

@ -292,7 +292,7 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
@ -308,7 +308,7 @@ hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,

View File

@ -75,15 +75,19 @@ hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
unsigned int g;
FT_Face ft_face = (FT_Face) font_data;
if (unlikely (variation_selector)) {
*glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
return *glyph != 0;
}
if (likely (!variation_selector))
g = FT_Get_Char_Index (ft_face, unicode);
else
g = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
*glyph = FT_Get_Char_Index (ft_face, unicode);
return *glyph != 0;
if (unlikely (!g))
return false;
*glyph = g;
return true;
}
static hb_position_t
@ -377,7 +381,7 @@ hb_ft_face_create (FT_Face ft_face,
*
*
* Return value: (transfer full):
* Since: 1.0
* Since: 0.9.38
**/
hb_face_t *
hb_ft_face_create_referenced (FT_Face ft_face)
@ -464,7 +468,7 @@ hb_ft_font_create (FT_Face ft_face,
*
*
* Return value: (transfer full):
* Since: 1.0
* Since: 0.9.38
**/
hb_font_t *
hb_ft_font_create_referenced (FT_Face ft_face)

View File

@ -382,6 +382,9 @@ hb_glib_get_unicode_funcs (void)
return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
}
/**
* Since: 0.9.38
**/
hb_blob_t *
hb_glib_blob_create (GBytes *gbytes)
{

View File

@ -54,6 +54,17 @@ hb_gobject_##name##_get_type (void) \
#define HB_DEFINE_OBJECT_TYPE(name) \
HB_DEFINE_BOXED_TYPE (name, hb_##name##_reference, hb_##name##_destroy);
#define HB_DEFINE_VALUE_TYPE(name) \
static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
{ \
hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \
if (unlikely (!c)) return NULL; \
*c = *l; \
return c; \
} \
static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \
HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy);
HB_DEFINE_OBJECT_TYPE (buffer)
HB_DEFINE_OBJECT_TYPE (blob)
HB_DEFINE_OBJECT_TYPE (face)
@ -62,59 +73,8 @@ HB_DEFINE_OBJECT_TYPE (font_funcs)
HB_DEFINE_OBJECT_TYPE (set)
HB_DEFINE_OBJECT_TYPE (shape_plan)
HB_DEFINE_OBJECT_TYPE (unicode_funcs)
static hb_feature_t *feature_reference (hb_feature_t *g)
{
hb_feature_t *c = (hb_feature_t *) calloc (1, sizeof (hb_feature_t));
if (unlikely (!c)) return NULL;
*c = *g;
return c;
}
static void feature_destroy (hb_feature_t *g) { free (g); }
HB_DEFINE_BOXED_TYPE (feature, feature_reference, feature_destroy)
static hb_glyph_info_t *glyph_info_reference (hb_glyph_info_t *g)
{
hb_glyph_info_t *c = (hb_glyph_info_t *) calloc (1, sizeof (hb_glyph_info_t));
if (unlikely (!c)) return NULL;
*c = *g;
return c;
}
static void glyph_info_destroy (hb_glyph_info_t *g) { free (g); }
HB_DEFINE_BOXED_TYPE (glyph_info, glyph_info_reference, glyph_info_destroy)
static hb_glyph_position_t *glyph_position_reference (hb_glyph_position_t *g)
{
hb_glyph_position_t *c = (hb_glyph_position_t *) calloc (1, sizeof (hb_glyph_position_t));
if (unlikely (!c)) return NULL;
*c = *g;
return c;
}
static void glyph_position_destroy (hb_glyph_position_t *g) { free (g); }
HB_DEFINE_BOXED_TYPE (glyph_position, glyph_position_reference, glyph_position_destroy)
static hb_segment_properties_t *segment_properties_reference (hb_segment_properties_t *g)
{
hb_segment_properties_t *c = (hb_segment_properties_t *) calloc (1, sizeof (hb_segment_properties_t));
if (unlikely (!c)) return NULL;
*c = *g;
return c;
}
static void segment_properties_destroy (hb_segment_properties_t *g) { free (g); }
HB_DEFINE_BOXED_TYPE (segment_properties, segment_properties_reference, segment_properties_destroy)
static hb_user_data_key_t user_data_key_reference (hb_user_data_key_t l) { return l; }
static void user_data_key_destroy (hb_user_data_key_t l) { }
HB_DEFINE_BOXED_TYPE (user_data_key, user_data_key_reference, user_data_key_destroy)
static hb_language_t *language_reference (hb_language_t *l)
{
hb_language_t *c = (hb_language_t *) calloc (1, sizeof (hb_language_t));
if (unlikely (!c)) return NULL;
*c = *l;
return c;
}
static void language_destroy (hb_language_t *l) { free (l); }
HB_DEFINE_BOXED_TYPE (language, language_reference, language_destroy)
HB_DEFINE_VALUE_TYPE (feature)
HB_DEFINE_VALUE_TYPE (glyph_info)
HB_DEFINE_VALUE_TYPE (glyph_position)
HB_DEFINE_VALUE_TYPE (segment_properties)
HB_DEFINE_VALUE_TYPE (user_data_key)

View File

@ -40,18 +40,33 @@ HB_BEGIN_DECLS
/* Object types */
/**
* Since: 0.9.2
**/
GType hb_gobject_blob_get_type (void);
#define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ())
/**
* Since: 0.9.2
**/
GType hb_gobject_buffer_get_type (void);
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
/**
* Since: 0.9.2
**/
GType hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
/**
* Since: 0.9.2
**/
GType hb_gobject_font_get_type (void);
#define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ())
/**
* Since: 0.9.2
**/
GType hb_gobject_font_funcs_get_type (void);
#define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ())
@ -61,6 +76,9 @@ GType hb_gobject_set_get_type (void);
GType hb_gobject_shape_plan_get_type (void);
#define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())
/**
* Since: 0.9.2
**/
GType hb_gobject_unicode_funcs_get_type (void);
#define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ())
@ -81,14 +99,6 @@ GType hb_gobject_segment_properties_get_type (void);
GType hb_gobject_user_data_key_get_type (void);
#define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ())
/* Currently gobject-introspection doesn't understand that hb_language_t
* can be passed by-value. As such we box it up. May remove in the
* future.
*
* https://bugzilla.gnome.org/show_bug.cgi?id=707656
*/
GType hb_gobject_language_get_type (void);
#define HB_GOBJECT_TYPE_LANGUAGE (hb_gobject_language_get_type ())
HB_END_DECLS

View File

@ -228,12 +228,11 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
int lang_len = lang_end ? lang_end - lang : -1;
gr_feature_val *feats = gr_face_featureval_for_lang (grface, lang ? hb_tag_from_string (lang, lang_len) : 0);
while (num_features--)
for (unsigned int i = 0; i < num_features; i++)
{
const gr_feature_ref *fref = gr_face_find_fref (grface, features->tag);
const gr_feature_ref *fref = gr_face_find_fref (grface, features[i].tag);
if (fref)
gr_fref_set_feature_value (fref, features->value, feats);
features++;
gr_fref_set_feature_value (fref, features[i].value, feats);
}
gr_segment *seg = NULL;
@ -249,6 +248,8 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
for (unsigned int i = 0; i < buffer->len; ++i)
chars[i] = buffer->info[i].codepoint;
/* TODO ensure_native_direction. */
hb_tag_t script_tag[2];
hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
@ -267,9 +268,11 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
if (unlikely (!glyph_count)) {
if (feats) gr_featureval_destroy (feats);
gr_seg_destroy (seg);
return false;
buffer->len = 0;
return true;
}
buffer->ensure (glyph_count);
scratch = buffer->get_scratch_buffer (&scratch_size);
while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) +
DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size)
@ -331,7 +334,6 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
}
ci++;
//buffer->clear_output ();
for (unsigned int i = 0; i < ci; ++i)
{
for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j)
@ -342,32 +344,57 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
}
}
buffer->len = glyph_count;
//buffer->swap_buffers ();
if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
curradvx = gr_seg_advance_X(seg);
hb_glyph_position_t *pPos;
for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg);
is; pPos++, is = gr_slot_next_in_segment (is))
/* Positioning. */
if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
{
pPos->x_offset = gr_slot_origin_X (is) - curradvx;
pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
pPos->x_advance = gr_slot_advance_X (is, grface, grfont);
pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
curradvx -= pPos->x_advance;
pPos->x_offset = gr_slot_origin_X (is) - curradvx;
if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
hb_glyph_position_t *pPos;
for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg);
is; pPos++, is = gr_slot_next_in_segment (is))
{
pPos->x_offset = gr_slot_origin_X (is) - curradvx;
pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
pPos->x_advance = gr_slot_advance_X (is, grface, grfont);
pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
curradvx += pPos->x_advance;
pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
curradvy += pPos->y_advance;
}
if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
curradvy += pPos->y_advance;
}
pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx;
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
}
else
{
hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL) + buffer->len - 1;
const hb_glyph_info_t *info = buffer->info + buffer->len - 1;
const hb_glyph_info_t *tinfo;
const gr_slot *tis;
int currclus = -1;
float clusx = 0., clusy = 0.;
for (is = gr_seg_last_slot (seg); is; pPos--, info--, is = gr_slot_prev_in_segment (is))
{
if (info->cluster != currclus)
{
curradvx += clusx;
curradvy += clusy;
currclus = info->cluster;
clusx = 0.;
clusy = 0.;
for (tis = is, tinfo = info; tis && tinfo->cluster == currclus; tis = gr_slot_prev_in_segment (tis), tinfo--)
{
clusx += gr_slot_advance_X (tis, grface, grfont);
clusy += gr_slot_advance_Y (tis, grface, grfont);
}
curradvx += clusx;
curradvy += clusy;
}
pPos->x_advance = gr_slot_advance_X (is, grface, grfont);
pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
curradvx -= pPos->x_advance;
curradvy -= pPos->y_advance;
pPos->x_offset = gr_slot_origin_X (is) - curradvx;
pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
}
hb_buffer_reverse_clusters (buffer);
}
if (feats) gr_featureval_destroy (feats);
gr_seg_destroy (seg);

View File

@ -220,7 +220,7 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph));
return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph));
}
static hb_bool_t
@ -335,6 +335,9 @@ _hb_ot_get_font_funcs (void)
}
/**
* Since: 0.9.28
**/
void
hb_ot_font_set_funcs (hb_font_t *font)
{

View File

@ -24,6 +24,10 @@
* Google Author(s): Behdad Esfahbod, Roozbeh Pournader
*/
#ifndef HB_OT_H_IN
#error "Include <hb-ot.h> instead."
#endif
#ifndef HB_OT_FONT_H
#define HB_OT_FONT_H

View File

@ -328,8 +328,7 @@ struct hb_apply_context_t
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
(ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
(ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
!_hb_glyph_info_ligated (&info)))
(ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
return SKIP_MAYBE;
return SKIP_NO;
@ -720,7 +719,7 @@ static inline bool match_input (hb_apply_context_t *c,
{
TRACE_APPLY (NULL);
if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false);
if (unlikely (count > MAX_CONTEXT_LENGTH)) return TRACE_RETURN (false);
hb_buffer_t *buffer = c->buffer;
@ -2165,7 +2164,7 @@ struct ExtensionFormat1
{
TRACE_DISPATCH (this, format);
if (unlikely (!c->may_dispatch (this, this))) TRACE_RETURN (c->default_return_value ());
return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
return TRACE_RETURN (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
}
/* This is called from may_dispatch() above with hb_sanitize_context_t. */

View File

@ -36,6 +36,15 @@
#include "hb-set-private.hh"
/* Private API corresponding to hb-ot-layout.h: */
HB_INTERNAL hb_bool_t
hb_ot_layout_table_find_feature (hb_face_t *face,
hb_tag_t table_tag,
hb_tag_t feature_tag,
unsigned int *feature_index);
/*
* GDEF
*/
@ -179,6 +188,30 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
#define lig_props() var1.u8[2] /* GSUB/GPOS ligature tracking */
#define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */
/* loop over syllables */
#define foreach_syllable(buffer, start, end) \
for (unsigned int \
_count = buffer->len, \
start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \
start < _count; \
start = end, end = _next_syllable (buffer, start))
static inline unsigned int
_next_syllable (hb_buffer_t *buffer, unsigned int start)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
unsigned int syllable = info[start].syllable();
while (++start < count && syllable == info[start].syllable())
;
return start;
}
/* unicode_props */
enum {
@ -225,10 +258,12 @@ _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
return info->unicode_props1();
}
static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
static inline hb_bool_t
_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
{
return !!(info->unicode_props0() & MASK0_IGNORABLE);
return (info->unicode_props0() & MASK0_IGNORABLE) && !_hb_glyph_info_ligated (info);
}
static inline hb_bool_t
@ -406,6 +441,14 @@ _hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
}
static inline void
_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (hb_glyph_info_t *info)
{
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
}
/* Allocation / deallocation. */

View File

@ -128,6 +128,9 @@ hb_ot_layout_has_glyph_classes (hb_face_t *face)
return _get_gdef (face).has_glyph_classes ();
}
/**
* Since: 0.9.7
**/
hb_ot_layout_glyph_class_t
hb_ot_layout_get_glyph_class (hb_face_t *face,
hb_codepoint_t glyph)
@ -135,6 +138,9 @@ hb_ot_layout_get_glyph_class (hb_face_t *face,
return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
}
/**
* Since: 0.9.7
**/
void
hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
hb_ot_layout_glyph_class_t klass,
@ -285,6 +291,28 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
return g.get_feature_tags (start_offset, feature_count, feature_tags);
}
hb_bool_t
hb_ot_layout_table_find_feature (hb_face_t *face,
hb_tag_t table_tag,
hb_tag_t feature_tag,
unsigned int *feature_index)
{
ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
unsigned int num_features = g.get_feature_count ();
for (unsigned int i = 0; i < num_features; i++)
{
if (feature_tag == g.get_feature_tag (i)) {
if (feature_index) *feature_index = i;
return true;
}
}
if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
return false;
}
unsigned int
hb_ot_layout_script_get_language_tags (hb_face_t *face,
@ -335,6 +363,9 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
NULL);
}
/**
* Since: 0.9.30
**/
hb_bool_t
hb_ot_layout_language_get_required_feature (hb_face_t *face,
hb_tag_t table_tag,
@ -419,6 +450,9 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
return false;
}
/**
* Since: 0.9.7
**/
unsigned int
hb_ot_layout_feature_get_lookups (hb_face_t *face,
hb_tag_t table_tag,
@ -433,6 +467,9 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
}
/**
* Since: 0.9.22
**/
unsigned int
hb_ot_layout_table_get_lookup_count (hb_face_t *face,
hb_tag_t table_tag)
@ -590,6 +627,9 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face,
}
}
/**
* Since: 0.9.8
**/
void
hb_ot_layout_collect_lookups (hb_face_t *face,
hb_tag_t table_tag,
@ -631,6 +671,9 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
}
}
/**
* Since: 0.9.7
**/
void
hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
hb_tag_t table_tag,
@ -676,6 +719,9 @@ hb_ot_layout_has_substitution (hb_face_t *face)
return &_get_gsub (face) != &OT::Null(OT::GSUB);
}
/**
* Since: 0.9.7
**/
hb_bool_t
hb_ot_layout_lookup_would_substitute (hb_face_t *face,
unsigned int lookup_index,
@ -714,6 +760,9 @@ hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
OT::GSUB::substitute_finish (font, buffer);
}
/**
* Since: 0.9.7
**/
void
hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
unsigned int lookup_index,
@ -748,6 +797,9 @@ hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
OT::GPOS::position_finish (font, buffer);
}
/**
* Since: 0.9.8
**/
hb_bool_t
hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *design_size, /* OUT. May be NULL */
@ -875,7 +927,7 @@ apply_backward (OT::hb_apply_context_t *c,
struct hb_apply_forward_context_t
{
inline const char *get_name (void) { return "APPLY_FORWARD"; }
inline const char *get_name (void) { return "APPLY_FWD"; }
static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
typedef bool return_t;
template <typename T, typename F>

View File

@ -154,9 +154,10 @@ struct hb_ot_map_t
enum hb_ot_map_feature_flags_t {
F_NONE = 0x0000u,
F_GLOBAL = 0x0001u,
F_HAS_FALLBACK = 0x0002u,
F_MANUAL_ZWJ = 0x0004u
F_GLOBAL = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */
F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */
};
/* Macro version for where const is desired. */
#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))

View File

@ -216,6 +216,16 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
info->tag,
&feature_index[table_index]);
}
if (!found && (info->flags & F_GLOBAL_SEARCH))
{
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
found |= hb_ot_layout_table_find_feature (face,
table_tags[table_index],
info->tag,
&feature_index[table_index]);
}
}
if (!found && !(info->flags & F_HAS_FALLBACK))
continue;

View File

@ -0,0 +1,50 @@
/*
* Copyright © 2015 Mozilla Foundation.
* Copyright © 2015 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.
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
#define HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
#include "hb-private.hh"
#include "hb-ot-shape-complex-private.hh"
struct arabic_shape_plan_t;
HB_INTERNAL void *
data_create_arabic (const hb_ot_shape_plan_t *plan);
HB_INTERNAL void
data_destroy_arabic (void *data);
HB_INTERNAL void
setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
hb_buffer_t *buffer,
hb_script_t script);
#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH */

View File

@ -6,10 +6,10 @@
*
* on files with these headers:
*
* # ArabicShaping-7.0.0.txt
* # Date: 2014-02-14, 21:00:00 GMT [RP, KW, LI]
* # Blocks-7.0.0.txt
* # Date: 2014-04-03, 23:23:00 GMT [RP, KW]
* # ArabicShaping-8.0.0.txt
* # Date: 2015-02-17, 23:33:00 GMT [RP]
* # Blocks-8.0.0.txt
* # Date: 2014-11-10, 23:04:00 GMT [KW]
* UnicodeData.txt does not have a header.
*/
@ -76,9 +76,9 @@ static const uint8_t joining_table[] =
/* Arabic Extended-A */
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,
#define joining_offset_0x1806u 691
#define joining_offset_0x1806u 693
/* Mongolian */
@ -89,40 +89,40 @@ static const uint8_t joining_table[] =
/* 1880 */ U,U,U,U,U,U,U,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
#define joining_offset_0x200cu 856
#define joining_offset_0x200cu 858
/* General Punctuation */
/* 2000 */ U,C,
#define joining_offset_0x2066u 858
#define joining_offset_0x2066u 860
/* General Punctuation */
/* 2060 */ U,U,U,U,
#define joining_offset_0xa840u 862
#define joining_offset_0xa840u 864
/* Phags-pa */
/* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U,
#define joining_offset_0x10ac0u 914
#define joining_offset_0x10ac0u 916
/* Manichaean */
/* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D,
/* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R,
#define joining_offset_0x10b80u 962
#define joining_offset_0x10b80u 964
/* Psalter Pahlavi */
/* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
}; /* Table items: 1010; occupancy: 57% */
}; /* Table items: 1012; occupancy: 57% */
static unsigned int
@ -131,7 +131,7 @@ joining_type (hb_codepoint_t u)
switch (u >> 12)
{
case 0x0u:
if (hb_in_range (u, 0x0600u, 0x08B2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
if (hb_in_range (u, 0x0600u, 0x08B4u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
break;
case 0x1u:

View File

@ -142,7 +142,7 @@
OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
) \
OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
/* ASSERT_STATIC_EXPR len(FromGlyphs) == len(ToGlyphs) */
/* ASSERT_STATIC_EXPR_ZERO (len(FromGlyphs) == len(ToGlyphs)) */
#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
OT_SUBLOOKUP(Name, 1, \
@ -151,7 +151,7 @@
OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
) \
OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
/* ASSERT_STATIC_EXPR len(FirstGlyphs) == len(LigatureSetOffsets) */
/* ASSERT_STATIC_EXPR_ZERO (len(FirstGlyphs) == len(LigatureSetOffsets)) */
#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))

View File

@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
#include "hb-ot-shape-complex-private.hh"
#include "hb-ot-shape-complex-arabic-private.hh"
#include "hb-ot-shape-private.hh"
@ -32,10 +32,14 @@
#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
/*
* Joining types:
*/
/*
* Bits used in the joining tables
*/
enum {
enum hb_arabic_joining_type_t {
JOINING_TYPE_U = 0,
JOINING_TYPE_L = 1,
JOINING_TYPE_R = 2,
@ -49,10 +53,6 @@ enum {
JOINING_TYPE_X = 8 /* means: use general-category to choose between U or T. */
};
/*
* Joining types:
*/
#include "hb-ot-shape-complex-arabic-table.hh"
static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
@ -61,7 +61,7 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ
if (likely (j_type != JOINING_TYPE_X))
return j_type;
return (FLAG(gen_cat) &
return (FLAG_SAFE(gen_cat) &
(FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
@ -212,7 +212,7 @@ struct arabic_shape_plan_t
arabic_fallback_plan_t *fallback_plan;
};
static void *
void *
data_create_arabic (const hb_ot_shape_plan_t *plan)
{
arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
@ -230,7 +230,7 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
return arabic_plan;
}
static void
void
data_destroy_arabic (void *data)
{
arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data;
@ -305,17 +305,15 @@ mongolian_variation_selectors (hb_buffer_t *buffer)
info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
}
static void
setup_masks_arabic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
void
setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
hb_buffer_t *buffer,
hb_script_t script)
{
HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
arabic_joining (buffer);
if (plan->props.script == HB_SCRIPT_MONGOLIAN)
if (script == HB_SCRIPT_MONGOLIAN)
mongolian_variation_selectors (buffer);
unsigned int count = buffer->len;
@ -326,6 +324,15 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
static void
setup_masks_arabic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
}
static void
nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,

View File

@ -209,13 +209,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
hb_glyph_info_t tone = info[end];
memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t));
info[start] = tone;
buffer->merge_out_clusters (start, end + 1);
}
/* Merge clusters across the (possibly reordered) syllable+tone.
* We want to merge even in the zero-width tone mark case here,
* so that clustering behavior isn't dependent on how the tone mark
* is handled by the font.
*/
buffer->merge_out_clusters (start, end + 1);
}
else
{
@ -296,7 +291,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
}
else
end = start + 2;
buffer->merge_out_clusters (start, end);
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
buffer->merge_out_clusters (start, end);
continue;
}
}
@ -368,7 +364,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
info[i++].hangul_shaping_feature() = VJMO;
if (i < end)
info[i++].hangul_shaping_feature() = TJMO;
buffer->merge_out_clusters (start, end);
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
buffer->merge_out_clusters (start, end);
continue;
}
}

View File

@ -161,8 +161,6 @@ enum indic_matra_category_t {
INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M
};
/* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and the comma operation
* because gcc fails to optimize the latter and fills the table in at runtime. */
#define INDIC_COMBINE_CATEGORIES(S,M) \
(ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \
( \

View File

@ -142,7 +142,7 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags)
{
/* If it ligated, all bets are off. */
if (_hb_glyph_info_ligated (&info)) return false;
return !!(FLAG (info.indic_category()) & flags);
return !!(FLAG_SAFE (info.indic_category()) & flags);
}
static inline bool
@ -237,7 +237,7 @@ set_indic_properties (hb_glyph_info_t &info)
* Re-assign position.
*/
if ((FLAG (cat) & CONSONANT_FLAGS))
if ((FLAG_SAFE (cat) & CONSONANT_FLAGS))
{
pos = POS_BASE_C;
if (is_ra (u))
@ -247,7 +247,7 @@ set_indic_properties (hb_glyph_info_t &info)
{
pos = matra_position (u, pos);
}
else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol))))
else if ((FLAG_SAFE (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol))))
{
pos = POS_SMVD;
}
@ -963,7 +963,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
indic_position_t last_pos = POS_START;
for (unsigned int i = start; i < end; i++)
{
if ((FLAG (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | HALANT_OR_COENG_FLAGS)))
if ((FLAG_SAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | HALANT_OR_COENG_FLAGS)))
{
info[i].indic_position() = last_pos;
if (unlikely (info[i].indic_category() == OT_H &&
@ -1161,17 +1161,6 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
}
}
static void
initial_reordering_vowel_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
/* We made the vowels look like consonants. So let's call the consonant logic! */
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
}
static void
initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
@ -1193,37 +1182,6 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
}
static void
initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
/* We already inserted dotted-circles, so just call the standalone_cluster. */
initial_reordering_standalone_cluster (plan, face, buffer, start, end);
}
static void
initial_reordering_symbol_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer HB_UNUSED,
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
}
static void
initial_reordering_non_indic_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer HB_UNUSED,
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
@ -1231,13 +1189,21 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type) {
case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return;
case vowel_syllable: initial_reordering_vowel_syllable (plan, face, buffer, start, end); return;
case standalone_cluster: initial_reordering_standalone_cluster (plan, face, buffer, start, end); return;
case symbol_cluster: initial_reordering_symbol_cluster (plan, face, buffer, start, end); return;
case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return;
case non_indic_cluster: initial_reordering_non_indic_cluster (plan, face, buffer, start, end); return;
switch (syllable_type)
{
case vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
case consonant_syllable:
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
break;
case broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
case standalone_cluster:
initial_reordering_standalone_cluster (plan, face, buffer, start, end);
break;
case symbol_cluster:
case non_indic_cluster:
break;
}
}
@ -1310,18 +1276,8 @@ initial_reordering (const hb_ot_shape_plan_t *plan,
update_consonant_positions (plan, font, buffer);
insert_dotted_circles (plan, font, buffer);
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
if (unlikely (!count)) return;
unsigned int last = 0;
unsigned int last_syllable = info[0].syllable();
for (unsigned int i = 1; i < count; i++)
if (last_syllable != info[i].syllable()) {
initial_reordering_syllable (plan, font->face, buffer, last, i);
last = i;
last_syllable = info[last].syllable();
}
initial_reordering_syllable (plan, font->face, buffer, last, count);
foreach_syllable (buffer, start, end)
initial_reordering_syllable (plan, font->face, buffer, start, end);
}
static void
@ -1550,7 +1506,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
{
new_reph_pos = base;
while (new_reph_pos < end &&
!( FLAG (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
!( FLAG_SAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
new_reph_pos++;
if (new_reph_pos < end)
goto reph_move;
@ -1701,7 +1657,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
/* Apply 'init' to the Left Matra if it's a word start. */
if (info[start].indic_position () == POS_PRE_M &&
(!start ||
!(FLAG (_hb_glyph_info_get_general_category (&info[start - 1])) &
!(FLAG_SAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))))
info[start].mask |= indic_plan->mask_array[INIT];
@ -1737,16 +1693,8 @@ final_reordering (const hb_ot_shape_plan_t *plan,
unsigned int count = buffer->len;
if (unlikely (!count)) return;
hb_glyph_info_t *info = buffer->info;
unsigned int last = 0;
unsigned int last_syllable = info[0].syllable();
for (unsigned int i = 1; i < count; i++)
if (last_syllable != info[i].syllable()) {
final_reordering_syllable (plan, buffer, last, i);
last = i;
last_syllable = info[last].syllable();
}
final_reordering_syllable (plan, buffer, last, count);
foreach_syllable (buffer, start, end)
final_reordering_syllable (plan, buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);

View File

@ -154,7 +154,7 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags)
{
/* If it ligated, all bets are off. */
if (_hb_glyph_info_ligated (&info)) return false;
return !!(FLAG (info.myanmar_category()) & flags);
return !!(FLAG_SAFE (info.myanmar_category()) & flags);
}
static inline bool
@ -304,9 +304,7 @@ compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm */
static void
initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
initial_reordering_consonant_syllable (hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
hb_glyph_info_t *info = buffer->info;
@ -398,37 +396,6 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_bubble_sort (info + start, end - start, compare_myanmar_order);
}
static void
initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
/* We already inserted dotted-circles, so just call the consonant_syllable. */
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
}
static void
initial_reordering_punctuation_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer HB_UNUSED,
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
}
static void
initial_reordering_non_myanmar_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer HB_UNUSED,
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
@ -437,10 +404,15 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type) {
case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return;
case punctuation_cluster: initial_reordering_punctuation_cluster (plan, face, buffer, start, end); return;
case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return;
case non_myanmar_cluster: initial_reordering_non_myanmar_cluster (plan, face, buffer, start, end); return;
case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
case consonant_syllable:
initial_reordering_consonant_syllable (buffer, start, end);
break;
case punctuation_cluster:
case non_myanmar_cluster:
break;
}
}
@ -505,18 +477,8 @@ initial_reordering (const hb_ot_shape_plan_t *plan,
{
insert_dotted_circles (plan, font, buffer);
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
if (unlikely (!count)) return;
unsigned int last = 0;
unsigned int last_syllable = info[0].syllable();
for (unsigned int i = 1; i < count; i++)
if (last_syllable != info[i].syllable()) {
initial_reordering_syllable (plan, font->face, buffer, last, i);
last = i;
last_syllable = info[last].syllable();
}
initial_reordering_syllable (plan, font->face, buffer, last, count);
foreach_syllable (buffer, start, end)
initial_reordering_syllable (plan, font->face, buffer, start, end);
}
static void

View File

@ -59,9 +59,9 @@ enum hb_ot_shape_zero_width_marks_type_t {
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
HB_COMPLEX_SHAPER_IMPLEMENT (sea) \
HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
HB_COMPLEX_SHAPER_IMPLEMENT (use) \
/* ^--- Add new shapers here */
@ -217,61 +217,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* ^--- Add new shapers here */
#if 0
/* Note:
*
* These disabled scripts are listed in ucd/IndicSyllabicCategory.txt, but according
* to Martin Hosken and Jonathan Kew do not require complex shaping.
*
* TODO We should automate figuring out which scripts do not need complex shaping
*
* TODO We currently keep data for these scripts in our indic table. Need to fix the
* generator to not do that.
*/
/* Simple? */
/* Unicode-3.2 additions */
case HB_SCRIPT_BUHID:
case HB_SCRIPT_HANUNOO:
/* Unicode-5.1 additions */
case HB_SCRIPT_SAURASHTRA:
/* Unicode-6.0 additions */
case HB_SCRIPT_BATAK:
case HB_SCRIPT_BRAHMI:
/* Simple */
/* Unicode-1.1 additions */
/* These have their own shaper now. */
case HB_SCRIPT_LAO:
case HB_SCRIPT_THAI:
/* Unicode-3.2 additions */
case HB_SCRIPT_TAGALOG:
case HB_SCRIPT_TAGBANWA:
/* Unicode-4.0 additions */
case HB_SCRIPT_LIMBU:
case HB_SCRIPT_TAI_LE:
/* Unicode-4.1 additions */
case HB_SCRIPT_KHAROSHTHI:
case HB_SCRIPT_NEW_TAI_LUE:
case HB_SCRIPT_SYLOTI_NAGRI:
/* Unicode-5.1 additions */
case HB_SCRIPT_KAYAH_LI:
/* Unicode-5.2 additions */
case HB_SCRIPT_TAI_VIET:
#endif
/* Unicode-1.1 additions */
@ -288,28 +236,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-3.0 additions */
case HB_SCRIPT_SINHALA:
/* Unicode-5.0 additions */
case HB_SCRIPT_BALINESE:
/* Unicode-5.1 additions */
case HB_SCRIPT_LEPCHA:
case HB_SCRIPT_REJANG:
case HB_SCRIPT_SUNDANESE:
/* Unicode-5.2 additions */
case HB_SCRIPT_JAVANESE:
case HB_SCRIPT_KAITHI:
case HB_SCRIPT_MEETEI_MAYEK:
/* Unicode-6.0 additions */
/* Unicode-6.1 additions */
case HB_SCRIPT_CHAKMA:
case HB_SCRIPT_SHARADA:
case HB_SCRIPT_TAKRI:
/* If the designer designed the font for the 'DFLT' script,
* use the default shaper. Otherwise, use the Indic shaper.
* use the default shaper. Otherwise, use the specific shaper.
* Note that for some simple scripts, there may not be *any*
* GSUB/GPOS needed, so there may be no scripts found! */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
@ -341,23 +272,82 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
else
return &_hb_ot_complex_shaper_default;
/* Unicode-2.0 additions */
//case HB_SCRIPT_TIBETAN:
/* Unicode-3.0 additions */
//case HB_SCRIPT_MONGOLIAN:
//case HB_SCRIPT_SINHALA:
/* Unicode-3.2 additions */
case HB_SCRIPT_BUHID:
case HB_SCRIPT_HANUNOO:
case HB_SCRIPT_TAGALOG:
case HB_SCRIPT_TAGBANWA:
/* Unicode-4.0 additions */
case HB_SCRIPT_LIMBU:
case HB_SCRIPT_TAI_LE:
/* Unicode-4.1 additions */
case HB_SCRIPT_BUGINESE:
case HB_SCRIPT_KHAROSHTHI:
case HB_SCRIPT_SYLOTI_NAGRI:
case HB_SCRIPT_TIFINAGH:
/* Unicode-5.0 additions */
case HB_SCRIPT_BALINESE:
//case HB_SCRIPT_NKO:
//case HB_SCRIPT_PHAGS_PA:
/* Unicode-5.1 additions */
case HB_SCRIPT_CHAM:
case HB_SCRIPT_KAYAH_LI:
case HB_SCRIPT_LEPCHA:
case HB_SCRIPT_REJANG:
case HB_SCRIPT_SAURASHTRA:
case HB_SCRIPT_SUNDANESE:
/* Unicode-5.2 additions */
case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
//case HB_SCRIPT_JAVANESE:
case HB_SCRIPT_KAITHI:
case HB_SCRIPT_MEETEI_MAYEK:
case HB_SCRIPT_TAI_THAM:
case HB_SCRIPT_TAI_VIET:
/* Unicode-6.0 additions */
case HB_SCRIPT_BATAK:
case HB_SCRIPT_BRAHMI:
//case HB_SCRIPT_MANDAIC:
/* Unicode-6.1 additions */
case HB_SCRIPT_CHAKMA:
case HB_SCRIPT_SHARADA:
case HB_SCRIPT_TAKRI:
/* Unicode-7.0 additions */
case HB_SCRIPT_DUPLOYAN:
case HB_SCRIPT_GRANTHA:
case HB_SCRIPT_KHOJKI:
case HB_SCRIPT_KHUDAWADI:
case HB_SCRIPT_MAHAJANI:
//case HB_SCRIPT_MANICHAEAN:
case HB_SCRIPT_MODI:
case HB_SCRIPT_PAHAWH_HMONG:
//case HB_SCRIPT_PSALTER_PAHLAVI:
case HB_SCRIPT_SIDDHAM:
case HB_SCRIPT_TIRHUTA:
/* If the designer designed the font for the 'DFLT' script,
* use the default shaper. Otherwise, use the Indic shaper.
* use the default shaper. Otherwise, use the specific shaper.
* Note that for some simple scripts, there may not be *any*
* GSUB/GPOS needed, so there may be no scripts found! */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
return &_hb_ot_complex_shaper_default;
else
return &_hb_ot_complex_shaper_sea;
return &_hb_ot_complex_shaper_use;
}
}

View File

@ -1,224 +0,0 @@
#line 1 "hb-ot-shape-complex-sea-machine.rl"
/*
* Copyright © 2011,2012,2013 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_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
#include "hb-private.hh"
#line 36 "hb-ot-shape-complex-sea-machine.hh"
static const unsigned char _sea_syllable_machine_trans_keys[] = {
1u, 1u, 1u, 1u, 1u, 29u, 3u, 29u, 3u, 29u, 1u, 1u, 0
};
static const char _sea_syllable_machine_key_spans[] = {
1, 1, 29, 27, 27, 1
};
static const char _sea_syllable_machine_index_offsets[] = {
0, 2, 4, 34, 62, 90
};
static const char _sea_syllable_machine_indicies[] = {
1, 0, 3, 2, 1, 1, 3, 5,
4, 4, 4, 4, 4, 3, 4, 1,
4, 4, 4, 4, 3, 4, 4, 4,
4, 3, 4, 4, 4, 3, 3, 3,
3, 4, 1, 7, 6, 6, 6, 6,
6, 1, 6, 6, 6, 6, 6, 6,
1, 6, 6, 6, 6, 1, 6, 6,
6, 1, 1, 1, 1, 6, 3, 9,
8, 8, 8, 8, 8, 3, 8, 8,
8, 8, 8, 8, 3, 8, 8, 8,
8, 3, 8, 8, 8, 3, 3, 3,
3, 8, 3, 10, 0
};
static const char _sea_syllable_machine_trans_targs[] = {
2, 3, 2, 4, 2, 5, 2, 0,
2, 1, 2
};
static const char _sea_syllable_machine_trans_actions[] = {
1, 2, 3, 2, 6, 0, 7, 0,
8, 0, 9
};
static const char _sea_syllable_machine_to_state_actions[] = {
0, 0, 4, 0, 0, 0
};
static const char _sea_syllable_machine_from_state_actions[] = {
0, 0, 5, 0, 0, 0
};
static const char _sea_syllable_machine_eof_trans[] = {
1, 3, 0, 7, 9, 11
};
static const int sea_syllable_machine_start = 2;
static const int sea_syllable_machine_first_final = 2;
static const int sea_syllable_machine_error = -1;
static const int sea_syllable_machine_en_main = 2;
#line 36 "hb-ot-shape-complex-sea-machine.rl"
#line 67 "hb-ot-shape-complex-sea-machine.rl"
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
int cs;
hb_glyph_info_t *info = buffer->info;
#line 117 "hb-ot-shape-complex-sea-machine.hh"
{
cs = sea_syllable_machine_start;
ts = 0;
te = 0;
act = 0;
}
#line 88 "hb-ot-shape-complex-sea-machine.rl"
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
#line 134 "hb-ot-shape-complex-sea-machine.hh"
{
int _slen;
int _trans;
const unsigned char *_keys;
const char *_inds;
if ( p == pe )
goto _test_eof;
_resume:
switch ( _sea_syllable_machine_from_state_actions[cs] ) {
case 5:
#line 1 "NONE"
{ts = p;}
break;
#line 148 "hb-ot-shape-complex-sea-machine.hh"
}
_keys = _sea_syllable_machine_trans_keys + (cs<<1);
_inds = _sea_syllable_machine_indicies + _sea_syllable_machine_index_offsets[cs];
_slen = _sea_syllable_machine_key_spans[cs];
_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].sea_category()) &&
( info[p].sea_category()) <= _keys[1] ?
( info[p].sea_category()) - _keys[0] : _slen ];
_eof_trans:
cs = _sea_syllable_machine_trans_targs[_trans];
if ( _sea_syllable_machine_trans_actions[_trans] == 0 )
goto _again;
switch ( _sea_syllable_machine_trans_actions[_trans] ) {
case 2:
#line 1 "NONE"
{te = p+1;}
break;
case 6:
#line 63 "hb-ot-shape-complex-sea-machine.rl"
{te = p+1;{ found_syllable (non_sea_cluster); }}
break;
case 7:
#line 61 "hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }}
break;
case 8:
#line 62 "hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }}
break;
case 9:
#line 63 "hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (non_sea_cluster); }}
break;
case 1:
#line 61 "hb-ot-shape-complex-sea-machine.rl"
{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
break;
case 3:
#line 62 "hb-ot-shape-complex-sea-machine.rl"
{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
break;
#line 194 "hb-ot-shape-complex-sea-machine.hh"
}
_again:
switch ( _sea_syllable_machine_to_state_actions[cs] ) {
case 4:
#line 1 "NONE"
{ts = 0;}
break;
#line 203 "hb-ot-shape-complex-sea-machine.hh"
}
if ( ++p != pe )
goto _resume;
_test_eof: {}
if ( p == eof )
{
if ( _sea_syllable_machine_eof_trans[cs] > 0 ) {
_trans = _sea_syllable_machine_eof_trans[cs] - 1;
goto _eof_trans;
}
}
}
#line 97 "hb-ot-shape-complex-sea-machine.rl"
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */

View File

@ -1,102 +0,0 @@
/*
* Copyright © 2011,2012,2013 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_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
#include "hb-private.hh"
%%{
machine sea_syllable_machine;
alphtype unsigned char;
write data;
}%%
%%{
# Same order as enum sea_category_t. Not sure how to avoid duplication.
C = 1;
GB = 12; # Generic Base
H = 4; # Halant
IV = 2; # Independent Vowel
MR = 22; # Medial Ra
CM = 17; # Consonant Medial
VAbv = 26;
VBlw = 27;
VPre = 28;
VPst = 29;
T = 3; # Tone Marks
A = 10; # Anusvara
syllable_tail = (VPre|VAbv|VBlw|VPst|H.C|CM|MR|T|A)*;
consonant_syllable = (C|IV|GB) syllable_tail;
broken_cluster = syllable_tail;
other = any;
main := |*
consonant_syllable => { found_syllable (consonant_syllable); };
broken_cluster => { found_syllable (broken_cluster); };
other => { found_syllable (non_sea_cluster); };
*|;
}%%
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
int cs;
hb_glyph_info_t *info = buffer->info;
%%{
write init;
getkey info[p].sea_category();
}%%
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
%%{
write exec;
}%%
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */

View File

@ -1,380 +0,0 @@
/*
* Copyright © 2011,2012,2013 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
*/
#include "hb-ot-shape-complex-indic-private.hh"
/* buffer var allocations */
#define sea_category() complex_var_u8_0() /* indic_category_t */
#define sea_position() complex_var_u8_1() /* indic_position_t */
/*
* South-East Asian shaper.
* Loosely based on the Myanmar spec / shaper.
* There is no OpenType spec for this.
*/
static const hb_tag_t
basic_features[] =
{
/*
* Basic features.
* These features are applied in order, one at a time, after initial_reordering.
*/
HB_TAG('p','r','e','f'),
HB_TAG('a','b','v','f'),
HB_TAG('b','l','w','f'),
HB_TAG('p','s','t','f'),
};
static const hb_tag_t
other_features[] =
{
/*
* Other features.
* These features are applied all at once, after final_reordering.
*/
HB_TAG('p','r','e','s'),
HB_TAG('a','b','v','s'),
HB_TAG('b','l','w','s'),
HB_TAG('p','s','t','s'),
/* Positioning features, though we don't care about the types. */
HB_TAG('d','i','s','t'),
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
collect_features_sea (hb_ot_shape_planner_t *plan)
{
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_global_bool_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
map->add_global_bool_feature (HB_TAG('c','c','m','p'));
map->add_gsub_pause (initial_reordering);
for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
{
map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
map->add_gsub_pause (NULL);
}
map->add_gsub_pause (final_reordering);
for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
}
static void
override_features_sea (hb_ot_shape_planner_t *plan)
{
plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
}
enum syllable_type_t {
consonant_syllable,
broken_cluster,
non_sea_cluster,
};
#include "hb-ot-shape-complex-sea-machine.hh"
/* Note: This enum is duplicated in the -machine.rl source file.
* Not sure how to avoid duplication. */
enum sea_category_t {
// OT_C = 1,
OT_GB = 12, /* Generic Base XXX DOTTED CIRCLE only for now */
// OT_H = 4, /* Halant */
OT_IV = 2, /* Independent Vowel */
OT_MR = 22, /* Medial Ra */
// OT_CM = 17, /* Consonant Medial */
OT_VAbv = 26,
OT_VBlw = 27,
OT_VPre = 28,
OT_VPst = 29,
OT_T = 3, /* Tone Marks */
// OT_A = 10, /* Anusvara */
};
static inline void
set_sea_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
indic_category_t cat = (indic_category_t) (type & 0x7Fu);
indic_position_t pos = (indic_position_t) (type >> 8);
/* Medial Ra */
if (u == 0x1A55u || u == 0xAA34u)
cat = (indic_category_t) OT_MR;
if (cat == OT_M)
{
switch ((int) pos)
{
case POS_PRE_C: cat = (indic_category_t) OT_VPre; break;
case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break;
case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break;
case POS_POST_C: cat = (indic_category_t) OT_VPst; break;
}
}
info.sea_category() = (sea_category_t) cat;
info.sea_position() = pos;
}
static void
setup_masks_sea (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
HB_BUFFER_ALLOCATE_VAR (buffer, sea_category);
HB_BUFFER_ALLOCATE_VAR (buffer, sea_position);
/* We cannot setup masks here. We save information about characters
* and setup masks later on in a pause-callback. */
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
set_sea_properties (info[i]);
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
}
static int
compare_sea_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
{
int a = pa->sea_position();
int b = pb->sea_position();
return a < b ? -1 : a == b ? 0 : +1;
}
static void
initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
hb_glyph_info_t *info = buffer->info;
unsigned int base = start;
/* Reorder! */
unsigned int i = start;
for (; i < base; i++)
info[i].sea_position() = POS_PRE_C;
if (i < end)
{
info[i].sea_position() = POS_BASE_C;
i++;
}
for (; i < end; i++)
{
if (info[i].sea_category() == OT_MR) /* Pre-base reordering */
{
info[i].sea_position() = POS_PRE_C;
continue;
}
if (info[i].sea_category() == OT_VPre) /* Left matra */
{
info[i].sea_position() = POS_PRE_M;
continue;
}
info[i].sea_position() = POS_AFTER_MAIN;
}
buffer->merge_clusters (start, end);
/* Sit tight, rock 'n roll! */
hb_bubble_sort (info + start, end - start, compare_sea_order);
}
static void
initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
/* We already inserted dotted-circles, so just call the consonant_syllable. */
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
}
static void
initial_reordering_non_sea_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer HB_UNUSED,
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type) {
case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return;
case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return;
case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return;
}
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
/* Note: This loop is extra overhead, but should not be measurable. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == broken_cluster)
{
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
set_sea_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
info.syllable() = buffer->cur().syllable();
buffer->output_info (info);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
if (unlikely (!count)) return;
unsigned int last = 0;
unsigned int last_syllable = info[0].syllable();
for (unsigned int i = 1; i < count; i++)
if (last_syllable != info[i].syllable()) {
initial_reordering_syllable (plan, font->face, buffer, last, i);
last = i;
last_syllable = info[last].syllable();
}
initial_reordering_syllable (plan, font->face, buffer, last, count);
}
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
/* Zero syllables now... */
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
HB_BUFFER_DEALLOCATE_VAR (buffer, sea_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, sea_position);
}
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea =
{
"sea",
collect_features_sea,
override_features_sea,
NULL, /* data_create */
NULL, /* data_destroy */
NULL, /* preprocess_text */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
NULL, /* decompose */
NULL, /* compose */
setup_masks_sea,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};

View File

@ -0,0 +1,548 @@
#line 1 "hb-ot-shape-complex-use-machine.rl"
/*
* Copyright © 2015 Mozilla Foundation.
* Copyright © 2015 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.
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
#include "hb-private.hh"
#line 38 "hb-ot-shape-complex-use-machine.hh"
static const unsigned char _use_syllable_machine_trans_keys[] = {
0u, 0u, 4u, 4u, 1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u,
8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u,
8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
8u, 39u, 12u, 21u, 12u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u,
8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u,
42u, 42u, 0
};
static const char _use_syllable_machine_key_spans[] = {
0, 1, 1, 40, 1, 32, 32, 1,
32, 32, 32, 19, 19, 19, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 1, 32, 32, 19, 19,
19, 32, 32, 32, 32, 32, 32, 32,
32, 10, 2, 32, 32, 32, 32, 19,
19, 19, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 39, 32, 22, 2,
1
};
static const short _use_syllable_machine_index_offsets[] = {
0, 0, 2, 4, 45, 47, 80, 113,
115, 148, 181, 214, 234, 254, 274, 307,
340, 373, 406, 439, 472, 505, 538, 571,
604, 637, 670, 703, 705, 738, 771, 791,
811, 831, 864, 897, 930, 963, 996, 1029,
1062, 1095, 1106, 1109, 1142, 1175, 1208, 1241,
1261, 1281, 1301, 1334, 1367, 1400, 1433, 1466,
1499, 1532, 1565, 1598, 1631, 1671, 1704, 1727,
1730
};
static const char _use_syllable_machine_indicies[] = {
1, 0, 3, 2, 4, 5, 6,
4, 1, 5, 8, 8, 7, 8, 8,
3, 9, 8, 8, 8, 4, 4, 10,
11, 8, 8, 12, 13, 14, 15, 16,
17, 18, 12, 19, 20, 21, 22, 23,
24, 8, 25, 26, 27, 8, 29, 28,
31, 30, 30, 32, 33, 30, 30, 30,
30, 30, 30, 30, 30, 34, 35, 36,
37, 38, 39, 40, 41, 35, 42, 34,
43, 44, 45, 46, 30, 47, 48, 49,
30, 31, 30, 30, 32, 33, 30, 30,
30, 30, 30, 30, 30, 30, 50, 35,
36, 37, 38, 39, 40, 41, 35, 42,
43, 43, 44, 45, 46, 30, 47, 48,
49, 30, 32, 51, 31, 30, 30, 32,
33, 30, 30, 30, 30, 30, 30, 30,
30, 30, 35, 36, 37, 38, 39, 40,
41, 35, 42, 43, 43, 44, 45, 46,
30, 47, 48, 49, 30, 31, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 35, 36, 37, 38, 39,
30, 30, 30, 30, 30, 30, 44, 45,
46, 30, 47, 48, 49, 30, 31, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 36, 37, 38,
39, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 47, 48, 49, 30, 31,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 37,
38, 39, 30, 31, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 38, 39, 30, 31,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 39, 30, 31, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 37, 38, 39, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
47, 48, 49, 30, 31, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 37, 38, 39, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 48, 49, 30, 31, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 37, 38, 39,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 49, 30, 31, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 36, 37, 38,
39, 30, 30, 30, 30, 30, 30, 44,
45, 46, 30, 47, 48, 49, 30, 31,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 36, 37,
38, 39, 30, 30, 30, 30, 30, 30,
30, 45, 46, 30, 47, 48, 49, 30,
31, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 36,
37, 38, 39, 30, 30, 30, 30, 30,
30, 30, 30, 46, 30, 47, 48, 49,
30, 31, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 35,
36, 37, 38, 39, 30, 41, 35, 30,
30, 30, 44, 45, 46, 30, 47, 48,
49, 30, 31, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
35, 36, 37, 38, 39, 30, 30, 35,
30, 30, 30, 44, 45, 46, 30, 47,
48, 49, 30, 31, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 35, 36, 37, 38, 39, 40, 41,
35, 30, 30, 30, 44, 45, 46, 30,
47, 48, 49, 30, 31, 30, 30, 32,
33, 30, 30, 30, 30, 30, 30, 30,
30, 30, 35, 36, 37, 38, 39, 40,
41, 35, 42, 30, 43, 44, 45, 46,
30, 47, 48, 49, 30, 31, 30, 30,
32, 33, 30, 30, 30, 30, 30, 30,
30, 30, 30, 35, 36, 37, 38, 39,
40, 41, 35, 42, 34, 43, 44, 45,
46, 30, 47, 48, 49, 30, 53, 52,
52, 54, 55, 52, 52, 52, 52, 52,
52, 52, 52, 56, 52, 57, 58, 59,
60, 61, 62, 57, 63, 56, 64, 52,
52, 52, 52, 65, 66, 67, 52, 53,
52, 52, 54, 55, 52, 52, 52, 52,
52, 52, 52, 52, 68, 52, 57, 58,
59, 60, 61, 62, 57, 63, 64, 64,
52, 52, 52, 52, 65, 66, 67, 52,
54, 51, 53, 52, 52, 54, 55, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 57, 58, 59, 60, 61, 62, 57,
63, 64, 64, 52, 52, 52, 52, 65,
66, 67, 52, 53, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 57, 58, 59, 60, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
65, 66, 67, 52, 53, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 58, 59, 60, 52,
53, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 59, 60, 52, 53, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 60, 52,
53, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
58, 59, 60, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 65, 66, 67,
52, 53, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 58, 59, 60, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 66,
67, 52, 53, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 58, 59, 60, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 67, 52, 53, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 57, 58, 59, 60, 52, 62,
57, 52, 52, 52, 52, 52, 52, 52,
65, 66, 67, 52, 53, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 57, 58, 59, 60, 52,
52, 57, 52, 52, 52, 52, 52, 52,
52, 65, 66, 67, 52, 53, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 57, 58, 59, 60,
61, 62, 57, 52, 52, 52, 52, 52,
52, 52, 65, 66, 67, 52, 53, 52,
52, 54, 55, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 57, 58, 59,
60, 61, 62, 57, 63, 52, 64, 52,
52, 52, 52, 65, 66, 67, 52, 53,
52, 52, 54, 55, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 57, 58,
59, 60, 61, 62, 57, 63, 56, 64,
52, 52, 52, 52, 65, 66, 67, 52,
70, 71, 69, 69, 69, 69, 69, 69,
69, 72, 69, 70, 71, 69, 7, 73,
73, 3, 9, 73, 73, 73, 73, 73,
73, 73, 73, 74, 12, 13, 14, 15,
16, 17, 18, 12, 19, 21, 21, 22,
23, 24, 73, 25, 26, 27, 73, 7,
73, 73, 3, 9, 73, 73, 73, 73,
73, 73, 73, 73, 73, 12, 13, 14,
15, 16, 17, 18, 12, 19, 21, 21,
22, 23, 24, 73, 25, 26, 27, 73,
7, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 12, 13,
14, 15, 16, 73, 73, 73, 73, 73,
73, 22, 23, 24, 73, 25, 26, 27,
73, 7, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
13, 14, 15, 16, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 25, 26,
27, 73, 7, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 14, 15, 16, 73, 7, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 15,
16, 73, 7, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 16, 73, 7, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 14, 15,
16, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 25, 26, 27, 73, 7,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 14,
15, 16, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 26, 27, 73,
7, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
14, 15, 16, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 27,
73, 7, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
13, 14, 15, 16, 73, 73, 73, 73,
73, 73, 22, 23, 24, 73, 25, 26,
27, 73, 7, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 13, 14, 15, 16, 73, 73, 73,
73, 73, 73, 73, 23, 24, 73, 25,
26, 27, 73, 7, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 13, 14, 15, 16, 73, 73,
73, 73, 73, 73, 73, 73, 24, 73,
25, 26, 27, 73, 7, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 12, 13, 14, 15, 16, 73,
18, 12, 73, 73, 73, 22, 23, 24,
73, 25, 26, 27, 73, 7, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 12, 13, 14, 15, 16,
73, 73, 12, 73, 73, 73, 22, 23,
24, 73, 25, 26, 27, 73, 7, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 12, 13, 14, 15,
16, 17, 18, 12, 73, 73, 73, 22,
23, 24, 73, 25, 26, 27, 73, 7,
73, 73, 3, 9, 73, 73, 73, 73,
73, 73, 73, 73, 73, 12, 13, 14,
15, 16, 17, 18, 12, 19, 73, 21,
22, 23, 24, 73, 25, 26, 27, 73,
5, 6, 73, 73, 5, 73, 73, 7,
73, 73, 3, 9, 73, 73, 73, 73,
73, 73, 73, 73, 73, 12, 13, 14,
15, 16, 17, 18, 12, 19, 20, 21,
22, 23, 24, 73, 25, 26, 27, 73,
7, 73, 73, 3, 9, 73, 73, 73,
73, 73, 73, 73, 73, 73, 12, 13,
14, 15, 16, 17, 18, 12, 19, 20,
21, 22, 23, 24, 73, 25, 26, 27,
73, 76, 75, 75, 75, 75, 75, 75,
75, 75, 75, 75, 75, 75, 75, 75,
75, 75, 75, 75, 75, 76, 77, 75,
76, 77, 75, 77, 75, 0
};
static const char _use_syllable_machine_trans_targs[] = {
3, 41, 3, 43, 4, 5, 25, 3,
0, 2, 60, 62, 45, 46, 47, 48,
49, 56, 57, 58, 61, 59, 53, 54,
55, 50, 51, 52, 3, 3, 3, 3,
6, 7, 24, 9, 10, 11, 12, 13,
20, 21, 22, 23, 17, 18, 19, 14,
15, 16, 8, 3, 3, 3, 26, 27,
40, 29, 30, 31, 32, 36, 37, 38,
39, 33, 34, 35, 28, 3, 3, 1,
42, 3, 44, 3, 63, 64
};
static const char _use_syllable_machine_trans_actions[] = {
1, 2, 3, 4, 0, 0, 0, 7,
0, 0, 4, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 4, 0, 0,
0, 0, 0, 0, 8, 9, 10, 11,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 12, 13, 14, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 15, 16, 0,
2, 17, 4, 18, 0, 0
};
static const char _use_syllable_machine_to_state_actions[] = {
0, 0, 0, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0
};
static const char _use_syllable_machine_from_state_actions[] = {
0, 0, 0, 6, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0
};
static const short _use_syllable_machine_eof_trans[] = {
0, 1, 3, 0, 29, 31, 31, 52,
31, 31, 31, 31, 31, 31, 31, 31,
31, 31, 31, 31, 31, 31, 31, 31,
31, 53, 53, 52, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53,
53, 70, 70, 74, 74, 74, 74, 74,
74, 74, 74, 74, 74, 74, 74, 74,
74, 74, 74, 74, 74, 74, 76, 76,
76
};
static const int use_syllable_machine_start = 3;
static const int use_syllable_machine_first_final = 3;
static const int use_syllable_machine_error = 0;
static const int use_syllable_machine_en_main = 3;
#line 38 "hb-ot-shape-complex-use-machine.rl"
#line 145 "hb-ot-shape-complex-use-machine.rl"
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
int cs;
hb_glyph_info_t *info = buffer->info;
#line 388 "hb-ot-shape-complex-use-machine.hh"
{
cs = use_syllable_machine_start;
ts = 0;
te = 0;
act = 0;
}
#line 166 "hb-ot-shape-complex-use-machine.rl"
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
#line 405 "hb-ot-shape-complex-use-machine.hh"
{
int _slen;
int _trans;
const unsigned char *_keys;
const char *_inds;
if ( p == pe )
goto _test_eof;
if ( cs == 0 )
goto _out;
_resume:
switch ( _use_syllable_machine_from_state_actions[cs] ) {
case 6:
#line 1 "NONE"
{ts = p;}
break;
#line 421 "hb-ot-shape-complex-use-machine.hh"
}
_keys = _use_syllable_machine_trans_keys + (cs<<1);
_inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
_slen = _use_syllable_machine_key_spans[cs];
_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].use_category()) &&
( info[p].use_category()) <= _keys[1] ?
( info[p].use_category()) - _keys[0] : _slen ];
_eof_trans:
cs = _use_syllable_machine_trans_targs[_trans];
if ( _use_syllable_machine_trans_actions[_trans] == 0 )
goto _again;
switch ( _use_syllable_machine_trans_actions[_trans] ) {
case 2:
#line 1 "NONE"
{te = p+1;}
break;
case 9:
#line 134 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (independent_cluster); }}
break;
case 11:
#line 136 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (consonant_cluster); }}
break;
case 14:
#line 137 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (vowel_cluster); }}
break;
case 16:
#line 138 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (number_joiner_terminated_cluster); }}
break;
case 7:
#line 141 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (broken_cluster); }}
break;
case 8:
#line 134 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (independent_cluster); }}
break;
case 12:
#line 135 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
break;
case 10:
#line 136 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (consonant_cluster); }}
break;
case 13:
#line 137 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (vowel_cluster); }}
break;
case 15:
#line 139 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (numeral_cluster); }}
break;
case 18:
#line 140 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (symbol_cluster); }}
break;
case 17:
#line 141 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }}
break;
case 1:
#line 139 "hb-ot-shape-complex-use-machine.rl"
{{p = ((te))-1;}{ found_syllable (numeral_cluster); }}
break;
case 3:
#line 1 "NONE"
{ switch( act ) {
case 0:
{{cs = 0; goto _again;}}
break;
case 8:
{{p = ((te))-1;} found_syllable (broken_cluster); }
break;
}
}
break;
case 4:
#line 1 "NONE"
{te = p+1;}
#line 141 "hb-ot-shape-complex-use-machine.rl"
{act = 8;}
break;
#line 513 "hb-ot-shape-complex-use-machine.hh"
}
_again:
switch ( _use_syllable_machine_to_state_actions[cs] ) {
case 5:
#line 1 "NONE"
{ts = 0;}
#line 1 "NONE"
{act = 0;}
break;
#line 524 "hb-ot-shape-complex-use-machine.hh"
}
if ( cs == 0 )
goto _out;
if ( ++p != pe )
goto _resume;
_test_eof: {}
if ( p == eof )
{
if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
_trans = _use_syllable_machine_eof_trans[cs] - 1;
goto _eof_trans;
}
}
_out: {}
}
#line 175 "hb-ot-shape-complex-use-machine.rl"
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */

View File

@ -0,0 +1,180 @@
/*
* Copyright © 2015 Mozilla Foundation.
* Copyright © 2015 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.
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
#include "hb-private.hh"
%%{
machine use_syllable_machine;
alphtype unsigned char;
write data;
}%%
%%{
# Same order as enum use_category_t. Not sure how to avoid duplication.
O = 0; # OTHER
B = 1; # BASE
IV = 2; # BASE_VOWEL
IND = 3; # BASE_IND
N = 4; # BASE_NUM
GB = 5; # BASE_OTHER
CGJ = 6; # CGJ
#F = 7; # CONS_FINAL
FM = 8; # CONS_FINAL_MOD
#M = 9; # CONS_MED
#CM = 10; # CONS_MOD
SUB = 11; # CONS_SUB
H = 12; # HALANT
HN = 13; # HALANT_NUM
ZWNJ = 14; # Zero width non-joiner
ZWJ = 15; # Zero width joiner
WJ = 16; # Word joiner
Rsv = 17; # Reserved characters
R = 18; # REPHA
S = 19; # SYM
#SM = 20; # SYM_MOD
VS = 21; # VARIATION_SELECTOR
#V = 36; # VOWEL
#VM = 40; # VOWEL_MOD
FAbv = 24; # CONS_FINAL_ABOVE
FBlw = 25; # CONS_FINAL_BELOW
FPst = 26; # CONS_FINAL_POST
MAbv = 27; # CONS_MED_ABOVE
MBlw = 28; # CONS_MED_BELOW
MPst = 29; # CONS_MED_POST
MPre = 30; # CONS_MED_PRE
CMAbv = 31; # CONS_MOD_ABOVE
CMBlw = 32; # CONS_MOD_BELOW
VAbv = 33; # VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST
VBlw = 34; # VOWEL_BELOW / VOWEL_BELOW_POST
VPst = 35; # VOWEL_POST UIPC = Right
VPre = 22; # VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST
VMAbv = 37; # VOWEL_MOD_ABOVE
VMBlw = 38; # VOWEL_MOD_BELOW
VMPst = 39; # VOWEL_MOD_POST
VMPre = 23; # VOWEL_MOD_PRE
SMAbv = 41; # SYM_MOD_ABOVE
SMBlw = 42; # SYM_MOD_BELOW
consonant_modifiers = CMAbv* CMBlw* ((H B | SUB) VS? CMAbv? CMBlw*)*;
medial_consonants = MPre? MAbv? MBlw? MPst?;
dependent_vowels = VPre* VAbv* VBlw* VPst*;
vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*;
final_consonants = FAbv* FBlw* FPst* FM?;
virama_terminated_cluster =
R? (B | GB | IV) VS?
consonant_modifiers
H
;
consonant_cluster =
R? (B | GB) VS?
consonant_modifiers
medial_consonants
dependent_vowels
vowel_modifiers
final_consonants
;
vowel_cluster =
R? (IV) VS?
consonant_modifiers
medial_consonants
vowel_modifiers
final_consonants
;
broken_cluster =
R?
consonant_modifiers
medial_consonants
dependent_vowels
vowel_modifiers
final_consonants
;
number_joiner_terminated_cluster = N VS? (HN N VS?)* H;
numeral_cluster = N VS? (HN N VS?)*;
symbol_cluster = S VS? SMAbv* SMBlw*;
independent_cluster = (IND | O | Rsv | WJ) VS?;
main := |*
independent_cluster => { found_syllable (independent_cluster); };
virama_terminated_cluster => { found_syllable (virama_terminated_cluster); };
consonant_cluster => { found_syllable (consonant_cluster); };
vowel_cluster => { found_syllable (vowel_cluster); };
number_joiner_terminated_cluster => { found_syllable (number_joiner_terminated_cluster); };
numeral_cluster => { found_syllable (numeral_cluster); };
symbol_cluster => { found_syllable (symbol_cluster); };
broken_cluster => { found_syllable (broken_cluster); };
*|;
}%%
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
int cs;
hb_glyph_info_t *info = buffer->info;
%%{
write init;
getkey info[p].use_category();
}%%
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
%%{
write exec;
}%%
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */

View File

@ -0,0 +1,97 @@
/*
* Copyright © 2015 Mozilla Foundation.
* Copyright © 2015 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.
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
#define HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
#include "hb-private.hh"
#include "hb-ot-shape-complex-private.hh"
#define USE_TABLE_ELEMENT_TYPE uint8_t
/* Cateories used in the Universal Shaping Engine spec:
* https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
*/
/* Note: This enum is duplicated in the -machine.rl source file.
* Not sure how to avoid duplication. */
enum use_category_t {
USE_O = 0, /* OTHER */
USE_B = 1, /* BASE */
USE_IV = 2, /* BASE_VOWEL */
USE_IND = 3, /* BASE_IND */
USE_N = 4, /* BASE_NUM */
USE_GB = 5, /* BASE_OTHER */
USE_CGJ = 6, /* CGJ */
// USE_F = 7, /* CONS_FINAL */
USE_FM = 8, /* CONS_FINAL_MOD */
// USE_M = 9, /* CONS_MED */
// USE_CM = 10, /* CONS_MOD */
USE_SUB = 11, /* CONS_SUB */
USE_H = 12, /* HALANT */
USE_HN = 13, /* HALANT_NUM */
USE_ZWNJ = 14, /* Zero width non-joiner */
USE_ZWJ = 15, /* Zero width joiner */
USE_WJ = 16, /* Word joiner */
USE_Rsv = 17, /* Reserved characters */
USE_R = 18, /* REPHA */
USE_S = 19, /* SYM */
// USE_SM = 20, /* SYM_MOD */
USE_VS = 21, /* VARIATION_SELECTOR */
// USE_V = 36, /* VOWEL */
// USE_VM = 40, /* VOWEL_MOD */
USE_FAbv = 24, /* CONS_FINAL_ABOVE */
USE_FBlw = 25, /* CONS_FINAL_BELOW */
USE_FPst = 26, /* CONS_FINAL_POST */
USE_MAbv = 27, /* CONS_MED_ABOVE */
USE_MBlw = 28, /* CONS_MED_BELOW */
USE_MPst = 29, /* CONS_MED_POST */
USE_MPre = 30, /* CONS_MED_PRE */
USE_CMAbv = 31, /* CONS_MOD_ABOVE */
USE_CMBlw = 32, /* CONS_MOD_BELOW */
USE_VAbv = 33, /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
USE_VBlw = 34, /* VOWEL_BELOW / VOWEL_BELOW_POST */
USE_VPst = 35, /* VOWEL_POST UIPC = Right */
USE_VPre = 22, /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
USE_VMAbv = 37, /* VOWEL_MOD_ABOVE */
USE_VMBlw = 38, /* VOWEL_MOD_BELOW */
USE_VMPst = 39, /* VOWEL_MOD_POST */
USE_VMPre = 23, /* VOWEL_MOD_PRE */
USE_SMAbv = 41, /* SYM_MOD_ABOVE */
USE_SMBlw = 42 /* SYM_MOD_BELOW */
};
HB_INTERNAL USE_TABLE_ELEMENT_TYPE
hb_use_get_categories (hb_codepoint_t u);
#endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */

View File

@ -0,0 +1,696 @@
/* == Start of generated table == */
/*
* The following table is generated by running:
*
* ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
*
* on files with these headers:
*
* # IndicSyllabicCategory-8.0.0.txt
* # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI]
* # IndicPositionalCategory-8.0.0.txt
* # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI]
* # Blocks-8.0.0.txt
* # Date: 2014-11-10, 23:04:00 GMT [KW]
* UnicodeData.txt does not have a header.
*/
#include "hb-ot-shape-complex-use-private.hh"
#define B USE_B /* BASE */
#define CGJ USE_CGJ /* CGJ */
#define FM USE_FM /* CONS_FINAL_MOD */
#define GB USE_GB /* BASE_OTHER */
#define H USE_H /* HALANT */
#define HN USE_HN /* HALANT_NUM */
#define IND USE_IND /* BASE_IND */
#define IV USE_IV /* BASE_VOWEL */
#define N USE_N /* BASE_NUM */
#define O USE_O /* OTHER */
#define R USE_R /* REPHA */
#define Rsv USE_Rsv /* Reserved */
#define S USE_S /* SYM */
#define SUB USE_SUB /* CONS_SUB */
#define VS USE_VS /* VARIATION_SELECTOR */
#define WJ USE_WJ /* Word_Joiner */
#define ZWJ USE_ZWJ /* ZWJ */
#define ZWNJ USE_ZWNJ /* ZWNJ */
#define CMBlw USE_CMBlw
#define CMAbv USE_CMAbv
#define FBlw USE_FBlw
#define FPst USE_FPst
#define FAbv USE_FAbv
#define MPre USE_MPre
#define MBlw USE_MBlw
#define MPst USE_MPst
#define MAbv USE_MAbv
#define SMBlw USE_SMBlw
#define SMAbv USE_SMAbv
#define VPre USE_VPre
#define VBlw USE_VBlw
#define VPst USE_VPst
#define VAbv USE_VAbv
#define VMPre USE_VMPre
#define VMBlw USE_VMBlw
#define VMPst USE_VMPst
#define VMAbv USE_VMAbv
static const USE_TABLE_ELEMENT_TYPE use_table[] = {
#define use_offset_0x0028u 0
/* Basic Latin */
O, O, O, O, O, GB, O, O,
/* 0030 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0x00a0u 24
/* Latin-1 Supplement */
/* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 00B0 */ O, O, FM, FM, O, O, O, O, O, O, O, O, O, O, O, O,
/* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 00D0 */ O, O, O, O, O, O, O, GB,
#define use_offset_0x0900u 80
/* Devanagari */
/* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 0910 */ IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre,
/* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst,
/* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B,
/* 0960 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0970 */ O, O, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B,
/* Bengali */
/* 0980 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV,
/* 0990 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
/* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O,
/* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B,
/* 09E0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Gurmukhi */
/* 0A00 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, O, O, O, O, IV,
/* 0A10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre,
/* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O,
/* 0A50 */ O, O, O, O, O, O, O, O, O, B, B, B, B, O, B, O,
/* 0A60 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, O, O, O, O, O, O, O, O, O,
/* Gujarati */
/* 0A80 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, O, IV,
/* 0A90 */ IV, IV, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0AA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0AB0 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
/* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O,
/* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 0AE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0AF0 */ O, O, O, O, O, O, O, O, O, B, O, O, O, O, O, O,
/* Oriya */
/* 0B00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV,
/* 0B10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
/* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
/* 0B50 */ O, O, O, O, O, O, VAbv, VAbv, O, O, O, O, B, B, O, B,
/* 0B60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Tamil */
/* 0B80 */ O, O, VMAbv, IND, O, IV, IV, IV, IV, IV, IV, O, O, O, IV, IV,
/* 0B90 */ IV, O, IV, IV, IV, B, O, O, O, B, B, O, B, O, B, B,
/* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B,
/* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst,
/* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O,
/* 0BD0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O,
/* 0BE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Telugu */
/* 0C00 */ VMAbv, VMPst, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV,
/* 0C10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, VAbv, VAbv,
/* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
/* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O,
/* 0C60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0C70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Kannada */
/* 0C80 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV,
/* 0C90 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0CA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0CB0 */ B, B, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
/* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
/* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O,
/* 0CE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0CF0 */ O, R, R, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Malayalam */
/* 0D00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV,
/* 0D10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, O, O, B, VPst, VPst,
/* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O,
/* 0D50 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, IV,
/* 0D60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0D70 */ O, O, O, O, O, O, O, O, O, O, IND, IND, IND, IND, IND, IND,
/* Sinhala */
/* 0D80 */ O, O, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 0D90 */ IV, IV, IV, IV, IV, IV, IV, O, O, O, B, B, B, B, B, B,
/* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O,
/* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst,
/* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst,
/* 0DE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0DF0 */ O, O, VPst, VPst, O, O, O, O,
#define use_offset_0x1000u 1352
/* Myanmar */
/* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1020 */ B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, VPst, VPst, VAbv, VAbv, VBlw,
/* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B,
/* 1040 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, GB, O,
/* 1050 */ B, B, IV, IV, IV, IV, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
/* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
/* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B,
/* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst,
/* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O,
#define use_offset_0x1700u 1512
/* Tagalog */
/* 1700 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B,
/* 1710 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O,
/* Hanunoo */
/* 1720 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1730 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O,
/* Buhid */
/* 1740 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1750 */ B, B, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
/* Tagbanwa */
/* 1760 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B,
/* 1770 */ B, O, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
/* Khmer */
/* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 17A0 */ B, B, B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 17B0 */ IV, IV, IV, IV, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
/* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FM, FAbv, CMAbv, FM, FM,
/* 17D0 */ FM, VAbv, H, FM, O, O, O, O, O, O, O, O, B, VAbv, O, O,
/* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0x1900u 1752
/* Limbu */
/* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O,
/* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, O, O, O, O,
/* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VAbv, FM, O, O, O, O,
/* 1940 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
/* Tai Le */
/* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, O,
/* 1970 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O,
/* New Tai Lue */
/* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
/* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, O, O, O, O, O, O,
/* 19D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Buginese */
/* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A10 */ B, B, B, B, B, B, B, VAbv, VBlw, VPre, VPst, VAbv, O, O, O, O,
/* Tai Tham */
/* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV, IV,
/* 1A50 */ IV, IV, IV, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O,
/* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre,
/* 1A70 */ VPre, VPre, VPre, VAbv, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, FM, FM, FM, O, O, FM,
/* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0x1b00u 2168
/* Balinese */
/* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 1B10 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre,
/* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O,
/* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
/* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O,
/* Sundanese */
/* 1B80 */ VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B,
/* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B,
/* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* Batak */
/* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BE0 */ B, B, B, B, IV, IV, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv,
/* 1BF0 */ FAbv, FAbv, VPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O,
/* Lepcha */
/* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv,
/* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FM, CMBlw, O, O, O, O, O, O, O, O,
/* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B,
#define use_offset_0x1cd0u 2504
/* Vedic Extensions */
/* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
/* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O,
/* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, O, VMAbv, VMAbv, O, O, O, O, O, O,
#define use_offset_0x2008u 2552
/* General Punctuation */
O, O, O, O, ZWNJ, ZWJ, O, O,
/* 2010 */ GB, GB, GB, GB, GB, O, O, O,
#define use_offset_0x2060u 2568
/* 2060 */ WJ, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Superscripts and Subscripts */
/* 2070 */ O, O, O, O, FM, O, O, O, O, O, O, O, O, O, O, O,
/* 2080 */ O, O, FM, FM, FM, O, O, O,
#define use_offset_0xa800u 2608
/* Syloti Nagri */
/* A800 */ IV, IV, O, IV, IV, IV, VAbv, B, B, B, B, VMAbv, B, B, B, B,
/* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, O, O, O, O,
/* A830 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Phags-pa */
/* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A870 */ B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, O,
/* Saurashtra */
/* A880 */ VMPst, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* A890 */ IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A8B0 */ B, B, B, B, FPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst,
/* A8C0 */ VPst, VPst, VPst, VPst, H, O, O, O, O, O, O, O, O, O, O, O,
/* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Devanagari Extended */
/* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
/* A8F0 */ VMAbv, VMAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Kayah Li */
/* A900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A920 */ B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VAbv, VMBlw, VMBlw, VMBlw, O, O,
/* Rejang */
/* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv,
/* A950 */ FAbv, FAbv, FPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O,
/* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Javanese */
/* A980 */ VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, B, B, B, IV, IV, IV, B,
/* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MPst,
/* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* A9D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Myanmar Extended-B */
/* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B,
/* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O,
/* Cham */
/* AA00 */ IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B,
/* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA20 */ B, B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
/* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MBlw, MBlw, O, O, O, O, O, O, O, O, O,
/* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O,
/* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Myanmar Extended-A */
/* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA70 */ O, B, B, B, O, O, O, O, O, O, B, VMPst, VMAbv, VMPst, B, B,
/* Tai Viet */
/* AA80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv,
/* AAC0 */ B, VMAbv, B, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* AAD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Meetei Mayek Extensions */
/* AAE0 */ IV, IV, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
/* AAF0 */ O, O, O, O, O, VMPst, H, O,
#define use_offset_0xabc0u 3368
/* Meetei Mayek */
/* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV,
/* ABD0 */ B, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O,
/* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0xfe00u 3432
/* Variation Selectors */
/* FE00 */ VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS,
#define use_offset_0x10a00u 3448
/* Kharoshthi */
/* 10A00 */ B, VBlw, VBlw, VBlw, O, VAbv, VBlw, O, O, O, O, O, VBlw, VBlw, VMBlw, VMAbv,
/* 10A10 */ B, B, B, B, O, B, B, B, O, B, B, B, B, B, B, B,
/* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 10A30 */ B, B, B, B, O, O, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H,
/* 10A40 */ B, B, B, B, B, B, B, B,
#define use_offset_0x11000u 3520
/* Brahmi */
/* 11000 */ VMPst, VMAbv, VMPst, R, R, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 11010 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw,
/* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O,
/* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
/* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B,
/* 11070 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Kaithi */
/* 11080 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B,
/* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
#define use_offset_0x11100u 3712
/* Chakma */
/* 11100 */ VMAbv, VMAbv, VMAbv, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B,
/* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11120 */ B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv,
/* 11130 */ VAbv, VBlw, VBlw, H, VAbv, O, B, B, B, B, B, B, B, B, B, B,
/* 11140 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Mahajani */
/* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11170 */ B, B, B, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
/* Sharada */
/* 11180 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 11190 */ IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
/* 111C0 */ H, B, R, R, O, O, O, O, O, O, CMBlw, VAbv, VBlw, O, O, O,
/* 111D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Sinhala Archaic Numbers */
/* 111E0 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111F0 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O,
/* Khojki */
/* 11200 */ IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B,
/* 11210 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
/* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv,
#define use_offset_0x11280u 4024
/* Multani */
/* 11280 */ IV, IV, IV, IV, B, B, B, O, B, O, B, B, B, B, O, B,
/* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, B,
/* 112A0 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
/* Khudawadi */
/* 112B0 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B,
/* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv,
/* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, O, O, O, O, O,
/* 112F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Grantha */
/* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV,
/* 11310 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 11330 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPst,
/* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
/* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O,
/* 11360 */ IV, IV, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
/* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
#define use_offset_0x11480u 4272
/* Tirhuta */
/* 11480 */ O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B,
/* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv,
/* 114C0 */ VMAbv, VMPst, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O,
/* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0x11580u 4368
/* Siddham */
/* 11580 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B,
/* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
/* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H,
/* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 115D0 */ O, O, O, O, O, O, O, O, IV, IV, IV, IV, VBlw, VBlw, O, O,
/* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 115F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Modi */
/* 11600 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B,
/* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H,
/* 11640 */ VAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 11650 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 11670 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Takri */
/* 11680 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B,
/* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst,
/* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, O, O, O, O, O, O, O, O,
/* 116C0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* 116D0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 116E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 116F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Ahom */
/* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11710 */ B, B, B, B, B, B, B, B, B, B, O, O, O, MBlw, MPre, MAbv,
/* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
/* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
}; /* Table items: 4816; occupancy: 72% */
USE_TABLE_ELEMENT_TYPE
hb_use_get_categories (hb_codepoint_t u)
{
switch (u >> 12)
{
case 0x0u:
if (hb_in_range (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
if (hb_in_range (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
if (hb_in_range (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
if (unlikely (u == 0x034Fu)) return CGJ;
break;
case 0x1u:
if (hb_in_range (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u];
if (hb_in_range (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u];
if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
break;
case 0x2u:
if (hb_in_range (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u];
if (hb_in_range (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u];
if (unlikely (u == 0x25CCu)) return GB;
break;
case 0xAu:
if (hb_in_range (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
if (hb_in_range (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
break;
case 0xFu:
if (hb_in_range (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
break;
case 0x10u:
if (hb_in_range (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
break;
case 0x11u:
if (hb_in_range (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u];
if (hb_in_range (u, 0x11100u, 0x11237u)) return use_table[u - 0x11100u + use_offset_0x11100u];
if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
if (hb_in_range (u, 0x11480u, 0x114DFu)) return use_table[u - 0x11480u + use_offset_0x11480u];
if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u];
if (unlikely (u == 0x1107Fu)) return HN;
break;
default:
break;
}
return USE_O;
}
#undef B
#undef CGJ
#undef FM
#undef GB
#undef H
#undef HN
#undef IND
#undef IV
#undef N
#undef O
#undef R
#undef Rsv
#undef S
#undef SUB
#undef VS
#undef WJ
#undef ZWJ
#undef ZWNJ
#undef CMBlw
#undef CMAbv
#undef FBlw
#undef FPst
#undef FAbv
#undef MPre
#undef MBlw
#undef MPst
#undef MAbv
#undef SMBlw
#undef SMAbv
#undef VPre
#undef VBlw
#undef VPst
#undef VAbv
#undef VMPre
#undef VMBlw
#undef VMPst
#undef VMAbv
/* == End of generated table == */

View File

@ -0,0 +1,593 @@
/*
* Copyright © 2015 Mozilla Foundation.
* Copyright © 2015 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.
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
#include "hb-ot-shape-complex-use-private.hh"
#include "hb-ot-shape-complex-arabic-private.hh"
/* buffer var allocations */
#define use_category() complex_var_u8_0()
/*
* Universal Shaping Engine.
* https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
*/
static const hb_tag_t
basic_features[] =
{
/*
* Basic features.
* These features are applied all at once, before reordering.
*/
HB_TAG('r','k','r','f'),
HB_TAG('a','b','v','f'),
HB_TAG('b','l','w','f'),
HB_TAG('h','a','l','f'),
HB_TAG('p','s','t','f'),
HB_TAG('v','a','t','u'),
HB_TAG('c','j','c','t'),
};
static const hb_tag_t
arabic_features[] =
{
HB_TAG('i','s','o','l'),
HB_TAG('i','n','i','t'),
HB_TAG('m','e','d','i'),
HB_TAG('f','i','n','a'),
/* The spec doesn't specify these but we apply anyway, since our Arabic shaper
* does. These are only used in Syriac spec. */
HB_TAG('m','e','d','2'),
HB_TAG('f','i','n','2'),
HB_TAG('f','i','n','3'),
};
/* Same order as arabic_features. Don't need Syriac stuff.*/
enum joining_form_t {
ISOL,
INIT,
MEDI,
FINA,
_NONE
};
static const hb_tag_t
other_features[] =
{
/*
* Other features.
* These features are applied all at once, after reordering.
*/
HB_TAG('a','b','v','s'),
HB_TAG('b','l','w','s'),
HB_TAG('h','a','l','n'),
HB_TAG('p','r','e','s'),
HB_TAG('p','s','t','s'),
/* Positioning features, though we don't care about the types. */
HB_TAG('d','i','s','t'),
HB_TAG('a','b','v','m'),
HB_TAG('b','l','w','m'),
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
clear_substitution_flags (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
record_rphf (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
record_pref (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
collect_features_use (hb_ot_shape_planner_t *plan)
{
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
/* "Default glyph pre-processing group" */
map->add_global_bool_feature (HB_TAG('l','o','c','l'));
map->add_global_bool_feature (HB_TAG('c','c','m','p'));
map->add_global_bool_feature (HB_TAG('n','u','k','t'));
map->add_global_bool_feature (HB_TAG('a','k','h','n'));
/* "Reordering group" */
map->add_gsub_pause (clear_substitution_flags);
map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ);
map->add_gsub_pause (record_rphf);
map->add_gsub_pause (clear_substitution_flags);
map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ);
map->add_gsub_pause (record_pref);
/* "Orthographic unit shaping group" */
for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
map->add_gsub_pause (reorder);
/* "Topographical features" */
for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
map->add_feature (arabic_features[i], 1, F_NONE);
map->add_gsub_pause (NULL);
/* "Standard typographic presentation" and "Positional feature application" */
for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
}
struct use_shape_plan_t
{
ASSERT_POD ();
hb_mask_t rphf_mask;
arabic_shape_plan_t *arabic_plan;
};
static bool
has_arabic_joining (hb_script_t script)
{
/* List of scripts that have data in arabic-table. */
switch ((int) script)
{
/* Unicode-1.1 additions */
case HB_SCRIPT_ARABIC:
/* Unicode-3.0 additions */
case HB_SCRIPT_MONGOLIAN:
case HB_SCRIPT_SYRIAC:
/* Unicode-5.0 additions */
case HB_SCRIPT_NKO:
case HB_SCRIPT_PHAGS_PA:
/* Unicode-6.0 additions */
case HB_SCRIPT_MANDAIC:
/* Unicode-7.0 additions */
case HB_SCRIPT_MANICHAEAN:
case HB_SCRIPT_PSALTER_PAHLAVI:
return true;
default:
return false;
}
}
static void *
data_create_use (const hb_ot_shape_plan_t *plan)
{
use_shape_plan_t *use_plan = (use_shape_plan_t *) calloc (1, sizeof (use_shape_plan_t));
if (unlikely (!use_plan))
return NULL;
use_plan->rphf_mask = plan->map.get_1_mask (HB_TAG('r','p','h','f'));
if (has_arabic_joining (plan->props.script))
{
use_plan->arabic_plan = (arabic_shape_plan_t *) data_create_arabic (plan);
if (unlikely (!use_plan->arabic_plan))
{
free (use_plan);
return NULL;
}
}
return use_plan;
}
static void
data_destroy_use (void *data)
{
use_shape_plan_t *use_plan = (use_shape_plan_t *) data;
if (use_plan->arabic_plan)
data_destroy_arabic (use_plan->arabic_plan);
free (data);
}
enum syllable_type_t {
independent_cluster,
virama_terminated_cluster,
consonant_cluster,
vowel_cluster,
number_joiner_terminated_cluster,
numeral_cluster,
symbol_cluster,
broken_cluster,
};
#include "hb-ot-shape-complex-use-machine.hh"
static inline void
set_use_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
info.use_category() = hb_use_get_categories (u);
}
static void
setup_masks_use (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
/* Do this before allocating use_category(). */
if (use_plan->arabic_plan)
{
setup_masks_arabic_plan (use_plan->arabic_plan, buffer, plan->props.script);
}
HB_BUFFER_ALLOCATE_VAR (buffer, use_category);
/* We cannot setup masks here. We save information about characters
* and setup masks later on in a pause-callback. */
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
info[i].use_category() = hb_use_get_categories (info[i].codepoint);
}
static void
setup_rphf_mask (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer)
{
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
hb_mask_t mask = use_plan->rphf_mask;
if (!mask) return;
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
{
unsigned int limit = info[start].use_category() == USE_R ? 1 : MIN (3u, end - start);
for (unsigned int i = start; i < start + limit; i++)
info[i].mask |= mask;
}
}
static void
setup_topographical_masks (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer)
{
ASSERT_STATIC (INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4);
hb_mask_t masks[4], all_masks = 0;
for (unsigned int i = 0; i < 4; i++)
{
masks[i] = plan->map.get_1_mask (arabic_features[i]);
if (masks[i] == plan->map.get_global_mask ())
masks[i] = 0;
all_masks |= masks[i];
}
if (!all_masks)
return;
hb_mask_t other_masks = ~all_masks;
unsigned int last_start = 0;
joining_form_t last_form = _NONE;
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
{
syllable_type_t syllable_type = (syllable_type_t) (info[start].syllable() & 0x0F);
switch (syllable_type)
{
case independent_cluster:
case symbol_cluster:
/* These don't join. Nothing to do. */
last_form = _NONE;
break;
case virama_terminated_cluster:
case consonant_cluster:
case vowel_cluster:
case number_joiner_terminated_cluster:
case numeral_cluster:
case broken_cluster:
bool join = last_form == FINA || last_form == ISOL;
if (join)
{
/* Fixup previous syllable's form. */
last_form = last_form == FINA ? MEDI : INIT;
for (unsigned int i = last_start; i < start; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
}
/* Form for this syllable. */
last_form = join ? FINA : ISOL;
for (unsigned int i = start; i < end; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
break;
}
last_start = start;
}
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
setup_rphf_mask (plan, buffer);
setup_topographical_masks (plan, buffer);
}
static void
clear_substitution_flags (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (&info[i]);
}
static void
record_rphf (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
hb_mask_t mask = use_plan->rphf_mask;
if (!mask) return;
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
{
/* Mark a substituted repha as USE_R. */
for (unsigned int i = start; i < end && (info[i].mask & mask); i++)
if (_hb_glyph_info_substituted (&info[i]))
{
info[i].use_category() = USE_R;
break;
}
}
}
static void
record_pref (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
{
/* Mark a substituted pref as VPre, as they behave the same way. */
for (unsigned int i = start; i < end; i++)
if (_hb_glyph_info_substituted (&info[i]))
{
info[i].use_category() = USE_VPre;
break;
}
}
}
static void
reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
/* Only a few syllable types need reordering. */
if (unlikely (!(FLAG_SAFE (syllable_type) &
(FLAG (virama_terminated_cluster) |
FLAG (consonant_cluster) |
FLAG (vowel_cluster) |
FLAG (broken_cluster) |
0))))
return;
hb_glyph_info_t *info = buffer->info;
#define HALANT_FLAGS FLAG(USE_H)
#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB) | FLAG (USE_IV))
/* Move things forward. */
if (info[start].use_category() == USE_R && end - start > 1)
{
/* Got a repha. Reorder it to after first base, before first halant. */
for (unsigned int i = start + 1; i < end; i++)
if (FLAG_UNSAFE (info[i].use_category()) & (HALANT_FLAGS | BASE_FLAGS))
{
/* If we hit a halant, move before it; otherwise it's a base: move to it's
* place, and shift things in between backward. */
if (info[i].use_category() == USE_H)
i--;
hb_glyph_info_t t = info[start];
memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0]));
info[i] = t;
buffer->merge_clusters (start, i + 1);
break;
}
}
/* Move things back. */
unsigned int j = end;
for (unsigned int i = start; i < end; i++)
{
uint32_t flag = FLAG_UNSAFE (info[i].use_category());
if (flag & (HALANT_FLAGS | BASE_FLAGS))
{
/* If we hit a halant, move before it; otherwise it's a base: move to it's
* place, and shift things in between backward. */
if (info[i].use_category() == USE_H)
j = i + 1;
else
j = i;
}
else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
/* Only move the first component of a MultipleSubst. */
0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
j < i)
{
hb_glyph_info_t t = info[i];
memmove (&info[j + 1], &info[j], (i - j) * sizeof (info[0]));
info[j] = t;
buffer->merge_clusters (j, i + 1);
}
}
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
/* Note: This loop is extra overhead, but should not be measurable. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == broken_cluster)
{
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
if (!font->get_glyph (0x25CCu, 0, &dottedcircle.codepoint))
return;
dottedcircle.use_category() = hb_use_get_categories (0x25CC);
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
info.syllable() = buffer->cur().syllable();
/* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().use_category() == USE_R)
buffer->next_glyph ();
buffer->output_info (info);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
reorder_syllable (buffer, start, end);
/* Zero syllables now... */
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
}
static bool
compose_use (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t a,
hb_codepoint_t b,
hb_codepoint_t *ab)
{
/* Avoid recomposing split matras. */
if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
return false;
return c->unicode->compose (a, b, ab);
}
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
{
"use",
collect_features_use,
NULL, /* override_features */
data_create_use,
data_destroy_use,
NULL, /* preprocess_text */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
NULL, /* decompose */
compose_use,
setup_masks_use,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};

View File

@ -59,10 +59,6 @@ static hb_tag_t horizontal_features[] = {
HB_TAG('r','c','l','t'),
};
static hb_tag_t vertical_features[] = {
HB_TAG('v','e','r','t'),
};
static void
@ -105,10 +101,13 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
(horizontal_features[i] == HB_TAG('k','e','r','n') ?
F_HAS_FALLBACK : F_NONE));
else
for (unsigned int i = 0; i < ARRAY_LENGTH (vertical_features); i++)
map->add_feature (vertical_features[i], 1, F_GLOBAL |
(vertical_features[i] == HB_TAG('v','k','r','n') ?
F_HAS_FALLBACK : F_NONE));
{
/* We really want to find a 'vert' feature if there's any in the font, no
* matter which script/langsys it is listed (or not) under.
* See various bugs referenced from:
* https://github.com/behdad/harfbuzz/issues/63 */
map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
}
if (planner->shaper->override_features)
planner->shaper->override_features (planner);
@ -264,11 +263,22 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
static void
hb_form_clusters (hb_buffer_t *buffer)
{
if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
return;
/* Loop duplicated in hb_ensure_native_direction(). */
unsigned int base = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
buffer->merge_clusters (i - 1, i + 1);
{
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
{
buffer->merge_clusters (base, i);
base = i;
}
}
buffer->merge_clusters (base, count);
}
static void
@ -283,7 +293,27 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
(HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB))
{
hb_buffer_reverse_clusters (buffer);
/* Same loop as hb_form_clusters().
* Since form_clusters() merged clusters already, we don't merge. */
unsigned int base = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
{
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
{
buffer->reverse_range (base, i);
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
buffer->merge_clusters (base, i);
base = i;
}
}
buffer->reverse_range (base, count);
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
buffer->merge_clusters (base, count);
buffer->reverse ();
buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
}
}
@ -305,7 +335,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c)
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++) {
hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
if (likely (codepoint == info[i].codepoint))
if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
info[i].mask |= rtlm_mask;
else
info[i].codepoint = codepoint;
@ -380,6 +410,101 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
}
}
static void
hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
return;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
unsigned int i = 0;
for (i = 0; i < count; i++)
if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
}
static void
hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
return;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
unsigned int i = 0;
for (i = 0; i < count; i++)
{
if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
break;
}
/* No default-ignorables found; return. */
if (i == count)
return;
hb_codepoint_t space;
if (c->font->get_glyph (' ', 0, &space))
{
/* Replace default-ignorables with a zero-advance space glyph. */
for (/*continue*/; i < count; i++)
{
if (_hb_glyph_info_is_default_ignorable (&info[i]))
info[i].codepoint = space;
}
}
else
{
/* Merge clusters and delete default-ignorables.
* NOTE! We can't use out-buffer as we have positioning data. */
unsigned int j = i;
for (; i < count; i++)
{
if (_hb_glyph_info_is_default_ignorable (&info[i]))
{
/* Merge clusters.
* Same logic as buffer->delete_glyph(), but for in-place removal. */
unsigned int cluster = info[i].cluster;
if (i + 1 < count && cluster == info[i + 1].cluster)
continue; /* Cluster survives; do nothing. */
if (j)
{
/* Merge cluster backward. */
if (cluster < info[j - 1].cluster)
{
unsigned int old_cluster = info[j - 1].cluster;
for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
info[k - 1].cluster = cluster;
}
continue;
}
if (i + 1 < count)
buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
continue;
}
if (j != i)
{
info[j] = info[i];
pos[j] = pos[i];
}
j++;
}
buffer->len = j;
}
}
static inline void
hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
{
@ -625,6 +750,8 @@ hb_ot_position (hb_ot_shape_context_t *c)
hb_bool_t fallback = !hb_ot_position_complex (c);
hb_ot_zero_width_default_ignorables (c);
hb_ot_layout_position_finish (c->font, c->buffer);
if (fallback && c->plan->shaper->fallback_position)
@ -642,53 +769,6 @@ hb_ot_position (hb_ot_shape_context_t *c)
}
/* Post-process */
static void
hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
{
if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
return;
hb_codepoint_t space;
enum {
SPACE_DONT_KNOW,
SPACE_AVAILABLE,
SPACE_UNAVAILABLE
} space_status = SPACE_DONT_KNOW;
unsigned int count = c->buffer->len;
hb_glyph_info_t *info = c->buffer->info;
hb_glyph_position_t *pos = c->buffer->pos;
unsigned int j = 0;
for (unsigned int i = 0; i < count; i++)
{
if (unlikely (!_hb_glyph_info_ligated (&info[i]) &&
_hb_glyph_info_is_default_ignorable (&info[i])))
{
if (space_status == SPACE_DONT_KNOW)
space_status = c->font->get_glyph (' ', 0, &space) ? SPACE_AVAILABLE : SPACE_UNAVAILABLE;
if (space_status == SPACE_AVAILABLE)
{
info[i].codepoint = space;
pos[i].x_advance = 0;
pos[i].y_advance = 0;
}
else
continue; /* Delete it. XXX Merge clusters? */
}
if (j != i)
{
info[j] = info[i];
pos[j] = pos[i];
}
j++;
}
c->buffer->len = j;
}
/* Pull it all together! */
static void
@ -736,6 +816,9 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan,
}
/**
* Since: 0.9.7
**/
void
hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
hb_tag_t table_tag,
@ -766,6 +849,9 @@ add_char (hb_font_t *font,
}
/**
* Since: 0.9.2
**/
void
hb_ot_shape_glyphs_closure (hb_font_t *font,
hb_buffer_t *buffer,

View File

@ -175,6 +175,11 @@ typedef struct {
*
* Some items still missing. Those are commented out at the end.
* Keep sorted for bsearch.
*
* Updated as of 2015-05-06: OT1.7 on MS website has some newer
* items that we don't have here, eg. Zazaki. This is the new
* items in OpenType 1.7 (red items), most of which we have:
* http://www.microsoft.com/typography/otspec170/languagetags.htm
*/
static const LangTag ot_languages[] = {
@ -217,9 +222,9 @@ static const LangTag ot_languages[] = {
{"bci", HB_TAG('B','A','U',' ')}, /* Baoulé */
{"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol */
{"bcq", HB_TAG('B','C','H',' ')}, /* Bench */
{"be", HB_TAG('B','E','L',' ')}, /* Belarusian */
{"be", HB_TAG('B','E','L',' ')}, /* Belarusian */
{"bem", HB_TAG('B','E','M',' ')}, /* Bemba (Zambia) */
{"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */
{"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */
{"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */
{"bft", HB_TAG('B','L','T',' ')}, /* Balti */
{"bfy", HB_TAG('B','A','G',' ')}, /* Baghelkhandi */
@ -346,9 +351,9 @@ static const LangTag ot_languages[] = {
{"gv", HB_TAG('M','N','X',' ')}, /* Manx */
{"ha", HB_TAG('H','A','U',' ')}, /* Hausa */
{"har", HB_TAG('H','R','I',' ')}, /* Harari */
{"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */
{"hay", HB_TAG('H','A','Y',' ')}, /* Haya */
{"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */
{"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */
{"hay", HB_TAG('H','A','Y',' ')}, /* Haya */
{"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */
{"he", HB_TAG('I','W','R',' ')}, /* Hebrew */
{"hz", HB_TAG('H','E','R',' ')}, /* Herero */
{"hi", HB_TAG('H','I','N',' ')}, /* Hindi */
@ -542,6 +547,7 @@ static const LangTag ot_languages[] = {
{"nr", HB_TAG('N','D','B',' ')}, /* [South] Ndebele */
{"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */
{"nso", HB_TAG('S','O','T',' ')}, /* [Northern] Sotho */
{"nv", HB_TAG('N','A','V',' ')}, /* Navajo */
{"ny", HB_TAG('C','H','I',' ')}, /* Chewa/Chichwa/Nyanja */
{"nym", HB_TAG('N','Y','M',' ')}, /* Nyamwezi */
{"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */
@ -864,6 +870,15 @@ hb_ot_tag_from_language (hb_language_t language)
return HB_OT_TAG_DEFAULT_LANGUAGE;
}
/**
* hb_ot_tag_to_language:
*
*
*
* Return value: (transfer none):
*
* Since: 1.0
**/
hb_language_t
hb_ot_tag_to_language (hb_tag_t tag)
{

View File

@ -193,7 +193,8 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
#define ASSERT_STATIC_EXPR(_cond)((void) sizeof (char[(_cond) ? 1 : -1]))
/* Note: C++ allows sizeof() of variable-lengh arrays. So, if _cond is not
* constant, it still compiles (ouch!), but at least we'll get a -Wvla warning. */
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1]))
#define _PASTE1(a,b) a##b
@ -247,8 +248,8 @@ ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
/* Void! */
struct _hb_void_t {};
typedef const _hb_void_t &hb_void_t;
#define HB_VOID (* (const _hb_void_t *) NULL)
typedef const _hb_void_t *hb_void_t;
#define HB_VOID ((const _hb_void_t *) NULL)
/* Return the number of 1 bits in mask. */
static inline HB_CONST_FUNC unsigned int
@ -845,9 +846,11 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
/* Useful for set-operations on small enums.
* For example, for testing "x ∈ {x1, x2, x3}" use:
* (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
* (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
*/
#define FLAG(x) (1<<(x))
#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((x) < 32) + (1U << (x)))
#define FLAG_SAFE(x) (1U << (x))
#define FLAG_UNSAFE(x) ((x) < 32 ? FLAG_SAFE(x) : 0)
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))

View File

@ -36,7 +36,15 @@
* "approximate member query". Conceptually these are like Bloom
* Filter and Quotient Filter, however, much smaller, faster, and
* designed to fit the requirements of our uses for glyph coverage
* queries. As a result, our filters have much higher.
* queries.
*
* Our filters are highly accurate if the lookup covers fairly local
* set of glyphs, but fully flooded and ineffective if coverage is
* all over the place.
*
* The frozen-set can be used instead of a digest, to trade more
* memory for 100% accuracy, but in practice, that doesn't look like
* an attractive trade-off.
*/
template <typename mask_t, unsigned int shift>

View File

@ -35,7 +35,7 @@
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.2
**/
hb_set_t *
hb_set_create (void)
@ -55,7 +55,7 @@ hb_set_create (void)
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.2
**/
hb_set_t *
hb_set_get_empty (void)
@ -76,7 +76,7 @@ hb_set_get_empty (void)
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.2
**/
hb_set_t *
hb_set_reference (hb_set_t *set)
@ -88,7 +88,7 @@ hb_set_reference (hb_set_t *set)
* hb_set_destroy: (skip)
* @set: a set.
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_destroy (hb_set_t *set)
@ -110,7 +110,7 @@ hb_set_destroy (hb_set_t *set)
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_set_set_user_data (hb_set_t *set,
@ -129,7 +129,7 @@ hb_set_set_user_data (hb_set_t *set,
*
* Return value: (transfer none):
*
* Since: 1.0
* Since: 0.9.2
**/
void *
hb_set_get_user_data (hb_set_t *set,
@ -147,7 +147,7 @@ hb_set_get_user_data (hb_set_t *set,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_set_allocation_successful (const hb_set_t *set HB_UNUSED)
@ -161,7 +161,7 @@ hb_set_allocation_successful (const hb_set_t *set HB_UNUSED)
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_clear (hb_set_t *set)
@ -177,7 +177,7 @@ hb_set_clear (hb_set_t *set)
*
* Return value:
*
* Since: 1.0
* Since: 0.9.7
**/
hb_bool_t
hb_set_is_empty (const hb_set_t *set)
@ -194,7 +194,7 @@ hb_set_is_empty (const hb_set_t *set)
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_set_has (const hb_set_t *set,
@ -210,7 +210,7 @@ hb_set_has (const hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_add (hb_set_t *set,
@ -227,7 +227,7 @@ hb_set_add (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_set_add_range (hb_set_t *set,
@ -244,7 +244,7 @@ hb_set_add_range (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_del (hb_set_t *set,
@ -261,7 +261,7 @@ hb_set_del (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_set_del_range (hb_set_t *set,
@ -280,7 +280,7 @@ hb_set_del_range (hb_set_t *set,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.7
**/
hb_bool_t
hb_set_is_equal (const hb_set_t *set,
@ -296,7 +296,7 @@ hb_set_is_equal (const hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_set (hb_set_t *set,
@ -312,7 +312,7 @@ hb_set_set (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_union (hb_set_t *set,
@ -328,7 +328,7 @@ hb_set_union (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_intersect (hb_set_t *set,
@ -344,7 +344,7 @@ hb_set_intersect (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_subtract (hb_set_t *set,
@ -360,7 +360,7 @@ hb_set_subtract (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_set_symmetric_difference (hb_set_t *set,
@ -375,7 +375,7 @@ hb_set_symmetric_difference (hb_set_t *set,
*
*
*
* Since: 1.0
* Since: 0.9.10
**/
void
hb_set_invert (hb_set_t *set)
@ -391,7 +391,7 @@ hb_set_invert (hb_set_t *set)
*
* Return value: set population.
*
* Since: 1.0
* Since: 0.9.7
**/
unsigned int
hb_set_get_population (const hb_set_t *set)
@ -407,7 +407,7 @@ hb_set_get_population (const hb_set_t *set)
*
* Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty.
*
* Since: 1.0
* Since: 0.9.7
**/
hb_codepoint_t
hb_set_get_min (const hb_set_t *set)
@ -423,7 +423,7 @@ hb_set_get_min (const hb_set_t *set)
*
* Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty.
*
* Since: 1.0
* Since: 0.9.7
**/
hb_codepoint_t
hb_set_get_max (const hb_set_t *set)
@ -440,7 +440,7 @@ hb_set_get_max (const hb_set_t *set)
*
* Return value: whether there was a next value.
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_set_next (const hb_set_t *set,
@ -460,7 +460,7 @@ hb_set_next (const hb_set_t *set,
*
* Return value: whether there was a next range.
*
* Since: 1.0
* Since: 0.9.7
**/
hb_bool_t
hb_set_next_range (const hb_set_t *set,

View File

@ -106,7 +106,7 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.7
**/
hb_shape_plan_t *
hb_shape_plan_create (hb_face_t *face,
@ -158,7 +158,7 @@ hb_shape_plan_create (hb_face_t *face,
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.7
**/
hb_shape_plan_t *
hb_shape_plan_get_empty (void)
@ -194,7 +194,7 @@ hb_shape_plan_get_empty (void)
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.7
**/
hb_shape_plan_t *
hb_shape_plan_reference (hb_shape_plan_t *shape_plan)
@ -208,7 +208,7 @@ hb_shape_plan_reference (hb_shape_plan_t *shape_plan)
*
*
*
* Since: 1.0
* Since: 0.9.7
**/
void
hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
@ -236,7 +236,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
*
* Return value:
*
* Since: 1.0
* Since: 0.9.7
**/
hb_bool_t
hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
@ -257,7 +257,7 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
*
* Return value: (transfer none):
*
* Since: 1.0
* Since: 0.9.7
**/
void *
hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
@ -279,7 +279,7 @@ hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.7
**/
hb_bool_t
hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
@ -395,7 +395,7 @@ hb_non_global_user_features_present (const hb_feature_t *user_features,
*
* Return value: (transfer full):
*
* Since: 1.0
* Since: 0.9.7
**/
hb_shape_plan_t *
hb_shape_plan_create_cached (hb_face_t *face,
@ -486,7 +486,7 @@ retry:
*
* Return value: (transfer none):
*
* Since: 1.0
* Since: 0.9.7
**/
const char *
hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)

View File

@ -33,6 +33,17 @@
#include "hb-buffer-private.hh"
#include "hb-font-private.hh"
/**
* SECTION:hb-shape
* @title: Shaping
* @short_description: Conversion of text strings into positioned glyphs
* @include: hb.h
*
* Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
* which are sequences of Unicode characters that use the same font and have
* the same text direction, script and language. After shaping the buffer
* contains the output glyphs and their positions.
**/
static bool
parse_space (const char **pp, const char *end)
@ -198,15 +209,16 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
/**
* hb_feature_from_string:
* @str: (array length=len) (element-type uint8_t):
* @len:
* @feature: (out) (optional):
* @str: (array length=len) (element-type uint8_t): a string to parse
* @len: length of @str, or -1 if string is nul-terminated
* @feature: (out): the #hb_feature_t to initialize with the parsed values
*
*
* Parses a string into a #hb_feature_t. If @len is -1 then @str is
* %NULL-terminated.
*
* Return value:
* Return value: %TRUE if @str is successfully parsed, %FALSE otherwise
*
* Since: 1.0
* Since: 0.9.5
**/
hb_bool_t
hb_feature_from_string (const char *str, int len,
@ -231,13 +243,15 @@ hb_feature_from_string (const char *str, int len,
/**
* hb_feature_to_string:
* @feature:
* @buf: (array length=size):
* @size:
* @feature: an #hb_feature_t to convert
* @buf: (array length=size) (out): output string
* @size: the allocated size of @buf
*
*
* Converts a #hb_feature_t into a %NULL-terminated string in the format
* understood by hb_feature_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
* Since: 1.0
* Since: 0.9.5
**/
void
hb_feature_to_string (hb_feature_t *feature,
@ -290,11 +304,12 @@ void free_static_shaper_list (void)
/**
* hb_shape_list_shapers:
*
*
* Retrieves the list of shapers supported by HarfBuzz.
*
* Return value: (transfer none):
* Return value: (transfer none) (array zero-terminated=1): an array of
* constant strings
*
* Since: 1.0
* Since: 0.9.2
**/
const char **
hb_shape_list_shapers (void)
@ -333,17 +348,21 @@ retry:
/**
* hb_shape_full:
* @font: a font.
* @buffer: a buffer.
* @features: (array length=num_features):
* @num_features:
* @shaper_list: (array zero-terminated=1):
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (allow-none): an array of user
* specified #hb_feature_t or %NULL
* @num_features: the length of @features array
* @shaper_list: (array zero-terminated=1) (allow-none): a %NULL-terminated
* array of shapers to use or %NULL
*
*
* See hb_shape() for details. If @shaper_list is not %NULL, the specified
* shapers will be used in the given order, otherwise the default shapers list
* will be used.
*
* Return value:
* Return value: %FALSE if all shapers failed, %TRUE otherwise
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_shape_full (hb_font_t *font,
@ -368,12 +387,17 @@ hb_shape_full (hb_font_t *font,
/**
* hb_shape:
* @font: a font.
* @buffer: a buffer.
* @features: (array length=num_features):
* @num_features:
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (allow-none): an array of user
* specified #hb_feature_t or %NULL
* @num_features: the length of @features array
*
*
* Shapes @buffer using @font turning its Unicode characters content to
* positioned glyphs. If @features is not %NULL, it will be used to control the
* features applied during shaping.
*
* Return value: %FALSE if all shapers failed, %TRUE otherwise
*
* Since: 1.0
**/

View File

@ -47,13 +47,10 @@ typedef struct hb_feature_t {
unsigned int end;
} hb_feature_t;
/* len=-1 means str is NUL-terminated */
hb_bool_t
hb_feature_from_string (const char *str, int len,
hb_feature_t *feature);
/* Something like 128 bytes is more than enough.
* nul-terminates. */
void
hb_feature_to_string (hb_feature_t *feature,
char *buf, unsigned int size);

View File

@ -148,6 +148,12 @@ static const hb_script_t ucdn_script_translate[] =
HB_SCRIPT_SIDDHAM,
HB_SCRIPT_TIRHUTA,
HB_SCRIPT_WARANG_CITI,
HB_SCRIPT_AHOM,
HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
HB_SCRIPT_HATRAN,
HB_SCRIPT_MULTANI,
HB_SCRIPT_OLD_HUNGARIAN,
HB_SCRIPT_SIGNWRITING,
};
static hb_unicode_combining_class_t

View File

@ -308,7 +308,7 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
/* Misc */
#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
(FLAG (gen_cat) & \
(FLAG_SAFE (gen_cat) & \
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))

View File

@ -146,14 +146,9 @@ hb_unicode_funcs_get_default (void)
}
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
#ifdef _MSC_VER
#pragma error("Could not find any Unicode functions implementation, you have to provide your own.")
#pragma error("Consider building hb-ucdn.c. If you absolutely want to build without any, check the code.")
#else
#error "Could not find any Unicode functions implementation, you have to provide your own"
#error "Consider building hb-ucdn.c. If you absolutely want to build without any, check the code."
#endif
#endif
/**
* hb_unicode_funcs_create: (Xconstructor)
@ -400,7 +395,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
@ -422,7 +417,7 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
hb_bool_t
hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
@ -443,7 +438,7 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
*
* Return value:
*
* Since: 1.0
* Since: 0.9.2
**/
unsigned int
hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,

View File

@ -363,7 +363,7 @@ hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
@ -379,7 +379,7 @@ hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
@ -395,7 +395,7 @@ hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
*
*
*
* Since: 1.0
* Since: 0.9.2
**/
void
hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
@ -404,37 +404,62 @@ hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
/* accessors */
/**
* Since: 0.9.2
**/
hb_unicode_combining_class_t
hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* Since: 0.9.2
**/
unsigned int
hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* Since: 0.9.2
**/
hb_unicode_general_category_t
hb_unicode_general_category (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* Since: 0.9.2
**/
hb_codepoint_t
hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* Since: 0.9.2
**/
hb_script_t
hb_unicode_script (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* Since: 0.9.2
**/
hb_bool_t
hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t a,
hb_codepoint_t b,
hb_codepoint_t *ab);
/**
* Since: 0.9.2
**/
hb_bool_t
hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t ab,
hb_codepoint_t *a,
hb_codepoint_t *b);
/**
* Since: 0.9.2
**/
unsigned int
hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t u,

View File

@ -36,11 +36,11 @@
HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 0
#define HB_VERSION_MINOR 9
#define HB_VERSION_MICRO 40
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 0
#define HB_VERSION_MICRO 1
#define HB_VERSION_STRING "0.9.40"
#define HB_VERSION_STRING "1.0.1"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \

View File

@ -29,21 +29,11 @@
#if defined(HB_ATOMIC_INT_NIL)
#ifdef _MSC_VER
#pragma error("Could not find any system to define atomic_int macros, library WILL NOT be thread-safe")
#pragma error("Check hb-atomic-private.hh for possible resolutions.")
#else
#error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
#error "Check hb-atomic-private.hh for possible resolutions."
#endif
#endif
#if defined(HB_MUTEX_IMPL_NIL)
#ifdef _MSC_VER
#pragma error("Could not find any system to define mutex macros, library WILL NOT be thread-safe")
#pragma error("Check hb-mutex-private.hh for possible resolutions.")
#else
#error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
#error "Check hb-mutex-private.hh for possible resolutions."
#endif
#endif

View File

@ -29,7 +29,7 @@ SOURCES += [
'hb-common.cc', # error: use of undeclared identifier 'strdup'
'hb-ot-shape-complex-hangul.cc', # error: redefinition of enumerator 'NONE'
'hb-ot-shape-complex-indic.cc', # error: redefinition of enumerator 'INIT'
'hb-ot-shape-complex-sea.cc', # error: redefinition of 'basic_features'
'hb-ot-shape-complex-use.cc', # error: redefinition of 'basic_features'
'hb-ot-shape.cc', # error: functions that differ only in their return type cannot be overloaded
'hb-shape-plan.cc', # error: redefinition of 'hb_ot_shaper_face_data_ensure'
]
@ -48,6 +48,7 @@ UNIFIED_SOURCES += [
'hb-ot-shape-complex-myanmar.cc',
'hb-ot-shape-complex-thai.cc',
'hb-ot-shape-complex-tibetan.cc',
'hb-ot-shape-complex-use-table.cc',
'hb-ot-shape-fallback.cc',
'hb-ot-shape-normalize.cc',
'hb-ot-tag.cc',

View File

@ -191,6 +191,8 @@ public:
gfx::Matrix4x4 mMVMatrix;
size_t mRects;
gfx::Rect mLayerRects[4];
gfx::Rect mTextureRects[4];
std::list<GLuint> mTexIDs;
};
class ContentMonitor {
@ -289,6 +291,18 @@ public:
return *mSession;
}
void SetPixelScale(double scale) {
mScale = scale;
}
double GetPixelScale() const {
return mScale;
}
LayerScopeManager()
: mScale(1.0)
{
}
private:
friend class CreateServerSocketRunnable;
class CreateServerSocketRunnable : public nsRunnable
@ -310,6 +324,7 @@ private:
mozilla::UniquePtr<LayerScopeWebSocketManager> mWebSocketManager;
mozilla::UniquePtr<DrawSession> mSession;
mozilla::UniquePtr<ContentMonitor> mContentMonitor;
double mScale;
};
LayerScopeManager gLayerScopeManager;
@ -367,6 +382,8 @@ public:
FramePacket* fp = packet.mutable_frame();
fp->set_value(static_cast<uint64_t>(mFrameStamp));
fp->set_scale(gLayerScopeManager.GetPixelScale());
return WriteToStream(packet);
}
@ -623,16 +640,20 @@ public:
const gfx::Matrix4x4& aMVMatrix,
size_t aRects,
const gfx::Rect* aLayerRects,
const gfx::Rect* aTextureRects,
const std::list<GLuint> aTexIDs,
void* aLayerRef)
: DebugGLData(Packet::DRAW),
mOffsetX(aOffsetX),
mOffsetY(aOffsetY),
mMVMatrix(aMVMatrix),
mRects(aRects),
mTexIDs(aTexIDs),
mLayerRef(reinterpret_cast<uint64_t>(aLayerRef))
{
for (size_t i = 0; i < mRects; i++){
mLayerRects[i] = aLayerRects[i];
mTextureRects[i] = aTextureRects[i];
}
}
@ -654,11 +675,23 @@ public:
MOZ_ASSERT(mRects > 0 && mRects < 4);
for (size_t i = 0; i < mRects; i++) {
// Vertex
layerscope::DrawPacket::Rect* pRect = dp->add_layerrect();
pRect->set_x(mLayerRects[i].x);
pRect->set_y(mLayerRects[i].y);
pRect->set_w(mLayerRects[i].width);
pRect->set_h(mLayerRects[i].height);
// UV
pRect = dp->add_texturerect();
pRect->set_x(mTextureRects[i].x);
pRect->set_y(mTextureRects[i].y);
pRect->set_w(mTextureRects[i].width);
pRect->set_h(mTextureRects[i].height);
}
for (GLuint texId: mTexIDs) {
dp->add_texids(texId);
}
return WriteToStream(packet);
@ -670,6 +703,8 @@ protected:
gfx::Matrix4x4 mMVMatrix;
size_t mRects;
gfx::Rect mLayerRects[4];
gfx::Rect mTextureRects[4];
std::list<GLuint> mTexIDs;
uint64_t mLayerRef;
};
@ -955,6 +990,8 @@ SenderHelper::SendTextureSource(GLContext* aGLContext,
aTexID, img));
sTextureIdList.push_back(aTexID);
gLayerScopeManager.CurrentSession().mTexIDs.push_back(aTexID);
}
#ifdef MOZ_WIDGET_GONK
@ -983,6 +1020,8 @@ SenderHelper::SendGraphicBuffer(void* aLayerRef,
gLayerScopeManager.GetSocketManager()->AppendDebugData(package.release());
sTextureIdList.push_back(aTexID);
gLayerScopeManager.CurrentSession().mTexIDs.push_back(aTexID);
gLayerScopeManager.GetContentMonitor()->ClearChangedHost(aEffect->mState.mTexture);
return true;
}
@ -1585,7 +1624,8 @@ LayerScope::DrawBegin()
gLayerScopeManager.NewDrawSession();
}
void LayerScope::SetRenderOffset(float aX, float aY)
void
LayerScope::SetRenderOffset(float aX, float aY)
{
if (!CheckSendable()) {
return;
@ -1595,7 +1635,8 @@ void LayerScope::SetRenderOffset(float aX, float aY)
gLayerScopeManager.CurrentSession().mOffsetY = aY;
}
void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
void
LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
{
if (!CheckSendable()) {
return;
@ -1604,7 +1645,10 @@ void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
gLayerScopeManager.CurrentSession().mMVMatrix = aMatrix;
}
void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects)
void
LayerScope::SetDrawRects(size_t aRects,
const gfx::Rect* aLayerRects,
const gfx::Rect* aTextureRects)
{
if (!CheckSendable()) {
return;
@ -1617,6 +1661,7 @@ void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects)
for (size_t i = 0; i < aRects; i++){
gLayerScopeManager.CurrentSession().mLayerRects[i] = aLayerRects[i];
gLayerScopeManager.CurrentSession().mTextureRects[i] = aTextureRects[i];
}
}
@ -1631,17 +1676,20 @@ LayerScope::DrawEnd(gl::GLContext* aGLContext,
return;
}
// 1. Send parameters of draw call, such as uniforms and attributes of
// 1. Send textures.
SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight);
// 2. Send parameters of draw call, such as uniforms and attributes of
// vertex adnd fragment shader.
DrawSession& draws = gLayerScopeManager.CurrentSession();
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLDrawData(draws.mOffsetX, draws.mOffsetY,
draws.mMVMatrix, draws.mRects,
draws.mLayerRects,
draws.mTextureRects,
draws.mTexIDs,
aEffectChain.mLayerRef));
// 2. Send textures.
SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight);
}
void
@ -1703,6 +1751,11 @@ LayerScope::SetHWComposed()
}
}
void
LayerScope::SetPixelScale(double devPixelsPerCSSPixel)
{
gLayerScopeManager.SetPixelScale(devPixelsPerCSSPixel);
}
// ----------------------------------------------
// LayerScopeAutoFrame implementation
// ----------------------------------------------
@ -1721,11 +1774,10 @@ LayerScopeAutoFrame::~LayerScopeAutoFrame()
void
LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp)
{
SenderHelper::ClearTextureIdList();
if (!LayerScope::CheckSendable()) {
return;
}
SenderHelper::ClearTextureIdList();
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLFrameStatusData(Packet::FRAMESTART, aFrameStamp));

View File

@ -26,7 +26,9 @@ public:
static void DrawBegin();
static void SetRenderOffset(float aX, float aY);
static void SetLayerTransform(const gfx::Matrix4x4& aMatrix);
static void SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects);
static void SetDrawRects(size_t aRects,
const gfx::Rect* aLayerRects,
const gfx::Rect* aTextureRects);
static void DrawEnd(gl::GLContext* aGLContext,
const EffectChain& aEffectChain,
int aWidth,
@ -40,6 +42,7 @@ public:
static void CleanLayer();
static void SetHWComposed();
static void SetPixelScale(double devPixelsPerCSSPixel);
static void ContentChanged(TextureHost *host);
private:
static void Init();

View File

@ -36,6 +36,7 @@
#include "nsPrintfCString.h" // for nsPrintfCString
#include "nsStyleStruct.h" // for nsTimingFunction, etc
#include "protobuf/LayerScopePacket.pb.h"
#include "mozilla/Compression.h"
uint8_t gLayerManagerLayerBuilder;
@ -51,6 +52,7 @@ FILEOrDefault(FILE* aFile)
typedef FrameMetrics::ViewID ViewID;
using namespace mozilla::gfx;
using namespace mozilla::Compression;
//--------------------------------------------------
// LayerManager
@ -1591,6 +1593,35 @@ Layer::Dump(layerscope::LayersPacket* aPacket, const void* aParent)
}
}
void
Layer::SetDisplayListLog(const char* log)
{
if (gfxUtils::DumpDisplayList()) {
mDisplayListLog = log;
}
}
void
Layer::GetDisplayListLog(nsCString& log)
{
log.SetLength(0);
if (gfxUtils::DumpDisplayList()) {
// This function returns a plain text string which consists of two things
// 1. DisplayList log.
// 2. Memory address of this layer.
// We know the target layer of each display item by information in #1.
// Here is an example of a Text display item line log in #1
// Text p=0xa9850c00 f=0x0xaa405b00(.....
// f keeps the address of the target client layer of a display item.
// For LayerScope, display-item-to-client-layer mapping is not enough since
// LayerScope, which lives in the chrome process, knows only composite layers.
// As so, we need display-item-to-client-layer-to-layer-composite
// mapping. That's the reason we insert #2 into the log
log.AppendPrintf("0x%p\n%s",(void*) this, mDisplayListLog.get());
}
}
void
Layer::Log(const char* aPrefix)
{
@ -1807,10 +1838,22 @@ Layer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
LayersPacket::Layer::HORIZONTAL);
layer->set_barid(GetScrollbarTargetContainerId());
}
// Mask layer
if (mMaskLayer) {
layer->set_mask(reinterpret_cast<uint64_t>(mMaskLayer.get()));
}
// DisplayList log.
if (mDisplayListLog.Length() > 0) {
layer->set_displaylistloglength(mDisplayListLog.Length());
auto compressedData =
MakeUnique<char[]>(LZ4::maxCompressedSize(mDisplayListLog.Length()));
int compressedSize = LZ4::compress((char*)mDisplayListLog.get(),
mDisplayListLog.Length(),
compressedData.get());
layer->set_displaylistlog(compressedData.get(), compressedSize);
}
}
void

View File

@ -258,11 +258,11 @@ public:
* The callee must draw all of aRegionToDraw.
* This region is relative to 0,0 in the PaintedLayer.
*
* aDirtyRegion contains the region that is due to be painted at some point,
* even though only aRegionToDraw should be drawn during this call.
* They will often be equal, but aDirtyRegion may be larger, for example
* when painting progressively. aRegionToDraw must be entirely contained
* within aDirtyRegion.
* aDirtyRegion, if non-null, contains the total region that is due to be
* painted during the transaction, even though only aRegionToDraw should
* be drawn during this call. The sum of every aRegionToDraw over the
* course of the transaction must equal aDirtyRegion. aDirtyRegion can be
* null if the total dirty region is unknown.
*
* aRegionToInvalidate contains a region whose contents have been
* changed by the layer manager and which must therefore be invalidated.
@ -284,7 +284,7 @@ public:
typedef void (* DrawPaintedLayerCallback)(PaintedLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aDirtyRegion,
const nsIntRegion* aDirtyRegion,
DrawRegionClip aClip,
const nsIntRegion& aRegionToInvalidate,
void* aCallbackData);
@ -1583,6 +1583,16 @@ public:
// instead of a StringStream. It is also internally used to implement Dump();
virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent);
/**
* Store display list log.
*/
void SetDisplayListLog(const char *log);
/**
* Return display list log.
*/
void GetDisplayListLog(nsCString& log);
static bool IsLogEnabled() { return LayerManager::IsLogEnabled(); }
/**
@ -1785,6 +1795,8 @@ protected:
#ifdef MOZ_DUMP_PAINTING
nsTArray<nsCString> mExtraDumpInfo;
#endif
// Store display list log.
nsCString mDisplayListLog;
};
/**

View File

@ -735,14 +735,6 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
return nullptr;
}
if (result->GetBackendType() == BackendType::DIRECT2D ||
result->GetBackendType() == BackendType::DIRECT2D1_1) {
// Simplify the draw region to avoid hitting expensive drawing paths for
// complex regions. Must be applied to the entire draw region so that it
// remains a superset of the iterator's draw region.
aPaintState.mRegionToDraw.SimplifyOutwardByArea(100 * 100);
}
nsIntRegion* drawPtr = &aPaintState.mRegionToDraw;
if (aIter) {
// The iterators draw region currently only contains the bounds of the region,
@ -750,6 +742,12 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
aIter->mDrawRegion.And(aIter->mDrawRegion, aPaintState.mRegionToDraw);
drawPtr = &aIter->mDrawRegion;
}
if (result->GetBackendType() == BackendType::DIRECT2D ||
result->GetBackendType() == BackendType::DIRECT2D1_1) {
// Simplify the draw region to avoid hitting expensive drawing paths
// for complex regions.
drawPtr->SimplifyOutwardByArea(100 * 100);
}
if (aPaintState.mMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
if (!mDTBuffer || !mDTBufferOnWhite) {

View File

@ -91,7 +91,7 @@ BasicPaintedLayer::PaintThebes(gfxContext* aContext,
groupContext = aContext;
}
SetAntialiasingFlags(this, groupContext->GetDrawTarget());
aCallback(this, groupContext, toDraw, toDraw,
aCallback(this, groupContext, toDraw, &toDraw,
DrawRegionClip::NONE, nsIntRegion(), aCallbackData);
if (needsGroup) {
aContext->PopGroupToSource();

View File

@ -112,7 +112,7 @@ protected:
BasicManager()->SetTransactionIncomplete();
return;
}
aCallback(this, aContext, aExtendedRegionToDraw, aExtendedRegionToDraw,
aCallback(this, aContext, aExtendedRegionToDraw, &aExtendedRegionToDraw,
aClip, aRegionToInvalidate, aCallbackData);
// Everything that's visible has been validated. Do this instead of just
// OR-ing with aRegionToDraw, since that can lead to a very complex region

View File

@ -87,7 +87,7 @@ ClientPaintedLayer::PaintThebes()
ClientManager()->GetPaintedLayerCallback()(this,
ctx,
iter.mDrawRegion,
state.mRegionToDraw,
nullptr,
state.mClip,
state.mRegionToInvalidate,
ClientManager()->GetPaintedLayerCallbackData());

View File

@ -181,7 +181,7 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
nsRefPtr<gfxContext> ctx = new gfxContext(dt);
ctx->SetMatrix(ctx->CurrentMatrix().Translate(-mTilingOrigin.x, -mTilingOrigin.y));
aCallback(mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
aCallback(mPaintedLayer, ctx, paintRegion, &paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
}
// Mark the area we just drew into the back buffer as invalid in the front buffer as they're

View File

@ -964,7 +964,7 @@ ClientMultiTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw",
js::ProfileEntry::Category::GRAPHICS);
mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion,
mCallback(mPaintedLayer, ctxt, aPaintRegion, &aDirtyRegion,
DrawRegionClip::NONE, nsIntRegion(), mCallbackData);
}
@ -1171,7 +1171,7 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
ctx->SetMatrix(
ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin)));
mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion,
mCallback(mPaintedLayer, ctx, aPaintRegion, &aDirtyRegion,
DrawRegionClip::DRAW, nsIntRegion(), mCallbackData);
mMoz2DTiles.clear();
// Reset:

View File

@ -75,6 +75,8 @@
#include "GeckoTouchDispatcher.h"
#endif
#include "LayerScope.h"
namespace mozilla {
namespace layers {
@ -681,6 +683,8 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
}
gfxPlatform::GetPlatform()->ComputeTileSize();
LayerScope::SetPixelScale(mWidget->GetDefaultScale().scale);
}
bool

View File

@ -347,6 +347,7 @@ LayerTransactionParent::RecvUpdate(InfallibleTArray<Edit>&& cset,
layer->SetAnimations(common.animations());
layer->SetInvalidRegion(common.invalidRegion());
layer->SetFrameMetrics(common.metrics());
layer->SetDisplayListLog(common.displayListLog().get());
nsTArray<nsRefPtr<Layer>> maskLayers;
for (size_t i = 0; i < common.ancestorMaskLayersParent().Length(); i++) {

View File

@ -233,6 +233,7 @@ struct CommonLayerAttributes {
nsIntRegion invalidRegion;
FrameMetrics[] metrics;
string contentDescription;
nsCString displayListLog;
};
struct PaintedLayerAttributes {

View File

@ -613,6 +613,10 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
auto layer = Shadow(mutant->GetAncestorMaskLayerAt(i)->AsShadowableLayer());
common.ancestorMaskLayersChild().AppendElement(layer);
}
nsCString log;
mutant->GetDisplayListLog(log);
common.displayListLog() = log;
attrs.specific() = null_t();
mutant->FillSpecificAttributes(attrs.specific());

View File

@ -1627,7 +1627,7 @@ CompositorOGL::BindAndDrawQuads(ShaderProgramOGL *aProg,
// We are using GL_TRIANGLES here because the Mac Intel drivers fail to properly
// process uniform arrays with GL_TRIANGLE_STRIP. Go figure.
mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, 6 * aQuads);
LayerScope::SetLayerRects(aQuads, aLayerRects);
LayerScope::SetDrawRects(aQuads, aLayerRects, aTextureRects);
}
GLBlitTextureImageHelper*

View File

@ -99,6 +99,7 @@ struct StaticDescriptorInitializer_LayerScopePacket_2eproto {
#ifndef _MSC_VER
const int FramePacket::kValueFieldNumber;
const int FramePacket::kScaleFieldNumber;
#endif // !_MSC_VER
FramePacket::FramePacket()
@ -120,6 +121,7 @@ FramePacket::FramePacket(const FramePacket& from)
void FramePacket::SharedCtor() {
_cached_size_ = 0;
value_ = GOOGLE_ULONGLONG(0);
scale_ = 0;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@ -158,7 +160,21 @@ FramePacket* FramePacket::New() const {
}
void FramePacket::Clear() {
value_ = GOOGLE_ULONGLONG(0);
#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
&reinterpret_cast<FramePacket*>(16)->f) - \
reinterpret_cast<char*>(16))
#define ZR_(first, last) do { \
size_t f = OFFSET_OF_FIELD_(first); \
size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
::memset(&first, 0, n); \
} while (0)
ZR_(value_, scale_);
#undef OFFSET_OF_FIELD_
#undef ZR_
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->clear();
}
@ -187,6 +203,21 @@ bool FramePacket::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(21)) goto parse_scale;
break;
}
// optional float scale = 2;
case 2: {
if (tag == 21) {
parse_scale:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
input, &scale_)));
set_has_scale();
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
@ -221,6 +252,11 @@ void FramePacket::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->value(), output);
}
// optional float scale = 2;
if (has_scale()) {
::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->scale(), output);
}
output->WriteRaw(unknown_fields().data(),
unknown_fields().size());
// @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.FramePacket)
@ -237,6 +273,11 @@ int FramePacket::ByteSize() const {
this->value());
}
// optional float scale = 2;
if (has_scale()) {
total_size += 1 + 4;
}
}
total_size += unknown_fields().size();
@ -257,6 +298,9 @@ void FramePacket::MergeFrom(const FramePacket& from) {
if (from.has_value()) {
set_value(from.value());
}
if (from.has_scale()) {
set_scale(from.scale());
}
}
mutable_unknown_fields()->append(from.unknown_fields());
}
@ -275,6 +319,7 @@ bool FramePacket::IsInitialized() const {
void FramePacket::Swap(FramePacket* other) {
if (other != this) {
std::swap(value_, other->value_);
std::swap(scale_, other->scale_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.swap(other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);
@ -2459,6 +2504,8 @@ const int LayersPacket_Layer::kColorFieldNumber;
const int LayersPacket_Layer::kFilterFieldNumber;
const int LayersPacket_Layer::kRefIDFieldNumber;
const int LayersPacket_Layer::kSizeFieldNumber;
const int LayersPacket_Layer::kDisplayListLogLengthFieldNumber;
const int LayersPacket_Layer::kDisplayListLogFieldNumber;
#endif // !_MSC_VER
LayersPacket_Layer::LayersPacket_Layer()
@ -2544,6 +2591,7 @@ LayersPacket_Layer::LayersPacket_Layer(const LayersPacket_Layer& from)
}
void LayersPacket_Layer::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
type_ = 0;
ptr_ = GOOGLE_ULONGLONG(0);
@ -2568,6 +2616,8 @@ void LayersPacket_Layer::SharedCtor() {
filter_ = 0;
refid_ = GOOGLE_ULONGLONG(0);
size_ = NULL;
displaylistloglength_ = 0u;
displaylistlog_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@ -2577,6 +2627,9 @@ LayersPacket_Layer::~LayersPacket_Layer() {
}
void LayersPacket_Layer::SharedDtor() {
if (displaylistlog_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete displaylistlog_;
}
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
if (this != &default_instance()) {
#else
@ -2657,7 +2710,7 @@ void LayersPacket_Layer::Clear() {
if (noactionregion_ != NULL) noactionregion_->::mozilla::layers::layerscope::LayersPacket_Layer_Region::Clear();
}
}
if (_has_bits_[16 / 32] & 8323072) {
if (_has_bits_[16 / 32] & 16711680) {
ZR_(color_, refid_);
if (has_hpanregion()) {
if (hpanregion_ != NULL) hpanregion_->::mozilla::layers::layerscope::LayersPacket_Layer_Region::Clear();
@ -2671,6 +2724,12 @@ void LayersPacket_Layer::Clear() {
if (has_size()) {
if (size_ != NULL) size_->::mozilla::layers::layerscope::LayersPacket_Layer_Size::Clear();
}
displaylistloglength_ = 0u;
}
if (has_displaylistlog()) {
if (displaylistlog_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
displaylistlog_->clear();
}
}
#undef OFFSET_OF_FIELD_
@ -3030,6 +3089,34 @@ bool LayersPacket_Layer::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(840)) goto parse_displayListLogLength;
break;
}
// optional uint32 displayListLogLength = 105;
case 105: {
if (tag == 840) {
parse_displayListLogLength:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
input, &displaylistloglength_)));
set_has_displaylistloglength();
} else {
goto handle_unusual;
}
if (input->ExpectTag(850)) goto parse_displayListLog;
break;
}
// optional bytes displayListLog = 106;
case 106: {
if (tag == 850) {
parse_displayListLog:
DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
input, this->mutable_displaylistlog()));
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
@ -3188,6 +3275,17 @@ void LayersPacket_Layer::SerializeWithCachedSizes(
104, this->size(), output);
}
// optional uint32 displayListLogLength = 105;
if (has_displaylistloglength()) {
::google::protobuf::internal::WireFormatLite::WriteUInt32(105, this->displaylistloglength(), output);
}
// optional bytes displayListLog = 106;
if (has_displaylistlog()) {
::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
106, this->displaylistlog(), output);
}
output->WriteRaw(unknown_fields().data(),
unknown_fields().size());
// @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.LayersPacket.Layer)
@ -3353,6 +3451,22 @@ int LayersPacket_Layer::ByteSize() const {
this->size());
}
// optional uint32 displayListLogLength = 105;
if (has_displaylistloglength()) {
total_size += 2 +
::google::protobuf::internal::WireFormatLite::UInt32Size(
this->displaylistloglength());
}
}
if (_has_bits_[24 / 32] & (0xffu << (24 % 32))) {
// optional bytes displayListLog = 106;
if (has_displaylistlog()) {
total_size += 2 +
::google::protobuf::internal::WireFormatLite::BytesSize(
this->displaylistlog());
}
}
total_size += unknown_fields().size();
@ -3443,6 +3557,14 @@ void LayersPacket_Layer::MergeFrom(const LayersPacket_Layer& from) {
if (from.has_size()) {
mutable_size()->::mozilla::layers::layerscope::LayersPacket_Layer_Size::MergeFrom(from.size());
}
if (from.has_displaylistloglength()) {
set_displaylistloglength(from.displaylistloglength());
}
}
if (from._has_bits_[24 / 32] & (0xffu << (24 % 32))) {
if (from.has_displaylistlog()) {
set_displaylistlog(from.displaylistlog());
}
}
mutable_unknown_fields()->append(from.unknown_fields());
}
@ -3484,6 +3606,8 @@ void LayersPacket_Layer::Swap(LayersPacket_Layer* other) {
std::swap(filter_, other->filter_);
std::swap(refid_, other->refid_);
std::swap(size_, other->size_);
std::swap(displaylistloglength_, other->displaylistloglength_);
std::swap(displaylistlog_, other->displaylistlog_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.swap(other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);
@ -4177,6 +4301,8 @@ const int DrawPacket::kMvMatrixFieldNumber;
const int DrawPacket::kTotalRectsFieldNumber;
const int DrawPacket::kLayerRectFieldNumber;
const int DrawPacket::kLayerrefFieldNumber;
const int DrawPacket::kTexIDsFieldNumber;
const int DrawPacket::kTextureRectFieldNumber;
#endif // !_MSC_VER
DrawPacket::DrawPacket()
@ -4249,14 +4375,19 @@ void DrawPacket::Clear() {
::memset(&first, 0, n); \
} while (0)
ZR_(offsetx_, offsety_);
ZR_(layerref_, totalrects_);
if (_has_bits_[0 / 32] & 43) {
ZR_(offsetx_, offsety_);
totalrects_ = 0u;
layerref_ = GOOGLE_ULONGLONG(0);
}
#undef OFFSET_OF_FIELD_
#undef ZR_
mvmatrix_.Clear();
layerrect_.Clear();
texids_.Clear();
texturerect_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->clear();
}
@ -4363,6 +4494,39 @@ bool DrawPacket::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(56)) goto parse_texIDs;
break;
}
// repeated uint32 texIDs = 7;
case 7: {
if (tag == 56) {
parse_texIDs:
DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
1, 56, input, this->mutable_texids())));
} else if (tag == 58) {
DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
input, this->mutable_texids())));
} else {
goto handle_unusual;
}
if (input->ExpectTag(56)) goto parse_texIDs;
if (input->ExpectTag(66)) goto parse_textureRect;
break;
}
// repeated .mozilla.layers.layerscope.DrawPacket.Rect textureRect = 8;
case 8: {
if (tag == 66) {
parse_textureRect:
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
input, add_texturerect()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(66)) goto parse_textureRect;
if (input->ExpectAtEnd()) goto success;
break;
}
@ -4424,6 +4588,18 @@ void DrawPacket::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteUInt64(6, this->layerref(), output);
}
// repeated uint32 texIDs = 7;
for (int i = 0; i < this->texids_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteUInt32(
7, this->texids(i), output);
}
// repeated .mozilla.layers.layerscope.DrawPacket.Rect textureRect = 8;
for (int i = 0; i < this->texturerect_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessage(
8, this->texturerect(i), output);
}
output->WriteRaw(unknown_fields().data(),
unknown_fields().size());
// @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.DrawPacket)
@ -4473,6 +4649,24 @@ int DrawPacket::ByteSize() const {
this->layerrect(i));
}
// repeated uint32 texIDs = 7;
{
int data_size = 0;
for (int i = 0; i < this->texids_size(); i++) {
data_size += ::google::protobuf::internal::WireFormatLite::
UInt32Size(this->texids(i));
}
total_size += 1 * this->texids_size() + data_size;
}
// repeated .mozilla.layers.layerscope.DrawPacket.Rect textureRect = 8;
total_size += 1 * this->texturerect_size();
for (int i = 0; i < this->texturerect_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->texturerect(i));
}
total_size += unknown_fields().size();
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
@ -4490,6 +4684,8 @@ void DrawPacket::MergeFrom(const DrawPacket& from) {
GOOGLE_CHECK_NE(&from, this);
mvmatrix_.MergeFrom(from.mvmatrix_);
layerrect_.MergeFrom(from.layerrect_);
texids_.MergeFrom(from.texids_);
texturerect_.MergeFrom(from.texturerect_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_offsetx()) {
set_offsetx(from.offsetx());
@ -4517,6 +4713,7 @@ bool DrawPacket::IsInitialized() const {
if ((_has_bits_[0] & 0x0000002b) != 0x0000002b) return false;
if (!::google::protobuf::internal::AllAreInitialized(this->layerrect())) return false;
if (!::google::protobuf::internal::AllAreInitialized(this->texturerect())) return false;
return true;
}
@ -4528,6 +4725,8 @@ void DrawPacket::Swap(DrawPacket* other) {
std::swap(totalrects_, other->totalrects_);
layerrect_.Swap(&other->layerrect_);
std::swap(layerref_, other->layerref_);
texids_.Swap(&other->texids_);
texturerect_.Swap(&other->texturerect_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.swap(other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);

View File

@ -183,16 +183,26 @@ class FramePacket : public ::google::protobuf::MessageLite {
inline ::google::protobuf::uint64 value() const;
inline void set_value(::google::protobuf::uint64 value);
// optional float scale = 2;
inline bool has_scale() const;
inline void clear_scale();
static const int kScaleFieldNumber = 2;
inline float scale() const;
inline void set_scale(float value);
// @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.FramePacket)
private:
inline void set_has_value();
inline void clear_has_value();
inline void set_has_scale();
inline void clear_has_scale();
::std::string _unknown_fields_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::uint64 value_;
float scale_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
friend void protobuf_AddDesc_LayerScopePacket_2eproto_impl();
#else
@ -1351,6 +1361,25 @@ class LayersPacket_Layer : public ::google::protobuf::MessageLite {
inline ::mozilla::layers::layerscope::LayersPacket_Layer_Size* release_size();
inline void set_allocated_size(::mozilla::layers::layerscope::LayersPacket_Layer_Size* size);
// optional uint32 displayListLogLength = 105;
inline bool has_displaylistloglength() const;
inline void clear_displaylistloglength();
static const int kDisplayListLogLengthFieldNumber = 105;
inline ::google::protobuf::uint32 displaylistloglength() const;
inline void set_displaylistloglength(::google::protobuf::uint32 value);
// optional bytes displayListLog = 106;
inline bool has_displaylistlog() const;
inline void clear_displaylistlog();
static const int kDisplayListLogFieldNumber = 106;
inline const ::std::string& displaylistlog() const;
inline void set_displaylistlog(const ::std::string& value);
inline void set_displaylistlog(const char* value);
inline void set_displaylistlog(const void* value, size_t size);
inline ::std::string* mutable_displaylistlog();
inline ::std::string* release_displaylistlog();
inline void set_allocated_displaylistlog(::std::string* displaylistlog);
// @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.LayersPacket.Layer)
private:
inline void set_has_type();
@ -1399,6 +1428,10 @@ class LayersPacket_Layer : public ::google::protobuf::MessageLite {
inline void clear_has_refid();
inline void set_has_size();
inline void clear_has_size();
inline void set_has_displaylistloglength();
inline void clear_has_displaylistloglength();
inline void set_has_displaylistlog();
inline void clear_has_displaylistlog();
::std::string _unknown_fields_;
@ -1427,6 +1460,8 @@ class LayersPacket_Layer : public ::google::protobuf::MessageLite {
int filter_;
::google::protobuf::uint64 refid_;
::mozilla::layers::layerscope::LayersPacket_Layer_Size* size_;
::std::string* displaylistlog_;
::google::protobuf::uint32 displaylistloglength_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
friend void protobuf_AddDesc_LayerScopePacket_2eproto_impl();
#else
@ -1863,6 +1898,30 @@ class DrawPacket : public ::google::protobuf::MessageLite {
inline ::google::protobuf::uint64 layerref() const;
inline void set_layerref(::google::protobuf::uint64 value);
// repeated uint32 texIDs = 7;
inline int texids_size() const;
inline void clear_texids();
static const int kTexIDsFieldNumber = 7;
inline ::google::protobuf::uint32 texids(int index) const;
inline void set_texids(int index, ::google::protobuf::uint32 value);
inline void add_texids(::google::protobuf::uint32 value);
inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >&
texids() const;
inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >*
mutable_texids();
// repeated .mozilla.layers.layerscope.DrawPacket.Rect textureRect = 8;
inline int texturerect_size() const;
inline void clear_texturerect();
static const int kTextureRectFieldNumber = 8;
inline const ::mozilla::layers::layerscope::DrawPacket_Rect& texturerect(int index) const;
inline ::mozilla::layers::layerscope::DrawPacket_Rect* mutable_texturerect(int index);
inline ::mozilla::layers::layerscope::DrawPacket_Rect* add_texturerect();
inline const ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >&
texturerect() const;
inline ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >*
mutable_texturerect();
// @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.DrawPacket)
private:
inline void set_has_offsetx();
@ -1883,6 +1942,8 @@ class DrawPacket : public ::google::protobuf::MessageLite {
::google::protobuf::RepeatedField< float > mvmatrix_;
::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect > layerrect_;
::google::protobuf::uint64 layerref_;
::google::protobuf::RepeatedField< ::google::protobuf::uint32 > texids_;
::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect > texturerect_;
::google::protobuf::uint32 totalrects_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
friend void protobuf_AddDesc_LayerScopePacket_2eproto_impl();
@ -2222,6 +2283,30 @@ inline void FramePacket::set_value(::google::protobuf::uint64 value) {
// @@protoc_insertion_point(field_set:mozilla.layers.layerscope.FramePacket.value)
}
// optional float scale = 2;
inline bool FramePacket::has_scale() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
inline void FramePacket::set_has_scale() {
_has_bits_[0] |= 0x00000002u;
}
inline void FramePacket::clear_has_scale() {
_has_bits_[0] &= ~0x00000002u;
}
inline void FramePacket::clear_scale() {
scale_ = 0;
clear_has_scale();
}
inline float FramePacket::scale() const {
// @@protoc_insertion_point(field_get:mozilla.layers.layerscope.FramePacket.scale)
return scale_;
}
inline void FramePacket::set_scale(float value) {
set_has_scale();
scale_ = value;
// @@protoc_insertion_point(field_set:mozilla.layers.layerscope.FramePacket.scale)
}
// -------------------------------------------------------------------
// ColorPacket
@ -3791,6 +3876,106 @@ inline void LayersPacket_Layer::set_allocated_size(::mozilla::layers::layerscope
// @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.LayersPacket.Layer.size)
}
// optional uint32 displayListLogLength = 105;
inline bool LayersPacket_Layer::has_displaylistloglength() const {
return (_has_bits_[0] & 0x00800000u) != 0;
}
inline void LayersPacket_Layer::set_has_displaylistloglength() {
_has_bits_[0] |= 0x00800000u;
}
inline void LayersPacket_Layer::clear_has_displaylistloglength() {
_has_bits_[0] &= ~0x00800000u;
}
inline void LayersPacket_Layer::clear_displaylistloglength() {
displaylistloglength_ = 0u;
clear_has_displaylistloglength();
}
inline ::google::protobuf::uint32 LayersPacket_Layer::displaylistloglength() const {
// @@protoc_insertion_point(field_get:mozilla.layers.layerscope.LayersPacket.Layer.displayListLogLength)
return displaylistloglength_;
}
inline void LayersPacket_Layer::set_displaylistloglength(::google::protobuf::uint32 value) {
set_has_displaylistloglength();
displaylistloglength_ = value;
// @@protoc_insertion_point(field_set:mozilla.layers.layerscope.LayersPacket.Layer.displayListLogLength)
}
// optional bytes displayListLog = 106;
inline bool LayersPacket_Layer::has_displaylistlog() const {
return (_has_bits_[0] & 0x01000000u) != 0;
}
inline void LayersPacket_Layer::set_has_displaylistlog() {
_has_bits_[0] |= 0x01000000u;
}
inline void LayersPacket_Layer::clear_has_displaylistlog() {
_has_bits_[0] &= ~0x01000000u;
}
inline void LayersPacket_Layer::clear_displaylistlog() {
if (displaylistlog_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
displaylistlog_->clear();
}
clear_has_displaylistlog();
}
inline const ::std::string& LayersPacket_Layer::displaylistlog() const {
// @@protoc_insertion_point(field_get:mozilla.layers.layerscope.LayersPacket.Layer.displayListLog)
return *displaylistlog_;
}
inline void LayersPacket_Layer::set_displaylistlog(const ::std::string& value) {
set_has_displaylistlog();
if (displaylistlog_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
displaylistlog_ = new ::std::string;
}
displaylistlog_->assign(value);
// @@protoc_insertion_point(field_set:mozilla.layers.layerscope.LayersPacket.Layer.displayListLog)
}
inline void LayersPacket_Layer::set_displaylistlog(const char* value) {
set_has_displaylistlog();
if (displaylistlog_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
displaylistlog_ = new ::std::string;
}
displaylistlog_->assign(value);
// @@protoc_insertion_point(field_set_char:mozilla.layers.layerscope.LayersPacket.Layer.displayListLog)
}
inline void LayersPacket_Layer::set_displaylistlog(const void* value, size_t size) {
set_has_displaylistlog();
if (displaylistlog_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
displaylistlog_ = new ::std::string;
}
displaylistlog_->assign(reinterpret_cast<const char*>(value), size);
// @@protoc_insertion_point(field_set_pointer:mozilla.layers.layerscope.LayersPacket.Layer.displayListLog)
}
inline ::std::string* LayersPacket_Layer::mutable_displaylistlog() {
set_has_displaylistlog();
if (displaylistlog_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
displaylistlog_ = new ::std::string;
}
// @@protoc_insertion_point(field_mutable:mozilla.layers.layerscope.LayersPacket.Layer.displayListLog)
return displaylistlog_;
}
inline ::std::string* LayersPacket_Layer::release_displaylistlog() {
clear_has_displaylistlog();
if (displaylistlog_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = displaylistlog_;
displaylistlog_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return temp;
}
}
inline void LayersPacket_Layer::set_allocated_displaylistlog(::std::string* displaylistlog) {
if (displaylistlog_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete displaylistlog_;
}
if (displaylistlog) {
set_has_displaylistlog();
displaylistlog_ = displaylistlog;
} else {
clear_has_displaylistlog();
displaylistlog_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
// @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.LayersPacket.Layer.displayListLog)
}
// -------------------------------------------------------------------
// LayersPacket
@ -4113,6 +4298,66 @@ inline void DrawPacket::set_layerref(::google::protobuf::uint64 value) {
// @@protoc_insertion_point(field_set:mozilla.layers.layerscope.DrawPacket.layerref)
}
// repeated uint32 texIDs = 7;
inline int DrawPacket::texids_size() const {
return texids_.size();
}
inline void DrawPacket::clear_texids() {
texids_.Clear();
}
inline ::google::protobuf::uint32 DrawPacket::texids(int index) const {
// @@protoc_insertion_point(field_get:mozilla.layers.layerscope.DrawPacket.texIDs)
return texids_.Get(index);
}
inline void DrawPacket::set_texids(int index, ::google::protobuf::uint32 value) {
texids_.Set(index, value);
// @@protoc_insertion_point(field_set:mozilla.layers.layerscope.DrawPacket.texIDs)
}
inline void DrawPacket::add_texids(::google::protobuf::uint32 value) {
texids_.Add(value);
// @@protoc_insertion_point(field_add:mozilla.layers.layerscope.DrawPacket.texIDs)
}
inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >&
DrawPacket::texids() const {
// @@protoc_insertion_point(field_list:mozilla.layers.layerscope.DrawPacket.texIDs)
return texids_;
}
inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >*
DrawPacket::mutable_texids() {
// @@protoc_insertion_point(field_mutable_list:mozilla.layers.layerscope.DrawPacket.texIDs)
return &texids_;
}
// repeated .mozilla.layers.layerscope.DrawPacket.Rect textureRect = 8;
inline int DrawPacket::texturerect_size() const {
return texturerect_.size();
}
inline void DrawPacket::clear_texturerect() {
texturerect_.Clear();
}
inline const ::mozilla::layers::layerscope::DrawPacket_Rect& DrawPacket::texturerect(int index) const {
// @@protoc_insertion_point(field_get:mozilla.layers.layerscope.DrawPacket.textureRect)
return texturerect_.Get(index);
}
inline ::mozilla::layers::layerscope::DrawPacket_Rect* DrawPacket::mutable_texturerect(int index) {
// @@protoc_insertion_point(field_mutable:mozilla.layers.layerscope.DrawPacket.textureRect)
return texturerect_.Mutable(index);
}
inline ::mozilla::layers::layerscope::DrawPacket_Rect* DrawPacket::add_texturerect() {
// @@protoc_insertion_point(field_add:mozilla.layers.layerscope.DrawPacket.textureRect)
return texturerect_.Add();
}
inline const ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >&
DrawPacket::texturerect() const {
// @@protoc_insertion_point(field_list:mozilla.layers.layerscope.DrawPacket.textureRect)
return texturerect_;
}
inline ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >*
DrawPacket::mutable_texturerect() {
// @@protoc_insertion_point(field_mutable_list:mozilla.layers.layerscope.DrawPacket.textureRect)
return &texturerect_;
}
// -------------------------------------------------------------------
// Packet

View File

@ -9,6 +9,7 @@ package mozilla.layers.layerscope;
// ===============================
message FramePacket {
optional uint64 value = 1;
optional float scale = 2;
}
message ColorPacket {
@ -114,6 +115,8 @@ message LayersPacket {
optional uint64 refID = 103;
// Readback Layer
optional Size size = 104;
optional uint32 displayListLogLength = 105;
optional bytes displayListLog = 106;
}
repeated Layer layer = 1;
}
@ -136,6 +139,8 @@ message DrawPacket {
required uint32 totalRects = 4;
repeated Rect layerRect = 5;
required uint64 layerref = 6;
repeated uint32 texIDs = 7;
repeated Rect textureRect = 8;
}
// We only need to use this Packet.

View File

@ -1410,6 +1410,10 @@ gfxFcPlatformFontList::FindGenericFamily(const nsAString& aGeneric,
nsAutoRef<FcFontSet> faces(FcFontSort(nullptr, genericPattern, FcFalse,
nullptr, &result));
if (!faces) {
return nullptr;
}
// -- pick the first font for which a font family exists
for (int i = 0; i < faces->nfont; i++) {
FcPattern* font = faces->fonts[i];

View File

@ -1221,6 +1221,12 @@ gfxFont::SpaceMayParticipateInShaping(int32_t aRunScript)
}
}
if (FontCanSupportGraphite()) {
if (gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
return mFontEntry->HasGraphiteSpaceContextuals();
}
}
// We record the presence of space-dependent features in the font entry
// so that subsequent instantiations for the same font face won't
// require us to re-check the tables; however, the actual check is done

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