Add SheenBidi library for better unicode support
This commit is contained in:
parent
bdbf961e76
commit
13db1b83c1
@ -372,6 +372,11 @@ endif()
|
||||
|
||||
# Text handling in STK (We use freetype, harfbuzz, fribidi and libraqm for i18n text handling)
|
||||
if (NOT SERVER_ONLY)
|
||||
# SheenBidi
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/sheenbidi")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/sheenbidi/Headers")
|
||||
SET(SHEENBIDI_LIBRARY sheenbidi)
|
||||
|
||||
# Freetype
|
||||
find_package(Freetype)
|
||||
if(FREETYPE_FOUND)
|
||||
@ -665,6 +670,7 @@ if(NOT SERVER_ONLY)
|
||||
${FREETYPE_LIBRARIES}
|
||||
${HARFBUZZ_LIBRARY}
|
||||
${SDL2_LIBRARY}
|
||||
${SHEENBIDI_LIBRARY}
|
||||
graphics_utils)
|
||||
endif()
|
||||
|
||||
|
@ -171,6 +171,16 @@ include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# SheenBidi
|
||||
LOCAL_MODULE := sheenbidi
|
||||
LOCAL_PATH := .
|
||||
LOCAL_CPP_FEATURES += rtti
|
||||
LOCAL_SRC_FILES := $(wildcard ../lib/sheenbidi/Source/*.c)
|
||||
LOCAL_CFLAGS := -I../lib/sheenbidi/Headers
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# Irrlicht
|
||||
LOCAL_MODULE := irrlicht
|
||||
LOCAL_PATH := .
|
||||
@ -249,6 +259,7 @@ LOCAL_LDLIBS := -llog -landroid -lGLESv1_CM -lGLESv3 -lOpenSLES -ldl -lm
|
||||
LOCAL_CFLAGS := -I../lib/angelscript/include \
|
||||
-I../lib/bullet/src \
|
||||
-I../lib/libraqm \
|
||||
-I../lib/sheenbidi/Headers \
|
||||
-I../lib/enet/include \
|
||||
-I../lib/ifaddrs \
|
||||
-I../lib/irrlicht/include \
|
||||
@ -279,7 +290,8 @@ LOCAL_CPPFLAGS := -std=gnu++0x
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := irrlicht bullet enet ifaddrs angelscript mcpp SDL2 \
|
||||
vorbisfile vorbis ogg openal curl libssl libcrypto \
|
||||
c++_static raqm fribidi harfbuzz freetype graphics_utils
|
||||
c++_static raqm fribidi sheenbidi harfbuzz freetype \
|
||||
graphics_utils
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
3
lib/sheenbidi/CMakeLists.txt
Normal file
3
lib/sheenbidi/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_definitions(-DSB_CONFIG_UNITY)
|
||||
include_directories("Headers")
|
||||
add_library(sheenbidi STATIC Source/SheenBidi.c)
|
119
lib/sheenbidi/Headers/SBAlgorithm.h
Normal file
119
lib/sheenbidi/Headers/SBAlgorithm.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_ALGORITHM_H
|
||||
#define _SB_PUBLIC_ALGORITHM_H
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBBidiType.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "SBParagraph.h"
|
||||
|
||||
typedef struct _SBAlgorithm *SBAlgorithmRef;
|
||||
|
||||
/**
|
||||
* Creates an algorithm object for the specified code point sequence. The source string inside the
|
||||
* code point sequence should not be freed until the algorithm object is in use.
|
||||
*
|
||||
* @param codepointSequence
|
||||
* The code point sequence to apply bidirectional algorithm on.
|
||||
* @return
|
||||
* A reference to an algorithm object if the call was successful, NULL otherwise.
|
||||
*/
|
||||
SBAlgorithmRef SBAlgorithmCreate(const SBCodepointSequence *codepointSequence);
|
||||
|
||||
/**
|
||||
* Returns a direct pointer to the bidirectional types of code units, stored in the algorithm
|
||||
* object.
|
||||
*
|
||||
* @param algorithm
|
||||
* The algorithm object from which to access the bidirectional types of code units.
|
||||
* @return
|
||||
* A valid pointer to an array of SBBidiType structures, whose length will be equal to that of
|
||||
* string buffer.
|
||||
*/
|
||||
const SBBidiType *SBAlgorithmGetBidiTypesPtr(SBAlgorithmRef algorithm);
|
||||
|
||||
/**
|
||||
* Determines the boundary of first paragraph within the specified range.
|
||||
*
|
||||
* The boundary of the paragraph occurs after a code point whose bidirectional type is Paragraph
|
||||
* Separator (B), or at the suggestedLength if no such code point exists before it. The exception to
|
||||
* this rule is when a Carriage Return (CR) is followed by a Line Feed (LF). Both CR and LF are
|
||||
* paragraph separators, but in that case, the boundary of the paragraph is considered after LF code
|
||||
* point.
|
||||
*
|
||||
* @param algorithm
|
||||
* The algorithm object to use for determining paragraph boundary.
|
||||
* @param paragraphOffset
|
||||
* The index to the first code unit of the paragraph in source string.
|
||||
* @param suggestedLength
|
||||
* The number of code units covering the suggested length of the paragraph.
|
||||
* @param acutalLength
|
||||
* The actual length of the first paragraph, including the paragraph separator, within the
|
||||
* given range.
|
||||
* @param separatorLength
|
||||
* On output, the length of paragraph separator. This parameter can be set to NULL if not
|
||||
* needed.
|
||||
*/
|
||||
void SBAlgorithmGetParagraphBoundary(SBAlgorithmRef algorithm,
|
||||
SBUInteger paragraphOffset, SBUInteger suggestedLength,
|
||||
SBUInteger *acutalLength, SBUInteger *separatorLength);
|
||||
|
||||
/**
|
||||
* Creates a paragraph object processed with Unicode Bidirectional Algorithm.
|
||||
*
|
||||
* This function processes only first paragraph starting at paragraphOffset with length less than or
|
||||
* equal to suggestedLength, in accordance with Rule P1 of Unicode Bidirectional Algorithm.
|
||||
*
|
||||
* The paragraph level is determined by applying Rules P2-P3 and embedding levels are resolved by
|
||||
* applying Rules X1-I2.
|
||||
*
|
||||
* @param algorithm
|
||||
* The algorithm object to use for creating the desired paragraph.
|
||||
* @param paragraphOffset
|
||||
* The index to the first code unit of the paragraph in source string.
|
||||
* @param suggestedLength
|
||||
* The number of code units covering the suggested length of the paragraph.
|
||||
* @param baseLevel
|
||||
* The desired base level of the paragraph. Rules P2-P3 would be ignored if it is neither
|
||||
* SBLevelDefaultLTR nor SBLevelDefaultRTL.
|
||||
* @return
|
||||
* A reference to a paragraph object if the call was successful, NULL otherwise.
|
||||
*/
|
||||
SBParagraphRef SBAlgorithmCreateParagraph(SBAlgorithmRef algorithm,
|
||||
SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel);
|
||||
|
||||
/**
|
||||
* Increments the reference count of an algorithm object.
|
||||
*
|
||||
* @param algorithm
|
||||
* The algorithm object whose reference count will be incremented.
|
||||
* @return
|
||||
* The same algorithm object passed in as the parameter.
|
||||
*/
|
||||
SBAlgorithmRef SBAlgorithmRetain(SBAlgorithmRef algorithm);
|
||||
|
||||
/**
|
||||
* Decrements the reference count of an algorithm object. The object will be deallocated when its
|
||||
* reference count reaches zero.
|
||||
*
|
||||
* @param algorithm
|
||||
* The algorithm object whose reference count will be decremented.
|
||||
*/
|
||||
void SBAlgorithmRelease(SBAlgorithmRef algorithm);
|
||||
|
||||
#endif
|
119
lib/sheenbidi/Headers/SBBase.h
Normal file
119
lib/sheenbidi/Headers/SBBase.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_BASE_H
|
||||
#define _SB_PUBLIC_BASE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* A type to represent an 8-bit signed integer.
|
||||
*/
|
||||
typedef int8_t SBInt8;
|
||||
|
||||
/**
|
||||
* A type to represent a 16-bit signed integer.
|
||||
*/
|
||||
typedef int16_t SBInt16;
|
||||
|
||||
/**
|
||||
* A type to represent a 32-bit signed integer.
|
||||
*/
|
||||
typedef int32_t SBInt32;
|
||||
|
||||
/**
|
||||
* A type to represent an 8-bit unsigned integer.
|
||||
*/
|
||||
typedef uint8_t SBUInt8;
|
||||
|
||||
/**
|
||||
* A type to represent a 16-bit unsigned integer.
|
||||
*/
|
||||
typedef uint16_t SBUInt16;
|
||||
|
||||
/**
|
||||
* A type to represent a 32-bit unsigned integer.
|
||||
*/
|
||||
typedef uint32_t SBUInt32;
|
||||
|
||||
/**
|
||||
* A signed integer type whose width is equal to the width of the machine word.
|
||||
*/
|
||||
typedef intptr_t SBInteger;
|
||||
|
||||
/**
|
||||
* An unsigned integer type whose width is equal to the width of the machine word.
|
||||
*/
|
||||
typedef uintptr_t SBUInteger;
|
||||
|
||||
/**
|
||||
* Constants that specify the states of a boolean.
|
||||
*/
|
||||
enum {
|
||||
SBFalse = 0, /**< A value representing the false state. */
|
||||
SBTrue = 1 /**< A value representing the true state. */
|
||||
};
|
||||
/**
|
||||
* A type to represent a boolean value.
|
||||
*/
|
||||
typedef SBUInt8 SBBoolean;
|
||||
|
||||
#define SBUInt8InRange(v, s, e) \
|
||||
( \
|
||||
(SBUInt8)((v) - (s)) \
|
||||
<= (SBUInt8)((e) - (s)) \
|
||||
)
|
||||
|
||||
#define SBUInt16InRange(v, s, e) \
|
||||
( \
|
||||
(SBUInt16)((v) - (s)) \
|
||||
<= (SBUInt16)((e) - (s)) \
|
||||
)
|
||||
|
||||
#define SBUInt32InRange(v, s, e) \
|
||||
( \
|
||||
(SBUInt32)((v) - (s)) \
|
||||
<= (SBUInt32)((e) - (s)) \
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* A type to represent a bidi level.
|
||||
*/
|
||||
typedef SBUInt8 SBLevel;
|
||||
|
||||
/**
|
||||
* A value representing an invalid bidi level.
|
||||
*/
|
||||
#define SBLevelInvalid 0xFF
|
||||
|
||||
/**
|
||||
* A value representing maximum explicit embedding level.
|
||||
*/
|
||||
#define SBLevelMax 125
|
||||
|
||||
/**
|
||||
* A value specifying to set base level to zero (left-to-right) if there is no strong character.
|
||||
*/
|
||||
#define SBLevelDefaultLTR 0xFE
|
||||
|
||||
/**
|
||||
* A value specifying to set base level to one (right-to-left) if there is no strong character.
|
||||
*/
|
||||
#define SBLevelDefaultRTL 0xFD
|
||||
|
||||
#endif
|
81
lib/sheenbidi/Headers/SBBidiType.h
Normal file
81
lib/sheenbidi/Headers/SBBidiType.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_BIDI_TYPE_H
|
||||
#define _SB_PUBLIC_BIDI_TYPE_H
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
/**
|
||||
* Constants that specify the bidirectional types of a character.
|
||||
*/
|
||||
enum {
|
||||
SBBidiTypeNil = 0x00,
|
||||
|
||||
SBBidiTypeL = 0x01, /**< Strong: Left-to-Right */
|
||||
SBBidiTypeR = 0x02, /**< Strong: Right-to-Left */
|
||||
SBBidiTypeAL = 0x03, /**< Strong: Right-to-Left Arabic */
|
||||
|
||||
SBBidiTypeBN = 0x04, /**< Weak: Boundary Neutral */
|
||||
SBBidiTypeNSM = 0x05, /**< Weak: Non-Spacing Mark */
|
||||
SBBidiTypeAN = 0x06, /**< Weak: Arabic Number */
|
||||
SBBidiTypeEN = 0x07, /**< Weak: European Number */
|
||||
SBBidiTypeET = 0x08, /**< Weak: European Number Terminator */
|
||||
SBBidiTypeES = 0x09, /**< Weak: European Number Separator */
|
||||
SBBidiTypeCS = 0x0A, /**< Weak: Common Number Separator */
|
||||
|
||||
SBBidiTypeWS = 0x0B, /**< Neutral: White Space */
|
||||
SBBidiTypeS = 0x0C, /**< Neutral: Segment Separator */
|
||||
SBBidiTypeB = 0x0D, /**< Neutral: Paragraph Separator */
|
||||
SBBidiTypeON = 0x0E, /**< Neutral: Other Neutral */
|
||||
|
||||
SBBidiTypeLRI = 0x0F, /**< Format: Left-to-Right Isolate */
|
||||
SBBidiTypeRLI = 0x10, /**< Format: Right-to-Left Isolate */
|
||||
SBBidiTypeFSI = 0x11, /**< Format: First Strong Isolate */
|
||||
SBBidiTypePDI = 0x12, /**< Format: Pop Directional Isolate */
|
||||
SBBidiTypeLRE = 0x13, /**< Format: Left-to-Right Embedding */
|
||||
SBBidiTypeRLE = 0x14, /**< Format: Right-to-Left Embedding */
|
||||
SBBidiTypeLRO = 0x15, /**< Format: Left-to-Right Override */
|
||||
SBBidiTypeRLO = 0x16, /**< Format: Right-to-Left Override */
|
||||
SBBidiTypePDF = 0x17 /**< Format: Pop Directional Formatting */
|
||||
};
|
||||
|
||||
/**
|
||||
* A type to represent the bidirectional type of a character.
|
||||
*/
|
||||
typedef SBUInt8 SBBidiType;
|
||||
|
||||
/**
|
||||
* Checks whether specified bidirectional type is strong.
|
||||
*/
|
||||
#define SBBidiTypeIsStrong(t) SBUInt8InRange(t, SBBidiTypeL, SBBidiTypeAL)
|
||||
|
||||
/**
|
||||
* Checks whether specified bidirectional type is weak.
|
||||
*/
|
||||
#define SBBidiTypeIsWeak(t) SBUInt8InRange(t, SBBidiTypeBN, SBBidiTypeCS)
|
||||
|
||||
/**
|
||||
* Checks whether specified bidirectional type is neutral.
|
||||
*/
|
||||
#define SBBidiTypeIsNeutral(t) SBUInt8InRange(t, SBBidiTypeWS, SBBidiTypeON)
|
||||
|
||||
/**
|
||||
* Checks whether specified bidirectional type is format.
|
||||
*/
|
||||
#define SBBidiTypeIsFormat(t) SBUInt8InRange(t, SBBidiTypeLRI, SBBidiTypePDF)
|
||||
|
||||
#endif
|
80
lib/sheenbidi/Headers/SBCodepoint.h
Normal file
80
lib/sheenbidi/Headers/SBCodepoint.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_CODEPOINT_H
|
||||
#define _SB_PUBLIC_CODEPOINT_H
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBBidiType.h"
|
||||
#include "SBGeneralCategory.h"
|
||||
#include "SBScript.h"
|
||||
|
||||
/**
|
||||
* A type to represent a unicode code point.
|
||||
*/
|
||||
typedef SBUInt32 SBCodepoint;
|
||||
|
||||
/**
|
||||
* A value representing an invalid code point.
|
||||
*/
|
||||
#define SBCodepointInvalid UINT32_MAX
|
||||
|
||||
/**
|
||||
* A value representing a faulty code point, used as a replacement by the decoder.
|
||||
*/
|
||||
#define SBCodepointFaulty 0xFFFD
|
||||
|
||||
/**
|
||||
* Returns the bidirectional type of a code point.
|
||||
*
|
||||
* @param codepoint
|
||||
* The code point whose bidirectional type is returned.
|
||||
* @return
|
||||
* The bidirectional type of specified code point.
|
||||
*/
|
||||
SBBidiType SBCodepointGetBidiType(SBCodepoint codepoint);
|
||||
|
||||
/**
|
||||
* Returns the general category of a code point.
|
||||
*
|
||||
* @param codepoint
|
||||
* The code point whose general category is returned.
|
||||
* @return
|
||||
* The general category of specified code point.
|
||||
*/
|
||||
SBGeneralCategory SBCodepointGetGeneralCategory(SBCodepoint codepoint);
|
||||
|
||||
/**
|
||||
* Returns the mirror of a code point.
|
||||
*
|
||||
* @param codepoint
|
||||
* The code point whose mirror is returned.
|
||||
* @return
|
||||
* The mirror of specified code point if available, 0 otherwise.
|
||||
*/
|
||||
SBCodepoint SBCodepointGetMirror(SBCodepoint codepoint);
|
||||
|
||||
/**
|
||||
* Returns the script of a code point.
|
||||
*
|
||||
* @param codepoint
|
||||
* The code point whose script is returned.
|
||||
* @return
|
||||
* The script of specified code point.
|
||||
*/
|
||||
SBScript SBCodepointGetScript(SBCodepoint codepoint);
|
||||
|
||||
#endif
|
66
lib/sheenbidi/Headers/SBCodepointSequence.h
Normal file
66
lib/sheenbidi/Headers/SBCodepointSequence.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_CODEPOINT_SEQUENCE_H
|
||||
#define _SB_PUBLIC_CODEPOINT_SEQUENCE_H
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepoint.h"
|
||||
|
||||
enum {
|
||||
SBStringEncodingUTF8 = 0, /**< An 8-bit representation of Unicode code points. */
|
||||
SBStringEncodingUTF16 = 1, /**< 16-bit UTF encoding in native endianness. */
|
||||
SBStringEncodingUTF32 = 2 /**< 32-bit UTF encoding in native endianness. */
|
||||
};
|
||||
typedef SBUInt32 SBStringEncoding;
|
||||
|
||||
typedef struct _SBCodepointSequence {
|
||||
SBStringEncoding stringEncoding; /**< The encoding of the string. */
|
||||
void *stringBuffer; /**< The source string containing the code units. */
|
||||
SBUInteger stringLength; /**< The length of the string in terms of code units. */
|
||||
} SBCodepointSequence;
|
||||
|
||||
/**
|
||||
* Returns the code point before the given string index.
|
||||
*
|
||||
* @param codepointSequence
|
||||
* The object holding the information of the string.
|
||||
* @param stringIndex
|
||||
* The index of code unit before which to get the code point. On output, it is set to point to
|
||||
* the first code unit of returned code point.
|
||||
* @return
|
||||
* The code point before the given string index, or SBCodepointInvalid if stringIndex is equal
|
||||
* to zero or larger than actual length of source string.
|
||||
*/
|
||||
SBCodepoint SBCodepointSequenceGetCodepointBefore(const SBCodepointSequence *codepointSequence,
|
||||
SBUInteger *stringIndex);
|
||||
|
||||
/**
|
||||
* Returns the code point at the given string index.
|
||||
*
|
||||
* @param codepointSequence
|
||||
* The object holding the information of the string.
|
||||
* @param stringIndex
|
||||
* The index of code unit at which to get the code point. On output, it is set to point to the
|
||||
* first code unit of next code point.
|
||||
* @return
|
||||
* The code point at the given string index, or SBCodepointInvalid if stringIndex is larger
|
||||
* than or equal to actual length of source string.
|
||||
*/
|
||||
SBCodepoint SBCodepointSequenceGetCodepointAt(const SBCodepointSequence *codepointSequence,
|
||||
SBUInteger *stringIndex);
|
||||
|
||||
#endif
|
29
lib/sheenbidi/Headers/SBConfig.h
Normal file
29
lib/sheenbidi/Headers/SBConfig.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_CONFIG_H
|
||||
#define _SB_PUBLIC_CONFIG_H
|
||||
|
||||
/* #define SB_CONFIG_LOG */
|
||||
/* #define SB_CONFIG_UNITY */
|
||||
|
||||
#ifdef SB_CONFIG_UNITY
|
||||
#define SB_INTERNAL static
|
||||
#else
|
||||
#define SB_INTERNAL
|
||||
#endif
|
||||
|
||||
#endif
|
106
lib/sheenbidi/Headers/SBGeneralCategory.h
Normal file
106
lib/sheenbidi/Headers/SBGeneralCategory.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_GENERAL_CATEGORY_H
|
||||
#define _SB_PUBLIC_GENERAL_CATEGORY_H
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
/**
|
||||
* Constants that specify the general category of a character.
|
||||
*/
|
||||
enum {
|
||||
SBGeneralCategoryNil = 0x00,
|
||||
|
||||
SBGeneralCategoryLU = 0x01, /**< Letter: Uppercase Letter */
|
||||
SBGeneralCategoryLL = 0x02, /**< Letter: Lowercase Letter */
|
||||
SBGeneralCategoryLT = 0x03, /**< Letter: Titlecase Letter */
|
||||
SBGeneralCategoryLM = 0x04, /**< Letter: Modifier Letter */
|
||||
SBGeneralCategoryLO = 0x05, /**< Letter: Other Letter */
|
||||
|
||||
SBGeneralCategoryMN = 0x06, /**< Mark: Nonspacing Mark */
|
||||
SBGeneralCategoryMC = 0x07, /**< Mark: Spacing Mark */
|
||||
SBGeneralCategoryME = 0x08, /**< Mark: Enclosing Mark */
|
||||
|
||||
SBGeneralCategoryND = 0x09, /**< Number: Decimal Number */
|
||||
SBGeneralCategoryNL = 0x0A, /**< Number: Letter Number */
|
||||
SBGeneralCategoryNO = 0x0B, /**< Number: Other Number */
|
||||
|
||||
SBGeneralCategoryPC = 0x0C, /**< Punctuation: Connector Punctuation */
|
||||
SBGeneralCategoryPD = 0x0D, /**< Punctuation: Dash Punctuation */
|
||||
SBGeneralCategoryPS = 0x0E, /**< Punctuation: Open Punctuation */
|
||||
SBGeneralCategoryPE = 0x0F, /**< Punctuation: Close Punctuation */
|
||||
SBGeneralCategoryPI = 0x10, /**< Punctuation: Initial Punctuation */
|
||||
SBGeneralCategoryPF = 0x11, /**< Punctuation: Final Punctuation */
|
||||
SBGeneralCategoryPO = 0x12, /**< Punctuation: Other Punctuation */
|
||||
|
||||
SBGeneralCategorySM = 0x13, /**< Symbol: Math Symbol */
|
||||
SBGeneralCategorySC = 0x14, /**< Symbol: Currency Symbol */
|
||||
SBGeneralCategorySK = 0x15, /**< Symbol: Modifier Symbol */
|
||||
SBGeneralCategorySO = 0x16, /**< Symbol: Other Symbol */
|
||||
|
||||
SBGeneralCategoryZS = 0x17, /**< Separator: Space Separator */
|
||||
SBGeneralCategoryZL = 0x18, /**< Separator: Line Separator */
|
||||
SBGeneralCategoryZP = 0x19, /**< Separator: Paragraph Separator */
|
||||
|
||||
SBGeneralCategoryCC = 0x1A, /**< Other: Control */
|
||||
SBGeneralCategoryCF = 0x1B, /**< Other: Format */
|
||||
SBGeneralCategoryCS = 0x1C, /**< Other: Surrogate */
|
||||
SBGeneralCategoryCO = 0x1D, /**< Other: Private_Use */
|
||||
SBGeneralCategoryCN = 0x1E /**< Other: Unassigned */
|
||||
};
|
||||
|
||||
/**
|
||||
* A type to represent the general category of a character.
|
||||
*/
|
||||
typedef SBUInt8 SBGeneralCategory;
|
||||
|
||||
/**
|
||||
* Checks whether specified general category is letter.
|
||||
*/
|
||||
#define SBGeneralCategoryIsLetter(gc) SBUInt8InRange(gc, SBGeneralCategoryLU, SBGeneralCategoryLO)
|
||||
|
||||
/**
|
||||
* Checks whether specified general category is mark.
|
||||
*/
|
||||
#define SBGeneralCategoryIsMark(gc) SBUInt8InRange(gc, SBGeneralCategoryMN, SBGeneralCategoryME)
|
||||
|
||||
/**
|
||||
* Checks whether specified general category is number.
|
||||
*/
|
||||
#define SBGeneralCategoryIsNumber(gc) SBUInt8InRange(gc, SBGeneralCategoryND, SBGeneralCategoryNO)
|
||||
|
||||
/**
|
||||
* Checks whether specified general category is punctuation.
|
||||
*/
|
||||
#define SBGeneralCategoryIsPunctuation(gc) SBUInt8InRange(gc, SBGeneralCategoryPC, SBGeneralCategoryPO)
|
||||
|
||||
/**
|
||||
* Checks whether specified general category is symbol.
|
||||
*/
|
||||
#define SBGeneralCategoryIsSymbol(gc) SBUInt8InRange(gc, SBGeneralCategorySM, SBGeneralCategorySO)
|
||||
|
||||
/**
|
||||
* Checks whether specified general category is separator.
|
||||
*/
|
||||
#define SBGeneralCategoryIsSeparator(gc) SBUInt8InRange(gc, SBGeneralCategoryZS, SBGeneralCategoryZP)
|
||||
|
||||
/**
|
||||
* Checks whether specified general category is other.
|
||||
*/
|
||||
#define SBGeneralCategoryIsOther(gc) SBUInt8InRange(gc, SBGeneralCategoryCC, SBGeneralCategoryCN)
|
||||
|
||||
#endif
|
84
lib/sheenbidi/Headers/SBLine.h
Normal file
84
lib/sheenbidi/Headers/SBLine.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_LINE_H
|
||||
#define _SB_PUBLIC_LINE_H
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBRun.h"
|
||||
|
||||
typedef struct _SBLine *SBLineRef;
|
||||
|
||||
/**
|
||||
* Returns the index to the first code unit of the line in source string.
|
||||
*
|
||||
* @param line
|
||||
* The line whose offset is returned.
|
||||
* @return
|
||||
* The offset of the line passed in.
|
||||
*/
|
||||
SBUInteger SBLineGetOffset(SBLineRef line);
|
||||
|
||||
/**
|
||||
* Returns the number of code units coverting the length of the line.
|
||||
*
|
||||
* @param line
|
||||
* The line whose length is returned.
|
||||
* @return
|
||||
* The length of the line passed in.
|
||||
*/
|
||||
SBUInteger SBLineGetLength(SBLineRef line);
|
||||
|
||||
/**
|
||||
* Returns the number of runs in the line.
|
||||
*
|
||||
* @param line
|
||||
* The line whose run count is returned.
|
||||
* @return
|
||||
* The number of runs in the line passed in.
|
||||
*/
|
||||
SBUInteger SBLineGetRunCount(SBLineRef line);
|
||||
|
||||
/**
|
||||
* Returns a direct pointer to the run array, stored in the line.
|
||||
*
|
||||
* @param line
|
||||
* The line from which to access the runs.
|
||||
* @return
|
||||
* A valid pointer to an array of SBRun structures.
|
||||
*/
|
||||
const SBRun *SBLineGetRunsPtr(SBLineRef line);
|
||||
|
||||
/**
|
||||
* Increments the reference count of a line object.
|
||||
*
|
||||
* @param line
|
||||
* The line object whose reference count will be incremented.
|
||||
* @return
|
||||
* The same line object passed in as the parameter.
|
||||
*/
|
||||
SBLineRef SBLineRetain(SBLineRef line);
|
||||
|
||||
/**
|
||||
* Decrements the reference count of a line object. The object will be deallocated when its
|
||||
* reference count reaches zero.
|
||||
*
|
||||
* @param line
|
||||
* The line object whose reference count will be decremented.
|
||||
*/
|
||||
void SBLineRelease(SBLineRef line);
|
||||
|
||||
#endif
|
103
lib/sheenbidi/Headers/SBMirrorLocator.h
Normal file
103
lib/sheenbidi/Headers/SBMirrorLocator.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_MIRROR_LOCATOR_H
|
||||
#define _SB_PUBLIC_MIRROR_LOCATOR_H
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepoint.h"
|
||||
#include "SBLine.h"
|
||||
|
||||
typedef struct _SBMirrorLocator *SBMirrorLocatorRef;
|
||||
|
||||
/**
|
||||
* A structure containing the information about a code point having Bidi_Mirrored property.
|
||||
*/
|
||||
typedef struct _SBMirrorAgent {
|
||||
SBUInteger index; /**< The absolute index of the code point. */
|
||||
SBCodepoint mirror; /**< The mirrored code point. */
|
||||
SBCodepoint codepoint; /**< The actual code point. */
|
||||
} SBMirrorAgent;
|
||||
|
||||
/**
|
||||
* Creates a mirror locator object which can be used to find mirrors in a line.
|
||||
*
|
||||
* @return
|
||||
* A reference to a mirror locator object.
|
||||
*/
|
||||
SBMirrorLocatorRef SBMirrorLocatorCreate(void);
|
||||
|
||||
/**
|
||||
* Loads a line in the locator so that its mirror can be located.
|
||||
*
|
||||
* @param locator
|
||||
* The locator in which the line will be loaded.
|
||||
* @param line
|
||||
* The line which will be loaded in the locator.
|
||||
* @param stringBuffer
|
||||
* The string buffer from which the line's algorithm was created.
|
||||
*/
|
||||
void SBMirrorLocatorLoadLine(SBMirrorLocatorRef locator, SBLineRef line, void *stringBuffer);
|
||||
|
||||
/**
|
||||
* Returns the agent containing the information of current located mirror.
|
||||
*
|
||||
* @param locator
|
||||
* The locator whose agent is returned.
|
||||
*/
|
||||
const SBMirrorAgent *SBMirrorLocatorGetAgent(SBMirrorLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Instructs the locator to find next mirror in the loaded line.
|
||||
*
|
||||
* @param locator
|
||||
* The locator whom you want to instruct.
|
||||
* @return
|
||||
* SBTrue if another mirror is available, SBFalse otherwise.
|
||||
* @note
|
||||
* The locator will be reset after locating last mirror.
|
||||
*/
|
||||
SBBoolean SBMirrorLocatorMoveNext(SBMirrorLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Instructs the locator to reset itself so that mirrors of the loaded line can be obatained from
|
||||
* the beginning.
|
||||
*
|
||||
* @param locator
|
||||
* The locator whom you want to reset.
|
||||
*/
|
||||
void SBMirrorLocatorReset(SBMirrorLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Increments the reference count of a mirror locator object.
|
||||
*
|
||||
* @param locator
|
||||
* The mirror locator object whose reference count will be incremented.
|
||||
* @return
|
||||
* The same mirror locator object passed in as the parameter.
|
||||
*/
|
||||
SBMirrorLocatorRef SBMirrorLocatorRetain(SBMirrorLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Decrements the reference count of a mirror locator object. The object will be deallocated when
|
||||
* its reference count reaches zero.
|
||||
*
|
||||
* @param locator
|
||||
* The mirror locator object whose reference count will be decremented.
|
||||
*/
|
||||
void SBMirrorLocatorRelease(SBMirrorLocatorRef locator);
|
||||
|
||||
#endif
|
100
lib/sheenbidi/Headers/SBParagraph.h
Normal file
100
lib/sheenbidi/Headers/SBParagraph.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_PARAGRAPH_H
|
||||
#define _SB_PUBLIC_PARAGRAPH_H
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBLine.h"
|
||||
|
||||
typedef struct _SBParagraph *SBParagraphRef;
|
||||
|
||||
/**
|
||||
* Returns the index to the first code unit of the paragraph in source string.
|
||||
*
|
||||
* @param paragraph
|
||||
* The paragraph whose offset is returned.
|
||||
* @return
|
||||
* The offset of the paragraph passed in.
|
||||
*/
|
||||
SBUInteger SBParagraphGetOffset(SBParagraphRef paragraph);
|
||||
|
||||
/**
|
||||
* Returns the number of code units covering the length of the paragraph.
|
||||
*
|
||||
* @param paragraph
|
||||
* The paragraph whose length is returned.
|
||||
* @return
|
||||
* The length of the paragraph passed in.
|
||||
*/
|
||||
SBUInteger SBParagraphGetLength(SBParagraphRef paragraph);
|
||||
|
||||
/**
|
||||
* Returns the base level of the paragraph.
|
||||
*
|
||||
* @param paragraph
|
||||
* The paragraph whose base level is returned.
|
||||
* @return
|
||||
* The base level of the paragraph passed in.
|
||||
*/
|
||||
SBLevel SBParagraphGetBaseLevel(SBParagraphRef paragraph);
|
||||
|
||||
/**
|
||||
* Returns a direct pointer to the embedding levels, stored in the paragraph.
|
||||
*
|
||||
* @param paragraph
|
||||
* The paragraph from which to access the embedding levels.
|
||||
* @return
|
||||
* A valid pointer to an array of SBLevel structures.
|
||||
*/
|
||||
const SBLevel *SBParagraphGetLevelsPtr(SBParagraphRef paragraph);
|
||||
|
||||
/**
|
||||
* Creates a line object of specified range by applying rules L1-L2 of Unicode Bidirectional
|
||||
* Algorithm.
|
||||
*
|
||||
* @param paragraph
|
||||
* The paragraph that creates the line.
|
||||
* @param lineOffset
|
||||
* The index to the first code unit of the line in source string. It should occur within the
|
||||
* range of paragraph.
|
||||
* @param lineLength
|
||||
* The number of code units covering the length of the line.
|
||||
* @return
|
||||
* A reference to a line object if the call was successful, NULL otherwise.
|
||||
*/
|
||||
SBLineRef SBParagraphCreateLine(SBParagraphRef paragraph, SBUInteger lineOffset, SBUInteger lineLength);
|
||||
|
||||
/**
|
||||
* Increments the reference count of a paragraph object.
|
||||
*
|
||||
* @param paragraph
|
||||
* The paragraph object whose reference count will be incremented.
|
||||
* @return
|
||||
* The same paragraph object passed in as the parameter.
|
||||
*/
|
||||
SBParagraphRef SBParagraphRetain(SBParagraphRef paragraph);
|
||||
|
||||
/**
|
||||
* Decrements the reference count of a paragraph object. The object will be deallocated when its
|
||||
* reference count reaches zero.
|
||||
*
|
||||
* @param paragraph
|
||||
* The paragraph object whose reference count will be decremented.
|
||||
*/
|
||||
void SBParagraphRelease(SBParagraphRef paragraph);
|
||||
|
||||
#endif
|
32
lib/sheenbidi/Headers/SBRun.h
Normal file
32
lib/sheenbidi/Headers/SBRun.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_RUN_H
|
||||
#define _SB_PUBLIC_RUN_H
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
/**
|
||||
* A structure containing the information of a sequence of characters having the same embedding
|
||||
* level.
|
||||
*/
|
||||
typedef struct _SBRun {
|
||||
SBUInteger offset; /**< The index to the first code unit of the run in source string. */
|
||||
SBUInteger length; /**< The number of code units covering the length of the run. */
|
||||
SBLevel level; /**< The embedding level of the run. */
|
||||
} SBRun;
|
||||
|
||||
#endif
|
247
lib/sheenbidi/Headers/SBScript.h
Normal file
247
lib/sheenbidi/Headers/SBScript.h
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (C) 2018-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_SCRIPT_H
|
||||
#define _SB_PUBLIC_SCRIPT_H
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
/**
|
||||
* Constants that specify the script of a character.
|
||||
*/
|
||||
enum {
|
||||
SBScriptNil = 0x00,
|
||||
|
||||
SBScriptZINH = 0x01, /**< Inherited */
|
||||
SBScriptZYYY = 0x02, /**< Common */
|
||||
SBScriptZZZZ = 0x03, /**< Unknown */
|
||||
|
||||
/* Unicode 1.1 */
|
||||
SBScriptARAB = 0x04, /**< Arabic */
|
||||
SBScriptARMN = 0x05, /**< Armenian */
|
||||
SBScriptBENG = 0x06, /**< Bengali */
|
||||
SBScriptBOPO = 0x07, /**< Bopomofo */
|
||||
SBScriptCYRL = 0x08, /**< Cyrillic */
|
||||
SBScriptDEVA = 0x09, /**< Devanagari */
|
||||
SBScriptGEOR = 0x0A, /**< Georgian */
|
||||
SBScriptGREK = 0x0B, /**< Greek */
|
||||
SBScriptGUJR = 0x0C, /**< Gujarati */
|
||||
SBScriptGURU = 0x0D, /**< Gurmukhi */
|
||||
SBScriptHANG = 0x0E, /**< Hangul */
|
||||
SBScriptHANI = 0x0F, /**< Han */
|
||||
SBScriptHEBR = 0x10, /**< Hebrew */
|
||||
SBScriptHIRA = 0x11, /**< Hiragana */
|
||||
SBScriptKANA = 0x12, /**< Katakana */
|
||||
SBScriptKNDA = 0x13, /**< Kannada */
|
||||
SBScriptLAOO = 0x14, /**< Lao */
|
||||
SBScriptLATN = 0x15, /**< Latin */
|
||||
SBScriptMLYM = 0x16, /**< Malayalam */
|
||||
SBScriptORYA = 0x17, /**< Oriya */
|
||||
SBScriptTAML = 0x18, /**< Tamil */
|
||||
SBScriptTELU = 0x19, /**< Telugu */
|
||||
SBScriptTHAI = 0x1A, /**< Thai */
|
||||
|
||||
/* Unicode 2.0 */
|
||||
SBScriptTIBT = 0x1B, /**< Tibetan */
|
||||
|
||||
/* Unicode 3.0 */
|
||||
SBScriptBRAI = 0x1C, /**< Braille */
|
||||
SBScriptCANS = 0x1D, /**< Canadian_Aboriginal */
|
||||
SBScriptCHER = 0x1E, /**< Cherokee */
|
||||
SBScriptETHI = 0x1F, /**< Ethiopic */
|
||||
SBScriptKHMR = 0x20, /**< Khmer */
|
||||
SBScriptMONG = 0x21, /**< Mongolian */
|
||||
SBScriptMYMR = 0x22, /**< Myanmar */
|
||||
SBScriptOGAM = 0x23, /**< Ogham */
|
||||
SBScriptRUNR = 0x24, /**< Runic */
|
||||
SBScriptSINH = 0x25, /**< Sinhala */
|
||||
SBScriptSYRC = 0x26, /**< Syriac */
|
||||
SBScriptTHAA = 0x27, /**< Thaana */
|
||||
SBScriptYIII = 0x28, /**< Yi */
|
||||
|
||||
/* Unicode 3.1 */
|
||||
SBScriptDSRT = 0x29, /**< Deseret */
|
||||
SBScriptGOTH = 0x2A, /**< Gothic */
|
||||
SBScriptITAL = 0x2B, /**< Old_Italic */
|
||||
|
||||
/* Unicode 3.2 */
|
||||
SBScriptBUHD = 0x2C, /**< Buhid */
|
||||
SBScriptHANO = 0x2D, /**< Hanunoo */
|
||||
SBScriptTAGB = 0x2E, /**< Tagbanwa */
|
||||
SBScriptTGLG = 0x2F, /**< Tagalog */
|
||||
|
||||
/* Unicode 4.0 */
|
||||
SBScriptCPRT = 0x30, /**< Cypriot */
|
||||
SBScriptLIMB = 0x31, /**< Limbu */
|
||||
SBScriptLINB = 0x32, /**< Linear_B */
|
||||
SBScriptOSMA = 0x33, /**< Osmanya */
|
||||
SBScriptSHAW = 0x34, /**< Shavian */
|
||||
SBScriptTALE = 0x35, /**< Tai_Le */
|
||||
SBScriptUGAR = 0x36, /**< Ugaritic */
|
||||
|
||||
/* Unicode 4.1 */
|
||||
SBScriptBUGI = 0x37, /**< Buginese */
|
||||
SBScriptCOPT = 0x38, /**< Coptic */
|
||||
SBScriptGLAG = 0x39, /**< Glagolitic */
|
||||
SBScriptKHAR = 0x3A, /**< Kharoshthi */
|
||||
SBScriptSYLO = 0x3B, /**< Syloti_Nagri */
|
||||
SBScriptTALU = 0x3C, /**< New_Tai_Lue */
|
||||
SBScriptTFNG = 0x3D, /**< Tifinagh */
|
||||
SBScriptXPEO = 0x3E, /**< Old_Persian */
|
||||
|
||||
/* Unicode 5.0 */
|
||||
SBScriptBALI = 0x3F, /**< Balinese */
|
||||
SBScriptNKOO = 0x40, /**< Nko */
|
||||
SBScriptPHAG = 0x41, /**< Phags_Pa */
|
||||
SBScriptPHNX = 0x42, /**< Phoenician */
|
||||
SBScriptXSUX = 0x43, /**< Cuneiform */
|
||||
|
||||
/* Unicode 5.1 */
|
||||
SBScriptCARI = 0x44, /**< Carian */
|
||||
SBScriptCHAM = 0x45, /**< Cham */
|
||||
SBScriptKALI = 0x46, /**< Kayah_Li */
|
||||
SBScriptLEPC = 0x47, /**< Lepcha */
|
||||
SBScriptLYCI = 0x48, /**< Lycian */
|
||||
SBScriptLYDI = 0x49, /**< Lydian */
|
||||
SBScriptOLCK = 0x4A, /**< Ol_Chiki */
|
||||
SBScriptRJNG = 0x4B, /**< Rejang */
|
||||
SBScriptSAUR = 0x4C, /**< Saurashtra */
|
||||
SBScriptSUND = 0x4D, /**< Sundanese */
|
||||
SBScriptVAII = 0x4E, /**< Vai */
|
||||
|
||||
/* Unicode 5.2 */
|
||||
SBScriptARMI = 0x4F, /**< Imperial_Aramaic */
|
||||
SBScriptAVST = 0x50, /**< Avestan */
|
||||
SBScriptBAMU = 0x51, /**< Bamum */
|
||||
SBScriptEGYP = 0x52, /**< Egyptian_Hieroglyphs */
|
||||
SBScriptJAVA = 0x53, /**< Javanese */
|
||||
SBScriptKTHI = 0x54, /**< Kaithi */
|
||||
SBScriptLANA = 0x55, /**< Tai_Tham */
|
||||
SBScriptLISU = 0x56, /**< Lisu */
|
||||
SBScriptMTEI = 0x57, /**< Meetei_Mayek */
|
||||
SBScriptORKH = 0x58, /**< Old_Turkic */
|
||||
SBScriptPHLI = 0x59, /**< Inscriptional_Pahlavi */
|
||||
SBScriptPRTI = 0x5A, /**< Inscriptional_Parthian */
|
||||
SBScriptSAMR = 0x5B, /**< Samaritan */
|
||||
SBScriptSARB = 0x5C, /**< Old_South_Arabian */
|
||||
SBScriptTAVT = 0x5D, /**< Tai_Viet */
|
||||
|
||||
/* Unicode 6.0 */
|
||||
SBScriptBATK = 0x5E, /**< Batak */
|
||||
SBScriptBRAH = 0x5F, /**< Brahmi */
|
||||
SBScriptMAND = 0x60, /**< Mandaic */
|
||||
|
||||
/* Unicode 6.1 */
|
||||
SBScriptCAKM = 0x61, /**< Chakma */
|
||||
SBScriptMERC = 0x62, /**< Meroitic_Cursive */
|
||||
SBScriptMERO = 0x63, /**< Meroitic_Hieroglyphs */
|
||||
SBScriptPLRD = 0x64, /**< Miao */
|
||||
SBScriptSHRD = 0x65, /**< Sharada */
|
||||
SBScriptSORA = 0x66, /**< Sora_Sompeng */
|
||||
SBScriptTAKR = 0x67, /**< Takri */
|
||||
|
||||
/* Unicode 7.0 */
|
||||
SBScriptAGHB = 0x68, /**< Caucasian_Albanian */
|
||||
SBScriptBASS = 0x69, /**< Bassa_Vah */
|
||||
SBScriptDUPL = 0x6A, /**< Duployan */
|
||||
SBScriptELBA = 0x6B, /**< Elbasan */
|
||||
SBScriptGRAN = 0x6C, /**< Grantha */
|
||||
SBScriptHMNG = 0x6D, /**< Pahawh_Hmong */
|
||||
SBScriptKHOJ = 0x6E, /**< Khojki */
|
||||
SBScriptLINA = 0x6F, /**< Linear_A */
|
||||
SBScriptMAHJ = 0x70, /**< Mahajani */
|
||||
SBScriptMANI = 0x71, /**< Manichaean */
|
||||
SBScriptMEND = 0x72, /**< Mende_Kikakui */
|
||||
SBScriptMODI = 0x73, /**< Modi */
|
||||
SBScriptMROO = 0x74, /**< Mro */
|
||||
SBScriptNARB = 0x75, /**< Old_North_Arabian */
|
||||
SBScriptNBAT = 0x76, /**< Nabataean */
|
||||
SBScriptPALM = 0x77, /**< Palmyrene */
|
||||
SBScriptPAUC = 0x78, /**< Pau_Cin_Hau */
|
||||
SBScriptPERM = 0x79, /**< Old_Permic */
|
||||
SBScriptPHLP = 0x7A, /**< Psalter_Pahlavi */
|
||||
SBScriptSIDD = 0x7B, /**< Siddham */
|
||||
SBScriptSIND = 0x7C, /**< Khudawadi */
|
||||
SBScriptTIRH = 0x7D, /**< Tirhuta */
|
||||
SBScriptWARA = 0x7E, /**< Warang_Citi */
|
||||
|
||||
/* Unicode 8.0 */
|
||||
SBScriptAHOM = 0x7F, /**< Ahom */
|
||||
SBScriptHATR = 0x80, /**< Hatran */
|
||||
SBScriptHLUW = 0x81, /**< Anatolian_Hieroglyphs */
|
||||
SBScriptHUNG = 0x82, /**< Old_Hungarian */
|
||||
SBScriptMULT = 0x83, /**< Multani */
|
||||
SBScriptSGNW = 0x84, /**< SignWriting */
|
||||
|
||||
/* Unicode 9.0 */
|
||||
SBScriptADLM = 0x85, /**< Adlam */
|
||||
SBScriptBHKS = 0x86, /**< Bhaiksuki */
|
||||
SBScriptMARC = 0x87, /**< Marchen */
|
||||
SBScriptNEWA = 0x88, /**< Newa */
|
||||
SBScriptOSGE = 0x89, /**< Osage */
|
||||
SBScriptTANG = 0x8A, /**< Tangut */
|
||||
|
||||
/* Unicode 10.0 */
|
||||
SBScriptGONM = 0x8B, /**< Masaram_Gondi */
|
||||
SBScriptNSHU = 0x8C, /**< Nushu */
|
||||
SBScriptSOYO = 0x8D, /**< Soyombo */
|
||||
SBScriptZANB = 0x8E, /**< Zanabazar_Square */
|
||||
|
||||
/* Unicode 11.0 */
|
||||
SBScriptDOGR = 0x8F, /**< Dogra */
|
||||
SBScriptGONG = 0x90, /**< Gunjala_Gondi */
|
||||
SBScriptMAKA = 0x91, /**< Makasar */
|
||||
SBScriptMEDF = 0x92, /**< Medefaidrin */
|
||||
SBScriptROHG = 0x93, /**< Hanifi_Rohingya */
|
||||
SBScriptSOGD = 0x94, /**< Sogdian */
|
||||
SBScriptSOGO = 0x95, /**< Old_Sogdian */
|
||||
|
||||
/* Unicode 12.0 */
|
||||
SBScriptELYM = 0x96, /**< Elymaic */
|
||||
SBScriptHMNP = 0x97, /**< Nyiakeng_Puachue_Hmong */
|
||||
SBScriptNAND = 0x98, /**< Nandinagari */
|
||||
SBScriptWCHO = 0x99, /**< Wancho */
|
||||
|
||||
/* Unicde 13.0 */
|
||||
SBScriptCHRS = 0x9A, /**< Chorasmian */
|
||||
SBScriptDIAK = 0x9B, /**< Dives_Akuru */
|
||||
SBScriptKITS = 0x9C, /**< Khitan_Small_Script */
|
||||
SBScriptYEZI = 0x9D /**< Yezidi */
|
||||
};
|
||||
|
||||
/**
|
||||
* A type to represent the script of a character.
|
||||
*/
|
||||
typedef SBUInt8 SBScript;
|
||||
|
||||
/**
|
||||
* Returns the OpenType tag of a script as UInt32 in big endian byte order. The association between
|
||||
* Unicode Script property and OpenType script tags is taken from the specification:
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags.
|
||||
*
|
||||
* If more than one tag is associated with a script, then the latest one is retured. For example,
|
||||
* Devanagari script has two tags, `deva` and `dev2`. So in this case, `dev2` will be returned.
|
||||
*
|
||||
* If no tag is associated with a script, then `DFLT` is returned.
|
||||
*
|
||||
* @param script
|
||||
* The script whose OpenType tag is returned.
|
||||
* @return
|
||||
* The OpenType tag of specified script as UInt32 in big endian byte order.
|
||||
*/
|
||||
SBUInt32 SBScriptGetOpenTypeTag(SBScript script);
|
||||
|
||||
#endif
|
101
lib/sheenbidi/Headers/SBScriptLocator.h
Normal file
101
lib/sheenbidi/Headers/SBScriptLocator.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_PUBLIC_SCRIPT_LOCATOR_H
|
||||
#define _SB_PUBLIC_SCRIPT_LOCATOR_H
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "SBScript.h"
|
||||
|
||||
typedef struct _SBScriptLocator *SBScriptLocatorRef;
|
||||
|
||||
/**
|
||||
* A structure containing the information about a run of code points having same script.
|
||||
*/
|
||||
typedef struct _SBScriptAgent {
|
||||
SBUInteger offset; /**< The index to the first code unit of the run in source string. */
|
||||
SBUInteger length; /**< The number of code units covering the length of the run. */
|
||||
SBScript script; /**< The script of the run. */
|
||||
} SBScriptAgent;
|
||||
|
||||
/**
|
||||
* Creates a script locator object which can be used to find script runs in a string.
|
||||
*
|
||||
* @return
|
||||
* A reference to a script locator object.
|
||||
*/
|
||||
SBScriptLocatorRef SBScriptLocatorCreate(void);
|
||||
|
||||
/**
|
||||
* Loads a code point sequence in the locator so that its script runs can be located.
|
||||
*
|
||||
* @param locator
|
||||
* The locator in which the code point sequence will be loaded.
|
||||
* @param codepointSequence
|
||||
* The code point sequence which will be loaded in the locator.
|
||||
*/
|
||||
void SBScriptLocatorLoadCodepoints(SBScriptLocatorRef locator, const SBCodepointSequence *codepointSequence);
|
||||
|
||||
/**
|
||||
* Returns the agent containing the information of current located script run.
|
||||
*
|
||||
* @param locator
|
||||
* The locator whose agent is returned.
|
||||
*/
|
||||
const SBScriptAgent *SBScriptLocatorGetAgent(SBScriptLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Instructs the locator to find next script run in the loaded code point sequence.
|
||||
*
|
||||
* @param locator
|
||||
* The locator whom you want to instruct.
|
||||
* @return
|
||||
* SBTrue if another script run is available, SBFalse otherwise.
|
||||
* @note
|
||||
* The locator will be reset after locating last script run.
|
||||
*/
|
||||
SBBoolean SBScriptLocatorMoveNext(SBScriptLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Instructs the locator to reset itself so that script runs of the loaded line can be obatained
|
||||
* from the beginning.
|
||||
*
|
||||
* @param locator
|
||||
* The locator whom you want to reset.
|
||||
*/
|
||||
void SBScriptLocatorReset(SBScriptLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Increments the reference count of a script locator object.
|
||||
*
|
||||
* @param locator
|
||||
* The script locator object whose reference count will be incremented.
|
||||
* @return
|
||||
* The same script locator object passed in as the parameter.
|
||||
*/
|
||||
SBScriptLocatorRef SBScriptLocatorRetain(SBScriptLocatorRef locator);
|
||||
|
||||
/**
|
||||
* Decrements the reference count of a script locator object. The object will be deallocated when
|
||||
* its reference count reaches zero.
|
||||
*
|
||||
* @param locator
|
||||
* The script locator object whose reference count will be decremented.
|
||||
*/
|
||||
void SBScriptLocatorRelease(SBScriptLocatorRef locator);
|
||||
|
||||
#endif
|
33
lib/sheenbidi/Headers/SheenBidi.h
Normal file
33
lib/sheenbidi/Headers/SheenBidi.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _SHEEN_BIDI_H
|
||||
#define _SHEEN_BIDI_H
|
||||
|
||||
#include "SBAlgorithm.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBBidiType.h"
|
||||
#include "SBCodepoint.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "SBGeneralCategory.h"
|
||||
#include "SBLine.h"
|
||||
#include "SBMirrorLocator.h"
|
||||
#include "SBParagraph.h"
|
||||
#include "SBRun.h"
|
||||
#include "SBScript.h"
|
||||
#include "SBScriptLocator.h"
|
||||
|
||||
#endif
|
202
lib/sheenbidi/LICENSE
Executable file
202
lib/sheenbidi/LICENSE
Executable file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
107
lib/sheenbidi/README.md
Normal file
107
lib/sheenbidi/README.md
Normal file
@ -0,0 +1,107 @@
|
||||
SheenBidi
|
||||
=========
|
||||
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
|
||||
[![Travis-CI Build Status](https://api.travis-ci.org/Tehreer/SheenBidi.svg?branch=master)](https://travis-ci.org/Tehreer/SheenBidi)
|
||||
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/k2vvegcdqsb9ld5a?svg=true)](https://ci.appveyor.com/project/mta452/sheenbidi)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/Tehreer/SheenBidi/badge.svg?branch=master)](https://coveralls.io/github/Tehreer/SheenBidi)
|
||||
|
||||
SheenBidi implements Unicode Bidirectional Algorithm available at http://www.unicode.org/reports/tr9. It is a sophisticated implementaion which provides the developers an easy way to use UBA in their applications.
|
||||
|
||||
Here are some of the advantages of SheenBidi.
|
||||
|
||||
* Object based.
|
||||
* Optimized to the core.
|
||||
* Designed to be thread safe.
|
||||
* Lightweight API for interaction.
|
||||
* Supports UTF-8, UTF-16 and UTF-32 encodings.
|
||||
|
||||
## API
|
||||
<img src="https://user-images.githubusercontent.com/2664112/39663208-716af1c4-5088-11e8-855c-ababe3e58c58.png" width="350">
|
||||
The above screenshot depicts a visual representation of the API on a sample text.
|
||||
|
||||
### SBCodepointSequence
|
||||
It works as a code point decoder by accepting a string buffer in specified encoding.
|
||||
|
||||
### SBAlgorithm
|
||||
It provides bidirectional type of each code unit in source string. Paragraph boundaries can be quried from it as determined by rule [P1](https://www.unicode.org/reports/tr9/#P1). Individual paragraph objects can be created from it by explicitly specifying the base level or deriving it from rules [P2](https://www.unicode.org/reports/tr9/#P2)-[P3](https://www.unicode.org/reports/tr9/#P3).
|
||||
|
||||
### SBParagraph
|
||||
It represents a single paragraph of text processed with rules [X1](https://www.unicode.org/reports/tr9/#X1)-[I2](https://www.unicode.org/reports/tr9/#I2). It provides resolved embedding levels of all the code units of a paragraph.
|
||||
|
||||
### SBLine
|
||||
It represents a single line of text processed with rules [L1](https://www.unicode.org/reports/tr9/#L1)-[L2](https://www.unicode.org/reports/tr9/#L2). However, it provides reordered level runs instead of reordered characters.
|
||||
|
||||
### SBRun
|
||||
It represents a sequence of characters which have the same embedding level. The direction of a run would be right-to-left, if its embedding level is odd.
|
||||
|
||||
### SBMirrorLocator
|
||||
It provides the facility to find out the mirrored characters in a line as determined by rule [L4](https://www.unicode.org/reports/tr9/#L4).
|
||||
|
||||
### SBScriptLocator
|
||||
Not directly related to UBA but can be useful for text shaping. It provides the facility to find out the script runs as specified in [UAX #24](https://www.unicode.org/reports/tr24/).
|
||||
|
||||
## Dependency
|
||||
SheenBidi does not depend on any external library. It only uses standard C library headers ```stddef.h```, ```stdint.h``` and ```stdlib.h```.
|
||||
|
||||
## Configuration
|
||||
The configuration options are available in `Headers/SBConfig.h`.
|
||||
|
||||
* ```SB_CONFIG_LOG``` logs every activity performed in order to apply bidirectional algorithm.
|
||||
* ```SB_CONFIG_UNITY``` builds the library as a single module and lets the compiler make decisions to inline functions.
|
||||
|
||||
## Compiling
|
||||
SheenBidi can be compiled with any C compiler. The best way for compiling is to add all the files in an IDE and hit build. The only thing to consider however is that if ```SB_CONFIG_UNITY``` is enabled then only ```Source/SheenBidi.c``` should be compiled.
|
||||
|
||||
## Example
|
||||
Here is a simple example written in C11.
|
||||
|
||||
```c
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <SheenBidi.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
/* Create code point sequence for a sample bidirectional text. */
|
||||
const char *bidiText = "یہ ایک )car( ہے۔";
|
||||
SBCodepointSequence codepointSequence = { SBStringEncodingUTF8, (void *)bidiText, strlen(bidiText) };
|
||||
|
||||
/* Extract the first bidirectional paragraph. */
|
||||
SBAlgorithmRef bidiAlgorithm = SBAlgorithmCreate(&codepointSequence);
|
||||
SBParagraphRef firstParagraph = SBAlgorithmCreateParagraph(bidiAlgorithm, 0, INT32_MAX, SBLevelDefaultLTR);
|
||||
SBUInteger paragraphLength = SBParagraphGetLength(firstParagraph);
|
||||
|
||||
/* Create a line consisting of whole paragraph and get its runs. */
|
||||
SBLineRef paragraphLine = SBParagraphCreateLine(firstParagraph, 0, paragraphLength);
|
||||
SBUInteger runCount = SBLineGetRunCount(paragraphLine);
|
||||
const SBRun *runArray = SBLineGetRunsPtr(paragraphLine);
|
||||
|
||||
/* Log the details of each run in the line. */
|
||||
for (SBUInteger i = 0; i < runCount; i++) {
|
||||
printf("Run Offset: %ld\n", (long)runArray[i].offset);
|
||||
printf("Run Length: %ld\n", (long)runArray[i].length);
|
||||
printf("Run Level: %ld\n\n", (long)runArray[i].level);
|
||||
}
|
||||
|
||||
/* Create a mirror locator and load the line in it. */
|
||||
SBMirrorLocatorRef mirrorLocator = SBMirrorLocatorCreate();
|
||||
SBMirrorLocatorLoadLine(mirrorLocator, paragraphLine, (void *)bidiText);
|
||||
const SBMirrorAgent *mirrorAgent = SBMirrorLocatorGetAgent(mirrorLocator);
|
||||
|
||||
/* Log the details of each mirror in the line. */
|
||||
while (SBMirrorLocatorMoveNext(mirrorLocator)) {
|
||||
printf("Mirror Index: %ld\n", (long)mirrorAgent->index);
|
||||
printf("Actual Code Point: %ld\n", (long)mirrorAgent->codepoint);
|
||||
printf("Mirrored Code Point: %ld\n\n", (long)mirrorAgent->mirror);
|
||||
}
|
||||
|
||||
/* Release all objects. */
|
||||
SBMirrorLocatorRelease(mirrorLocator);
|
||||
SBLineRelease(paragraphLine);
|
||||
SBParagraphRelease(firstParagraph);
|
||||
SBAlgorithmRelease(bidiAlgorithm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
110
lib/sheenbidi/Source/BidiChain.c
Normal file
110
lib/sheenbidi/Source/BidiChain.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 "SBBase.h"
|
||||
#include "BidiChain.h"
|
||||
|
||||
SB_INTERNAL void BidiChainInitialize(BidiChainRef chain,
|
||||
SBBidiType *types, SBLevel *levels, BidiLink *links)
|
||||
{
|
||||
chain->types = types;
|
||||
chain->levels = levels;
|
||||
chain->links = links;
|
||||
chain->roller = 0;
|
||||
chain->last = 0;
|
||||
|
||||
/* Make first link empty. */
|
||||
chain->types[0] = SBBidiTypeNil;
|
||||
chain->levels[0] = SBLevelInvalid;
|
||||
chain->links[0] = BidiLinkNone;
|
||||
}
|
||||
|
||||
SB_INTERNAL void BidiChainAdd(BidiChainRef chain, SBBidiType type, SBUInteger length)
|
||||
{
|
||||
BidiLink last = chain->last;
|
||||
BidiLink current = last + (SBUInt32)length;
|
||||
|
||||
chain->types[current] = type;
|
||||
chain->links[current] = chain->roller;
|
||||
|
||||
chain->links[last] = current;
|
||||
chain->last = current;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBoolean BidiChainIsSingle(BidiChainRef chain, BidiLink link)
|
||||
{
|
||||
BidiLink next = chain->links[link];
|
||||
|
||||
/* Check the type of in between code units. */
|
||||
while (++link != next) {
|
||||
if (chain->types[link] != SBBidiTypeBN) {
|
||||
return SBFalse;
|
||||
}
|
||||
}
|
||||
|
||||
return SBTrue;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBidiType BidiChainGetType(BidiChainRef chain, BidiLink link)
|
||||
{
|
||||
return chain->types[link];
|
||||
}
|
||||
|
||||
SB_INTERNAL void BidiChainSetType(BidiChainRef chain, BidiLink link, SBBidiType type)
|
||||
{
|
||||
chain->types[link] = type;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBLevel BidiChainGetLevel(BidiChainRef chain, BidiLink link)
|
||||
{
|
||||
return chain->levels[link];
|
||||
}
|
||||
|
||||
SB_INTERNAL void BidiChainSetLevel(BidiChainRef chain, BidiLink link, SBLevel level)
|
||||
{
|
||||
chain->levels[link] = level;
|
||||
}
|
||||
|
||||
SB_INTERNAL BidiLink BidiChainGetNext(BidiChainRef chain, BidiLink link)
|
||||
{
|
||||
return chain->links[link];
|
||||
}
|
||||
|
||||
SB_INTERNAL void BidiChainSetNext(BidiChainRef chain, BidiLink link, BidiLink next)
|
||||
{
|
||||
chain->links[link] = next;
|
||||
}
|
||||
|
||||
SB_INTERNAL void BidiChainAbandonNext(BidiChainRef chain, BidiLink link)
|
||||
{
|
||||
BidiLink next = chain->links[link];
|
||||
BidiLink limit = chain->links[next];
|
||||
|
||||
chain->links[link] = limit;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBoolean BidiChainMergeIfEqual(BidiChainRef chain, BidiLink first, BidiLink second)
|
||||
{
|
||||
if (chain->types[first] == chain->types[second]
|
||||
&& chain->levels[first] == chain->levels[second]) {
|
||||
chain->links[first] = chain->links[second];
|
||||
return SBTrue;
|
||||
}
|
||||
|
||||
return SBFalse;
|
||||
}
|
60
lib/sheenbidi/Source/BidiChain.h
Normal file
60
lib/sheenbidi/Source/BidiChain.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_BIDI_CHAIN_H
|
||||
#define _SB_INTERNAL_BIDI_CHAIN_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
#include "SBBase.h"
|
||||
|
||||
typedef SBUInt32 BidiLink;
|
||||
|
||||
#define BidiLinkNone (SBUInt32)(-1)
|
||||
|
||||
typedef struct _BidiChain {
|
||||
SBBidiType *types;
|
||||
SBLevel *levels;
|
||||
BidiLink *links;
|
||||
BidiLink roller;
|
||||
BidiLink last;
|
||||
} BidiChain, *BidiChainRef;
|
||||
|
||||
SB_INTERNAL void BidiChainInitialize(BidiChainRef chain,
|
||||
SBBidiType *types, SBLevel *levels, BidiLink *links);
|
||||
SB_INTERNAL void BidiChainAdd(BidiChainRef chain, SBBidiType type, SBUInteger length);
|
||||
|
||||
#define BidiChainGetOffset(chain, link) \
|
||||
( \
|
||||
(link) - 1 \
|
||||
)
|
||||
|
||||
SB_INTERNAL SBBoolean BidiChainIsSingle(BidiChainRef chain, BidiLink link);
|
||||
|
||||
SB_INTERNAL SBBidiType BidiChainGetType(BidiChainRef chain, BidiLink link);
|
||||
SB_INTERNAL void BidiChainSetType(BidiChainRef chain, BidiLink link, SBBidiType type);
|
||||
|
||||
SB_INTERNAL SBLevel BidiChainGetLevel(BidiChainRef chain, BidiLink link);
|
||||
SB_INTERNAL void BidiChainSetLevel(BidiChainRef chain, BidiLink link, SBLevel level);
|
||||
|
||||
SB_INTERNAL BidiLink BidiChainGetNext(BidiChainRef chain, BidiLink link);
|
||||
SB_INTERNAL void BidiChainSetNext(BidiChainRef chain, BidiLink link, BidiLink next);
|
||||
SB_INTERNAL void BidiChainAbandonNext(BidiChainRef chain, BidiLink link);
|
||||
SB_INTERNAL SBBoolean BidiChainMergeIfEqual(BidiChainRef chain, BidiLink first, BidiLink second);
|
||||
|
||||
#define BidiChainForEach(chain, roller, link) \
|
||||
for (link = chain->links[roller]; link != roller; link = chain->links[link])
|
||||
|
||||
#endif
|
1014
lib/sheenbidi/Source/BidiTypeLookup.c
Normal file
1014
lib/sheenbidi/Source/BidiTypeLookup.c
Normal file
File diff suppressed because it is too large
Load Diff
16
lib/sheenbidi/Source/BidiTypeLookup.h
Normal file
16
lib/sheenbidi/Source/BidiTypeLookup.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Automatically generated by SheenBidiGenerator tool.
|
||||
* DO NOT EDIT!!
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_BIDI_TYPE_LOOKUP_H
|
||||
#define _SB_INTERNAL_BIDI_TYPE_LOOKUP_H
|
||||
|
||||
#include <SBBidiType.h>
|
||||
#include <SBConfig.h>
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
SB_INTERNAL SBBidiType LookupBidiType(SBCodepoint codepoint);
|
||||
|
||||
#endif
|
230
lib/sheenbidi/Source/BracketQueue.c
Normal file
230
lib/sheenbidi/Source/BracketQueue.c
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "BidiChain.h"
|
||||
#include "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "BracketQueue.h"
|
||||
|
||||
static void BracketQueueFinalizePairs(BracketQueueRef queue, BracketQueueListRef list, SBInteger top)
|
||||
{
|
||||
do {
|
||||
SBInteger limit = (list == queue->_rearList ? queue->_rearTop : BracketQueueList_MaxIndex);
|
||||
|
||||
while (++top <= limit) {
|
||||
if (list->openingLink[top] != BidiLinkNone
|
||||
&& list->closingLink[top] == BidiLinkNone) {
|
||||
list->openingLink[top] = BidiLinkNone;
|
||||
}
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
top = 0;
|
||||
} while (list);
|
||||
}
|
||||
|
||||
SB_INTERNAL void BracketQueueInitialize(BracketQueueRef queue)
|
||||
{
|
||||
queue->_firstList.previous = NULL;
|
||||
queue->_firstList.next = NULL;
|
||||
queue->_frontList = NULL;
|
||||
queue->_rearList = NULL;
|
||||
queue->count = 0;
|
||||
queue->shouldDequeue = SBFalse;
|
||||
}
|
||||
|
||||
SB_INTERNAL void BracketQueueReset(BracketQueueRef queue, SBBidiType direction)
|
||||
{
|
||||
queue->_frontList = &queue->_firstList;
|
||||
queue->_rearList = &queue->_firstList;
|
||||
queue->_frontTop = 0;
|
||||
queue->_rearTop = -1;
|
||||
queue->count = 0;
|
||||
queue->shouldDequeue = SBFalse;
|
||||
queue->_direction = direction;
|
||||
}
|
||||
|
||||
SB_INTERNAL void BracketQueueEnqueue(BracketQueueRef queue,
|
||||
BidiLink priorStrongLink, BidiLink openingLink, SBCodepoint bracket)
|
||||
{
|
||||
BracketQueueListRef list;
|
||||
SBInteger top;
|
||||
|
||||
/* The queue can only take a maximum of 63 elements. */
|
||||
SBAssert(queue->count < BracketQueueGetMaxCapacity());
|
||||
|
||||
if (queue->_rearTop != BracketQueueList_MaxIndex) {
|
||||
list = queue->_rearList;
|
||||
top = ++queue->_rearTop;
|
||||
} else {
|
||||
BracketQueueListRef rearList;
|
||||
|
||||
rearList = queue->_rearList;
|
||||
list = rearList->next;
|
||||
|
||||
if (!list) {
|
||||
list = malloc(sizeof(BracketQueueList));
|
||||
list->previous = rearList;
|
||||
list->next = NULL;
|
||||
|
||||
rearList->next = list;
|
||||
}
|
||||
|
||||
queue->_rearList = list;
|
||||
queue->_rearTop = top = 0;
|
||||
}
|
||||
queue->count += 1;
|
||||
|
||||
list->priorStrongLink[top] = priorStrongLink;
|
||||
list->openingLink[top] = openingLink;
|
||||
list->closingLink[top] = BidiLinkNone;
|
||||
list->bracket[top] = bracket;
|
||||
list->strongType[top] = SBBidiTypeNil;
|
||||
}
|
||||
|
||||
SB_INTERNAL void BracketQueueDequeue(BracketQueueRef queue)
|
||||
{
|
||||
/* The queue must NOT be empty. */
|
||||
SBAssert(queue->count != 0);
|
||||
|
||||
if (queue->_frontTop != BracketQueueList_MaxIndex) {
|
||||
queue->_frontTop += 1;
|
||||
} else {
|
||||
BracketQueueListRef frontList = queue->_frontList;
|
||||
|
||||
if (frontList == queue->_rearList) {
|
||||
queue->_rearTop = -1;
|
||||
} else {
|
||||
queue->_frontList = frontList->next;
|
||||
}
|
||||
|
||||
queue->_frontTop = 0;
|
||||
}
|
||||
|
||||
queue->count -= 1;
|
||||
}
|
||||
|
||||
SB_INTERNAL void BracketQueueSetStrongType(BracketQueueRef queue, SBBidiType strongType)
|
||||
{
|
||||
BracketQueueListRef list = queue->_rearList;
|
||||
SBInteger top = queue->_rearTop;
|
||||
|
||||
while (1) {
|
||||
SBInteger limit = (list == queue->_frontList ? queue->_frontTop : 0);
|
||||
|
||||
do {
|
||||
if (list->closingLink[top] == BidiLinkNone
|
||||
&& list->strongType[top] != queue->_direction) {
|
||||
list->strongType[top] = strongType;
|
||||
}
|
||||
} while (top-- > limit);
|
||||
|
||||
if (list == queue->_frontList) {
|
||||
break;
|
||||
}
|
||||
|
||||
list = list->previous;
|
||||
top = BracketQueueList_MaxIndex;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void BracketQueueClosePair(BracketQueueRef queue, BidiLink closingLink, SBCodepoint bracket)
|
||||
{
|
||||
BracketQueueListRef list = queue->_rearList;
|
||||
SBInteger top = queue->_rearTop;
|
||||
SBCodepoint canonical;
|
||||
|
||||
switch (bracket) {
|
||||
case 0x232A:
|
||||
canonical = 0x3009;
|
||||
break;
|
||||
|
||||
case 0x3009:
|
||||
canonical = 0x232A;
|
||||
break;
|
||||
|
||||
default:
|
||||
canonical = bracket;
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
SBBoolean isFrontList = (list == queue->_frontList);
|
||||
SBInteger limit = (isFrontList ? queue->_frontTop : 0);
|
||||
|
||||
do {
|
||||
if (list->openingLink[top] != BidiLinkNone
|
||||
&& list->closingLink[top] == BidiLinkNone
|
||||
&& (list->bracket[top] == bracket || list->bracket[top] == canonical)) {
|
||||
list->closingLink[top] = closingLink;
|
||||
BracketQueueFinalizePairs(queue, list, top);
|
||||
|
||||
if (isFrontList && top == queue->_frontTop) {
|
||||
queue->shouldDequeue = SBTrue;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} while (top-- > limit);
|
||||
|
||||
if (isFrontList) {
|
||||
break;
|
||||
}
|
||||
|
||||
list = list->previous;
|
||||
top = BracketQueueList_MaxIndex;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBoolean BracketQueueShouldDequeue(BracketQueueRef queue)
|
||||
{
|
||||
return queue->shouldDequeue;
|
||||
}
|
||||
|
||||
SB_INTERNAL BidiLink BracketQueueGetPriorStrongLink(BracketQueueRef queue)
|
||||
{
|
||||
return queue->_frontList->priorStrongLink[queue->_frontTop];
|
||||
}
|
||||
|
||||
SB_INTERNAL BidiLink BracketQueueGetOpeningLink(BracketQueueRef queue)
|
||||
{
|
||||
return queue->_frontList->openingLink[queue->_frontTop];
|
||||
}
|
||||
|
||||
SB_INTERNAL BidiLink BracketQueueGetClosingLink(BracketQueueRef queue)
|
||||
{
|
||||
return queue->_frontList->closingLink[queue->_frontTop];
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBidiType BracketQueueGetStrongType(BracketQueueRef queue)
|
||||
{
|
||||
return queue->_frontList->strongType[queue->_frontTop];
|
||||
}
|
||||
|
||||
SB_INTERNAL void BracketQueueFinalize(BracketQueueRef queue)
|
||||
{
|
||||
BracketQueueListRef list = queue->_firstList.next;
|
||||
|
||||
while (list) {
|
||||
BracketQueueListRef next = list->next;
|
||||
free(list);
|
||||
list = next;
|
||||
}
|
||||
}
|
72
lib/sheenbidi/Source/BracketQueue.h
Normal file
72
lib/sheenbidi/Source/BracketQueue.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_BRACKET_QUEUE_H
|
||||
#define _SB_INTERNAL_BRACKET_QUEUE_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
|
||||
#include "BidiChain.h"
|
||||
#include "SBBase.h"
|
||||
|
||||
#define BracketQueueList_Length 8
|
||||
#define BracketQueueList_MaxIndex (BracketQueueList_Length - 1)
|
||||
|
||||
typedef struct _BracketQueueList {
|
||||
SBCodepoint bracket[BracketQueueList_Length];
|
||||
BidiLink priorStrongLink[BracketQueueList_Length];
|
||||
BidiLink openingLink[BracketQueueList_Length];
|
||||
BidiLink closingLink[BracketQueueList_Length];
|
||||
SBBidiType strongType[BracketQueueList_Length];
|
||||
|
||||
struct _BracketQueueList *previous;
|
||||
struct _BracketQueueList *next;
|
||||
} BracketQueueList, *BracketQueueListRef;
|
||||
|
||||
typedef struct _BracketQueue {
|
||||
BracketQueueList _firstList;
|
||||
BracketQueueListRef _frontList;
|
||||
BracketQueueListRef _rearList;
|
||||
SBInteger _frontTop;
|
||||
SBInteger _rearTop;
|
||||
SBUInteger count;
|
||||
SBBoolean shouldDequeue;
|
||||
SBBidiType _direction;
|
||||
} BracketQueue, *BracketQueueRef;
|
||||
|
||||
#define BracketQueueGetMaxCapacity() 63
|
||||
|
||||
SB_INTERNAL void BracketQueueInitialize(BracketQueueRef queue);
|
||||
SB_INTERNAL void BracketQueueReset(BracketQueueRef queue, SBBidiType direction);
|
||||
|
||||
SB_INTERNAL void BracketQueueEnqueue(BracketQueueRef queue,
|
||||
BidiLink priorStrongLink, BidiLink openingLink, SBCodepoint bracket);
|
||||
SB_INTERNAL void BracketQueueDequeue(BracketQueueRef queue);
|
||||
|
||||
SB_INTERNAL void BracketQueueSetStrongType(BracketQueueRef queue, SBBidiType strongType);
|
||||
SB_INTERNAL void BracketQueueClosePair(BracketQueueRef queue,
|
||||
BidiLink closingLink, SBCodepoint bracket);
|
||||
|
||||
SB_INTERNAL SBBoolean BracketQueueShouldDequeue(BracketQueueRef queue);
|
||||
|
||||
SB_INTERNAL BidiLink BracketQueueGetPriorStrongLink(BracketQueueRef queue);
|
||||
SB_INTERNAL BidiLink BracketQueueGetOpeningLink(BracketQueueRef queue);
|
||||
SB_INTERNAL BidiLink BracketQueueGetClosingLink(BracketQueueRef queue);
|
||||
SB_INTERNAL SBBidiType BracketQueueGetStrongType(BracketQueueRef queue);
|
||||
|
||||
SB_INTERNAL void BracketQueueFinalize(BracketQueueRef queue);
|
||||
|
||||
#endif
|
32
lib/sheenbidi/Source/BracketType.h
Normal file
32
lib/sheenbidi/Source/BracketType.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_BRACKET_TYPE_H
|
||||
#define _SB_INTERNAL_BRACKET_TYPE_H
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
enum {
|
||||
BracketTypeNone = 0x00,
|
||||
BracketTypeOpen = 0x40, /**< Opening paired bracket. */
|
||||
BracketTypeClose = 0x80, /**< Closing paired bracket. */
|
||||
|
||||
BracketTypePrimaryMask = BracketTypeOpen | BracketTypeClose,
|
||||
BracketTypeInverseMask = ~BracketTypePrimaryMask
|
||||
};
|
||||
typedef SBUInt8 BracketType;
|
||||
|
||||
#endif
|
1964
lib/sheenbidi/Source/GeneralCategoryLookup.c
Normal file
1964
lib/sheenbidi/Source/GeneralCategoryLookup.c
Normal file
File diff suppressed because it is too large
Load Diff
16
lib/sheenbidi/Source/GeneralCategoryLookup.h
Normal file
16
lib/sheenbidi/Source/GeneralCategoryLookup.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Automatically generated by SheenBidiGenerator tool.
|
||||
* DO NOT EDIT!!
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_GENERAL_CATEGORY_LOOKUP_H
|
||||
#define _SB_INTERNAL_GENERAL_CATEGORY_LOOKUP_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
#include <SBGeneralCategory.h>
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
SB_INTERNAL SBGeneralCategory LookupGeneralCategory(SBCodepoint codepoint);
|
||||
|
||||
#endif
|
529
lib/sheenbidi/Source/IsolatingRun.c
Normal file
529
lib/sheenbidi/Source/IsolatingRun.c
Normal file
@ -0,0 +1,529 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 "BidiChain.h"
|
||||
#include "BracketQueue.h"
|
||||
#include "BracketType.h"
|
||||
#include "LevelRun.h"
|
||||
#include "PairingLookup.h"
|
||||
#include "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBLog.h"
|
||||
#include "IsolatingRun.h"
|
||||
|
||||
static void ResolveAvailableBracketPairs(IsolatingRunRef isolatingRun);
|
||||
|
||||
static void AttachLevelRunLinks(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BidiChainRef chain = isolatingRun->bidiChain;
|
||||
LevelRunRef baseLevelRun = isolatingRun->baseLevelRun;
|
||||
LevelRunRef current;
|
||||
LevelRunRef next;
|
||||
|
||||
isolatingRun->_originalLink = BidiChainGetNext(chain, chain->roller);
|
||||
BidiChainSetNext(chain, chain->roller, baseLevelRun->firstLink);
|
||||
|
||||
/* Iterate over level runs and attach their links to form an isolating run. */
|
||||
for (current = baseLevelRun; (next = current->next); current = next) {
|
||||
BidiChainSetNext(chain, current->lastLink, next->firstLink);
|
||||
}
|
||||
BidiChainSetNext(chain, current->lastLink, chain->roller);
|
||||
|
||||
isolatingRun->_lastLevelRun = current;
|
||||
isolatingRun->_sos = RunExtrema_SOR(baseLevelRun->extrema);
|
||||
|
||||
if (!RunKindIsPartialIsolate(baseLevelRun->kind)) {
|
||||
isolatingRun->_eos = RunExtrema_EOR(current->extrema);
|
||||
} else {
|
||||
SBLevel paragraphLevel = isolatingRun->paragraphLevel;
|
||||
SBLevel runLevel = baseLevelRun->level;
|
||||
SBLevel eosLevel = (runLevel > paragraphLevel ? runLevel : paragraphLevel);
|
||||
isolatingRun->_eos = ((eosLevel & 1) ? SBBidiTypeR : SBBidiTypeL);
|
||||
}
|
||||
}
|
||||
|
||||
static void AttachOriginalLinks(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BidiChainRef chain = isolatingRun->bidiChain;
|
||||
LevelRunRef current;
|
||||
|
||||
BidiChainSetNext(chain, chain->roller, isolatingRun->_originalLink);
|
||||
|
||||
/* Iterate over level runs and attach original subsequent links. */
|
||||
for (current = isolatingRun->baseLevelRun; current; current = current->next) {
|
||||
BidiChainSetNext(chain, current->lastLink, current->subsequentLink);
|
||||
}
|
||||
}
|
||||
|
||||
static BidiLink ResolveWeakTypes(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BidiChainRef chain = isolatingRun->bidiChain;
|
||||
BidiLink roller = chain->roller;
|
||||
BidiLink link;
|
||||
|
||||
BidiLink priorLink;
|
||||
SBBidiType sos;
|
||||
|
||||
SBBidiType w1PriorType;
|
||||
SBBidiType w2StrongType;
|
||||
SBBidiType w4PriorType;
|
||||
SBBidiType w5PriorType;
|
||||
SBBidiType w7StrongType;
|
||||
|
||||
priorLink = roller;
|
||||
sos = isolatingRun->_sos;
|
||||
|
||||
w1PriorType = sos;
|
||||
w2StrongType = sos;
|
||||
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
SBBoolean forceMerge = SBFalse;
|
||||
|
||||
/* Rule W1 */
|
||||
if (type == SBBidiTypeNSM) {
|
||||
/* Change the 'type' variable as well because it can be EN on which W2 depends. */
|
||||
type = (SBBidiTypeIsIsolate(w1PriorType) ? SBBidiTypeON : w1PriorType);
|
||||
BidiChainSetType(chain, link, type);
|
||||
|
||||
/* Fix for 3rd point of rule N0. */
|
||||
if (w1PriorType == SBBidiTypeON) {
|
||||
forceMerge = SBTrue;
|
||||
}
|
||||
}
|
||||
w1PriorType = type;
|
||||
|
||||
/* Rule W2 */
|
||||
if (type == SBBidiTypeEN) {
|
||||
if (w2StrongType == SBBidiTypeAL) {
|
||||
BidiChainSetType(chain, link, SBBidiTypeAN);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Rule W3
|
||||
* NOTE: It is safe to apply W3 in 'else-if' statement because it only depends on type AL.
|
||||
* Even if W2 changes EN to AN, there won't be any harm.
|
||||
*/
|
||||
else if (type == SBBidiTypeAL) {
|
||||
BidiChainSetType(chain, link, SBBidiTypeR);
|
||||
}
|
||||
|
||||
if (SBBidiTypeIsStrong(type)) {
|
||||
/* Save the strong type as it is checked in W2. */
|
||||
w2StrongType = type;
|
||||
}
|
||||
|
||||
if ((type != SBBidiTypeON && BidiChainGetType(chain, priorLink) == type) || forceMerge) {
|
||||
BidiChainAbandonNext(chain, priorLink);
|
||||
} else {
|
||||
priorLink = link;
|
||||
}
|
||||
}
|
||||
|
||||
priorLink = roller;
|
||||
w4PriorType = sos;
|
||||
w5PriorType = sos;
|
||||
w7StrongType = sos;
|
||||
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
SBBidiType nextType = BidiChainGetType(chain, BidiChainGetNext(chain, link));
|
||||
|
||||
/* Rule W4 */
|
||||
if (BidiChainIsSingle(chain, link)
|
||||
&& SBBidiTypeIsNumberSeparator(type)
|
||||
&& SBBidiTypeIsNumber(w4PriorType)
|
||||
&& (w4PriorType == nextType)
|
||||
&& (w4PriorType == SBBidiTypeEN || type == SBBidiTypeCS))
|
||||
{
|
||||
/* Change the current type as well because it can be EN on which W5 depends. */
|
||||
type = w4PriorType;
|
||||
BidiChainSetType(chain, link, type);
|
||||
}
|
||||
w4PriorType = type;
|
||||
|
||||
/* Rule W5 */
|
||||
if (type == SBBidiTypeET && (w5PriorType == SBBidiTypeEN || nextType == SBBidiTypeEN)) {
|
||||
/* Change the current type as well because it is EN on which W7 depends. */
|
||||
type = SBBidiTypeEN;
|
||||
BidiChainSetType(chain, link, type);
|
||||
}
|
||||
w5PriorType = type;
|
||||
|
||||
switch (type) {
|
||||
/* Rule W6 */
|
||||
case SBBidiTypeET:
|
||||
case SBBidiTypeCS:
|
||||
case SBBidiTypeES:
|
||||
BidiChainSetType(chain, link, SBBidiTypeON);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Rule W7
|
||||
* NOTE: W7 is expected to be applied after W6. However this is not the case here. The
|
||||
* reason is that W6 can only create the type ON which is not tested in W7 by any
|
||||
* means. So it won't affect the algorithm.
|
||||
*/
|
||||
case SBBidiTypeEN:
|
||||
if (w7StrongType == SBBidiTypeL) {
|
||||
BidiChainSetType(chain, link, SBBidiTypeL);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
* Save the strong type for W7.
|
||||
* NOTE: The strong type is expected to be saved after applying W7 because W7 itself creates
|
||||
* a strong type. However the strong type being saved here is based on the type after
|
||||
* W5. This won't effect the algorithm because a single link contains all consecutive
|
||||
* EN types. This means that even if W7 creates a strong type, it will be saved in
|
||||
* next iteration.
|
||||
*/
|
||||
case SBBidiTypeL:
|
||||
case SBBidiTypeR:
|
||||
w7StrongType = type;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type != SBBidiTypeON && BidiChainGetType(chain, priorLink) == type) {
|
||||
BidiChainAbandonNext(chain, priorLink);
|
||||
} else {
|
||||
priorLink = link;
|
||||
}
|
||||
}
|
||||
|
||||
return priorLink;
|
||||
}
|
||||
|
||||
static void ResolveBrackets(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
const SBCodepointSequence *sequence = isolatingRun->codepointSequence;
|
||||
SBUInteger paragraphOffset = isolatingRun->paragraphOffset;
|
||||
BracketQueueRef queue = &isolatingRun->_bracketQueue;
|
||||
BidiChainRef chain = isolatingRun->bidiChain;
|
||||
BidiLink roller = chain->roller;
|
||||
BidiLink link;
|
||||
|
||||
BidiLink priorStrongLink;
|
||||
SBLevel runLevel;
|
||||
|
||||
priorStrongLink = BidiLinkNone;
|
||||
runLevel = isolatingRun->baseLevelRun->level;
|
||||
|
||||
BracketQueueReset(queue, SBLevelAsNormalBidiType(runLevel));
|
||||
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBUInteger stringIndex;
|
||||
SBCodepoint codepoint;
|
||||
SBBidiType type;
|
||||
|
||||
SBCodepoint bracketValue;
|
||||
BracketType bracketType;
|
||||
|
||||
type = BidiChainGetType(chain, link);
|
||||
|
||||
switch (type) {
|
||||
case SBBidiTypeON:
|
||||
stringIndex = BidiChainGetOffset(chain, link) + paragraphOffset;
|
||||
codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex);
|
||||
bracketValue = LookupBracketPair(codepoint, &bracketType);
|
||||
|
||||
switch (bracketType) {
|
||||
case BracketTypeOpen:
|
||||
if (queue->count < BracketQueueGetMaxCapacity()) {
|
||||
BracketQueueEnqueue(queue, priorStrongLink, link, bracketValue);
|
||||
} else {
|
||||
goto Resolve;
|
||||
}
|
||||
break;
|
||||
|
||||
case BracketTypeClose:
|
||||
if (queue->count != 0) {
|
||||
BracketQueueClosePair(queue, link, codepoint);
|
||||
|
||||
if (BracketQueueShouldDequeue(queue)) {
|
||||
ResolveAvailableBracketPairs(isolatingRun);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SBBidiTypeEN:
|
||||
case SBBidiTypeAN:
|
||||
type = SBBidiTypeR;
|
||||
|
||||
case SBBidiTypeR:
|
||||
case SBBidiTypeL:
|
||||
if (queue->count != 0) {
|
||||
BracketQueueSetStrongType(queue, type);
|
||||
}
|
||||
|
||||
priorStrongLink = link;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Resolve:
|
||||
ResolveAvailableBracketPairs(isolatingRun);
|
||||
}
|
||||
|
||||
static void ResolveAvailableBracketPairs(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BracketQueueRef queue = &isolatingRun->_bracketQueue;
|
||||
BidiChainRef chain = isolatingRun->bidiChain;
|
||||
|
||||
SBLevel runLevel;
|
||||
SBBidiType embeddingDirection;
|
||||
SBBidiType oppositeDirection;
|
||||
|
||||
runLevel = isolatingRun->baseLevelRun->level;
|
||||
embeddingDirection = SBLevelAsNormalBidiType(runLevel);
|
||||
oppositeDirection = SBLevelAsOppositeBidiType(runLevel);
|
||||
|
||||
while (queue->count != 0) {
|
||||
BidiLink openingLink = BracketQueueGetOpeningLink(queue);
|
||||
BidiLink closingLink = BracketQueueGetClosingLink(queue);
|
||||
|
||||
if ((openingLink != BidiLinkNone) && (closingLink != BidiLinkNone)) {
|
||||
SBBidiType innerStrongType;
|
||||
SBBidiType pairType;
|
||||
|
||||
innerStrongType = BracketQueueGetStrongType(queue);
|
||||
|
||||
/* Rule: N0.b */
|
||||
if (innerStrongType == embeddingDirection) {
|
||||
pairType = innerStrongType;
|
||||
}
|
||||
/* Rule: N0.c */
|
||||
else if (innerStrongType == oppositeDirection) {
|
||||
BidiLink priorStrongLink;
|
||||
SBBidiType priorStrongType;
|
||||
|
||||
priorStrongLink = BracketQueueGetPriorStrongLink(queue);
|
||||
|
||||
if (priorStrongLink != BidiLinkNone) {
|
||||
BidiLink link;
|
||||
|
||||
priorStrongType = BidiChainGetType(chain, priorStrongLink);
|
||||
if (SBBidiTypeIsNumber(priorStrongType)) {
|
||||
priorStrongType = SBBidiTypeR;
|
||||
}
|
||||
|
||||
link = BidiChainGetNext(chain, priorStrongLink);
|
||||
|
||||
while (link != openingLink) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
if (type == SBBidiTypeL || type == SBBidiTypeR) {
|
||||
priorStrongType = type;
|
||||
}
|
||||
|
||||
link = BidiChainGetNext(chain, link);
|
||||
}
|
||||
} else {
|
||||
priorStrongType = isolatingRun->_sos;
|
||||
}
|
||||
|
||||
/* Rule: N0.c.1 */
|
||||
if (priorStrongType == oppositeDirection) {
|
||||
pairType = oppositeDirection;
|
||||
}
|
||||
/* Rule: N0.c.2 */
|
||||
else {
|
||||
pairType = embeddingDirection;
|
||||
}
|
||||
}
|
||||
/* Rule: N0.d */
|
||||
else {
|
||||
pairType = SBBidiTypeNil;
|
||||
}
|
||||
|
||||
if (pairType != SBBidiTypeNil) {
|
||||
/* Do the substitution */
|
||||
BidiChainSetType(chain, openingLink, pairType);
|
||||
BidiChainSetType(chain, closingLink, pairType);
|
||||
}
|
||||
}
|
||||
|
||||
BracketQueueDequeue(queue);
|
||||
}
|
||||
}
|
||||
|
||||
static void ResolveNeutrals(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BidiChainRef chain = isolatingRun->bidiChain;
|
||||
BidiLink roller = chain->roller;
|
||||
BidiLink link;
|
||||
|
||||
SBLevel runLevel;
|
||||
SBBidiType strongType;
|
||||
BidiLink neutralLink;
|
||||
|
||||
runLevel = isolatingRun->baseLevelRun->level;
|
||||
strongType = isolatingRun->_sos;
|
||||
neutralLink = BidiLinkNone;
|
||||
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
SBBidiType nextType;
|
||||
|
||||
SBAssert(SBBidiTypeIsStrongOrNumber(type) || SBBidiTypeIsNeutralOrIsolate(type));
|
||||
|
||||
switch (type) {
|
||||
case SBBidiTypeL:
|
||||
strongType = SBBidiTypeL;
|
||||
break;
|
||||
|
||||
case SBBidiTypeR:
|
||||
case SBBidiTypeEN:
|
||||
case SBBidiTypeAN:
|
||||
strongType = SBBidiTypeR;
|
||||
break;
|
||||
|
||||
case SBBidiTypeB:
|
||||
case SBBidiTypeS:
|
||||
case SBBidiTypeWS:
|
||||
case SBBidiTypeON:
|
||||
case SBBidiTypeLRI:
|
||||
case SBBidiTypeRLI:
|
||||
case SBBidiTypeFSI:
|
||||
case SBBidiTypePDI:
|
||||
if (neutralLink == BidiLinkNone) {
|
||||
neutralLink = link;
|
||||
}
|
||||
|
||||
nextType = BidiChainGetType(chain, BidiChainGetNext(chain, link));
|
||||
if (SBBidiTypeIsNumber(nextType)) {
|
||||
nextType = SBBidiTypeR;
|
||||
} else if (nextType == SBBidiTypeNil) {
|
||||
nextType = isolatingRun->_eos;
|
||||
}
|
||||
|
||||
if (SBBidiTypeIsStrong(nextType)) {
|
||||
/* Rules N1, N2 */
|
||||
SBBidiType resolvedType = (strongType == nextType
|
||||
? strongType
|
||||
: SBLevelAsNormalBidiType(runLevel));
|
||||
|
||||
do {
|
||||
BidiChainSetType(chain, neutralLink, resolvedType);
|
||||
neutralLink = BidiChainGetNext(chain, neutralLink);
|
||||
} while (neutralLink != BidiChainGetNext(chain, link));
|
||||
|
||||
neutralLink = BidiLinkNone;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ResolveImplicitLevels(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BidiChainRef chain = isolatingRun->bidiChain;
|
||||
BidiLink roller = chain->roller;
|
||||
BidiLink link;
|
||||
|
||||
SBLevel runLevel = isolatingRun->baseLevelRun->level;
|
||||
|
||||
if ((runLevel & 1) == 0) {
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
SBLevel level = BidiChainGetLevel(chain, link);
|
||||
|
||||
SBAssert(SBBidiTypeIsStrongOrNumber(type));
|
||||
|
||||
/* Rule I1 */
|
||||
if (type == SBBidiTypeR) {
|
||||
BidiChainSetLevel(chain, link, level + 1);
|
||||
} else if (type != SBBidiTypeL) {
|
||||
BidiChainSetLevel(chain, link, level + 2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
SBLevel level = BidiChainGetLevel(chain, link);
|
||||
|
||||
SBAssert(SBBidiTypeIsStrongOrNumber(type));
|
||||
|
||||
/* Rule I2 */
|
||||
if (type != SBBidiTypeR) {
|
||||
BidiChainSetLevel(chain, link, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void IsolatingRunInitialize(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BracketQueueInitialize(&isolatingRun->_bracketQueue);
|
||||
}
|
||||
|
||||
SB_INTERNAL void IsolatingRunResolve(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BidiLink lastLink;
|
||||
BidiLink subsequentLink;
|
||||
|
||||
SB_LOG_BLOCK_OPENER("Identified Isolating Run");
|
||||
|
||||
/* Attach level run links to form isolating run. */
|
||||
AttachLevelRunLinks(isolatingRun);
|
||||
/* Save last subsequent link. */
|
||||
subsequentLink = isolatingRun->_lastLevelRun->subsequentLink;
|
||||
|
||||
SB_LOG_STATEMENT("Range", 1, SB_LOG_RUN_RANGE(isolatingRun));
|
||||
SB_LOG_STATEMENT("Types", 1, SB_LOG_RUN_TYPES(isolatingRun));
|
||||
SB_LOG_STATEMENT("Level", 1, SB_LOG_LEVEL(isolatingRun->baseLevelRun->level));
|
||||
SB_LOG_STATEMENT("SOS", 1, SB_LOG_BIDI_TYPE(isolatingRun->_sos));
|
||||
SB_LOG_STATEMENT("EOS", 1, SB_LOG_BIDI_TYPE(isolatingRun->_eos));
|
||||
|
||||
/* Rules W1-W7 */
|
||||
lastLink = ResolveWeakTypes(isolatingRun);
|
||||
SB_LOG_BLOCK_OPENER("Resolved Weak Types");
|
||||
SB_LOG_STATEMENT("Types", 1, SB_LOG_RUN_TYPES(isolatingRun));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
/* Rule N0 */
|
||||
ResolveBrackets(isolatingRun);
|
||||
SB_LOG_BLOCK_OPENER("Resolved Brackets");
|
||||
SB_LOG_STATEMENT("Types", 1, SB_LOG_RUN_TYPES(isolatingRun));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
/* Rules N1, N2 */
|
||||
ResolveNeutrals(isolatingRun);
|
||||
SB_LOG_BLOCK_OPENER("Resolved Neutrals");
|
||||
SB_LOG_STATEMENT("Types", 1, SB_LOG_RUN_TYPES(isolatingRun));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
/* Rules I1, I2 */
|
||||
ResolveImplicitLevels(isolatingRun);
|
||||
SB_LOG_BLOCK_OPENER("Resolved Implicit Levels");
|
||||
SB_LOG_STATEMENT("Levels", 1, SB_LOG_RUN_LEVELS(isolatingRun));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
/* Re-attach original links. */
|
||||
AttachOriginalLinks(isolatingRun);
|
||||
/* Attach new final link (of isolating run) with last subsequent link. */
|
||||
BidiChainSetNext(isolatingRun->bidiChain, lastLink, subsequentLink);
|
||||
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
}
|
||||
|
||||
SB_INTERNAL void IsolatingRunFinalize(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
BracketQueueFinalize(&isolatingRun->_bracketQueue);
|
||||
}
|
47
lib/sheenbidi/Source/IsolatingRun.h
Normal file
47
lib/sheenbidi/Source/IsolatingRun.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_ISOLATING_RUN_H
|
||||
#define _SB_INTERNAL_ISOLATING_RUN_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
|
||||
#include "BidiChain.h"
|
||||
#include "BracketQueue.h"
|
||||
#include "LevelRun.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
|
||||
typedef struct _IsolatingRun {
|
||||
const SBCodepointSequence *codepointSequence;
|
||||
const SBBidiType *bidiTypes;
|
||||
BidiChainRef bidiChain;
|
||||
LevelRunRef baseLevelRun;
|
||||
LevelRunRef _lastLevelRun;
|
||||
BracketQueue _bracketQueue;
|
||||
SBUInteger paragraphOffset;
|
||||
BidiLink _originalLink;
|
||||
SBBidiType _sos;
|
||||
SBBidiType _eos;
|
||||
SBLevel paragraphLevel;
|
||||
} IsolatingRun, *IsolatingRunRef;
|
||||
|
||||
SB_INTERNAL void IsolatingRunInitialize(IsolatingRunRef isolatingRun);
|
||||
SB_INTERNAL void IsolatingRunResolve(IsolatingRunRef isolatingRun);
|
||||
|
||||
SB_INTERNAL void IsolatingRunFinalize(IsolatingRunRef isolatingRun);
|
||||
|
||||
#endif
|
68
lib/sheenbidi/Source/LevelRun.c
Normal file
68
lib/sheenbidi/Source/LevelRun.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <stddef.h>
|
||||
|
||||
#include "BidiChain.h"
|
||||
#include "RunExtrema.h"
|
||||
#include "RunKind.h"
|
||||
#include "SBAssert.h"
|
||||
#include "LevelRun.h"
|
||||
|
||||
SB_INTERNAL void LevelRunInitialize(LevelRunRef levelRun,
|
||||
BidiChainRef bidiChain, BidiLink firstLink, BidiLink lastLink,
|
||||
SBBidiType sor, SBBidiType eor)
|
||||
{
|
||||
SBBidiType firstType = BidiChainGetType(bidiChain, firstLink);
|
||||
SBBidiType lastType = BidiChainGetType(bidiChain, lastLink);
|
||||
|
||||
levelRun->next = NULL;
|
||||
levelRun->firstLink = firstLink;
|
||||
levelRun->lastLink = lastLink;
|
||||
levelRun->subsequentLink = BidiChainGetNext(bidiChain, lastLink);
|
||||
levelRun->extrema = RunExtremaMake(sor, eor);
|
||||
levelRun->kind = RunKindMake
|
||||
(
|
||||
SBBidiTypeIsIsolateInitiator(lastType),
|
||||
SBBidiTypeIsIsolateTerminator(firstType)
|
||||
);
|
||||
levelRun->level = BidiChainGetLevel(bidiChain, firstLink);
|
||||
}
|
||||
|
||||
SB_INTERNAL void LevelRunAttach(LevelRunRef levelRun, LevelRunRef next)
|
||||
{
|
||||
/* Only the runs of same level can be attached. */
|
||||
SBAssert(levelRun->level == next->level);
|
||||
/* No other run can be attached with a simple run. */
|
||||
SBAssert(!RunKindIsSimple(levelRun->kind));
|
||||
/* No other run can be attached with a complete isolating run. */
|
||||
SBAssert(!RunKindIsCompleteIsolate(levelRun->kind));
|
||||
/* Only a terminating run can be attached with an isolating run. */
|
||||
SBAssert(RunKindIsIsolate(levelRun->kind) && RunKindIsTerminating(next->kind));
|
||||
/* The next run must be unattached. */
|
||||
SBAssert(!RunKindIsAttachedTerminating(next->kind));
|
||||
|
||||
if (RunKindIsTerminating(next->kind)) {
|
||||
RunKindMakeAttached(next->kind);
|
||||
}
|
||||
|
||||
if (RunKindIsIsolate(levelRun->kind)) {
|
||||
RunKindMakeComplete(levelRun->kind);
|
||||
}
|
||||
|
||||
levelRun->next = next;
|
||||
}
|
42
lib/sheenbidi/Source/LevelRun.h
Normal file
42
lib/sheenbidi/Source/LevelRun.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_LEVEL_RUN_H
|
||||
#define _SB_INTERNAL_LEVEL_RUN_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
|
||||
#include "BidiChain.h"
|
||||
#include "RunExtrema.h"
|
||||
#include "RunKind.h"
|
||||
#include "SBBase.h"
|
||||
|
||||
typedef struct _LevelRun {
|
||||
struct _LevelRun *next; /**< Reference to the next sequence of run links. */
|
||||
BidiLink firstLink; /**< First link of the run. */
|
||||
BidiLink lastLink; /**< Last link of the run. */
|
||||
BidiLink subsequentLink; /**< Subsequent link of the run. */
|
||||
RunExtrema extrema;
|
||||
RunKind kind;
|
||||
SBLevel level;
|
||||
} LevelRun, *LevelRunRef;
|
||||
|
||||
SB_INTERNAL void LevelRunInitialize(LevelRunRef levelRun,
|
||||
BidiChainRef bidiChain, BidiLink firstLink, BidiLink lastLink,
|
||||
SBBidiType sor, SBBidiType eor);
|
||||
SB_INTERNAL void LevelRunAttach(LevelRunRef levelRun, LevelRunRef next);
|
||||
|
||||
#endif
|
256
lib/sheenbidi/Source/PairingLookup.c
Normal file
256
lib/sheenbidi/Source/PairingLookup.c
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Automatically generated by SheenBidiGenerator tool.
|
||||
* DO NOT EDIT!!
|
||||
*
|
||||
* REQUIRED MEMORY: (37)+2326+(579*2) = 3558 Bytes
|
||||
*/
|
||||
|
||||
#include "PairingLookup.h"
|
||||
|
||||
static const SBInt16 PairDifferences[37] = {
|
||||
0, 1, -1, 2, -2, 16, -16, 3, -3, 2016, 2527, 1923, 1914, 1918,
|
||||
2250, 138, 7, -7, 1824, 2104, 2108, 2106, 1316, -138, 8, -8, -1316,
|
||||
-1914, -1918, -1923, -1824, -2016, -2104, -2106, -2108, -2250, -2527
|
||||
};
|
||||
|
||||
static const SBUInt8 PairData[2326] = {
|
||||
/* DATA_BLOCK: -- 0x0000..0x0070 -- */
|
||||
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, 65, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 0, 4, 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, 67, 0, 132, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* DATA_BLOCK: -- 0x0071..0x00E1 -- */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 132, 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, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
|
||||
/* DATA_BLOCK: -- 0x00E2..0x0152 -- */
|
||||
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, 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,
|
||||
/* DATA_BLOCK: -- 0x0153..0x01C3 -- */
|
||||
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, 65,
|
||||
130, 65, 130, 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,
|
||||
/* DATA_BLOCK: -- 0x01C4..0x0234 -- */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 65, 130, 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, 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,
|
||||
/* DATA_BLOCK: -- 0x0235..0x02A5 -- */
|
||||
1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 130, 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, 65, 130, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 65, 130, 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,
|
||||
/* DATA_BLOCK: -- 0x02A6..0x0316 -- */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 8, 8, 8, 0, 0,
|
||||
0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13,
|
||||
0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0,
|
||||
0, 0, 0, 17, 0, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0,
|
||||
/* DATA_BLOCK: -- 0x0317..0x0387 -- */
|
||||
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
|
||||
2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 1, 2, 1, 2, 0,
|
||||
0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 19,
|
||||
0, 20, 21, 0, 21, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 22, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2,
|
||||
23, 0, 0, 1, 2, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1,
|
||||
/* DATA_BLOCK: -- 0x0388..0x03F8 -- */
|
||||
2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 1, 2,
|
||||
24, 24, 24, 0, 16, 16, 0, 0, 25, 25, 25, 17, 17, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 65, 130, 65, 130, 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, 65, 130,
|
||||
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,
|
||||
/* DATA_BLOCK: -- 0x03F9..0x0469 -- */
|
||||
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, 65, 130, 65, 130, 65, 130, 65,
|
||||
130, 65, 130, 65, 130, 65, 130, 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, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* DATA_BLOCK: -- 0x046A..0x04DA -- */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 65, 130, 0, 1, 2, 0, 3, 0,
|
||||
4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 26, 1, 2, 0,
|
||||
0, 0, 1, 2, 1, 2, 65, 130, 65, 130, 65, 130, 65, 130, 65, 130, 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,
|
||||
/* DATA_BLOCK: -- 0x04DB..0x054B -- */
|
||||
0, 0, 0, 0, 0, 65, 130, 65, 130, 65, 130, 65, 130, 65, 130, 71, 129, 66, 136,
|
||||
65, 130, 65, 130, 65, 130, 65, 130, 0, 0, 27, 0, 0, 0, 0, 28, 0, 0, 29,
|
||||
1, 2, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 30, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 2, 1, 2, 0, 1, 2, 0, 0, 65, 130, 65, 130, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0,
|
||||
/* DATA_BLOCK: -- 0x054C..0x05BC -- */
|
||||
0, 0, 0, 0, 0, 0, 31, 0, 0, 1, 2, 0, 0, 65, 130, 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, 1, 2, 1, 2, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 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,
|
||||
/* DATA_BLOCK: -- 0x05BD..0x062D -- */
|
||||
0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
|
||||
2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
|
||||
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 1, 2, 1, 2, 1, 2,
|
||||
1, 2, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
|
||||
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
|
||||
/* DATA_BLOCK: -- 0x062E..0x069E -- */
|
||||
1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 33,
|
||||
34, 33, 0, 0, 0, 0, 0, 0, 1, 2, 35, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 1, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* DATA_BLOCK: -- 0x069F..0x070F -- */
|
||||
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36,
|
||||
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,
|
||||
/* DATA_BLOCK: -- 0x0710..0x0780 -- */
|
||||
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, 1, 2, 1, 2, 0, 0, 0, 1, 2, 0, 1, 2,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1,
|
||||
2, 65, 130, 65, 130, 65, 130, 65, 130, 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,
|
||||
/* DATA_BLOCK: -- 0x0781..0x07F1 -- */
|
||||
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, 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, 65, 130, 65,
|
||||
130, 65, 130, 65, 130, 65, 130, 0, 0, 65, 130, 65, 130, 65, 130, 65, 130, 0,
|
||||
/* DATA_BLOCK: -- 0x07F2..0x0862 -- */
|
||||
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, 65, 130, 65, 130, 65, 130, 0, 0, 0, 0, 0, 1, 2,
|
||||
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* DATA_BLOCK: -- 0x0863..0x08D3 -- */
|
||||
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, 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, 65, 130, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 4, 0, 0, 0,
|
||||
/* DATA_BLOCK: -- 0x08D4..0x0915 -- */
|
||||
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, 67, 0, 132, 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,
|
||||
67, 0, 132, 0, 65, 130, 0, 65, 130,
|
||||
};
|
||||
|
||||
static const SBUInt16 PairIndexes[579] = {
|
||||
0x0000, 0x0071, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x0153, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x01C4, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x0235, 0x00E2, 0x00E2, 0x00E2, 0x02A6, 0x0317, 0x0388, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x03F9, 0x046A, 0x00E2, 0x00E2, 0x00E2, 0x04DB, 0x054C,
|
||||
0x05BD, 0x062E, 0x00E2, 0x069F, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x0710, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x0781, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2, 0x00E2,
|
||||
0x07F2, 0x0863, 0x08D4
|
||||
};
|
||||
|
||||
SB_INTERNAL SBCodepoint LookupMirror(SBCodepoint codepoint)
|
||||
{
|
||||
if (codepoint <= 0xFF63) {
|
||||
SBInt16 diff = PairDifferences[
|
||||
PairData[
|
||||
PairIndexes[
|
||||
codepoint / 0x071
|
||||
] + (codepoint % 0x071)
|
||||
] & BracketTypeInverseMask
|
||||
];
|
||||
|
||||
if (diff != 0) {
|
||||
return (codepoint + diff);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBCodepoint LookupBracketPair(SBCodepoint codepoint, BracketType *type)
|
||||
{
|
||||
if (codepoint <= 0xFF63) {
|
||||
SBUInt8 data = PairData[
|
||||
PairIndexes[
|
||||
codepoint / 0x071
|
||||
] + (codepoint % 0x071)
|
||||
];
|
||||
*type = (data & BracketTypePrimaryMask);
|
||||
|
||||
if (*type != 0) {
|
||||
SBInt16 diff = PairDifferences[
|
||||
data & BracketTypeInverseMask
|
||||
];
|
||||
return (codepoint + diff);
|
||||
}
|
||||
} else {
|
||||
*type = BracketTypeNone;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
17
lib/sheenbidi/Source/PairingLookup.h
Normal file
17
lib/sheenbidi/Source/PairingLookup.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Automatically generated by SheenBidiGenerator tool.
|
||||
* DO NOT EDIT!!
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_PAIRING_LOOKUP_H
|
||||
#define _SB_INTERNAL_PAIRING_LOOKUP_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
|
||||
#include "BracketType.h"
|
||||
#include "SBBase.h"
|
||||
|
||||
SB_INTERNAL SBCodepoint LookupMirror(SBCodepoint codepoint);
|
||||
SB_INTERNAL SBCodepoint LookupBracketPair(SBCodepoint codepoint, BracketType *bracketType);
|
||||
|
||||
#endif
|
50
lib/sheenbidi/Source/RunExtrema.h
Normal file
50
lib/sheenbidi/Source/RunExtrema.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_RUN_EXTREMA_H
|
||||
#define _SB_INTERNAL_RUN_EXTREMA_H
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
enum {
|
||||
RunExtremaLeadingL = SBBidiTypeL << 0,
|
||||
RunExtremaLeadingR = SBBidiTypeR << 0,
|
||||
|
||||
RunExtremaTrailingL = SBBidiTypeL << 4,
|
||||
RunExtremaTrailingR = SBBidiTypeR << 4
|
||||
};
|
||||
typedef SBUInt8 RunExtrema;
|
||||
|
||||
#define RunExtremaMake(sor, eor) \
|
||||
(RunExtrema) \
|
||||
( \
|
||||
((sor) << 0) \
|
||||
| ((eor) << 4) \
|
||||
)
|
||||
|
||||
#define RunExtrema_SOR(e) \
|
||||
(RunExtrema) \
|
||||
( \
|
||||
(e) & 0xF \
|
||||
)
|
||||
|
||||
#define RunExtrema_EOR(e) \
|
||||
(RunExtrema) \
|
||||
( \
|
||||
(e) >> 4 \
|
||||
)
|
||||
|
||||
#endif
|
81
lib/sheenbidi/Source/RunKind.h
Normal file
81
lib/sheenbidi/Source/RunKind.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_RUN_KIND_H
|
||||
#define _SB_INTERNAL_RUN_KIND_H
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
enum {
|
||||
RunKindSimple = 0x00,
|
||||
|
||||
RunKindIsolate = 0x01,
|
||||
RunKindPartial = 0x02,
|
||||
RunKindPartialIsolate = RunKindIsolate | RunKindPartial,
|
||||
|
||||
RunKindTerminating = 0x04,
|
||||
RunKindAttached = 0x08
|
||||
};
|
||||
typedef SBUInt8 RunKind;
|
||||
|
||||
#define RunKindMake(i, t) \
|
||||
( \
|
||||
((i) ? RunKindPartialIsolate : 0) \
|
||||
| ((t) ? RunKindTerminating : 0) \
|
||||
)
|
||||
|
||||
#define RunKindMakeComplete(k) \
|
||||
( \
|
||||
(k) &= ~RunKindPartial \
|
||||
)
|
||||
|
||||
#define RunKindMakeAttached(k) \
|
||||
( \
|
||||
(k) |= RunKindAttached \
|
||||
)
|
||||
|
||||
#define RunKindIsSimple(k) \
|
||||
( \
|
||||
(k) == RunKindSimple \
|
||||
)
|
||||
|
||||
#define RunKindIsIsolate(k) \
|
||||
( \
|
||||
(k) & RunKindIsolate \
|
||||
)
|
||||
|
||||
#define RunKindIsTerminating(k) \
|
||||
( \
|
||||
(k) & RunKindTerminating \
|
||||
)
|
||||
|
||||
#define RunKindIsPartialIsolate(k) \
|
||||
( \
|
||||
(k) & RunKindPartial \
|
||||
)
|
||||
|
||||
#define RunKindIsCompleteIsolate(k) \
|
||||
( \
|
||||
((k) & RunKindPartialIsolate) \
|
||||
== RunKindIsolate \
|
||||
)
|
||||
|
||||
#define RunKindIsAttachedTerminating(k) \
|
||||
( \
|
||||
(k) & RunKindAttached \
|
||||
)
|
||||
|
||||
#endif
|
148
lib/sheenbidi/Source/RunQueue.c
Normal file
148
lib/sheenbidi/Source/RunQueue.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "LevelRun.h"
|
||||
#include "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "RunQueue.h"
|
||||
|
||||
static void FindPreviousPartialRun(RunQueueRef queue)
|
||||
{
|
||||
RunQueueListRef list = queue->_partialList;
|
||||
SBInteger top = queue->_partialTop;
|
||||
|
||||
do {
|
||||
SBInteger limit = (list == queue->_frontList ? queue->_frontTop : 0);
|
||||
|
||||
do {
|
||||
LevelRunRef levelRun = &list->elements[top];
|
||||
if (RunKindIsPartialIsolate(levelRun->kind)) {
|
||||
queue->_partialList = list;
|
||||
queue->_partialTop = top;
|
||||
return;
|
||||
}
|
||||
} while (top-- > limit);
|
||||
|
||||
list = list->previous;
|
||||
top = RunQueueList_MaxIndex;
|
||||
} while (list);
|
||||
|
||||
queue->_partialList = NULL;
|
||||
queue->_partialTop = -1;
|
||||
queue->shouldDequeue = SBFalse;
|
||||
}
|
||||
|
||||
SB_INTERNAL void RunQueueInitialize(RunQueueRef queue)
|
||||
{
|
||||
/* Initialize first list. */
|
||||
queue->_firstList.previous = NULL;
|
||||
queue->_firstList.next = NULL;
|
||||
|
||||
/* Initialize front and rear lists with first list. */
|
||||
queue->_frontList = &queue->_firstList;
|
||||
queue->_rearList = &queue->_firstList;
|
||||
queue->_partialList = NULL;
|
||||
|
||||
/* Initialize list indexes. */
|
||||
queue->_frontTop = 0;
|
||||
queue->_rearTop = -1;
|
||||
queue->_partialTop = -1;
|
||||
|
||||
/* Initialize rest of the elements. */
|
||||
queue->count = 0;
|
||||
queue->peek = &queue->_frontList->elements[queue->_frontTop];
|
||||
queue->shouldDequeue = SBFalse;
|
||||
}
|
||||
|
||||
SB_INTERNAL void RunQueueEnqueue(RunQueueRef queue, const LevelRunRef levelRun)
|
||||
{
|
||||
LevelRunRef element;
|
||||
|
||||
if (queue->_rearTop != RunQueueList_MaxIndex) {
|
||||
element = &queue->_rearList->elements[++queue->_rearTop];
|
||||
} else {
|
||||
RunQueueListRef previousList = queue->_rearList;
|
||||
RunQueueListRef rearList = previousList->next;
|
||||
|
||||
if (!rearList) {
|
||||
rearList = malloc(sizeof(RunQueueList));
|
||||
rearList->previous = previousList;
|
||||
rearList->next = NULL;
|
||||
|
||||
previousList->next = rearList;
|
||||
}
|
||||
|
||||
queue->_rearList = rearList;
|
||||
queue->_rearTop = 0;
|
||||
|
||||
element = &rearList->elements[0];
|
||||
}
|
||||
queue->count += 1;
|
||||
|
||||
/* Copy the level run into current element. */
|
||||
*element = *levelRun;
|
||||
|
||||
/* Complete the latest isolating run with this terminating run */
|
||||
if (queue->_partialTop != -1 && RunKindIsTerminating(element->kind)) {
|
||||
LevelRunRef incompleteRun = &queue->_partialList->elements[queue->_partialTop];
|
||||
LevelRunAttach(incompleteRun, element);
|
||||
FindPreviousPartialRun(queue);
|
||||
}
|
||||
|
||||
/* Save the location of the isolating run */
|
||||
if (RunKindIsIsolate(element->kind)) {
|
||||
queue->_partialList = queue->_rearList;
|
||||
queue->_partialTop = queue->_rearTop;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void RunQueueDequeue(RunQueueRef queue)
|
||||
{
|
||||
/* The queue should not be empty. */
|
||||
SBAssert(queue->count != 0);
|
||||
|
||||
if (queue->_frontTop != RunQueueList_MaxIndex) {
|
||||
queue->_frontTop += 1;
|
||||
} else {
|
||||
RunQueueListRef frontList = queue->_frontList;
|
||||
|
||||
if (frontList == queue->_rearList) {
|
||||
queue->_rearTop = -1;
|
||||
} else {
|
||||
queue->_frontList = frontList->next;
|
||||
}
|
||||
|
||||
queue->_frontTop = 0;
|
||||
}
|
||||
|
||||
queue->count -= 1;
|
||||
queue->peek = &queue->_frontList->elements[queue->_frontTop];
|
||||
}
|
||||
|
||||
SB_INTERNAL void RunQueueFinalize(RunQueueRef queue)
|
||||
{
|
||||
RunQueueListRef list = queue->_firstList.next;
|
||||
|
||||
while (list) {
|
||||
RunQueueListRef next = list->next;
|
||||
free(list);
|
||||
list = next;
|
||||
};
|
||||
}
|
55
lib/sheenbidi/Source/RunQueue.h
Normal file
55
lib/sheenbidi/Source/RunQueue.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_RUN_QUEUE_H
|
||||
#define _SB_INTERNAL_RUN_QUEUE_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
|
||||
#include "LevelRun.h"
|
||||
#include "SBBase.h"
|
||||
|
||||
#define RunQueueList_Length 8
|
||||
#define RunQueueList_MaxIndex (RunQueueList_Length - 1)
|
||||
|
||||
typedef struct _RunQueueList {
|
||||
LevelRun elements[RunQueueList_Length];
|
||||
|
||||
struct _RunQueueList *previous; /**< Reference to the previous list of queue elements */
|
||||
struct _RunQueueList *next; /**< Reference to the next list of queue elements */
|
||||
} RunQueueList, *RunQueueListRef;
|
||||
|
||||
typedef struct _RunQueue {
|
||||
RunQueueList _firstList; /**< First list of elements, which is part of the queue */
|
||||
RunQueueListRef _frontList; /**< The list containing front element of the queue */
|
||||
RunQueueListRef _rearList; /**< The list containing rear element of the queue */
|
||||
RunQueueListRef _partialList; /**< The list containing latest partial isolating run */
|
||||
SBInteger _frontTop; /**< Index of front element in front list */
|
||||
SBInteger _rearTop; /**< Index of rear element in rear list */
|
||||
SBInteger _partialTop; /**< Index of partial run in partial list */
|
||||
LevelRunRef peek; /**< Peek element of the queue */
|
||||
SBUInteger count; /**< Number of elements the queue contains */
|
||||
SBBoolean shouldDequeue;
|
||||
} RunQueue, *RunQueueRef;
|
||||
|
||||
SB_INTERNAL void RunQueueInitialize(RunQueueRef queue);
|
||||
|
||||
SB_INTERNAL void RunQueueEnqueue(RunQueueRef queue, const LevelRunRef levelRun);
|
||||
SB_INTERNAL void RunQueueDequeue(RunQueueRef queue);
|
||||
|
||||
SB_INTERNAL void RunQueueFinalize(RunQueueRef queue);
|
||||
|
||||
#endif
|
177
lib/sheenbidi/Source/SBAlgorithm.c
Normal file
177
lib/sheenbidi/Source/SBAlgorithm.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "BidiTypeLookup.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "SBLog.h"
|
||||
#include "SBParagraph.h"
|
||||
#include "SBAlgorithm.h"
|
||||
|
||||
static SBAlgorithmRef AlgorithmAllocate(SBUInteger stringLength)
|
||||
{
|
||||
const SBUInteger sizeAlgorithm = sizeof(SBAlgorithm);
|
||||
const SBUInteger sizeTypes = sizeof(SBBidiType) * stringLength;
|
||||
|
||||
const SBUInteger sizeMemory = sizeAlgorithm
|
||||
+ sizeTypes;
|
||||
|
||||
SBUInt8 *memory = (SBUInt8 *)malloc(sizeMemory);
|
||||
|
||||
SBUInteger offset = 0;
|
||||
SBAlgorithmRef algorithm = (SBAlgorithmRef)(memory + offset);
|
||||
|
||||
offset += sizeAlgorithm;
|
||||
algorithm->fixedTypes = (SBBidiType *)(memory + offset);
|
||||
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
static void DetermineBidiTypes(const SBCodepointSequence *sequence, SBBidiType *types)
|
||||
{
|
||||
SBUInteger stringIndex = 0;
|
||||
SBUInteger firstIndex = 0;
|
||||
SBCodepoint codepoint;
|
||||
|
||||
while ((codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex)) != SBCodepointInvalid) {
|
||||
types[firstIndex] = LookupBidiType(codepoint);
|
||||
|
||||
/* Subsequent code units get 'BN' type. */
|
||||
while (++firstIndex < stringIndex) {
|
||||
types[firstIndex] = SBBidiTypeBN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SBAlgorithmRef SBAlgorithmCreate(const SBCodepointSequence *codepointSequence)
|
||||
{
|
||||
if (SBCodepointSequenceIsValid(codepointSequence)) {
|
||||
SBUInteger stringLength = codepointSequence->stringLength;
|
||||
SBAlgorithmRef algorithm;
|
||||
|
||||
SB_LOG_BLOCK_OPENER("Algorithm Input");
|
||||
SB_LOG_STATEMENT("Codepoints", 1, SB_LOG_CODEPOINT_SEQUENCE(codepointSequence));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
algorithm = AlgorithmAllocate(stringLength);
|
||||
algorithm->codepointSequence = *codepointSequence;
|
||||
algorithm->retainCount = 1;
|
||||
|
||||
DetermineBidiTypes(codepointSequence, algorithm->fixedTypes);
|
||||
|
||||
SB_LOG_BLOCK_OPENER("Determined Types");
|
||||
SB_LOG_STATEMENT("Types", 1, SB_LOG_BIDI_TYPES_ARRAY(algorithm->fixedTypes, stringLength));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
SB_LOG_BREAKER();
|
||||
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const SBBidiType *SBAlgorithmGetBidiTypesPtr(SBAlgorithmRef algorithm)
|
||||
{
|
||||
return algorithm->fixedTypes;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBUInteger SBAlgorithmGetSeparatorLength(SBAlgorithmRef algorithm, SBUInteger separatorIndex)
|
||||
{
|
||||
const SBCodepointSequence *codepointSequence = &algorithm->codepointSequence;
|
||||
SBUInteger stringIndex = separatorIndex;
|
||||
SBCodepoint codepoint;
|
||||
SBUInteger separatorLength;
|
||||
|
||||
codepoint = SBCodepointSequenceGetCodepointAt(codepointSequence, &stringIndex);
|
||||
separatorLength = stringIndex - separatorIndex;
|
||||
|
||||
if (codepoint == '\r') {
|
||||
/* Don't break in between 'CR' and 'LF'. */
|
||||
if (stringIndex < codepointSequence->stringLength) {
|
||||
codepoint = SBCodepointSequenceGetCodepointAt(codepointSequence, &stringIndex);
|
||||
|
||||
if (codepoint == '\n') {
|
||||
separatorLength = stringIndex - separatorIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return separatorLength;
|
||||
}
|
||||
|
||||
void SBAlgorithmGetParagraphBoundary(SBAlgorithmRef algorithm,
|
||||
SBUInteger paragraphOffset, SBUInteger suggestedLength,
|
||||
SBUInteger *acutalLength, SBUInteger *separatorLength)
|
||||
{
|
||||
const SBCodepointSequence *codepointSequence = &algorithm->codepointSequence;
|
||||
SBBidiType *bidiTypes = algorithm->fixedTypes;
|
||||
SBUInteger limitIndex;
|
||||
SBUInteger startIndex;
|
||||
|
||||
SBUIntegerNormalizeRange(codepointSequence->stringLength, ¶graphOffset, &suggestedLength);
|
||||
limitIndex = paragraphOffset + suggestedLength;
|
||||
|
||||
for (startIndex = paragraphOffset; startIndex < limitIndex; startIndex++) {
|
||||
SBBidiType currentType = bidiTypes[startIndex];
|
||||
|
||||
if (currentType == SBBidiTypeB) {
|
||||
if (separatorLength) {
|
||||
*separatorLength = SBAlgorithmGetSeparatorLength(algorithm, startIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (acutalLength) {
|
||||
*acutalLength = startIndex - paragraphOffset;
|
||||
}
|
||||
}
|
||||
|
||||
SBParagraphRef SBAlgorithmCreateParagraph(SBAlgorithmRef algorithm,
|
||||
SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel)
|
||||
{
|
||||
const SBCodepointSequence *codepointSequence = &algorithm->codepointSequence;
|
||||
SBUInteger stringLength = codepointSequence->stringLength;
|
||||
|
||||
SBUIntegerNormalizeRange(stringLength, ¶graphOffset, &suggestedLength);
|
||||
|
||||
if (suggestedLength > 0) {
|
||||
return SBParagraphCreate(algorithm, paragraphOffset, suggestedLength, baseLevel);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SBAlgorithmRef SBAlgorithmRetain(SBAlgorithmRef algorithm)
|
||||
{
|
||||
if (algorithm) {
|
||||
algorithm->retainCount += 1;
|
||||
}
|
||||
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
void SBAlgorithmRelease(SBAlgorithmRef algorithm)
|
||||
{
|
||||
if (algorithm && --algorithm->retainCount == 0) {
|
||||
free(algorithm);
|
||||
}
|
||||
}
|
34
lib/sheenbidi/Source/SBAlgorithm.h
Normal file
34
lib/sheenbidi/Source/SBAlgorithm.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_ALGORITHM_H
|
||||
#define _SB_INTERNAL_ALGORITHM_H
|
||||
|
||||
#include <SBAlgorithm.h>
|
||||
#include <SBBase.h>
|
||||
#include <SBBidiType.h>
|
||||
#include <SBCodepointSequence.h>
|
||||
#include <SBConfig.h>
|
||||
|
||||
typedef struct _SBAlgorithm {
|
||||
SBCodepointSequence codepointSequence;
|
||||
SBBidiType *fixedTypes;
|
||||
SBUInteger retainCount;
|
||||
} SBAlgorithm;
|
||||
|
||||
SB_INTERNAL SBUInteger SBAlgorithmGetSeparatorLength(SBAlgorithmRef algorithm, SBUInteger separatorIndex);
|
||||
|
||||
#endif
|
24
lib/sheenbidi/Source/SBAssert.h
Normal file
24
lib/sheenbidi/Source/SBAssert.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_ASSERT_H
|
||||
#define _SB_INTERNAL_ASSERT_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define SBAssert(exp) assert(exp)
|
||||
|
||||
#endif
|
420
lib/sheenbidi/Source/SBBase.c
Normal file
420
lib/sheenbidi/Source/SBBase.c
Normal file
@ -0,0 +1,420 @@
|
||||
/*
|
||||
* 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');
|
||||
}
|
||||
}
|
108
lib/sheenbidi/Source/SBBase.h
Normal file
108
lib/sheenbidi/Source/SBBase.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_BASE_H
|
||||
#define _SB_INTERNAL_BASE_H
|
||||
|
||||
#include <SBBase.h>
|
||||
#include <SBBidiType.h>
|
||||
#include <SBCodepoint.h>
|
||||
#include <SBConfig.h>
|
||||
#include <SBGeneralCategory.h>
|
||||
#include <SBScript.h>
|
||||
|
||||
/**
|
||||
* A value that indicates an invalid unsigned index.
|
||||
*/
|
||||
#define SBInvalidIndex (SBUInteger)(-1)
|
||||
|
||||
SB_INTERNAL void SBUIntegerNormalizeRange(SBUInteger actualLength,
|
||||
SBUInteger *rangeOffset, SBUInteger *rangeLength);
|
||||
|
||||
SB_INTERNAL SBBoolean SBUIntegerVerifyRange(SBUInteger actualLength,
|
||||
SBUInteger rangeOffset, SBUInteger rangeLength);
|
||||
|
||||
|
||||
#define SBNumberGetMax(first, second) \
|
||||
( \
|
||||
(first) > (second) \
|
||||
? (first) \
|
||||
: (second) \
|
||||
)
|
||||
|
||||
#define SBNumberLimitIncrement(number, limit) \
|
||||
( \
|
||||
(number) < (limit) \
|
||||
? (number) + (1) \
|
||||
: (limit) \
|
||||
)
|
||||
|
||||
#define SBNumberLimitDecrement(number, limit) \
|
||||
( \
|
||||
(number) > (limit) \
|
||||
? (number) - (1) \
|
||||
: (limit) \
|
||||
)
|
||||
|
||||
#define SBNumberRingAdd(number, count, capacity) \
|
||||
(((number) + (count)) % (capacity))
|
||||
|
||||
#define SBNumberRingIncrement(number, capacity) \
|
||||
SBNumberRingAdd(number, 1, capacity)
|
||||
|
||||
#define SBNumberRingSubtract(number, count, capacity) \
|
||||
(((number) + (capacity) - (count)) % (capacity))
|
||||
|
||||
#define SBNumberRingDecrement(number, capacity) \
|
||||
SBNumberRingSubtract(number, 1, capacity)
|
||||
|
||||
|
||||
#define SBLevelAsNormalBidiType(level) \
|
||||
( \
|
||||
((level) & 1) \
|
||||
? SBBidiTypeR \
|
||||
: SBBidiTypeL \
|
||||
)
|
||||
|
||||
#define SBLevelAsOppositeBidiType(level) \
|
||||
( \
|
||||
((level) & 1) \
|
||||
? SBBidiTypeL \
|
||||
: SBBidiTypeR \
|
||||
)
|
||||
|
||||
|
||||
#define SBBidiTypeIsEqual(t1, t2) ((t1) == (t2))
|
||||
|
||||
#define SBBidiTypeIsNumber(t) SBUInt8InRange(t, SBBidiTypeAN, SBBidiTypeEN)
|
||||
#define SBBidiTypeIsIsolate(t) SBUInt8InRange(t, SBBidiTypeLRI, SBBidiTypePDI)
|
||||
|
||||
#define SBBidiTypeIsStrongOrNumber(t) (SBBidiTypeIsStrong(t) || SBBidiTypeIsNumber(t))
|
||||
#define SBBidiTypeIsNumberSeparator(t) SBUInt8InRange(t, SBBidiTypeES, SBBidiTypeCS)
|
||||
#define SBBidiTypeIsIsolateInitiator(t) SBUInt8InRange(t, SBBidiTypeLRI, SBBidiTypeFSI)
|
||||
#define SBBidiTypeIsIsolateTerminator(t) SBBidiTypeIsEqual(t, SBBidiTypePDI)
|
||||
#define SBBidiTypeIsNeutralOrIsolate(t) SBUInt8InRange(t, SBBidiTypeWS, SBBidiTypePDI)
|
||||
|
||||
|
||||
#define SBCodepointMax 0x10FFFF
|
||||
#define SBCodepointInRange(v, s, e) SBUInt32InRange(v, s, e)
|
||||
#define SBCodepointIsSurrogate(c) SBCodepointInRange(c, 0xD800, 0xDFFF)
|
||||
#define SBCodepointIsValid(c) (!SBCodepointIsSurrogate(c) && (c) <= SBCodepointMax)
|
||||
|
||||
|
||||
#define SBScriptIsCommonOrInherited(s) ((s) <= SBScriptZYYY)
|
||||
|
||||
#endif
|
303
lib/sheenbidi/Source/SBCodepointSequence.c
Normal file
303
lib/sheenbidi/Source/SBCodepointSequence.c
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
|
||||
typedef struct {
|
||||
SBUInt8 valid;
|
||||
SBUInt8 total;
|
||||
SBUInt8 start;
|
||||
SBUInt8 end;
|
||||
} UTF8State;
|
||||
|
||||
static const UTF8State UTF8StateTable[9] = {
|
||||
{1,0,0x00,0x00}, {0,0,0x00,0x00}, {1,2,0x80,0xBF}, {1,3,0xA0,0xBF}, {1,3,0x80,0xBF},
|
||||
{1,3,0x80,0x9F}, {1,4,0x90,0xBF}, {1,4,0x80,0xBF}, {1,4,0x80,0x8F}
|
||||
};
|
||||
|
||||
static const SBUInt8 UTF8LookupTable[256] = {
|
||||
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, 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, 0, 0, 0, 0, 0, 0,
|
||||
/* LEAD: -- 80..BF -- */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1,
|
||||
/* LEAD: -- C0..C1 -- */
|
||||
1, 1,
|
||||
/* LEAD: -- C2..DF -- */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* LEAD: -- E0..E0 -- */
|
||||
3,
|
||||
/* LEAD: -- E1..EC -- */
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
/* LEAD: -- ED..ED -- */
|
||||
5,
|
||||
/* LEAD: -- EE..EF -- */
|
||||
4, 4,
|
||||
/* LEAD: -- F0..F0 -- */
|
||||
6,
|
||||
/* LEAD: -- F1..F3 -- */
|
||||
7, 7, 7,
|
||||
/* LEAD: -- F4..F4 -- */
|
||||
8,
|
||||
/* LEAD: -- F5..F7 -- */
|
||||
1, 1, 1,
|
||||
/* LEAD: -- F8..FB -- */
|
||||
1, 1, 1, 1,
|
||||
/* LEAD: -- FC..FD -- */
|
||||
1, 1,
|
||||
/* LEAD: -- FE..FF -- */
|
||||
1, 1
|
||||
};
|
||||
|
||||
static SBCodepoint GetUTF8CodepointAt(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);
|
||||
static SBCodepoint GetUTF8CodepointBefore(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);
|
||||
static SBCodepoint GetUTF16CodepointAt(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);
|
||||
static SBCodepoint GetUTF16CodepointBefore(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);
|
||||
static SBCodepoint GetUTF32CodepointAt(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);
|
||||
static SBCodepoint GetUTF32CodepointBefore(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);
|
||||
|
||||
SB_INTERNAL SBBoolean SBCodepointSequenceIsValid(const SBCodepointSequence *codepointSequence)
|
||||
{
|
||||
if (codepointSequence) {
|
||||
SBBoolean encodingValid = SBFalse;
|
||||
|
||||
switch (codepointSequence->stringEncoding) {
|
||||
case SBStringEncodingUTF8:
|
||||
case SBStringEncodingUTF16:
|
||||
case SBStringEncodingUTF32:
|
||||
encodingValid = SBTrue;
|
||||
break;
|
||||
}
|
||||
|
||||
return (encodingValid && codepointSequence->stringBuffer && codepointSequence->stringLength > 0);
|
||||
}
|
||||
|
||||
return SBFalse;
|
||||
}
|
||||
|
||||
SBCodepoint SBCodepointSequenceGetCodepointBefore(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex)
|
||||
{
|
||||
SBCodepoint codepoint = SBCodepointInvalid;
|
||||
|
||||
if ((*stringIndex - 1) < codepointSequence->stringLength) {
|
||||
switch (codepointSequence->stringEncoding) {
|
||||
case SBStringEncodingUTF8:
|
||||
codepoint = GetUTF8CodepointBefore(codepointSequence, stringIndex);
|
||||
break;
|
||||
|
||||
case SBStringEncodingUTF16:
|
||||
codepoint = GetUTF16CodepointBefore(codepointSequence, stringIndex);
|
||||
break;
|
||||
|
||||
case SBStringEncodingUTF32:
|
||||
codepoint = GetUTF32CodepointBefore(codepointSequence, stringIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
SBCodepoint SBCodepointSequenceGetCodepointAt(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex)
|
||||
{
|
||||
SBCodepoint codepoint = SBCodepointInvalid;
|
||||
|
||||
if (*stringIndex < codepointSequence->stringLength) {
|
||||
switch (codepointSequence->stringEncoding) {
|
||||
case SBStringEncodingUTF8:
|
||||
codepoint = GetUTF8CodepointAt(codepointSequence, stringIndex);
|
||||
break;
|
||||
|
||||
case SBStringEncodingUTF16:
|
||||
codepoint = GetUTF16CodepointAt(codepointSequence, stringIndex);
|
||||
break;
|
||||
|
||||
case SBStringEncodingUTF32:
|
||||
codepoint = GetUTF32CodepointAt(codepointSequence, stringIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
static SBCodepoint GetUTF8CodepointAt(const SBCodepointSequence *sequence, SBUInteger *index)
|
||||
{
|
||||
const SBUInt8 *buffer = sequence->stringBuffer;
|
||||
SBUInteger length = sequence->stringLength;
|
||||
SBUInt8 lead;
|
||||
UTF8State state;
|
||||
SBUInteger limit;
|
||||
SBCodepoint codepoint;
|
||||
|
||||
lead = buffer[*index];
|
||||
state = UTF8StateTable[UTF8LookupTable[lead]];
|
||||
limit = *index + state.total;
|
||||
|
||||
if (limit > length) {
|
||||
limit = length;
|
||||
state.valid = SBFalse;
|
||||
}
|
||||
|
||||
codepoint = lead & (0x7F >> state.total);
|
||||
|
||||
while (++(*index) < limit) {
|
||||
SBUInt8 byte = buffer[*index];
|
||||
|
||||
if (byte >= state.start && byte <= state.end) {
|
||||
codepoint = (codepoint << 6) | (byte & 0x3F);
|
||||
} else {
|
||||
state.valid = SBFalse;
|
||||
break;
|
||||
}
|
||||
|
||||
state.start = 0x80;
|
||||
state.end = 0xBF;
|
||||
}
|
||||
|
||||
if (state.valid) {
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
return SBCodepointFaulty;
|
||||
}
|
||||
|
||||
static SBCodepoint GetUTF8CodepointBefore(const SBCodepointSequence *sequence, SBUInteger *index)
|
||||
{
|
||||
const SBUInt8 *buffer = sequence->stringBuffer;
|
||||
SBUInteger startIndex = *index;
|
||||
SBUInteger limitIndex;
|
||||
SBUInteger continuation;
|
||||
SBCodepoint codepoint;
|
||||
|
||||
continuation = 7;
|
||||
|
||||
while (--continuation && --startIndex) {
|
||||
SBUInt8 codeunit = buffer[startIndex];
|
||||
|
||||
if ((codeunit & 0xC0) != 0x80) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
limitIndex = startIndex;
|
||||
codepoint = GetUTF8CodepointAt(sequence, &limitIndex);
|
||||
|
||||
if (limitIndex == *index) {
|
||||
*index = startIndex;
|
||||
} else {
|
||||
codepoint = SBCodepointFaulty;
|
||||
*index -= 1;
|
||||
}
|
||||
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
static SBCodepoint GetUTF16CodepointAt(const SBCodepointSequence *sequence, SBUInteger *index)
|
||||
{
|
||||
const SBUInt16 *buffer = sequence->stringBuffer;
|
||||
SBUInteger length = sequence->stringLength;
|
||||
SBCodepoint codepoint;
|
||||
SBUInt16 lead;
|
||||
|
||||
codepoint = SBCodepointFaulty;
|
||||
|
||||
lead = buffer[*index];
|
||||
*index += 1;
|
||||
|
||||
if (!SBCodepointIsSurrogate(lead)) {
|
||||
codepoint = lead;
|
||||
} else if (lead <= 0xDBFF) {
|
||||
if (*index < length) {
|
||||
SBUInt16 trail = buffer[*index];
|
||||
|
||||
if (SBUInt16InRange(trail, 0xDC00, 0xDFFF)) {
|
||||
codepoint = (lead << 10) + trail - ((0xD800 << 10) + 0xDC00 - 0x10000);
|
||||
*index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
static SBCodepoint GetUTF16CodepointBefore(const SBCodepointSequence *sequence, SBUInteger *index)
|
||||
{
|
||||
const SBUInt16 *buffer = sequence->stringBuffer;
|
||||
SBCodepoint codepoint;
|
||||
SBUInt16 trail;
|
||||
|
||||
codepoint = SBCodepointFaulty;
|
||||
|
||||
*index -= 1;
|
||||
trail = buffer[*index];
|
||||
|
||||
if (!SBCodepointIsSurrogate(trail)) {
|
||||
codepoint = trail;
|
||||
} else if (trail >= 0xDC00) {
|
||||
if (*index > 0) {
|
||||
SBUInt16 lead = buffer[*index - 1];
|
||||
|
||||
if (SBUInt16InRange(lead, 0xD800, 0xDBFF)) {
|
||||
codepoint = (lead << 10) + trail - ((0xD800 << 10) + 0xDC00 - 0x10000);
|
||||
*index -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
static SBCodepoint GetUTF32CodepointAt(const SBCodepointSequence *sequence, SBUInteger *index)
|
||||
{
|
||||
const SBUInt32 *buffer = sequence->stringBuffer;
|
||||
SBCodepoint codepoint;
|
||||
|
||||
codepoint = buffer[*index];
|
||||
*index += 1;
|
||||
|
||||
if (SBCodepointIsValid(codepoint)) {
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
return SBCodepointFaulty;
|
||||
}
|
||||
|
||||
static SBCodepoint GetUTF32CodepointBefore(const SBCodepointSequence *sequence, SBUInteger *index)
|
||||
{
|
||||
const SBUInt32 *buffer = sequence->stringBuffer;
|
||||
SBCodepoint codepoint;
|
||||
|
||||
*index -= 1;
|
||||
codepoint = buffer[*index];
|
||||
|
||||
if (SBCodepointIsValid(codepoint)) {
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
return SBCodepointFaulty;
|
||||
}
|
25
lib/sheenbidi/Source/SBCodepointSequence.h
Normal file
25
lib/sheenbidi/Source/SBCodepointSequence.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_CODEPOINT_SEQUENCE_H
|
||||
#define _SB_INTERNAL_CODEPOINT_SEQUENCE_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
#include <SBCodepointSequence.h>
|
||||
|
||||
SB_INTERNAL SBBoolean SBCodepointSequenceIsValid(const SBCodepointSequence *codepointSequence);
|
||||
|
||||
#endif
|
300
lib/sheenbidi/Source/SBLine.c
Normal file
300
lib/sheenbidi/Source/SBLine.c
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "PairingLookup.h"
|
||||
#include "SBAlgorithm.h"
|
||||
#include "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "SBParagraph.h"
|
||||
#include "SBRun.h"
|
||||
#include "SBLine.h"
|
||||
|
||||
typedef struct _LineContext {
|
||||
const SBBidiType *refTypes;
|
||||
SBLevel *fixedLevels;
|
||||
SBUInteger runCount;
|
||||
SBLevel maxLevel;
|
||||
} LineContext, *LineContextRef;
|
||||
|
||||
static SBLevel CopyLevels(SBLevel *destination,
|
||||
const SBLevel *source, SBUInteger length, SBUInteger *runCount)
|
||||
{
|
||||
SBLevel lastLevel = SBLevelInvalid;
|
||||
SBLevel maxLevel = 0;
|
||||
SBUInteger totalRuns = 0;
|
||||
|
||||
while (length--) {
|
||||
SBLevel level = *(source++);
|
||||
*(destination++) = level;
|
||||
|
||||
if (level != lastLevel) {
|
||||
totalRuns += 1;
|
||||
|
||||
if (level > maxLevel) {
|
||||
maxLevel = level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*runCount = totalRuns;
|
||||
|
||||
return maxLevel;
|
||||
}
|
||||
|
||||
static LineContextRef CreateLineContext(const SBBidiType *types, const SBLevel *levels, SBUInteger length)
|
||||
{
|
||||
const SBUInteger sizeContext = sizeof(LineContext);
|
||||
const SBUInteger sizeLevels = sizeof(SBLevel) * length;
|
||||
const SBUInteger sizeMemory = sizeContext + sizeLevels;
|
||||
|
||||
const SBUInteger offsetContext = 0;
|
||||
const SBUInteger offsetLevels = offsetContext + sizeContext;
|
||||
|
||||
SBUInt8 *memory = (SBUInt8 *)malloc(sizeMemory);
|
||||
LineContextRef context = (LineContextRef)(memory + offsetContext);
|
||||
SBLevel *fixedLevels = (SBLevel *)(memory + offsetLevels);
|
||||
|
||||
context->refTypes = types;
|
||||
context->fixedLevels = fixedLevels;
|
||||
context->maxLevel = CopyLevels(fixedLevels, levels, length, &context->runCount);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static void DisposeLineContext(LineContextRef context)
|
||||
{
|
||||
free(context);
|
||||
}
|
||||
|
||||
static SBLineRef AllocateLine(SBUInteger runCount)
|
||||
{
|
||||
const SBUInteger sizeLine = sizeof(SBLine);
|
||||
const SBUInteger sizeRuns = sizeof(SBRun) * runCount;
|
||||
const SBUInteger sizeMemory = sizeLine + sizeRuns;
|
||||
|
||||
const SBUInteger offsetLine = 0;
|
||||
const SBUInteger offsetRuns = offsetLine + sizeLine;
|
||||
|
||||
SBUInt8 *memory = (SBUInt8 *)malloc(sizeMemory);
|
||||
SBLineRef line = (SBLineRef)(memory + offsetLine);
|
||||
SBRun *runs = (SBRun *)(memory + offsetRuns);
|
||||
|
||||
line->fixedRuns = runs;
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
static void SetNewLevel(SBLevel *levels, SBUInteger length, SBLevel newLevel)
|
||||
{
|
||||
SBUInteger index = length;
|
||||
|
||||
while (index--) {
|
||||
levels[index] = newLevel;
|
||||
}
|
||||
}
|
||||
|
||||
static void ResetLevels(LineContextRef context, SBLevel baseLevel, SBUInteger charCount)
|
||||
{
|
||||
const SBBidiType *types = context->refTypes;
|
||||
SBLevel *levels = context->fixedLevels;
|
||||
SBUInteger index;
|
||||
SBUInteger length;
|
||||
SBBoolean reset;
|
||||
|
||||
index = charCount;
|
||||
length = 0;
|
||||
reset = SBTrue;
|
||||
|
||||
while (index--) {
|
||||
SBBidiType type = types[index];
|
||||
|
||||
switch (type) {
|
||||
case SBBidiTypeB:
|
||||
case SBBidiTypeS:
|
||||
SetNewLevel(levels + index, length + 1, baseLevel);
|
||||
length = 0;
|
||||
reset = SBTrue;
|
||||
context->runCount += 1;
|
||||
break;
|
||||
|
||||
case SBBidiTypeLRE:
|
||||
case SBBidiTypeRLE:
|
||||
case SBBidiTypeLRO:
|
||||
case SBBidiTypeRLO:
|
||||
case SBBidiTypePDF:
|
||||
case SBBidiTypeBN:
|
||||
length += 1;
|
||||
break;
|
||||
|
||||
case SBBidiTypeWS:
|
||||
case SBBidiTypeLRI:
|
||||
case SBBidiTypeRLI:
|
||||
case SBBidiTypeFSI:
|
||||
case SBBidiTypePDI:
|
||||
if (reset) {
|
||||
SetNewLevel(levels + index, length + 1, baseLevel);
|
||||
length = 0;
|
||||
|
||||
context->runCount += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
length = 0;
|
||||
reset = SBFalse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SBUInteger InitializeRuns(SBRun *runs,
|
||||
const SBLevel *levels, SBUInteger length, SBUInteger lineOffset)
|
||||
{
|
||||
SBUInteger index;
|
||||
SBUInteger runCount = 1;
|
||||
|
||||
(*runs).offset = lineOffset;
|
||||
(*runs).level = levels[0];
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
SBLevel level = levels[index];
|
||||
|
||||
if (level != (*runs).level) {
|
||||
(*runs).length = index + lineOffset - (*runs).offset;
|
||||
|
||||
++runs;
|
||||
(*runs).offset = lineOffset + index;
|
||||
(*runs).level = level;
|
||||
|
||||
runCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
(*runs).length = index + lineOffset - (*runs).offset;
|
||||
|
||||
return runCount;
|
||||
}
|
||||
|
||||
static void ReverseRunSequence(SBRun *runs, SBUInteger runCount)
|
||||
{
|
||||
SBUInteger halfCount = runCount / 2;
|
||||
SBUInteger finalIndex = runCount - 1;
|
||||
SBUInteger index;
|
||||
|
||||
for (index = 0; index < halfCount; index++) {
|
||||
SBUInteger tieIndex;
|
||||
SBRun tempRun;
|
||||
|
||||
tieIndex = finalIndex - index;
|
||||
|
||||
tempRun = runs[index];
|
||||
runs[index] = runs[tieIndex];
|
||||
runs[tieIndex] = tempRun;
|
||||
}
|
||||
}
|
||||
|
||||
static void ReorderRuns(SBRun *runs, SBUInteger runCount, SBLevel maxLevel)
|
||||
{
|
||||
SBLevel newLevel;
|
||||
|
||||
for (newLevel = maxLevel; newLevel; newLevel--) {
|
||||
SBUInteger start = runCount;
|
||||
|
||||
while (start--) {
|
||||
if (runs[start].level >= newLevel) {
|
||||
SBUInteger count = 1;
|
||||
|
||||
for (; start && runs[start - 1].level >= newLevel; start--) {
|
||||
count += 1;
|
||||
}
|
||||
|
||||
ReverseRunSequence(runs + start, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL SBLineRef SBLineCreate(SBParagraphRef paragraph,
|
||||
SBUInteger lineOffset, SBUInteger lineLength)
|
||||
{
|
||||
SBUInteger innerOffset = lineOffset - paragraph->offset;
|
||||
const SBBidiType *refTypes = paragraph->refTypes + innerOffset;
|
||||
const SBLevel *refLevels = paragraph->fixedLevels + innerOffset;
|
||||
LineContextRef context;
|
||||
SBLineRef line;
|
||||
|
||||
/* Line range MUST be valid. */
|
||||
SBAssert(lineOffset < (lineOffset + lineLength)
|
||||
&& lineOffset >= paragraph->offset
|
||||
&& (lineOffset + lineLength) <= (paragraph->offset + paragraph->length));
|
||||
|
||||
context = CreateLineContext(refTypes, refLevels, lineLength);
|
||||
ResetLevels(context, paragraph->baseLevel, lineLength);
|
||||
|
||||
line = AllocateLine(context->runCount);
|
||||
line->runCount = InitializeRuns(line->fixedRuns, context->fixedLevels, lineLength, lineOffset);
|
||||
ReorderRuns(line->fixedRuns, line->runCount, context->maxLevel);
|
||||
|
||||
line->codepointSequence = paragraph->algorithm->codepointSequence;
|
||||
line->offset = lineOffset;
|
||||
line->length = lineLength;
|
||||
line->retainCount = 1;
|
||||
|
||||
DisposeLineContext(context);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
SBUInteger SBLineGetOffset(SBLineRef line)
|
||||
{
|
||||
return line->offset;
|
||||
}
|
||||
|
||||
SBUInteger SBLineGetLength(SBLineRef line)
|
||||
{
|
||||
return line->length;
|
||||
}
|
||||
|
||||
SBUInteger SBLineGetRunCount(SBLineRef line)
|
||||
{
|
||||
return line->runCount;
|
||||
}
|
||||
|
||||
const SBRun *SBLineGetRunsPtr(SBLineRef line)
|
||||
{
|
||||
return line->fixedRuns;
|
||||
}
|
||||
|
||||
SBLineRef SBLineRetain(SBLineRef line)
|
||||
{
|
||||
if (line) {
|
||||
line->retainCount += 1;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
void SBLineRelease(SBLineRef line)
|
||||
{
|
||||
if (line && --line->retainCount == 0) {
|
||||
free(line);
|
||||
}
|
||||
}
|
39
lib/sheenbidi/Source/SBLine.h
Normal file
39
lib/sheenbidi/Source/SBLine.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_LINE_H
|
||||
#define _SB_INTERNAL_LINE_H
|
||||
|
||||
#include <SBBase.h>
|
||||
#include <SBCodepointSequence.h>
|
||||
#include <SBConfig.h>
|
||||
#include <SBLine.h>
|
||||
#include <SBParagraph.h>
|
||||
#include <SBRun.h>
|
||||
|
||||
typedef struct _SBLine {
|
||||
SBCodepointSequence codepointSequence;
|
||||
SBRun *fixedRuns;
|
||||
SBUInteger runCount;
|
||||
SBUInteger offset;
|
||||
SBUInteger length;
|
||||
SBUInteger retainCount;
|
||||
} SBLine;
|
||||
|
||||
SB_INTERNAL SBLineRef SBLineCreate(SBParagraphRef paragraph,
|
||||
SBUInteger lineOffset, SBUInteger lineLength);
|
||||
|
||||
#endif
|
303
lib/sheenbidi/Source/SBLog.c
Normal file
303
lib/sheenbidi/Source/SBLog.c
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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>
|
||||
|
||||
#ifdef SB_CONFIG_LOG
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBBidiChain.h"
|
||||
#include "SBBidiType.h"
|
||||
#include "SBIsolatingRun.h"
|
||||
#include "SBLog.h"
|
||||
|
||||
int _SBLogPosition = 0;
|
||||
|
||||
SB_INTERNAL void PrintBaseLevel(SBLevel baseLevel)
|
||||
{
|
||||
switch (baseLevel) {
|
||||
case SBLevelDefaultLTR:
|
||||
SB_LOG_STRING("Auto-LTR");
|
||||
break;
|
||||
|
||||
case SBLevelDefaultRTL:
|
||||
SB_LOG_STRING("Auto-RTL");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
SB_LOG_STRING("LTR");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
SB_LOG_STRING("RTL");
|
||||
break;
|
||||
|
||||
default:
|
||||
SB_LOG(("Level - %d", baseLevel));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void PrintBidiType(SBBidiType type)
|
||||
{
|
||||
switch (type) {
|
||||
case SBBidiTypeNil:
|
||||
SB_LOG_STRING("Nil");
|
||||
break;
|
||||
|
||||
case SBBidiTypeL:
|
||||
SB_LOG_STRING("L");
|
||||
break;
|
||||
|
||||
case SBBidiTypeR:
|
||||
SB_LOG_STRING("R");
|
||||
break;
|
||||
|
||||
case SBBidiTypeAL:
|
||||
SB_LOG_STRING("AL");
|
||||
break;
|
||||
|
||||
case SBBidiTypeEN:
|
||||
SB_LOG_STRING("EN");
|
||||
break;
|
||||
|
||||
case SBBidiTypeES:
|
||||
SB_LOG_STRING("ES");
|
||||
break;
|
||||
|
||||
case SBBidiTypeET:
|
||||
SB_LOG_STRING("EN");
|
||||
break;
|
||||
|
||||
case SBBidiTypeAN:
|
||||
SB_LOG_STRING("AN");
|
||||
break;
|
||||
|
||||
case SBBidiTypeCS:
|
||||
SB_LOG_STRING("CS");
|
||||
break;
|
||||
|
||||
case SBBidiTypeNSM:
|
||||
SB_LOG_STRING("NSM");
|
||||
break;
|
||||
|
||||
case SBBidiTypeBN:
|
||||
SB_LOG_STRING("BN");
|
||||
break;
|
||||
|
||||
case SBBidiTypeB:
|
||||
SB_LOG_STRING("B");
|
||||
break;
|
||||
|
||||
case SBBidiTypeS:
|
||||
SB_LOG_STRING("S");
|
||||
break;
|
||||
|
||||
case SBBidiTypeWS:
|
||||
SB_LOG_STRING("WS");
|
||||
break;
|
||||
|
||||
case SBBidiTypeON:
|
||||
SB_LOG_STRING("ON");
|
||||
break;
|
||||
|
||||
case SBBidiTypeLRE:
|
||||
SB_LOG_STRING("LRE");
|
||||
break;
|
||||
|
||||
case SBBidiTypeRLE:
|
||||
SB_LOG_STRING("RLE");
|
||||
break;
|
||||
|
||||
case SBBidiTypeLRO:
|
||||
SB_LOG_STRING("LRO");
|
||||
break;
|
||||
|
||||
case SBBidiTypeRLO:
|
||||
SB_LOG_STRING("RLO");
|
||||
break;
|
||||
|
||||
case SBBidiTypePDF:
|
||||
SB_LOG_STRING("PDF");
|
||||
break;
|
||||
|
||||
case SBBidiTypeLRI:
|
||||
SB_LOG_STRING("LRI");
|
||||
break;
|
||||
|
||||
case SBBidiTypeRLI:
|
||||
SB_LOG_STRING("RLI");
|
||||
break;
|
||||
|
||||
case SBBidiTypeFSI:
|
||||
SB_LOG_STRING("FSI");
|
||||
break;
|
||||
|
||||
case SBBidiTypePDI:
|
||||
SB_LOG_STRING("PDI");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void PrintCodepointSequence(const SBCodepointSequence *codepointSequence)
|
||||
{
|
||||
SBUInteger stringIndex = 0;
|
||||
SBCodepoint codepoint;
|
||||
|
||||
while ((codepoint = SBCodepointSequenceGetCodepointAt(codepointSequence, &stringIndex)) != SBCodepointInvalid) {
|
||||
SB_LOG(("%04X ", codepoint));
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void PrintBidiTypesArray(SBBidiType *types, SBUInteger length)
|
||||
{
|
||||
SBUInteger index;
|
||||
|
||||
for (index = 0; index < length; ++index) {
|
||||
SB_LOG_BIDI_TYPE(types[index]);
|
||||
SB_LOG_DIVIDER(1);
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void PrintLevelsArray(SBLevel *levels, SBUInteger length)
|
||||
{
|
||||
SBUInteger index;
|
||||
|
||||
for (index = 0; index < length; ++index) {
|
||||
SB_LOG_LEVEL(levels[index]);
|
||||
SB_LOG_DIVIDER(1);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void *object;
|
||||
BidiLink link;
|
||||
SBUInteger length;
|
||||
} IsolatingContext;
|
||||
|
||||
typedef void (*IsolatingConsumer)(IsolatingRunRef isolatingRun, IsolatingContext *context);
|
||||
|
||||
SB_INTERNAL void IsolatingRunForEach(IsolatingRunRef isolatingRun,
|
||||
IsolatingContext *context, IsolatingConsumer consumer)
|
||||
{
|
||||
BidiChainRef bidiChain = isolatingRun->bidiChain;
|
||||
LevelRunRef levelRun;
|
||||
|
||||
/* Iterate over individual level runs of the isolating run. */
|
||||
for (levelRun = isolatingRun->baseLevelRun; levelRun; levelRun = levelRun->next) {
|
||||
BidiLink breakLink = BidiChainGetNext(bidiChain, levelRun->lastLink);
|
||||
BidiLink currentLink = levelRun->firstLink;
|
||||
BidiLink subsequentLink = levelRun->subsequentLink;
|
||||
|
||||
/* Iterate over each link of the level run. */
|
||||
while (currentLink != breakLink) {
|
||||
BidiLink nextLink = BidiChainGetNext(bidiChain, currentLink);
|
||||
SBUInteger linkOffset = BidiChainGetOffset(bidiChain, currentLink);
|
||||
SBUInteger linkLength;
|
||||
SBUInteger index;
|
||||
|
||||
if (nextLink != breakLink) {
|
||||
linkLength = BidiChainGetOffset(bidiChain, nextLink) - linkOffset;
|
||||
} else {
|
||||
linkLength = BidiChainGetOffset(bidiChain, subsequentLink) - linkOffset;
|
||||
}
|
||||
|
||||
/* Skip any sequence of BN character types. */
|
||||
for (index = 1; index < linkLength; index++) {
|
||||
SBBidiType bidiType = BidiChainGetType(bidiChain, currentLink + index);
|
||||
if (bidiType == SBBidiTypeBN) {
|
||||
linkLength = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
context->link = currentLink;
|
||||
context->length = linkLength;
|
||||
consumer(isolatingRun, context);
|
||||
|
||||
currentLink = nextLink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintTypesOperation(IsolatingRunRef isolatingRun, IsolatingContext *context)
|
||||
{
|
||||
SBBidiType bidiType = BidiChainGetType(isolatingRun->bidiChain, context->link);
|
||||
|
||||
while (context->length--) {
|
||||
SB_LOG_BIDI_TYPE(bidiType);
|
||||
SB_LOG_DIVIDER(1);
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void PrintRunTypes(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
IsolatingContext context;
|
||||
IsolatingRunForEach(isolatingRun, &context, _SBPrintTypesOperation);
|
||||
}
|
||||
|
||||
static void PrintLevelsOperation(IsolatingRunRef isolatingRun, IsolatingContext *context)
|
||||
{
|
||||
SBLevel charLevel = BidiChainGetLevel(isolatingRun->bidiChain, context->link);
|
||||
|
||||
while (context->length--) {
|
||||
SB_LOG_LEVEL(charLevel);
|
||||
SB_LOG_DIVIDER(1);
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void PrintRunLevels(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
IsolatingContext context;
|
||||
IsolatingRunForEach(isolatingRun, &context, _SBPrintLevelsOperation);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
SBUInteger offset;
|
||||
SBUInteger length;
|
||||
} IsolatingRange;
|
||||
|
||||
static void PrintRangeOperation(IsolatingRunRef isolatingRun, IsolatingContext *context)
|
||||
{
|
||||
IsolatingRange *range = context->object;
|
||||
SBUInteger offset = BidiChainGetOffset(isolatingRun->bidiChain, context->link);
|
||||
|
||||
if (range->length == 0) {
|
||||
range->offset = offset;
|
||||
range->length = context->length;
|
||||
} else if (offset == (range->offset + range->length)) {
|
||||
range->length += context->length;
|
||||
} else {
|
||||
SB_LOG_RANGE(range->offset, range->length);
|
||||
SB_LOG_DIVIDER(1);
|
||||
|
||||
range->offset = offset;
|
||||
range->length = context->length;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void PrintRunRange(IsolatingRunRef isolatingRun)
|
||||
{
|
||||
IsolatingRange range = { 0, 0 };
|
||||
IsolatingContext context;
|
||||
context.object = ⦥
|
||||
|
||||
IsolatingRunForEach(isolatingRun, &context, _SBPrintRangeOperation);
|
||||
SB_LOG_RANGE(range.offset, range.length);
|
||||
SB_LOG_DIVIDER(1);
|
||||
}
|
||||
|
||||
#endif
|
153
lib/sheenbidi/Source/SBLog.h
Normal file
153
lib/sheenbidi/Source/SBLog.h
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_LOG_H
|
||||
#define _SB_INTERNAL_LOG_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
|
||||
#ifdef SB_CONFIG_LOG
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SBBase.h"
|
||||
#include "SBBidiType.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "SBIsolatingRun.h"
|
||||
|
||||
SB_INTERNAL void PrintBaseLevel(SBLevel baseLevel);
|
||||
SB_INTERNAL void PrintBidiType(SBBidiType type);
|
||||
|
||||
SB_INTERNAL void PrintCodepointSequence(const SBCodepointSequence *codepointSequence);
|
||||
SB_INTERNAL void PrintBidiTypesArray(SBBidiType *types, SBUInteger length);
|
||||
SB_INTERNAL void PrintLevelsArray(SBLevel *levels, SBUInteger length);
|
||||
|
||||
SB_INTERNAL void PrintRunTypes(IsolatingRunRef isolatingRun);
|
||||
SB_INTERNAL void PrintRunLevels(IsolatingRunRef isolatingRun);
|
||||
SB_INTERNAL void PrintRunRange(IsolatingRunRef isolatingRun);
|
||||
|
||||
extern int _SBLogPosition;
|
||||
|
||||
#define SB_LOG_BEGIN() (++_SBLogPosition)
|
||||
#define SB_LOG_END() (--_SBLogPosition)
|
||||
|
||||
#define SB_LOG(s) printf s
|
||||
|
||||
#define SB_LOG_NUMBER(n) \
|
||||
SB_LOG(("%ld", (long)n))
|
||||
|
||||
#define SB_LOG_RANGE(o, l) \
|
||||
SB_LOG(("[%ld, %ld]", (long)o, (long)(o + l - 1)))
|
||||
|
||||
#define SB_LOG_CHAR(c) \
|
||||
SBLOG(("%c", c))
|
||||
|
||||
#define SB_LOG_STRING(s) \
|
||||
SB_LOG(("%s", s))
|
||||
|
||||
#define SB_LOG_LEVEL(l) \
|
||||
SB_LOG_NUMBER(l)
|
||||
|
||||
#define SB_LOG_BREAKER() \
|
||||
SB_LOG(("\n"))
|
||||
|
||||
#define SB_LOG_DIVIDER(n) \
|
||||
SB_LOG(("%.*s", n, "\t\t\t\t\t\t\t\t\t\t"))
|
||||
|
||||
#define SB_LOG_INITIATOR() \
|
||||
SB_LOG_DIVIDER(_SBLogPosition)
|
||||
|
||||
#define SB_LOG_CAPTION(c) \
|
||||
SB_LOG((c":"))
|
||||
|
||||
#define SB_LOG_STATEMENT_TEXT(t) \
|
||||
(t)
|
||||
|
||||
#define SB_LOG_LINE(s) \
|
||||
do { \
|
||||
SB_LOG(s); \
|
||||
SB_LOG_BREAKER(); \
|
||||
} while (0)
|
||||
|
||||
#define SB_LOG_STATEMENT(c, d, t) \
|
||||
do { \
|
||||
SB_LOG_INITIATOR(); \
|
||||
SB_LOG_CAPTION(c); \
|
||||
SB_LOG_DIVIDER(d); \
|
||||
SB_LOG_STATEMENT_TEXT(t); \
|
||||
SB_LOG_BREAKER(); \
|
||||
} while (0)
|
||||
|
||||
#define SB_LOG_BLOCK_OPENER(c) \
|
||||
do { \
|
||||
SB_LOG_INITIATOR(); \
|
||||
SB_LOG_CAPTION(c); \
|
||||
SB_LOG_BREAKER(); \
|
||||
SB_LOG_BEGIN(); \
|
||||
} while (0)
|
||||
|
||||
#define SB_LOG_BLOCK_CLOSER() SB_LOG_END()
|
||||
|
||||
#define SB_LOG_BASE_LEVEL(l) PrintBaseLevel(l)
|
||||
#define SB_LOG_BIDI_TYPE(t) PrintBidiType(t)
|
||||
|
||||
#define SB_LOG_CODEPOINT_SEQUENCE(s) PrintCodepointSequence(s)
|
||||
#define SB_LOG_BIDI_TYPES_ARRAY(a, l) PrintBidiTypesArray(a, l)
|
||||
#define SB_LOG_LEVELS_ARRAY(a, l) PrintLevelsArray(a, l)
|
||||
|
||||
#define SB_LOG_RUN_TYPES(r) PrintRunTypes(r)
|
||||
#define SB_LOG_RUN_LEVELS(r) PrintRunLevels(r)
|
||||
#define SB_LOG_RUN_RANGE(r) PrintRunRange(r)
|
||||
|
||||
#else
|
||||
|
||||
#define SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG(s) SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_NUMBER(n) SB_LOG_NONE()
|
||||
#define SB_LOG_RANGE(o, l) SB_LOG_NONE()
|
||||
#define SB_LOG_CHAR(c) SB_LOG_NONE()
|
||||
#define SB_LOG_STRING(s) SB_LOG_NONE()
|
||||
#define SB_LOG_LEVEL(l) SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_BREAKER() SB_LOG_NONE()
|
||||
#define SB_LOG_DIVIDER(n) SB_LOG_NONE()
|
||||
#define SB_LOG_INITIATOR() SB_LOG_NONE()
|
||||
#define SB_LOG_CAPTION(c) SB_LOG_NONE()
|
||||
#define SB_LOG_STATEMENT_TEXT(t) SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_LINE(s) SB_LOG_NONE()
|
||||
#define SB_LOG_STATEMENT(c, d, t) SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_BLOCK_OPENER(c) SB_LOG_NONE()
|
||||
#define SB_LOG_BLOCK_CLOSER() SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_BASE_LEVEL(l) SB_LOG_NONE()
|
||||
#define SB_LOG_BIDI_TYPE(t) SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_CODEPOINT_SEQUENCE(s) SB_LOG_NONE()
|
||||
#define SB_LOG_BIDI_TYPES_ARRAY(a, l) SB_LOG_NONE()
|
||||
#define SB_LOG_LEVELS_ARRAY(a, l) SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_RUN_TYPES(r) SB_LOG_NONE()
|
||||
#define SB_LOG_RUN_LEVELS(r) SB_LOG_NONE()
|
||||
|
||||
#define SB_LOG_RUN_RANGE(r) SB_LOG_NONE()
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
121
lib/sheenbidi/Source/SBMirrorLocator.c
Normal file
121
lib/sheenbidi/Source/SBMirrorLocator.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "PairingLookup.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBLine.h"
|
||||
#include "SBMirrorLocator.h"
|
||||
|
||||
SBMirrorLocatorRef SBMirrorLocatorCreate(void)
|
||||
{
|
||||
SBMirrorLocatorRef locator;
|
||||
|
||||
locator = malloc(sizeof(SBMirrorLocator));
|
||||
locator->_line = NULL;
|
||||
locator->retainCount = 1;
|
||||
SBMirrorLocatorReset(locator);
|
||||
|
||||
return locator;
|
||||
}
|
||||
|
||||
void SBMirrorLocatorLoadLine(SBMirrorLocatorRef locator, SBLineRef line, void *stringBuffer)
|
||||
{
|
||||
SBLineRelease(locator->_line);
|
||||
|
||||
if (line && stringBuffer == line->codepointSequence.stringBuffer) {
|
||||
locator->_line = SBLineRetain(line);
|
||||
}
|
||||
|
||||
SBMirrorLocatorReset(locator);
|
||||
}
|
||||
|
||||
const SBMirrorAgent *SBMirrorLocatorGetAgent(SBMirrorLocatorRef locator)
|
||||
{
|
||||
return &locator->agent;
|
||||
}
|
||||
|
||||
SBBoolean SBMirrorLocatorMoveNext(SBMirrorLocatorRef locator)
|
||||
{
|
||||
SBLineRef line = locator->_line;
|
||||
|
||||
if (line) {
|
||||
const SBCodepointSequence *sequence = &line->codepointSequence;
|
||||
|
||||
do {
|
||||
const SBRun *run = &line->fixedRuns[locator->_runIndex];
|
||||
|
||||
if (run->level & 1) {
|
||||
SBUInteger stringIndex;
|
||||
SBUInteger stringLimit;
|
||||
|
||||
stringIndex = locator->_stringIndex;
|
||||
if (stringIndex == SBInvalidIndex) {
|
||||
stringIndex = run->offset;
|
||||
}
|
||||
stringLimit = run->offset + run->length;
|
||||
|
||||
while (stringIndex < stringLimit) {
|
||||
SBUInteger initialIndex = stringIndex;
|
||||
SBCodepoint codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex);
|
||||
SBCodepoint mirror = LookupMirror(codepoint);
|
||||
|
||||
if (mirror) {
|
||||
locator->_stringIndex = stringIndex;
|
||||
locator->agent.index = initialIndex;
|
||||
locator->agent.mirror = mirror;
|
||||
locator->agent.codepoint = codepoint;
|
||||
|
||||
return SBTrue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locator->_stringIndex = SBInvalidIndex;
|
||||
} while (++locator->_runIndex < line->runCount);
|
||||
|
||||
SBMirrorLocatorReset(locator);
|
||||
}
|
||||
|
||||
return SBFalse;
|
||||
}
|
||||
|
||||
void SBMirrorLocatorReset(SBMirrorLocatorRef locator)
|
||||
{
|
||||
locator->_runIndex = 0;
|
||||
locator->_stringIndex = SBInvalidIndex;
|
||||
locator->agent.index = SBInvalidIndex;
|
||||
locator->agent.mirror = 0;
|
||||
}
|
||||
|
||||
SBMirrorLocatorRef SBMirrorLocatorRetain(SBMirrorLocatorRef locator)
|
||||
{
|
||||
if (locator) {
|
||||
locator->retainCount += 1;
|
||||
}
|
||||
|
||||
return locator;
|
||||
}
|
||||
|
||||
void SBMirrorLocatorRelease(SBMirrorLocatorRef locator)
|
||||
{
|
||||
if (locator && --locator->retainCount == 0) {
|
||||
SBLineRelease(locator->_line);
|
||||
free(locator);
|
||||
}
|
||||
}
|
32
lib/sheenbidi/Source/SBMirrorLocator.h
Normal file
32
lib/sheenbidi/Source/SBMirrorLocator.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_MIRROR_LOCATOR_H
|
||||
#define _SB_INTERNAL_MIRROR_LOCATOR_H
|
||||
|
||||
#include <SBBase.h>
|
||||
#include <SBMirrorLocator.h>
|
||||
#include <SBLine.h>
|
||||
|
||||
typedef struct _SBMirrorLocator {
|
||||
SBLineRef _line;
|
||||
SBUInteger _runIndex;
|
||||
SBUInteger _stringIndex;
|
||||
SBMirrorAgent agent;
|
||||
SBUInteger retainCount;
|
||||
} SBMirrorLocator;
|
||||
|
||||
#endif
|
646
lib/sheenbidi/Source/SBParagraph.c
Normal file
646
lib/sheenbidi/Source/SBParagraph.c
Normal file
@ -0,0 +1,646 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "BidiChain.h"
|
||||
#include "BidiTypeLookup.h"
|
||||
#include "IsolatingRun.h"
|
||||
#include "LevelRun.h"
|
||||
#include "RunQueue.h"
|
||||
#include "SBAlgorithm.h"
|
||||
#include "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "SBLine.h"
|
||||
#include "SBLog.h"
|
||||
#include "StatusStack.h"
|
||||
#include "SBParagraph.h"
|
||||
|
||||
typedef struct _ParagraphContext {
|
||||
BidiChain bidiChain;
|
||||
StatusStack statusStack;
|
||||
RunQueue runQueue;
|
||||
IsolatingRun isolatingRun;
|
||||
} ParagraphContext, *ParagraphContextRef;
|
||||
|
||||
static void PopulateBidiChain(BidiChainRef chain, const SBBidiType *types, SBUInteger length);
|
||||
static void ProcessRun(ParagraphContextRef context, const LevelRunRef levelRun, SBBoolean forceFinish);
|
||||
|
||||
static ParagraphContextRef CreateParagraphContext(const SBBidiType *types, SBLevel *levels, SBUInteger length)
|
||||
{
|
||||
const SBUInteger sizeContext = sizeof(ParagraphContext);
|
||||
const SBUInteger sizeLinks = sizeof(BidiLink) * (length + 2);
|
||||
const SBUInteger sizeTypes = sizeof(SBBidiType) * (length + 2);
|
||||
const SBUInteger sizeMemory = sizeContext + sizeLinks + sizeTypes;
|
||||
|
||||
const SBUInteger offsetContext = 0;
|
||||
const SBUInteger offsetLinks = offsetContext + sizeContext;
|
||||
const SBUInteger offsetTypes = offsetLinks + sizeLinks;
|
||||
|
||||
SBUInt8 *memory = (SBUInt8 *)malloc(sizeMemory);
|
||||
ParagraphContextRef context = (ParagraphContextRef)(memory + offsetContext);
|
||||
BidiLink *fixedLinks = (BidiLink *)(memory + offsetLinks);
|
||||
SBBidiType *fixedTypes = (SBBidiType *)(memory + offsetTypes);
|
||||
|
||||
BidiChainInitialize(&context->bidiChain, fixedTypes, levels, fixedLinks);
|
||||
StatusStackInitialize(&context->statusStack);
|
||||
RunQueueInitialize(&context->runQueue);
|
||||
IsolatingRunInitialize(&context->isolatingRun);
|
||||
|
||||
PopulateBidiChain(&context->bidiChain, types, length);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static void DisposeParagraphContext(ParagraphContextRef context)
|
||||
{
|
||||
StatusStackFinalize(&context->statusStack);
|
||||
RunQueueFinalize(&context->runQueue);
|
||||
IsolatingRunFinalize(&context->isolatingRun);
|
||||
free(context);
|
||||
}
|
||||
|
||||
static SBParagraphRef ParagraphAllocate(SBUInteger length)
|
||||
{
|
||||
const SBUInteger sizeParagraph = sizeof(SBParagraph);
|
||||
const SBUInteger sizeLevels = sizeof(SBLevel) * (length + 2);
|
||||
const SBUInteger sizeMemory = sizeParagraph + sizeLevels;
|
||||
|
||||
const SBUInteger offsetParagraph = 0;
|
||||
const SBUInteger offsetLevels = offsetParagraph + sizeParagraph;
|
||||
|
||||
SBUInt8 *memory = (SBUInt8 *)malloc(sizeMemory);
|
||||
SBParagraphRef paragraph = (SBParagraphRef)(memory + offsetParagraph);
|
||||
SBLevel *levels = (SBLevel *)(memory + offsetLevels);
|
||||
|
||||
paragraph->fixedLevels = levels;
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
static SBUInteger DetermineBoundary(SBAlgorithmRef algorithm, SBUInteger paragraphOffset, SBUInteger suggestedLength)
|
||||
{
|
||||
SBBidiType *bidiTypes = algorithm->fixedTypes;
|
||||
SBUInteger suggestedLimit = paragraphOffset + suggestedLength;
|
||||
SBUInteger stringIndex;
|
||||
|
||||
for (stringIndex = paragraphOffset; stringIndex < suggestedLimit; stringIndex++) {
|
||||
if (bidiTypes[stringIndex] == SBBidiTypeB) {
|
||||
goto Return;
|
||||
}
|
||||
}
|
||||
|
||||
Return:
|
||||
stringIndex += SBAlgorithmGetSeparatorLength(algorithm, stringIndex);
|
||||
|
||||
return (stringIndex - paragraphOffset);
|
||||
}
|
||||
|
||||
static void PopulateBidiChain(BidiChainRef chain, const SBBidiType *types, SBUInteger length)
|
||||
{
|
||||
SBBidiType type = SBBidiTypeNil;
|
||||
SBUInteger priorIndex = SBInvalidIndex;
|
||||
SBUInteger index;
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
SBBidiType priorType = type;
|
||||
type = types[index];
|
||||
|
||||
switch (type) {
|
||||
case SBBidiTypeB:
|
||||
case SBBidiTypeON:
|
||||
case SBBidiTypeLRE:
|
||||
case SBBidiTypeRLE:
|
||||
case SBBidiTypeLRO:
|
||||
case SBBidiTypeRLO:
|
||||
case SBBidiTypePDF:
|
||||
case SBBidiTypeLRI:
|
||||
case SBBidiTypeRLI:
|
||||
case SBBidiTypeFSI:
|
||||
case SBBidiTypePDI:
|
||||
BidiChainAdd(chain, type, index - priorIndex);
|
||||
priorIndex = index;
|
||||
|
||||
if (type == SBBidiTypeB) {
|
||||
index = length;
|
||||
goto AddLast;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (type != priorType) {
|
||||
BidiChainAdd(chain, type, index - priorIndex);
|
||||
priorIndex = index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AddLast:
|
||||
BidiChainAdd(chain, SBBidiTypeNil, index - priorIndex);
|
||||
}
|
||||
|
||||
static BidiLink SkipIsolatingRun(BidiChainRef chain, BidiLink skipLink, BidiLink breakLink)
|
||||
{
|
||||
BidiLink link = skipLink;
|
||||
SBUInteger depth = 1;
|
||||
|
||||
while ((link = BidiChainGetNext(chain, link)) != breakLink) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
|
||||
switch (type) {
|
||||
case SBBidiTypeLRI:
|
||||
case SBBidiTypeRLI:
|
||||
case SBBidiTypeFSI:
|
||||
depth += 1;
|
||||
break;
|
||||
|
||||
case SBBidiTypePDI:
|
||||
if (--depth == 0) {
|
||||
return link;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return BidiLinkNone;
|
||||
}
|
||||
|
||||
static SBLevel DetermineBaseLevel(BidiChainRef chain, BidiLink skipLink, BidiLink breakLink, SBLevel defaultLevel, SBBoolean isIsolate)
|
||||
{
|
||||
BidiLink link = skipLink;
|
||||
|
||||
/* Rules P2, P3 */
|
||||
while ((link = BidiChainGetNext(chain, link)) != breakLink) {
|
||||
SBBidiType type = BidiChainGetType(chain, link);
|
||||
|
||||
switch (type) {
|
||||
case SBBidiTypeL:
|
||||
return 0;
|
||||
|
||||
case SBBidiTypeAL:
|
||||
case SBBidiTypeR:
|
||||
return 1;
|
||||
|
||||
case SBBidiTypeLRI:
|
||||
case SBBidiTypeRLI:
|
||||
case SBBidiTypeFSI:
|
||||
link = SkipIsolatingRun(chain, link, breakLink);
|
||||
if (link == BidiLinkNone) {
|
||||
goto Default;
|
||||
}
|
||||
break;
|
||||
|
||||
case SBBidiTypePDI:
|
||||
if (isIsolate) {
|
||||
/*
|
||||
* In case of isolating run, the PDI will be the last code point.
|
||||
* NOTE:
|
||||
* The inner isolating runs will be skipped by the case above this one.
|
||||
*/
|
||||
goto Default;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Default:
|
||||
return defaultLevel;
|
||||
}
|
||||
|
||||
static SBLevel DetermineParagraphLevel(BidiChainRef chain, SBLevel baseLevel)
|
||||
{
|
||||
if (baseLevel >= SBLevelMax) {
|
||||
return DetermineBaseLevel(chain, chain->roller, chain->roller,
|
||||
(baseLevel != SBLevelDefaultRTL ? 0 : 1),
|
||||
SBFalse);
|
||||
}
|
||||
|
||||
return baseLevel;
|
||||
}
|
||||
|
||||
static void DetermineLevels(ParagraphContextRef context, SBLevel baseLevel)
|
||||
{
|
||||
BidiChainRef chain = &context->bidiChain;
|
||||
StatusStackRef stack = &context->statusStack;
|
||||
BidiLink roller = chain->roller;
|
||||
BidiLink link;
|
||||
|
||||
BidiLink priorLink;
|
||||
BidiLink firstLink;
|
||||
BidiLink lastLink;
|
||||
|
||||
SBLevel priorLevel;
|
||||
SBBidiType sor;
|
||||
SBBidiType eor;
|
||||
|
||||
SBUInteger overIsolate;
|
||||
SBUInteger overEmbedding;
|
||||
SBUInteger validIsolate;
|
||||
|
||||
priorLink = chain->roller;
|
||||
firstLink = BidiLinkNone;
|
||||
lastLink = BidiLinkNone;
|
||||
|
||||
priorLevel = baseLevel;
|
||||
sor = SBBidiTypeNil;
|
||||
|
||||
/* Rule X1 */
|
||||
overIsolate = 0;
|
||||
overEmbedding = 0;
|
||||
validIsolate = 0;
|
||||
|
||||
StatusStackPush(stack, baseLevel, SBBidiTypeON, SBFalse);
|
||||
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBBoolean forceFinish = SBFalse;
|
||||
SBBoolean bnEquivalent = SBFalse;
|
||||
SBBidiType type;
|
||||
|
||||
type = BidiChainGetType(chain, link);
|
||||
|
||||
#define LeastGreaterOddLevel() \
|
||||
( \
|
||||
(StatusStackGetEmbeddingLevel(stack) + 1) | 1 \
|
||||
)
|
||||
|
||||
#define LeastGreaterEvenLevel() \
|
||||
( \
|
||||
(StatusStackGetEmbeddingLevel(stack) + 2) & ~1 \
|
||||
)
|
||||
|
||||
#define MergeLinkIfNeeded() \
|
||||
{ \
|
||||
if (BidiChainMergeIfEqual(chain, priorLink, link)) { \
|
||||
continue; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PushEmbedding(l, o) \
|
||||
{ \
|
||||
SBLevel newLevel = l; \
|
||||
\
|
||||
bnEquivalent = SBTrue; \
|
||||
\
|
||||
if (newLevel <= SBLevelMax && !overIsolate && !overEmbedding) { \
|
||||
StatusStackPush(stack, newLevel, o, SBFalse); \
|
||||
} else { \
|
||||
if (!overIsolate) { \
|
||||
overEmbedding += 1; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PushIsolate(l, o) \
|
||||
{ \
|
||||
SBBidiType priorStatus = StatusStackGetOverrideStatus(stack); \
|
||||
SBLevel newLevel = l; \
|
||||
\
|
||||
BidiChainSetLevel(chain, link, \
|
||||
StatusStackGetEmbeddingLevel(stack)); \
|
||||
\
|
||||
if (newLevel <= SBLevelMax && !overIsolate && !overEmbedding) { \
|
||||
validIsolate += 1; \
|
||||
StatusStackPush(stack, newLevel, o, SBTrue); \
|
||||
} else { \
|
||||
overIsolate += 1; \
|
||||
} \
|
||||
\
|
||||
if (priorStatus != SBBidiTypeON) { \
|
||||
BidiChainSetType(chain, link, priorStatus); \
|
||||
MergeLinkIfNeeded(); \
|
||||
} \
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
/* Rule X2 */
|
||||
case SBBidiTypeRLE:
|
||||
PushEmbedding(LeastGreaterOddLevel(), SBBidiTypeON);
|
||||
break;
|
||||
|
||||
/* Rule X3 */
|
||||
case SBBidiTypeLRE:
|
||||
PushEmbedding(LeastGreaterEvenLevel(), SBBidiTypeON);
|
||||
break;
|
||||
|
||||
/* Rule X4 */
|
||||
case SBBidiTypeRLO:
|
||||
PushEmbedding(LeastGreaterOddLevel(), SBBidiTypeR);
|
||||
break;
|
||||
|
||||
/* Rule X5 */
|
||||
case SBBidiTypeLRO:
|
||||
PushEmbedding(LeastGreaterEvenLevel(), SBBidiTypeL);
|
||||
break;
|
||||
|
||||
/* Rule X5a */
|
||||
case SBBidiTypeRLI:
|
||||
PushIsolate(LeastGreaterOddLevel(), SBBidiTypeON);
|
||||
break;
|
||||
|
||||
/* Rule X5b */
|
||||
case SBBidiTypeLRI:
|
||||
PushIsolate(LeastGreaterEvenLevel(), SBBidiTypeON);
|
||||
break;
|
||||
|
||||
/* Rule X5c */
|
||||
case SBBidiTypeFSI:
|
||||
{
|
||||
SBBoolean isRTL = (DetermineBaseLevel(chain, link, roller, 0, SBTrue) == 1);
|
||||
PushIsolate(isRTL ? LeastGreaterOddLevel() : LeastGreaterEvenLevel(), SBBidiTypeON);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Rule X6 */
|
||||
default:
|
||||
BidiChainSetLevel(chain, link, StatusStackGetEmbeddingLevel(stack));
|
||||
|
||||
if (StatusStackGetOverrideStatus(stack) != SBBidiTypeON) {
|
||||
BidiChainSetType(chain, link, StatusStackGetOverrideStatus(stack));
|
||||
MergeLinkIfNeeded();
|
||||
}
|
||||
break;
|
||||
|
||||
/* Rule X6a */
|
||||
case SBBidiTypePDI:
|
||||
{
|
||||
SBBidiType overrideStatus;
|
||||
|
||||
if (overIsolate != 0) {
|
||||
overIsolate -= 1;
|
||||
} else if (validIsolate == 0) {
|
||||
/* Do nothing */
|
||||
} else {
|
||||
overEmbedding = 0;
|
||||
|
||||
while (!StatusStackGetIsolateStatus(stack)) {
|
||||
StatusStackPop(stack);
|
||||
}
|
||||
StatusStackPop(stack);
|
||||
|
||||
validIsolate -= 1;
|
||||
}
|
||||
|
||||
BidiChainSetLevel(chain, link, StatusStackGetEmbeddingLevel(stack));
|
||||
overrideStatus = StatusStackGetOverrideStatus(stack);
|
||||
|
||||
if (overrideStatus != SBBidiTypeON) {
|
||||
BidiChainSetType(chain, link, overrideStatus);
|
||||
MergeLinkIfNeeded();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Rule X7 */
|
||||
case SBBidiTypePDF:
|
||||
bnEquivalent = SBTrue;
|
||||
|
||||
if (overIsolate != 0) {
|
||||
/* Do nothing */
|
||||
} else if (overEmbedding != 0) {
|
||||
overEmbedding -= 1;
|
||||
} else if (!StatusStackGetIsolateStatus(stack) && stack->count >= 2) {
|
||||
StatusStackPop(stack);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Rule X8 */
|
||||
case SBBidiTypeB:
|
||||
/*
|
||||
* These values are reset for clarity, in this implementation B can only occur as the
|
||||
* last code in the array.
|
||||
*/
|
||||
StatusStackSetEmpty(stack);
|
||||
StatusStackPush(stack, baseLevel, SBBidiTypeON, SBFalse);
|
||||
|
||||
overIsolate = 0;
|
||||
overEmbedding = 0;
|
||||
validIsolate = 0;
|
||||
|
||||
BidiChainSetLevel(chain, link, baseLevel);
|
||||
break;
|
||||
|
||||
case SBBidiTypeBN:
|
||||
bnEquivalent = SBTrue;
|
||||
break;
|
||||
|
||||
case SBBidiTypeNil:
|
||||
forceFinish = SBTrue;
|
||||
BidiChainSetLevel(chain, link, baseLevel);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Rule X9 */
|
||||
if (bnEquivalent) {
|
||||
/* The type of this link is BN equivalent, so abandon it and continue the loop. */
|
||||
BidiChainSetType(chain, link, SBBidiTypeBN);
|
||||
BidiChainAbandonNext(chain, priorLink);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sor == SBBidiTypeNil) {
|
||||
sor = SBLevelAsNormalBidiType(SBNumberGetMax(baseLevel, BidiChainGetLevel(chain, link)));
|
||||
firstLink = link;
|
||||
priorLevel = BidiChainGetLevel(chain, link);
|
||||
} else if (priorLevel != BidiChainGetLevel(chain, link) || forceFinish) {
|
||||
LevelRun levelRun;
|
||||
SBLevel currentLevel;
|
||||
|
||||
/* Since the level has changed at this link, therefore the run must end at prior link. */
|
||||
lastLink = priorLink;
|
||||
|
||||
/* Save the current level i.e. level of the next run. */
|
||||
currentLevel = BidiChainGetLevel(chain, link);
|
||||
/*
|
||||
* Now we have both the prior level and the current level i.e. unchanged levels of both
|
||||
* the current run and the next run. So, identify eor of the current run.
|
||||
* NOTE:
|
||||
* sor of the run has been already determined at this stage.
|
||||
*/
|
||||
eor = SBLevelAsNormalBidiType(SBNumberGetMax(priorLevel, currentLevel));
|
||||
|
||||
LevelRunInitialize(&levelRun, chain, firstLink, lastLink, sor, eor);
|
||||
ProcessRun(context, &levelRun, forceFinish);
|
||||
|
||||
/* The sor of next run (if any) should be technically equal to eor of this run. */
|
||||
sor = eor;
|
||||
/* The next run (if any) will start from this index. */
|
||||
firstLink = link;
|
||||
|
||||
priorLevel = currentLevel;
|
||||
}
|
||||
|
||||
priorLink = link;
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessRun(ParagraphContextRef context, const LevelRunRef levelRun, SBBoolean forceFinish)
|
||||
{
|
||||
RunQueueRef queue = &context->runQueue;
|
||||
RunQueueEnqueue(queue, levelRun);
|
||||
|
||||
if (queue->shouldDequeue || forceFinish) {
|
||||
IsolatingRunRef isolatingRun = &context->isolatingRun;
|
||||
LevelRunRef peek;
|
||||
|
||||
/* Rule X10 */
|
||||
for (; queue->count != 0; RunQueueDequeue(queue)) {
|
||||
peek = queue->peek;
|
||||
if (RunKindIsAttachedTerminating(peek->kind)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
isolatingRun->baseLevelRun = peek;
|
||||
IsolatingRunResolve(isolatingRun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SaveLevels(BidiChainRef chain, SBLevel *levels, SBLevel baseLevel)
|
||||
{
|
||||
BidiLink roller = chain->roller;
|
||||
BidiLink link;
|
||||
|
||||
SBUInteger index = 0;
|
||||
SBLevel level = baseLevel;
|
||||
|
||||
BidiChainForEach(chain, roller, link) {
|
||||
SBUInteger offset = BidiChainGetOffset(chain, link);
|
||||
|
||||
for (; index < offset; index++) {
|
||||
levels[index] = level;
|
||||
}
|
||||
|
||||
level = BidiChainGetLevel(chain, link);
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL SBParagraphRef SBParagraphCreate(SBAlgorithmRef algorithm,
|
||||
SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel)
|
||||
{
|
||||
const SBCodepointSequence *codepointSequence = &algorithm->codepointSequence;
|
||||
SBUInteger stringLength = codepointSequence->stringLength;
|
||||
SBUInteger actualLength;
|
||||
|
||||
SBParagraphRef paragraph;
|
||||
ParagraphContextRef context;
|
||||
SBLevel resolvedLevel;
|
||||
|
||||
/* The given range MUST be valid. */
|
||||
SBAssert(SBUIntegerVerifyRange(stringLength, paragraphOffset, suggestedLength) && suggestedLength > 0);
|
||||
|
||||
SB_LOG_BLOCK_OPENER("Paragraph Input");
|
||||
SB_LOG_STATEMENT("Paragraph Offset", 1, SB_LOG_NUMBER(paragraphOffset));
|
||||
SB_LOG_STATEMENT("Suggested Length", 1, SB_LOG_NUMBER(suggestedLength));
|
||||
SB_LOG_STATEMENT("Base Direction", 1, SB_LOG_BASE_LEVEL(baseLevel));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
actualLength = DetermineBoundary(algorithm, paragraphOffset, suggestedLength);
|
||||
|
||||
SB_LOG_BLOCK_OPENER("Determined Paragraph Boundary");
|
||||
SB_LOG_STATEMENT("Actual Length", 1, SB_LOG_NUMBER(actualLength));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
paragraph = ParagraphAllocate(actualLength);
|
||||
paragraph->refTypes = algorithm->fixedTypes + paragraphOffset;
|
||||
|
||||
context = CreateParagraphContext(paragraph->refTypes, paragraph->fixedLevels, actualLength);
|
||||
|
||||
resolvedLevel = DetermineParagraphLevel(&context->bidiChain, baseLevel);
|
||||
|
||||
SB_LOG_BLOCK_OPENER("Determined Paragraph Level");
|
||||
SB_LOG_STATEMENT("Base Level", 1, SB_LOG_LEVEL(resolvedLevel));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
context->isolatingRun.codepointSequence = codepointSequence;
|
||||
context->isolatingRun.bidiTypes = paragraph->refTypes;
|
||||
context->isolatingRun.bidiChain = &context->bidiChain;
|
||||
context->isolatingRun.paragraphOffset = paragraphOffset;
|
||||
context->isolatingRun.paragraphLevel = resolvedLevel;
|
||||
|
||||
DetermineLevels(context, resolvedLevel);
|
||||
SaveLevels(&context->bidiChain, ++paragraph->fixedLevels, resolvedLevel);
|
||||
|
||||
SB_LOG_BLOCK_OPENER("Determined Embedding Levels");
|
||||
SB_LOG_STATEMENT("Levels", 1, SB_LOG_LEVELS_ARRAY(paragraph->fixedLevels, actualLength));
|
||||
SB_LOG_BLOCK_CLOSER();
|
||||
|
||||
paragraph->algorithm = SBAlgorithmRetain(algorithm);
|
||||
paragraph->offset = paragraphOffset;
|
||||
paragraph->length = actualLength;
|
||||
paragraph->baseLevel = resolvedLevel;
|
||||
paragraph->retainCount = 1;
|
||||
|
||||
DisposeParagraphContext(context);
|
||||
|
||||
SB_LOG_BREAKER();
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
SBUInteger SBParagraphGetOffset(SBParagraphRef paragraph)
|
||||
{
|
||||
return paragraph->offset;
|
||||
}
|
||||
|
||||
SBUInteger SBParagraphGetLength(SBParagraphRef paragraph)
|
||||
{
|
||||
return paragraph->length;
|
||||
}
|
||||
|
||||
SBLevel SBParagraphGetBaseLevel(SBParagraphRef paragraph)
|
||||
{
|
||||
return paragraph->baseLevel;
|
||||
}
|
||||
|
||||
const SBLevel *SBParagraphGetLevelsPtr(SBParagraphRef paragraph)
|
||||
{
|
||||
return paragraph->fixedLevels;
|
||||
}
|
||||
|
||||
SBLineRef SBParagraphCreateLine(SBParagraphRef paragraph, SBUInteger lineOffset, SBUInteger lineLength)
|
||||
{
|
||||
SBUInteger paragraphOffset = paragraph->offset;
|
||||
SBUInteger paragraphLength = paragraph->length;
|
||||
SBUInteger paragraphLimit = paragraphOffset + paragraphLength;
|
||||
SBUInteger lineLimit = lineOffset + lineLength;
|
||||
|
||||
if (lineOffset < lineLimit && lineOffset >= paragraphOffset && lineLimit <= paragraphLimit) {
|
||||
return SBLineCreate(paragraph, lineOffset, lineLength);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SBParagraphRef SBParagraphRetain(SBParagraphRef paragraph)
|
||||
{
|
||||
if (paragraph) {
|
||||
paragraph->retainCount += 1;
|
||||
}
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
void SBParagraphRelease(SBParagraphRef paragraph)
|
||||
{
|
||||
if (paragraph && --paragraph->retainCount == 0) {
|
||||
SBAlgorithmRelease(paragraph->algorithm);
|
||||
free(paragraph);
|
||||
}
|
||||
}
|
38
lib/sheenbidi/Source/SBParagraph.h
Normal file
38
lib/sheenbidi/Source/SBParagraph.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_PARAGRAPH_H
|
||||
#define _SB_INTERNAL_PARAGRAPH_H
|
||||
|
||||
#include <SBAlgorithm.h>
|
||||
#include <SBBase.h>
|
||||
#include <SBConfig.h>
|
||||
#include <SBParagraph.h>
|
||||
|
||||
typedef struct _SBParagraph {
|
||||
SBAlgorithmRef algorithm;
|
||||
const SBBidiType *refTypes;
|
||||
SBLevel *fixedLevels;
|
||||
SBUInteger offset;
|
||||
SBUInteger length;
|
||||
SBLevel baseLevel;
|
||||
SBUInteger retainCount;
|
||||
} SBParagraph;
|
||||
|
||||
SB_INTERNAL SBParagraphRef SBParagraphCreate(SBAlgorithmRef algorithm,
|
||||
SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel);
|
||||
|
||||
#endif
|
174
lib/sheenbidi/Source/SBScriptLocator.c
Normal file
174
lib/sheenbidi/Source/SBScriptLocator.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (C) 2018-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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "GeneralCategoryLookup.h"
|
||||
#include "PairingLookup.h"
|
||||
#include "SBBase.h"
|
||||
#include "SBCodepointSequence.h"
|
||||
#include "ScriptLookup.h"
|
||||
#include "ScriptStack.h"
|
||||
#include "SBScriptLocator.h"
|
||||
|
||||
static SBBoolean IsSimilarScript(SBScript lhs, SBScript rhs)
|
||||
{
|
||||
return SBScriptIsCommonOrInherited(lhs)
|
||||
|| SBScriptIsCommonOrInherited(rhs)
|
||||
|| lhs == rhs;
|
||||
}
|
||||
|
||||
SBScriptLocatorRef SBScriptLocatorCreate(void)
|
||||
{
|
||||
SBScriptLocatorRef locator;
|
||||
|
||||
locator = malloc(sizeof(SBScriptLocator));
|
||||
locator->_codepointSequence.stringEncoding = SBStringEncodingUTF8;
|
||||
locator->_codepointSequence.stringBuffer = NULL;
|
||||
locator->_codepointSequence.stringLength = 0;
|
||||
locator->retainCount = 1;
|
||||
SBScriptLocatorReset(locator);
|
||||
|
||||
return locator;
|
||||
}
|
||||
|
||||
void SBScriptLocatorLoadCodepoints(SBScriptLocatorRef locator, const SBCodepointSequence *codepointSequence)
|
||||
{
|
||||
locator->_codepointSequence = *codepointSequence;
|
||||
SBScriptLocatorReset(locator);
|
||||
}
|
||||
|
||||
const SBScriptAgent *SBScriptLocatorGetAgent(SBScriptLocatorRef locator)
|
||||
{
|
||||
return &locator->agent;
|
||||
}
|
||||
|
||||
static void ResolveScriptRun(SBScriptLocatorRef locator, SBUInteger offset)
|
||||
{
|
||||
const SBCodepointSequence *sequence = &locator->_codepointSequence;
|
||||
ScriptStackRef stack = &locator->_scriptStack;
|
||||
SBScript result = SBScriptZYYY;
|
||||
SBUInteger current = offset;
|
||||
SBUInteger next = offset;
|
||||
SBCodepoint codepoint;
|
||||
|
||||
/* Iterate over the code points of specified string buffer. */
|
||||
while ((codepoint = SBCodepointSequenceGetCodepointAt(sequence, &next)) != SBCodepointInvalid) {
|
||||
SBBoolean isStacked = SBFalse;
|
||||
SBScript script;
|
||||
|
||||
script = LookupScript(codepoint);
|
||||
|
||||
/* Handle paired punctuations in case of a common script. */
|
||||
if (script == SBScriptZYYY) {
|
||||
SBGeneralCategory generalCategory = LookupGeneralCategory(codepoint);
|
||||
|
||||
/* Check if current code point is an open punctuation. */
|
||||
if (generalCategory == SBGeneralCategoryPS) {
|
||||
SBCodepoint mirror = LookupMirror(codepoint);
|
||||
if (mirror) {
|
||||
/* A closing pair exists for this punctuation, so push it onto the stack. */
|
||||
ScriptStackPush(stack, result, mirror);
|
||||
}
|
||||
}
|
||||
/* Check if current code point is a close punctuation. */
|
||||
else if (generalCategory == SBGeneralCategoryPE) {
|
||||
SBBoolean isMirrored = (LookupMirror(codepoint) != 0);
|
||||
if (isMirrored) {
|
||||
/* Find the matching entry in the stack, while popping the unmatched ones. */
|
||||
while (!ScriptStackIsEmpty(stack)) {
|
||||
SBCodepoint mirror = ScriptStackGetMirror(stack);
|
||||
if (mirror != codepoint) {
|
||||
ScriptStackPop(stack);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ScriptStackIsEmpty(stack)) {
|
||||
isStacked = SBTrue;
|
||||
/* Paired punctuation match the script of enclosing text. */
|
||||
script = ScriptStackGetScript(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSimilarScript(result, script)) {
|
||||
if (SBScriptIsCommonOrInherited(result) && !SBScriptIsCommonOrInherited(script)) {
|
||||
/* Set the concrete script of this code point as the result. */
|
||||
result = script;
|
||||
/* Seal the pending punctuations with the result. */
|
||||
ScriptStackSealPairs(stack, result);
|
||||
}
|
||||
|
||||
if (isStacked) {
|
||||
/* Pop the paired punctuation from the stack. */
|
||||
ScriptStackPop(stack);
|
||||
}
|
||||
} else {
|
||||
/* The current code point has a different script, so finish the run. */
|
||||
break;
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
ScriptStackLeavePairs(stack);
|
||||
|
||||
/* Set the run info in agent. */
|
||||
locator->agent.offset = offset;
|
||||
locator->agent.length = current - offset;
|
||||
locator->agent.script = result;
|
||||
}
|
||||
|
||||
SBBoolean SBScriptLocatorMoveNext(SBScriptLocatorRef locator)
|
||||
{
|
||||
SBUInteger offset = locator->agent.offset + locator->agent.length;
|
||||
|
||||
if (offset < locator->_codepointSequence.stringLength) {
|
||||
ResolveScriptRun(locator, offset);
|
||||
return SBTrue;
|
||||
}
|
||||
|
||||
SBScriptLocatorReset(locator);
|
||||
return SBFalse;
|
||||
}
|
||||
|
||||
void SBScriptLocatorReset(SBScriptLocatorRef locator)
|
||||
{
|
||||
ScriptStackReset(&locator->_scriptStack);
|
||||
locator->agent.offset = 0;
|
||||
locator->agent.length = 0;
|
||||
locator->agent.script = SBScriptNil;
|
||||
}
|
||||
|
||||
SBScriptLocatorRef SBScriptLocatorRetain(SBScriptLocatorRef locator)
|
||||
{
|
||||
if (locator) {
|
||||
locator->retainCount += 1;
|
||||
}
|
||||
|
||||
return locator;
|
||||
}
|
||||
|
||||
void SBScriptLocatorRelease(SBScriptLocatorRef locator)
|
||||
{
|
||||
if (locator && --locator->retainCount == 0) {
|
||||
free(locator);
|
||||
}
|
||||
}
|
33
lib/sheenbidi/Source/SBScriptLocator.h
Normal file
33
lib/sheenbidi/Source/SBScriptLocator.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2018-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_SCRIPT_LOCATOR_H
|
||||
#define _SB_INTERNAL_SCRIPT_LOCATOR_H
|
||||
|
||||
#include <SBBase.h>
|
||||
#include <SBCodepointSequence.h>
|
||||
#include <SBScriptLocator.h>
|
||||
|
||||
#include "ScriptStack.h"
|
||||
|
||||
typedef struct _SBScriptLocator {
|
||||
SBCodepointSequence _codepointSequence;
|
||||
ScriptStack _scriptStack;
|
||||
SBScriptAgent agent;
|
||||
SBUInteger retainCount;
|
||||
} SBScriptLocator;
|
||||
|
||||
#endif
|
2142
lib/sheenbidi/Source/ScriptLookup.c
Normal file
2142
lib/sheenbidi/Source/ScriptLookup.c
Normal file
File diff suppressed because it is too large
Load Diff
16
lib/sheenbidi/Source/ScriptLookup.h
Normal file
16
lib/sheenbidi/Source/ScriptLookup.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Automatically generated by SheenBidiGenerator tool.
|
||||
* DO NOT EDIT!!
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_SCRIPT_LOOKUP_H
|
||||
#define _SB_INTERNAL_SCRIPT_LOOKUP_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
#include <SBScript.h>
|
||||
|
||||
#include "SBBase.h"
|
||||
|
||||
SB_INTERNAL SBScript LookupScript(SBCodepoint codepoint);
|
||||
|
||||
#endif
|
83
lib/sheenbidi/Source/ScriptStack.c
Normal file
83
lib/sheenbidi/Source/ScriptStack.c
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2018-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 "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "ScriptStack.h"
|
||||
|
||||
SB_INTERNAL void ScriptStackReset(ScriptStackRef stack)
|
||||
{
|
||||
stack->top = -1;
|
||||
stack->count = 0;
|
||||
stack->open = 0;
|
||||
}
|
||||
|
||||
SB_INTERNAL void ScriptStackPush(ScriptStackRef stack, SBScript script, SBCodepoint mirror)
|
||||
{
|
||||
stack->count = SBNumberLimitIncrement(stack->count, _SBScriptStackCapacity);
|
||||
stack->open = SBNumberLimitIncrement(stack->open, _SBScriptStackCapacity);
|
||||
|
||||
stack->top = SBNumberRingIncrement(stack->top, _SBScriptStackCapacity);
|
||||
stack->_elements[stack->top].script = script;
|
||||
stack->_elements[stack->top].mirror = mirror;
|
||||
}
|
||||
|
||||
SB_INTERNAL void ScriptStackPop(ScriptStackRef stack)
|
||||
{
|
||||
/* There must be at least one entry in the stack. */
|
||||
SBAssert(stack->count > 0);
|
||||
|
||||
stack->count -= 1;
|
||||
stack->open = SBNumberLimitDecrement(stack->open, 0);
|
||||
stack->top = SBNumberRingDecrement(stack->top, _SBScriptStackCapacity);
|
||||
|
||||
if (ScriptStackIsEmpty(stack)) {
|
||||
stack->top = -1;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL void ScriptStackLeavePairs(ScriptStackRef stack)
|
||||
{
|
||||
stack->open = 0;
|
||||
}
|
||||
|
||||
SB_INTERNAL void ScriptStackSealPairs(ScriptStackRef stack, SBScript script)
|
||||
{
|
||||
SBInteger index = SBNumberRingSubtract(stack->top, (SBInteger)stack->open, _SBScriptStackCapacity);
|
||||
|
||||
while (stack->open) {
|
||||
index = SBNumberRingIncrement(index, _SBScriptStackCapacity);
|
||||
stack->_elements[index].script = script;
|
||||
stack->open -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBoolean ScriptStackIsEmpty(ScriptStackRef stack)
|
||||
{
|
||||
return (stack->count == 0);
|
||||
}
|
||||
|
||||
SB_INTERNAL SBScript ScriptStackGetScript(ScriptStackRef stack)
|
||||
{
|
||||
return stack->_elements[stack->top].script;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBCodepoint ScriptStackGetMirror(ScriptStackRef stack)
|
||||
{
|
||||
return stack->_elements[stack->top].mirror;
|
||||
}
|
49
lib/sheenbidi/Source/ScriptStack.h
Normal file
49
lib/sheenbidi/Source/ScriptStack.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2018-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_SCRIPT_STACK_H
|
||||
#define _SB_INTERNAL_SCRIPT_STACK_H
|
||||
|
||||
#include <SBBase.h>
|
||||
#include <SBConfig.h>
|
||||
|
||||
#define _SBScriptStackCapacity 63
|
||||
|
||||
typedef struct _SBScriptStackElement {
|
||||
SBScript script;
|
||||
SBCodepoint mirror;
|
||||
} _SBScriptStackElement;
|
||||
|
||||
typedef struct _SBScriptStack {
|
||||
_SBScriptStackElement _elements[_SBScriptStackCapacity];
|
||||
SBInteger top;
|
||||
SBUInteger count;
|
||||
SBUInteger open;
|
||||
} ScriptStack, *ScriptStackRef;
|
||||
|
||||
SB_INTERNAL void ScriptStackReset(ScriptStackRef stack);
|
||||
|
||||
SB_INTERNAL void ScriptStackPush(ScriptStackRef stack, SBScript script, SBCodepoint mirror);
|
||||
SB_INTERNAL void ScriptStackPop(ScriptStackRef stack);
|
||||
|
||||
SB_INTERNAL void ScriptStackLeavePairs(ScriptStackRef stack);
|
||||
SB_INTERNAL void ScriptStackSealPairs(ScriptStackRef stack, SBScript script);
|
||||
|
||||
SB_INTERNAL SBBoolean ScriptStackIsEmpty(ScriptStackRef stack);
|
||||
SB_INTERNAL SBScript ScriptStackGetScript(ScriptStackRef stack);
|
||||
SB_INTERNAL SBCodepoint ScriptStackGetMirror(ScriptStackRef stack);
|
||||
|
||||
#endif
|
42
lib/sheenbidi/Source/SheenBidi.c
Normal file
42
lib/sheenbidi/Source/SheenBidi.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <SheenBidi.h>
|
||||
|
||||
#ifdef SB_CONFIG_UNITY
|
||||
|
||||
#include "BidiChain.c"
|
||||
#include "BidiTypeLookup.c"
|
||||
#include "BracketQueue.c"
|
||||
#include "GeneralCategoryLookup.c"
|
||||
#include "IsolatingRun.c"
|
||||
#include "LevelRun.c"
|
||||
#include "PairingLookup.c"
|
||||
#include "RunQueue.c"
|
||||
#include "SBAlgorithm.c"
|
||||
#include "SBBase.c"
|
||||
#include "SBCodepointSequence.c"
|
||||
#include "SBLine.c"
|
||||
#include "SBLog.c"
|
||||
#include "SBMirrorLocator.c"
|
||||
#include "SBParagraph.c"
|
||||
#include "SBScriptLocator.c"
|
||||
#include "ScriptLookup.c"
|
||||
#include "ScriptStack.c"
|
||||
#include "StatusStack.c"
|
||||
|
||||
#endif
|
111
lib/sheenbidi/Source/StatusStack.c
Normal file
111
lib/sheenbidi/Source/StatusStack.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SBAssert.h"
|
||||
#include "SBBase.h"
|
||||
#include "StatusStack.h"
|
||||
|
||||
SB_INTERNAL void StatusStackInitialize(StatusStackRef stack)
|
||||
{
|
||||
stack->_firstList.previous = NULL;
|
||||
stack->_firstList.next = NULL;
|
||||
|
||||
StatusStackSetEmpty(stack);
|
||||
}
|
||||
|
||||
SB_INTERNAL void StatusStackPush(StatusStackRef stack, SBLevel embeddingLevel, SBBidiType overrideStatus, SBBoolean isolateStatus)
|
||||
{
|
||||
_SBStatusStackElementRef element;
|
||||
|
||||
/* The stack can hold upto 127 elements. */
|
||||
SBAssert(stack->count <= 127);
|
||||
|
||||
if (stack->_peekTop != _SBStatusStackList_MaxIndex) {
|
||||
element = &stack->_peekList->elements[++stack->_peekTop];
|
||||
} else {
|
||||
_SBStatusStackListRef previousList = stack->_peekList;
|
||||
_SBStatusStackListRef peekList = previousList->next;
|
||||
|
||||
if (!peekList) {
|
||||
peekList = malloc(sizeof(_SBStatusStackList));
|
||||
peekList->previous = previousList;
|
||||
peekList->next = NULL;
|
||||
|
||||
previousList->next = peekList;
|
||||
}
|
||||
|
||||
stack->_peekList = peekList;
|
||||
stack->_peekTop = 0;
|
||||
|
||||
element = &peekList->elements[0];
|
||||
}
|
||||
stack->count += 1;
|
||||
|
||||
element->embeddingLevel = embeddingLevel;
|
||||
element->overrideStatus = overrideStatus;
|
||||
element->isolateStatus = isolateStatus;
|
||||
}
|
||||
|
||||
SB_INTERNAL void StatusStackPop(StatusStackRef stack)
|
||||
{
|
||||
/* The stack should not be empty. */
|
||||
SBAssert(stack->count != 0);
|
||||
|
||||
if (stack->_peekTop != 0) {
|
||||
stack->_peekTop -= 1;
|
||||
} else {
|
||||
stack->_peekList = stack->_peekList->previous;
|
||||
stack->_peekTop = _SBStatusStackList_MaxIndex;
|
||||
}
|
||||
stack->count -= 1;
|
||||
}
|
||||
|
||||
SB_INTERNAL void StatusStackSetEmpty(StatusStackRef stack)
|
||||
{
|
||||
stack->_peekList = &stack->_firstList;
|
||||
stack->_peekTop = 0;
|
||||
stack->count = 0;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBLevel StatusStackGetEmbeddingLevel(StatusStackRef stack)
|
||||
{
|
||||
return stack->_peekList->elements[stack->_peekTop].embeddingLevel;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBidiType StatusStackGetOverrideStatus(StatusStackRef stack)
|
||||
{
|
||||
return stack->_peekList->elements[stack->_peekTop].overrideStatus;
|
||||
}
|
||||
|
||||
SB_INTERNAL SBBoolean StatusStackGetIsolateStatus(StatusStackRef stack)
|
||||
{
|
||||
return stack->_peekList->elements[stack->_peekTop].isolateStatus;
|
||||
}
|
||||
|
||||
SB_INTERNAL void StatusStackFinalize(StatusStackRef stack)
|
||||
{
|
||||
_SBStatusStackListRef list = stack->_firstList.next;
|
||||
|
||||
while (list) {
|
||||
_SBStatusStackListRef next = list->next;
|
||||
free(list);
|
||||
list = next;
|
||||
};
|
||||
}
|
58
lib/sheenbidi/Source/StatusStack.h
Normal file
58
lib/sheenbidi/Source/StatusStack.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef _SB_INTERNAL_STATUS_STACK_H
|
||||
#define _SB_INTERNAL_STATUS_STACK_H
|
||||
|
||||
#include <SBConfig.h>
|
||||
#include "SBBase.h"
|
||||
|
||||
#define _SBStatusStackList_Length 16
|
||||
#define _SBStatusStackList_MaxIndex (_SBStatusStackList_Length - 1)
|
||||
|
||||
typedef struct _SBStatusStackElement {
|
||||
SBBoolean isolateStatus;
|
||||
SBBidiType overrideStatus;
|
||||
SBLevel embeddingLevel;
|
||||
} _SBStatusStackElement, *_SBStatusStackElementRef;
|
||||
|
||||
typedef struct _SBStatusStackList {
|
||||
_SBStatusStackElement elements[_SBStatusStackList_Length];
|
||||
|
||||
struct _SBStatusStackList *previous;
|
||||
struct _SBStatusStackList *next;
|
||||
} _SBStatusStackList, *_SBStatusStackListRef;
|
||||
|
||||
typedef struct _SBStatusStack {
|
||||
_SBStatusStackList _firstList;
|
||||
_SBStatusStackListRef _peekList;
|
||||
SBUInteger _peekTop;
|
||||
SBUInteger count;
|
||||
} StatusStack, *StatusStackRef;
|
||||
|
||||
SB_INTERNAL void StatusStackInitialize(StatusStackRef stack);
|
||||
SB_INTERNAL void StatusStackFinalize(StatusStackRef stack);
|
||||
|
||||
SB_INTERNAL void StatusStackPush(StatusStackRef stack,
|
||||
SBLevel embeddingLevel, SBBidiType overrideStatus, SBBoolean isolateStatus);
|
||||
SB_INTERNAL void StatusStackPop(StatusStackRef stack);
|
||||
SB_INTERNAL void StatusStackSetEmpty(StatusStackRef stack);
|
||||
|
||||
SB_INTERNAL SBLevel StatusStackGetEmbeddingLevel(StatusStackRef stack);
|
||||
SB_INTERNAL SBBidiType StatusStackGetOverrideStatus(StatusStackRef stack);
|
||||
SB_INTERNAL SBBoolean StatusStackGetIsolateStatus(StatusStackRef stack);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user