From d42665d9e20d6f188333f22303c3657e2a39fc84 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Wed, 11 Nov 2020 22:17:05 +0300 Subject: [PATCH] added truetype font support into OpenCV, based on STB_truetype --- CMakeLists.txt | 7 + cmake/OpenCVUtils.cmake | 25 + cmake/templates/cvconfig.h.in | 3 + modules/core/include/opencv2/core/cvdef.h | 8 + modules/core/misc/objc/common/Range.h | 8 + modules/core/misc/objc/common/Range.mm | 96 + modules/core/misc/objc/gen_dict.json | 4 +- modules/imgproc/CMakeLists.txt | 41 + modules/imgproc/fonts/Rubik-Italic.ttf.gz | Bin 0 -> 98147 bytes modules/imgproc/fonts/Rubik.ttf.gz | Bin 0 -> 106508 bytes modules/imgproc/fonts/Rubik_OFL.txt | 93 + modules/imgproc/include/opencv2/imgproc.hpp | 107 + .../imgproc/misc/java/test/ImgprocTest.java | 17 +- modules/imgproc/misc/objc/common/FontFace.h | 38 + modules/imgproc/misc/objc/common/FontFace.mm | 43 + modules/imgproc/misc/objc/gen_dict.json | 10 + .../imgproc/misc/objc/test/ImgprocTest.swift | 15 +- modules/imgproc/src/drawing.cpp | 327 +- modules/imgproc/src/drawing_text.cpp | 1547 ++++++ modules/imgproc/src/hershey_fonts.cpp | 3359 ------------ modules/imgproc/src/stb_truetype.cpp | 4864 +++++++++++++++++ modules/imgproc/src/stb_truetype.hpp | 692 +++ modules/imgproc/test/test_drawing.cpp | 181 +- .../opencv2/videoio/legacy/constants_c.h | 13 - platforms/ios/build_framework.py | 6 +- platforms/ios/run_tests.py | 2 +- 26 files changed, 7786 insertions(+), 3720 deletions(-) create mode 100644 modules/core/misc/objc/common/Range.mm create mode 100644 modules/imgproc/fonts/Rubik-Italic.ttf.gz create mode 100644 modules/imgproc/fonts/Rubik.ttf.gz create mode 100644 modules/imgproc/fonts/Rubik_OFL.txt create mode 100644 modules/imgproc/misc/objc/common/FontFace.h create mode 100644 modules/imgproc/misc/objc/common/FontFace.mm create mode 100644 modules/imgproc/src/drawing_text.cpp delete mode 100644 modules/imgproc/src/hershey_fonts.cpp create mode 100644 modules/imgproc/src/stb_truetype.cpp create mode 100644 modules/imgproc/src/stb_truetype.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 746b50f8cb..cd0341aea2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -508,6 +508,9 @@ OCV_OPTION(OPENCV_ENABLE_MEMALIGN "Enable posix_memalign or memalign usage" OCV_OPTION(ENABLE_PYLINT "Add target with Pylint checks" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) ) OCV_OPTION(ENABLE_FLAKE8 "Add target with Python flake8 checker" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) ) +OCV_OPTION(WITH_UNIFONT "Build 'uni' font (WQY MicroHei) into OpenCV" (NOT BUILD_opencv_js) + VERIFY HAVE_UNIFONT) + if(ENABLE_IMPL_COLLECTION) add_definitions(-DCV_COLLECT_IMPL_DATA) endif() @@ -1238,6 +1241,10 @@ if(WITH_VTK OR HAVE_VTK) status(" VTK support:" HAVE_VTK THEN "YES (ver ${VTK_VERSION})" ELSE NO) endif() +if(WITH_UNIFONT OR HAVE_UNIFONT) + status(" Built-in Unicode font:" HAVE_UNIFONT THEN "YES" ELSE "NO") +endif() + # ========================== MEDIA IO ========================== status("") status(" Media I/O: ") diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index 08f7e8ea06..a63861e987 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -1881,3 +1881,28 @@ function(ocv_update_file filepath content) file(WRITE "${filepath}" "${content}") endif() endfunction() + +# adopted from https://gist.github.com/amir-saniyan/de99cee82fa9d8d615bb69f3f53b6004 +function(ocv_blob2hdr blob_filename hdr_filename cpp_variable) + if(EXISTS "${hdr_filename}") + if("${hdr_filename}" IS_NEWER_THAN "${blob_filename}") + return() + endif() + endif() + + file(READ "${blob_filename}" hex_content HEX) + + # repeat [0-9a-f] 32 times + set(pattern "[0-9a-f][0-9a-f][0-9a-f][0-9a-f]") + set(pattern "${pattern}${pattern}") + set(pattern "${pattern}${pattern}") + set(pattern "${pattern}${pattern}") + string(REGEX REPLACE "(${pattern})" "\\1\n" content "${hex_content}") + string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " content "${content}") + string(REGEX REPLACE ", $" "" content "${content}") + + set(array_definition "static const unsigned char ${cpp_variable}[] =\n{\n${content}\n};") + set(source "// Auto generated file.\n${array_definition}\n") + + file(WRITE "${hdr_filename}" "${source}") +endfunction() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index c0f073604b..8cb59c34cd 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -164,4 +164,7 @@ /* Library QR-code decoding */ #cmakedefine HAVE_QUIRC +/* The font "uni" (WQY MicroHei) is available */ +#cmakedefine HAVE_UNIFONT + #endif // OPENCV_CVCONFIG_H_INCLUDED diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 3b273590fb..f7a11a29fd 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -915,6 +915,14 @@ protected: } #endif +/** @brief Constructs the 'fourcc' code, used in video codecs and many other places. + Simply call it with 4 chars like `CV_FOURCC('I', 'Y', 'U', 'V')` +*/ +CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4) +{ + return (c1 & 255) + ((c2 & 255) << 8) + ((c3 & 255) << 16) + ((c4 & 255) << 24); +} + //! @} #ifndef __cplusplus diff --git a/modules/core/misc/objc/common/Range.h b/modules/core/misc/objc/common/Range.h index dd84edf6aa..91e76393d2 100644 --- a/modules/core/misc/objc/common/Range.h +++ b/modules/core/misc/objc/common/Range.h @@ -21,6 +21,10 @@ NS_ASSUME_NONNULL_BEGIN */ CV_EXPORTS @interface Range : NSObject +#ifdef __cplusplus +@property(readonly) cv::Range& nativeRef; +#endif + #pragma mark - Properties @property int start; @@ -90,6 +94,10 @@ CV_EXPORTS @interface Range : NSObject */ - (NSString*)description; +#ifdef __cplusplus ++ (instancetype)fromNative:(cv::Range&)range; +#endif + @end NS_ASSUME_NONNULL_END diff --git a/modules/core/misc/objc/common/Range.mm b/modules/core/misc/objc/common/Range.mm new file mode 100644 index 0000000000..e12a8186ca --- /dev/null +++ b/modules/core/misc/objc/common/Range.mm @@ -0,0 +1,96 @@ +// +// Range.m +// +// Created by Giles Payne on 2019/10/08. +// + +#import "Range.h" + +@implementation Range { + cv::Range native; +} + +- (cv::Range&)nativeRef { + return native; +} + +- (instancetype)init { + return [self initWithStart:0 end: 0]; +} + +- (instancetype)initWithStart:(int)start end:(int)end { + self = [super init]; + if (self != nil) { + self.start = start; + self.end = end; + } + return self; +} + +- (instancetype)initWithVals:(NSArray*)vals { + self = [self init]; + if (self != nil) { + [self set:vals]; + } + return self; +} + +- (void)set:(NSArray*)vals { + self.start = (vals != nil && vals.count > 0) ? vals[0].intValue : 0; + self.end = (vals != nil && vals.count > 1 ) ? vals[1].intValue : 0; +} + +- (int)size { + return [self empty] ? 0 : self.end - self.start; +} + +- (BOOL)empty { + return self.end <= self.start; +} + ++ (Range*)all { + return [[Range alloc] initWithStart:INT_MIN end:INT_MAX]; +} + +- (Range*)intersection:(Range*)r1 { + Range* out = [[Range alloc] initWithStart:MAX(r1.start, self.start) end:MIN(r1.end, self.end)]; + out.end = MAX(out.end, out.start); + return out; +} + +- (Range*)shift:(int)delta { + return [[Range alloc] initWithStart:self.start + delta end:self.end + delta]; +} + +- (Range*)clone { + return [[Range alloc] initWithStart:self.start end:self.end]; +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } else if (![other isKindOfClass:[Range class]]) { + return NO; + } else { + Range* it = (Range*)other; + return self.start == it.start && self.end == it.end; + } +} + +- (NSUInteger)hash { + int prime = 31; + uint32_t result = 1; + result = prime * result + self.start; + result = prime * result + self.end; + return result; +} + ++ (instancetype)fromNative:(cv::Range&)range { + return [[Range alloc] initWithStart:range.start end:range.end]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"Range {%d, %d}", self.start, self.end]; +} + +@end diff --git a/modules/core/misc/objc/gen_dict.json b/modules/core/misc/objc/gen_dict.json index 4cb8133dc4..25521c9326 100644 --- a/modules/core/misc/objc/gen_dict.json +++ b/modules/core/misc/objc/gen_dict.json @@ -147,7 +147,9 @@ "from_cpp": "[Point3i fromNative:%(n)s]" }, "Range": { - "objc_type": "Range*" + "objc_type": "Range*", + "to_cpp": "%(n)s.nativeRef", + "from_cpp": "[Point3i fromNative:%(n)s]" }, "Rect": { "objc_type": "Rect2i*", diff --git a/modules/imgproc/CMakeLists.txt b/modules/imgproc/CMakeLists.txt index 8ee300c320..d85b95ed26 100644 --- a/modules/imgproc/CMakeLists.txt +++ b/modules/imgproc/CMakeLists.txt @@ -12,8 +12,49 @@ ocv_add_dispatched_file(smooth SSE2 SSE4_1 AVX2) ocv_add_dispatched_file(sumpixels SSE2 AVX2 AVX512_SKX) ocv_define_module(imgproc opencv_core WRAP java objc python js) +ocv_module_include_directories(opencv_imgproc ${ZLIB_INCLUDE_DIRS}) + ocv_check_environment_variables(OPENCV_IPP_GAUSSIAN_BLUR) option(OPENCV_IPP_GAUSSIAN_BLUR "Enable IPP optimizations for GaussianBlur (+8Mb in binary size)" OFF) if(OPENCV_IPP_GAUSSIAN_BLUR) ocv_append_source_file_compile_definitions(${CMAKE_CURRENT_SOURCE_DIR}/src/smooth.dispatch.cpp "ENABLE_IPP_GAUSSIAN_BLUR=1") endif() + +set(UNIFONT_MD5 "fb79cf5b4f4c89414f1233f14c2eb273") +set(UNIFONT_NAME "WenQuanYiMicroHei.ttf.gz") +set(UNIFONT_COMMIT "cc7d85179d69a704bee209aa37ce8a657f2f8b34") +set(UNIFONT_URL "https://raw.githubusercontent.com/vpisarev/opencv_3rdparty/${UNIFONT_COMMIT}/") + +unset(HAVE_UNIFONT) +unset(HAVE_UNIFONT CACHE) + +if (WITH_UNIFONT) + ocv_download(FILENAME ${UNIFONT_NAME} + HASH ${UNIFONT_MD5} + URL + "${OPENCV_UNIFONT_URL}" + "${UNIFONT_URL}" + DESTINATION_DIR "${CMAKE_CURRENT_BINARY_DIR}" + ID UNIFONT + STATUS res + RELATIVE_URL) + + if (res) + message(STATUS "Unicode font has been downloaded successfully.") + set(HAVE_UNIFONT ON CACHE INTERNAL "") + else() + message(STATUS "Unicode font download failed. Turning it off.") + set(HAVE_UNIFONT OFF CACHE INTERNAL "") + endif() +else() + set(HAVE_UNIFONT OFF CACHE INTERNAL "") +endif() + +ocv_blob2hdr("${CMAKE_CURRENT_SOURCE_DIR}/fonts/Rubik.ttf.gz" "${CMAKE_CURRENT_BINARY_DIR}/builtin_font_sans.h" OcvBuiltinFontSans) +ocv_blob2hdr("${CMAKE_CURRENT_SOURCE_DIR}/fonts/Rubik-Italic.ttf.gz" "${CMAKE_CURRENT_BINARY_DIR}/builtin_font_italic.h" OcvBuiltinFontItalic) +if (HAVE_UNIFONT) + ocv_blob2hdr("${CMAKE_CURRENT_BINARY_DIR}/${UNIFONT_NAME}" "${CMAKE_CURRENT_BINARY_DIR}/builtin_font_uni.h" OcvBuiltinFontUni) +endif() +include_directories("${CMAKE_CURRENT_BINARY_DIR}") +ocv_target_link_libraries(${the_module} LINK_PRIVATE ${ZLIB_LIBRARIES}) +ocv_install_3rdparty_licenses(fonts fonts/Rubik_OFL.txt) diff --git a/modules/imgproc/fonts/Rubik-Italic.ttf.gz b/modules/imgproc/fonts/Rubik-Italic.ttf.gz new file mode 100644 index 0000000000000000000000000000000000000000..d81e60a069934135d2dae7c1307118f616dfc19f GIT binary patch literal 98147 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 cHg1r}=8lJ7gVf;?#K( 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
aU@Q=PE6`HFYxEt?%$dotPoF+6 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 literal 0 HcmV?d00001 diff --git a/modules/imgproc/fonts/Rubik.ttf.gz b/modules/imgproc/fonts/Rubik.ttf.gz new file mode 100644 index 0000000000000000000000000000000000000000..a40bc52e7726d24b556a53bef571da8f1b1795b4 GIT binary patch literal 106508 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

{$g!0!+PCXe!7MmV!{+i`?t%0DPXB(K%=-nsoz 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 z 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

juvm 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∾Ytw$lkw(viowRC$2fei$0efiNI!duk$$${ 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

UtY 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%0A@Wy4Jp(fU8D68)@!Zie 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

(R)HF;9e-;0yExy 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 params); + CV_WRAP bool getInstance(CV_OUT std::vector& params) const; + + struct Impl; + + Impl* operator -> (); + static bool getBuiltinFontData(const String& fontName, const uchar*& data, size_t& datasize); + +protected: + Ptr impl; +}; + +/** @brief Defines various put text flags */ +enum PutTextFlags +{ + PUT_TEXT_ALIGN_LEFT=0, // put the text to the right from the origin + PUT_TEXT_ALIGN_CENTER=1,// center the text at the origin; not implemented yet + PUT_TEXT_ALIGN_RIGHT=2, // put the text to the left of the origin + PUT_TEXT_ALIGN_MASK=3, // alignment mask + PUT_TEXT_ORIGIN_TL=0, + PUT_TEXT_ORIGIN_BL=32, // treat the target image as having bottom-left origin + PUT_TEXT_WRAP=128 // wrap text to the next line if it does not fit +}; + +/** @brief Draws a text string using specified font. + +The function cv::putText renders the specified text string in the image. Symbols that cannot be rendered +using the specified font are replaced by question marks. See #getTextSize for a text rendering code +example. The function returns the coordinates in pixels from where the text can be continued. + +@param img Image. +@param text Text string to be drawn. +@param org Bottom-left corner of the first character of the printed text + (see PUT_TEXT_ALIGN_... though) +@param color Text color. +@param fface The font to use for the text +@param size Font size in pixels (by default) or pts +@param weight Font weight, 100..1000, + where 100 is "thin" font, 400 is "regular", + 600 is "semibold", 800 is "bold" and beyond that is "black". + The parameter is ignored if the font is not a variable font or if it does not provide variation along 'wght' axis. + If the weight is 0, then the weight, currently set via setInstance(), is used. +@param flags Various flags, see PUT_TEXT_... +@param wrap The optional text wrapping range: + In the case of left-to-right (LTR) text if the printed character would cross wrap.end boundary, + the "cursor" is set to wrap.start. + In the case of right-to-left (RTL) text it's vice versa. + If the parameters is not set, + [org.x, img.cols] is used for LTR text and + [0, org.x] is for RTL one. +*/ +CV_EXPORTS_W Point putText( InputOutputArray img, const String& text, Point org, + Scalar color, FontFace& fface, int size, int weight=0, + PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range() ); + +/** @brief Calculates the bounding rect for the text + +The function cv::getTextSize calculates and returns the size of a box that contains the specified text. +That is, the following code renders some text, the tight box surrounding it, and the baseline: : + +@param imgsize Size of the target image, can be empty +@param text Text string to be drawn. +@param org Bottom-left corner of the first character of the printed text + (see PUT_TEXT_ALIGN_... though) +@param fface The font to use for the text +@param size Font size in pixels (by default) or pts +@param weight Font weight, 100..1000, + where 100 is "thin" font, 400 is "regular", + 600 is "semibold", 800 is "bold" and beyond that is "black". + The default weight means "400" for variable-weight fonts or + whatever "default" weight the used font provides. +@param flags Various flags, see PUT_TEXT_... +@param wrap The optional text wrapping range; see #putText. +*/ +CV_EXPORTS_W Rect getTextSize( Size imgsize, const String& text, Point org, + FontFace& fface, int size, int weight=0, + PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range() ); + /** @brief Line iterator The class is used to iterate over all the pixels on the raster line diff --git a/modules/imgproc/misc/java/test/ImgprocTest.java b/modules/imgproc/misc/java/test/ImgprocTest.java index 656a57c1ee..537f871331 100644 --- a/modules/imgproc/misc/java/test/ImgprocTest.java +++ b/modules/imgproc/misc/java/test/ImgprocTest.java @@ -1814,13 +1814,14 @@ public class ImgprocTest extends OpenCVTestCase { double fontScale = 2; int thickness = 3; int baseLine[] = new int[1]; + double EPS=5.0; Imgproc.getTextSize(text, Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, null); Size res = Imgproc.getTextSize(text, Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, baseLine); - assertEquals(543.0, res.width); - assertEquals(44.0, res.height); - assertEquals(20, baseLine[0]); + assertEquals(494.0, res.width, EPS); + assertEquals(51.0, res.height, EPS); + assertEquals(10, baseLine[0], 2.0); } public void testCircleMatPointIntScalar() { @@ -2032,7 +2033,7 @@ public class ImgprocTest extends OpenCVTestCase { public void testPutTextMatStringPointIntDoubleScalar() { String text = "Hello World"; - Size labelSize = new Size(175, 22); + Size labelSize = new Size(170, 23); Mat img = new Mat(20 + (int) labelSize.height, 20 + (int) labelSize.width, CvType.CV_8U, colorBlack); Point origin = new Point(10, labelSize.height + 10); @@ -2040,13 +2041,13 @@ public class ImgprocTest extends OpenCVTestCase { assertTrue(Core.countNonZero(img) > 0); // check that border is not corrupted - Imgproc.rectangle(img, new Point(11, 11), new Point(labelSize.width + 10, labelSize.height + 10), colorBlack, Imgproc.FILLED); + Imgproc.rectangle(img, new Point(10, 10), new Point(labelSize.width + 10, labelSize.height + 10), colorBlack, Imgproc.FILLED); assertEquals(0, Core.countNonZero(img)); } public void testPutTextMatStringPointIntDoubleScalarInt() { String text = "Hello World"; - Size labelSize = new Size(176, 22); + Size labelSize = new Size(170, 23); Mat img = new Mat(20 + (int) labelSize.height, 20 + (int) labelSize.width, CvType.CV_8U, colorBlack); Point origin = new Point(10, labelSize.height + 10); @@ -2060,7 +2061,7 @@ public class ImgprocTest extends OpenCVTestCase { public void testPutTextMatStringPointIntDoubleScalarIntIntBoolean() { String text = "Hello World"; - Size labelSize = new Size(175, 22); + Size labelSize = new Size(170, 23); Mat img = new Mat(20 + (int) labelSize.height, 20 + (int) labelSize.width, CvType.CV_8U, colorBlack); Point origin = new Point(10, 10); @@ -2069,7 +2070,7 @@ public class ImgprocTest extends OpenCVTestCase { assertTrue(Core.countNonZero(img) > 0); // check that border is not corrupted - Imgproc.rectangle(img, new Point(10, 10), new Point(labelSize.width + 9, labelSize.height + 9), colorBlack, Imgproc.FILLED); + Imgproc.rectangle(img, new Point(10, 10), new Point(labelSize.width + 10, labelSize.height + 10), colorBlack, Imgproc.FILLED); assertEquals(0, Core.countNonZero(img)); } } diff --git a/modules/imgproc/misc/objc/common/FontFace.h b/modules/imgproc/misc/objc/common/FontFace.h new file mode 100644 index 0000000000..a3abe081c8 --- /dev/null +++ b/modules/imgproc/misc/objc/common/FontFace.h @@ -0,0 +1,38 @@ +// +// FontFace.h +// +// Created by VP in 2020 +// + +#pragma once + +#ifdef __cplusplus +#import "opencv.hpp" +#else +#define CV_EXPORTS +#endif + +#import + +NS_ASSUME_NONNULL_BEGIN + +CV_EXPORTS @interface FontFace : NSObject + +@property(readonly) NSString* name; + +#ifdef __cplusplus +@property(readonly) cv::FontFace& nativeRef; +#endif + +-(instancetype)initWith:(const NSString*)name; +-(instancetype)init; + +#ifdef __cplusplus ++(instancetype)fromNative:(cv::FontFace&)fface; +#endif + +-(NSString *)description; + +@end + +NS_ASSUME_NONNULL_END diff --git a/modules/imgproc/misc/objc/common/FontFace.mm b/modules/imgproc/misc/objc/common/FontFace.mm new file mode 100644 index 0000000000..1045d0d206 --- /dev/null +++ b/modules/imgproc/misc/objc/common/FontFace.mm @@ -0,0 +1,43 @@ +// +// FontFace.mm +// +// Created by VP in 2020. +// + +#import "FontFace.h" + +@implementation FontFace { + cv::FontFace native; +} + +-(cv::FontFace&)nativeRef { + return native; +} + +- (NSString*)name { + return [NSString stringWithUTF8String:native.getName().c_str()]; +} + +-(instancetype)init { + return [super init]; +} + +-(instancetype)initWith:(NSString*)name { + self = [super init]; + if (self) { + self.nativeRef.set(std::string(name.UTF8String)); + } + return self; +} + ++(instancetype)fromNative:(cv::FontFace&)fface { + FontFace* ff = [[FontFace alloc] init]; + ff.nativeRef = fface; + return ff; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FontFace [name=%s]", self.nativeRef.getName().c_str()]; +} + +@end diff --git a/modules/imgproc/misc/objc/gen_dict.json b/modules/imgproc/misc/objc/gen_dict.json index 043baa5a5b..e2cac520fc 100644 --- a/modules/imgproc/misc/objc/gen_dict.json +++ b/modules/imgproc/misc/objc/gen_dict.json @@ -1,4 +1,7 @@ { + "class_ignore_list": [ + "FontFace" + ], "enum_ignore_list" : [ "MorphShapes_c", "SmoothMethod_c" @@ -125,5 +128,12 @@ "Subdiv2D" : { "(void)insert:(NSArray*)ptvec" : { "insert" : {"name" : "insertVector"} } } + }, + "type_dict": { + "FontFace": { + "objc_type": "FontFace*", + "to_cpp": "%(n)s.nativeRef", + "from_cpp": "[FontFace fromNative:%(n)s]" + } } } diff --git a/modules/imgproc/misc/objc/test/ImgprocTest.swift b/modules/imgproc/misc/objc/test/ImgprocTest.swift index 72432ceb4a..75675e89bd 100644 --- a/modules/imgproc/misc/objc/test/ImgprocTest.swift +++ b/modules/imgproc/misc/objc/test/ImgprocTest.swift @@ -1490,13 +1490,14 @@ class ImgprocTest: OpenCVTestCase { let fontScale:Int32 = 2 let thickness:Int32 = 3 var baseLine:Int32 = 0 + let EPS = 0.0 Imgproc.getTextSize(text: text, fontFace: .FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale: Double(fontScale), thickness: thickness, baseLine: &baseLine) let res = Imgproc.getTextSize(text: text, fontFace: .FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale: Double(fontScale), thickness: thickness, baseLine: &baseLine) - XCTAssertEqual(431, res.width) - XCTAssertEqual(44, res.height) - XCTAssertEqual(20, baseLine) + XCTAssertEqual(454, res.width, accuracy:EPS) + XCTAssertEqual(51, res.height, accuracy:EPS) + XCTAssertEqual(10, baseLine, accuracy:2.0) } func testCircleMatPointIntScalar() { @@ -1700,7 +1701,7 @@ class ImgprocTest: OpenCVTestCase { func testPutTextMatStringPointIntDoubleScalar() { let text = "Hello World" - let labelSize = Size(width: 175, height: 22) + let labelSize = Size(width: 170, height: 23) let img = Mat(rows: 20 + labelSize.height, cols: 20 + labelSize.width, type: CvType.CV_8U, scalar: colorBlack) let origin = Point(x: 10, y: labelSize.height + 10) @@ -1708,13 +1709,13 @@ class ImgprocTest: OpenCVTestCase { XCTAssert(Core.countNonZero(src: img) > 0) // check that border is not corrupted - Imgproc.rectangle(img: img, pt1: Point(x: 11, y: 11), pt2: Point(x: labelSize.width + 10, y: labelSize.height + 10), color: colorBlack, thickness: Core.FILLED) + Imgproc.rectangle(img: img, pt1: Point(x: 10, y: 10), pt2: Point(x: labelSize.width + 10, y: labelSize.height + 10), color: colorBlack, thickness: Core.FILLED) XCTAssertEqual(0, Core.countNonZero(src: img)) } func testPutTextMatStringPointIntDoubleScalarInt() { let text = "Hello World" - let labelSize = Size(width: 176, height: 22) + let labelSize = Size(width: 170, height: 23) let img = Mat(rows: 20 + labelSize.height, cols: 20 + labelSize.width, type: CvType.CV_8U, scalar: colorBlack) let origin = Point(x: 10, y: labelSize.height + 10) @@ -1728,7 +1729,7 @@ class ImgprocTest: OpenCVTestCase { func testPutTextMatStringPointIntDoubleScalarIntIntBoolean() { let text = "Hello World" - let labelSize = Size(width: 175, height: 22) + let labelSize = Size(width: 170, height: 23) let img = Mat(rows: 20 + labelSize.height, cols: 20 + labelSize.width, type: CvType.CV_8U, scalar: colorBlack) let origin = Point(x: 10, y: 10) diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index ae8c6209e8..2a3e717973 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -2037,331 +2037,6 @@ void polylines( InputOutputArray _img, const Point* const* pts, const int* npts, } } - -enum { FONT_SIZE_SHIFT=8, FONT_ITALIC_ALPHA=(1 << 8), - FONT_ITALIC_DIGIT=(2 << 8), FONT_ITALIC_PUNCT=(4 << 8), - FONT_ITALIC_BRACES=(8 << 8), FONT_HAVE_GREEK=(16 << 8), - FONT_HAVE_CYRILLIC=(32 << 8) }; - -static const int HersheyPlain[] = { -(5 + 4*16) + FONT_HAVE_GREEK, -199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220, -200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192, -215, 190, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 193, 84, -194, 85, 86, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, -112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, -195, 223, 196, 88 }; - -static const int HersheyPlainItalic[] = { -(5 + 4*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK, -199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220, -200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192, -215, 190, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 193, 84, -194, 85, 86, 87, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, -162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, -195, 223, 196, 88 }; - -static const int HersheyComplexSmall[] = { -(6 + 7*16) + FONT_HAVE_GREEK, -1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220, -1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 2213, 1241, 1238, 1242, -1215, 1273, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, -1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1223, 1084, -1224, 1247, 586, 1249, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, -1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, -1225, 1229, 1226, 1246 }; - -static const int HersheyComplexSmallItalic[] = { -(6 + 7*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK, -1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220, -1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 1213, 1241, 1238, 1242, -1215, 1273, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, -1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1223, 1084, -1224, 1247, 586, 1249, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, -1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, -1225, 1229, 1226, 1246 }; - -static const int HersheySimplex[] = { -(9 + 12*16) + FONT_HAVE_GREEK, -2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720, -700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692, -715, 690, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, -514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 693, 584, -694, 2247, 586, 2249, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, -612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, -695, 723, 696, 2246 }; - -static const int HersheyDuplex[] = { -(9 + 12*16) + FONT_HAVE_GREEK, -2199, 2714, 2728, 2732, 2719, 2733, 2718, 2727, 2721, 2722, 2723, 2725, 2711, 2724, 2710, 2720, -2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2712, 2713, 2730, 2726, 2731, -2715, 2734, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, -2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2223, 2084, -2224, 2247, 587, 2249, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, -2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, -2225, 2229, 2226, 2246 }; - -static const int HersheyComplex[] = { -(9 + 12*16) + FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC, -2199, 2214, 2217, 2275, 2274, 2271, 2272, 2216, 2221, 2222, 2219, 2232, 2211, 2231, 2210, 2220, -2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2212, 2213, 2241, 2238, 2242, -2215, 2273, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, -2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2223, 2084, -2224, 2247, 587, 2249, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, -2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, -2225, 2229, 2226, 2246, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, -2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, -2827, 2828, 2829, 2830, 2831, 2832, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, -2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, -2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932}; - -static const int HersheyComplexItalic[] = { -(9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT + -FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC, -2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220, -2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242, -2765, 2273, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, -2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2223, 2084, -2224, 2247, 587, 2249, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, -2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, -2225, 2229, 2226, 2246 }; - -static const int HersheyTriplex[] = { -(9 + 12*16) + FONT_HAVE_GREEK, -2199, 3214, 3228, 3232, 3219, 3233, 3218, 3227, 3221, 3222, 3223, 3225, 3211, 3224, 3210, 3220, -3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3212, 3213, 3230, 3226, 3231, -3215, 3234, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, -2014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 2223, 2084, -2224, 2247, 587, 2249, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, -3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, -2225, 2229, 2226, 2246 }; - -static const int HersheyTriplexItalic[] = { -(9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + -FONT_ITALIC_PUNCT + FONT_HAVE_GREEK, -2199, 3264, 3278, 3282, 3269, 3233, 3268, 3277, 3271, 3272, 3223, 3225, 3261, 3224, 3260, 3270, -3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3262, 3263, 3230, 3226, 3231, -3265, 3234, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, -2064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 2223, 2084, -2224, 2247, 587, 2249, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, -3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, -2225, 2229, 2226, 2246 }; - -static const int HersheyScriptSimplex[] = { -(9 + 12*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK, -2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720, -700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692, -715, 690, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, -564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 693, 584, -694, 2247, 586, 2249, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, -662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, -695, 723, 696, 2246 }; - -static const int HersheyScriptComplex[] = { -(9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT + FONT_HAVE_GREEK, -2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220, -2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242, -2215, 2273, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, -2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2223, 2084, -2224, 2247, 586, 2249, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, -2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, -2225, 2229, 2226, 2246 }; - - -static const int* getFontData(int fontFace) -{ - bool isItalic = (fontFace & FONT_ITALIC) != 0; - const int* ascii = 0; - - switch( fontFace & 15 ) - { - case FONT_HERSHEY_SIMPLEX: - ascii = HersheySimplex; - break; - case FONT_HERSHEY_PLAIN: - ascii = !isItalic ? HersheyPlain : HersheyPlainItalic; - break; - case FONT_HERSHEY_DUPLEX: - ascii = HersheyDuplex; - break; - case FONT_HERSHEY_COMPLEX: - ascii = !isItalic ? HersheyComplex : HersheyComplexItalic; - break; - case FONT_HERSHEY_TRIPLEX: - ascii = !isItalic ? HersheyTriplex : HersheyTriplexItalic; - break; - case FONT_HERSHEY_COMPLEX_SMALL: - ascii = !isItalic ? HersheyComplexSmall : HersheyComplexSmallItalic; - break; - case FONT_HERSHEY_SCRIPT_SIMPLEX: - ascii = HersheyScriptSimplex; - break; - case FONT_HERSHEY_SCRIPT_COMPLEX: - ascii = HersheyScriptComplex; - break; - default: - CV_Error( CV_StsOutOfRange, "Unknown font type" ); - } - return ascii; -} - -inline void readCheck(int &c, int &i, const String &text, int fontFace) -{ - - int leftBoundary = ' ', rightBoundary = 127; - - if(c >= 0x80 && fontFace == FONT_HERSHEY_COMPLEX) - { - if(c == 0xD0 && (uchar)text[i + 1] >= 0x90 && (uchar)text[i + 1] <= 0xBF) - { - c = (uchar)text[++i] - 17; - leftBoundary = 127; - rightBoundary = 175; - } - else if(c == 0xD1 && (uchar)text[i + 1] >= 0x80 && (uchar)text[i + 1] <= 0x8F) - { - c = (uchar)text[++i] + 47; - leftBoundary = 175; - rightBoundary = 191; - } - else - { - if(c >= 0xC0 && text[i+1] != 0) //2 bytes utf - i++; - - if(c >= 0xE0 && text[i+1] != 0) //3 bytes utf - i++; - - if(c >= 0xF0 && text[i+1] != 0) //4 bytes utf - i++; - - if(c >= 0xF8 && text[i+1] != 0) //5 bytes utf - i++; - - if(c >= 0xFC && text[i+1] != 0) //6 bytes utf - i++; - - c = '?'; - } - } - - if(c >= rightBoundary || c < leftBoundary) - c = '?'; -} - -extern const char* g_HersheyGlyphs[]; - -void putText( InputOutputArray _img, const String& text, Point org, - int fontFace, double fontScale, Scalar color, - int thickness, int line_type, bool bottomLeftOrigin ) - -{ - CV_INSTRUMENT_REGION(); - - if ( text.empty() ) - { - return; - } - Mat img = _img.getMat(); - const int* ascii = getFontData(fontFace); - - double buf[4]; - scalarToRawData(color, buf, img.type(), 0); - - int base_line = -(ascii[0] & 15); - int hscale = cvRound(fontScale*XY_ONE), vscale = hscale; - - if( line_type == CV_AA && img.depth() != CV_8U ) - line_type = 8; - - if( bottomLeftOrigin ) - vscale = -vscale; - - int64 view_x = (int64)org.x << XY_SHIFT; - int64 view_y = ((int64)org.y << XY_SHIFT) + base_line*vscale; - std::vector pts; - pts.reserve(1 << 10); - const char **faces = cv::g_HersheyGlyphs; - - for( int i = 0; i < (int)text.size(); i++ ) - { - int c = (uchar)text[i]; - Point2l p; - - readCheck(c, i, text, fontFace); - - const char* ptr = faces[ascii[(c-' ')+1]]; - p.x = (uchar)ptr[0] - 'R'; - p.y = (uchar)ptr[1] - 'R'; - int64 dx = p.y*hscale; - view_x -= p.x*hscale; - pts.resize(0); - - for( ptr += 2;; ) - { - if( *ptr == ' ' || !*ptr ) - { - if( pts.size() > 1 ) - PolyLine( img, &pts[0], (int)pts.size(), false, buf, thickness, line_type, XY_SHIFT ); - if( !*ptr++ ) - break; - pts.resize(0); - } - else - { - p.x = (uchar)ptr[0] - 'R'; - p.y = (uchar)ptr[1] - 'R'; - ptr += 2; - pts.push_back(Point2l(p.x*hscale + view_x, p.y*vscale + view_y)); - } - } - view_x += dx; - } -} - -Size getTextSize( const String& text, int fontFace, double fontScale, int thickness, int* _base_line) -{ - Size size; - double view_x = 0; - const char **faces = cv::g_HersheyGlyphs; - const int* ascii = getFontData(fontFace); - - int base_line = (ascii[0] & 15); - int cap_line = (ascii[0] >> 4) & 15; - size.height = cvRound((cap_line + base_line)*fontScale + (thickness+1)/2); - - for( int i = 0; i < (int)text.size(); i++ ) - { - int c = (uchar)text[i]; - Point p; - - readCheck(c, i, text, fontFace); - - const char* ptr = faces[ascii[(c-' ')+1]]; - p.x = (uchar)ptr[0] - 'R'; - p.y = (uchar)ptr[1] - 'R'; - view_x += (p.y - p.x)*fontScale; - } - - size.width = cvRound(view_x + thickness); - if( _base_line ) - *_base_line = cvRound(base_line*fontScale + thickness*0.5); - return size; -} - -double getFontScaleFromHeight(const int fontFace, const int pixelHeight, const int thickness) -{ - // By https://stackoverflow.com/a/27898487/1531708 - const int* ascii = getFontData(fontFace); - - int base_line = (ascii[0] & 15); - int cap_line = (ascii[0] >> 4) & 15; - - return static_cast(pixelHeight - static_cast((thickness + 1)) / 2.0) / static_cast(cap_line + base_line); -} - } void cv::fillConvexPoly(InputOutputArray img, InputArray _points, @@ -2861,7 +2536,7 @@ cvInitFont( CvFont *font, int font_face, double hscale, double vscale, { CV_Assert( font != 0 && hscale > 0 && vscale > 0 && thickness >= 0 ); - font->ascii = cv::getFontData(font_face); + font->ascii = 0; font->font_face = font_face; font->hscale = (float)hscale; font->vscale = (float)vscale; diff --git a/modules/imgproc/src/drawing_text.cpp b/modules/imgproc/src/drawing_text.cpp new file mode 100644 index 0000000000..8202ed63f3 --- /dev/null +++ b/modules/imgproc/src/drawing_text.cpp @@ -0,0 +1,1547 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#include "precomp.hpp" + +#include +#include +#include +#include "zlib.h" +#include "stb_truetype.hpp" + +namespace cv +{ + +#include "builtin_font_sans.h" +#include "builtin_font_italic.h" +#ifdef HAVE_UNIFONT +#include "builtin_font_uni.h" +#endif + +typedef stbtt_fontinfo font_t; + +/////////////////////// Some temporary stub for Harfbuzz API ///////////////////////// + +#ifndef HAVE_HARFBUZZ + +typedef struct hb_glyph_position_t +{ + int x_advance; + int y_advance; + int x_offset; + int y_offset; +} hb_glyph_position_t; + +typedef struct hb_font_t +{ + int font_data; +} hb_font_t; + +typedef struct hb_buffer_t +{ + int buf_data; +} hb_buffer_t; + +typedef enum hb_direction_t +{ + HB_DIRECTION_INVALID = 0, + HB_DIRECTION_LTR = 1, + HB_DIRECTION_RTL = 2 +} hb_direction_t; + +typedef enum hb_script_t +{ + HB_SCRIPT_INVALID = -1, + HB_SCRIPT_UNKNOWN = 0, + HB_SCRIPT_COMMON = 1, + HB_SCRIPT_INHERITED, + HB_SCRIPT_LATIN, + HB_SCRIPT_CYRILLIC, + HB_SCRIPT_GREEK, + + HB_SCRIPT_HAN, + HB_SCRIPT_HIRAGANA, + + HB_SCRIPT_ARABIC, + HB_SCRIPT_HEBREW, + HB_SCRIPT_SYRIAC, + HB_SCRIPT_THAANA +} hb_script_t; + +typedef struct hb_unicode_funcs_t +{ + int funcs_data; +} hb_unicode_funcs_t; + +static hb_buffer_t* hb_buffer_create() { return 0; } +static void hb_buffer_destroy(hb_buffer_t*) {} +static void hb_buffer_guess_segment_properties(hb_buffer_t *) {} +static hb_unicode_funcs_t* hb_unicode_funcs_get_default() { return 0; } + +#endif + +////////////////////////////////////////////////////////////////////////////////////// + +typedef struct BuiltinFontData +{ + const uchar* gzdata; + size_t size; + const char* name; + double sf; + bool italic; +} BuiltinFontData; + +enum +{ + BUILTIN_FONTS_NUM = 2 +#ifdef HAVE_UNIFONT + +1 +#endif +}; + +static BuiltinFontData builtinFontData[BUILTIN_FONTS_NUM+1] = +{ + {OcvBuiltinFontSans, sizeof(OcvBuiltinFontSans), "sans", 1.0, false}, + {OcvBuiltinFontItalic, sizeof(OcvBuiltinFontItalic), "italic", 1.0, true}, +#ifdef HAVE_UNIFONT + {OcvBuiltinFontUni, sizeof(OcvBuiltinFontUni), "uni", 1.0, true}, +#endif + {0, 0, 0, 0.0, false} +}; + +static bool inflate(const void* src, size_t srclen, std::vector& dst) +{ + std::vector newdst((size_t)(srclen*2.5)); + std::swap(dst, newdst); // make sure we deallocated all the unused space that would be wasted otherwise + for(int attempts = 0; attempts < 5; attempts++) + { + z_stream strm = {}; + strm.total_in = strm.avail_in = (uInt)srclen; + strm.total_out = strm.avail_out = (uInt)dst.size(); + strm.next_in = (Bytef*)src; + strm.next_out = (Bytef*)&dst[0]; + + int err = inflateInit2(&strm, (15 + 32)); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib + if (err == Z_OK) + { + err = inflate(&strm, Z_FINISH); + inflateEnd(&strm); + if (err == Z_STREAM_END) + { + dst.resize((size_t)strm.total_out); + return true; + } + else + dst.resize(dst.size()*3/2); + } + else + { + inflateEnd(&strm); + return false; + } + } + return false; +} + +struct FontFace::Impl { + Impl() + { + initParams(); + ttface = 0; + hb_font = 0; + scalefactor = 1.0; + italic = false; + } + + ~Impl() + { + deleteFont(); + } + + void deleteFont() + { + stbtt_ReleaseFont(&ttface); + currname.clear(); + initParams(); + } + + void initParams() + { + currweight = -1; + currsize = -1; + scale = 1; + } + + bool setStd(const BuiltinFontData& fontdata) + { + if(fontdata.size <= 1) + return false; + if(ttface == 0 || currname != fontdata.name) + { + deleteFont(); + if(!inflate(fontdata.gzdata, fontdata.size, fontbuf)) + return false; + ttface = stbtt_CreateFont(&fontbuf[0], (unsigned)fontbuf.size(), stbtt_GetFontOffsetForIndex(&fontbuf[0],0)); + if (!ttface) + return false; + } + currname = fontdata.name; + scalefactor = fontdata.sf; + italic = fontdata.italic; + initParams(); + return true; + } + + bool set(const String& fontname) + { + CV_Assert(!fontname.empty()); + + if(ttface != 0 && fontname == currname) + return true; + + deleteFont(); + + const char* fntname = fontname.c_str(); + size_t fntnamelen = fontname.size(); + FILE* f = fopen(fntname, "rb"); + if (!f) + return false; + fseek(f, 0, SEEK_END); + long sz0 = ftell(f), sz1 = 0; + std::vector srcdata(sz0); + if (sz0 > 0) + { + fseek(f, 0, SEEK_SET); + sz1 = (long)fread(&srcdata[0], 1, sz0, f); + } + fclose(f); + if (sz0 == 0 || sz1 != sz0) + return false; + if (fntnamelen > 3 && strcmp(fntname + fntnamelen - 3, ".gz") == 0) + { + if (!inflate(&srcdata[0], srcdata.size(), fontbuf)) + return false; + } + else + { + fontbuf.resize(srcdata.size()); + std::copy(srcdata.begin(), srcdata.end(), fontbuf.begin()); + } + ttface = stbtt_CreateFont(&fontbuf[0], (unsigned)fontbuf.size(), stbtt_GetFontOffsetForIndex(&fontbuf[0],0)); + if (!ttface) + return false; + currname = fontname; + initParams(); + return true; + } + + bool setParams(int size, int weight) + { + if (ttface == 0) + return false; + if (std::abs(size - currsize) < 1e-3 && + (weight == currweight || weight == 0)) + return true; + + if (weight != currweight && weight != 0) { + int params[] = {STBTT_FOURCC('w','g','h','t'), weight}; + if (!stbtt_SetInstance(ttface, params, 1, 0)) + return false; + currweight = weight; + } + + if(size != currsize) + scale = stbtt_ScaleForPixelHeightNoDesc(ttface, (float)size); + + currsize = size; + return true; + } + + String currname; + double scalefactor; + bool italic; + int currsize; + int currweight; + float scale; + stbtt_fontinfo* ttface; + hb_font_t* hb_font; + std::vector fontbuf; +}; + +struct GlyphCacheKey +{ + GlyphCacheKey() + { + ttface = 0; + size = 0; + weight = 0; + } + GlyphCacheKey(font_t* ttface_, int index_, double size_, int weight_, float scale_) + { + ttface = ttface_; + glyph_index = index_; + size = cvRound(size_*256); + weight = weight_; + scale = scale_; + } + + font_t* ttface; + int glyph_index; + int size; + int weight; + float scale; +}; + +static bool operator == (const GlyphCacheKey& k1, const GlyphCacheKey& k2) +{ + return k1.ttface == k2.ttface && k1.glyph_index == k2.glyph_index && + k1.size == k2.size && k1.weight == k2.weight && k1.scale == k2.scale; +} + +static size_t hash_seq(const size_t* hashvals, size_t n) +{ + size_t h = (size_t)-1; + const int hsz = (int)(sizeof(h)*8); + for( size_t i = 0; i < n; i++ ) + { + h = (h >> 5) ^ (h << (hsz - 5)) ^ hashvals[i]; + } + return h; +} + +struct GlyphCacheHash +{ + size_t operator()(const GlyphCacheKey& key) const noexcept + { + size_t hs[] = {(size_t)(void*)key.ttface, (size_t)key.glyph_index, + (size_t)key.size, (size_t)key.weight}; // do not include scale, because it's completely defined by size + return hash_seq(hs, sizeof(hs)/sizeof(hs[0])); + } +}; + +struct GlyphCacheVal +{ + GlyphCacheVal() + { + crc = 0; + width = height = linegap = ascent = horiBearingX = horiBearingY = 0; + } + + std::vector rlebuf; + Rect bbox; + unsigned crc; + int width; + int height; + Point advance; + int linegap, ascent; + int horiBearingX; + int horiBearingY; +}; + +typedef std::pair GlyphCacheEntry; +typedef std::list::iterator GlyphCacheEntryIt; + +struct TextSegment +{ + TextSegment() + { + ttface = 0; + fontidx = 0; + start = end = 0; + script = HB_SCRIPT_UNKNOWN; + dir = HB_DIRECTION_LTR; + } + TextSegment(font_t* ttface_, int fontidx_, int start_, int end_, hb_script_t script_, hb_direction_t dir_) + { + ttface = ttface_; + fontidx = fontidx_; + start = start_; + end = end_; + script = script_; + dir = dir_; + } + font_t* ttface; + int fontidx; + int start, end; + hb_script_t script; + hb_direction_t dir; +}; + +struct FontGlyph +{ + FontGlyph() { ttface = 0; index = -1; scale = 1.f; } + FontGlyph(font_t* ttface_, int glyph_index_, const hb_glyph_position_t& pos_, float scale_) + { + ttface = ttface_; + index = glyph_index_; + pos = pos_; + scale = scale_; + } + font_t* ttface; + int index; + float scale; + hb_glyph_position_t pos; +}; + + +class FontRenderEngine +{ +public: + enum { MAX_CACHED_GLYPH_SIZE = 128, MAX_CACHE_SIZE=2048 }; + FontRenderEngine() + { + hb_buf = hb_buffer_create(); + hb_buffer_guess_segment_properties(hb_buf); + hb_uni_funcs = hb_unicode_funcs_get_default(); + max_cache_size = (size_t)MAX_CACHE_SIZE; + glyph_buf = 0; + glyph_bufsz = 0; + } + + ~FontRenderEngine() + { + hb_buffer_destroy(hb_buf); + for(int i = 0; i < BUILTIN_FONTS_NUM; i++) + builtin_ffaces[i] = FontFace(); + if (glyph_buf) + free(glyph_buf); + glyph_buf = 0; + glyph_bufsz = 0; + } + + void addToCache(const GlyphCacheKey& key, const GlyphCacheVal& val) + { + if(glyph_cache.size() == max_cache_size) + { + GlyphCacheEntryIt last = all_cached.end(); + --last; + glyph_cache.erase(last->first); + all_cached.pop_back(); + } + + all_cached.push_front(std::make_pair(key, val)); + GlyphCacheEntryIt first = all_cached.begin(); + glyph_cache.insert(std::make_pair(first->first, first)); + } + + GlyphCacheVal* findCachedGlyph(const GlyphCacheKey& key) + { + auto it = glyph_cache.find(key); + if(it == glyph_cache.end()) + return 0; + all_cached.splice(all_cached.begin(), all_cached, it->second); + return &it->second->second; + } + + FontFace& getStdFontFace(int i) + { + CV_Assert(i >= 0 && i < BUILTIN_FONTS_NUM); + builtin_ffaces[i]->setStd(builtinFontData[i]); + return builtin_ffaces[i]; + } + + Point putText_( Mat& img, Size imgsize, const String& str_, Point org, + const uchar* color, FontFace& fontface, int size, + int weight, PutTextFlags flags, Range wrapRange, bool render, + Rect* bbox ); + +protected: + FontFace builtin_ffaces[BUILTIN_FONTS_NUM]; + bool builtin_ffaces_initialized; + + hb_unicode_funcs_t* hb_uni_funcs; + + // LRU cache of glyphs + GlyphCacheVal new_cached; + std::list all_cached; + std::unordered_map glyph_cache; + size_t max_cache_size; + + hb_buffer_t* hb_buf; + std::vector u32buf; + std::vector segments; + std::vector glyphs; + std::vector pixbuf; + uchar* glyph_buf; + int glyph_bufsz; +}; + +thread_local FontRenderEngine fontRenderEngine; + +FontFace::FontFace() { impl = makePtr(); } +FontFace::FontFace(const String& fontname) +{ + impl = makePtr(); + set(fontname); +} + +bool FontFace::set(const String& fontname_) +{ + String fontname = fontname_; + if(fontname.empty()) + fontname = "sans"; + if(impl->ttface != 0 && impl->currname == fontname) + return true; + int i = 0; + for( ; i < BUILTIN_FONTS_NUM; i++ ) + { + if( builtinFontData[i].name == fontname && builtinFontData[i].size > 1 ) + break; + } + if( i >= BUILTIN_FONTS_NUM ) + i = -1; + + FontRenderEngine& engine = fontRenderEngine; + + bool ok = false; + if( i >= 0 ) + { + FontFace& builtin_fface = engine.getStdFontFace(i); + if(builtin_fface.impl->ttface) + { + impl = builtin_fface.impl; + ok = true; + } + } + else + { + if(impl->ttface != 0) + impl = makePtr(); + ok = impl->set(fontname); + } + return ok; +} + +bool FontFace::getBuiltinFontData(const String& fontname_, + const uchar*& data, size_t& size) +{ + String fontname = fontname_; + if(fontname.empty()) + fontname = "sans"; + data = 0; + size = 0; + for(int i = 0; i < BUILTIN_FONTS_NUM; i++) + { + if(builtinFontData[i].name == fontname && builtinFontData[i].size > 1) + { + FontFace& builtin_fface = fontRenderEngine.getStdFontFace(i); + if( builtin_fface.impl->ttface ) + { + std::vector& fbuf = builtin_fface.impl->fontbuf; + size = fbuf.size(); + data = size > 0 ? &fbuf[0] : 0; + return size > 0; + } + return false; + } + } + return false; +} + +String FontFace::getName() const { return impl->currname; } +FontFace::Impl* FontFace::operator -> () { return impl.get(); } +FontFace::~FontFace() {} + +bool FontFace::setInstance(const std::vector& params) +{ + if (params.empty()) + return true; + if (!impl->ttface) + return false; + CV_Assert(params.size() % 2 == 0); + return stbtt_SetInstance(impl->ttface, ¶ms[0], (int)(params.size()/2), 1) > 0; +} + +bool FontFace::getInstance(std::vector& params) const +{ + if (!impl->ttface) + return false; + + stbtt_axisinfo axes[STBTT_MAX_AXES]; + int i, naxes = stbtt_GetInstance(impl->ttface, axes, STBTT_MAX_AXES); + params.resize(naxes*2); + + for( i = 0; i < naxes; i++ ) + { + int tag = axes[i].tag; + params[i*2] = CV_FOURCC((char)(tag >> 24), (char)(tag >> 16), (char)(tag >> 8), (char)tag); + params[i*2+1] = axes[i].currval; + } + return naxes > 0; +} + +static unsigned calccrc(const std::vector& buf) +{ + unsigned crc = (unsigned)-1; + size_t i, n = buf.size(); + for(i = 0; i < n; i++) + crc = (crc << 5) ^ (crc >> 27) ^ buf[i]; + return crc; +} + +static void +compressCharacter(const uchar* bitmap_buf, + int bitmap_step, Size bitmap_size, + std::vector& rlebuf, + Rect& roi, unsigned* crc) +{ + const int RLE_MAX = 255; + int width = bitmap_size.width, height = bitmap_size.height; + int left = width-1, right = 0, top = height-1, bottom = 0; + bool global_have_nz = false; + for( int i = 0; i < height; i++ ) + { + bool have_nz = false; + for( int j = 0; j < width; j++ ) + { + if(bitmap_buf[i*bitmap_step + j] != 0) + { + left = min(left, j); + right = max(right, j); + have_nz = true; + } + } + if( have_nz ) + { + global_have_nz |= have_nz; + top = min(top, i); + bottom = max(bottom, i); + } + } + // all 0's + if(!global_have_nz) + { + roi = Rect(0, 0, 0, 0); + rlebuf.clear(); + if(crc) + *crc = calccrc(rlebuf); + return; + } + roi = Rect(left, top, right - left + 1, bottom - top + 1); + bool rle_mode = true; + int k = 0, count = 0; + int count_pos = -1; + int bufsz = roi.width*roi.height*2+256; + rlebuf.resize(bufsz); + uchar* buf = &rlebuf[0]; + int prev = 0, x = 0; + + // c b + // a x + for( int i = top; i <= bottom; i++ ) + { + for( int j = left; j <= right; j++ ) + { + const uchar* ptr = bitmap_buf + i*bitmap_step + j; + prev = x; + x = *ptr; + int a = 0, b = 0, c = 0; + if( i > top ) + { + b = ptr[-bitmap_step]; + if( j > left ) + { + a = ptr[-1]; + c = ptr[-1-bitmap_step]; + } + } + else if( j > left ) + a = ptr[-1]; + int predicted = a + b - c; + if( x == predicted ) + { + if(rle_mode) ++count; + else + { + if(count > 0) + buf[count_pos] = (uchar)count; + count = 1; + rle_mode = true; + } + } + else if( !rle_mode ) + { + if(count == RLE_MAX) + { + buf[count_pos] = (uchar)count; + buf[k++] = 0; + count_pos = k++; + count = 0; + } + buf[k++] = (uchar)x; + count++; + } + else if( count == 1 && count_pos >= 0 && buf[count_pos] < RLE_MAX-1 ) + { + count = buf[count_pos] + 2; + buf[k++] = (uchar)prev; + buf[k++] = (uchar)x; + rle_mode = false; + } + else + { + if(count == 0) + buf[k++] = 0; + while(count > 0) + { + int dcount = min(count, RLE_MAX); + count -= dcount; + buf[k++] = (uchar)dcount; + if(count > 0) + buf[k++] = 0; + } + count_pos = k++; + buf[k++] = (uchar)x; + count = 1; + rle_mode = false; + } + } + } + + if(rle_mode) + { + while(count > 0) + { + int dcount = min(count, RLE_MAX); + count -= dcount; + buf[k++] = (uchar)dcount; + if(count > 0) + buf[k++] = 0; + } + } + else buf[count_pos] = (uchar)count; + rlebuf.resize(k); + if(crc) + *crc = calccrc(rlebuf); +} + +static bool +decompressCharacter(const std::vector& rlebuf, Rect r, + std::vector& pixbuf, const unsigned* crc) +{ + if(crc) + CV_Assert(*crc == calccrc(rlebuf)); + + int width = r.width, height = r.height; + int i = 0, j = 0, k = 0; + int bufsz = (int)rlebuf.size(); + const uchar* buf = bufsz > 0 ? &rlebuf[0] : 0; + + pixbuf.resize(width*height); + uchar* pixels = width*height > 0 ? &pixbuf[0] : 0; + + if(bufsz == 0) + { + if(width > 0 && height > 0) + memset(pixels, 0, width*height); + return true; + } + + while( k < bufsz ) + { + int rle_count = buf[k++]; + for( ; rle_count > 0; rle_count-- ) + { + int a = 0, b = 0, c = 0; + uchar* ptr = pixels + i*width + j; + if( i > 0 ) + { + b = ptr[-width]; + if( j > 0 ) + { + a = ptr[-1]; + c = ptr[-width-1]; + } + } + else if( j > 0 ) + a = ptr[-1]; + int pred = a + b - c; + ptr[0] = (uchar)pred; + if( ++j >= width ) + { + j = 0; + if( ++i >= height ) + return true; + } + } + if( k >= bufsz ) + return false; + int nz_end = buf[k++]; + nz_end += k; + if( nz_end > bufsz ) + return false; + for( ; k < nz_end; k++ ) + { + pixels[i*width + j] = buf[k]; + if( ++j >= width ) + { + j = 0; + if( ++i >= height ) + return true; + } + } + } + return false; +} + +static void drawCharacter( + Mat& img, const uchar* color, + const uchar* bitmap_buf, + int bitmap_step, Size bitmap_size, + int x0, int y0, bool bottom_left ) +{ + int nch = img.channels(); + int bw = bitmap_size.width, bh = bitmap_size.height; + int rows = img.rows, cols = img.cols; + uchar b = color[0], g = color[1], r = color[2]; + + if(x0 >= cols || x0 + bw <= 0) + return; + + // for simplicity, we assume that `bitmap->pixel_mode' + // is `FT_PIXEL_MODE_GRAY' (i.e., not a bitmap font) + for( int dy = 0; dy < bh; dy++ ) + { + int y = y0 + dy*(bottom_left ? -1 : 1); + if( y < 0 || y >= rows ) + continue; + uchar* imgptr0 = img.ptr(y); + for( int dx = 0; dx < bw; dx++ ) + { + int x = x0 + dx; + if( x < 0 || x >= cols ) + continue; + uchar* imgptr = imgptr0 + x*nch; + uchar alpha = bitmap_buf[dy*bitmap_step + dx]; + if(alpha == 0) + continue; + if( nch == 3 ) + { + uchar b1 = (uchar)((imgptr[0]*(255 - alpha) + b*alpha + 127)/255); + uchar g1 = (uchar)((imgptr[1]*(255 - alpha) + g*alpha + 127)/255); + uchar r1 = (uchar)((imgptr[2]*(255 - alpha) + r*alpha + 127)/255); + imgptr[0] = b1; + imgptr[1] = g1; + imgptr[2] = r1; + } + else if(nch == 1) + { + uchar b1 = (uchar)((imgptr[0]*(255 - alpha) + b*alpha + 127)/255); + imgptr[0] = b1; + } + else + { + uchar b1 = (uchar)((imgptr[0]*(255 - alpha) + b*alpha + 127)/255); + uchar g1 = (uchar)((imgptr[1]*(255 - alpha) + g*alpha + 127)/255); + uchar r1 = (uchar)((imgptr[2]*(255 - alpha) + r*alpha + 127)/255); + imgptr[0] = b1; + imgptr[1] = g1; + imgptr[2] = r1; + imgptr[3] = alpha; + } + } + } +} + +#ifdef HAVE_HARFBUZZ +//by amarullz from https://stackoverflow.com/questions/5423960/how-can-i-recognize-rtl-strings-in-c +static bool isRightToLeft(unsigned c) +{ + if(c < 0x5BE) + return false; + + return + ((c==0x05BE)||(c==0x05C0)||(c==0x05C3)||(c==0x05C6)|| + ((c>=0x05D0)&&(c<=0x05F4))|| + (c==0x0608)||(c==0x060B)||(c==0x060D)|| + ((c>=0x061B)&&(c<=0x064A))|| + ((c>=0x066D)&&(c<=0x066F))|| + ((c>=0x0671)&&(c<=0x06D5))|| + ((c>=0x06E5)&&(c<=0x06E6))|| + ((c>=0x06EE)&&(c<=0x06EF))|| + ((c>=0x06FA)&&(c<=0x0710))|| + ((c>=0x0712)&&(c<=0x072F))|| + ((c>=0x074D)&&(c<=0x07A5))|| + ((c>=0x07B1)&&(c<=0x07EA))|| + ((c>=0x07F4)&&(c<=0x07F5))|| + ((c>=0x07FA)&&(c<=0x0815))|| + (c==0x081A)||(c==0x0824)||(c==0x0828)|| + ((c>=0x0830)&&(c<=0x0858))|| + ((c>=0x085E)&&(c<=0x08AC))|| + (c==0x200F)||(c==0xFB1D)|| + ((c>=0xFB1F)&&(c<=0xFB28))|| + ((c>=0xFB2A)&&(c<=0xFD3D))|| + ((c>=0xFD50)&&(c<=0xFDFC))|| + ((c>=0xFE70)&&(c<=0xFEFC))|| + ((c>=0x10800)&&(c<=0x1091B))|| + ((c>=0x10920)&&(c<=0x10A00))|| + ((c>=0x10A10)&&(c<=0x10A33))|| + ((c>=0x10A40)&&(c<=0x10B35))|| + ((c>=0x10B40)&&(c<=0x10C48))|| + ((c>=0x1EE00)&&(c<=0x1EEBB))); +} +#endif + +Point FontRenderEngine::putText_( + Mat& img, Size imgsize, const String& str_, Point org, + const uchar* color, FontFace& fontface, int size, + int weight_, PutTextFlags flags, Range wrapRange, + bool render, Rect* bbox_ ) +{ + bool bottom_left = (flags & PUT_TEXT_ORIGIN_BL) != 0; + int saved_weights[BUILTIN_FONTS_NUM+1]={0}; + int weight = weight_*65536; + + if(fontface.getName().empty()) + fontface.set("sans"); + if(!fontface->ttface) + CV_Error(Error::StsError, "No available fonts for putText()"); + + Point pen = org; + int i, j, len = (int)str_.size(); + bool wrap = (flags & PUT_TEXT_WRAP) != 0; + int alignment = flags & PUT_TEXT_ALIGN_MASK; + int x0 = std::min(wrapRange.start, wrapRange.end); + int x1 = std::max(wrapRange.start, wrapRange.end); + + if(x0 == 0 && x1 == 0) + { + if(alignment == PUT_TEXT_ALIGN_RIGHT) + { + x0 = 0; + x1 = org.x; + } + else + { + x0 = org.x; + x1 = imgsize.width > 0 ? imgsize.width : INT_MAX; + } + } + + if(x0 >= x1 || len == 0) + { + if(bbox_) + *bbox_ = Rect(org.x, org.y, 0, 0); + return org; + } + + saved_weights[BUILTIN_FONTS_NUM] = stbtt_GetWeight(fontface->ttface); + fontface->setParams(size, weight); + + for(j = 0; j < BUILTIN_FONTS_NUM; j++) + { + FontFace& fface = builtin_ffaces[j]; + if(!builtin_ffaces_initialized) + fface.set(builtinFontData[j].name); + + if (fface->ttface) { + saved_weights[j] = stbtt_GetWeight(fface->ttface); + fface->setParams(size, weight); + } + } + builtin_ffaces_initialized = true; + + if(alignment == PUT_TEXT_ALIGN_RIGHT) + std::swap(x0, x1); + + int alignSign = alignment == PUT_TEXT_ALIGN_RIGHT ? -1 : 1; + + // text size computing algorithm is adopted from G-API module, ft_render.cpp. + const char* str = &str_[0]; + int max_dy = 0, max_baseline = 0; + int max_x = INT_MIN, min_x = INT_MAX; + bool wrapped = false; + + // step 1. convert UTF8 to UTF32 + u32buf.clear(); + for( i = 0; i < len; i++ ) + { + uchar ch = (uchar)str[i]; + unsigned charcode; + if( ch <= 127 ) + charcode = ch; + else if( ch <= 223 && i+1 < len && (str[i+1] & 0xc0) == 0x80) { + charcode = ((ch & 31) << 6) | (str[i+1] & 63); + i++; + } + else if( ch <= 239 && i+2 < len && (str[i+1] & 0xc0) == 0x80 && (str[i+2] & 0xc0) == 0x80) { + charcode = ((ch & 15) << 12) | ((str[i+1] & 63) << 6) | (str[i+2] & 63); + i += 2; + } + else if( ch <= 247 && i+3 < len && (str[i+1] & 0xc0) == 0x80 && (str[i+2] & 0xc0) == 0x80 && (str[i+3] & 0xc0) == 0x80) { + int val = (int)(((ch & 15) << 18) | ((str[i+1] & 63) << 12) | ((str[i+2] & 63) << 6) | (str[i+3] & 63)); + if( val > 1114111 ) val = 65533; + charcode = val; + i += 3; + } + else + { + charcode = 65533; + while(i+1 < len && (str[i+1] & 0xc0) == 0x80) + i++; + } + u32buf.push_back(charcode); + } + + // step 2. form segments, for each segment find the proper font, direction and script. + len = (int)u32buf.size(); + unsigned* chars = &u32buf[0]; + int prev_dy = 0; + +#ifdef HAVE_HARFBUZZ + hb_direction_t glob_dir = HB_DIRECTION_INVALID; +#endif + + while(len > 0) + { + int nextline_dy = 0; + font_t* ttface0 = fontface->ttface; + float scale0 = fontface->scale; + font_t* curr_ttface = ttface0; + + segments.clear(); + glyphs.clear(); + + #ifdef HAVE_HARFBUZZ + hb_script_t curr_script = HB_SCRIPT_UNKNOWN; + hb_direction_t curr_dir = HB_DIRECTION_INVALID; + int curr_fontidx = -1; + + int k, segstart = 0, punctstart = -1; + // TODO: possibly implement https://unicode.org/reports/tr9/ or find compact implementation of it + for(i = 0; i < len; i++) + { + int c = chars[i]; + if(c == '\n') + break; + hb_unicode_general_category_t cat = hb_unicode_general_category(hb_uni_funcs, c); + hb_script_t script = hb_unicode_script(hb_uni_funcs, c); + int glyph_index = stbtt_FindGlyphIndex(curr_ttface, c); + bool is_rtl = isRightToLeft(c); + hb_direction_t dir = HB_DIRECTION_INVALID; + + if(script == HB_SCRIPT_ARABIC || script == HB_SCRIPT_HEBREW || + script == HB_SCRIPT_SYRIAC || script == HB_SCRIPT_THAANA || is_rtl) + dir = HB_DIRECTION_RTL; + else if(script == HB_SCRIPT_LATIN || script == HB_SCRIPT_CYRILLIC || script == HB_SCRIPT_GREEK || + (cat >= HB_UNICODE_GENERAL_CATEGORY_SURROGATE && + cat <= HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION) || + cat == HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL) + dir = HB_DIRECTION_LTR; + + bool is_punct = dir == HB_DIRECTION_INVALID && + ((c < 128 && (ispunct((char)c) || isspace((char)c))) || + (cat >= HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION && + cat <= HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION) || + (cat >= HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL && + cat <= HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR) || + cat == HB_UNICODE_GENERAL_CATEGORY_FORMAT); + + // when we switch to fallback (e.g. uni) font for some characters after quote or open paren, + // and when we meet the corresponding closing quote/closing paren, we would prefer to + // take it from the same font. this hack helps to achieve this effect in some cases + if (is_punct && c < 256 && cat != HB_UNICODE_GENERAL_CATEGORY_FORMAT && + cat != HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR && !isspace((char)c) && + curr_script != HB_SCRIPT_LATIN && curr_script != HB_SCRIPT_CYRILLIC && curr_dir != HB_DIRECTION_RTL) + { + is_punct = false; + script = HB_SCRIPT_LATIN; + dir = HB_DIRECTION_LTR; + } + + #if 0 + printf("%d. c=%d, scr=%c%c%c%c, cat=%d, is_rtl=%d, dir=%s, is_punct=%d\n", i, c, + (script>>24)&255, (script>>16)&255, (script>>8)&255, (script>>0)&255, (int)cat, (int)is_rtl, + (dir == HB_DIRECTION_INVALID? "invalid" : dir == HB_DIRECTION_LTR ? "left" : "right"), (int)is_punct); + #endif + + if(glyph_index != 0 || + (cat == HB_UNICODE_GENERAL_CATEGORY_FORMAT && + dir == HB_DIRECTION_INVALID)) + { + if(is_punct) + { + if(punctstart < 0) + punctstart = i; + continue; + } + + if(cat == HB_UNICODE_GENERAL_CATEGORY_SURROGATE || cat == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK || + ((script == curr_script || curr_script == HB_SCRIPT_UNKNOWN || curr_script == HB_SCRIPT_COMMON || + script == HB_SCRIPT_UNKNOWN || script == HB_SCRIPT_COMMON || script == HB_SCRIPT_INHERITED) && + (dir == curr_dir || curr_dir == HB_DIRECTION_INVALID || dir == HB_DIRECTION_INVALID))) + { + punctstart = -1; + if(curr_dir == HB_DIRECTION_INVALID) + curr_dir = dir; + if(curr_script == HB_SCRIPT_UNKNOWN || curr_script == HB_SCRIPT_INHERITED) + curr_script = script; + continue; + } + } + + if(glob_dir == HB_DIRECTION_INVALID) + { + glob_dir = curr_dir; + if(glob_dir == HB_DIRECTION_INVALID) + glob_dir = dir; + } + + font_t* ttface = 0; + for(j = -1; j < BUILTIN_FONTS_NUM; j++) + { + ttface = j < 0 ? ttface0 : builtin_ffaces[j]->ttface; + glyph_index = stbtt_FindGlyphIndex(ttface, c); + if(glyph_index != 0) + break; + if(j+1 == BUILTIN_FONTS_NUM) + { + chars[i] = c = '?'; // replace the character with 'unknown' ~ (TBD: replace ? with 0xFFFD) + break; + } + } + int fontidx = j; + int seglen = i - segstart; + // if the current segment (if any) ends with 1 or more neutral/punctuation characters, + // we have 3 choices: + // 1. attach this "tail" to the current segment + // 2. make this "tail" the head of the new segment + // 3. split those characters somehow between the current and the new segment + // if the current segment direction matches the global direction, we choose the option 1. + // otherwise we choose the option 3, depending on which characters from the tail + // are available in the new font for the new segment. + // Unless they are some specific marks, they are all available, in which case + // the option 3 turns into the option 2. + if(seglen > 0 && punctstart >= 0 && glob_dir != curr_dir) + { + for(k = i; k > punctstart; k--) + { + if(stbtt_FindGlyphIndex(ttface, chars[k-1]) == 0) + break; + } + seglen = k - segstart; + } + + if(seglen > 0) + { + //printf("segment of %d characters pushed\n", seglen); + segments.push_back(TextSegment(curr_ttface, curr_fontidx, + segstart, segstart + seglen, curr_script, curr_dir)); + } + segstart += seglen; + punctstart = punctstart >= 0 && is_punct ? segstart : -1; + curr_ttface = ttface; + curr_fontidx = fontidx; + curr_script = script; + curr_dir = dir; + } + + if(i > segstart) + { + segments.push_back(TextSegment(curr_ttface, curr_fontidx, + segstart, i, curr_script, curr_dir)); + } + + if(glob_dir == HB_DIRECTION_INVALID) + glob_dir = HB_DIRECTION_LTR; + + int nsegments = (int)segments.size(); + ttface0 = segments[0].ttface; + + if(nsegments > 0) + { + TextSegment& seg = segments[0]; + if(seg.dir == HB_DIRECTION_INVALID) + seg.dir = glob_dir; + if(seg.script == HB_SCRIPT_INVALID) + seg.script = HB_SCRIPT_COMMON; + } + + // step 3. try to merge some segments + for(k = 0, j = 1; j < nsegments; j++) + { + TextSegment& seg = segments[j]; + if(seg.dir == HB_DIRECTION_INVALID) + seg.dir = glob_dir; + hb_script_t script = seg.script; + if(script == HB_SCRIPT_INVALID) + seg.script = script = HB_SCRIPT_COMMON; + TextSegment& prev = segments[k]; + if(seg.ttface == prev.ttface && seg.dir == prev.dir && + (script == prev.script || + ((script == HB_SCRIPT_COMMON || script == HB_SCRIPT_LATIN || + script == HB_SCRIPT_CYRILLIC || script == HB_SCRIPT_GREEK || + script == HB_SCRIPT_HAN || script == HB_SCRIPT_HIRAGANA) && + (prev.script == HB_SCRIPT_COMMON || prev.script == HB_SCRIPT_LATIN || + prev.script == HB_SCRIPT_CYRILLIC || prev.script == HB_SCRIPT_GREEK || + prev.script == HB_SCRIPT_HAN || prev.script == HB_SCRIPT_HIRAGANA)))) + { + prev.end = seg.end; + if(prev.script != script) + prev.script = HB_SCRIPT_COMMON; + } + else + { + k++; + if(j > k) + segments[k] = seg; + } + } + + if(nsegments > 0) + segments.resize(k+1); + else + nextline_dy = prev_dy; + nsegments = (int)segments.size(); + + if(glob_dir == HB_DIRECTION_RTL) + { + std::reverse(segments.begin(), segments.end()); + } + //printf("%s: nsegments=%d\n", str_.c_str(), nsegments); + + // step 4. shape each text segment using Harfbuzz + for(j = 0; j < nsegments; j++) + { + const TextSegment& seg = segments[j]; + int fontidx = seg.fontidx; + FontFace& fface = fontidx < 0 ? fontface : builtin_ffaces[fontidx]; + font_t* ttface = fface->ttface; + hb_font_t* hb_font = fface->hb_font; + hb_buffer_reset(hb_buf); + hb_buffer_add_utf32(hb_buf, chars, len, seg.start, seg.end - seg.start); + hb_buffer_set_direction(hb_buf, seg.dir); + hb_buffer_set_script(hb_buf, seg.script); + hb_shape(hb_font, hb_buf, 0, 0); + + unsigned nglyphs = 0; + hb_glyph_info_t *ginfo = hb_buffer_get_glyph_infos(hb_buf, &nglyphs); + hb_glyph_position_t* gpos = hb_buffer_get_glyph_positions(hb_buf, &nglyphs); + + for(k = 0; k < (int)nglyphs; k++) + { + FontGlyph glyph(ttface, ginfo[k].codepoint, gpos[k], fface->scale); + glyphs.push_back(glyph); + } + } + #else + for(i = 0; i < len; i++) + { + int c = chars[i]; + if(c == '\n') + break; + font_t* ttface = ttface0; + float scale = scale0; + int q_glyph_index = stbtt_FindGlyphIndex(ttface0, '?'); + for(j = -1; j < BUILTIN_FONTS_NUM; j++) + { + if (j >= 0) + { + ttface = builtin_ffaces[j]->ttface; + scale = builtin_ffaces[j]->scale; + } + int glyph_index = ttface ? stbtt_FindGlyphIndex(ttface, c) : 0; + if(glyph_index == 0) + { + if (j+1 < BUILTIN_FONTS_NUM) + continue; + ttface = ttface0; + scale = scale0; + glyph_index = q_glyph_index; + } + hb_glyph_position_t pos; + pos.x_advance = pos.y_advance = 0; + pos.x_offset = pos.y_offset = 0; + glyphs.push_back(FontGlyph(ttface, glyph_index, pos, scale)); + break; + } + } + if (i == 0) + nextline_dy = prev_dy; + #endif + + chars += i; + len -= i; + + if(len > 0 && chars[0] == '\n') + { + chars++; + len--; + } + + // step 5. finally, let's render it + // (TODO: in the case of right alignment we need to render it from the right-most character) + int nglyphs = (int)glyphs.size(); + int space_glyph = -1; + curr_ttface = 0; + min_x = std::min(min_x, pen.x); + max_x = std::max(max_x, pen.x); + + curr_ttface = 0; + int ascent = 0, descent = 0, linegap = 0; + for(j = 0; j < nglyphs; j++) + { + const FontGlyph& glyph = glyphs[alignment == PUT_TEXT_ALIGN_RIGHT ? nglyphs - j - 1 : j]; + font_t* ttface = glyph.ttface; + if(ttface != curr_ttface) + { + curr_ttface = ttface; + space_glyph = stbtt_FindGlyphIndex(ttface, ' '); + stbtt_GetFontVMetrics(ttface, &ascent, &descent, &linegap); + if (linegap == 0) linegap = ascent - descent; + } + + float scale = glyph.scale; + GlyphCacheKey key(curr_ttface, glyph.index, size, weight, scale); + GlyphCacheVal* cached = findCachedGlyph(key); + const uchar* bitmap_buf = 0; + int bitmap_step = 0; + Rect bbox; + + if(!cached) + { + cached = &new_cached; + int w=0, h=0, xoff=0, yoff=0; + float advx = 0.f; + bitmap_buf = stbtt_GetGlyphBitmapSubpixelRealloc(ttface, scale, scale, 0.f, 0.f, + glyph.index, &w, &h, &bitmap_step, &xoff, &yoff, &advx, &glyph_buf, &glyph_bufsz); + if(!bitmap_buf) + continue; + //printf("j=%d. bw=%d, bh=%d, step=%d, xoff=%d, yoff=%d, advx=%.1f, glyph_bufsz=%d\n", j, w, h, bitmap_step, xoff, yoff, advx, glyph_bufsz); + + cached->width = w; + cached->height = h; + cached->advance.x = cvRound(advx*64); + cached->advance.y = 0; + cached->ascent = cvRound(ascent*glyph.scale); + cached->linegap = cvRound(linegap*glyph.scale); + cached->horiBearingX = (int)(xoff*64); + cached->horiBearingY = (int)(-yoff*64); + + bbox = Rect(0, 0, w, h); + + if(w <= MAX_CACHED_GLYPH_SIZE && h <= MAX_CACHED_GLYPH_SIZE) + { + compressCharacter(bitmap_buf, bitmap_step, Size(w, h), + cached->rlebuf, cached->bbox, + 0 //&cached->crc + ); + addToCache(key, *cached); + } + } + else + { + if(render) + { + CV_Assert(decompressCharacter(cached->rlebuf, cached->bbox, + pixbuf, 0 //&cached->crc + )); + } + bitmap_buf = pixbuf.empty() ? 0 : &pixbuf[0]; + bitmap_step = cached->bbox.width; + bbox = cached->bbox; + } + + const hb_glyph_position_t& pos = glyph.pos; + int dx = cached->advance.x >> 6; + int dy = cached->advance.y >> 6; + int new_pen_x = pen.x + dx*alignSign; + nextline_dy = max(nextline_dy, cached->linegap); + // TODO: this wrapping algorithm is quite dumb, + // preferably should split text at word boundary + if( wrap && imgsize.width > 0 && new_pen_x*alignSign > x1*alignSign ) + { + pen.y += nextline_dy; + dy = 0; + pen.x = x0; + wrapped = true; + //max_baseline = 0; + if(glyph.index == space_glyph) continue; + new_pen_x = pen.x + dx*alignSign; + } + + if(!wrapped) + max_dy = std::max(max_dy, cached->ascent); + int baseline = cached->height - (cached->horiBearingY >> 6); + max_baseline = std::max(max_baseline, baseline); + + if(alignment == PUT_TEXT_ALIGN_RIGHT) + pen.x = new_pen_x; + + int x = pen.x + bbox.x + ((pos.x_offset + cached->horiBearingX) >> 6); + int y = pen.y + (bottom_left ? 1 : -1)*(((pos.y_offset + cached->horiBearingY) >> 6) - bbox.y); + + if( render ) + { + //circle(img, pen, 2, Scalar(0, 0, 128), -1, LINE_AA); + drawCharacter(img, color, bitmap_buf, bitmap_step, bbox.size(), x, y, bottom_left); + } + + pen.x = new_pen_x; + pen.y += dy; + min_x = std::min(min_x, pen.x); + max_x = std::max(max_x, pen.x); + } + + if(len > 0 && (pen.x != x0 || segments.empty())) + { + pen.x = x0; + pen.y += nextline_dy; + prev_dy = nextline_dy; + } + } + + if(bbox_) + { + if(flags & PUT_TEXT_ORIGIN_BL) + *bbox_ = Rect(min_x, org.y - max_baseline, max_x - min_x + 1, pen.y - org.y + max_dy + max_baseline); + else + *bbox_ = Rect(min_x, org.y - max_dy, max_x - min_x + 1, pen.y - org.y + max_dy + max_baseline); + } + + // restore the weights + if (weight != 0) + for(j = 0; j <= BUILTIN_FONTS_NUM; j++) + { + int params[] = {STBTT_FOURCC('w', 'g', 'h', 't'), saved_weights[j]}; + font_t* ttface = (j < BUILTIN_FONTS_NUM ? builtin_ffaces[j] : fontface)->ttface; + if (ttface) + stbtt_SetInstance(ttface, params, 1, 0); + } + + return pen; +} + + +Point putText(InputOutputArray img_, const String& str, + Point org, Scalar color_, + FontFace& fontface, int size, + int weight, PutTextFlags flags, Range wrap) +{ + uchar color[] = + { + saturate_cast(color_[0]), saturate_cast(color_[1]), + saturate_cast(color_[2]), saturate_cast(color_[3]) + }; + Mat img = img_.getMat(); + int nch = img.channels(); + CV_Assert(img.depth() == CV_8U); + CV_Assert(nch == 1 || nch == 3 || nch == 4); + + return fontRenderEngine.putText_(img, img.size(), str, org, color, fontface, size, + weight, flags, wrap, true, 0); +} + + +Rect getTextSize(Size imgsize, const String& str, Point org, + FontFace& fontface, int size, + int weight, PutTextFlags flags, Range wrap) +{ + Mat img; + Rect bbox; + fontRenderEngine.putText_(img, imgsize, str, org, 0, fontface, size, + weight, flags, wrap, false, &bbox); + return bbox; +} + +} + +//////////////////////////// text drawing functions for backward compatibility /////////////////////////// + +namespace cv +{ + +static void hersheyToTruetype(int fontFace, double fontScale, int thickness, + String& ttname, int& ttsize, int& ttweight) +{ + double sf = 0; + switch(fontFace & ~FONT_ITALIC) + { + case FONT_HERSHEY_PLAIN: + ttname = "sans"; + sf = 6.6; + ttweight = thickness <= 1 ? 400 : 800; + break; + case FONT_HERSHEY_SIMPLEX: + ttname = "sans"; + sf = 3.7; + ttweight = thickness <= 1 ? 400 : 600; + break; + case FONT_HERSHEY_DUPLEX: + ttname = "sans"; + sf = 3.7; + ttweight = thickness <= 1 ? 600 : 800; + break; + case FONT_HERSHEY_COMPLEX: + ttname = "serif"; + sf = 3.7; + ttweight = thickness <= 1 ? 400 : 800; + break; + case FONT_HERSHEY_TRIPLEX: + ttname = "serif"; + sf = 3.7; + ttweight = thickness <= 1 ? 600 : 800; + break; + case FONT_HERSHEY_COMPLEX_SMALL: + ttname = "serif"; + sf = 4.6; + ttweight = thickness <= 1 ? 400 : 800; + break; + case FONT_HERSHEY_SCRIPT_COMPLEX: + ttname = "italic"; + sf = 4.0; + ttweight = thickness <= 1 ? 400 : 600; + break; + case FONT_HERSHEY_SCRIPT_SIMPLEX: + ttname = "italic"; + sf = 4.0; + ttweight = thickness <= 1 ? 300 : 500; + break; + default: + CV_Error(Error::StsBadArg, "Unknown font"); + } + + ttsize = cvRound(100*fontScale/sf); +} + +void putText( InputOutputArray _img, const String& text, Point org, + int fontFace, double fontScale, Scalar color, + int thickness, int, bool bottomLeftOrigin ) + +{ + String ttname; + int ttsize = 0; + int ttweight = 0; + hersheyToTruetype(fontFace, fontScale, thickness, ttname, ttsize, ttweight); + FontFace fface(ttname); + PutTextFlags flags = bottomLeftOrigin ? PUT_TEXT_ORIGIN_BL : PUT_TEXT_ORIGIN_TL; + putText(_img, text, org, color, fface, ttsize, ttweight, flags); +} + +Size getTextSize(const String& text, int fontFace, double fontScale, int thickness, int* _base_line) +{ + String ttname; + int ttsize = 0; + int ttweight = 0; + hersheyToTruetype(fontFace, fontScale, thickness, ttname, ttsize, ttweight); + + FontFace fface(ttname); + Rect r = getTextSize(Size(), text, Point(), fface, ttsize, ttweight, PUT_TEXT_ALIGN_LEFT); + + int baseline = r.y + r.height; + if(_base_line) + *_base_line = baseline; + return Size(r.width, r.height - baseline); +} + +double getFontScaleFromHeight(const int fontFace, const int pixelHeight, const int thickness) +{ + String ttname; + int ttsize = 0; + int ttweight = 0; + hersheyToTruetype(fontFace, 1.0, thickness, ttname, ttsize, ttweight); + return (double)pixelHeight/ttsize; +} + +} diff --git a/modules/imgproc/src/hershey_fonts.cpp b/modules/imgproc/src/hershey_fonts.cpp deleted file mode 100644 index 0703de09bd..0000000000 --- a/modules/imgproc/src/hershey_fonts.cpp +++ /dev/null @@ -1,3359 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -/* //////////////////////////////////////////////////////////////////// -// -// CvMat helper tables -// -// */ - -#include "precomp.hpp" - -namespace cv -{ - -const char* g_HersheyGlyphs[] = { - "", - "MWRMNV RMVV PSTS", - "MWOMOV OMSMUNUPSQ OQSQURUUSVOV", - "MXVNTMRMPNOPOSPURVTVVU", - "MWOMOV OMRMTNUPUSTURVOV", - "MWOMOV OMUM OQSQ OVUV", - "MVOMOV OMUM OQSQ", - "MXVNTMRMPNOPOSPURVTVVUVR SRVR", - "MWOMOV UMUV OQUQ", - "PTRMRV", - "NUSMSTRVPVOTOS", - "MWOMOV UMOS QQUV", - "MVOMOV OVUV", - "LXNMNV NMRV VMRV VMVV", - "MWOMOV OMUV UMUV", - "MXRMPNOPOSPURVSVUUVSVPUNSMRM", - "MWOMOV OMSMUNUQSROR", - "MXRMPNOPOSPURVSVUUVSVPUNSMRM STVW", - "MWOMOV OMSMUNUQSROR RRUV", - "MWUNSMQMONOOPPTRUSUUSVQVOU", - "MWRMRV NMVM", - "MXOMOSPURVSVUUVSVM", - "MWNMRV VMRV", - "LXNMPV RMPV RMTV VMTV", - "MWOMUV UMOV", - "MWNMRQRV VMRQ", - "MWUMOV OMUM OVUV", - "MWRMNV RMVV PSTS", - "MWOMOV OMSMUNUPSQ OQSQURUUSVOV", - "MVOMOV OMUM", - "MWRMNV RMVV NVVV", - "MWOMOV OMUM OQSQ OVUV", - "MWUMOV OMUM OVUV", - "MWOMOV UMUV OQUQ", - "MXRMPNOPOSPURVSVUUVSVPUNSMRM QQTR TQQR", - "PTRMRV", - "MWOMOV UMOS QQUV", - "MWRMNV RMVV", - "LXNMNV NMRV VMRV VMVV", - "MWOMOV OMUV UMUV", - "MWOMUM PQTR TQPR OVUV", - "MXRMPNOPOSPURVSVUUVSVPUNSMRM", - "MWOMOV UMUV OMUM", - "MWOMOV OMSMUNUQSROR", - "MWOMRQOV OMUM OVUV", - "MWRMRV NMVM", - "MWNONNOMPMQNRPRV VOVNUMTMSNRP", - "LXRMRV PONPNSPTTTVSVPTOPO", - "MWOMUV UMOV", - "LXRMRV NOOPOSQTSTUSUPVO", - "MXOVQVOROPPNRMSMUNVPVRTVVV", - "MWSMMV SMUV OSTS", - "MWQMNV QMTMVNVPSQPQ SQURUTTURVNV", - "LXVPUNTMRMPNOONQNSOUPVRVTUUT", - "MXQMNV QMUMVOVQUTTURVNV", - "MVQMNV QMVM PQSQ NVSV", - "MVQMNV QMVM PQSQ", - "LXVPUNTMRMPNOONQNSOUPVRVTUUSRS", - "MXQMNV WMTV PQUQ", - "PUTMQV", - "OVUMSSRUQVPVOUOT", - "MVQMNV VMOS RQTV", - "NVRMOV OVTV", - "LYPMMV PMQV XMQV XMUV", - "MXQMNV QMTV WMTV", - "LXRMPNOONQNSOUPVRVTUUTVRVPUNTMRM", - "MWQMNV QMUMVNVPUQSRPR", - "LXRMPNOONQNSOUPVRVTUUTVRVPUNTMRM QVPUPTQSRSSTTVUWVW", - "MWQMNV QMUMVNVPUQSRPR QRRUSVTVUU", - "MWVNTMRMPNPPQQTRUSUUSVPVNU", - "MVSMPV PMVM", - "LXPMNSNUOVRVTUUSWM", - "MWOMQV WMQV", - "KXNMNV SMNV SMSV XMSV", - "NWQMTV WMNV", - "NWQMSQQV WMSQ", - "MWQMWMNVTV", - "", - "", - "", - "", - "", - "", - "LXNMRV VMRV NMVM", - "MWNLVX", - "LXRONU ROVU", - "MWNVVV", - "PVRMUQ", - "MWMMOKQKTMVMWK", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NWQPTPUQUV URQSPTPUQVSVUU", - "MWOMOV OSPURVTUUSTQRPPQOS", - "MWUQSPRPPQOSPURVSVUU", - "MWUMUV USTQRPPQOSPURVTUUS", - "MWOSUSTQRPPQOSPURVTV", - "NVUNTMSMRNRV PPTP", - "MWUPUVTXRYPY USTQRPPQOSPURVTUUS", - "MWOMOV OSPQRPTQUSUV", - "PTRLQMRNSMRL RPRV", - "PUSLRMSNTMSL SPSXRYQYPX", - "NWPMPV UPPT RSUV", - "PTRMRV", - "KYMPMV MSNQOPPPQQRSRV RSSQTPUPVQWSWV", - "MWOPOV OSPQRPTQUSUV", - "MWRPPQOSPURVTUUSTQRP", - "MWOPOY OSPURVTUUSTQRPPQOS", - "MWUPUY USTQRPPQOSPURVTUUS", - "NVPPPV PSQQSPTP", - "NWUQTPQPPQPRQSTSUTUUTVQVPU", - "NVRMRUSVTVUU PPTP", - "MWUPUV OPOSPURVTUUS", - "NVOPRV UPRV", - "LXNPPV RPPV RPTV VPTV", - "MWOPUV UPOV", - "MWOPRV UPRVQXPYOY", - "MWOPUPOVUV", - "MXVPUSTURVPUOSPQRPTQUUVV", - "MWOTQVSVTUTSSRPQRQTPUOUNTMRMQNPPOTNY", - "MXNQOPQPRQRSQW VPURSTQWPY", - "MWTNSMRMQNQORPTQUSTURVPUOSPQRP", - "NWUQSPQPPQPRQS SSQSPTPUQVSVUU", - "NWTMSNSOTP UPSPQQPSPUQVSWSXRYQY", - "LXNQOPPPQQQSPV QSRQTPUPVQVSUVTY", - "LXNQOPPPQQQURVSVTUUSVPVNUMTMSNSPTRUSWT", - "OVRPQSQURVSVTU", - "MWQPOV UPTPRQPS PSQUSVTV", - "MWOMPMQNRPUV RPOV", - "LYPPMY UPTSSUQVPVOUOS TSTUUVVVWU", - "MWNPOPOV UPTSRUOV", - "NWTMSNSOTP UPSPQQQRRSTS SSQTPUPVQWSXSYRZQZ", - "MWRPPQOSPURVTUUSTQRP", - "MXOQQPVP QPQRPV TPTRUV", - "MWOSPURVTUUSTQRPPQOSNY", - "MXVPRPPQOSPURVTUUSTQRP", - "MXOQQPVP SPRV", - "KXMQNPOPPQPUQVSVTUUSVP", - "MXPPOQOSPURVSVUUVSVQUPTPSQRSQY", - "MWOPPPQQSXTYUY UPTRPWOY", - "KYTMRY MQNPOPPQPUQVTVUUVSWP", - "LXOPNRNTOVQVRTRR UPVRVTUVSVRT", - "LWTSSQQPOQNSOUQVSUTS UPTSTUUVVV", - "MWQMOSPURVTUUSTQRPPQOS", - "MWUQSPRPPQOSPURVTV", - "LWTSSQQPOQNSOUQVSUTS VMTSTUUVVV", - "MWOSTSURUQSPRPPQOSPURVTV", - "OVVMUMTNSPQVPXOYNY QPUP", - "MXUSTQRPPQOSPURVTUUS VPTVSXRYPYOX", - "MVQMNV OSPQQPSPTQTRSTSUTVUV", - "PUSMSNTNTMSM QPRPSQSRRTRUSVTV", - "OUSMSNTNTMSM QPRPSQSRRVQXPYOYNX", - "NVRMOV UPTPRQPS PSQUSVTV", - "OTSMQSQURVSV", - "JYKPLPMQMSLV MSNQOPQPRQRSQV RSSQTPVPWQWRVTVUWVXV", - "MWNPOPPQPSOV PSQQRPTPUQURTTTUUVVV", - "MWRPPQOSPURVTUUSTQRP", - "MXNPOPPQPSNY PSQUSVUUVSUQSPQQPS", - "MXUSTQRPPQOSPURVTUUS VPSY", - "MVOPPPQQQSPV UQTPSPRQQS", - "NVTQSPQPPQPRQSRSSTSURVPVOU", - "NUSMQSQURVSV PPTP", - "MWNPOPPQPROTOUPVRVSUTS UPTSTUUVVV", - "MWNPOPPQPROTOUPVRVTUURUP", - "KYLPMPNQNRMTMUNVPVQURSSP RSRUSVUVVUWRWP", - "MWOQPPQPRQRUSVTVUU VQUPTPSQQUPVOVNU", - "MWNPOPPQPROTOUPVRVSUTS UPSVRXQYOYNX", - "NVUPOV PQQPSPTQ PUQVSVTU", - "", - "", - "", - "", - "", - "", - "MWUSTQRPPQOSPURVTUUSUPTNRMQM", - "MWUQSPRPPQOSPURVSVUU OSSS", - "MWRMQNPPOSOVPWRWSVTTUQUNTMRM PRTR", - "MWTMQY RPPQOSPURVSVUUVSUQSPRP", - "MWUQSPQPOQOSPTRUSVSWRXQX", - "", - "", - "KYTPTSUTVTWSWQVOUNSMQMONNOMQMSNUOVQWSWUV TQSPQPPQPSQTSTTS", - "MWUNORUV", - "MWONUROV", - "OUTKQKQYTY", - "OUPKSKSYPY", - "OUTKSLRNROSQQRSSRURVSXTY", - "OUPKQLRNROQQSRQSRURVQXPY", - "LYPMQNQOPPOPNONNOMPMSNUNWMNV USTTTUUVVVWUWTVSUS", - "PT", - "NV", - "MWRMPNOPOSPURVTUUSUPTNRM", - "MWPORMRV", - "MWONQMSMUNUPTROVUV", - "MWONQMSMUNUPSQ RQSQURUUSVQVOU", - "MWSMSV SMNSVS", - "MWPMOQQPRPTQUSTURVQVOU PMTM", - "MWTMRMPNOPOSPURVTUUSTQRPPQOS", - "MWUMQV OMUM", - "MWQMONOPQQSQUPUNSMQM QQOROUQVSVUUURSQ", - "MWUPTRRSPROPPNRMTNUPUSTURVPV", - "PURURVSVSURU", - "PUSVRVRUSUSWRY", - "PURPRQSQSPRP RURVSVSURU", - "PURPRQSQSPRP SVRVRUSUSWRY", - "PURMRR SMSR RURVSVSURU", - "NWPNRMSMUNUPRQRRSRSQUP RURVSVSURU", - "PTRMRQ", - "NVPMPQ TMTQ", - "NVQMPNPPQQSQTPTNSMQM", - "MWRKRX UNSMQMONOPQQTRUSUUSVQVOU", - "MWVLNX", - "OUTKRNQQQSRVTY", - "OUPKRNSQSSRVPY", - "PTRKRY", - "LXNRVR", - "LXRNRV NRVR", - "LXNPVP NTVT", - "MWOOUU UOOU", - "MWRORU OPUT UPOT", - "PURQRRSRSQRQ", - "PUSMRORQSQSPRP", - "PUSNRNRMSMSORQ", - "LXSOVRSU NRVR", - "MXQLQY TLTY OQVQ OTVT", - "LXVRURTSSURVOVNUNSORRQSPSNRMPMONOPQSSUUVVV", - "LXNNOQOSNV VNUQUSVV NNQOSOVN NVQUSUVV", - "LYRQQPOPNQNSOTQTRSSQTPVPWQWSVTTTSSRQ", - "", - "H\\NRMQLRMSNR VRWQXRWSVR", - "H\\MPLQLRMSNSOROQNPMP MQMRNRNQMQ WPVQVRWSXSYRYQXPWP WQWRXRXQWQ", - "I[KRYR", - "", - "H\\RUJPRTZPRU", - "", - "", - "", - "", - "", - "F^ISJQLPNPPQTTVUXUZT[Q ISJPLONOPPTSVTXTZS[Q IYJWLVNVPWTZV[X[ZZ[W IYJVLUNUPVTYVZXZZY[W", - "", - "F^ISJQLPNPPQTTVUXUZT[Q ISJPLONOPPTSVTXTZS[Q IW[W I[[[", - "", - "CaGO]OXI L[GU]U", - "", - "D`F^^^^FFFF^", - "", - "KYQVOUNSNQOOQNSNUOVQVSUUSVQV SVVS QVVQ OUUO NSSN NQQN", - "", - "H\\IR[R", - "H\\IR[R IQ[Q", - "", - "LYPFSCSP RDRP OPVP MRXR OVOWNWNVOUQTTTVUWWVYTZQ[O\\N^Na TTUUVWUYTZ N`O_P_S`V`W_ P_SaVaW_W^", - "LYPFSCSP RDRP OPVP MRXR OVOWNWNVOUQTTTVUWWVYTZ TTUUVWUYTZ RZTZV[W]W^V`TaQaO`N_N^O^O_ TZU[V]V^U`Ta", - "LYPFSCSP RDRP OPVP MRXR VVVWWWWVVUTTRTPUOVNYN^O`QaTaV`W^W\\VZTYQYN[ RTPVOYO^P`Qa TaU`V^V\\UZTY", - "LYPFSCSP RDRP OPVP MRXR QTOUNWOYQZTZVYWWVUTTQT QTPUOWPYQZ TZUYVWUUTT QZO[N]N^O`QaTaV`W^W]V[TZ QZP[O]O^P`Qa TaU`V^V]U[TZ", - "LYOEOFNFNEODQCTCVDWFVHTIQJOKNMNP TCUDVFUHTI NOONPNSOVOWN PNSPVPWNWM MRXR OVOWNWNVOUQTTTVUWWVYTZ TTUUVWUYTZ RZTZV[W]W^V`TaQaO`N_N^O^O_ TZU[V]V^U`Ta", - "LYOEOFNFNEODQCTCVDWFVHTI TCUDVFUHTI RITIVJWLWMVOTPQPOONNNMOMON TIUJVLVMUOTP MRXR QTOUNWOYQZTZVYWWVUTTQT QTPUOWPYQZ TZUYVWUUTT QZO[N]N^O`QaTaV`W^W]V[TZ QZP[O]O^P`Qa TaU`V^V]U[TZ", - "LYOCNI OCVC ODSDVC NIOHQGTGVHWJWMVOTPQPOONNNMOMON TGUHVJVMUOTP MRXR QTOUNWOYQZTZVYWWVUTTQT QTPUOWPYQZ TZUYVWUUTT QZO[N]N^O`QaTaV`W^W]V[TZ QZP[O]O^P`Qa TaU`V^V]U[TZ", - "LYNCNG VERLPP WCTIQP NEPCRCUE NEPDRDUEVE MRXR QTOUNWOYQZTZVYWWVUTTQT QTPUOWPYQZ TZUYVWUUTT QZO[N]N^O`QaTaV`W^W]V[TZ QZP[O]O^P`Qa TaU`V^V]U[TZ", - "LYOCNI OCVC ODSDVC NIOHQGTGVHWJWMVOTPQPOONNNMOMON TGUHVJVMUOTP MRXR VVVWWWWVVUTTRTPUOVNYN^O`QaTaV`W^W\\VZTYQYN[ RTPVOYO^P`Qa TaU`V^V\\UZTY", - "LYPFSCSP RDRP OPVP MRXR SVSa TTTa TTM]X] QaVa", - "LYOEOFNFNEODQCTCVDWFVHTI TCUDVFUHTI RITIVJWLWMVOTPQPOONNNMOMON TIUJVLVMUOTP MRXR SVSa TTTa TTM]X] QaVa", - "F^YXWZU[R[PZMXKWIWHXHZI[K[MZOWPURQTKWGYFZF[G\\H[IZH[G[FZFYFWGVHTLRPPVNZMZ OPUP", - "E^P[MZJXHUGRGOHLJIMGPFTFWGYI[L\\O\\R[UYXVZS[P[ NJNW OJOW LJSJVKWMWNVPSQOQ SJUKVMVNUPSQ LWQW SQTRUVVWWWXV SQURVVWW", - "E^P[MZJXHUGRGOHLJIMGPFTFWGYI[L\\O\\R[UYXVZS[P[ UKVJVNUKSJPJNKMLLOLRMUNVPWSWUVVT PJNLMOMRNUPW", - "E_IM[M IR[R IW[W K[YI", - "CaHQGRHSIRHQ RQQRRSSRRQ \\Q[R\\S]R\\Q", - "", - "E_NWLTIRLPNM LPJRLT JRZR VWXT[RXPVM XPZRXT", - "JZWNTLRIPLMN PLRJTL RJRZ WVTXR[PXMV PXRZTX", - "F^ZJSJOKMLKNJQJSKVMXOYSZZZ SFS^", - "F^JJQJUKWLYNZQZSYVWXUYQZJZ QFQ^", - "F^JJQJUKWLYNZQZSYVWXUYQZJZ ORZR", - "", - "H\\LBL[ RBR[ XBX[", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "I[RFJ[ RFZ[ MTWT", - "G\\KFK[ KFTFWGXHYJYLXNWOTP KPTPWQXRYTYWXYWZT[K[", - "H]ZKYIWGUFQFOGMILKKNKSLVMXOZQ[U[WZYXZV", - "G\\KFK[ KFRFUGWIXKYNYSXVWXUZR[K[", - "H[LFL[ LFYF LPTP L[Y[", - "HZLFL[ LFYF LPTP", - "H]ZKYIWGUFQFOGMILKKNKSLVMXOZQ[U[WZYXZVZS USZS", - "G]KFK[ YFY[ KPYP", - "NVRFR[", - "JZVFVVUYTZR[P[NZMYLVLT", - "G\\KFK[ YFKT POY[", - "HYLFL[ L[X[", - "F^JFJ[ JFR[ ZFR[ ZFZ[", - "G]KFK[ KFY[ YFY[", - "G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF", - "G\\KFK[ KFTFWGXHYJYMXOWPTQKQ", - "G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF SWY]", - "G\\KFK[ KFTFWGXHYJYLXNWOTPKP RPY[", - "H\\YIWGTFPFMGKIKKLMMNOOUQWRXSYUYXWZT[P[MZKX", - "JZRFR[ KFYF", - "G]KFKULXNZQ[S[VZXXYUYF", - "I[JFR[ ZFR[", - "F^HFM[ RFM[ RFW[ \\FW[", - "H\\KFY[ YFK[", - "I[JFRPR[ ZFRP", - "H\\YFK[ KFYF K[Y[", - "I[RFJ[ RFZ[ MTWT", - "G\\KFK[ KFTFWGXHYJYLXNWOTP KPTPWQXRYTYWXYWZT[K[", - "HYLFL[ LFXF", - "I[RFJ[ RFZ[ J[Z[", - "H[LFL[ LFYF LPTP L[Y[", - "H\\YFK[ KFYF K[Y[", - "G]KFK[ YFY[ KPYP", - "G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF OPUP", - "NVRFR[", - "G\\KFK[ YFKT POY[", - "I[RFJ[ RFZ[", - "F^JFJ[ JFR[ ZFR[ ZFZ[", - "G]KFK[ KFY[ YFY[", - "I[KFYF OPUP K[Y[", - "G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF", - "G]KFK[ YFY[ KFYF", - "G\\KFK[ KFTFWGXHYJYMXOWPTQKQ", - "I[KFRPK[ KFYF K[Y[", - "JZRFR[ KFYF", - "I[KKKILGMFOFPGQIRMR[ YKYIXGWFUFTGSIRM", - "H\\RFR[ PKMLLMKOKRLTMUPVTVWUXTYRYOXMWLTKPK", - "H\\KFY[ K[YF", - "G]RFR[ ILJLKMLQMSNTQUSUVTWSXQYMZL[L", - "H\\K[O[LTKPKLLINGQFSFVGXIYLYPXTU[Y[", - "G[G[IZLWOSSLVFV[UXSUQSNQLQKRKTLVNXQZT[Y[", - "F]SHTITLSPRSQUOXMZK[J[IZIWJRKOLMNJPHRGUFXFZG[I[KZMYNWOTP SPTPWQXRYTYWXYWZU[R[PZOX", - "H\\TLTMUNWNYMZKZIYGWFTFQGOIMLLNKRKVLYMZO[Q[TZVXWV", - "G^TFRGQIPMOSNVMXKZI[G[FZFXGWIWKXMZP[S[VZXXZT[O[KZHYGWFTFRHRJSMUPWRZT\\U", - "H\\VJVKWLYLZKZIYGVFRFOGNINLONPOSPPPMQLRKTKWLYMZP[S[VZXXYV", - "H\\RLPLNKMINGQFTFXG[G]F XGVNTTRXPZN[L[JZIXIVJULUNV QPZP", - "G^G[IZMVPQQNRJRGQFPFOGNINLONQOUOXNYMZKZQYVXXVZS[O[LZJXIVIT", - "F^MMKLJJJIKGMFNFPGQIQKPONULYJ[H[GZGX MRVOXN[L]J^H^G]F\\FZHXLVRUWUZV[W[YZZY\\V", - "IZWVUTSQROQLQIRGSFUFVGWIWLVQTVSXQZO[M[KZJXJVKUMUOV", - "JYT^R[PVOPOJPGRFTFUGVJVMURR[PaOdNfLgKfKdLaN^P\\SZWX", - "F^MMKLJJJIKGMFNFPGQIQKPONULYJ[H[GZGX ^I^G]F\\FZGXIVLTNROPO ROSQSXTZU[V[XZYY[V", - "I\\MRORSQVOXMYKYHXFVFUGTISNRSQVPXNZL[J[IZIXJWLWNXQZT[V[YZ[X", - "@aEMCLBJBICGEFFFHGIIIKHPGTE[ GTJLLHMGOFPFRGSISKRPQTO[ QTTLVHWGYFZF\\G]I]K\\PZWZZ[[\\[^Z_YaV", - "E]JMHLGJGIHGJFKFMGNINKMPLTJ[ LTOLQHRGTFVFXGYIYKXPVWVZW[X[ZZ[Y]V", - "H]TFQGOIMLLNKRKVLYMZO[Q[TZVXXUYSZOZKYHXGVFTFRHRKSNUQWSZU\\V", - "F_SHTITLSPRSQUOXMZK[J[IZIWJRKOLMNJPHRGUFZF\\G]H^J^M]O\\PZQWQUPTO", - "H^ULTNSOQPOPNNNLOIQGTFWFYGZIZMYPWSSWPYNZK[I[HZHXIWKWMXPZS[V[YZ[X", - "F_SHTITLSPRSQUOXMZK[J[IZIWJRKOLMNJPHRGUFYF[G\\H]J]M\\O[PYQVQSPTQUSUXVZX[ZZ[Y]V", - "H\\H[JZLXOTQQSMTJTGSFRFQGPIPKQMSOVQXSYUYWXYWZT[P[MZKXJVJT", - "H[RLPLNKMINGQFTFXG[G]F XGVNTTRXPZN[L[JZIXIVJULUNV", - "E]JMHLGJGIHGJFKFMGNINKMOLRKVKXLZN[P[RZSYUUXMZF XMWQVWVZW[X[ZZ[Y]V", - "F]KMILHJHIIGKFLFNGOIOKNOMRLVLYM[O[QZTWVTXPYMZIZGYFXFWGVIVKWNYP[Q", - "C_HMFLEJEIFGHFIFKGLILLK[ UFK[ UFS[ aF_G\\JYNVTS[", - "F^NLLLKKKILGNFPFRGSISLQUQXRZT[V[XZYXYVXUVU ]I]G\\FZFXGVITLPUNXLZJ[H[GZGX", - "F]KMILHJHIIGKFLFNGOIOKNOMRLVLXMZN[P[RZTXVUWSYM [FYMVWT]RbPfNgMfMdNaP^S[VY[V", - "H]ULTNSOQPOPNNNLOIQGTFWFYGZIZMYPWTTWPZN[K[JZJXKWNWPXQYR[R^QaPcNfLgKfKdLaN^Q[TYZV", - "", - "", - "", - "", - "", - "", - "I[JFR[ ZFR[ JFZF", - "G]IL[b", - "E_RJIZ RJ[Z", - "I[J[Z[", - "I[J[Z[ZZJZJ[", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "I\\XMX[ XPVNTMQMONMPLSLUMXOZQ[T[VZXX", - "H[LFL[ LPNNPMSMUNWPXSXUWXUZS[P[NZLX", - "I[XPVNTMQMONMPLSLUMXOZQ[T[VZXX", - "I\\XFX[ XPVNTMQMONMPLSLUMXOZQ[T[VZXX", - "I[LSXSXQWOVNTMQMONMPLSLUMXOZQ[T[VZXX", - "MYWFUFSGRJR[ OMVM", - "I\\XMX]W`VaTbQbOa XPVNTMQMONMPLSLUMXOZQ[T[VZXX", - "I\\MFM[ MQPNRMUMWNXQX[", - "NVQFRGSFREQF RMR[", - "MWRFSGTFSERF SMS^RaPbNb", - "IZMFM[ WMMW QSX[", - "NVRFR[", - "CaGMG[ GQJNLMOMQNRQR[ RQUNWMZM\\N]Q][", - "I\\MMM[ MQPNRMUMWNXQX[", - "I\\QMONMPLSLUMXOZQ[T[VZXXYUYSXPVNTMQM", - "H[LMLb LPNNPMSMUNWPXSXUWXUZS[P[NZLX", - "I\\XMXb XPVNTMQMONMPLSLUMXOZQ[T[VZXX", - "KXOMO[ OSPPRNTMWM", - "J[XPWNTMQMNNMPNRPSUTWUXWXXWZT[Q[NZMX", - "MYRFRWSZU[W[ OMVM", - "I\\MMMWNZP[S[UZXW XMX[", - "JZLMR[ XMR[", - "G]JMN[ RMN[ RMV[ ZMV[", - "J[MMX[ XMM[", - "JZLMR[ XMR[P_NaLbKb", - "J[XMM[ MMXM M[X[", - "H]QMONMPLRKUKXLZN[P[RZUWWTYPZM QMSMTNUPWXXZY[Z[", - "I\\UFSGQIOMNPMTLZKb UFWFYHYKXMWNUORO ROTPVRWTWWVYUZS[Q[OZNYMV", - "I\\JPLNNMOMQNROSRSVR[ ZMYPXRR[P_Ob", - "I[TMQMONMPLSLVMYNZP[R[TZVXWUWRVOTMRKQIQGRFTFVGXI", - "JZWOVNTMQMONOPPRSS SSOTMVMXNZP[S[UZWX", - "JYTFRGQHQIRJUKXK XKTMQONRMUMWNYP[S]T_TaSbQbP`", - "H\\IQJOLMNMONOPNTL[ NTPPRNTMVMXOXRWWTb", - "G\\HQIOKMMMNNNPMUMXNZO[Q[SZUWVUWRXMXJWGUFSFRHRJSMUPWRZT", - "LWRMPTOXOZP[R[TYUW", - "I[OMK[ YNXMWMUNQROSNS NSPTQUSZT[U[VZ", - "JZKFMFOGPHX[ RML[", - "H]OMIb NQMVMYO[Q[SZUXWT YMWTVXVZW[Y[[Y\\W", - "I[LMOMNSMXL[ YMXPWRUURXOZL[", - "JZTFRGQHQIRJUKXK UKRLPMOOOQQSTTVT TTPUNVMXMZO\\S^T_TaRbPb", - "J[RMPNNPMSMVNYOZQ[S[UZWXXUXRWOVNTMRM", - "G]PML[ UMVSWXX[ IPKNNM[M", - "I[MSMVNYOZQ[S[UZWXXUXRWOVNTMRMPNNPMSIb", - "I][MQMONMPLSLVMYNZP[R[TZVXWUWRVOUNSM", - "H\\SMP[ JPLNOMZM", - "H\\IQJOLMNMONOPMVMYO[Q[TZVXXTYPYM", - "G]ONMOKQJTJWKYLZN[Q[TZWXYUZRZOXMVMTORSPXMb", - "I[KMMMOOU`WbYb ZMYOWRM]K`Jb", - "F]VFNb GQHOJMLMMNMPLULXMZO[Q[TZVXXUZP[M", - "F]NMLNJQITIWJZK[M[OZQW RSQWRZS[U[WZYWZTZQYNXM", - "L\\UUTSRRPRNSMTLVLXMZO[Q[SZTXVRUWUZV[W[YZZY\\V", - "M[MVOSRNSLTITGSFQGPIOMNTNZO[P[RZTXUUURVVWWYW[V", - "MXTTTSSRQROSNTMVMXNZP[S[VYXV", - "L\\UUTSRRPRNSMTLVLXMZO[Q[SZTXZF VRUWUZV[W[YZZY\\V", - "NXOYQXRWSUSSRRQROSNUNXOZQ[S[UZVYXV", - "OWOVSQUNVLWIWGVFTGSIQQNZKaJdJfKgMfNcOZP[R[TZUYWV", - "L[UUTSRRPRNSMTLVLXMZO[Q[SZTY VRTYPdOfMgLfLdMaP^S\\U[XY[V", - "M\\MVOSRNSLTITGSFQGPIOMNSM[ M[NXOVQSSRURVSVUUXUZV[W[YZZY\\V", - "PWSMSNTNTMSM PVRRPXPZQ[R[TZUYWV", - "PWSMSNTNTMSM PVRRLdKfIgHfHdIaL^O\\Q[TYWV", - "M[MVOSRNSLTITGSFQGPIOMNSM[ M[NXOVQSSRURVSVUTVQV QVSWTZU[V[XZYY[V", - "OWOVQSTNULVIVGUFSGRIQMPTPZQ[R[TZUYWV", - "E^EVGSIRJSJTIXH[ IXJVLSNRPRQSQTPXO[ PXQVSSURWRXSXUWXWZX[Y[[Z\\Y^V", - "J\\JVLSNROSOTNXM[ NXOVQSSRURVSVUUXUZV[W[YZZY\\V", - "LZRRPRNSMTLVLXMZO[Q[SZTYUWUUTSRRQSQURWTXWXYWZV", - "KZKVMSNQMUGg MUNSPRRRTSUUUWTYSZQ[ MZO[R[UZWYZV", - "L[UUTSRRPRNSMTLVLXMZO[Q[SZ VRUUSZPaOdOfPgRfScS\\U[XY[V", - "MZMVOSPQPSSSTTTVSYSZT[U[WZXYZV", - "NYNVPSQQQSSVTXTZR[ NZP[T[VZWYYV", - "OXOVQSSO VFPXPZQ[S[UZVYXV PNWN", - "L[LVNRLXLZM[O[QZSXUU VRTXTZU[V[XZYY[V", - "L[LVNRMWMZN[O[RZTXUUUR URVVWWYW[V", - "I^LRJTIWIYJ[L[NZPX RRPXPZQ[S[UZWXXUXR XRYVZW\\W^V", - "JZJVLSNRPRQSQZR[U[XYZV WSVRTRSSOZN[L[KZ", - "L[LVNRLXLZM[O[QZSXUU VRPdOfMgLfLdMaP^S\\U[XY[V", - "LZLVNSPRRRTTTVSXQZN[P\\Q^QaPdOfMgLfLdMaP^S\\WYZV", - "J\\K[NZQXSVUSWOXKXIWGUFSGRHQJPOPTQXRZT[V[XZYY", - "", - "", - "", - "", - "", - "I[WUWRVOUNSMQMONMPLSLVMYNZP[R[TZVXWUXPXKWHVGTFRFPGNI", - "JZWNUMRMPNNPMSMVNYOZQ[T[VZ MTUT", - "J[TFRGPJOLNOMTMXNZO[Q[SZUWVUWRXMXIWGVFTF NPWP", - "H\\VFNb QMNNLPKSKVLXNZQ[S[VZXXYUYRXPVNSMQM", - "I[XOWNTMQMNNMOLQLSMUOWSZT\\T^S_Q_", - "", - "", - "DaWNVLTKQKOLNMMOMRNTOUQVTVVUWS WKWSXUYV[V\\U]S]O\\L[JYHWGTFQFNGLHJJILHOHRIUJWLYNZQ[T[WZYY", - "F^ZIJRZ[", - "F^JIZRJ[", - "KYOBOb OBVB ObVb", - "KYUBUb NBUB NbUb", - "KYTBQEPHPJQMSOSPORSTSUQWPZP\\Q_Tb", - "KYPBSETHTJSMQOQPURQTQUSWTZT\\S_Pb", - "F^[FYGVHSHPGNFLFJGIIIKKMMMOLPJPHNF [FI[ YTWTUUTWTYV[X[ZZ[X[VYT", - "NV", - "JZ", - "H\\QFNGLJKOKRLWNZQ[S[VZXWYRYOXJVGSFQF", - "H\\NJPISFS[", - "H\\LKLJMHNGPFTFVGWHXJXLWNUQK[Y[", - "H\\MFXFRNUNWOXPYSYUXXVZS[P[MZLYKW", - "H\\UFKTZT UFU[", - "H\\WFMFLOMNPMSMVNXPYSYUXXVZS[P[MZLYKW", - "H\\XIWGTFRFOGMJLOLTMXOZR[S[VZXXYUYTXQVOSNRNOOMQLT", - "H\\YFO[ KFYF", - "H\\PFMGLILKMMONSOVPXRYTYWXYWZT[P[MZLYKWKTLRNPQOUNWMXKXIWGTFPF", - "H\\XMWPURRSQSNRLPKMKLLINGQFRFUGWIXMXRWWUZR[P[MZLX", - "MWRYQZR[SZRY", - "MWSZR[QZRYSZS\\R^Q_", - "MWRMQNROSNRM RYQZR[SZRY", - "MWRMQNROSNRM SZR[QZRYSZS\\R^Q_", - "MWRFRT RYQZR[SZRY", - "I[LKLJMHNGPFTFVGWHXJXLWNVORQRT RYQZR[SZRY", - "NVRFRM", - "JZNFNM VFVM", - "KYQFOGNINKOMQNSNUMVKVIUGSFQF", - "H\\PBP_ TBT_ YIWGTFPFMGKIKKLMMNOOUQWRXSYUYXWZT[P[MZKX", - "G][BIb", - "KYVBTDRGPKOPOTPYR]T`Vb", - "KYNBPDRGTKUPUTTYR]P`Nb", - "NVRBRb", - "E_IR[R", - "E_RIR[ IR[R", - "E_IO[O IU[U", - "G]KKYY YKKY", - "JZRLRX MOWU WOMU", - "MWRQQRRSSRRQ", - "MWSFRGQIQKRLSKRJ", - "MWRHQGRFSGSIRKQL", - "E_UMXP[RXTUW IR[R", - "G]OFOb UFUb JQZQ JWZW", - "E_\\O\\N[MZMYNXPVUTXRZP[L[JZIYHWHUISJRQNRMSKSIRGPFNGMIMKNNPQUXWZY[[[\\Z\\Y", - "G]IIJKKOKUJYI[ [IZKYOYUZY[[ IIKJOKUKYJ[I I[KZOYUYYZ[[", - "F_\\Q[OYNWNUOTPQTPUNVLVJUISIQJOLNNNPOQPTTUUWVYV[U\\S\\Q", - "KYOBO[ UBU[", - "F^RBR[ I[[[", - "F^[BI[[[", - "E_RIQJRKSJRI IYHZI[JZIY [YZZ[[\\Z[Y", - "F^RHNLKPJSJUKWMXOXQWRU RHVLYPZSZUYWWXUXSWRU RUQYP\\ RUSYT\\ P\\T\\", - "F^RNQKPINHMHKIJKJOKRLTNWR\\ RNSKTIVHWHYIZKZOYRXTVWR\\", - "F^RGPJLOIR RGTJXO[R IRLUPZR] [RXUTZR]", - "F^RTTWVXXXZW[U[SZQXPVPSQ SQUOVMVKUISHQHOINKNMOOQQ QQNPLPJQISIUJWLXNXPWRT RTQYP\\ RTSYT\\ P\\T\\", - "F^RRR[Q\\ RVQ\\ RIQHOHNINKONRR RISHUHVIVKUNRR RRNOLNJNIOIQJR RRVOXNZN[O[QZR RRNULVJVIUISJR RRVUXVZV[U[SZR", - "F^ISJSLTMVMXLZ ISIRJQLQMRNTNWMYLZ RGPIOLOOQUQXPZR\\ RGTIULUOSUSXTZR\\ [S[RZQXQWRVTVWWYXZ [SZSXTWVWXXZ KVYV", - "", - "", - "", - "PSSRRSQSPRPQQPRPSQSSRUQV QQQRRRRQQQ", - "PTQPPQPSQTSTTSTQSPQP RQQRRSSRRQ", - "NVPOTU TOPU NRVR", - "MWRKQMOPMR RKSMUPWR RMOQ RMUQ ROPQ ROTQ QQSQ MRWR", - "MWMRMQNOONQMSMUNVOWQWR PNTN OOUO NPVP NQVQ MRWR", - "LRLFLRRRLF LIPQ LLOR LOMQ", - "MWRKQMOPMR RKSMUPWR", - "MWWRWQVOUNSMQMONNOMQMR", - "G]]R]P\\MZJWHTGPGMHJJHMGPGR", - "MWMRMSNUOVQWSWUVVUWSWR", - "LXLPNRQSSSVRXP", - "RURUTTURTPRO", - "RVRRUPVNVLUKTK", - "NRRROPNNNLOKPK", - "MWWHVGTFQFOGNHMJMLNNOOUSVTWVWXVZU[S\\P\\N[MZ", - "G]IWHVGTGQHOINKMMMONPOTUUVWWYW[V\\U]S]P\\N[M", - "G]RRTUUVWWYW[V\\U]S]Q\\O[NYMWMUNTOPUOVMWKWIVHUGSGQHOINKMMMONPORR", - "H\\KFK[ HF[FQP[Z ZV[Y\\[ ZVZY WYZY WYZZ\\[", - "KYUARBPCNELHKLKRLUNWQXSXVWXUYR KPLMNKQJSJVKXMYPYVXZV]T_R`Oa", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - ">f>RfR", - "D`D``D", - "RRR>Rf", - "D`DD``", - "D`DR`R", - "F^FY^K", - "KYK^YF", - "", - "KYKFY^", - "F^FK^Y", - "KYKRYR", - "MWMWWM", - "", - "MWMMWW", - "", - "", - "", - "", - "D`DOGQKSPTTTYS]Q`O", - "PUUDSGQKPPPTQYS]U`", - "OTODQGSKTPTTSYQ]O`", - "D`DUGSKQPPTPYQ]S`U", - "KYRJYNKVRZ", - "JZJRNKVYZR", - "KYKVKNYVYN", - "JZLXJPZTXL", - "JZJ]L]O\\Q[TXUVVSVOULTJSIQIPJOLNONSOVPXS[U\\X]Z]", - "I]]Z]X\\U[SXPVOSNONLOJPIQISJTLUOVSVVUXT[Q\\O]L]J", - "JZZGXGUHSIPLONNQNUOXPZQ[S[TZUXVUVQUNTLQIOHLGJG", - "G[GJGLHOIQLTNUQVUVXUZT[S[QZPXOUNQNNOLPISHUGXGZ", - "E[EPFRHTJUMVQVUUXSZP[NZLWLSMQNNPLSKVKYL\\M^", - "EYETHVKWPWSVVTXQYNYLXKVKSLPNNQMTMYN\\P_", - "OUQOOQOSQUSUUSUQSOQO QPPQPSQTSTTSTQSPQP RQQRRSSRRQ", - "", - "D`DRJR ORUR ZR`R", - "D`DUDO`O`U", - "JZRDJR RDZR", - "D`DR`R JYZY P`T`", - "D`DR`R DRRb `RRb", - "", - "", - "", - "", - "", - "KYQKNLLNKQKSLVNXQYSYVXXVYSYQXNVLSKQK", - "LXLLLXXXXLLL", - "KYRJKVYVRJ", - "LXRHLRR\\XRRH", - "JZRIPOJOOSMYRUWYUSZOTORI", - "KYRKRY KRYR", - "MWMMWW WMMW", - "MWRLRX MOWU WOMU", - "", - "", - "NVQNOONQNSOUQVSVUUVSVQUOSNQN OQOS PPPT QOQU RORU SOSU TPTT UQUS", - "NVNNNVVVVNNN OOOU POPU QOQU RORU SOSU TOTU UOUU", - "MWRLMUWURL ROOT ROUT RRQT RRST", - "LULRUWUMLR ORTU ORTO RRTS RRTQ", - "MWRXWOMORX RUUP RUOP RRSP RRQP", - "OXXROMOWXR URPO URPU RRPQ RRPS", - "LXRLNWXPLPVWRL RRRL RRLP RRNW RRVW RRXP", - "", - "", - "", - "MWRLRX OOUO MUOWQXSXUWWU", - "LXRLRX LQMOWOXQ PWTW", - "KYMNWX WNMX OLLOKQ ULXOYQ", - "I[NII[ VI[[ MM[[ WMI[ NIVI MMWM", - "I[RGRV MJWP WJMP IVL\\ [VX\\ IV[V L\\X\\", - "G[MJSV KPSL G\\[\\[RG\\", - "LXPLPPLPLTPTPXTXTTXTXPTPTLPL", - "KYYPXNVLSKQKNLLNKQKSLVNXQYSYVXXVYT YPWNUMSMQNPOOQOSPUQVSWUWWVYT", - "KYRJKVYVRJ RZYNKNRZ", - "G]PIPGQFSFTGTI GZHXJVKTLPLKMJOIUIWJXKXPYTZV\\X]Z GZ]Z QZP[Q\\S\\T[SZ", - "JZRMRS RSQ\\ RSS\\ Q\\S\\ RMQJPHNG QJNG RMSJTHVG SJVG RMNKLKJM PLLLJM RMVKXKZM TLXLZM RMPNOOOR RMPOOR RMTNUOUR RMTOUR", - "JZRIRK RNRP RSRU RYQ\\ RYS\\ Q\\S\\ RGQIPJ RGSITJ PJRITJ RKPNNOMN RKTNVOWN NOPORNTOVO RPPSNTLTKRKSLT RPTSVTXTYRYSXT NTPTRSTTVT RUPXOYMZLZKYJWJYLZ RUTXUYWZXZYYZWZYXZ MZOZRYUZWZ", - "JZRYQ\\ RYS\\ Q\\S\\ RYUZXZZXZUYTWTYRZOYMWLUMVJUHSGQGOHNJOMMLKMJOKRMTKTJUJXLZOZRY", - "JZRYQ\\ RYS\\ Q\\S\\ RYVXVVXUXRZQZLYIXHVHTGPGNHLHKIJLJQLRLUNVNXRY", - "I[IPKR LKNP RGRO XKVP [PYR", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "QSRQQRRSSRRQ", - "PTQPPQPSQTSTTSTQSPQP", - "NVQNOONQNSOUQVSVUUVSVQUOSNQN", - "MWQMONNOMQMSNUOVQWSWUVVUWSWQVOUNSMQM", - "KYQKNLLNKQKSLVNXQYSYVXXVYSYQXNVLSKQK", - "G]PGMHJJHMGPGTHWJZM\\P]T]W\\ZZ\\W]T]P\\MZJWHTGPG", - "AcPALBJCGEEGCJBLAPATBXCZE]G_JaLbPcTcXbZa]__]aZbXcTcPbLaJ_G]EZCXBTAPA", - "fRAPCMDJDGCEA>H@JAMAZB]D_G`M`PaRc RATCWDZD]C_AfHdJcMcZb]`_]`W`TaRc", - "AcRAPCMDJDGCEABGAKAPBTDXG\\L`Rc RATCWDZD]C_AbGcKcPbT`X]\\X`Rc BHbH", - "H[WPVQWRXQXPVNTMQMNNLPKSKULXNZQ[S[VZXX QMONMPLSLUMXOZQ[ LbXF", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "KYRKMX RNVX RKWX OTTT KXPX TXYX", - "JZNKNX OKOX LKSKVLWNVPSQ SKULVNUPSQ OQSQVRWTWUVWSXLX SQURVTVUUWSX", - "KYVLWKWOVLTKQKOLNMMPMSNVOWQXTXVWWU QKOMNPNSOVQX", - "JZNKNX OKOX LKSKVLWMXPXSWVVWSXLX SKULVMWPWSVVUWSX", - "JYNKNX OKOX SOSS LKVKVOUK OQSQ LXVXVTUX", - "JXNKNX OKOX SOSS LKVKVOUK OQSQ LXQX", - "K[VLWKWOVLTKQKOLNMMPMSNVOWQXTXVW QKOMNPNSOVQX TXUWVU VSVX WSWX TSYS", - "J[NKNX OKOX VKVX WKWX LKQK TKYK OQVQ LXQX TXYX", - "NWRKRX SKSX PKUK PXUX", - "LXSKSURWQX TKTUSWQXPXNWMUNTOUNV QKVK", - "JZNKNX OKOX WKOS QQVX RQWX LKQK TKYK LXQX TXYX", - "KXOKOX PKPX MKRK MXWXWTVX", - "I\\MKMX NNRX NKRU WKRX WKWX XKXX KKNK WKZK KXOX UXZX", - "JZNKNX OMVX OKVV VKVX LKOK TKXK LXPX", - "KZQKOLNMMPMSNVOWQXTXVWWVXSXPWMVLTKQK QKOMNPNSOVQX TXVVWSWPVMTK", - "JYNKNX OKOX LKSKVLWNWOVQSROR SKULVNVOUQSR LXQX", - "KZQKOLNMMPMSNVOWQXTXVWWVXSXPWMVLTKQK QKOMNPNSOVQX TXVVWSWPVMTK PWPUQTSTTUUZV[W[XZ TUUXVZW[", - "JZNKNX OKOX LKSKVLWNWOVQSROR SKULVNVOUQSR LXQX SRTSUWVXWXXW SRUSVWWX", - "KZVMWKWOVMULSKQKOLNMNOOPQQTRVSWT NNOOQPTQVRWSWVVWTXRXPWOVNTNXOV", - "KZRKRX SKSX NKMOMKXKXOWK PXUX", - "J[NKNUOWQXTXVWWUWK OKOUPWQX LKQK UKYK", - "KYMKRX NKRU WKRX KKPK TKYK", - "I[LKOX MKOT RKOX RKUX SKUT XKUX JKOK VKZK", - "KZNKVX OKWX WKNX LKQK TKYK LXQX TXYX", - "LYNKRRRX OKSR WKSRSX LKQK TKYK PXUX", - "LYVKNX WKOX OKNONKWK NXWXWTVX", - "KYRKMX RNVX RKWX OTTT KXPX TXYX", - "JZNKNX OKOX LKSKVLWNVPSQ SKULVNUPSQ OQSQVRWTWUVWSXLX SQURVTVUUWSX", - "KXOKOX PKPX MKWKWOVK MXRX", - "KYRKLX RMWX RKXX MWVW LXXX", - "JYNKNX OKOX SOSS LKVKVOUK OQSQ LXVXVTUX", - "LYVKNX WKOX OKNONKWK NXWXWTVX", - "J[NKNX OKOX VKVX WKWX LKQK TKYK OQVQ LXQX TXYX", - "KZQKOLNMMPMSNVOWQXTXVWWVXSXPWMVLTKQK QKOMNPNSOVQX TXVVWSWPVMTK QOQT TOTT QQTQ QRTR", - "NWRKRX SKSX PKUK PXUX", - "JZNKNX OKOX WKOS QQVX RQWX LKQK TKYK LXQX TXYX", - "KYRKMX RNVX RKWX KXPX TXYX", - "I\\MKMX NNRX NKRU WKRX WKWX XKXX KKNK WKZK KXOX UXZX", - "JZNKNX OMVX OKVV VKVX LKOK TKXK LXPX", - "JZMJLM XJWM PPOS UPTS MVLY XVWY MKWK MLWL PQTQ PRTR MWWW MXWX", - "KZQKOLNMMPMSNVOWQXTXVWWVXSXPWMVLTKQK QKOMNPNSOVQX TXVVWSWPVMTK", - "J[NKNX OKOX VKVX WKWX LKYK LXQX TXYX", - "JYNKNX OKOX LKSKVLWNWOVQSROR SKULVNVOUQSR LXQX", - "K[MKRQ NKSQMX MKWKXOVK NWWW MXWXXTVX", - "KZRKRX SKSX NKMOMKXKXOWK PXUX", - "KZMONLOKPKQLRORX XOWLVKUKTLSOSX MONMOLPLQMRO XOWMVLULTMSO PXUX", - "KZRKRX SKSX QNNOMQMRNTQUTUWTXRXQWOTNQN QNOONQNROTQU TUVTWRWQVOTN PKUK PXUX", - "KZNKVX OKWX WKNX LKQK TKYK LXQX TXYX", - "J[RKRX SKSX LPMONOOSQU TUVSWOXOYP MONROTQUTUVTWRXO PKUK PXUX", - "KZMVNXQXMRMONMOLQKTKVLWMXOXRTXWXXV OUNRNOOMQK TKVMWOWRVU NWPW UWWW", - "KYTKKX SMTX TKUX NTTT IXNX RXWX", - "JYPKLX QKMX NKUKWLWNVPSQ UKVLVNUPSQ OQRQTRUSUUTWQXJX RQTSTUSWQX", - "KXVLWLXKWNVLTKRKPLOMNOMRMUNWPXRXTWUU RKPMOONRNVPX", - "JYPKLX QKMX NKTKVLWNWQVTUVTWQXJX TKULVNVQUTTVSWQX", - "JYPKLX QKMX SORS NKXKWNWK OQRQ JXTXUUSX", - "JXPKLX QKMX SORS NKXKWNWK OQRQ JXOX", - "KYVLWLXKWNVLTKRKPLOMNOMRMUNWPXRXTWUVVS RKPMOONRNVPX RXTVUS SSXS", - "J[PKLX QKMX XKTX YKUX NKSK VK[K OQVQ JXOX RXWX", - "NWTKPX UKQX RKWK NXSX", - "LXUKRUQWPX VKSURWPXOXMWLUMTNUMV SKXK", - "JZPKLX QKMX YKOR RPTX SPUX NKSK VK[K JXOX RXWX", - "KXQKMX RKNX OKTK KXUXVUTX", - "I\\OKKX OMPX PKQV YKPX YKUX ZKVX MKPK YK\\K IXMX SXXX", - "JZPKLX PKTX QKTU XKTX NKQK VKZK JXNX", - "KYRKPLOMNOMRMUNWPXRXTWUVVTWQWNVLTKRK RKPMOONRNVPX RXTVUTVQVMTK", - "JYPKLX QKMX NKUKWLXMXOWQTROR UKWMWOVQTR JXOX", - "KYRKPLOMNOMRMUNWPXRXTWUVVTWQWNVLTKRK RKPMOONRNVPX RXTVUTVQVMTK OWOVPUQURVRZS[T[UZ RVSZT[", - "JZPKLX QKMX NKUKWLXMXOWQTROR UKWMWOVQTR SRTWUXVXWW SRTSUWVX JXOX", - "KZWLXLYKXNWLUKRKPLOMOOPPUSVT ONPOURVSVVUWSXPXNWMULXMWNW", - "KZTKPX UKQX PKNNOKZKYNYK NXSX", - "J[PKMUMWOXSXUWVUYK QKNUNWOX NKSK WK[K", - "KYOKPX PKQV YKPX MKRK VK[K", - "I[NKMX OKNV TKMX TKSX UKTV ZKSX LKQK XK\\K", - "KZPKTX QKUX YKLX NKSK VK[K JXOX RXWX", - "LYPKRQPX QKSQ YKSQQX NKSK VK[K NXSX", - "LYXKLX YKMX QKONPKYK LXUXVUTX", - "", - "", - "", - "", - "", - "", - "", - "KZMHX\\", - "JZRMLW RMXW", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "LZQOPPPQOQOPQOTOVQVWWXXX TOUQUWWX URRSPTOUOWPXSXTWUU RSPUPWQX", - "JYNKNX OKOX ORPPROTOVPWRWUVWTXRXPWOU TOUPVRVUUWTX LKOK", - "LXVQUQURVRVQUPSOQOOPNRNUOWQXSXUWVV QOPPOROUPWQX", - "L[VKVX WKWX VRUPSOQOOPNRNUOWQXSXUWVU QOPPOROUPWQX TKWK VXYX", - "LXOSVSVRUPSOQOOPNRNUOWQXSXUWVV USUQSO QOPPOROUPWQX", - "LWTKULUMVMVLTKRKPMPX RKQMQX NOSO NXSX", - "LYQOOQOSQUSUUSUQSOQO QOPQPSQU SUTSTQSO TPUOVO PTOUOXPYTYVZ OWPXTXVYV[T\\P\\N[NYPX", - "J[NKNX OKOX ORPPROTOVPWRWX TOUPVRVX LKOK LXQX TXYX", - "NWRKRLSLSKRK RORX SOSX POSO PXUX", - "NWSKSLTLTKSK SOSZR\\ TOTZR\\P\\O[OZPZP[O[ QOTO", - "JZNKNX OKOX WOOU RSVX SSWX LKOK TOYO LXQX TXYX", - "NWRKRX SKSX PKSK PXUX", - "F_JOJX KOKX KRLPNOPORPSRSX POQPRRRX SRTPVOXOZP[R[X XOYPZRZX HOKO HXMX PXUX XX]X", - "J[NONX OOOX ORPPROTOVPWRWX TOUPVRVX LOOO LXQX TXYX", - "LYQOOPNRNUOWQXTXVWWUWRVPTOQO QOPPOROUPWQX TXUWVUVRUPTO", - "JYNON\\ OOO\\ ORPPROTOVPWRWUVWTXRXPWOU TOUPVRVUUWTX LOOO L\\Q\\", - "KYUOU\\ VOV\\ URTPROPONPMRMUNWPXRXTWUU POOPNRNUOWPX S\\X\\", - "KXOOOX POPX PRQPSOUOVPVQUQUPVP MOPO MXRX", - "LYTOUPUQVQVPTOQOOPORQSTTVU OQQRTSVTVWTXQXOWOVPVPWQX", - "LWPKPVRXTXUWUV QKQVRX NOTO", - "J[NONUOWQXSXUWVU OOOUPWQX VOVX WOWX LOOO TOWO VXYX", - "KYNORX OORV VORX LOQO TOXO", - "I[LOOX MOOU ROOX ROUX SOUU XOUX JOOO VOZO", - "KYNOUX OOVX VONX LOQO TOXO LXPX SXXX", - "KYNORX OORV VORXP[N\\M\\L[LZMZM[L[ LOQO TOXO", - "LXUONX VOOX OONQNOVO NXVXVVUX", - "K[QOOPNQMSMUNWPXQXSWUUWRXO QOOQNSNUOWPX QOSOUPWWXX SOTPVWXXYX", - "KXRKPMOOMUK\\ QLPNNTL\\ RKTKVLVNUPRQ TKULUNTPRQ RQTRUTUVTWRXQXOWNT RQSRTTTVRX", - "KYLQNOPORPSSSXR\\ LQNPPPRQSS WOVRSXQ\\", - "KYSOQOOPNQMSMUNWPXRXTWUVVTVRUPRNQLQKRJTJUKVM QOOQNSNVPX RXTVUTUQSO QLRKTKVM", - "LXVPTOQOOPOQPRRS QOPPPQRS RSOTNUNWPXSXUW RSPTOUOWPX", - "LWRKQLQMSNVNVMSNPOOPNRNTOVPWRXSYS[R\\P\\O[ SNQOPPOROTPVRX", - "IYJRKPLONOOPOQMX MONPNQLX OQPPROTOVPVRS\\ TOUPURR\\", - "IYJSKQLPNPOQOVPX MPNQNUOWPXQXSWTVUTVQVNULTKRKQLQNRPURWS QXSVTTUQUNTK", - "NWROPVPWQXSXUWVU SOQVQWRX", - "KYOOLX POMX UOVPWPVOTORQOR ORPSRWTXVWWU ORQSSWTX", - "LXLKNKPLWX NKOLVX RPMX RPNX", - "KZOOK\\ POL\\ NUNWOXQXSWTV VOTVTWUXWXXWYU WOUVUWVX", - "JYNOMX OONUMX VRVOWOVRTUQWNXMX LOOO", - "MXRKQLQMSNVN TNQOPPPRRSUS TNROQPQRRS SSPTOUOWQXSYTZT[S\\Q\\ SSQTPUPWQX", - "KXQOOPNQMSMUNWPXRXTWUVVTVRUPSOQO QOOQNSNVPX RXTVUTUQSO", - "IZPPMX PPNX TPSX TPTX KQMOXO KQMPXP", - "JXSOQOOPNQMSJ\\ QOOQNSK\\ SOUPVRVTUVTWRXPXNWMU SOUQUTTVRX", - "K[YOQOOPNQMSMUNWPXRXTWUVVTVRUPYP QOOQNSNVPX RXTVUTUQSO", - "KZSPQX SPRX MQOOXO MQOPXP", - "JXKRLPMOOOPPPROUOWPX NOOPORNUNWPXQXSWUUVRVOUOVP", - "KZOPNQMSMUNWPXRXUWWUXRXPWOUOTPSRRUO\\ MUNVPWRWUVWTXR XQWPUPSR RUQXP\\", - "KXMONOPPS[T\\ NOOPR[T\\U\\ VOTRNYL\\", - "I[TKQ\\ UKP\\ JRKPLONOOPOVPWSWUVWT MONPNTOWPXSXUWWTXRYO", - "JZNPPPPONPMQLSLUMWNXPXQWRUSR LUNWPWRU RRRWSXUXWVXTXRWPVOVPWP RUSWUWWV", - "KZVOTVTWUXWXXWYU WOUVUWVX USUQSOQOOPNQMSMUNWPXRXTV QOOQNSNVPX", - "JXOKMR PKNRNVPX NROPQOSOUPVRVTUVTWRXPXNWMUMR SOUQUTTVRX MKPK", - "KXUPUQVQUPSOQOOPNQMSMUNWPXRXTWUV QOOQNSNVPX", - "KZWKTVTWUXWXXWYU XKUVUWVX USUQSOQOOPNQMSMUNWPXRXTV QOOQNSNVPX UKXK", - "KWNURTTSURUPSOQOOPNQMSMUNWPXRXTWUV QOOQNSNVPX", - "MXWKXLXKVKTLSNPYO[N\\ VKULTNQYP[N\\L\\L[M\\ POVO", - "KYVOTVSYR[ WOUVTYR[P\\M\\L[M[N\\ USUQSOQOOPNQMSMUNWPXRXTV QOOQNSNVPX", - "KZPKLX QKMX OQPPROTOVPVRUUUWVX TOUPURTUTWUXWXXWYU NKQK", - "MWSKSLTLTKSK NROPPOROSPSRRURWSX QORPRRQUQWRXTXUWVU", - "MWTKTLULUKTK ORPPQOSOTPTRRYQ[O\\M\\M[N\\ ROSPSRQYP[O\\", - "KXPKLX QKMX VPUQVQVPUOTORQPROR ORPSQWRXTXUWVU ORQSRWSX NKQK", - "NVSKPVPWQXSXTWUU TKQVQWRX QKTK", - "F^GRHPIOKOLPLQJX JOKPKQIX LQMPOOQOSPSQQX QORPRQPX SQTPVOXOZPZRYUYWZX XOYPYRXUXWYX[X\\W]U", - "J[KRLPMOOOPPPQNX NOOPOQMX PQQPSOUOWPWRVUVWWX UOVPVRUUUWVXXXYWZU", - "KXQOOPNQMSMUNWPXRXTWUVVTVRUPSOQO QOOQNSNVPX RXTVUTUQSO", - "JYKRLPMOOOPPPQM\\ NOOPOQL\\ PQROTOVPWRWTVVUWSXQXOVOT TOVQVTUVSX J\\O\\", - "KYVOR\\ WOS\\ USUQSOQOOPNQMSMUNWPXRXTV QOOQNSNVPX P\\U\\", - "LXMRNPOOQORPRQPX POQPQQOX RQSPUOVOWPWQVQWP", - "LYVPVQWQVPTOQOOPORQSTTVU OQQRTSVTVWTXQXOWNVOVOW", - "NWSKPVPWQXSXTWUU TKQVQWRX POUO", - "IZJRKPLONOOPORNUNWOX MONPNRMUMWOXQXSWTV VOTVTWUXWXXWYU WOUVUWVX", - "JXKRLPMOOOPPPROUOWPX NOOPORNUNWPXQXSWUUVRVOUOVP", - "H\\IRJPKOMONPNRMUMWNX LOMPMRLULWNXOXQWRV TORVRWTX UOSVSWTXUXWWYUZRZOYOZP", - "JZMRNPPOROSPSR QORPRRQUPWNXMXLWLVMVLW XPWQXQXPWOVOTPSRRURWSX QUQWRXTXVWWU", - "IYJRKPLONOOPORNUNWOX MONPNRMUMWOXQXSWTV VOTVSYR[ WOUVTYR[P\\M\\L[M[N\\", - "KYWOWPVQNVMWMX NQOOROUQ OPRPUQVQ NVOVRWUW OVRXUXVV", - "H[RKSLSMTMTLRKOKMLLNLX OKNLMNMX XKYLYMZMZLXKVKTMTX VKUMUX JOWO JXOX RXWX", - "J[UKVLWLWKQKOLNNNX QKPLONOX VOVX WOWX LOWO LXQX TXYX", - "J[WKQKOLNNNX QKPLONOX UKVLVX WKWX LOVO LXQX TXYX", - "F_PKQLQMRMRLPKMKKLJNJX MKLLKNKX YKZL[L[KUKSLRNRX UKTLSNSX ZOZX [O[X HO[O HXMX PXUX XX]X", - "F_PKQLQMRMRLPKMKKLJNJX MKLLKNKX [KUKSLRNRX UKTLSNSX YKZLZX [K[X HOZO HXMX PXUX XX]X", - "NWRORX SOSX POSO PXUX", - "", - "LXVPTOROPPOQNSNUOWQXSXUW ROPQOSOVQX OSSS", - "LYSKQLPMOONRNUOWPXRXTWUVVTWQWNVLUKSK SKQMPOOSOVPX RXTVUTVPVMUK OQVQ", - "KZTKQ\\ UKP\\ QONPMRMUNWQXTXWWXUXRWPTOQO QOOPNRNUOWQX TXVWWUWRVPTO", - "LXUPVRVQUPSOQOOPNRNTOVRX QOOQOTPVRXSYS[R\\P\\", - "", - "", - "", - "I[VKWLXLVKSKQLPMOOLYK[J\\ SKQMPOMYL[J\\H\\H[I\\ ZK[L[KYKWLVNSYR[Q\\ YKXLWNTYS[Q\\O\\O[P\\ LOYO", - "IZVKWLXLXKSKQLPMOOLYK[J\\ SKQMPOMYL[J\\H\\H[I\\ VOTVTWUXWXXWYU WOUVUWVX LOWO", - "IZVKWL XKSKQLPMOOLYK[J\\ SKQMPOMYL[J\\H\\H[I\\ WKTVTWUXWXXWYU XKUVUWVX LOVO", - "F^SKTLTM ULSKPKNLMMLOIYH[G\\ PKNMMOJYI[G\\E\\E[F\\ ZK[L\\L\\KWKUL TMSOPYO[N\\ WKUMTOQYP[N\\L\\L[M\\ ZOXVXWYX[X\\W]U [OYVYWZX IO[O", - "F^SKTLTM ULSKPKNLMMLOIYH[G\\ PKNMMOJYI[G\\E\\E[F\\ ZK[L \\KWKUL TMSOPYO[N\\ WKUMTOQYP[N\\L\\L[M\\ [KXVXWYX[X\\W]U \\KYVYWZX IOZO", - "MWNROPPOROSPSRRURWSX QORPRRQUQWRXTXUWVU", - "", - "OU", - "LX", - "LYQKOLNONTOWQXTXVWWTWOVLTKQK QKPLOOOTPWQX TXUWVTVOULTK", - "LYPNSKSX RLRX OXVX", - "LYOMONNNNMOLQKTKVLWNVPTQQROSNUNX TKULVNUPTQ NWOVPVSWVWWV PVSXVXWVWU", - "LYOMONNNNMOLQKTKVLWNVPTQ TKULVNUPTQ RQTQVRWTWUVWTXQXOWNVNUOUOV TQURVTVUUWTX", - "LYSMSX TKTX TKMTXT QXVX", - "LYOKNQ OKVK OLSLVK NQOPQOTOVPWRWUVWTXQXOWNVNUOUOV TOUPVRVUUWTX", - "LYVMVNWNWMVLTKRKPLOMNPNUOWQXTXVWWUWSVQTPQPNR RKPMOPOUPWQX TXUWVUVSUQTP", - "LYNKNO VMRTPX WKTQQX NMPKRKUM NMPLRLUMVM", - "LYQKOLNNOPQQTQVPWNVLTKQK QKPLONPPQQ TQUPVNULTK QQORNTNUOWQXTXVWWUWTVRTQ QQPROTOUPWQX TXUWVUVTURTQ", - "LYOVOUNUNVOWQXSXUWVVWSWNVLTKQKOLNNNPORQSTSWQ SXUVVSVNULTK QKPLONOPPRQS", - "NVRVQWRXSWRV", - "NVSWRXQWRVSWSYQ[", - "NVROQPRQSPRO RVQWRXSWRV", - "NVROQPRQSPRO SWRXQWRVSWSYQ[", - "NVRKQLRSSLRK RLRO RVQWRXSWRV", - "LYNNONOONONNOLQKTKVLWNWOVQSRRSRTST TKVMVPUQSR RWRXSXSWRW", - "OVRKRP SKRP", - "LXOKOP PKOP UKUP VKUP", - "MWQKPLPNQOSOTNTLSKQK", - "MWRJRP OKUO UKOO", - "KZXHM\\", - "MWUHSJQMPPPTQWSZU\\ SJRLQPQTRXSZ", - "MWOHQJSMTPTTSWQZO\\ QJRLSPSTRXQZ", - "MWPHP\\ QHQ\\ PHUH P\\U\\", - "MWSHS\\ THT\\ OHTH O\\T\\", - "LWSHRIQKQMRORPPRRTRUQWQYR[S\\ RIQM QKRO RUQY QWR[", - "MXQHRISKSMRORPTRRTRUSWSYR[Q\\ RISM SKRO RUSY SWR[", - "MWTHPRT\\", - "MWPHTRP\\", - "OURHR\\", - "MWPHP\\ THT\\", - "I[LRXR", - "I[RLRX LRXR", - "JZRMRX MRWR MXWX", - "JZRMRX MMWM MRWR", - "JZMMWW WMMW", - "NVRQQRRSSRRQ", - "I[RLQMRNSMRL LRXR RVQWRXSWRV", - "I[LPXP LTXT", - "I[WLMX LPXP LTXT", - "I[LNXN LRXR LVXV", - "JZWLMRWX", - "JZMLWRMX", - "JZWKMOWS MTWT MXWX", - "JZMKWOMS MTWT MXWX", - "H[YUWUUTTSRPQOONNNLOKQKRLTNUOUQTRSTPUOWNYN", - "JZLTLRMPOPUSWSXR LRMQOQUTWTXRXP", - "JZMSRPWS MSRQWS", - "NVSKPO SKTLPO", - "NVQKTO QKPLTO", - "LXNKOMQNSNUMVK NKONQOSOUNVK", - "NVSLRMQLRKSLSNQP", - "NVSKQMQORPSORNQO", - "NVQLRMSLRKQLQNSP", - "NVQKSMSORPQORNSO", - "", - "JZWMQMONNOMQMSNUOVQWWW", - "JZMMMSNUOVQWSWUVVUWSWM", - "JZMMSMUNVOWQWSVUUVSWMW", - "JZMWMQNOONQMSMUNVOWQWW", - "JZWMQMONNOMQMSNUOVQWWW MRUR", - "I[TOUPXRUTTU UPWRUT LRWR", - "MWRMRX OPPORLTOUP PORMTO", - "I[POOPLROTPU OPMROT MRXR", - "MWRLRW OTPURXTUUT PURWTU", - "KYVSUPSOQOOPNQMSMUNWPXRXTWUVVTWQWNVLTKQKPLQLRK QOOQNSNVPX RXTVUTVQVNULTK", - "JZLKRX MKRV XKRX LKXK NLWL", - "G[IOLORW KORX [FRX", - "I[XIXJYJYIXHVHTJSLROQUPYO[ UITKSORUQXPZN\\L\\K[KZLZL[", - "I[XIXJYJYIXHVHTJSLROQUPYO[ UITKSORUQXPZN\\L\\K[KZLZL[ QNOONQNSOUQVSVUUVSVQUOSNQN", - "H\\ZRYTWUVUTTSSQPPONNMNKOJQJRKTMUNUPTQSSPTOVNWNYOZQZR", - "JZXKLX OKPLPNOOMOLNLLMKOKSLVLXK UTTUTWUXWXXWXUWTUT", - "J[YPXPXQYQYPXOWOVPUTTVSWQXOXMWLVLTMSORRPSNSLRKPKOLONPQUWWXXXYW OXMVMTOR ONPPVWWX", - "J[UPSOQOPQPRQTSTUS UOUSVTXTYRYQXNVLSKRKOLMNLQLRMUOWRXSXVW", - "KZQHQ\\ THT\\ WLVLVMWMWLUKPKNLNNOPVSWT NNOOVRWTWVVWTXQXOWNVNUOUOVNV", - "KYPKP[ TKT[ MQWQ MUWU", - "LXTLSLSMTMTLSKQKPLPNQPTRUS PNQOTQUSUUSW QPOROTPVSXTY OTPUSWTYT[S\\Q\\P[PZQZQ[P[", - "LXRKQLRMSLRK RMRQ RQQSRVSSRQ RVR\\ POONNOOPPOTOUNVOUPTO", - "LXRMSLRKQLRMRQQRSURV RQSRQURVRZQ[R\\S[RZ POONNOOPPOTOUNVOUPTO PXOWNXOYPXTXUWVXUYTX", - "LYVKVX NKVK QQVQ NXVX", - "", - "H\\QKNLLNKQKSLVNXQYSYVXXVYSYQXNVLSKQK RQQRRSSRRQ", - "LYQKPLPMQN TKULUMTN RNPOOQORPTRUSUUTVRVQUOSNRN RURY SUSY OWVW", - "LYRKPLONOOPQRRSRUQVOVNULSKRK RRRX SRSX OUVU", - "H\\QKNLLNKQKSLVNXQYSYVXXVYSYQXNVLSKQK RKRY KRYR", - "JYRRPQOQMRLTLUMWOXPXRWSUSTRR WMRR RMWMWR RMVNWR", - "JZLLMKOKQLRNRPQRPSNT OKPLQNQQPS VKUX WKTX NTXT", - "JYNKNU OKNR NROPQOSOUPVQVTTVTXUYVYWX SOUQUTTV LKOK", - "LYONRKRQ VNSKSQ RQPROTOUPWRXSXUWVUVTURSQ RTRUSUSTRT", - "JZRKRY MKMPNRPSTSVRWPWK LMMKNM QMRKSM VMWKXM OVUV", - "JYNKNX OKOX LKSKVLWNWOVQSROR SKULVNVOUQSR LXVXVUUX", - "LYWKTKQLONNQNSOVQXTYWY WKTLRNQQQSRVTXWY", - "JZRRPQOQMRLTLUMWOXPXRWSUSTRR SLQQ WMRR XQSS", - "KYPMTW TMPW MPWT WPMT", - "J[OUMULVLXMYOYPXPVNTMRMONMOLQKTKVLWMXOXRWTUVUXVYXYYXYVXUVU NMPLULWM", - "J[OOMOLNLLMKOKPLPNNPMRMUNWOXQYTYVXWWXUXRWPUNULVKXKYLYNXOVO NWPXUXWW", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "F^KHK\\ LHL\\ XHX\\ YHY\\ HH\\H H\\O\\ U\\\\\\", - "H]KHRQJ\\ JHQQ JHYHZMXH K[X[ J\\Y\\ZWX\\", - "KYVBTDRGPKOPOTPYR]T`Vb TDRHQKPPPTQYR\\T`", - "KYNBPDRGTKUPUTTYR]P`Nb PDRHSKTPTTSYR\\P`", - "KYOBOb PBPb OBVB ObVb", - "KYTBTb UBUb NBUB NbUb", - "JYTBQEPHPJQMSOSPORSTSUQWPZP\\Q_Tb RDQGQKRN RVQYQ]R`", - "KZPBSETHTJSMQOQPURQTQUSWTZT\\S_Pb RDSGSKRN RVSYS]R`", - "KYU@RCPFOIOLPOSVTYT\\S_Ra RCQEPHPKQNTUUXU[T^RaOd", - "KYO@RCTFUIULTOQVPYP\\Q_Ra RCSETHTKSNPUOXO[P^RaUd", - "AXCRGRR` GSRa FSRb X:Rb", - "F^[CZD[E\\D\\C[BYBWCUETGSJRNPZO^N` VDUFTJRVQZP]O_MaKbIbHaH`I_J`Ia", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "H\\RFK[ RFY[ RIX[ MUVU I[O[ U[[[", - "G]LFL[ MFM[ IFUFXGYHZJZLYNXOUP UFWGXHYJYLXNWOUP MPUPXQYRZTZWYYXZU[I[ UPWQXRYTYWXYWZU[", - "G\\XIYLYFXIVGSFQFNGLIKKJNJSKVLXNZQ[S[VZXXYV QFOGMILKKNKSLVMXOZQ[", - "G]LFL[ MFM[ IFSFVGXIYKZNZSYVXXVZS[I[ SFUGWIXKYNYSXVWXUZS[", - "G\\LFL[ MFM[ SLST IFYFYLXF MPSP I[Y[YUX[", - "G[LFL[ MFM[ SLST IFYFYLXF MPSP I[P[", - "G^XIYLYFXIVGSFQFNGLIKKJNJSKVLXNZQ[S[VZXX QFOGMILKKNKSLVMXOZQ[ XSX[ YSY[ US\\S", - "F^KFK[ LFL[ XFX[ YFY[ HFOF UF\\F LPXP H[O[ U[\\[", - "MXRFR[ SFS[ OFVF O[V[", - "KZUFUWTZR[P[NZMXMVNUOVNW TFTWSZR[ QFXF", - "F\\KFK[ LFL[ YFLS QOY[ POX[ HFOF UF[F H[O[ U[[[", - "I[NFN[ OFO[ KFRF K[Z[ZUY[", - "F_KFK[ LFRX KFR[ YFR[ YFY[ ZFZ[ HFLF YF]F H[N[ V[][", - "G^LFL[ MFYY MHY[ YFY[ IFMF VF\\F I[O[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF QFOGMILKKOKRLVMXOZQ[ S[UZWXXVYRYOXKWIUGSF", - "G]LFL[ MFM[ IFUFXGYHZJZMYOXPUQMQ UFWGXHYJYMXOWPUQ I[P[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF QFOGMILKKOKRLVMXOZQ[ S[UZWXXVYRYOXKWIUGSF NYNXOVQURUTVUXV_W`Y`Z^Z] UXV\\W^X_Y_Z^", - "G]LFL[ MFM[ IFUFXGYHZJZLYNXOUPMP UFWGXHYJYLXNWOUP I[P[ RPTQURXYYZZZ[Y TQUSWZX[Z[[Y[X", - "H\\XIYFYLXIVGSFPFMGKIKKLMMNOOUQWRYT KKMMONUPWQXRYTYXWZT[Q[NZLXKUK[LX", - "I\\RFR[ SFS[ LFKLKFZFZLYF O[V[", - "F^KFKULXNZQ[S[VZXXYUYF LFLUMXOZQ[ HFOF VF\\F", - "H\\KFR[ LFRX YFR[ IFOF UF[F", - "F^JFN[ KFNV RFN[ RFV[ SFVV ZFV[ GFNF WF]F", - "H\\KFX[ LFY[ YFK[ IFOF UF[F I[O[ U[[[", - "H]KFRQR[ LFSQS[ ZFSQ IFOF VF\\F O[V[", - "H\\XFK[ YFL[ LFKLKFYF K[Y[YUX[", - "H\\RFK[ RFY[ RIX[ MUVU I[O[ U[[[", - "G]LFL[ MFM[ IFUFXGYHZJZLYNXOUP UFWGXHYJYLXNWOUP MPUPXQYRZTZWYYXZU[I[ UPWQXRYTYWXYWZU[", - "I[NFN[ OFO[ KFZFZLYF K[R[", - "H\\RFJ[ RFZ[ RIY[ KZYZ J[Z[", - "G\\LFL[ MFM[ SLST IFYFYLXF MPSP I[Y[YUX[", - "H\\XFK[ YFL[ LFKLKFYF K[Y[YUX[", - "F^KFK[ LFL[ XFX[ YFY[ HFOF UF\\F LPXP H[O[ U[\\[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF QFOGMILKKOKRLVMXOZQ[ S[UZWXXVYRYOXKWIUGSF OMOT UMUT OPUP OQUQ", - "MXRFR[ SFS[ OFVF O[V[", - "F\\KFK[ LFL[ YFLS QOY[ POX[ HFOF UF[F H[O[ U[[[", - "H\\RFK[ RFY[ RIX[ I[O[ U[[[", - "F_KFK[ LFRX KFR[ YFR[ YFY[ ZFZ[ HFLF YF]F H[N[ V[][", - "G^LFL[ MFYY MHY[ YFY[ IFMF VF\\F I[O[", - "G]KEJJ ZEYJ ONNS VNUS KWJ\\ ZWY\\ KGYG KHYH OPUP OQUQ KYYY KZYZ", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF QFOGMILKKOKRLVMXOZQ[ S[UZWXXVYRYOXKWIUGSF", - "F^KFK[ LFL[ XFX[ YFY[ HF\\F H[O[ U[\\[", - "G]LFL[ MFM[ IFUFXGYHZJZMYOXPUQMQ UFWGXHYJYMXOWPUQ I[P[", - "H]KFRPJ[ JFQP JFYFZLXF KZXZ J[Y[ZUX[", - "I\\RFR[ SFS[ LFKLKFZFZLYF O[V[", - "I\\KKKILGMFOFPGQIRMR[ KIMGOGQI ZKZIYGXFVFUGTISMS[ ZIXGVGTI O[V[", - "H]RFR[ SFS[ PKMLLMKOKRLTMUPVUVXUYTZRZOYMXLUKPK PKNLMMLOLRMTNUPV UVWUXTYRYOXMWLUK OFVF O[V[", - "H\\KFX[ LFY[ YFK[ IFOF UF[F I[O[ U[[[", - "G^RFR[ SFS[ IMJLLMMQNSOTQU JLKMLQMSNTQUTUWTXSYQZM[L TUVTWSXQYM[L\\M OFVF O[V[", - "G]JXK[O[MWKSJPJLKIMGPFTFWGYIZLZPYSWWU[Y[ZX MWLTKPKLLINGPF TFVGXIYLYPXTWW KZNZ VZYZ", - "H\\UFH[ UFV[ THU[ LUUU F[L[ R[X[", - "F^OFI[ PFJ[ LFWFZG[I[KZNYOVP WFYGZIZKYNXOVP MPVPXQYSYUXXVZR[F[ VPWQXSXUWXUZR[", - "H]ZH[H\\F[L[JZHYGWFTFQGOIMLLOKSKVLYMZP[S[UZWXXV TFRGPINLMOLSLVMYNZP[", - "F]OFI[ PFJ[ LFUFXGYHZKZOYSWWUYSZO[F[ UFWGXHYKYOXSVWTYRZO[", - "F]OFI[ PFJ[ TLRT LF[FZLZF MPSP F[U[WVT[", - "F\\OFI[ PFJ[ TLRT LF[FZLZF MPSP F[M[", - "H^ZH[H\\F[L[JZHYGWFTFQGOIMLLOKSKVLYMZP[R[UZWXYT TFRGPINLMOLSLVMYNZP[ R[TZVXXT UT\\T", - "E_NFH[ OFI[ [FU[ \\FV[ KFRF XF_F LPXP E[L[ R[Y[", - "LYUFO[ VFP[ RFYF L[S[", - "I[XFSWRYQZO[M[KZJXJVKULVKW WFRWQYO[ TF[F", - "F]OFI[ PFJ[ ]FLS SOW[ ROV[ LFSF YF_F F[M[ S[Y[", - "H\\QFK[ RFL[ NFUF H[W[YUV[", - "E`NFH[ NFO[ OFPY \\FO[ \\FV[ ]FW[ KFOF \\F`F E[K[ S[Z[", - "F_OFI[ OFVX OIV[ \\FV[ LFOF YF_F F[L[", - "G]SFPGNILLKOJSJVKYLZN[Q[TZVXXUYRZNZKYHXGVFSF SFQGOIMLLOKSKVLYN[ Q[SZUXWUXRYNYKXHVF", - "F]OFI[ PFJ[ LFXF[G\\I\\K[NYPUQMQ XFZG[I[KZNXPUQ F[M[", - "G]SFPGNILLKOJSJVKYLZN[Q[TZVXXUYRZNZKYHXGVFSF SFQGOIMLLOKSKVLYN[ Q[SZUXWUXRYNYKXHVF LYLXMVOUPURVSXS_T`V`W^W] SXT^U_V_W^", - "F^OFI[ PFJ[ LFWFZG[I[KZNYOVPMP WFYGZIZKYNXOVP RPTQURVZW[Y[ZYZX URWYXZYZZY F[M[", - "G^ZH[H\\F[L[JZHYGVFRFOGMIMKNMONVRXT MKOMVQWRXTXWWYVZS[O[LZKYJWJUI[JYKY", - "H]UFO[ VFP[ OFLLNF]F\\L\\F L[S[", - "F_NFKQJUJXKZN[R[UZWXXU\\F OFLQKUKXLZN[ KFRF YF_F", - "H\\NFO[ OFPY \\FO[ LFRF XF^F", - "E_MFK[ NFLY UFK[ UFS[ VFTY ]FS[ JFQF ZF`F", - "G]NFU[ OFV[ \\FH[ LFRF XF^F F[L[ R[X[", - "H]NFRPO[ OFSPP[ ]FSP LFRF YF_F L[S[", - "G][FH[ \\FI[ OFLLNF\\F H[V[XUU[", - "H\\KILKXWYYY[ LLXX KIKKLMXYY[ PPLTKVKXLZK[ KVMZ LTLVMXMZK[ SSXN VIVLWNYNYLWKVI VIWLYN", - "H\\QIK[ SIY[ RIX[ MUVU I[O[ U[[[ QBOCNENGOIQJSJUIVGVEUCSBQB", - "", - "", - "", - "", - "", - "G]IB[b", - "F^RJIZ RJ[Z", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "I]NONPMPMONNPMTMVNWOXQXXYZZ[ WOWXXZZ[[[ WQVRPSMTLVLXMZP[S[UZWX PSNTMVMXNZP[", - "G\\LFL[ MFM[ MPONQMSMVNXPYSYUXXVZS[Q[OZMX SMUNWPXSXUWXUZS[ IFMF", - "H[WPVQWRXQXPVNTMQMNNLPKSKULXNZQ[S[VZXX QMONMPLSLUMXOZQ[", - "H]WFW[ XFX[ WPUNSMQMNNLPKSKULXNZQ[S[UZWX QMONMPLSLUMXOZQ[ TFXF W[[[", - "H[LSXSXQWOVNTMQMNNLPKSKULXNZQ[S[VZXX WSWPVN QMONMPLSLUMXOZQ[", - "KXUGTHUIVHVGUFSFQGPIP[ SFRGQIQ[ MMUM M[T[", - "I\\QMONNOMQMSNUOVQWSWUVVUWSWQVOUNSMQM ONNPNTOV UVVTVPUN VOWNYMYNWN NUMVLXLYM[P\\U\\X]Y^ LYMZP[U[X\\Y^Y_XaUbObLaK_K^L\\O[", - "G]LFL[ MFM[ MPONRMTMWNXPX[ TMVNWPW[ IFMF I[P[ T[[[", - "MXRFQGRHSGRF RMR[ SMS[ OMSM O[V[", - "MXSFRGSHTGSF TMT_SaQbObNaN`O_P`Oa SMS_RaQb PMTM", - "G\\LFL[ MFM[ WMMW RSX[ QSW[ IFMF TMZM I[P[ T[Z[", - "MXRFR[ SFS[ OFSF O[V[", - "BcGMG[ HMH[ HPJNMMOMRNSPS[ OMQNRPR[ SPUNXMZM]N^P^[ ZM\\N]P][ DMHM D[K[ O[V[ Z[a[", - "G]LML[ MMM[ MPONRMTMWNXPX[ TMVNWPW[ IMMM I[P[ T[[[", - "H\\QMNNLPKSKULXNZQ[S[VZXXYUYSXPVNSMQM QMONMPLSLUMXOZQ[ S[UZWXXUXSWPUNSM", - "G\\LMLb MMMb MPONQMSMVNXPYSYUXXVZS[Q[OZMX SMUNWPXSXUWXUZS[ IMMM IbPb", - "H\\WMWb XMXb WPUNSMQMNNLPKSKULXNZQ[S[UZWX QMONMPLSLUMXOZQ[ Tb[b", - "IZNMN[ OMO[ OSPPRNTMWMXNXOWPVOWN KMOM K[R[", - "J[WOXMXQWOVNTMPMNNMOMQNRPSUUWVXW MPNQPRUTWUXVXYWZU[Q[OZNYMWM[NY", - "KZPFPWQZS[U[WZXX QFQWRZS[ MMUM", - "G]LMLXMZP[R[UZWX MMMXNZP[ WMW[ XMX[ IMMM TMXM W[[[", - "I[LMR[ MMRY XMR[ JMPM TMZM", - "F^JMN[ KMNX RMN[ RMV[ SMVX ZMV[ GMNM WM]M", - "H\\LMW[ MMX[ XML[ JMPM TMZM J[P[ T[Z[", - "H[LMR[ MMRY XMR[P_NaLbKbJaK`La JMPM TMZM", - "I[WML[ XMM[ MMLQLMXM L[X[XWW[", - "G^QMNNLPKRJUJXKZN[P[RZUWWTYPZM QMONMPLRKUKXLZN[ QMSMUNVPXXYZZ[ SMTNUPWXXZZ[[[", - "G\\TFQGOIMMLPKTJZIb TFRGPINMMPLTKZJb TFVFXGYHYKXMWNTOPO VFXHXKWMVNTO POTPVRWTWWVYUZR[P[NZMYLV POSPURVTVWUYTZR[", - "H\\IPKNMMOMQNROSRSVRZOb JOLNPNRO ZMYPXRSYP^Nb YMXPWRSY", - "I\\VNTMRMONMQLTLWMYNZP[R[UZWWXTXQWOSJRHRFSEUEWFYH RMPNNQMTMXNZ R[TZVWWTWPVNTKSISGTFVFYH", - "I[XPVNTMPMNNNPPRSS PMONOPQRSS SSNTLVLXMZP[S[UZWX SSOTMVMXNZP[", - "I[TFRGQHQIRJUKZKZJWKSMPOMRLULWMYP[S]T_TaSbQbPa ULQONRMUMWNYP[", - "G]HQIOKMNMONOPNTL[ MMNNNPMTK[ NTPPRNTMVMXNYOYRXWUb VMXOXRWWTb", - "F]GQHOJMMMNNNPMUMXNZO[ LMMNMPLULXMZO[Q[SZUXWUXRYMYIXGVFTFRHRJSMUPWRZT SZUWVUWRXMXIWGVF", - "LXRMPTOXOZP[S[UYVW SMQTPXPZQ[", - "H\\NMJ[ OMK[ XMYNZNYMWMUNQROSMS OSQTSZT[ OSPTRZS[U[WZYW", - "H\\KFMFOGPHQJWXXZY[ MFOHPJVXWZY[Z[ RMJ[ RMK[", - "F]MMGb NMHb MPLVLYN[P[RZTXVU XMUXUZV[Y[[Y\\W YMVXVZW[", - "H\\NML[ OMNSMXL[ YMXQVU ZMYPXRVUTWQYOZL[ KMOM", - "IZTFRGQHQIRJUKXK UKQLOMNONQPSSTVT UKRLPMOOOQQSST STOUMVLXLZN\\S^T_TaRbPb STPUNVMXMZO\\S^", - "I[RMONMQLTLWMYNZP[R[UZWWXTXQWOVNTMRM RMPNNQMTMXNZ R[TZVWWTWPVN", - "G]PNL[ PNM[ VNV[ VNW[ IPKNNM[M IPKONN[N", - "H[LVMYNZP[R[UZWWXTXQWOVNTMRMONMQLTHb R[TZVWWTWPVN RMPNNQMTIb", - "H][MQMNNLQKTKWLYMZO[Q[TZVWWTWQVOUNSM QMONMQLTLXMZ Q[SZUWVTVPUN UN[N", - "H\\SNP[ SNQ[ JPLNOMZM JPLOONZN", - "H\\IQJOLMOMPNPPNVNYP[ NMONOPMVMYNZP[Q[TZVXXUYRYOXMWNXOYR XUYO", - "G]ONMOKQJTJWKYLZN[Q[TZWXYUZRZOXMVMTORSPXMb JWLYNZQZTYWWYU ZOXNVNTPRSPYNb", - "I[KMMMONPPU_VaWb MMNNOPT_UaWbYb ZMYOWRM]K`Jb", - "F]UFOb VFNb GQHOJMMMNNNPMUMXOZRZTYWVYS LMMNMPLULXMZO[R[TZVXXUYS[M", - "F]JQLOONNMLNJQITIWJZK[M[OZQWRT IWJYKZMZOYQW QTQWRZS[U[WZYWZTZQYNXMWNYOZQ QWRYSZUZWYYW", - "H]XMVTUXUZV[Y[[Y\\W YMWTVXVZW[ VTVQUNSMQMNNLQKTKWLYMZO[Q[SZUWVT QMONMQLTLXMZ", - "H[PFLSLVMYNZ QFMS MSNPPNRMTMVNWOXQXTWWUZR[P[NZMWMS VNWPWTVWTZR[ MFQF", - "I[WPWQXQXPWNUMRMONMQLTLWMYNZP[R[UZWW RMPNNQMTMXNZ", - "H]ZFVTUXUZV[Y[[Y\\W [FWTVXVZW[ VTVQUNSMQMNNLQKTKWLYMZO[Q[SZUWVT QMONMQLTLXMZ WF[F", - "I[MVQUTTWRXPWNUMRMONMQLTLWMYNZP[R[UZWX RMPNNQMTMXNZ", - "KZZGYHZI[H[GZFXFVGUHTJSMP[O_Na XFVHUJTNRWQ[P^O`NaLbJbIaI`J_K`Ja OMYM", - "H\\YMU[T^RaObLbJaI`I_J^K_J` XMT[S^QaOb VTVQUNSMQMNNLQKTKWLYMZO[Q[SZUWVT QMONMQLTLXMZ", - "H]PFJ[ QFK[ MTOPQNSMUMWNXOXQVWVZW[ UMWOWQUWUZV[Y[[Y\\W MFQF", - "LYUFTGUHVGUF MQNOPMSMTNTQRWRZS[ RMSNSQQWQZR[U[WYXW", - "LYVFUGVHWGVF NQOOQMTMUNUQR[Q^P`OaMbKbJaJ`K_L`Ka SMTNTQQ[P^O`Mb", - "H\\PFJ[ QFK[ XNWOXPYOYNXMWMUNQROSMS OSQTSZT[ OSPTRZS[U[WZYW MFQF", - "MYUFQTPXPZQ[T[VYWW VFRTQXQZR[ RFVF", - "AbBQCOEMHMINIPHTF[ GMHNHPGTE[ HTJPLNNMPMRNSOSQP[ PMRORQO[ RTTPVNXMZM\\N]O]Q[W[Z\\[ ZM\\O\\QZWZZ[[^[`YaW", - "F]GQHOJMMMNNNPMTK[ LMMNMPLTJ[ MTOPQNSMUMWNXOXQVWVZW[ UMWOWQUWUZV[Y[[Y\\W", - "I[RMONMQLTLWMYNZP[R[UZWWXTXQWOVNTMRM RMPNNQMTMXNZ R[TZVWWTWPVN", - "G\\HQIOKMNMONOPNTJb MMNNNPMTIb NTOQQNSMUMWNXOYQYTXWVZS[Q[OZNWNT WNXPXTWWUZS[ FbMb", - "H\\XMRb YMSb VTVQUNSMQMNNLQKTKWLYMZO[Q[SZUWVT QMONMQLTLXMZ ObVb", - "IZJQKOMMPMQNQPPTN[ OMPNPPOTM[ PTRPTNVMXMYNYOXPWOXN", - "J[XOXPYPYOXNUMRMONNONQORVVWW NPOQVUWVWYVZS[P[MZLYLXMXMY", - "KYTFPTOXOZP[S[UYVW UFQTPXPZQ[ NMWM", - "F]GQHOJMMMNNNQLWLYN[ LMMNMQKWKYLZN[P[RZTXVT XMVTUXUZV[Y[[Y\\W YMWTVXVZW[", - "H\\IQJOLMOMPNPQNWNYP[ NMONOQMWMYNZP[Q[TZVXXUYQYMXMYO", - "C`DQEOGMJMKNKQIWIYK[ IMJNJQHWHYIZK[M[OZQXRV TMRVRYSZU[W[YZ[X\\V]R]M\\M]O UMSVSYU[", - "H\\KQMNOMRMSOSR QMRORRQVPXNZL[K[JZJYKXLYKZ QVQYR[U[WZYW YNXOYPZOZNYMXMVNTPSRRVRYS[", - "G\\HQIOKMNMONOQMWMYO[ MMNNNQLWLYMZO[Q[SZUXWT ZMV[U^SaPbMbKaJ`J_K^L_K` YMU[T^RaPb", - "H\\YMXOVQNWLYK[ LQMOOMRMVO MOONRNVOXO LYNYRZUZWY NYR[U[WYXW", - "G^VGUHVIWHWGUFRFOGMILLL[ RFPGNIMLM[ \\G[H\\I]H]G\\FZFXGWIW[ ZFYGXIX[ IM[M I[P[ T[[[", - "G]WGVHWIXHWGUFRFOGMILLL[ RFPGNIMLM[ WMW[ XMX[ IMXM I[P[ T[[[", - "G]VGUHVIWHWGUF XFRFOGMILLL[ RFPGNIMLM[ WHW[ XFX[ IMWM I[P[ T[[[", - "BcRGQHRISHRGPFMFJGHIGLG[ MFKGIIHLH[ ]G\\H]I^H]G[FXFUGSIRLR[ XFVGTISLS[ ]M][ ^M^[ DM^M D[K[ O[V[ Z[a[", - "BcRGQHRISHRGPFMFJGHIGLG[ MFKGIIHLH[ \\G[H\\I]H]G[F ^FXFUGSIRLR[ XFVGTISLS[ ]H][ ^F^[ DM]M D[K[ O[V[ Z[a[", - "MXRMR[ SMS[ OMSM O[V[", - "", - "IZWNUMRMONMPLSLVMYNZQ[T[VZ RMPNNPMSMVNYOZQ[ MTUT", - "I\\TFQGOJNLMOLTLXMZO[Q[TZVWWUXRYMYIXGVFTF TFRGPJOLNOMTMXNZO[ Q[SZUWVUWRXMXIWGVF NPWP", - "G]UFOb VFNb QMMNKPJSJVKXMZP[S[WZYXZUZRYPWNTMQM QMNNLPKSKVLXNZP[ S[VZXXYUYRXPVNTM", - "I[TMVNXPXOWNTMQMNNMOLQLSMUOWSZ QMONNOMQMSNUSZT\\T^S_Q_", - "", - "", - "G]LMKNJPJRKUOYP[ JRKTOXP[P]O`MbLbKaJ_J\\KXMTOQRNTMVMYNZPZTYXWZU[T[SZSXTWUXTY VMXNYPYTXXWZ", - "E_YGXHYIZHYGWFTFQGOINKMNLRJ[I_Ha TFRGPIOKNNLWK[J^I`HaFbDbCaC`D_E`Da _G^H_I`H`G_F]F[GZHYJXMU[T_Sa ]F[HZJYNWWV[U^T`SaQbObNaN`O_P`Oa IM^M", - "F^[GZH[I\\H[GXFUFRGPIOKNNMRK[J_Ia UFSGQIPKONMWL[K^J`IaGbEbDaD`E_F`Ea YMWTVXVZW[Z[\\Y]W ZMXTWXWZX[ JMZM", - "F^YGXHYIZHZGXF \\FUFRGPIOKNNMRK[J_Ia UFSGQIPKONMWL[K^J`IaGbEbDaD`E_F`Ea [FWTVXVZW[Z[\\Y]W \\FXTWXWZX[ JMYM", - "@cTGSHTIUHTGRFOFLGJIIKHNGRE[D_Ca OFMGKIJKINGWF[E^D`CaAb?b>a>`?_@`?a `G_H`IaH`G]FZFWGUITKSNRRP[O_Na ZFXGVIUKTNRWQ[P^O`NaLbJbIaI`J_K`Ja ^M\\T[X[Z\\[_[aYbW _M]T\\X\\Z][ DM_M", - "@cTGSHTIUHTGRFOFLGJIIKHNGRE[D_Ca OFMGKIJKINGWF[E^D`CaAb?b>a>`?_@`?a ^G]H^I_H_G]F aFZFWGUITKSNRRP[O_Na ZFXGVIUKTNRWQ[P^O`NaLbJbIaI`J_K`Ja `F\\T[X[Z\\[_[aYbW aF]T\\X\\Z][ DM^M", - "LYMQNOPMSMTNTQRWRZS[ RMSNSQQWQZR[U[WYXW", - "", - "NV", - "JZ", - "H\\QFNGLJKOKRLWNZQ[S[VZXWYRYOXJVGSFQF QFOGNHMJLOLRMWNYOZQ[ S[UZVYWWXRXOWJVHUGSF", - "H\\NJPISFS[ RGR[ N[W[", - "H\\LJMKLLKKKJLHMGPFTFWGXHYJYLXNUPPRNSLUKXK[ TFVGWHXJXLWNTPPR KYLXNXSZVZXYYX NXS[W[XZYXYV", - "H\\LJMKLLKKKJLHMGPFTFWGXIXLWNTOQO TFVGWIWLVNTO TOVPXRYTYWXYWZT[P[MZLYKWKVLUMVLW WQXTXWWYVZT[", - "H\\THT[ UFU[ UFJUZU Q[X[", - "H\\MFKP KPMNPMSMVNXPYSYUXXVZS[P[MZLYKWKVLUMVLW SMUNWPXSXUWXUZS[ MFWF MGRGWF", - "H\\WIVJWKXJXIWGUFRFOGMILKKOKULXNZQ[S[VZXXYUYTXQVOSNRNOOMQLT RFPGNIMKLOLUMXOZQ[ S[UZWXXUXTWQUOSN", - "H\\KFKL KJLHNFPFUIWIXHYF LHNGPGUI YFYIXLTQSSRVR[ XLSQRSQVQ[", - "H\\PFMGLILLMNPOTOWNXLXIWGTFPF PFNGMIMLNNPO TOVNWLWIVGTF POMPLQKSKWLYMZP[T[WZXYYWYSXQWPTO PONPMQLSLWMYNZP[ T[VZWYXWXSWQVPTO", - "H\\XMWPURRSQSNRLPKMKLLINGQFSFVGXIYLYRXVWXUZR[O[MZLXLWMVNWMX QSORMPLMLLMIOGQF SFUGWIXLXRWVVXTZR[", - "MWRYQZR[SZRY", - "MWR[QZRYSZS\\R^Q_", - "MWRMQNROSNRM RYQZR[SZRY", - "MWRMQNROSNRM R[QZRYSZS\\R^Q_", - "MWRFQHRTSHRF RHRN RYQZR[SZRY", - "I[MJNKMLLKLJMHNGPFSFVGWHXJXLWNVORQRT SFUGVHWJWLVNTP RYQZR[SZRY", - "NVRFQM SFQM", - "JZNFMM OFMM VFUM WFUM", - "KYQFOGNINKOMQNSNUMVKVIUGSFQF", - "JZRFRR MIWO WIMO", - "G][BIb", - "KYVBTDRGPKOPOTPYR]T`Vb TDRHQKPPPTQYR\\T`", - "KYNBPDRGTKUPUTTYR]P`Nb PDRHSKTPTTSYR\\P`", - "KYOBOb PBPb OBVB ObVb", - "KYTBTb UBUb NBUB NbUb", - "JYTBQEPHPJQMSOSPORSTSUQWPZP\\Q_Tb RDQGQKRN RVQYQ]R`", - "KZPBSETHTJSMQOQPURQTQUSWTZT\\S_Pb RDSGSKRN RVSYS]R`", - "KYUBNRUb", - "KYOBVROb", - "NVRBRb", - "KYOBOb UBUb", - "E_IR[R", - "E_RIR[ IR[R", - "F^RJR[ JRZR J[Z[", - "F^RJR[ JJZJ JRZR", - "G]KKYY YKKY", - "MWQQQSSSSQQQ RQRS QRSR", - "E_RIQJRKSJRI IR[R RYQZR[SZRY", - "E_IO[O IU[U", - "E_YIK[ IO[O IU[U", - "E_IM[M IR[R IW[W", - "F^ZIJRZ[", - "F^JIZRJ[", - "F^ZFJMZT JVZV J[Z[", - "F^JFZMJT JVZV J[Z[", - "F_[WYWWVUTRPQOONMNKOJQJSKUMVOVQURTUPWNYM[M", - "F^IUISJPLONOPPTSVTXTZS[Q ISJQLPNPPQTTVUXUZT[Q[O", - "G]JTROZT JTRPZT", - "LXTFOL TFUGOL", - "LXPFUL PFOGUL", - "H\\KFLHNJQKSKVJXHYF KFLINKQLSLVKXIYF", - "MWRHQGRFSGSIRKQL", - "MWSFRGQIQKRLSKRJ", - "MWRHSGRFQGQIRKSL", - "MWQFRGSISKRLQKRJ", - "E[HMLMRY KMR[ [BR[", - "F^ZJSJOKMLKNJQJSKVMXOYSZZZ", - "F^JJJQKULWNYQZSZVYXWYUZQZJ", - "F^JJQJUKWLYNZQZSYVWXUYQZJZ", - "F^JZJSKOLMNKQJSJVKXMYOZSZZ", - "F^ZJSJOKMLKNJQJSKVMXOYSZZZ JRVR", - "E_XP[RXT UMZRUW IRZR", - "JZPLRITL MORJWO RJR[", - "E_LPIRLT OMJROW JR[R", - "JZPXR[TX MURZWU RIRZ", - "I\\XRWOVNTMRMONMQLTLWMYNZP[R[UZWXXUYPYKXHWGUFRFPGOHOIPIPH RMPNNQMTMXNZ R[TZVXWUXPXKWHUF", - "H\\JFR[ KFRY ZFR[ JFZF KGYG", - "AbDMIMRY HNR[ b:R[", - "F^[CZD[E\\D\\C[BYBWCUETGSJRNPZO^N` VDUFTJRVQZP]O_MaKbIbHaH`I_J`Ia", - "F^[CZD[E\\D\\C[BYBWCUETGSJRNPZO^N` VDUFTJRVQZP]O_MaKbIbHaH`I_J`Ia QKNLLNKQKSLVNXQYSYVXXVYSYQXNVLSKQK", - "F_\\S[UYVWVUUTTQPPONNLNJOIQISJULVNVPUQTTPUOWNYN[O\\Q\\S", - "F^[FI[ NFPHPJOLMMKMIKIIJGLFNFPGSHVHYG[F WTUUTWTYV[X[ZZ[X[VYTWT", - "F_[NZO[P\\O\\N[MZMYNXPVUTXRZP[M[JZIXIUJSPORMSKSIRGPFNGMIMKNNPQUXWZZ[[[\\Z\\Y M[KZJXJUKSMQ MKNMVXXZZ[", - "E`WNVLTKQKOLNMMPMSNUPVSVUUVS QKOMNPNSOUPV WKVSVUXVZV\\T]Q]O\\L[JYHWGTFQFNGLHJJILHOHRIUJWLYNZQ[T[WZYYZX XKWSWUXV", - "H\\PBP_ TBT_ XIWJXKYJYIWGTFPFMGKIKKLMMNOOUQWRYT KKMMONUPWQXRYTYXWZT[P[MZKXKWLVMWLX", - "G]OFOb UFUb JQZQ JWZW", - "JZUITJUKVJVIUGSFQFOGNINKOMQOVR OMTPVRWTWVVXTZ PNNPMRMTNVPXU[ NVSYU[V]V_UaSbQbOaN_N^O]P^O_", - "JZRFQHRJSHRF RFRb RQQTRbSTRQ LMNNPMNLLM LMXM TMVNXMVLTM", - "JZRFQHRJSHRF RFRT RPQRSVRXQVSRRP RTRb R^Q`RbS`R^ LMNNPMNLLM LMXM TMVNXMVLTM L[N\\P[NZL[ L[X[ T[V\\X[VZT[", - "I\\XFX[ KFXF PPXP K[X[", - "", - "E`QFNGKIILHOHRIUKXNZQ[T[WZZX\\U]R]O\\LZIWGTFQF ROQPQQRRSRTQTPSORO RPRQSQSPRP", - "J[PFNGOIQJ PFOGOI UFWGVITJ UFVGVI QJOKNLMNMQNSOTQUTUVTWSXQXNWLVKTJQJ RUR[ SUS[ NXWX", - "I\\RFOGMILLLMMPORRSSSVRXPYMYLXIVGSFRF RSR[ SSS[ NWWW", - "D`PFMGJIHLGOGSHVJYM[P\\T\\W[ZY\\V]S]O\\LZIWGTFPF RFR\\ GQ]Q", - "G`PMMNKPJSJTKWMYPZQZTYVWWTWSVPTNQMPM ]GWG[HUN ]G]M\\IVO \\HVN", - "F\\IIJGLFOFQGRIRLQOPQNSKU OFPGQIQMPPNS VFT[ WFS[ KUYU", - "I\\MFMU NFMQ MQNOONQMTMWNXPXRWTUV TMVNWPWRTXTZU[W[YY KFNF", - "I\\RNOOMQLTLUMXOZR[S[VZXXYUYTXQVOSNRN RHNJRFRN SHWJSFSN RSQTQURVSVTUTTSSRS RTRUSUSTRT", - "G^QHRFR[ THSFS[ JHKFKMLPNRQSRS MHLFLNMQ [HZFZMYPWRTSSS XHYFYNXQ NWWW", - "G]LFL[ MFM[ IFUFXGYHZJZMYOXPUQMQ UFWGXHYJYMXOWPUQ I[Y[YVX[", - "H[YGUGQHNJLMKPKSLVNYQ[U\\Y\\ YGVHSJQMPPPSQVSYV[Y\\", - "F_OQMQKRJSIUIWJYKZM[O[QZRYSWSURSQROQ SHPQ ZJRR \\QST", - "H\\OKUY UKOY KOYU YOKU", - "F^NVLUKUIVHXHYI[K\\L\\N[OYOXNVKRJOJMKJMHPGTGWHYJZMZOYRVVUXUYV[X\\Y\\[[\\Y\\X[VYUXUVV JMKKMIPHTHWIYKZM", - "F^NMLNKNIMHKHJIHKGLGNHOJOKNMKQJTJVKYM[P\\T\\W[YYZVZTYQVMUKUJVHXGYG[H\\J\\K[MYNXNVM JVKXMZP[T[WZYXZV", - "I[KYYK QLULYKXOXS ULXLXO", - "I[YKKY LQLUKYOXSX LULXOX", - "I[YYKK SLOLKKLOLS OLLLLO", - "I[KKYY QXUXYYXUXQ UXXXXU", - "", - "F_JMILIJJHLGNGPHQIRKSP IJKHMHOIPJQLRPR[ [M\\L\\J[HYGWGUHTISKRP \\JZHXHVIUJTLSPS[", - "F^IGJKKMMOPPTPWOYMZK[G IGJJKLMNPOTOWNYLZJ[G PONPMQLSLVMXOZQ[S[UZWXXVXSWQVPTO PPNQMSMVNY VYWVWSVQTP", - "F^MJMV NKNU VKVU WJWV IGKIMJPKTKWJYI[G IYKWMVPUTUWVYW[Y", - "F^[ILIJJILINJPLQNQPPQNQLPJ[J IMJOKPMQ QMPKOJMI IXXXZW[U[SZQXPVPTQSSSUTWIW [TZRYQWP STTVUWWX", - "F]OUMTLTJUIWIXJZL[M[OZPXPWOUJPINIKJILHOGSGWHYJZLZOYRVUUWUYV[X[YZZX MSKPJNJKKILH SGVHXJYLYOXRVU", - "G_HKKHMKMV JILLLV MKPHRKRU OIQLQU RKUHWKW[ TIVLV[ WKZH[J\\M\\P[SZUXWUYP[ YIZJ[M[PZSYUWWTYP[", - "F^ISMSLRKOKMLJNHQGSGVHXJYMYOXRWS[S ITOTMRLOLMMJOHQG SGUHWJXMXOWRUT[T KXYX KYYY", - "F_GLJIMLMX IJLMLX MLPISLSX OJRMRX SLVIYLYW[Y UJXMXXZZ]W", - "G]ZIJY ZIWJQJ XKUKQJ ZIYLYR XKXNYR QRJR PSMSJR QRQY PSPVQY", - "F^HOJKOU JMOWRPWPZO[M[KZIXHWHUITKTMUPVRWUWXUZ WHVIUKUMWQXTXWWYUZ", - "F^IOLLPN KMOORLUN QMTOWLYN VMXO[L IULRPT KSOURRUT QSTUWRYT VSXU[R", - "F^JHNJPLQOQRPUNWJY JHMIOJQLRO RRQUOWMXJY ZHWIUJSLRO RRSUUWWXZY ZHVJTLSOSRTUVWZY IP[P IQ[Q", - "", - "", - "", - "", - "NVQQQSSSSQQQ QQSS SQQS", - "JZMPQRTTVVWYW[V]U^ MQST MRPSTUVWWY", - "JZWKVMTOPQMR SPMS UFVGWIWKVNTPQRMT", - "H\\SMONLPKRKTLVNWQWUVXTYRYPXNVMSM XNSM VMQNLP ONKR LVQW NWSVXT UVYR", - "H\\SMONLPKRKTLVNWQWUVXTYRYPXNVMSM XNSM VMQNLP ONKR LVQW NWSVXT UVYR", - "J[SMPNNPMRMTNVPWRWUVWTXRXPWNUMSM OPUM NRVN MTWO NUXP OVWR PWVT", - "JZOGO^ UFU] MNWL MOWM MWWU MXWV", - "JZNFNX VLV^ NNVL NOVM NWVU NXVV", - "JZNBNW NNQLTLVMWOWQVSSUQVNW NNQMTMVN UMVOVQUSSU", - "E_HIHL \\I\\L HI\\I HJ\\J HK\\K HL\\L", - "JZMNMQ WNWQ MNWN MOWO MPWP MQWQ", - "JZMLWX MLONQOTOVNWMWKUKUMTO ONTO QOWM VKVN ULWL WXUVSUPUNVMWMYOYOWPU UVPU SUMW NVNY MXOX", - "JZPOOMOKMKMMNNPOSOUNWL NKNN MLOL MMSO POUN WLWY", - "A^GfHfIeIdHcGcFdFfGhIiKiNhPfQdR`RUQ;Q4R/S-U,V,X-Y/Y3X6W8U;P?JCHEFHEJDNDREVGYJ[N\\R\\V[XZZW[T[PZMYKWITHPHMIKKJNJRKUMW GdGeHeHdGd U;Q?LCIFGIFKENERFVGXJ[ R\\U[WZYWZTZPYMXKVITH", - "EfNSOUQVSVUUVSVQUOSNQNOONPMSMVNYP[S\\V\\Y[[Y\\W]T]P\\MZJXIUHRHOIMJKLIOHSHXI]KaMcPeTfYf]e`cba KLJNIRIXJ\\L`NbQdUeYe]d_cba POTO OPUP NQVQ NRVR NSVS OTUT PUTU aLaNcNcLaL bLbN aMcM aVaXcXcVaV bVbX aWcW", - "D`H@Hd M@Md W@Wd \\@\\d MMWK MNWL MOWM MWWU MXWV MYWW", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NVQQQSSSSQQQ QQSS SQQS", - "JZMPQRTTVVWYW[V]U^ MQST MRPSTUVWWY", - "JZWKVMTOPQMR SPMS UFVGWIWKVNTPQRMT", - "H\\PMMNLOKQKSLUMVPWTWWVXUYSYQXOWNTMPM MNLPLSMUNVPW WVXTXQWOVNTM", - "H\\SMONLPKRKTLVNWQWUVXTYRYPXNVMSM XNSM VMQNLP ONKR LVQW NWSVXT UVYR", - "J[SMPNNPMRMTNVPWRWUVWTXRXPWNUMSM OPUM NRVN MTWO NUXP OVWR PWVT", - "JZOGO^ UFU] MNWL MOWM MWWU MXWV", - "JZNFNX VLV^ NNVL NOVM NWVU NXVV", - "JZNBNW NNQLTLVMWOWQVSSUQVNW NNQMTMVN UMVOVQUSSU", - "E_HIHL \\I\\L HI\\I HJ\\J HK\\K HL\\L", - "JZMNMQ WNWQ MNWN MOWO MPWP MQWQ", - "JZQCVMRTRU ULQS TITKPRRUUY W\\UYSXQXOYN[N]O_Ra W\\UZSYOYO]P_Ra SXPZN]", - "JZPOOMOKMKMMNNPOSOUNWL NKNN MLOL MMSO POUN WLSY", - "A^GfHfIeIdHcGcFdFfGhIiKiNhPfQdR`RUQ;Q4R/S-U,V,X-Y/Y3X6W8U;P?JCHEFHEJDNDREVGYJ[N\\R\\V[XZZW[T[PZMYKWITHPHMIKKJNJRKUMW GdGeHeHdGd U;Q?LCIFGIFKENERFVGXJ[ R\\U[WZYWZTZPYMXKVITH", - "IjNQOOQNSNUOVQVSUUSVQVOUNTMQMNNKPISHWH[I^K`NaRaW`[_]]`ZcVfQiMk WHZI]K_N`R`W_[^]\\`YcTgQi POTO OPUP NQVQ NRVR NSVS OTUT PUTU eLeNgNgLeL fLfN eMgM eVeXgXgVeV fVfX eWgW", - "D`H>Hf I>If M>Mf QBSBSDQDQAR?T>W>Y?[A\\D\\I[LYNWOUOSNRLQNOQNROSQVRXSVUUWUYV[X\\[\\`[cYeWfTfReQcQ`S`SbQb RBRD QCSC Y?ZA[D[IZLYN RLRNPQNRPSRVRX YVZX[[[`ZcYe R`Rb QaSa", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "AcHBHb IBIb [B[b \\B\\b DB`B DbMb Wb`b", - "BaGBQPFb FBPP EBPQ EB\\B^I[B Ga\\a Fb\\b^[[b", - "I[X+U1R8P=OANFMNMVN^OcPgRlUsXy U1S6QPBTJTLSNROMRRUSVTXTZPbOfOjPoRsVy T.R2Q5P:P>QCRF R^QaPfPjQoRrTv", - "I\\N+R1T5U:U>TBPJPLQNROWRRUQVPXPZTbUfUjToRsNy P.R2S5T:T>SCRF R^SaTfTjSoRrPv", - "I[V.S1Q4O8N=NCOIPMSXT\\UbUgTlSoQs S1Q5P8O=OBPHQLTWU[VaVgUlSpQsNv", - "I[N.Q1S4U8V=VCUITMQXP\\ObOgPlQoSs Q1S5T8U=UBTHSLPWO[NaNgOlQpSsVv", - "7Z:RARRo @RQo ?RRr Z\"VJRr", - "Ca].\\.[/[0\\1]1^0^.],[+Y+W,U.T0S3R:QJQjPsOv \\/\\0]0]/\\/ R:Rj U.T1S:SZRjQqPtOvMxKyIyGxFvFtGsHsItIuHvGv GtGuHuHtGt", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "H\\RFJ[ RIK[J[ RIY[Z[ RFZ[ MUWU LVXV", - "H\\LFL[ MGMZ LFTFWGXHYJYMXOWPTQ MGTGWHXJXMWOTP MPTPWQXRYTYWXYWZT[L[ MQTQWRXTXWWYTZMZ", - "H]ZKYIWGUFQFOGMILKKNKSLVMXOZQ[U[WZYXZV ZKYKXIWHUGQGOHMKLNLSMVOYQZUZWYXXYVZV", - "H]LFL[ MGMZ LFSFVGXIYKZNZSYVXXVZS[L[ MGSGVHWIXKYNYSXVWXVYSZMZ", - "I\\MFM[ NGNZ MFYF NGYGYF NPTPTQ NQTQ NZYZY[ M[Y[", - "I[MFM[ NGN[M[ MFYF NGYGYF NPTPTQ NQTQ", - "H]ZKYIWGUFQFOGMILKKNKSLVMXOZQ[U[WZYXZVZRUR ZKYKXIWHUGQGOHNIMKLNLSMVNXOYQZUZWYXXYVYSUSUR", - "G]KFK[ KFLFL[K[ YFXFX[Y[ YFY[ LPXP LQXQ", - "NWRFR[S[ RFSFS[", - "J[VFVVUYSZQZOYNVMV VFWFWVVYUZS[Q[OZNYMV", - "H]LFL[M[ LFMFM[ ZFYFMR ZFMS POY[Z[ QOZ[", - "IZMFM[ MFNFNZ NZYZY[ M[Y[", - "F^JFJ[ KKK[J[ KKR[ JFRX ZFRX YKR[ YKY[Z[ ZFZ[", - "G]KFK[ LIL[K[ LIY[ KFXX XFXX XFYFY[", - "G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF QGNHLKKNKSLVNYQZSZVYXVYSYNXKVHSGQG", - "H\\LFL[ MGM[L[ LFUFWGXHYJYMXOWPUQMQ MGUGWHXJXMWOUPMP", - "G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF QGNHLKKNKSLVNYQZSZVYXVYSYNXKVHSGQG SXX]Y] SXTXY]", - "H\\LFL[ MGM[L[ LFTFWGXHYJYMXOWPTQMQ MGTGWHXJXMWOTPMP RQX[Y[ SQY[", - "H\\YIWGTFPFMGKIKKLMMNOOTQVRWSXUXXWYTZPZNYMXKX YIWIVHTGPGMHLILKMMONTPVQXSYUYXWZT[P[MZKX", - "J[RGR[ SGS[R[ LFYFYG LFLGYG", - "G]KFKULXNZQ[S[VZXXYUYF KFLFLUMXNYQZSZVYWXXUXFYF", - "H\\JFR[ JFKFRX ZFYFRX ZFR[", - "E_GFM[ GFHFMX RFMX RIM[ RIW[ RFWX ]F\\FWX ]FW[", - "H\\KFX[Y[ KFLFY[ YFXFK[ YFL[K[", - "I\\KFRPR[S[ KFLFSP ZFYFRP ZFSPS[", - "H\\XFK[ YFL[ KFYF KFKGXG LZYZY[ K[Y[", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "E\\XFVHTKQPOSLWIZG[E[DZDXEWFXEY XFWJUTT[ XFU[ T[TYSVRTPRNQLQKRKTLWOZR[V[XZ", - "F^UGTHSJQOOUNWLZJ[ THSKQSPVOXMZJ[H[GZGXHWIXHY OLNNMOKOJNJLKJMHOGRFXFZG[I[KZMXNTORO XFYGZIZKYMXN TOWPXQYSYVXYWZU[S[RZRXSU TOVPWQXSXVWYU[", - "H]KHJJJLKNNOQOUNWMYKZIZGYFWFTGQJOMMQLULXMZP[R[UZWXXVXTWRURSSRU WFUGRJPMNQMUMXNZP[", - "F]UGTHSJQOOUNWLZJ[ THSKQSPVOXMZJ[H[GZGXHWJWLXNZP[S[UZWXYTZOZLYIWGUFPFMGKIJKJMKNMNNMOK", - "I\\WIVJVLWMYMZKZIYGWFTFRGQHPJPLQNSO TFRHQJQMSO SOQONPLRKTKWLYMZO[R[UZWXXVXTWRURSSRU QOOPMRLTLXMZ", - "G\\WHVJTORUQWOZM[ QLPNNOLOKMKKLINGQF[FXGWHVKTSSVRXPZM[K[IZHYHXIWJXIY SFWGXG OSPRRQVQXPZMXT", - "G]JIIKIMJOLPOPROTNWKXHXGWFVFTGRIQKPNPQQSSTUTWSYQZO WFUGSIRKQNQRST ZOYSWWUYSZO[L[JZIXIWJVKWJX YSWVUXRZO[", - "F^LLKKKILGOFRFOQMWLYKZI[G[FZFXGWHXGY RFOONRLWKYI[ JTKSMRVOXN[L]J^H^G]F\\FZGXJWLURTVTYV[W[YZ[X \\FZHXLVRUVUYV[", - "IYWHUKSPQUPWNZL[ YLWNTOQOONNLNJOHQGUFYFWHVJTPRVQXOZL[J[IZIXJWKXJY", - "IZYFWHUKSPPYN] YMWOTPQPOONMNKOIQGUFYFWIVKSTQXPZN]M^K_J^J\\KZMXOWRVVU", - "F^LLKKKIMGPFRFOQMWLYKZI[G[FZFXGWHXGY RFOONRLWKYI[ ZGWKUMSNPO ]G\\H]I^H^G]F\\FZGWLVMTNPO POSPTRUYV[ PORPSRTYV[W[YZ[X", - "I[MILKLMMOOPRPUOWNZK[H[GZFYFWGVHTKPUOWMZK[ VHTLRSQVPXNZK[I[HZHXIWKWMXPZR[U[WZYX", - "D`RFNOKUIXGZE[C[BZBXCWDXCY RFPMOQNVNZP[ RFQJPOOVOZP[ [FWORXP[ [FYMXQWVWZY[Z[\\Z^X [FZJYOXVXZY[", - "G^RFQJOPMULWJZH[F[EZEXFWGXFY RFRKSVT[ RFSKTVT[ `G_H`IaHaG`F^F\\GZJYLWQUWT[", - "H]SFQGOIMLLNKRKVLYMZO[Q[TZVXXUYSZOZKYHXGWGUHSJQNPSPV QGOJMNLRLVMYO[", - "F]UGTHSJQOOUNWLZJ[ THSKQSPVOXMZJ[H[GZGXHWIXHY OLNNMOKOJNJLKJMHOGRFVFYGZH[J[MZOYPVQTQRP VFXGYHZJZMYOXPVQ", - "H]UJULTNSOQPOPNNNLOIQGTFWFYGZIZMYPWSSWPYNZK[I[HZHXIWKWMXPZS[V[XZZX WFXGYIYMXPVSSVOYK[", - "F^UGTHSJQOOUNWLZJ[ THSKQSPVOXMZJ[H[GZGXHWIXHY OLNNMOKOJNJLKJMHOGRFWFZG[I[KZMYNVORO WFYGZIZKYMXNVO ROUPVRWYX[ ROTPURVYX[Y[[Z]X", - "H\\NIMKMMNOPPSPVOXN[K\\H\\G[FZFXGWHVJUMSTRWPZN[ VJUNTUSXQZN[K[IZHXHWIVJWIX", - "I[YHXJVOTUSWQZO[ SLRNPONOMMMKNIPGSF\\FZGYHXKVSUVTXRZO[M[KZJYJXKWLXKY UFYGZG", - "G]HJJGLFMFOHOKNNKVKYL[ MFNHNKKSJVJYL[N[PZSWUTVR ZFVRUVUYW[X[ZZ\\X [FWRVVVYW[", - "G\\HJJGLFMFOHOKNOLVLYM[ MFNHNKLRKVKYM[N[QZTWVTXPYMZIZGYFXFWGVIVLWNYP[Q]Q", - "F]ILHLGKGIHGJFNFMHLLKUJ[ LLLUK[ VFTHRLOUMYK[ VFUHTLSUR[ TLTUS[ `F^G\\IZLWUUYS[", - "H\\PKOLMLLKLIMGOFQFSGTITLSPQUOXMZJ[H[GZGXHWIXHY QFRGSISLRPPUNXLZJ[ ]G\\H]I^H^G]F[FYGWIULSPRURXSZT[U[WZYX", - "G]JJLGNFOFQGQIOOORPT OFPGPINONRPTRTUSWQYNZL \\FZLWTUX ]F[LYQWUUXSZP[L[JZIXIWJVKWJX", - "G\\ZHYJWOVRUTSWQYOZL[ SLRNPONOMMMKNIPGSF]F[GZHYKXOVUTXQZL[H[GZGXHWJWLXOZQ[T[WZYX VFZG[G", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "H\\WMW[X[ WMXMX[ WPUNSMPMNNLPKSKULXNZP[S[UZWX WPSNPNNOMPLSLUMXNYPZSZWX", - "H\\LFL[M[ LFMFM[ MPONQMTMVNXPYSYUXXVZT[Q[OZMX MPQNTNVOWPXSXUWXVYTZQZMX", - "I[XPVNTMQMONMPLSLUMXOZQ[T[VZXX XPWQVOTNQNOONPMSMUNXOYQZTZVYWWXX", - "H\\WFW[X[ WFXFX[ WPUNSMPMNNLPKSKULXNZP[S[UZWX WPSNPNNOMPLSLUMXNYPZSZWX", - "I[MTXTXQWOVNTMQMONMPLSLUMXOZQ[T[VZXX MSWSWQVOTNQNOONPMSMUNXOYQZTZVYWWXX", - "LZWFUFSGRJR[S[ WFWGUGSH TGSJS[ OMVMVN OMONVN", - "H\\XMWMW\\V_U`SaQaO`N_L_ XMX\\W_UaSbPbNaL_ WPUNSMPMNNLPKSKULXNZP[S[UZWX WPSNPNNOMPLSLUMXNYPZSZWX", - "H\\LFL[M[ LFMFM[ MQPNRMUMWNXQX[ MQPORNTNVOWQW[X[", - "NWRFQGQHRISITHTGSFRF RGRHSHSGRG RMR[S[ RMSMS[", - "NWRFQGQHRISITHTGSFRF RGRHSHSGRG RMRbSb RMSMSb", - "H[LFL[M[ LFMFM[ XMWMMW XMMX PTV[X[ QSX[", - "NWRFR[S[ RFSFS[", - "CbGMG[H[ GMHMH[ HQKNMMPMRNSQS[ HQKOMNONQORQR[S[ SQVNXM[M]N^Q^[ SQVOXNZN\\O]Q][^[", - "H\\LML[M[ LMMMM[ MQPNRMUMWNXQX[ MQPORNTNVOWQW[X[", - "I\\QMONMPLSLUMXOZQ[T[VZXXYUYSXPVNTMQM QNOONPMSMUNXOYQZTZVYWXXUXSWPVOTNQN", - "H\\LMLbMb LMMMMb MPONQMTMVNXPYSYUXXVZT[Q[OZMX MPQNTNVOWPXSXUWXVYTZQZMX", - "H\\WMWbXb WMXMXb WPUNSMPMNNLPKSKULXNZP[S[UZWX WPSNPNNOMPLSLUMXNYPZSZWX", - "KYOMO[P[ OMPMP[ PSQPSNUMXM PSQQSOUNXNXM", - "J[XPWNTMQMNNMPNRPSUUWV VUWWWXVZ WYTZQZNY OZNXMX XPWPVN WOTNQNNO ONNPOR NQPRUTWUXWXXWZT[Q[NZMX", - "MXRFR[S[ RFSFS[ OMVMVN OMONVN", - "H\\LMLWMZO[R[TZWW LMMMMWNYPZRZTYWW WMW[X[ WMXMX[", - "JZLMR[ LMMMRY XMWMRY XMR[", - "F^IMN[ IMJMNX RMNX RPN[ RPV[ RMVX [MZMVX [MV[", - "I[LMW[X[ LMMMX[ XMWML[ XMM[L[", - "JZLMR[ LMMMRY XMWMRYNb XMR[ObNb", - "I[VNL[ XMNZ LMXM LMLNVN NZXZX[ L[X[", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "K[UUTSRRPRNSMTLVLXMZO[Q[SZTX PRNTMVMYO[ VRTXTZV[XZYY[V WRUXUZV[", - "LZLVNSPO SFMXMZO[P[RZTXUUURVVWWXWZV TFNXNZO[", - "LXTSSTTTTSSRQROSNTMVMXNZP[S[VYXV QROTNVNYP[", - "K[UUTSRRPRNSMTLVLXMZO[Q[SZTX PRNTMVMYO[ ZFTXTZV[XZYY[V [FUXUZV[", - "LXOYQXRWSUSSRRQROSNTMVMXNZP[S[VYXV QROTNVNYP[", - "OXRRUOWLXIXGWFUGTIKdKfLgNfOcPZQ[S[UZVYXV TISNRRO[M`Kd", - "K[UUTSRRPRNSMTLVLXMZO[Q[SZTX PRNTMVMYO[ VRPd WRT[R`PdOfMgLfLdMaO_R]V[YY[V", - "L[LVNSPO SFL[ TFM[ OUQSSRTRVSVUUXUZV[ TRUSUUTXTZV[XZYY[V", - "NVSLRMSNTMSL QROXOZQ[SZTYVV RRPXPZQ[", - "NVSLRMSNTMSL QRKd RRO[M`KdJfHgGfGdHaJ_M]Q[TYVV", - "LZLVNSPO SFL[ TFM[ URUSVSURTRRTOU OURVSZT[ OUQVRZT[U[XYZV", - "NVNVPSRO UFOXOZQ[SZTYVV VFPXPZQ[", - "E^EVGSIRKSKUI[ IRJSJUH[ KUMSORPRRSRUP[ PRQSQUO[ RUTSVRWRYSYUXXXZY[ WRXSXUWXWZY[[Z\\Y^V", - "I[IVKSMROSOUM[ MRNSNUL[ OUQSSRTRVSVUUXUZV[ TRUSUUTXTZV[XZYY[V", - "KYRRPRNSMTLVLXMZO[Q[SZTYUWUUTSRRQSQURWTXVXXWYV PRNTMVMYO[", - "L[LVNSPO QLHg RLIg OUQSSRTRVSVUUXUZV[ TRUSUUTXTZV[XZYY[V", - "K[UUTSRRPRNSMTLVLXMZO[Q[SZ PRNTMVMYO[ VRPdPfQgSfTcT[V[YY[V WRT[R`Pd", - "LZLVNSPRRSRUP[ PRQSQUO[ RUTSVRWRVU VRVUWWXWZV", - "NZNVPSQQQSTUUWUYTZR[ QSSUTWTYR[ NZP[U[XYZV", - "NVNVPSRO UFOXOZQ[SZTYVV VFPXPZQ[ PNVN", - "K[NRLXLZN[O[QZSXUU ORMXMZN[ VRTXTZV[XZYY[V WRUXUZV[", - "KZNRMTLWLZN[O[RZTXUUUR ORNTMWMZN[ URVVWWXWZV", - "H]LRJTIWIZK[L[NZPX MRKTJWJZK[ RRPXPZR[S[UZWXXUXR SRQXQZR[ XRYVZW[W]V", - "JZJVLSNRPRQSQUPXOZM[L[KZKYLYKZ WSVTWTWSVRURSSRUQXQZR[U[XYZV QSRU SSQU PXQZ QXOZ", - "K[NRLXLZN[O[QZSXUU ORMXMZN[ VRPd WRT[R`PdOfMgLfLdMaO_R]V[YY[V", - "LYLVNSPRRRTSTVSXPZN[ RRSSSVRXPZ N[P\\Q^QaPdNfLgKfKdLaO^R\\VYYV N[O\\P^PaOdNf", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NV", - "JZ", - "H\\QFNGLJKOKRLWNZQ[S[VZXWYRYOXJVGSFQF OGMJLOLRMWOZ NYQZSZVY UZWWXRXOWJUG VHSGQGNH", - "H\\NJPISFS[ NJNKPJRHR[S[", - "H\\LKLJMHNGPFTFVGWHXJXLWNUQL[ LKMKMJNHPGTGVHWJWLVNTQK[ LZYZY[ K[Y[", - "H\\MFXFQO MFMGWG WFPO QNSNVOXQYTYUXXVZS[P[MZLYKWLW POSOVPXS TOWQXTXUWXTZ XVVYSZPZMYLW OZLX", - "H\\UIU[V[ VFV[ VFKVZV UILV LUZUZV", - "H\\MFLO NGMN MFWFWG NGWG MNPMSMVNXPYSYUXXVZS[P[MZLYKWLW LOMOONSNVOXR TNWPXSXUWXTZ XVVYSZPZMYLW OZLX", - "H\\VGWIXIWGTFRFOGMJLOLTMXOZR[S[VZXXYUYTXQVOSNRNOOMQ WHTGRGOH PGNJMOMTNXQZ MVOYRZSZVYXV TZWXXUXTWQTO XSVPSOROOPMS QONQMT", - "H\\KFYFO[ KFKGXG XFN[O[", - "H\\PFMGLILKMMNNPOTPVQWRXTXWWYTZPZMYLWLTMRNQPPTOVNWMXKXIWGTFPF NGMIMKNMPNTOVPXRYTYWXYWZT[P[MZLYKWKTLRNPPOTNVMWKWIVG WHTGPGMH LXOZ UZXX", - "H\\WPURRSQSNRLPKMKLLINGQFRFUGWIXMXRWWUZR[P[MZLXMXNZ WMVPSR WNUQRRQRNQLN PRMPLMLLMIPG LKNHQGRGUHWK SGVIWMWRVWTZ UYRZPZMY", - "MXRXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "MXTZS[R[QZQYRXSXTYT\\S^Q_ RYRZSZSYRY S[T\\ TZS^", - "MXRMQNQORPSPTOTNSMRM RNROSOSNRN RXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "MXRMQNQORPSPTOTNSMRM RNROSOSNRN TZS[R[QZQYRXSXTYT\\S^Q_ RYRZSZSYRY S[T\\ TZS^", - "MXRFRTST RFSFST RXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "I\\LKLJMHNGQFTFWGXHYJYLXNWOUPRQ LKMKMJNHQGTGWHXJXLWNUORP MIPG UGXI XMTP RPRTSTSP RXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "MXTFRGQIQLRMSMTLTKSJRJQK RKRLSLSKRK RGQK QIRJ", - "MXTHSIRIQHQGRFSFTGTJSLQM RGRHSHSGRG SITJ THSL", - "F_\\MZMXNWPUVTXSYQZMZKYJWJUKSLRQOSMTKTISGQFPFNGMIMKNNPQUWXZZ[\\[ \\M\\NZNWP ZMXPVVUXSZQ[M[KZJYIWIUJSLQQNRMSKSIRG SHQGPGNH OGNINKONQQVWXYZZ\\Z\\[", - "I\\RBR_S_ RBSBS_ WIYIWGTFQFNGLILKMMNNVRWSXUXWWYTZQZOYNX WIVHTGQGNHMIMKNMVQXSYUYWXYWZT[Q[NZLXNX XXUZ", - "G^[BIbJb [B\\BJb", - "KYUBSDQGOKNPNTOYQ]S`UbVb UBVBTDRGPKOPOTPYR]T`Vb", - "KYNBPDRGTKUPUTTYR]P`NbOb NBOBQDSGUKVPVTUYS]Q`Ob", - "JZRFQGSQRR RFRR RFSGQQRR MINIVOWO MIWO MIMJWNWO WIVINOMO WIMO WIWJMNMO", - "F_JQ[Q[R JQJR[R", - "F_RIRZSZ RISISZ JQ[Q[R JQJR[R", - "F_JM[M[N JMJN[N JU[U[V JUJV[V", - "NWSFRGRM SGRM SFTGRM", - "I[NFMGMM NGMM NFOGMM WFVGVM WGVM WFXGVM", - "KYQFOGNINKOMQNSNUMVKVIUGSFQF QFNIOMSNVKUGQF SFOGNKQNUMVISF", - "F^ZIJRZ[ ZIZJLRZZZ[", - "F^JIZRJ[ JIJJXRJZJ[", - "G^OFObPb OFPFPb UFUbVb UFVFVb JP[P[Q JPJQ[Q JW[W[X JWJX[X", - "F^[FYGVHSHPGNFLFJGIIIKKMMMOLPJPHNF [FH[I[ [F\\FI[ YTWTUUTWTYV[X[ZZ[X[VYT NFJGIKMMPJNF LFIIKMOLPHLF YTUUTYX[[XYT WTTWV[ZZ[VWT", - "E`WMTKQKOLNMMOMRNTOUQVTVWT WMTLQLOMNONROTQUTUWT VKVSWUYVZV\\U]S]O\\L[JYHWGTFQFNGLHJJILHOHRIUJWLYNZQ[U[YZ VKWKWSXUZV YV[U\\S\\O[LZJYIWHTGQGNHLIKJJLIOIRJUKWLXNYQZUZYYYZ", - "E_JPLONOPPSTTUVVXVZU[S[QZOXNVNTOSPPTNULUJT ZPXOVOTPQTPUNVLVJUISIQJOLNNNPOQPTTVUXUZT KOJQJSKU YUZSZQYO", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NV", - "JZ", - "H]TFQGOIMLLOKSKVLYMZO[Q[TZVXXUYRZNZKYHXGVFTF TFRGPINLMOLSLVMYO[ Q[SZUXWUXRYNYKXHVF", - "H]TJO[ VFP[ VFSIPKNL UIQKNL", - "H]OJPKOLNKNJOHPGSFVFYGZIZKYMWOTQPSMUKWI[ VFXGYIYKXMVOPS JYKXMXRZUZWYXW MXR[U[WZXW", - "H]OJPKOLNKNJOHPGSFVFYGZIZKYMVOSP VFXGYIYKXMVO QPSPVQWRXTXWWYVZS[O[LZKYJWJVKULVKW SPUQVRWTWWVYUZS[", - "H]XGR[ YFS[ YFJUZU", - "H]QFLP QF[F QGVG[F LPMOPNSNVOWPXRXUWXUZR[O[LZKYJWJVKULVKW SNUOVPWRWUVXTZR[", - "H]YIXJYKZJZIYGWFTFQGOIMLLOKSKWLYMZO[R[UZWXXVXSWQVPTOQOOPMRLT TFRGPINLMOLSLXMZ R[TZVXWVWRVP", - "H]NFLL [FZIXLSRQUPWO[ XLRRPUOWN[ MIPFRFWI NHPGRGWIYIZH[F", - "H]SFPGOHNJNMOOQPTPXOYNZLZIYGVFSF SFQGPHOJOMPOQP TPWOXNYLYIXGVF QPMQKSJUJXKZN[R[VZWYXWXTWRVQTP QPNQLSKUKXLZN[ R[UZVYWWWSVQ", - "H]YMXOVQTRQROQNPMNMKNIPGSFVFXGYHZJZNYRXUVXTZQ[N[LZKXKWLVMWLX OQNONKOIQGSF XGYIYNXRWUUXSZQ[", - "MXPYOZP[QZPY", - "MXP[OZPYQZQ[P]N_", - "MXSMRNSOTNSM PYOZP[QZ", - "MXSMRNSOTNSM P[OZPYQZQ[P]N_", - "MXUFTGRS UGRS UFVGRS PYOZP[QZPY", - "H]OJPKOLNKNJOHPGSFWFZG[I[KZMYNSPQQQSRTTT WFYGZIZKYMXNVO PYOZP[QZPY", - "MXVFTHSJSKTLUKTJ", - "MXUHTGUFVGVHUJSL", - "E_\\N[O\\P]O]N\\M[MYNWPRXPZN[K[HZGXGVHTISKRPPROTMUKUITGRFPGOIOLPRQUSXUZW[Y[ZYZX K[IZHXHVITJSPP OLPQQTSWUYWZYZZY", - "H]TBL_ YBQ_ ZJYKZL[K[JZHYGVFRFOGMIMKNMONVRXT MKOMVQWRXTXWWYVZS[O[LZKYJWJVKULVKW", - "G]_BEb", - "KZZBVESHQKOONTNXO]P`Qb VESIQMPPOUOZP_Qb", - "JYSBTDUGVLVPUUSYQ\\N_Jb SBTEUJUOTTSWQ[N_", - "J[TFTR OIYO YIOO", - "E_IR[R", - "E_RIR[ IR[R", - "E_IO[O IU[U", - "NWUFSM VFSM", - "I[PFNM QFNM YFWM ZFWM", - "KZSFQGPIPKQMSNUNWMXKXIWGUFSF", - "F^ZIJRZ[", - "F^JIZRJ[", - "H]SFLb YFRb LQZQ KWYW", - "E_^F\\GXHUHQGOFMFKGJIJKLMNMPLQJQHOF ^FF[ XTVTTUSWSYU[W[YZZXZVXT", - "E`WNVLTKQKOLNMMPMSNUPVSVUUVS QKOMNPNSOUPV WKVSVUXVZV\\T]Q]O\\L[JYHWGTFQFNGLHJJILHOHRIUJWLYNZQ[T[WZYYZX XKWSWUXV", - "F_\\S[UYVWVUUTTQPPONNLNJOIQISJULVNVPUQTTPUOWNYN[O\\Q\\S", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "H\\RFK[ RFY[ RIX[ MUVU I[O[ U[[[", - "G]LFL[ MFM[ IFYFYLXF MPUPXQYRZTZWYYXZU[I[ UPWQXRYTYWXYWZU[", - "G]LFL[ MFM[ IFUFXGYHZJZLYNXOUP UFWGXHYJYLXNWOUP MPUPXQYRZTZWYYXZU[I[ UPWQXRYTYWXYWZU[", - "I[NFN[ OFO[ KFZFZLYF K[R[", - "F^NFNLMTLXKZJ[ XFX[ YFY[ KF\\F G[\\[ G[Gb H[Gb [[\\b \\[\\b", - "G\\LFL[ MFM[ SLST IFYFYLXF MPSP I[Y[YUX[", - "CbRFR[ SFS[ OFVF GGHHGIFHFGGFHFIGJIKMLONPWPYOZM[I\\G]F^F_G_H^I]H^G NPLQKSJXIZH[ NPMQLSKXJZI[G[FZEX WPYQZS[X\\Z][ WPXQYSZX[Z\\[^[_Z`X O[V[", - "H\\LIKFKLLINGPFTFWGXIXLWNTOQO TFVGWIWLVNTO TOVPXRYTYWXYWZT[O[MZLYKWKVLUMVLW WQXTXWWYVZT[", - "F^KFK[ LFL[ XFX[ YFY[ HFOF UF\\F XHLY H[O[ U[\\[", - "F^KFK[ LFL[ XFX[ YFY[ HFOF UF\\F XHLY H[O[ U[\\[ N@N?M?M@NBPCTCVBW@", - "F^KFK[ LFL[ HFOF LPSPUOVMWIXGYFZF[G[HZIYHZG SPUQVSWXXZY[ SPTQUSVXWZX[Z[[Z\\X H[O[", - "E^MFMLLTKXJZI[H[GZGYHXIYHZ XFX[ YFY[ JF\\F U[\\[", - "F_KFK[ LFRX KFR[ YFR[ YFY[ ZFZ[ HFLF YF]F H[N[ V[][", - "F^KFK[ LFL[ XFX[ YFY[ HFOF UF\\F LPXP H[O[ U[\\[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF QFOGMILKKOKRLVMXOZQ[ S[UZWXXVYRYOXKWIUGSF", - "F^KFK[ LFL[ XFX[ YFY[ HF\\F H[O[ U[\\[", - "G]LFL[ MFM[ IFUFXGYHZJZMYOXPUQMQ UFWGXHYJYMXOWPUQ I[P[", - "G\\XIYLYFXIVGSFQFNGLIKKJNJSKVLXNZQ[S[VZXXYV QFOGMILKKNKSLVMXOZQ[", - "I\\RFR[ SFS[ LFKLKFZFZLYF O[V[", - "H]KFRV LFSV ZFSVQYPZN[M[LZLYMXNYMZ IFOF VF\\F", - "F_RFR[ SFS[ OFVF PILJJLIOIRJULWPXUXYW[U\\R\\O[LYJUIPI PIMJKLJOJRKUMWPX UXXWZU[R[OZLXJUI O[V[", - "H\\KFX[ LFY[ YFK[ IFOF UF[F I[O[ U[[[", - "F^KFK[ LFL[ XFX[ YFY[ HFOF UF\\F H[\\[ [[\\b \\[\\b", - "F]KFKQLSOTRTUSWQ LFLQMSOT WFW[ XFX[ HFOF TF[F T[[[", - "BcGFG[ HFH[ RFR[ SFS[ ]F][ ^F^[ DFKF OFVF ZFaF D[a[", - "BcGFG[ HFH[ RFR[ SFS[ ]F][ ^F^[ DFKF OFVF ZFaF D[a[ `[ab a[ab", - "F`PFP[ QFQ[ IFHLHFTF QPXP[Q\\R]T]W\\Y[ZX[M[ XPZQ[R\\T\\W[YZZX[", - "CaHFH[ IFI[ EFLF IPPPSQTRUTUWTYSZP[E[ PPRQSRTTTWSYRZP[ [F[[ \\F\\[ XF_F X[_[", - "H]MFM[ NFN[ JFQF NPUPXQYRZTZWYYXZU[J[ UPWQXRYTYWXYWZU[", - "H]LIKFKLLINGQFSFVGXIYKZNZSYVXXVZS[P[MZLYKWKVLUMVLW SFUGWIXKYNYSXVWXUZS[ PPYP", - "CbHFH[ IFI[ EFLF E[L[ VFSGQIPKOOORPVQXSZV[X[[Z]X^V_R_O^K]I[GXFVF VFTGRIQKPOPRQVRXTZV[ X[ZZ\\X]V^R^O]K\\IZGXF IPOP", - "G]WFW[ XFX[ [FOFLGKHJJJLKNLOOPWP OFMGLHKJKLLNMOOP RPPQORLYKZJZIY PQOSMZL[J[IYIX T[[[", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "I]NONPMPMONNPMTMVNWOXQXXYZZ[ WOWXXZZ[[[ WQVRPSMTLVLXMZP[S[UZWX PSNTMVMXNZP[", - "H\\XFWGQINKLNKQKULXNZQ[S[VZXXYUYSXPVNSMQMNNLPKS XFWHUIQJNLLN QMONMPLSLUMXOZQ[ S[UZWXXUXSWPUNSM", - "H\\MMM[ NMN[ JMUMXNYPYQXSUT UMWNXPXQWSUT NTUTXUYWYXXZU[J[ UTWUXWXXWZU[", - "HZMMM[ NMN[ JMXMXRWM J[Q[", - "F]NMNQMWLZK[ WMW[ XMX[ KM[M I[H`H[[[[`Z[", - "H[LSXSXQWOVNTMQMNNLPKSKULXNZQ[S[VZXX WSWPVN QMONMPLSLUMXOZQ[", - "E`RMR[ SMS[ OMVM JNIOHNIMJMKNMRNSPTUTWSXRZN[M\\M]N\\O[N PTNUMVKZJ[ PTNVLZK[I[HZGX UTWUXVZZ[[ UTWVYZZ[\\[]Z^X O[V[", - "I[MOLMLQMONNPMTMWNXPXQWSTT TMVNWPWQVSTT QTTTWUXWXXWZT[P[MZLXLWMVNWMX TTVUWWWXVZT[", - "G]LML[ MMM[ WMW[ XMX[ IMPM TM[M I[P[ T[[[ WNMZ", - "G]LML[ MMM[ WMW[ XMX[ IMPM TM[M I[P[ T[[[ WNMZ OGOFNFNGOIQJSJUIVG", - "H\\MMM[ NMN[ JMQM NTPTSSTRVNWMXMYNXOWN PTSUTVVZW[ PTRUSVUZV[X[YZZX J[Q[", - "G]NMNQMWLZK[J[IZJYKZ WMW[ XMX[ KM[M T[[[", - "G^LML[ LMR[ MMRY XMR[ XMX[ YMY[ IMMM XM\\M I[O[ U[\\[", - "G]LML[ MMM[ WMW[ XMX[ IMPM TM[M MTWT I[P[ T[[[", - "H\\QMNNLPKSKULXNZQ[S[VZXXYUYSXPVNSMQM QMONMPLSLUMXOZQ[ S[UZWXXUXSWPUNSM", - "G]LML[ MMM[ WMW[ XMX[ IM[M I[P[ T[[[", - "G\\LMLb MMMb MPONQMSMVNXPYSYUXXVZS[Q[OZMX SMUNWPXSXUWXUZS[ IMMM IbPb", - "H[WPVQWRXQXPVNTMQMNNLPKSKULXNZQ[S[VZXX QMONMPLSLUMXOZQ[", - "I\\RMR[ SMS[ MMLRLMYMYRXM O[V[", - "I[LMR[ MMRY XMR[P_NaLbKbJaK`La JMPM TMZM", - "H]RFRb SFSb OFSF RPQNPMNMLNKQKWLZN[P[QZRX NMMNLQLWMZN[ WMXNYQYWXZW[ SPTNUMWMYNZQZWYZW[U[TZSX ObVb", - "H\\LMW[ MMX[ XML[ JMPM TMZM J[P[ T[Z[", - "G]LML[ MMM[ WMW[ XMX[ IMPM TM[M I[[[[`Z[", - "G]LMLTMVPWRWUVWT MMMTNVPW WMW[ XMX[ IMPM TM[M T[[[", - "CbHMH[ IMI[ RMR[ SMS[ \\M\\[ ]M][ EMLM OMVM YM`M E[`[", - "CbHMH[ IMI[ RMR[ SMS[ \\M\\[ ]M][ EMLM OMVM YM`M E[`[``_[", - "H]QMQ[ RMR[ LMKRKMUM RTVTYUZWZXYZV[N[ VTXUYWYXXZV[", - "E_JMJ[ KMK[ GMNM KTOTRUSWSXRZO[G[ OTQURWRXQZO[ YMY[ ZMZ[ VM]M V[][", - "J[OMO[ PMP[ LMSM PTTTWUXWXXWZT[L[ TTVUWWWXVZT[", - "I\\MOLMLQMONNPMSMVNXPYSYUXXVZS[P[NZLXLWMVNWMX SMUNWPXSXUWXUZS[ RTXT", - "DaIMI[ JMJ[ FMMM F[M[ VMSNQPPSPUQXSZV[X[[Z]X^U^S]P[NXMVM VMTNRPQSQURXTZV[ X[ZZ\\X]U]S\\PZNXM JTPT", - "G\\VMV[ WMW[ ZMOMLNKPKQLSOTVT OMMNLPLQMSOT TTQUPVNZM[ TTRUQVOZN[L[KZJX S[Z[", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "H\\RFKZ QIW[ RIX[ RFY[ MUVU I[O[ T[[[ KZJ[ KZM[ WZU[ WYV[ XYZ[", - "G]LFL[ MGMZ NFN[ IFUFXGYHZJZLYNXOUP XHYJYLXN UFWGXIXMWOUP NPUPXQYRZTZWYYXZU[I[ XRYTYWXY UPWQXSXXWZU[ JFLG KFLH OFNH PFNG LZJ[ LYK[ NYO[ NZP[", - "G\\XIYFYLXIVGTFQFNGLIKKJNJSKVLXNZQ[T[VZXXYV MILKKNKSLVMX QFOGMJLNLSMWOZQ[", - "G]LFL[ MGMZ NFN[ IFSFVGXIYKZNZSYVXXVZS[I[ WIXKYNYSXVWX SFUGWJXNXSWWUZS[ JFLG KFLH OFNH PFNG LZJ[ LYK[ NYO[ NZP[", - "G\\LFL[ MGMZ NFN[ IFYFYL NPTP TLTT I[Y[YU JFLG KFLH OFNH PFNG TFYG VFYH WFYI XFYL TLSPTT TNRPTR TOPPTQ LZJ[ LYK[ NYO[ NZP[ T[YZ V[YY W[YX X[YU", - "G[LFL[ MGMZ NFN[ IFYFYL NPTP TLTT I[Q[ JFLG KFLH OFNH PFNG TFYG VFYH WFYI XFYL TLSPTT TNRPTR TOPPTQ LZJ[ LYK[ NYO[ NZP[", - "G^XIYFYLXIVGTFQFNGLIKKJNJSKVLXNZQ[T[VZXZY[YS MILKKNKSLVMX QFOGMJLNLSMWOZQ[ XTXY WSWYVZ TS\\S USWT VSWU ZSYU [SYT", - "F^KFK[ LGLZ MFM[ WFW[ XGXZ YFY[ HFPF TF\\F MPWP H[P[ T[\\[ IFKG JFKH NFMH OFMG UFWG VFWH ZFYH [FYG KZI[ KYJ[ MYN[ MZO[ WZU[ WYV[ YYZ[ YZ[[", - "LXQFQ[ RGRZ SFS[ NFVF N[V[ OFQG PFQH TFSH UFSG QZO[ QYP[ SYT[ SZU[", - "JZSFSWRZQ[ TGTWSZ UFUWTZQ[O[MZLXLVMUNUOVOWNXMX MVMWNWNVMV PFXF QFSG RFSH VFUH WFUG", - "F\\KFK[ LGLZ MFM[ XGMR PPW[ QPX[ QNY[ HFPF UF[F H[P[ T[[[ IFKG JFKH NFMH OFMG WFXG ZFXG KZI[ KYJ[ MYN[ MZO[ WYU[ WYZ[", - "I[NFN[ OGOZ PFP[ KFSF K[Z[ZU LFNG MFNH QFPH RFPG NZL[ NYM[ PYQ[ PZR[ U[ZZ W[ZY X[ZX Y[ZU", - "E_JFJZ JFQ[ KFQX LFRX XFQ[ XFX[ YGYZ ZFZ[ GFLF XF]F G[M[ U[][ HFJG [FZH \\FZG JZH[ JZL[ XZV[ XYW[ ZY[[ ZZ\\[", - "F^KFKZ KFY[ LFXX MFYX YGY[ HFMF VF\\F H[N[ IFKG WFYG [FYG KZI[ KZM[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF MILKKNKSLVMX WXXVYSYNXKWI QFOGMJLNLSMWOZQ[ S[UZWWXSXNWJUGSF", - "G]LFL[ MGMZ NFN[ IFUFXGYHZJZMYOXPUQNQ XHYJYMXO UFWGXIXNWPUQ I[Q[ JFLG KFLH OFNH PFNG LZJ[ LYK[ NYO[ NZP[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF MILKKNKSLVMX WXXVYSYNXKWI QFOGMJLNLSMWOZQ[ S[UZWWXSXNWJUGSF NXOVQURUTVUXV^W`Y`Z^Z\\ V\\W^X_Y_ UXW]X^Y^Z]", - "G]LFL[ MGMZ NFN[ IFUFXGYHZJZLYNXOUPNP XHYJYLXN UFWGXIXMWOUP RPTQUSWYX[Z[[Y[W WWXYYZZZ TQURXXYYZY[X I[Q[ JFLG KFLH OFNH PFNG LZJ[ LYK[ NYO[ NZP[", - "H\\XIYFYLXIVGSFPFMGKIKLLNOPURWSXUXXWZ LLMNOOUQWRXT MGLILKMMONUPXRYTYWXYWZT[Q[NZLXKUK[LX", - "H\\JFJL QFQ[ RGRZ SFS[ ZFZL JFZF N[V[ KFJL LFJI MFJH OFJG UFZG WFZH XFZI YFZL QZO[ QYP[ SYT[ SZU[", - "F^KFKULXNZQ[S[VZXXYUYG LGLVMX MFMVNYOZQ[ HFPF VF\\F IFKG JFKH NFMH OFMG WFYG [FYG", - "H\\KFR[ LFRXR[ MFSX YGR[ IFPF UF[F JFLH NFMH OFMG WFYG ZFYG", - "F^JFN[ KFNVN[ LFOV RFOVN[ RFV[ SFVVV[ TFWV ZGWVV[ GFOF RFTF WF]F HFKG IFKH MFLH NFLG XFZG \\FZG", - "H\\KFW[ LFX[ MFY[ XGLZ IFPF UF[F I[O[ T[[[ JFMH NFMH OFMG VFXG ZFXG LZJ[ LZN[ WZU[ WYV[ WYZ[", - "G]JFQQQ[ KFRQRZ LFSQS[ YGSQ HFOF VF\\F N[V[ IFKG NFLG WFYG [FYG QZO[ QYP[ SYT[ SZU[", - "H\\YFKFKL WFK[ XFL[ YFM[ K[Y[YU LFKL MFKI NFKH PFKG T[YZ V[YY W[YX X[YU", - "H\\RFKZ QIW[ RIX[ RFY[ MUVU I[O[ T[[[ KZJ[ KZM[ WZU[ WYV[ XYZ[", - "G]LFL[ MGMZ NFN[ IFUFXGYHZJZLYNXOUP XHYJYLXN UFWGXIXMWOUP NPUPXQYRZTZWYYXZU[I[ XRYTYWXY UPWQXSXXWZU[ JFLG KFLH OFNH PFNG LZJ[ LYK[ NYO[ NZP[", - "I[NFN[ OGOZ PFP[ KFZFZL K[S[ LFNG MFNH QFPH RFPG UFZG WFZH XFZI YFZL NYM[ NZL[ PYQ[ PZR[", - "H\\RFJ[ QIX[ RIY[ RFZ[ KYXY KZXZ J[Z[", - "G\\LFL[ MGMZ NFN[ IFYFYL NPTP TLTT I[Y[YU JFLG KFLH OFNH PFNG TFYG VFYH WFYI XFYL TLSPTT TNRPTR TOPPTQ LZJ[ LYK[ NYO[ NZP[ T[YZ V[YY W[YX X[YU", - "H\\YFKFKL WFK[ XFL[ YFM[ K[Y[YU LFKL MFKI NFKH PFKG T[YZ V[YY W[YX X[YU", - "F^KFK[ LGLZ MFM[ WFW[ XGXZ YFY[ HFPF TF\\F MPWP H[P[ T[\\[ IFKG JFKH NFMH OFMG UFWG VFWH ZFYH [FYG KZI[ KYJ[ MYN[ MZO[ WZU[ WYV[ YYZ[ YZ[[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF MILKKNKSLVMX WXXVYSYNXKWI QFOGMJLNLSMWOZQ[ S[UZWWXSXNWJUGSF OMOT UMUT OPUP OQUQ ONPP OOQP UNTP UOSP PQOS QQOR SQUR TQUS", - "LXQFQ[ RGRZ SFS[ NFVF N[V[ OFQG PFQH TFSH UFSG QZO[ QYP[ SYT[ SZU[", - "F\\KFK[ LGLZ MFM[ XGMR PPW[ QPX[ QNY[ HFPF UF[F H[P[ T[[[ IFKG JFKH NFMH OFMG WFXG ZFXG KZI[ KYJ[ MYN[ MZO[ WYU[ WYZ[", - "H\\RFKZ QIW[ RIX[ RFY[ I[O[ T[[[ KZJ[ KZM[ WZU[ WYV[ XYZ[", - "E_JFJZ JFQ[ KFQX LFRX XFQ[ XFX[ YGYZ ZFZ[ GFLF XF]F G[M[ U[][ HFJG [FZH \\FZG JZH[ JZL[ XZV[ XYW[ ZY[[ ZZ\\[", - "F^KFKZ KFY[ LFXX MFYX YGY[ HFMF VF\\F H[N[ IFKG WFYG [FYG KZI[ KZM[", - "G]JEJL ZEZL OMOT UMUT JUJ\\ ZUZ\\ JGZG JHZH JIZI OPUP OQUQ JXZX JYZY JZZZ JFMH ZFWH KIJK LIJJ XIZJ YIZK ONPP OOQP UNTP UOSP PQOS QQOR SQUR TQUS JVKX JWLX ZWXX ZVYX MYJ[ WYZ[", - "G]QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZOYKXIVGSFQF MILKKNKSLVMX WXXVYSYNXKWI QFOGMJLNLSMWOZQ[ S[UZWWXSXNWJUGSF", - "F^KFK[ LGLZ MFM[ WFW[ XGXZ YFY[ HF\\F H[P[ T[\\[ IFKG JFKH NFMH OFMG UFWG VFWH ZFYH [FYG KZI[ KYJ[ MYN[ MZO[ WZU[ WYV[ YYZ[ YZ[[", - "G]LFL[ MGMZ NFN[ IFUFXGYHZJZMYOXPUQNQ XHYJYMXO UFWGXIXNWPUQ I[Q[ JFLG KFLH OFNH PFNG LZJ[ LYK[ NYO[ NZP[", - "G]IFPPQQ JFQP KFRPI[ IFYFZLYIWF VFYH TFYG KYYY JZYZ I[Y[ZUYXWY", - "H\\JFJL QFQ[ RGRZ SFS[ ZFZL JFZF N[V[ KFJL LFJI MFJH OFJG UFZG WFZH XFZI YFZL QZO[ QYP[ SYT[ SZU[", - "H\\JMKILGMFOFPGQIRM LHMGOGPH JMKJMHOHPIQMQ[ RMR[ ZMYJWHUHTISMS[ XHWGUGTH ZMYIXGWFUFTGSIRM N[V[ QYP[ QZO[ SZU[ SYT[", - "G]QFQ[ RGRZ SFS[ NFVF N[V[ OFQG PFQH TFSH UFSG QZO[ QYP[ SYT[ SZU[ OKLLKMJOJRKTLUOVUVXUYTZRZOYMXLUKOK LMKOKRLT XTYRYOXM OKMLLOLRMUOV UVWUXRXOWLUK", - "H\\KFW[ LFX[ MFY[ XGLZ IFPF UF[F I[O[ T[[[ JFMH NFMH OFMG VFXG ZFXG LZJ[ LZN[ WZU[ WYV[ WYZ[", - "F^QFQ[ RGRZ SFS[ NFVF N[V[ OFQG PFQH TFSH UFSG QZO[ QYP[ SYT[ SZU[ HMIMJNKQLSMTPUTUWTXSYQZN[M\\M LRKNJLILKN HMIKJKKLLPMSNTPU YN[LZLYNXR TUVTWSXPYLZK[K\\M", - "G]NYKYJWK[O[MVKRJOJLKIMGPFTFWGYIZLZOYRWVU[Y[ZWYYVY LSKOKLLI XIYLYOXS O[MULPLKMHNGPF TFVGWHXKXPWUU[ KZNZ VZYZ", - "H\\UFIZ SJT[ THUZ UFUHVYV[ LUTU F[L[ Q[X[ IZG[ IZK[ TZR[ TYS[ VYW[", - "F^OFI[ PFJ[ QFK[ LFWFZG[I[KZNYOVP YGZIZKYNXO WFXGYIYKXNVP NPVPXQYSYUXXVZR[F[ WQXSXUWXUZ VPWRWUVXTZR[ MFPG NFOH RFPH SFPG JZG[ JYH[ KYL[ JZM[", - "H]ZH[H\\F[L[JZHYGWFTFQGOIMLLOKSKVLYMZP[S[UZWXXV QHOJNLMOLSLWMY TFRGPJOLNOMSMXNZP[", - "F]OFI[ PFJ[ QFK[ LFUFXGYHZKZOYSWWUYSZO[F[ WGXHYKYOXSVWTY UFWHXKXOWSUWRZO[ MFPG NFOH RFPH SFPG JZG[ JYH[ KYL[ JZM[", - "F]OFI[ PFJ[ QFK[ ULST LF[FZL NPTP F[U[WV MFPG NFOH RFPH SFPG WFZG XFZH YFZI ZFZL ULSPST TNRPSR TOQPSQ JZG[ JYH[ KYL[ JZM[ P[UZ R[UY UYWV", - "F\\OFI[ PFJ[ QFK[ ULST LF[FZL NPTP F[N[ MFPG NFOH RFPH SFPG WFZG XFZH YFZI ZFZL ULSPST TNRPSR TOQPSQ JZG[ JYH[ KYL[ JZM[", - "H^ZH[H\\F[L[JZHYGWFTFQGOIMLLOKSKVLYMZP[R[UZWXYT QHOJNLMOLSLWMY VXWWXT TFRGPJOLNOMSMXNZP[ R[TZVWWT TT\\T UTWU VTWW ZTXV [TXU", - "E_NFH[ OFI[ PFJ[ ZFT[ [FU[ \\FV[ KFSF WF_F LPXP E[M[ Q[Y[ LFOG MFNH QFOH RFOG XF[G YFZH ]F[H ^F[G IZF[ IYG[ JYK[ IZL[ UZR[ UYS[ VYW[ UZX[", - "KYTFN[ UFO[ VFP[ QFYF K[S[ RFUG SFTH WFUH XFUG OZL[ OYM[ PYQ[ OZR[", - "I\\WFRWQYO[ XFTSSVRX YFUSSXQZO[M[KZJXJVKULUMVMWLXKX KVKWLWLVKV TF\\F UFXG VFWH ZFXH [FXG", - "F]OFI[ PFJ[ QFK[ \\GMR QOU[ ROV[ SNWZ LFTF YF_F F[N[ R[Y[ MFPG NFOH RFPH SFPG ZF\\G ^F\\G JZG[ JYH[ KYL[ JZM[ UZS[ UYT[ VYX[", - "H\\QFK[ RFL[ SFM[ NFVF H[W[YU OFRG PFQH TFRH UFRG LZI[ LYJ[ MYN[ LZO[ R[WZ T[XX V[YU", - "D`MFGZ MGNYN[ NFOY OFPX [FPXN[ [FU[ \\FV[ ]FW[ JFOF [F`F D[J[ R[Z[ KFMG LFMH ^F\\H _F\\G GZE[ GZI[ VZS[ VYT[ WYX[ VZY[", - "F_OFIZ OFV[ PFVX QFWX \\GWXV[ LFQF YF_F F[L[ MFPG NFPH ZF\\G ^F\\G IZG[ IZK[", - "G]SFPGNILLKOJSJVKYLZN[Q[TZVXXUYRZNZKYHXGVFSF OIMLLOKSKWLY UXWUXRYNYJXH SFQGOJNLMOLSLXMZN[ Q[SZUWVUWRXNXIWGVF", - "F]OFI[ PFJ[ QFK[ LFXF[G\\I\\K[NYPUQMQ ZG[I[KZNXP XFYGZIZKYNWPUQ F[N[ MFPG NFOH RFPH SFPG JZG[ JYH[ KYL[ JZM[", - "G]SFPGNILLKOJSJVKYLZN[Q[TZVXXUYRZNZKYHXGVFSF OIMLLOKSKWLY UXWUXRYNYJXH SFQGOJNLMOLSLXMZN[ Q[SZUWVUWRXNXIWGVF LXMVOUPURVSXT]U^V^W] T^U_V_ SXS_T`V`W]W\\", - "F^OFI[ PFJ[ QFK[ LFWFZG[I[KZNYOVPNP YGZIZKYNXO WFXGYIYKXNVP RPTQURWXXYYYZX WYXZYZ URVZW[Y[ZXZW F[N[ MFPG NFOH RFPH SFPG JZG[ JYH[ KYL[ JZM[", - "G^ZH[H\\F[L[JZHYGVFRFOGMIMLNNPPVSWUWXVZ NLONVRWT OGNINKOMUPWRXTXWWYVZS[O[LZKYJWJUI[JYKY", - "G]TFN[ UFO[ VFP[ MFKL ]F\\L MF]F K[S[ NFKL PFLI RFMG YF\\G ZF\\H [F\\I \\F\\L OZL[ OYM[ PYQ[ OZR[", - "F_NFKQJUJXKZN[R[UZWXXU\\G OFLQKUKYLZ PFMQLULYN[ KFSF YF_F LFOG MFNH QFOH RFOG ZF\\G ^F\\G", - "H\\NFNHOYO[ OGPX PFQW [GO[ LFSF XF^F MFNH QFPH RFOG YF[G ]F[G", - "E_MFMHKYK[ NGLX OFMW UFMWK[ UFUHSYS[ VGTX WFUW ]GUWS[ JFRF UFWF ZF`F KFNG LFMH PFNI QFNG [F]G _F]G", - "G]NFT[ OFU[ PFV[ [GIZ LFSF XF^F F[L[ Q[X[ MFOH QFPH RFPG YF[G ]F[G IZG[ IZK[ TZR[ TYS[ UYW[", - "G]MFQPN[ NFRPO[ OFSPP[ \\GSP KFRF YF_F K[S[ LFNG PFOH QFNG ZF\\G ^F\\G OZL[ OYM[ PYQ[ OZR[", - "G]ZFH[ [FI[ \\FJ[ \\FNFLL H[V[XU OFLL PFMI RFNG R[VZ T[WX U[XU", - "", - "", - "", - "", - "", - "", - "H\\JFR[ KFRX LFSX JFZFR[ LGYG LHYH", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "I]NPNOOOOQMQMONNPMTMVNWOXQXXYZZ[ VOWQWXXZ TMUNVPVXWZZ[[[ VRUSPTMULWLXMZP[S[UZVX NUMWMXNZ USQTOUNWNXOZP[", - "G\\LFL[MZOZ MGMY IFNFNZ NPONQMSMVNXPYSYUXXVZS[Q[OZNX WPXRXVWX SMUNVOWRWVVYUZS[ JFLG KFLH", - "H[WQWPVPVRXRXPVNTMQMNNLPKSKULXNZQ[S[VZXX MPLRLVMX QMONNOMRMVNYOZQ[", - "H]VFV[[[ WGWZ SFXFX[ VPUNSMQMNNLPKSKULXNZQ[S[UZVX MPLRLVMX QMONNOMRMVNYOZQ[ TFVG UFVH XYY[ XZZ[", - "H[MSXSXQWOVNSMQMNNLPKSKULXNZQ[S[VZXX WRWQVO MPLRLVMX VSVPUNSM QMONNOMRMVNYOZQ[", - "KYWHWGVGVIXIXGWFTFRGQHPKP[ RHQKQZ TFSGRIR[ MMVM M[U[ PZN[ PYO[ RYS[ RZT[", - "I\\XNYOZNYMXMVNUO QMONNOMQMSNUOVQWSWUVVUWSWQVOUNSMQM OONQNSOU UUVSVQUO QMPNOPOTPVQW SWTVUTUPTNSM NUMVLXLYM[N\\Q]U]X^Y_ N[Q\\U\\X] LYMZP[U[X\\Y^Y_XaUbObLaK_K^L\\O[ ObMaL_L^M\\O[", - "G^LFL[ MGMZ IFNFN[ NQOOPNRMUMWNXOYRY[ WOXRXZ UMVNWQW[ I[Q[ T[\\[ JFLG KFLH LZJ[ LYK[ NYO[ NZP[ WZU[ WYV[ YYZ[ YZ[[", - "LXQFQHSHSFQF RFRH QGSG QMQ[ RNRZ NMSMS[ N[V[ OMQN PMQO QZO[ QYP[ SYT[ SZU[", - "KXRFRHTHTFRF SFSH RGTG RMR^QaPb SNS]R` OMTMT]S`RaPbMbLaL_N_NaMaM` PMRN QMRO", - "G]LFL[ MGMZ IFNFN[ WNNW RSY[ RTX[ QTW[ TM[M I[Q[ T[[[ JFLG KFLH UMWN ZMWN LZJ[ LYK[ NYO[ NZP[ WYU[ VYZ[", - "LXQFQ[ RGRZ NFSFS[ N[V[ OFQG PFQH QZO[ QYP[ SYT[ SZU[", - "AcFMF[ GNGZ CMHMH[ HQIOJNLMOMQNROSRS[ QORRRZ OMPNQQQ[ SQTOUNWMZM\\N]O^R^[ \\O]R]Z ZM[N\\Q\\[ C[K[ N[V[ Y[a[ DMFN EMFO FZD[ FYE[ HYI[ HZJ[ QZO[ QYP[ SYT[ SZU[ \\ZZ[ \\Y[[ ^Y_[ ^Z`[", - "G^LML[ MNMZ IMNMN[ NQOOPNRMUMWNXOYRY[ WOXRXZ UMVNWQW[ I[Q[ T[\\[ JMLN KMLO LZJ[ LYK[ NYO[ NZP[ WZU[ WYV[ YYZ[ YZ[[", - "H\\QMNNLPKSKULXNZQ[S[VZXXYUYSXPVNSMQM MPLRLVMX WXXVXRWP QMONNOMRMVNYOZQ[ S[UZVYWVWRVOUNSM", - "G\\LMLb MNMa IMNMNb NPONQMSMVNXPYSYUXXVZS[Q[OZNX WPXRXVWX SMUNVOWRWVVYUZS[ IbQb JMLN KMLO LaJb L`Kb N`Ob NaPb", - "H\\VNVb WOWa UNWNXMXb VPUNSMQMNNLPKSKULXNZQ[S[UZVX MPLRLVMX QMONNOMRMVNYOZQ[ Sb[b VaTb V`Ub X`Yb XaZb", - "IZNMN[ ONOZ KMPMP[ WOWNVNVPXPXNWMUMSNQPPS K[S[ LMNN MMNO NZL[ NYM[ PYQ[ PZR[", - "J[WOXMXQWOVNTMPMNNMOMQNSPTUUWVXY NNMQ NRPSUTWU XVWZ MONQPRUSWTXVXYWZU[Q[OZNYMWM[NY", - "KZPHPVQYRZT[V[XZYX QHQWRY PHRFRWSZT[ MMVM", - "G^LMLVMYNZP[S[UZVYWW MNMWNY IMNMNWOZP[ WMW[\\[ XNXZ TMYMY[ JMLN KMLO YYZ[ YZ[[", - "I[LMR[ MMRY NMSY XNSYR[ JMQM TMZM KMNO PMNN VMXN YMXN", - "F^JMN[ KMNX LMOX RMOXN[ RMV[ SMVX RMTMWX ZNWXV[ GMOM WM]M HMKN NMLN XMZN \\MZN", - "H\\LMV[ MMW[ NMX[ WNMZ JMQM TMZM J[P[ S[Z[ KMMN PMNN UMWN YMWN MZK[ MZO[ VZT[ WZY[", - "H[LMR[ MMRY NMSY XNSYP_NaLbJbIaI_K_KaJaJ` JMQM TMZM KMNO PMNN VMXN YMXN", - "I[VML[ WMM[ XMN[ XMLMLQ L[X[XW MMLQ NMLP OMLO QMLN S[XZ U[XY V[XX W[XW", - "G^[MZQYTWXUZR[P[MZKXJUJSKPMNPMRMUNVOWQYXZZ[[\\[ ZMYQXTWVUYTZR[ LXKVKRLP P[NZMYLVLRMONNPM RMTNUOVQXXYZ[[", - "G\\QFNGMHLJKNKb NHMJLNLa QFOGNIMNMb QFSFVGWHXJXLWNVOSP PPTPWQXRYTYWXYWZT[Q[OZNYMW VHWJWLVN WRXTXWWY SFUGVIVMUOSP TPVQWSWXVZT[ KbMb", - "F\\HRINKMMMONPOQRRYSb IOKNMNOOPP HRIPKOMOOPPQQTRYRa XMWPVRTUSWR[Qb YMWQ ZMYOWRTVSXR[ XMZM QbSb", - "H\\SMQMNNLPKSKULXNZQ[S[VZXXYUYSXPVNSMPLNKMJMHNGPFSFWH MPLSLUMX WXXUXSWP QMONNOMRMVNYOZQ[ S[UZVYWVWRVOUNOKNJNIOHQGTGWH", - "I[SMUNVOWOVNSMQMMNLOLQMRQS SSQSMTKVKXMZP[S[VZXXWXVZ NNMOMQNR MULVLXMY QMONNONQORQS QSNTMVMXNZP[", - "I[QHRGRFQFPGPIQJTKXKYKYJXJUKSLPNNPMRLULWMYNZP[S\\U]V_VaUbSbRaR`S`Sa POOPNRMUMWNYOZ UKRMQNOQNTNWOYQ[S\\", - "G]JMKNLPL[ KMLNMPMZ HPINJMLMMNNPN[ UMVNWQWb WOXRXa NQOOPNRMUMWNXOYRYb L[N[ WbYb", - "F]IMJNKPKTLWMYNZQ[S[VZWYXWYRYOXJVGTFRFPGOIOKPMSOVP[Q JMKNLPLTMWNY VYWWXRXOWJVHTG GPHNIMKMLNMPMTNXOZQ[ S[UZVXWSWNVJUHSGQGOI", - "KZNMONPPPXQZS[U[WZXX OMPNQPQXRZ LPMNNMPMQNRPRXSZT[", - "G]JMKNLPL[ KMLNMPMZ HPINJMLMMNNPN[ SOUNWNXOXPZPZNXMVMTNQQOTNW XNYOYP PSQSWYYYZX TWWZYZ RTUZV[X[YZZX L[N[", - "H\\JGKFMFOGQIXXYZZ[ OHPIWXXY MFNGOIVXXZZ[[[ RMJZJ[K[RM", - "G]KMKb LNLa MMMb VMVXWZX[Z[[Z\\X WNWXXZY[ XMXXYZZ[ MXNZP[R[TZUYVW KMMM VMXM KbMb", - "G]JMKNLPMTN[ KMLNMPNTOZ HPINJMLMMNNPOTPZ VVWTXQXMYMZNYQXSVVTXQZN[ XRYOYM", - "JZPGSFRFPGOHOIPJSKVLWKVJSKPLNMMOMQNRPSSTVUWTVSSTOUMVLXLZM[O\\S]U^V_VaTbRbOaPaRb OMNONQOR NVMXMZN[ VKSKQLPMOOOQQSST VTSTPUOVNXNZP\\S]", - "H\\QMNNLPKSKULXNZQ[S[VZXXYUYSXPVNSMQM MPLRLVMX WXXVXRWP QMONNOMRMVNYOZQ[ S[UZVYWVWRVOUNSM", - "G]IQJOKNMM[M KOMNZN IQJPLO[O OONZM[LZMWOO UOVZW[XZWWUO [M[O OOMZ UOWZ", - "G\\QMNNLPKTKb MPLTLa QMONNOMSMb MWNYOZQ[S[VZXXYUYSXPVNSMQM WXXVXRWP S[UZVYWVWRVOUNSM KbMb", - "G]PMMNKPJSJUKXMZP[R[UZWXXUXSWPUNRM LPKRKVLX VXWVWRVP PMNNMOLRLVMYNZP[ R[TZUYVVVRUOTNRM RMZO[N[MPM RMZN", - "H\\JQKOLNNMZM LONNYN JQKPMOZO ROQZR[SZRO ZMZO RORZ", - "G\\JMKNLPLUMXOZQ[S[UZWXXVYRYNXMWMXPXSWWUZ KMLNMPMUNX WMXNXO HPINJMLMMNNPNVOYQ[", - "G]RQQNPMNMLNKOJRJUKXMZP[T[WZYXZUZRYOXNVMTMSNRQ LOKRKULX XXYUYRXO NMMNLQLVMYNZP[ T[VZWYXVXQWNVM RQQb RQRa RQSb QbSb", - "H\\LMMNNPT_VaXbZb[a NOOPU_V` INJMLMNNPPV_WaXb VSXPYMZMYOVSN\\K`JbKbL_N\\", - "F]HNINJPJUKXMZP[T[VZXXYVZRZNYMXMYPYSXWVZ JNKPKULX XMYNYO GPHNIMJMKNLPLVMYNZP[ QFSb RGRa SFQb QFSF QbSb", - "F^NMLNJPISIWJYKZM[O[QZRYSWSTRSQTQWRYSZU[W[YZZY[W[SZPXNVM KPJSJWKY RTRX YYZWZSYP NMLOKRKWLZM[ W[XZYWYRXOVM", - "G]WMUTUXVZW[Y[[Y\\W XMVTVZ WMYMWTVX UTUQTNRMPMMNKQJTJVKYLZN[P[RZSYTWUT NNLQKTKWLY PMNOMQLTLWMZN[", - "I\\PFNMMSMWNYOZQ[S[VZXWYTYRXOWNUMSMQNPOOQNT QFOMNQNWOZ VYWWXTXQWO MFRFPMNT S[UYVWWTWQVNUM NFQG OFPH", - "I[WQWPVPVRXRXPWNUMRMONMQLTLVMYNZP[R[UZWW OONQMTMWNY RMPOOQNTNWOZP[", - "G]YFVQUUUXVZW[Y[[Y\\W ZFWQVUVZ VF[FWTVX UTUQTNRMPMMNKQJTJVKYLZN[P[RZSYTWUT MOLQKTKWLY PMNOMQLTLWMZN[ WFZG XFYH", - "I[MVQUTTWRXPWNUMRMONMQLTLVMYNZP[R[UZWX OONQMTMWNY RMPOOQNTNWOZP[", - "JZZHZGYGYI[I[GZFXFVGTISKRNQRO[N^M`Kb TJSMRRP[O^ XFVHUJTMSRQZP]O_MaKbIbHaH_J_JaIaI` NMYM", - "H]XMT[S^QaOb YMU[S_ XMZMV[T_RaObLbJaI`I^K^K`J`J_ VTVQUNSMQMNNLQKTKVLYMZO[Q[SZTYUWVT NOMQLTLWMY QMOONQMTMWNZO[", - "G]OFI[K[ PFJ[ LFQFK[ MTOPQNSMUMWNXPXSVX WNWRVVVZ WPUUUXVZW[Y[[Y\\W MFPG NFOH", - "KXTFTHVHVFTF UFUH TGVG LQMOOMQMRNSPSSQX RNRRQVQZ RPPUPXQZR[T[VYWW", - "KXUFUHWHWFUF VFVH UGWG MQNOPMRMSNTPTSRZQ]P_NaLbJbIaI_K_KaJaJ` SNSSQZP]O_ SPRTP[O^N`Lb", - "G]OFI[K[ PFJ[ LFQFK[ YOYNXNXPZPZNYMWMUNQROS MSOSQTRUTYUZWZ QUSYTZ OSPTRZS[U[WZYW MFPG NFOH", - "LXTFQQPUPXQZR[T[VYWW UFRQQUQZ QFVFRTQX RFUG SFTH", - "@cAQBODMFMGNHPHSF[ GNGSE[ GPFTD[F[ HSJPLNNMPMRNSPSSQ[ RNRSP[ RPQTO[Q[ SSUPWNYM[M]N^P^S\\X ]N]R\\V\\Z ]P[U[X\\Z][_[aYbW", - "F^GQHOJMLMMNNPNSL[ MNMSK[ MPLTJ[L[ NSPPRNTMVMXNYPYSWX XNXRWVWZ XPVUVXWZX[Z[\\Y]W", - "H\\QMNNLQKTKVLYMZP[S[VZXWYTYRXOWNTMQM NOMQLTLWMY VYWWXTXQWO QMOONQMTMWNZP[ S[UYVWWTWQVNTM", - "G]HQIOKMMMNNOPOSNWKb NNNSMWJb NPMTIb OTPQQORNTMVMXNYOZRZTYWWZT[R[PZOWOT XOYQYTXWWY VMWNXQXTWWVYT[ FbNb JaGb J`Hb K`Lb JaMb", - "G\\WMQb XMRb WMYMSb UTUQTNRMPMMNKQJTJVKYLZN[P[RZSYTWUT MOLQKTKWLY PMNOMQLTLWMZN[ NbVb RaOb R`Pb S`Tb RaUb", - "I[JQKOMMOMPNQPQTO[ PNPTN[ PPOTM[O[ YOYNXNXPZPZNYMWMUNSPQT", - "J[XPXOWOWQYQYOXNUMRMONNONQOSQTTUVVWX ONNQ ORQSTTVU WVVZ NOOQQRTSVTWVWXVZS[P[MZLYLWNWNYMYMX", - "KYTFQQPUPXQZR[T[VYWW UFRQQUQZ TFVFRTQX NMXM", - "F^GQHOJMLMMNNPNSLX MNMRLVLZ MPKUKXLZN[P[RZTXVU XMVUVXWZX[Z[\\Y]W YMWUWZ XMZMXTWX", - "H\\IQJOLMNMONPPPSNX ONORNVNZ OPMUMXNZP[R[TZVXXUYQYMXMXNYP", - "CaDQEOGMIMJNKPKSIX JNJRIVIZ JPHUHXIZK[M[OZQXRU TMRURXSZU[W[YZ[X]U^Q^M]M]N^P UMSUSZ TMVMTTSX", - "G]JQLNNMPMRNSPSR PMQNQRPVOXMZK[I[HZHXJXJZIZIY RORRQVQY ZOZNYNYP[P[NZMXMVNTPSRRVRZS[ PVPXQZS[U[WZYW", - "G]HQIOKMMMNNOPOSMX NNNRMVMZ NPLULXMZO[Q[SZUXWT YMU[T^RaPb ZMV[T_ YM[MW[U_SaPbMbKaJ`J^L^L`K`K_", - "H\\YMXOVQNWLYK[ XOOOMPLR VORNONNO VORMOMMOLR LYUYWXXV NYRZUZVY NYR[U[WYXV", - "", - "", - "", - "", - "", - "", - "H\\WQVOUNSMQMNNLPKSKULXNZQ[S[VZWYXWYSYNXJWHVGSFQFNGMHNHOGQF MPLRLVMX VYWWXSXNWJVH QMONNOMRMVNYOZQ[ S[UZVXWTWMVIUGSF", - "I[UMWNXOYOXNUMRMONMPLSLUMXOZR[U[XZYYXYWZU[ NPMSMUNX RMPNOONRNVOYPZR[ NTTUUTTSNT NTTT", - "H\\QFNGLJKOKRLWNZQ[S[VZXWYRYOXJVGSFQF NHMJLNLSMWNY VYWWXSXNWJVH QFOGNIMNMSNXOZQ[ S[UZVXWSWNVIUGSF LPXQ LQXP", - "G]PMMNKPJSJUKXMZP[T[WZYXZUZSYPWNTMPM LPKSKULX XXYUYSXP PMNNMOLRLVMYNZP[T[VZWYXVXRWOVNTM QFSb RGRa SFQb QFSF QbSb", - "H\\TMVNXPYPYOWNTMPMMNLOKQKSLUNWPXRYSZT\\T^S_Q_O^P^Q_ MOLQLSMUOW PMNNMPMSNURY YPXO", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NV", - "JZ", - "H\\QFNGLJKOKRLWNZQ[S[VZXWYRYOXJVGSFQF NHMJLNLSMWNY VYWWXSXNWJVH QFOGNIMNMSNXOZQ[ S[UZVXWSWNVIUGSF", - "H\\QHQ[ RHRZ SFS[ SFPINJ M[W[ QZO[ QYP[ SYT[ SZU[", - "H\\LJLKMKMJLJ LIMINJNKMLLLKKKJLHMGPFTFWGXHYJYLXNUPPRNSLUKXK[ WHXJXLWN TFVGWJWLVNTPPR KYLXNXSYWYYX NXSZWZXY NXS[W[XZYXYV", - "H\\LJLKMKMJLJ LIMINJNKMLLLKKKJLHMGPFTFWGXIXLWNTO VGWIWLVN SFUGVIVLUNSO QOTOVPXRYTYWXYWZT[P[MZLYKWKVLUMUNVNWMXLX WRXTXWWY SOUPVQWTWWVZT[ LVLWMWMVLV", - "H\\SIS[ THTZ UFU[ UFJUZU P[X[ SZQ[ SYR[ UYV[ UZW[", - "H\\MFKPMNPMSMVNXPYSYUXXVZS[P[MZLYKWKVLUMUNVNWMXLX WPXRXVWX SMUNVOWRWVVYUZS[ LVLWMWMVLV MFWF MGUG MHQHUGWF", - "H\\VIVJWJWIVI WHVHUIUJVKWKXJXIWGUFRFOGMILKKOKULXNZQ[S[VZXXYUYTXQVOSNQNOONPMR NIMKLOLUMXNY WXXVXSWQ RFPGOHNJMNMUNXOZQ[ S[UZVYWVWSVPUOSN", - "H\\KFKL YFYIXLTQSSRWR[ SRRTQWQ[ XLSQQTPWP[R[ KJLHNFPFUIWIXHYF MHNGPGRH KJLINHPHUI", - "H\\PFMGLILLMNPOTOWNXLXIWGTFPF NGMIMLNN VNWLWIVG PFOGNINLONPO TOUNVLVIUGTF POMPLQKSKWLYMZP[T[WZXYYWYSXQWPTO MQLSLWMY WYXWXSWQ PONPMSMWNZP[ T[VZWWWSVPTO", - "H\\MWMXNXNWMW WOVQURSSQSNRLPKMKLLINGQFSFVGXIYLYRXVWXUZR[O[MZLXLWMVNVOWOXNYMY MPLNLKMI VHWIXLXRWVVX QSORNQMNMKNHOGQF SFUGVIWLWSVWUYTZR[", - "MXRXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "MXTZS[R[QZQYRXSXTYT\\S^Q_ RYRZSZSYRY S[T\\ TZS^", - "MXRMQNQORPSPTOTNSMRM RNROSOSNRN RXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "MXRMQNQORPSPTOTNSMRM RNROSOSNRN TZS[R[QZQYRXSXTYT\\S^Q_ RYRZSZSYRY S[T\\ TZS^", - "MXRFQGQIRQ RFRTST RFSFST SFTGTISQ RXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "I\\MKMJNJNLLLLJMHNGPFTFWGXHYJYLXNWOSQ WHXIXMWN TFVGWIWMVOUP RQRTSTSQRQ RXQYQZR[S[TZTYSXRX RYRZSZSYRY", - "MXTFRGQIQLRMSMTLTKSJRJQK RKRLSLSKRK RGQK QIRJ", - "MXTHSIRIQHQGRFSFTGTJSLQM RGRHSHSGRG SITJ THSL", - "E_[O[NZNZP\\P\\N[MZMYNXPVUTXRZP[L[JZIXIUJSPORMSKSIRGPFNGMIMLNOPRTWWZY[[[\\Y\\X KZJXJUKSLR RMSI SKRG NGMK NNPQTVWYYZ N[LZKXKULSPO MINMQQUVXYZZ[Z\\Y", - "H\\PBP_ TBT_ XKXJWJWLYLYJXHWGTFPFMGKIKLLNOPURWSXUXXWZ LLMNOOUQWRXT MGLILKMMONUPXRYTYWXYWZT[P[MZLYKWKUMUMWLWLV", - "G^[BIbJb [B\\BJb", - "KYUBSDQGOKNPNTOYQ]S`Ub QHPKOOOUPYQ\\ SDRFQIPOPUQ[R^S`", - "KYOBQDSGUKVPVTUYS]Q`Ob SHTKUOUUTYS\\ QDRFSITOTUS[R^Q`", - "JZRFQGSQRR RFRR RFSGQQRR MINIVOWO MIWO MIMJWNWO WIVINOMO WIMO WIWJMNMO", - "F_JQ[Q[R JQJR[R", - "F_RIRZSZ RISISZ JQ[Q[R JQJR[R", - "F_JM[M[N JMJN[N JU[U[V JUJV[V", - "NWSFRGRM SGRM SFTGRM", - "I[NFMGMM NGMM NFOGMM WFVGVM WGVM WFXGVM", - "KYQFOGNINKOMQNSNUMVKVIUGSFQF QFNIOMSNVKUGQF SFOGNKQNUMVISF", - "F^ZIJRZ[ ZIZJLRZZZ[", - "F^JIZRJ[ JIJJXRJZJ[", - "G^OFObPb OFPFPb UFUbVb UFVFVb JP[P[Q JPJQ[Q JW[W[X JWJX[X", - "F^[FYGVHSHPGNFLFJGIIIKKMMMOLPJPHNF [FH[ [FI[ [FJ[ YTWTUUTWTYV[X[ZZ[X[VYT OGLFIIJLMMPJOG NFJGIK KMOLPH ZUWTTWUZX[[XZU YTUUTY V[ZZ[V H[J[", - "E`VNULSKQKOLNMMOMRNTOUQVSVUUVS OMNONROT QKPLOOORPUQV VKVSWUYVZV\\U]R]O\\L[JYHWGTFQFNGLHJJILHOHRIUJWLYNZQ[T[WZYYXYWZ WLWSXU VKXKXSYUZV", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NV", - "JZ", - "H]TFQGOIMLLOKSKVLYMZO[Q[TZVXXUYRZNZKYHXGVFTF QHOJNLMOLSLWMY TYVWWUXRYNYJXH TFRGPJOLNOMSMXNZO[ Q[SZUWVUWRXNXIWGVF", - "H]TJO[Q[ WFUJP[ WFQ[ WFTIQKOL TJRKOL", - "H]OKOJPJPLNLNJOHPGSFVFYGZIZKYMWOMUKWI[ XGYIYKXMVOSQ VFWGXIXKWMUOMU JYKXMXRYWYXX MXRZWZ MXR[U[WZXXXW", - "H]OKOJPJPLNLNJOHPGSFVFYGZIZKYMXNVOSP XGYIYKXMWN VFWGXIXKWMUOSP QPSPVQWRXTXWWYUZR[O[LZKYJWJULULWKWKV VRWTWWVY SPUQVSVWUYTZR[", - "H]WJR[T[ ZFXJS[ ZFT[ ZFJUZU", - "H]QFLP QF[F QGYG PHUHYG[F LPMOPNSNVOWPXRXUWXUZQ[N[LZKYJWJULULWKWKV VPWRWUVXTZ SNUOVQVUUXSZQ[", - "H]YJYIXIXKZKZIYGWFTFQGOIMLLOKSKVLYMZO[R[UZWXXVXSWQVPTOQOOPNQMS PINLMOLSLWMY VXWVWSVQ TFRGPJOLNOMSMXNZO[ R[TZUYVVVRUPTO", - "H]NFLL [FZIXLTQRTQWP[ RSPWO[ XLRRPUOWN[P[ MIPFRFWI OGRGWI MIOHRHWIYIZH[F", - "H]SFPGOHNJNMOOQPTPWOYNZLZIYGWFSF UFPG PHOJONPO OORP SPWO XNYLYIXG YGUF SFQHPJPNQP TPVOWNXLXHWF QPMQKSJUJXKZN[R[VZWYXWXTWRVQTP RPMQ NQLSKUKXLZ KZP[VZ VYWWWTVR VQSP QPOQMSLULXMZN[ R[TZUYVWVSUQTP", - "H]XNWPVQTRQROQNPMNMKNIPGSFVFXGYHZKZNYRXUVXTZQ[N[LZKXKVMVMXLXLW OPNNNKOI XHYJYNXRWUUX QRPQOOOKPHQGSF VFWGXIXNWRVUUWSZQ[", - "MXPXOYOZP[Q[RZRYQXPX PYPZQZQYPY", - "MXQ[P[OZOYPXQXRYR[Q]P^N_ PYPZQZQYPY Q[Q\\P^", - "MXSMRNROSPTPUOUNTMSM SNSOTOTNSN PXOYOZP[Q[RZRYQXPX PYPZQZQYPY", - "MXSMRNROSPTPUOUNTMSM SNSOTOTNSN Q[P[OZOYPXQXRYR[Q]P^N_ PYPZQZQYPY Q[Q\\P^", - "MXVFUFTGRT VGUGRT VGVHRT VFWGWHRT PXOYOZP[Q[RZRYQXPX PYPZQZQYPY", - "H]OKOJPJPLNLNJOHPGSFWFZG[I[KZMYNWOSPQQQSSTTT UFZG YGZIZKYMXNVO WFXGYIYKXMWNSPRQRSST PXOYOZP[Q[RZRYQXPX PYPZQZQYPY", - "MXWFUGTHSJSLTMUMVLVKUJTJ UGTITJ TKTLULUKTK", - "MXVIUITHTGUFVFWGWIVKULSM UGUHVHVGUG VIVJUL", - "E_\\O\\N[N[P]P]N\\M[MYNWPRXPZN[K[HZGXGVHTISKRPPROTMUKUITGRFPGOIOLPRQURWTZV[X[YYYX L[HZ IZHXHVITJSLR PPQSTYVZ K[JZIXIVJTKSMRRO OLPOQRSVUYWZXZYY", - "H]TBL_ YBQ_ ZKZJYJYL[L[JZHYGVFRFOGMIMLNNPPVSWUWXVZ NLONVRWT OGNINKOMUPWRXTXWWYVZS[O[LZKYJWJULULWKWKV", - "G^_BEbFb _B`BFb", - "JZZBXCUERHPKNOMSMXN\\O_Qb SHQKOONTN\\ ZBWDTGRJQLPOOSN\\ NTO]P`Qb", - "JZSBUEVHWLWQVUTYR\\O_LaJb VHVPUUSYQ\\ SBTDUGVP VHUQTUSXRZP]M`Jb", - "J[TFSGUQTR TFTR TFUGSQTR OIPIXOYO OIYO OIOJYNYO YIXIPOOO YIOO YIYJONOO", - "F_JQ[Q[R JQJR[R", - "F_RIRZSZ RISISZ JQ[Q[R JQJR[R", - "F_JM[M[N JMJN[N JU[U[V JUJV[V", - "MWUFTGRM UGRM UFVGRM", - "H\\PFOGMM PGMM PFQGMM ZFYGWM ZGWM ZF[GWM", - "KZSFQGPIPKQMSNUNWMXKXIWGUFSF SFPIQMUNXKWGSF UFQGPKSNWMXIUF", - "F^ZIJRZ[ ZIZJLRZZZ[", - "F^JIZRJ[ JIJJXRJZJ[", - "G^SFKbLb SFTFLb YFQbRb YFZFRb KP\\P\\Q KPKQ\\Q IWZWZX IWIXZX", - "E^^F\\GXHUHQGOFMFKGJIJKLMNMPLQJQHOF ^FE[ ^FF[ ^FG[ XTVTTUSWSYU[W[YZZXZVXT PGMFJIKLNMQJPG OFKGJK LMPLQH YUVTSWTZW[ZXYU XTTUSY U[YZZV E[G[", - "E`UQUNTLRKPKNLMMLPLSMUOVQVSUTTUQ OLNMMPMSNU RKPLOMNPNSOUPV VKUQUSVUXVZV\\U]R]O\\L[JYHWGTFQFNGLHJJILHOHRIUJWLYNZQ[T[WZYYXYWZ WKVQVSWU VKXKWQWSXUZV", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - 0 }; - -} - -/* End of file. */ diff --git a/modules/imgproc/src/stb_truetype.cpp b/modules/imgproc/src/stb_truetype.cpp new file mode 100644 index 0000000000..d33962005d --- /dev/null +++ b/modules/imgproc/src/stb_truetype.cpp @@ -0,0 +1,4864 @@ +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ + +// stb_truetype.cpp - v1.24 - public domain +// authored from 2009-2020 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) +// +// VERSION HISTORY +// +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to +#include + +#define STB_TRUETYPE_IMPLEMENTATION +//#define STBTT_RASTERIZER_VERSION 1 + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif + + #undef STBTT_min + #undef STBTT_max + #define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) + #define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 size, stbtt_uint32 fontstart, const char *tag) +{ + if(!data || fontstart + 12 >= size) + return 0; + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + if(fontstart + 12 + num_tables*16 >= size) + return 0; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) { + stbtt_uint32 ofs = ttULONG(data+loc+8); + return ofs < size? ofs : 0; + } + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +///////////////////////// variable font support //////////////////////// + +static int stbtt__SetVarfontInstance(stbtt_fontinfo* info, const int* values) +{ + int i, acount = 0; + const stbtt_uint8* pairs[STBTT_MAX_AXES] = {0}; + int pcounts[STBTT_MAX_AXES] = {0}; + + if (info->avar && (unsigned)(info->avar + 8) < info->size) { + int off = info->avar; + const stbtt_uint8* data = info->data; + int ver = ttLONG(data + off); + acount = ttLONG(data + off + 4); + + if (ver == 0x10000 && acount <= info->axis_count) { + off += 8; + for(i = 0; i < acount; i++) { + stbtt_uint16 pcount = ttUSHORT(data + off); + if (pcount == 0 || (unsigned)(off + 2 + pcount*4) > info->size) { + acount = 0; + break; + } + pairs[i] = data + off + 2; + pcounts[i] = pcount; + off += 2 + pcount*4; + } + } + } + + memset(info->axes_normvalues, 0, sizeof(info->axes_normvalues)); + for (i = 0; i < info->axis_count; i++) { + const stbtt_axisinfo* axis = &info->axes[i]; + int x = values[i]; + x = x < axis->minval ? axis->minval : x > axis->maxval ? axis->maxval : x; + // compute default normalized value within [-1, 1] + int num, denom = 1, s = 1; + if (x < axis->defval) { + num = axis->defval - x; + denom = axis->defval - axis->minval; + s = -1; + } else if (x > axis->defval) { + num = x - axis->defval; + denom = axis->maxval - axis->defval; + } else { + num = 0; + } + const int ONE = 1 << 14; + int norm_x = s*(int)(((long long)num*ONE + denom/2)/denom); + int left = axis->minval < axis->defval ? -ONE : 0; + int right = axis->maxval > axis->defval ? ONE : 0; + norm_x = norm_x < left ? left : norm_x > right ? right : norm_x; + // now if we have a custom curve, apply it + if (pairs[i]) { + const stbtt_uint8* p = pairs[i]; + int j, n = pcounts[i]; + int prev_x = ttSHORT(p), prev_fx = ttSHORT(p + 2); + for (j = 1; j < n; j++) { + int xj = ttSHORT(p + j*4), fx = ttSHORT(p + j*4 + 2); + if (xj <= prev_x || fx < prev_fx) + return 0; + if (norm_x >= prev_x && norm_x < xj) { + denom = xj - prev_x; + norm_x = prev_fx + ((fx - prev_fx)*(norm_x - prev_x) + denom/2)/denom; + break; + } + prev_x = xj; prev_fx = fx; + } + if (j == n) { + if (norm_x != prev_x) + return 0; + norm_x = prev_fx; + } + norm_x = norm_x < left ? left : norm_x > right ? right : norm_x; + } + info->axes_normvalues[i] = (short)norm_x; + } + return 1; +} + +static int stbtt__read_fvar(stbtt_fontinfo *info) +{ + stbtt_uint8* data = info->data + info->fvar; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + int off = ttUSHORT(data+4); + int i, axis_count = ttUSHORT(data+8); + int axis_size = ttUSHORT(data+10); + + if(axis_count == 0) + return 1; + + if(axis_count > STBTT_MAX_AXES || axis_size != 20 || + (unsigned)(info->fvar + off + axis_count*axis_size) > info->size) + return 0; + + for(i = 0; i < axis_count; i++) { + const stbtt_uint8* axis_data = info->data + info->fvar + off + i*axis_size; + stbtt_axisinfo* axis = &info->axes[i]; + axis->tag = ttULONG(axis_data); + axis->minval = ttLONG(axis_data + 4); + axis->defval = axis->currval = ttLONG(axis_data + 8); + axis->maxval = ttLONG(axis_data + 12); + if(axis->minval > axis->defval || axis->defval > axis->maxval) + return 0; + } + info->axis_count = axis_count; + return 1; +} + +static int stbtt__read_gvar(stbtt_fontinfo *info) +{ + stbtt_uint8* data = info->data + info->gvar; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + int axis_count = ttUSHORT(data+4); + if (axis_count != info->axis_count) + return 0; + + int shared_count = ttUSHORT(data+6); + unsigned shared_off = ttULONG(data+8); + if(shared_count > 0 && info->gvar + shared_off + shared_count*axis_count*2 > info->size) + return 0; + int glyphcount = ttUSHORT(data+12); + int off_format = ttUSHORT(data+14); + unsigned glob_off = ttULONG(data+16); + + if(off_format > 1 || (unsigned)(info->gvar + 20 + (glyphcount+1)*(off_format == 0 ? 2 : 4)) > info->size) + return 0; + + info->gvar_shared_count = shared_count; + info->gvar_shared_tuples = (int)(info->gvar + shared_off); + info->gvar_glob_offset = info->gvar + glob_off; + info->gvar_glyph_offsets = info->gvar + 20; + info->gvar_off_format = off_format; + return 1; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, stbtt_uint32 size, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + memset(info, 0, sizeof(*info)); + + info->data = data; + info->size = size; + info->dataend = info->data + info->size; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, size, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, size, fontstart, "loca"); // required + info->head = stbtt__find_table(data, size, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, size, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, size, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, size, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, size, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, size, fontstart, "GPOS"); // not required + info->avar = stbtt__find_table(data, size, fontstart, "avar"); // optional for variable fonts + info->fvar = stbtt__find_table(data, size, fontstart, "fvar"); // required for variable fonts + info->gvar = stbtt__find_table(data, size, fontstart, "gvar"); // required for variable fonts + info->hvar = stbtt__find_table(data, size, fontstart, "HVAR"); // required for variable fonts + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, size, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, size-cff); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, size, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + + if (info->fvar || info->gvar || info->hvar) { + if(!info->fvar || !info->gvar || !info->hvar || !stbtt__read_fvar(info) || + !stbtt__read_gvar(info) || !stbtt_SetInstance(info, 0, 0, 1)) { + info->fvar = info->gvar = 0; + return 0; + } + } + + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + if (unicode_codepoint < start) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, + stbtt_vertex **vertices, int* ix0, int* ix1, int* iy0, int* iy1) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices, ix0, iy0, ix1, iy1); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF void stbtt__ScaleGlyphBox(int ix0, int iy0, int ix1, int iy1, + float scale_x, float scale_y, float shift_x, float shift_y, + int *out_ix0, int *out_iy0, int *out_ix1, int *out_iy1) +{ + if (out_ix0) *out_ix0 = STBTT_ifloor( ix0 * scale_x + shift_x); + if (out_iy0) *out_iy0 = STBTT_ifloor(-iy1 * scale_y + shift_y); + if (out_ix1) *out_ix1 = STBTT_iceil ( ix1 * scale_x + shift_x); + if (out_iy1) *out_iy1 = STBTT_iceil (-iy0 * scale_y + shift_y); +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetVarTupleScale(const stbtt_fontinfo *info, const stbtt_uint8* peaktuple, + const stbtt_uint8* mintuple, const stbtt_uint8* maxtuple) +{ + int i, axis_count = info->axis_count; + int scale = 1 << 16; + const short* currtuple = info->axes_normvalues; + for (i = 0; i < axis_count; i++) { + int x = currtuple[i], peak = ttSHORT(peaktuple + i*2); + if (x == peak || peak == 0) + continue; + if (x == 0) { + scale = 0; + break; + } + if (!mintuple) { + if ((0 < x && x <= peak) || (peak <= x && x < 0)) { + scale = (int)(((long long)scale*x)/peak); + } else { + scale = 0; + break; + } + } else { + int minv = ttSHORT(mintuple+i*2), maxv = ttSHORT(maxtuple+i*2); + if (minv <= x && x <= maxv) { + int num, denom; + if (x < peak) { + num = x - minv; + denom = peak - minv; + } else { + num = maxv - x; + denom = maxv - peak; + } + scale = (int)(((long long)scale*num)/denom); + } else { + scale = 0; + break; + } + } + } + return scale; +} + +static int stbtt__ReadPointNumbers(const stbtt_fontinfo *info, int ofs, int* npoints, stbtt_uint16* ptnum) +{ + const stbtt_uint8* data = info->data; + int i, k, n = ttBYTE(data + ofs); ofs++; + if (n & 0x80) { + n = (n & 0x7f)*256 + ttBYTE(data + ofs); + ofs++; + } + if (npoints) *npoints = n; + if (n == 0) + return ofs; + int idx = 0; + for (i = 0; i < n; ) { + if ((unsigned)ofs >= info->size) + return 0; + int ctl = ttBYTE(data + ofs); ofs++; + int runlen = (ctl & 0x7f) + 1; + int words = (ctl & 0x80) != 0; + if (i + runlen > n) + return 0; + if (ptnum) { + for (k = 0; k < runlen; k++) { + int delta = words ? (int)ttUSHORT(data + ofs + k*2) : (int)ttBYTE(data + ofs + k); + idx += delta; + *ptnum++ = (stbtt_uint16)idx; + } + } + ofs += runlen*(words ? 2 : 1); + i += runlen; + } + return ofs; +} + +static int stbtt__VaryGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, + int isComposite, int numberOfContoursOrComponents, int endPtsOfContours, + stbtt_vertex *vertices, int out_vtxcount, int* ix0, int* iy0, int *ix1, int* iy1) +{ + int ok = 0; + int g1, g2; + + if (info->gvar == 0 || info->gvar_glyph_offsets == 0) + return 1; + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + + if (info->gvar_off_format == 0) { + g1 = ttUSHORT(info->data + info->gvar_glyph_offsets + glyph_index*2) * 2; + g2 = ttUSHORT(info->data + info->gvar_glyph_offsets + glyph_index*2 + 2) * 2; + } else { + g1 = ttULONG(info->data + info->gvar_glyph_offsets + glyph_index*4); + g2 = ttULONG(info->data + info->gvar_glyph_offsets + glyph_index*4 + 4); + } + + int sz = g2 - g1; + int off = info->gvar_glob_offset + g1; + + if (sz <= 0 || (unsigned)(off + sz) > info->size) + return 0; + + int i, tidx, ntuples = ttUSHORT(info->data + off); + int gvar_data = ttUSHORT(info->data + off + 2) + off; + if ((unsigned)gvar_data >= info->size) return -1; + int gvar_tup = off + 4; + + if(ntuples == 0) + return 1; + + const stbtt_uint8* data = info->data; + int axis_count = info->axis_count; + int have_shared_ptnum = (ntuples & 0x8000) != 0; + ntuples &= 0xfff; + int shared_ptnum_count = 0; + + int vtxcount = isComposite ? numberOfContoursOrComponents : out_vtxcount; + int max_ptcount = vtxcount + 4; + int* varbuf = (int*)STBTT_malloc(max_ptcount*(2*sizeof(int)+6*sizeof(short)), info->userdata); + if (!varbuf) + return 0; + + int* sum_deltas = varbuf; + stbtt_uint16* private_ptnum = (stbtt_uint16*)(sum_deltas + max_ptcount*2); + stbtt_uint16* shared_ptnum = private_ptnum + max_ptcount; + stbtt_int16* deltas = (stbtt_int16*)(shared_ptnum + max_ptcount); + stbtt_int16* packed_deltas = (stbtt_int16*)(deltas + max_ptcount*2); + short NO_DELTA = isComposite ? (short)0 : (short)-32768; + + for (i = 0; i < max_ptcount*2; i++) + sum_deltas[i] = 0; + + if (have_shared_ptnum) { + gvar_data = stbtt__ReadPointNumbers(info, gvar_data, &shared_ptnum_count, shared_ptnum); + if (gvar_data == 0) + goto err; + } + + for (tidx = 0; tidx < ntuples; tidx++) { + int tupsz = ttUSHORT(data + gvar_tup); + int tupidx = ttUSHORT(data + gvar_tup+2); + if ((unsigned)(gvar_data + tupsz) > info->size) return 0; + const stbtt_uint8 *peaktup = 0, *mintup = 0, *maxtup = 0; + gvar_tup += 4; + + if (tupidx & 0x8000) { + peaktup = data + gvar_tup; + gvar_tup += axis_count*2; + } else { + int shared_idx = tupidx & 0x0fff; + if (shared_idx >= info->gvar_shared_count) + goto err; + peaktup = data + info->gvar_shared_tuples + shared_idx*axis_count*2; + } + if (tupidx & 0x4000) { + mintup = data + gvar_tup; + maxtup = mintup + axis_count*2; + gvar_tup += axis_count*4; + } + + int scale = stbtt__GetVarTupleScale(info, peaktup, mintup, maxtup); + if(scale == 0) // skip this tuple, because it does not have effect + // for this particular variable font instance. + // all the offsets to the next tuple header/data + // should already be properly incremented + { + gvar_data += tupsz; + continue; + } + + int use_private_ptnum = (tupidx & 0x2000) != 0; + stbtt_uint16* ptnum = shared_ptnum; + int ptnum_count = shared_ptnum_count; + + if (use_private_ptnum) { + gvar_data = stbtt__ReadPointNumbers(info, gvar_data, &ptnum_count, private_ptnum); + if (gvar_data == 0) + goto err; + ptnum = private_ptnum; + } + int k, k1, delta_count = ptnum_count > 0 ? ptnum_count : max_ptcount; + for (i = 0; i < 2*delta_count; ) { + if ((unsigned)gvar_data >= info->size) goto err; + int c = ttBYTE(data + gvar_data); gvar_data++; + int zeros = (c & 0x80) != 0; + int words = (c & 0x40) != 0; + int runlen = (c & 0x3F) + 1; + if (i + runlen > 2*delta_count) + goto err; + for (k = 0; k < runlen; k++) { + int delta = zeros ? 0 : words ? + (int)ttSHORT(data + gvar_data + k*2) : + (int)ttCHAR(data + gvar_data + k); + packed_deltas[i+k] = (short)delta; + } + gvar_data += (zeros ? 0 : words ? 2 : 1)*runlen; + i += runlen; + } + + for (i = 0; i < vtxcount*2; i++) + deltas[i] = NO_DELTA; + for (i = 0; i < 4; i++) + deltas[(vtxcount + i)*2] = deltas[(vtxcount + i)*2+1] = 0; + + for(i = 0; i < delta_count; i++) { + int ptidx = ptnum_count == 0 ? i : ptnum[i]; + deltas[ptidx*2] = packed_deltas[i]; + deltas[ptidx*2+1] = packed_deltas[i+delta_count]; + } + if (delta_count < max_ptcount && !isComposite) { + // interpolate missing delta's + int start = 0; + for (i = 0; i < numberOfContoursOrComponents; i++) { + int end = ttUSHORT(data + endPtsOfContours + i*2); + int left = -1, right = -1, firstleft = -1; + /*printf("before interpolation: \n"); + for( k = start; k <= end; k++) { + printf("%d. (%d, %d) @ (%d, %d)\n", k, deltas[k*2], deltas[k*2+1], vertices[k].x, vertices[k].y); + }*/ + for (k = start; k <= end; k++) { + int d = deltas[k*2]; + if (d != NO_DELTA) { + if (k == right) right = -1; + left = k; + if (firstleft < 0) firstleft = left; + continue; + } + if (left < 0) { + for (k1 = end; k1 > k; k1--) { + if (deltas[k1*2] != NO_DELTA) + break; + } + if (k1 == k) { + // no any explicitly specified points in the contours; set all delta's to 0's + for (; k <= end; k++) + deltas[k*2] = deltas[k*2+1] = 0; + break; + } + firstleft = left = k1; + } + if (right < 0) { + for (k1 = k+1; k1 <= end; k1++) { + if (deltas[k1*2] != NO_DELTA) + break; + } + right = k1 <= end ? k1 : firstleft; + } + int x = vertices[k].x, y = vertices[k].y; + int x0 = vertices[left].x, y0 = vertices[left].y; + int x1 = vertices[right].x, y1 = vertices[right].y; + int d0x = deltas[left*2], d0y = deltas[left*2+1]; + int d1x = deltas[right*2], d1y = deltas[right*2+1]; + int dx, dy, ddx = x1 - x0, ddy = y1 - y0; + if (x0 == x1) { + dx = d0x == d1x ? d0x : 0; + } else if (x0 < x1) { + dx = x <= x0 ? d0x : x >= x1 ? d1x : ((d1x - d0x)*(x - x0) + d0x*ddx)/ddx; + } else { + dx = x <= x1 ? d1x : x >= x0 ? d0x : ((d0x - d1x)*(x - x1) - d1x*ddx)/-ddx; + } + if (y0 == y1) { + dy = d0y == d1y ? d0y : 0; + } else if (y0 < y1) { + dy = y <= y0 ? d0y : y >= y1 ? d1y : ((d1y - d0y)*(y - y0) + d0y*ddy)/ddy; + } else { + dy = y <= y1 ? d1y : y >= y0 ? d0y : ((d0y - d1y)*(y - y1) - d1y*ddy)/-ddy; + } + deltas[k*2] = (short)dx; + deltas[k*2+1] = (short)dy; + } + /*printf("after interpolation: \n"); + for( k = start; k <= end; k++) { + printf("%d. (%d, %d) @ (%d, %d)\n", k, deltas[k*2], deltas[k*2+1], vertices[k].x, vertices[k].y); + }*/ + start = end+1; + } + STBTT_assert(start == vtxcount); + } + for(i = 0; i < max_ptcount*2; i++) { + sum_deltas[i] += deltas[i]*scale >> 8; + } + } + + for (i = 0; i < out_vtxcount; i++) { + vertices[i].x += (stbtt_vertex_type)(sum_deltas[i*2] >> 8); + vertices[i].y += (stbtt_vertex_type)(sum_deltas[i*2+1] >> 8); + } + + if (ix0) *ix0 += sum_deltas[vtxcount*2] >> 8; + if (iy0) *iy0 += sum_deltas[vtxcount*2+5] >> 8; + if (ix1) *ix1 += sum_deltas[vtxcount*2+2] >> 8; + if (iy1) *iy1 += sum_deltas[vtxcount*2+7] >> 8; + + ok = 1; + +err: + STBTT_free(varbuf, info->userdata); + return ok; +} + +enum {STBTT_MAX_COMPONENTS=32}; + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, + stbtt_vertex **pvertices, int* ix0, int* iy0, int* ix1, int* iy1) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + if (ix0) *ix0 = ttSHORT(data + g + 2); + if (iy0) *iy0 = ttSHORT(data + g + 4); + if (ix1) *ix1 = ttSHORT(data + g + 6); + if (iy1) *iy1 = ttSHORT(data + g + 8); + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + stbtt__VaryGlyphShapeTT(info, glyph_index, 0, numberOfContours, + (int)(endPtsOfContours - data), vertices+off, n, + ix0, iy0, ix1, iy1); + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + int numComponents = 0; + stbtt_vertex compofs[STBTT_MAX_COMPONENTS] = {{0,0,0,0,0,0,0,0}}; + int isVariable = info->gvar != 0 && info->gvar_glyph_offsets != 0; + num_vertices = 0; + vertices = 0; + stbtt_GetGlyphBox(info, glyph_index, ix0, iy0, ix1, iy1); + if (isVariable) { + while (more && comp < info->dataend) { + numComponents++; + stbtt_uint16 flags = ttSHORT(comp); comp+=4; + comp += (flags & 1) != 0 ? 4 : 2; + comp += (flags & (1 << 3)) != 0 ? 2 : (flags & (1 << 6)) != 0 ? 4 : (flags & (1 << 7)) != 0 ? 8 : 0; + more = flags & (1<<5); + } + comp = data + g + 10; + more = 1; + stbtt__VaryGlyphShapeTT(info, glyph_index, 1, numComponents, + 0, compofs, STBTT_min(STBTT_MAX_COMPONENTS, numComponents), + ix0, iy0, ix1, iy1); + } + + int compIdx = -1; + while (more && comp < info->dataend) { + compIdx++; + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + int cx0=0, cy0=0, cx1=0, cy1=0; + stbtt_vertex *comp_verts = 0, *tmp = 0; + int dx = 0, dy = 0; + float mtx[] = {1,0,0,1}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + int idx_base = 0, idx_comp = 0; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + dx = ttSHORT(comp); comp+=2; + dy = ttSHORT(comp); comp+=2; + } else { + dx = ttCHAR(comp); comp+=1; + dy = ttCHAR(comp); comp+=1; + } + } + else { + if (flags & 1) { // shorts + idx_base = ttUSHORT(comp); comp+=2; + idx_comp = ttUSHORT(comp); comp+=2; + } else { + idx_base = ttBYTE(comp); comp+=1; + idx_comp = ttBYTE(comp); comp+=1; + } + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + dx += compofs[compIdx].x; + dy += compofs[compIdx].y; + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts, &cx0, &cy0, &cx1, &cy1); + /*if(flags & 0x0200) { + if (ix0) *ix0 = cx0 + dx; + if (ix1) *ix1 = cx1 + dx; + }*/ + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + dx)); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + dy)); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + dx)); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + dy)); + } + if (!(flags & 2)) { + STBTT_assert(idx_base < num_vertices && idx_comp < comp_num_verts); + dx = vertices[idx_base].x - comp_verts[idx_comp].x; + dy = vertices[idx_base].y - comp_verts[idx_comp].y; + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + v->x = (stbtt_vertex_type)(v->x + dx); + v->y = (stbtt_vertex_type)(v->y + dy); + v->cx = (stbtt_vertex_type)(v->cx + dx); + v->cy = (stbtt_vertex_type)(v->cy + dy); + } + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // fallthrough + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices, + int* ix0, int* iy0, int* ix1, int* iy1) +{ + if (ix0) *ix0 = 0; + if (ix1) *ix1 = 0; + if (iy0) *iy0 = 0; + if (iy1) *iy1 = 0; + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices, ix0, iy0, ix1, iy1); + else { + if (ix0 || iy0 || ix1 || iy1) + stbtt_GetGlyphBox(info, glyph_index, ix0, iy0, ix1, iy1); + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); + } +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch(coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + } break; + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch(classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + + classDefTable = classDef1ValueArray + 2 * glyphCount; + } break; + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + + classDefTable = classRangeRecords + 6 * classRangeCount; + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } break; + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + STBTT_assert(glyph1class < class1Count); + STBTT_assert(glyph2class < class2Count); + + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { + stbtt_uint8 *class1Records = table + 16; + stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); + stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + break; + }; + } + } + break; + }; + + default: + // TODO: Implement other stuff. + break; + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->size, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForPixelHeightNoDesc(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, + float scale_x, float scale_y, float shift_x, float shift_y, + int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1=0,y1=0; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0, &y0, &x1, &y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + stbtt__ScaleGlyphBox(x0, y0, x1, y1, scale_x, scale_y, shift_x, shift_y, ix0, iy0, ix1, iy1); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, + float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, + float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = sy1 - sy0; + STBTT_assert(x >= 0 && x < len); + scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; + scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = (x1+1 - x0) * dy + y_top; + + sign = e->direction; + // area of the rectangle covered from y0..y_crossing + area = sign * (y_crossing-sy0); + // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) + scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); + + step = sign * dy; + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; + area += step; + } + y_crossing += dy * (x2 - (x1+1)); + + STBTT_assert(STBTT_fabs(area) <= 1.01f); + + scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); + + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char* stbtt_GetGlyphBitmapSubpixelRealloc(const stbtt_fontinfo *info, + float scale_x, float scale_y, float shift_x, float shift_y, + int glyph, int *width, int *height, int *step, + int *xoff, int *yoff, float* advx, + unsigned char** buf, int* bufsize) +{ + if (!buf || !bufsize) return 0; + + int ix0,ix1,iy0,iy1; + int scaled_ix0, scaled_iy0, scaled_ix1, scaled_iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices, &ix0, &iy0, &ix1, &iy1); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt__ScaleGlyphBox(ix0, iy0, ix1, iy1, scale_x, scale_y, shift_x, shift_y, + &scaled_ix0, &scaled_iy0, &scaled_ix1, &scaled_iy1); + + int w0 = scaled_ix1 - scaled_ix0; + int h0 = scaled_iy1 - scaled_iy0; + int pad_x = STBTT_max((h0+9)/10, (w0+9)/10)+10; + int pad_y = pad_x; + + // now we get the size + gbm.w = (scaled_ix1 - scaled_ix0)+pad_x*2; + gbm.h = (scaled_iy1 - scaled_iy0)+pad_y*2; + gbm.pixels = *buf; // in case we error + + if (width) *width = 0; + if (height) *height = 0; + if (step) *step = gbm.w; + if (xoff) *xoff = 0; + if (yoff) *yoff = 0; + if (advx) { + int advx0 = 0, lsb = 0, x0 = 0, x1 = 0; + stbtt_GetGlyphBox(info, glyph, &x0, 0, &x1, 0); + stbtt_GetGlyphHMetrics(info, glyph, &advx0, &lsb); + int interspace = advx0 - (x1 - x0); + *advx = (interspace + (ix1 - ix0))*scale_x; + } + + if (gbm.w && gbm.h) { + int new_bufsz = gbm.w*gbm.h; + if (!*buf) *bufsize = 0; + if (new_bufsz > *bufsize) { + int bufsz_to_alloc = STBTT_max(*bufsize*3/2, new_bufsz); + STBTT_free(*buf, info->userdata); + *buf = (unsigned char*)STBTT_malloc(bufsz_to_alloc, info->userdata); + *bufsize = bufsz_to_alloc; + } + gbm.pixels = *buf; + if (gbm.pixels) { + memset(gbm.pixels, 0, new_bufsz); + gbm.stride = gbm.w; + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, + shift_x+pad_x, shift_y+pad_y, scaled_ix0, scaled_iy0, 1, info->userdata); + int x, y; + ix0 = iy0 = INT_MAX; + ix1 = iy1 = INT_MIN; + for (y = 0; y < gbm.h; y++) { + int have_nz = 0; + for (x = 0; x < gbm.w; x++) { + if (gbm.pixels[y*gbm.w + x] != 0) { + have_nz = 1; + ix0 = STBTT_min(ix0, x); + ix1 = STBTT_max(ix1, x); + } + } + if (have_nz) { + iy0 = STBTT_min(iy0, y); + iy1 = STBTT_max(iy1, y); + } + } + int w = ix1 - ix0 + 1, h = iy1 - iy0 + 1; + if (ix0 == INT_MAX || iy0 == INT_MAX || ix1 == INT_MIN || iy1 == INT_MIN ) { + w = h = 0; + ix0 = pad_x; + iy0 = pad_y; + } + if (width) *width = w; + if (height) *height = h; + if (xoff) *xoff = scaled_ix0 - pad_x + ix0; + if (yoff) *yoff = scaled_iy0 - pad_y + iy0; + gbm.pixels += gbm.w*iy0 + ix0; + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices, 0, 0, 0, 0); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + orig[0] = x; + orig[1] = y; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + c*x^2 + b*x + a = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, + int padding, unsigned char onedge_value, float pixel_dist_scale, + int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int w, h, ix0 = 0, iy0 = 0, ix1 = 0, iy1 = 0; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts, &ix0, &iy0, &ix1, &iy1); + stbtt__ScaleGlyphBox(ix0, iy0, ix1, iy1, scale, scale, 0.f, 0.f, &ix0, &iy0, &ix1, &iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) { + STBTT_free(verts, info->userdata); + return 0; + } + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve + float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (verts[i].type == STBTT_vline) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3],px,py,t,it; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, font->size, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 datasize, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, datasize, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, datasize, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, stbtt_uint32 datasize, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0 || (stbtt_uint32)off >= datasize) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, datasize, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, 512*1024*1024, offset); +} + +STBTT_DEF int stbtt_InitFont2(stbtt_fontinfo *info, const unsigned char *data, unsigned size, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, size, offset); +} + +STBTT_DEF stbtt_fontinfo* stbtt_CreateFont(const unsigned char *data, unsigned size, int offset) +{ + stbtt_fontinfo* info = (stbtt_fontinfo*)STBTT_malloc(sizeof(*info), 0); + if(info) { + if (stbtt_InitFont2(info, data, size, offset)) + return info; + STBTT_free(info, 0); + info = 0; + } + return info; +} + +STBTT_DEF void stbtt_ReleaseFont(stbtt_fontinfo **info) +{ + if (info && *info) { + STBTT_free(*info, 0); + *info = 0; + } +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, 512*1024*1024, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +STBTT_DEF int stbtt_GetInstance(const stbtt_fontinfo* info, stbtt_axisinfo* axes, int max_count) +{ + if (!info) return 0; + if (!axes) return info->axis_count; + int count = info->axis_count < max_count ? info->axis_count : max_count; + if (count > 0) + memcpy(axes, info->axes, count*sizeof(axes[0])); + return count; +} + +STBTT_DEF int stbtt_GetWeight(const stbtt_fontinfo* info) +{ + int i; + for (i = 0; i < info->axis_count; i++) { + const stbtt_axisinfo* axis = &info->axes[i]; + if (axis->tag == STBTT_FOURCC('w', 'g', 'h', 't')) + return axis->currval; + } + return 0; +} + +STBTT_DEF int stbtt_SetInstance(stbtt_fontinfo* info, const int* params, int count, int reset_to_defaults) +{ + if (!info || count < 0) return 0; + if (count > 0 && !params) return 0; + if (info->axis_count == 0) return 1; + int fixptvals[STBTT_MAX_AXES]; + int i, j; + for (i = 0; i < info->axis_count; i++) { + const stbtt_axisinfo* axis = &info->axes[i]; + for (j = 0; j < count; j++) { + int tag = params[j*2]; + int revtag = STBTT_FOURCC(tag, tag >> 8, tag >> 16, tag >> 24); + if (axis->tag == tag || axis->tag == revtag) + break; + } + fixptvals[i] = reset_to_defaults ? info->axes[i].defval : info->axes[i].currval; + if (j == count) + continue; + int val = params[j*2+1]; + fixptvals[i] = val < axis->minval ? axis->minval : val > axis->maxval ? axis->maxval : val; + } + return stbtt__SetVarfontInstance(info, fixptvals); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// diff --git a/modules/imgproc/src/stb_truetype.hpp b/modules/imgproc/src/stb_truetype.hpp new file mode 100644 index 0000000000..e1224213c6 --- /dev/null +++ b/modules/imgproc/src/stb_truetype.hpp @@ -0,0 +1,692 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// This is refactored (and split into 2 files) version of stb_truetype.h +// from https://github.com/nothings/stb. +// Support for variable fonts has been added and +// a few other modifications & optimizations have been done. + +//////////////// Below is the original copyright information ///////////////// +///////// (btw, OpenCV chooses the option A (MIT) for the license) /////////// + +// Authored from 2009-2020 by Sean Barrett / RAD Game Tools. +// See stb_truetype.cpp for the details + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_HPP__ +#define __STB_INCLUDE_STB_TRUETYPE_HPP__ + +#if 0 //def STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define STBTT_FOURCC(a, b, c, d) \ + (unsigned)((((unsigned char)(a)) << 24) | \ + (((unsigned char)(b)) << 16) | \ + (((unsigned char)(c)) << 8) | \ + ((unsigned char)(d))) + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +#ifndef STBTT_MAX_AXES +#define STBTT_MAX_AXES 16 +#endif + +typedef struct stbtt_axisinfo +{ + int tag; + int minval, defval, maxval; + int currval; +} stbtt_axisinfo; + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + unsigned char * dataend; // data + size + int fontstart; // offset of start of font + unsigned size; // the data buffer size + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg,avar,fvar,gvar,hvar; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + int axis_count; // the number of variable font axes + stbtt_axisinfo axes[STBTT_MAX_AXES]; // information about each axis + short axes_normvalues[STBTT_MAX_AXES]; // normalized (within [-1, 1]) coordinates of + // the currently used variation. They are already transformed + // using avar (if any) + int gvar_shared_count; // the number of shared tuples, used by 'gvar' + int gvar_shared_tuples; // offset of the shared tuples + int gvar_glob_offset; // the global offset of glyph variations table + int gvar_glyph_offsets; // the relative offsets of glyph variations + int gvar_off_format; // true if offsets are 32-bit + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + +STBTT_DEF int stbtt_InitFont2(stbtt_fontinfo *info, const unsigned char *data, unsigned size, int offset); +// Same as stbtt_InitFont, but also takes the size of "data" buffer, +// in order to control and avoid out of range accesses. + +STBTT_DEF stbtt_fontinfo* stbtt_CreateFont(const unsigned char *data, unsigned size, int offset); +// Allocates font structure and initializes it. Returns 0 if there was an error. + +STBTT_DEF void stbtt_ReleaseFont(stbtt_fontinfo **info); +// Allocates font structure and initializes it. Returns 0 if there was an error. + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForPixelHeightNoDesc(const stbtt_fontinfo *info, float height); + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +STBTT_DEF void stbtt__ScaleGlyphBox(int ix0, int iy0, int ix1, int iy1, + float scale_x, float scale_y, float shift_x, float shift_y, + int *out_ix0, int *out_iy0, int *out_ix1, int *out_iy1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, + stbtt_vertex **vertices, int* ix0, int* iy0, int* ix1, int* iy1); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices, + int* ix0, int* iy0, int* ix1, int* iy1); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// FONT VARIATIONS +// +STBTT_DEF int stbtt_GetWeight(const stbtt_fontinfo* info); +STBTT_DEF int stbtt_GetInstance(const stbtt_fontinfo* info, stbtt_axisinfo* axes, int max_count); +STBTT_DEF int stbtt_SetInstance(stbtt_fontinfo* info, const int* params, int count, int reset_to_defaults); + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixelRealloc(const stbtt_fontinfo *info, float scale_x, float scale_y, + float shift_x, float shift_y, + int glyph, int *width, int *height, int* step, + int *xoff, int *yoff, float* advx, + unsigned char** buf, int* bufsize); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ diff --git a/modules/imgproc/test/test_drawing.cpp b/modules/imgproc/test/test_drawing.cpp index 00aeecc5f2..ab559e790e 100644 --- a/modules/imgproc/test/test_drawing.cpp +++ b/modules/imgproc/test/test_drawing.cpp @@ -86,6 +86,9 @@ void CV_DrawingTest::run( int ) float Eps = 1; if( err > Eps) { + //imshow("reference", valImg); + //imshow("result", testImg); + //waitKey(); ts->printf( ts->LOG, "NORM_L1 between testImg and valImg is equal %f (larger than %f)\n", err, Eps ); ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); } @@ -619,8 +622,17 @@ TEST(Drawing, putText_no_garbage) EXPECT_EQ(0, cv::countNonZero(mat(Rect(0, 0, 10, sz.height)))); EXPECT_EQ(0, cv::countNonZero(mat(Rect(sz.width-10, 0, 10, sz.height)))); - EXPECT_EQ(0, cv::countNonZero(mat(Rect(205, 0, 10, sz.height)))); - EXPECT_EQ(0, cv::countNonZero(mat(Rect(405, 0, 10, sz.height)))); + EXPECT_EQ(0, cv::countNonZero(mat(Rect(190, 0, 10, sz.height)))); + EXPECT_EQ(0, cv::countNonZero(mat(Rect(380, 0, 10, sz.height)))); + +#if 0 + rectangle(mat, Rect(0, 0, 10, sz.height), Scalar::all(255), 1, LINE_8); + rectangle(mat, Rect(sz.width-10, 0, 10, sz.height), Scalar::all(255), 1, LINE_8); + rectangle(mat, Rect(190, 0, 10, sz.height), Scalar::all(255), 1, LINE_8); + rectangle(mat, Rect(380, 0, 10, sz.height), Scalar::all(255), 1, LINE_8); + imshow("result", mat); + waitKey(); +#endif } @@ -679,4 +691,169 @@ TEST(Drawing, fillpoly_circle) EXPECT_LT(diff_fp3, 1.); } + +TEST(Drawing, fromJava_getTextSize) +{ + String text = "Android all the way"; + double fontScale = 2; + int thickness = 3; + int baseLine = 0; + + Size res0 = getTextSize(text, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, 0); + Size res = getTextSize(text, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, &baseLine); + +#if 0 + Mat img(200, 700, CV_8UC3, Scalar::all(255)); + Point org(100, 100); + putText(img, text, org, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, Scalar(128, 0, 0), thickness); + rectangle(img, org, Point(org.x + res0.width, org.y - res0.height), Scalar(0, 0, 128), 2, LINE_AA); + imshow("result", img); + waitKey(); +#endif + + EXPECT_EQ(res0.width, res.width); + EXPECT_EQ(res0.height, res.height); + EXPECT_NEAR(494, res.width, 3.0); + EXPECT_NEAR(51, res.height, 3.0); + EXPECT_NEAR(10, baseLine, 3.0); +} + +TEST(Drawing, fromJava_testPutTextMatStringPointIntDoubleScalarIntIntBoolean) +{ + String text = "Hello World"; + Size labelSize(170, 23); + + Mat img(20 + (int)labelSize.height, 20 + (int)labelSize.width, CV_8U, Scalar::all(0)); + Point origin(10, 10); + + putText(img, text, origin, FONT_HERSHEY_SIMPLEX, 1.0, Scalar::all(255), 1, LINE_8, true); + + EXPECT_LT(0, countNonZero(img)); + // check that border is not corrupted + rectangle(img, origin, + Point(origin.x + labelSize.width, origin.y + labelSize.height), + Scalar::all(0), -1, 8); + //imshow("img", img); + //waitKey(); + EXPECT_EQ(0, countNonZero(img)); + + origin = Point(10, labelSize.height + 10); + + putText(img, text, origin, FONT_HERSHEY_SIMPLEX, 1.0, Scalar::all(255)); + EXPECT_LT(0, countNonZero(img)); + // check that border is not corrupted + rectangle(img, Point(10, 10), Point(labelSize.width + 10, labelSize.height + 10), Scalar::all(0), -1); + EXPECT_EQ(0, countNonZero(img)); +} + +typedef struct TextProp +{ + const char* str; + bool ralign; + int weight; + bool italic; +} TextProp; + +#ifdef HAVE_UNIFONT // there are other tests for text drawing, so the functionality is tested anyway, + // but this test needs concrete unicode font to compare the printed text + // (including CJK characters) with the reference picture from the database +TEST(Drawing, ttf_text) +{ + string ts_data_path = TS::ptr()->get_data_path(); + string custom_font_path = ts_data_path + "../highgui/drawing/"; + + FontFace sans("sans"); + FontFace italic("italic"); + Mat img(600, 1300, CV_8UC3); + TextProp text[] = + { + {"The quick brown fox jumps over lazy dog. Fly, start, finish, shuffle shuttle.", false, 400, false}, + {"vechicle #5 detected; fps=123.45.\n", false, 600, false}, + {"Съешь же ещё этих мягких французских булок, да выпей чаю!\n" + "Dès Noël où un zéphyr haï me vêt de glaçons würmiens je dîne\nd’exquis rôtis de bœuf au kir à l’aÿ d’âge mûr & cætera!\n" + "“Falsches Üben von Xylophonmusik quält jeden größeren Zwerg”.", false, 400, true}, + + {"¡Oh tú, sabio encantador, quienquiera que seas,\n" + "a quien ha de tocar el ser coronista desta peregrina\n" + "historia, ruégote que no te olvides de mi buen Rocinante,\n" + "compañero eterno mío en todos mis caminos y carreras!\n", false, 300, false}, + {"Ταχίστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός.", false, 400, false}, + {"春眠不觉晓,\n处处闻啼鸟。\n夜来风雨声,\n花落知多少。\n" + " あなたはそれが困難見つけた場合 — あなたは正しい方向に向かっている。\n" + " 넌 모든 꽃들을 다 꺾어버릴 수는 있겠지만, 봄이 오는 걸 막을 수는 없어。 ", false, 400, false} + }; + Scalar color(150, 80, 0); + + for(int iter = 0; iter < 1; iter++) + { + //double ts = (double)getTickCount(); + img.setTo(Scalar::all(255)); + int sz = 20; + int x0 = 50, y0 = 70; + Point org(x0, y0); + + int j = 0, column = 1; + for(const TextProp& t: text) + { + PutTextFlags flags = t.ralign ? PUT_TEXT_ALIGN_RIGHT : PUT_TEXT_ALIGN_LEFT; + if(t.ralign) + { + if(j > 0) + break; + if(column == 1) + { + column = 2; + org.y = y0; + } + org.x = img.cols - x0; + } + else + { + org.x = column == 1 ? x0 : img.cols/2; + } + FontFace& face = t.italic ? italic : sans; + //Rect r = getTextSize(img.size(), t.str, org, face, sz, t.weight, flags); + org = putText(img, t.str, org, color, face, + sz, t.weight, flags, Range()); + //rectangle(img, r, Scalar(80, 0, 128), 1, LINE_AA); + org.y += sz + 10; + } + + Scalar color2(80, 0, 128); + + org = Point(img.cols - 500, 150); + putText(img, "Пробуем\n ", org, color2, italic, 80, 300, + PUT_TEXT_ALIGN_LEFT, Range()); + org.x -= 90; + org.y += 130; + // testing alternative way to set the weight; + // in putText we use weight=0 + italic.setInstance({CV_FOURCC('w','g','h','t'), 800<<16}); + putText(img, "OpenCV", org, color2, italic, 120, 0, + PUT_TEXT_ALIGN_LEFT, Range()); + org.y += 140; + org.x += 60; + putText(img, "打印文字", org, color2, sans, 100, 400, + PUT_TEXT_ALIGN_LEFT, Range()); + //ts = (double)getTickCount() - ts; + //printf("iter=%d. ts=%.2fms\n", iter, ts*1000./getTickFrequency()); + } + +#if 0 + //imwrite(ts_data_path + "../highgui/drawing/text_test.png", img); + imshow("test", img); + waitKey(); +#else + Mat refimg = imread(ts_data_path + "../highgui/drawing/text_test.png", IMREAD_UNCHANGED); + //imshow("ref", refimg); + //imshow("actual", img); + //absdiff(refimg, img, refimg); + //imshow("diff", refimg); + //waitKey(); + EXPECT_EQ(refimg.size(), img.size()); + EXPECT_LT(cv::norm(refimg, img, NORM_L1), 6500); +#endif +} +#endif + }} // namespace diff --git a/modules/videoio/include/opencv2/videoio/legacy/constants_c.h b/modules/videoio/include/opencv2/videoio/legacy/constants_c.h index 91f85f87b8..23ea7fd768 100644 --- a/modules/videoio/include/opencv2/videoio/legacy/constants_c.h +++ b/modules/videoio/include/opencv2/videoio/legacy/constants_c.h @@ -413,19 +413,6 @@ enum //! Macro to construct the fourcc code of the codec. Same as CV_FOURCC() #define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24)) -/** @brief Constructs the fourcc code of the codec function - -Simply call it with 4 chars fourcc code like `CV_FOURCC('I', 'Y', 'U', 'V')` - -List of codes can be obtained at [Video Codecs by FOURCC](http://www.fourcc.org/codecs.php) page. -FFMPEG backend with MP4 container natively uses other values as fourcc code: -see [ObjectType](http://mp4ra.org/#/codecs). -*/ -CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4) -{ - return CV_FOURCC_MACRO(c1, c2, c3, c4); -} - //! (Windows only) Open Codec Selection Dialog #define CV_FOURCC_PROMPT -1 //! (Linux only) Use default codec for specified filename diff --git a/platforms/ios/build_framework.py b/platforms/ios/build_framework.py index e89cf3c666..af0db8f09a 100755 --- a/platforms/ios/build_framework.py +++ b/platforms/ios/build_framework.py @@ -36,7 +36,7 @@ import glob, re, os, os.path, shutil, string, sys, argparse, traceback, multipro from subprocess import check_call, check_output, CalledProcessError from distutils.dir_util import copy_tree -IPHONEOS_DEPLOYMENT_TARGET='8.0' # default, can be changed via command line options or environment variable +IPHONEOS_DEPLOYMENT_TARGET='9.0' # default, can be changed via command line options or environment variable def execute(cmd, cwd = None): print("Executing: %s in %s" % (cmd, cwd), file=sys.stderr) @@ -426,8 +426,8 @@ if __name__ == "__main__": parser.add_argument('--dynamic', default=False, action='store_true', help='build dynamic framework (default is "False" - builds static framework)') parser.add_argument('--disable-bitcode', default=False, dest='bitcodedisabled', action='store_true', help='disable bitcode (enabled by default)') parser.add_argument('--iphoneos_deployment_target', default=os.environ.get('IPHONEOS_DEPLOYMENT_TARGET', IPHONEOS_DEPLOYMENT_TARGET), help='specify IPHONEOS_DEPLOYMENT_TARGET') - parser.add_argument('--iphoneos_archs', default='armv7,armv7s,arm64', help='select iPhoneOS target ARCHS') - parser.add_argument('--iphonesimulator_archs', default='i386,x86_64', help='select iPhoneSimulator target ARCHS') + parser.add_argument('--iphoneos_archs', default='armv7s,arm64', help='select iPhoneOS target ARCHS') + parser.add_argument('--iphonesimulator_archs', default='x86_64', help='select iPhoneSimulator target ARCHS') parser.add_argument('--enable_nonfree', default=False, dest='enablenonfree', action='store_true', help='enable non-free modules (disabled by default)') parser.add_argument('--debug', default=False, dest='debug', action='store_true', help='Build "Debug" binaries (disabled by default)') parser.add_argument('--debug_info', default=False, dest='debug_info', action='store_true', help='Build with debug information (useful for Release mode: BUILD_WITH_DEBUG_INFO=ON)') diff --git a/platforms/ios/run_tests.py b/platforms/ios/run_tests.py index de302c2bfe..12603b2226 100755 --- a/platforms/ios/run_tests.py +++ b/platforms/ios/run_tests.py @@ -7,7 +7,7 @@ from __future__ import print_function import glob, re, os, os.path, shutil, string, sys, argparse, traceback, multiprocessing from subprocess import check_call, check_output, CalledProcessError -IPHONEOS_DEPLOYMENT_TARGET='8.0' # default, can be changed via command line options or environment variable +IPHONEOS_DEPLOYMENT_TARGET='9.0' # default, can be changed via command line options or environment variable def execute(cmd, cwd = None): print("Executing: %s in %s" % (cmd, cwd), file=sys.stderr)