Add SheenBidi library for better unicode support

This commit is contained in:
Benau 2020-08-24 00:53:04 +08:00
parent bdbf961e76
commit 13db1b83c1
62 changed files with 11869 additions and 1 deletions

View File

@ -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()

View File

@ -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)

View File

@ -0,0 +1,3 @@
add_definitions(-DSB_CONFIG_UNITY)
include_directories("Headers")
add_library(sheenbidi STATIC Source/SheenBidi.c)

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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
View 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
View 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;
}
```

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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;
}
}

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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);
}

View 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

View 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;
}

View 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

View 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;
}

View 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

View 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

View 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

View 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;
};
}

View 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

View 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, &paragraphOffset, &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, &paragraphOffset, &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);
}
}

View 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

View 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

View 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');
}
}

View 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

View 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;
}

View 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

View 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);
}
}

View 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

View 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 = &range;
IsolatingRunForEach(isolatingRun, &context, _SBPrintRangeOperation);
SB_LOG_RANGE(range.offset, range.length);
SB_LOG_DIVIDER(1);
}
#endif

View 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

View 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);
}
}

View 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

View 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);
}
}

View 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

View 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);
}
}

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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;
}

View 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

View 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

View 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;
};
}

View 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