421 lines
12 KiB
C
421 lines
12 KiB
C
/*
|
|
* Copyright (C) 2016-2019 Muhammad Tayyab Akram
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <SBConfig.h>
|
|
|
|
#include "BidiTypeLookup.h"
|
|
#include "GeneralCategoryLookup.h"
|
|
#include "PairingLookup.h"
|
|
#include "ScriptLookup.h"
|
|
#include "SBBase.h"
|
|
|
|
#define TAG(a, b, c, d) \
|
|
(SBUInt32) \
|
|
( \
|
|
((SBUInt8)(a) << 24) \
|
|
| ((SBUInt8)(b) << 16) \
|
|
| ((SBUInt8)(c) << 8) \
|
|
| ((SBUInt8)(d) << 0) \
|
|
)
|
|
|
|
SB_INTERNAL void SBUIntegerNormalizeRange(SBUInteger actualLength,
|
|
SBUInteger *rangeOffset, SBUInteger *rangeLength)
|
|
{
|
|
/**
|
|
* Assume:
|
|
* Actual Length = 10
|
|
*
|
|
* Case 1:
|
|
* Offset = 0, Length = 10
|
|
* Result:
|
|
* Offset = 0, Length = 10
|
|
*
|
|
* Case 2:
|
|
* Offset = 0, Length = 11
|
|
* Result:
|
|
* Offset = 0, Length = 10
|
|
*
|
|
* Case 3:
|
|
* Offset = 1, Length = -1 (MAX)
|
|
* Result:
|
|
* Offset = 1, Length = 9
|
|
*
|
|
* Case 4:
|
|
* Offset = 10, Length = 0
|
|
* Result:
|
|
* Offset = Invalid, Length = 0
|
|
*
|
|
* Case 5:
|
|
* Offset = -1 (MAX), Length = 1
|
|
* Result:
|
|
* Offset = Invalid, Length = 0
|
|
*/
|
|
|
|
if (*rangeOffset < actualLength) {
|
|
SBUInteger possibleLimit = *rangeOffset + *rangeLength;
|
|
|
|
if (*rangeOffset <= possibleLimit && possibleLimit <= actualLength) {
|
|
/* The range is valid. Nothing to do here. */
|
|
} else {
|
|
*rangeLength = actualLength - *rangeOffset;
|
|
}
|
|
} else {
|
|
*rangeOffset = SBInvalidIndex;
|
|
*rangeLength = 0;
|
|
}
|
|
}
|
|
|
|
SB_INTERNAL SBBoolean SBUIntegerVerifyRange(SBUInteger actualLength,
|
|
SBUInteger rangeOffset, SBUInteger rangeLength)
|
|
{
|
|
SBUInteger possibleLimit = rangeOffset + rangeLength;
|
|
|
|
return rangeOffset < actualLength
|
|
&& rangeOffset <= possibleLimit
|
|
&& possibleLimit <= actualLength;
|
|
}
|
|
|
|
SBBidiType SBCodepointGetBidiType(SBCodepoint codepoint)
|
|
{
|
|
return LookupBidiType(codepoint);
|
|
}
|
|
|
|
SBGeneralCategory SBCodepointGetGeneralCategory(SBCodepoint codepoint)
|
|
{
|
|
return LookupGeneralCategory(codepoint);
|
|
}
|
|
|
|
SBCodepoint SBCodepointGetMirror(SBCodepoint codepoint)
|
|
{
|
|
return LookupMirror(codepoint);
|
|
}
|
|
|
|
SBScript SBCodepointGetScript(SBCodepoint codepoint)
|
|
{
|
|
return LookupScript(codepoint);
|
|
}
|
|
|
|
SBUInt32 SBScriptGetOpenTypeTag(SBScript script)
|
|
{
|
|
/* Reference: https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags */
|
|
/* Dated: 07/24/2017 */
|
|
|
|
switch (script) {
|
|
case SBScriptADLM:
|
|
return TAG('a', 'd', 'l', 'm');
|
|
case SBScriptAHOM:
|
|
return TAG('a', 'h', 'o', 'm');
|
|
case SBScriptHLUW:
|
|
return TAG('h', 'l', 'u', 'w');
|
|
case SBScriptARAB:
|
|
return TAG('a', 'r', 'a', 'b');
|
|
case SBScriptARMN:
|
|
return TAG('a', 'r', 'm', 'n');
|
|
case SBScriptAVST:
|
|
return TAG('a', 'v', 's', 't');
|
|
case SBScriptBALI:
|
|
return TAG('b', 'a', 'l', 'i');
|
|
case SBScriptBAMU:
|
|
return TAG('b', 'a', 'm', 'u');
|
|
case SBScriptBASS:
|
|
return TAG('b', 'a', 's', 's');
|
|
case SBScriptBATK:
|
|
return TAG('b', 'a', 't', 'k');
|
|
/* case SBScriptBENG:
|
|
return TAG('b', 'e', 'n', 'g'); */
|
|
case SBScriptBENG:
|
|
return TAG('b', 'n', 'g', '2');
|
|
case SBScriptBHKS:
|
|
return TAG('b', 'h', 'k', 's');
|
|
case SBScriptBOPO:
|
|
return TAG('b', 'o', 'p', 'o');
|
|
case SBScriptBRAH:
|
|
return TAG('b', 'r', 'a', 'h');
|
|
case SBScriptBRAI:
|
|
return TAG('b', 'r', 'a', 'i');
|
|
case SBScriptBUGI:
|
|
return TAG('b', 'u', 'g', 'i');
|
|
case SBScriptBUHD:
|
|
return TAG('b', 'u', 'h', 'd');
|
|
/* case SBScriptBYZM:
|
|
return TAG('b', 'y', 'z', 'm'); */
|
|
case SBScriptCANS:
|
|
return TAG('c', 'a', 'n', 's');
|
|
case SBScriptCARI:
|
|
return TAG('c', 'a', 'r', 'i');
|
|
case SBScriptAGHB:
|
|
return TAG('a', 'g', 'h', 'b');
|
|
case SBScriptCAKM:
|
|
return TAG('c', 'a', 'k', 'm');
|
|
case SBScriptCHAM:
|
|
return TAG('c', 'h', 'a', 'm');
|
|
case SBScriptCHER:
|
|
return TAG('c', 'h', 'e', 'r');
|
|
case SBScriptHANI:
|
|
return TAG('h', 'a', 'n', 'i');
|
|
case SBScriptCOPT:
|
|
return TAG('c', 'o', 'p', 't');
|
|
case SBScriptCPRT:
|
|
return TAG('c', 'p', 'r', 't');
|
|
case SBScriptCYRL:
|
|
return TAG('c', 'y', 'r', 'l');
|
|
/* case SBScriptDFLT:
|
|
return TAG('D', 'F', 'L', 'T'); */
|
|
case SBScriptDSRT:
|
|
return TAG('d', 's', 'r', 't');
|
|
/* case SBScriptDEVA:
|
|
return TAG('d', 'e', 'v', 'a'); */
|
|
case SBScriptDEVA:
|
|
return TAG('d', 'e', 'v', '2');
|
|
case SBScriptDUPL:
|
|
return TAG('d', 'u', 'p', 'l');
|
|
case SBScriptEGYP:
|
|
return TAG('e', 'g', 'y', 'p');
|
|
case SBScriptELBA:
|
|
return TAG('e', 'l', 'b', 'a');
|
|
case SBScriptETHI:
|
|
return TAG('e', 't', 'h', 'i');
|
|
case SBScriptGEOR:
|
|
return TAG('g', 'e', 'o', 'r');
|
|
case SBScriptGLAG:
|
|
return TAG('g', 'l', 'a', 'g');
|
|
case SBScriptGOTH:
|
|
return TAG('g', 'o', 't', 'h');
|
|
case SBScriptGRAN:
|
|
return TAG('g', 'r', 'a', 'n');
|
|
case SBScriptGREK:
|
|
return TAG('g', 'r', 'e', 'k');
|
|
/* case SBScriptGUJR:
|
|
return TAG('g', 'u', 'j', 'r'); */
|
|
case SBScriptGUJR:
|
|
return TAG('g', 'j', 'r', '2');
|
|
/* case SBScriptGURU:
|
|
return TAG('g', 'u', 'r', 'u'); */
|
|
case SBScriptGURU:
|
|
return TAG('g', 'u', 'r', '2');
|
|
case SBScriptHANG:
|
|
return TAG('h', 'a', 'n', 'g');
|
|
/* case SBScriptJAMO:
|
|
return TAG('j', 'a', 'm', 'o'); */
|
|
case SBScriptHANO:
|
|
return TAG('h', 'a', 'n', 'o');
|
|
case SBScriptHATR:
|
|
return TAG('h', 'a', 't', 'r');
|
|
case SBScriptHEBR:
|
|
return TAG('h', 'e', 'b', 'r');
|
|
case SBScriptHIRA:
|
|
return TAG('k', 'a', 'n', 'a');
|
|
case SBScriptARMI:
|
|
return TAG('a', 'r', 'm', 'i');
|
|
case SBScriptPHLI:
|
|
return TAG('p', 'h', 'l', 'i');
|
|
case SBScriptPRTI:
|
|
return TAG('p', 'r', 't', 'i');
|
|
case SBScriptJAVA:
|
|
return TAG('j', 'a', 'v', 'a');
|
|
case SBScriptKTHI:
|
|
return TAG('k', 't', 'h', 'i');
|
|
/* case SBScriptKNDA:
|
|
return TAG('k', 'n', 'd', 'a'); */
|
|
case SBScriptKNDA:
|
|
return TAG('k', 'n', 'd', '2');
|
|
case SBScriptKANA:
|
|
return TAG('k', 'a', 'n', 'a');
|
|
case SBScriptKALI:
|
|
return TAG('k', 'a', 'l', 'i');
|
|
case SBScriptKHAR:
|
|
return TAG('k', 'h', 'a', 'r');
|
|
case SBScriptKHMR:
|
|
return TAG('k', 'h', 'm', 'r');
|
|
case SBScriptKHOJ:
|
|
return TAG('k', 'h', 'o', 'j');
|
|
case SBScriptSIND:
|
|
return TAG('s', 'i', 'n', 'd');
|
|
case SBScriptLAOO:
|
|
return TAG('l', 'a', 'o', ' ');
|
|
case SBScriptLATN:
|
|
return TAG('l', 'a', 't', 'n');
|
|
case SBScriptLEPC:
|
|
return TAG('l', 'e', 'p', 'c');
|
|
case SBScriptLIMB:
|
|
return TAG('l', 'i', 'm', 'b');
|
|
case SBScriptLINA:
|
|
return TAG('l', 'i', 'n', 'a');
|
|
case SBScriptLINB:
|
|
return TAG('l', 'i', 'n', 'b');
|
|
case SBScriptLISU:
|
|
return TAG('l', 'i', 's', 'u');
|
|
case SBScriptLYCI:
|
|
return TAG('l', 'y', 'c', 'i');
|
|
case SBScriptLYDI:
|
|
return TAG('l', 'y', 'd', 'i');
|
|
case SBScriptMAHJ:
|
|
return TAG('m', 'a', 'h', 'j');
|
|
/* case SBScriptMLYM:
|
|
return TAG('m', 'l', 'y', 'm'); */
|
|
case SBScriptMLYM:
|
|
return TAG('m', 'l', 'm', '2');
|
|
case SBScriptMAND:
|
|
return TAG('m', 'a', 'n', 'd');
|
|
case SBScriptMANI:
|
|
return TAG('m', 'a', 'n', 'i');
|
|
case SBScriptMARC:
|
|
return TAG('m', 'a', 'r', 'c');
|
|
/* case SBScriptMATH:
|
|
return TAG('m', 'a', 't', 'h'); */
|
|
case SBScriptMTEI:
|
|
return TAG('m', 't', 'e', 'i');
|
|
case SBScriptMEND:
|
|
return TAG('m', 'e', 'n', 'd');
|
|
case SBScriptMERC:
|
|
return TAG('m', 'e', 'r', 'c');
|
|
case SBScriptMERO:
|
|
return TAG('m', 'e', 'r', 'o');
|
|
case SBScriptPLRD:
|
|
return TAG('p', 'l', 'r', 'd');
|
|
case SBScriptMODI:
|
|
return TAG('m', 'o', 'd', 'i');
|
|
case SBScriptMONG:
|
|
return TAG('m', 'o', 'n', 'g');
|
|
case SBScriptMROO:
|
|
return TAG('m', 'r', 'o', 'o');
|
|
case SBScriptMULT:
|
|
return TAG('m', 'u', 'l', 't');
|
|
/* case SBScriptMUSC:
|
|
return TAG('m', 'u', 's', 'c'); */
|
|
/* case SBScriptMYMR:
|
|
return TAG('m', 'y', 'm', 'r'); */
|
|
case SBScriptMYMR:
|
|
return TAG('m', 'y', 'm', '2');
|
|
case SBScriptNBAT:
|
|
return TAG('n', 'b', 'a', 't');
|
|
case SBScriptNEWA:
|
|
return TAG('n', 'e', 'w', 'a');
|
|
case SBScriptTALU:
|
|
return TAG('t', 'a', 'l', 'u');
|
|
case SBScriptNKOO:
|
|
return TAG('n', 'k', 'o', ' ');
|
|
/* case SBScriptORYA:
|
|
return TAG('o', 'r', 'y', 'a'); */
|
|
case SBScriptORYA:
|
|
return TAG('o', 'r', 'y', '2');
|
|
case SBScriptOGAM:
|
|
return TAG('o', 'g', 'a', 'm');
|
|
case SBScriptOLCK:
|
|
return TAG('o', 'l', 'c', 'k');
|
|
case SBScriptITAL:
|
|
return TAG('i', 't', 'a', 'l');
|
|
case SBScriptHUNG:
|
|
return TAG('h', 'u', 'n', 'g');
|
|
case SBScriptNARB:
|
|
return TAG('n', 'a', 'r', 'b');
|
|
case SBScriptPERM:
|
|
return TAG('p', 'e', 'r', 'm');
|
|
case SBScriptXPEO:
|
|
return TAG('x', 'p', 'e', 'o');
|
|
case SBScriptSARB:
|
|
return TAG('s', 'a', 'r', 'b');
|
|
case SBScriptORKH:
|
|
return TAG('o', 'r', 'k', 'h');
|
|
case SBScriptOSGE:
|
|
return TAG('o', 's', 'g', 'e');
|
|
case SBScriptOSMA:
|
|
return TAG('o', 's', 'm', 'a');
|
|
case SBScriptHMNG:
|
|
return TAG('h', 'm', 'n', 'g');
|
|
case SBScriptPALM:
|
|
return TAG('p', 'a', 'l', 'm');
|
|
case SBScriptPAUC:
|
|
return TAG('p', 'a', 'u', 'c');
|
|
case SBScriptPHAG:
|
|
return TAG('p', 'h', 'a', 'g');
|
|
case SBScriptPHNX:
|
|
return TAG('p', 'h', 'n', 'x');
|
|
case SBScriptPHLP:
|
|
return TAG('p', 'h', 'l', 'p');
|
|
case SBScriptRJNG:
|
|
return TAG('r', 'j', 'n', 'g');
|
|
case SBScriptRUNR:
|
|
return TAG('r', 'u', 'n', 'r');
|
|
case SBScriptSAMR:
|
|
return TAG('s', 'a', 'm', 'r');
|
|
case SBScriptSAUR:
|
|
return TAG('s', 'a', 'u', 'r');
|
|
case SBScriptSHRD:
|
|
return TAG('s', 'h', 'r', 'd');
|
|
case SBScriptSHAW:
|
|
return TAG('s', 'h', 'a', 'w');
|
|
case SBScriptSIDD:
|
|
return TAG('s', 'i', 'd', 'd');
|
|
case SBScriptSGNW:
|
|
return TAG('s', 'g', 'n', 'w');
|
|
case SBScriptSINH:
|
|
return TAG('s', 'i', 'n', 'h');
|
|
case SBScriptSORA:
|
|
return TAG('s', 'o', 'r', 'a');
|
|
case SBScriptXSUX:
|
|
return TAG('x', 's', 'u', 'x');
|
|
case SBScriptSUND:
|
|
return TAG('s', 'u', 'n', 'd');
|
|
case SBScriptSYLO:
|
|
return TAG('s', 'y', 'l', 'o');
|
|
case SBScriptSYRC:
|
|
return TAG('s', 'y', 'r', 'c');
|
|
case SBScriptTGLG:
|
|
return TAG('t', 'g', 'l', 'g');
|
|
case SBScriptTAGB:
|
|
return TAG('t', 'a', 'g', 'b');
|
|
case SBScriptTALE:
|
|
return TAG('t', 'a', 'l', 'e');
|
|
case SBScriptLANA:
|
|
return TAG('l', 'a', 'n', 'a');
|
|
case SBScriptTAVT:
|
|
return TAG('t', 'a', 'v', 't');
|
|
case SBScriptTAKR:
|
|
return TAG('t', 'a', 'k', 'r');
|
|
/* case SBScriptTAML:
|
|
return TAG('t', 'a', 'm', 'l'); */
|
|
case SBScriptTAML:
|
|
return TAG('t', 'm', 'l', '2');
|
|
case SBScriptTANG:
|
|
return TAG('t', 'a', 'n', 'g');
|
|
/* case SBScriptTELU:
|
|
return TAG('t', 'e', 'l', 'u'); */
|
|
case SBScriptTELU:
|
|
return TAG('t', 'e', 'l', '2');
|
|
case SBScriptTHAA:
|
|
return TAG('t', 'h', 'a', 'a');
|
|
case SBScriptTHAI:
|
|
return TAG('t', 'h', 'a', 'i');
|
|
case SBScriptTIBT:
|
|
return TAG('t', 'i', 'b', 't');
|
|
case SBScriptTFNG:
|
|
return TAG('t', 'f', 'n', 'g');
|
|
case SBScriptTIRH:
|
|
return TAG('t', 'i', 'r', 'h');
|
|
case SBScriptUGAR:
|
|
return TAG('u', 'g', 'a', 'r');
|
|
case SBScriptVAII:
|
|
return TAG('v', 'a', 'i', ' ');
|
|
case SBScriptWARA:
|
|
return TAG('w', 'a', 'r', 'a');
|
|
case SBScriptYIII:
|
|
return TAG('y', 'i', ' ', ' ');
|
|
default:
|
|
return TAG('D', 'F', 'L', 'T');
|
|
}
|
|
}
|